Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# CONTRIBUTING.md

It's just a memorandum for myself

### Release

- 1, Make sure you're on `dev`

- 2, Run:

```sh
yarn lerna version <newversion> --exact --no-push # will also inspects and builds
yarn lerna publish from-git --dist-tag latest

git switch release
git merge dev
git push
```

- 3, Add a release note to https://github.com/0b5vr/automaton/releases
2 changes: 1 addition & 1 deletion packages/automaton-with-gui/playground-examples/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const context = canvas.getContext( '2d' );
// == initialize an automaton instance =============================================================
const automaton = new AUTOMATON_WITH_GUI.AutomatonWithGUI(
JSON.parse( `
{"version":"4.0.0","resolution":100,"curves":[{"nodes":[[0,0,0,0,0.06345177664974619],[0.2238578680203046,0.8088235294117649,-0.08883248730964469,-0.08921568627450979,0.08883248730964469,0.08921568627450979],[1,1,-0.47969543147208127]]},{"nodes":[[0,0,0,0,0.10913705583756345],[0.6000000000000001,1,-0.5507614213197969]]},{"nodes":[[],[0.1,1],[0.5,1],[0.6000000000000001],[1.8]],"fxs":[{"def":"cds","params":{"factor":300,"ratio":1,"preserve":false},"length":0.5},{"def":"gravity","params":{"a":30,"e":0.5,"preserve":true},"time":0.5,"length":0.728136781314195}]},{"nodes":[[0,1,0,0,0.05],[0.05,0,-0.05]]},{"nodes":[[],[1,1]]},{"nodes":[[0,0,0,0,0.2817258883248731],[0.4,1,-0.11421319796954314,-0.5970588235294118]]},{"nodes":[[],[4,1]]},{"nodes":[[],[0.1,1],[2,1]],"fxs":[{"def":"cds","params":{"factor":100,"ratio":1,"preserve":false},"length":2}]}],"channels":[["rect/x",{"items":[{"value":0.5}]}],["rect/y",{"items":[{"value":0.5},{"time":0.4,"length":1.3000000000000003,"value":0.5,"curve":2,"amp":-0.3},{"time":3.6,"length":0.40000000000000036,"value":0.5,"curve":5}]}],["rect/rotate",{"items":[{"time":0.2,"length":0.6,"curve":1},{"time":3.6,"length":0.40000000000000036,"curve":5,"amp":0.1}]}],["rect/sizeX",{"items":[{"time":0.2,"length":0.6,"curve":1,"amp":0.29999999999999993},{"time":1.9000000000000001,"length":0.15,"value":0.3,"curve":1,"speed":4,"amp":0.6000000000000001}]}],["rect/sizeY",{"items":[{"time":0.2,"length":0.6,"curve":1,"amp":0.29999999999999993}]}],["ring/radius0",{"items":[{"length":1,"curve":0}]}],["ring/radius1",{"items":[{"time":0.045685279187817264,"length":1,"curve":0,"amp":0.9}]}],["ring/radius2",{"items":[{"time":0.10152284263959391,"length":1,"curve":0,"amp":0.9}]}],["ring/radius3",{"items":[{"time":0.15228426395939088,"length":1,"curve":0,"amp":0.9}]}],["ring/radius4",{"items":[{"time":0.1979695431472081,"length":1,"curve":0,"amp":1.1}]}],["rect/bounce",{"items":[{"time":0.9,"length":0.8000000000000002,"value":1,"reset":true}]}],["dots/radius0",{"items":[{"time":1.5,"length":0.15,"curve":1,"speed":4,"amp":0.05}]}],["dots/radius1",{"items":[{"time":1.525,"length":0.15,"curve":1,"speed":4,"amp":0.05}]}],["dots/radius3",{"items":[{"time":1.55,"length":0.15,"curve":1,"speed":4,"amp":0.05}]}],["dots/radius2",{"items":[{"time":1.575,"length":0.15,"curve":1,"speed":4,"amp":0.05}]}],["rect/fill",{"items":[{"value":1},{"time":1.7000000000000002,"length":0.05,"curve":3},{"time":1.7500000000000002,"length":0.05,"curve":3},{"time":1.8000000000000003,"length":0.05,"curve":3}]}],["text/name",{"items":[{"time":2.1,"length":0.30000000000000027,"curve":4,"speed":3.33333333333334}]}],["text/description",{"items":[{"time":2.5,"length":0.8,"curve":4,"speed":1.25}]}],["zigzag/scroll",{"items":[{"time":0.5,"length":3.5,"value":0.5,"curve":6}]}],["zigzag/pos",{"items":[{"time":1.8,"length":1.2000000000000002,"curve":7,"amp":1.4},{"time":3.5,"length":0.40000000000000036,"value":1.4000000000000001,"curve":5,"amp":-1.4000000000000001}]}]],"labels":{"blink":1.7000000000000002,"wave":0,"text":2.1,"fall":3.6,"bounce":0.9},"guiSettings":{"snapTimeActive":true,"snapTimeInterval":0.1,"snapValueActive":true,"snapValueInterval":0.1,"snapBeatActive":false,"bpm":120,"beatOffset":0,"minimizedPrecisionTime":3,"minimizedPrecisionValue":3}}
{"version":"4.3.0","resolution":100,"curves":[{"nodes":[[0,0,0,0,0.06345177664974619],[0.2238578680203046,0.8088235294117649,-0.08883248730964469,-0.08921568627450979,0.08883248730964469,0.08921568627450979],[1,1,-0.47969543147208127]]},{"nodes":[[0,0,0,0,0.10913705583756345],[0.6000000000000001,1,-0.5507614213197969]]},{"nodes":[[],[0.1,1],[0.5,1],[0.6000000000000001],[1.8]],"fxs":[{"def":"cds","params":{"factor":300,"ratio":1,"preserve":false},"length":0.5},{"def":"gravity","params":{"a":30,"e":0.5,"preserve":true},"time":0.5,"length":0.728136781314195}]},{"nodes":[[0,1,0,0,0.05],[0.05,0,-0.05]]},{"nodes":[[],[1,1]]},{"nodes":[[0,0,0,0,0.2817258883248731],[0.4,1,-0.11421319796954314,-0.5970588235294118]]},{"nodes":[[],[4,1]]},{"nodes":[[],[0.1,1],[2,1]],"fxs":[{"def":"cds","params":{"factor":100,"ratio":1,"preserve":false},"length":2}]}],"channels":[["rect/x",{"items":[],"init":0.5}],["rect/y",{"items":[{"time":0.4,"length":1.3000000000000003,"value":0.5,"curve":2,"amp":-0.3},{"time":3.6,"length":0.40000000000000036,"value":0.5,"curve":5}],"init":0.5}],["rect/rotate",{"items":[{"time":0.2,"length":0.6,"curve":1},{"time":3.6,"length":0.40000000000000036,"curve":5,"amp":0.1}],"init":0}],["rect/sizeX",{"items":[{"time":0.2,"length":0.6,"curve":1,"amp":0.29999999999999993},{"time":1.9000000000000001,"length":0.15,"value":0.3,"curve":1,"speed":4,"amp":0.6000000000000001}],"init":0}],["rect/sizeY",{"items":[{"time":0.2,"length":0.6,"curve":1,"amp":0.29999999999999993}],"init":0}],["ring/radius0",{"items":[{"length":1,"curve":0}],"init":0}],["ring/radius1",{"items":[{"time":0.045685279187817264,"length":1,"curve":0,"amp":0.9}],"init":0}],["ring/radius2",{"items":[{"time":0.10152284263959391,"length":1,"curve":0,"amp":0.9}],"init":0}],["ring/radius3",{"items":[{"time":0.15228426395939088,"length":1,"curve":0,"amp":0.9}],"init":0}],["ring/radius4",{"items":[{"time":0.1979695431472081,"length":1,"curve":0,"amp":1.1}],"init":0}],["rect/bounce",{"items":[{"time":0.9,"length":0.8000000000000002,"value":1,"reset":true}],"init":0}],["dots/radius0",{"items":[{"time":1.5,"length":0.15,"curve":1,"speed":4,"amp":0.05}],"init":0}],["dots/radius1",{"items":[{"time":1.525,"length":0.15,"curve":1,"speed":4,"amp":0.05}],"init":0}],["dots/radius3",{"items":[{"time":1.55,"length":0.15,"curve":1,"speed":4,"amp":0.05}],"init":0}],["dots/radius2",{"items":[{"time":1.575,"length":0.15,"curve":1,"speed":4,"amp":0.05}],"init":0}],["rect/fill",{"items":[{"time":1.7000000000000002,"length":0.05,"curve":3},{"time":1.7500000000000002,"length":0.05,"curve":3},{"time":1.8000000000000003,"length":0.05,"curve":3}],"init":1}],["text/name",{"items":[{"time":2.1,"length":0.30000000000000027,"curve":4,"speed":3.33333333333334}],"init":0}],["text/description",{"items":[{"time":2.5,"length":0.8,"curve":4,"speed":1.25}],"init":0}],["zigzag/scroll",{"items":[{"time":0.5,"length":3.5,"value":0.5,"curve":6}],"init":0}],["zigzag/pos",{"items":[{"time":1.8,"length":1.2000000000000002,"curve":7,"amp":1.4},{"time":3.5,"length":0.40000000000000036,"value":1.4000000000000001,"curve":5,"amp":-1.4000000000000001}],"init":0}]],"labels":{"blink":1.7000000000000002,"wave":0,"text":2.1,"fall":3.6,"bounce":0.9},"guiSettings":{"snapTimeActive":true,"snapTimeInterval":0.1,"snapValueActive":true,"snapValueInterval":0.1,"snapBeatActive":false,"bpm":120,"beatOffset":0,"useBeatInGUI":false,"minimizedPrecisionTime":3,"minimizedPrecisionValue":3}}
` ), // put your automaton savedata here
{
gui: divAutomatonContainer, // where you want to put entire automaton GUI
Expand Down
3 changes: 2 additions & 1 deletion packages/automaton-with-gui/src/ChannelItemWithGUI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export class ChannelItemWithGUI extends ChannelItem {
public curve?: CurveWithGUI;

/**
* TODO
* Return a value of the item at the given timepoint.
*
* @param time The timepoint you want to grab the value
* @param isFromGUI If you're poking the method from Automaton GUI, set this to true otherwise you are going to suffer in redux hell
*/
Expand Down
40 changes: 31 additions & 9 deletions packages/automaton-with-gui/src/ChannelWithGUI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ export class ChannelWithGUI extends Channel implements Serializable<SerializedCh
return this.__items;
}

/**
* The initial value of the channel.
*/
public get init(): number {
return this.__init;
}

/**
* Whether it should reset itself in next update call or not.
*/
Expand Down Expand Up @@ -81,6 +88,7 @@ export class ChannelWithGUI extends Channel implements Serializable<SerializedCh
item.curve?.incrementUserCount();
return item;
} ) ?? [];
this.__init = data.init ?? 0.0;
}

/**
Expand Down Expand Up @@ -117,22 +125,20 @@ export class ChannelWithGUI extends Channel implements Serializable<SerializedCh
public getValueFromGUI( time: number ): number {
// no items??? damn
if ( this.__items.length === 0 ) {
return 0.0;
return this.__init;
}

const next = binarySearch( this.__items, ( item ) => ( item.time < time ) );
const next = binarySearch( this.__items, ( item ) => ( item.time <= time ) );

// it's the first one!
if ( next === 0 ) {
return 0.0;
return this.__init;
}

const item = this.__items[ next - 1 ];
if ( item.end < time ) {
return item.getValue( item.length, true );
} else {
return item.getValue( time - item.time, true );
}
return ( item.reset && item.end <= time )
? this.__init
: item.getValue( time - item.time, true );
}

/**
Expand Down Expand Up @@ -197,7 +203,8 @@ export class ChannelWithGUI extends Channel implements Serializable<SerializedCh
*/
public serialize(): SerializedChannel {
return {
items: this.__serializeItems()
items: this.__serializeItems(),
init: this.__init,
};
}

Expand Down Expand Up @@ -672,6 +679,20 @@ export class ChannelWithGUI extends Channel implements Serializable<SerializedCh
this.__automaton.shouldSave = true;
}

/**
* Change the init of the channel.
* @param init The initial value
*/
public changeInit( init: number ): void {
this.__init = init;

this.reset();

this.__emit( 'changeInit', { init } );

this.__automaton.shouldSave = true;
}

/**
* Serialize its items.
* @returns Serialized items
Expand Down Expand Up @@ -730,6 +751,7 @@ export interface ChannelWithGUIEvents {
changeValue: { value: number };
reset: void;
updateStatus: void;
changeInit: { init: number };
changeLength: { length: number };
}

Expand Down
3 changes: 2 additions & 1 deletion packages/automaton-with-gui/src/minimizeData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ function minimizeChannel(
const items = data.items?.map( ( item ) => minimizeChannelItem( item, options ) );

return {
items
items,
init: precOrUndefined( data.init, options.precisionValue ),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ const AutomatonStateListener = ( props: AutomatonStateListenerProps ): JSX.Eleme
} );
} );

refAccumActions.current.push( {
type: 'Automaton/ChangeChannelInit',
channel: name,
init: channel.init,
} );

refAccumActions.current.push( {
type: 'Automaton/UpdateChannelLength',
channel: name,
Expand Down Expand Up @@ -133,6 +139,14 @@ const AutomatonStateListener = ( props: AutomatonStateListenerProps ): JSX.Eleme
} );
} );

channel.on( 'changeInit', ( { init } ) => {
refAccumActions.current.push( {
type: 'Automaton/ChangeChannelInit',
channel: name,
init,
} );
} );

channel.on( 'changeLength', ( { length } ) => {
refAccumActions.current.push( {
type: 'Automaton/UpdateChannelLength',
Expand Down
7 changes: 7 additions & 0 deletions packages/automaton-with-gui/src/view/components/Inspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Colors } from '../constants/Colors';
import { ErrorBoundary } from './ErrorBoundary';
import { Icons } from '../icons/Icons';
import { InspectorBeat } from './InspectorBeat';
import { InspectorChannel } from './InspectorChannel';
import { InspectorChannelItem } from './InspectorChannelItem';
import { InspectorCurveFx } from './InspectorCurveFx';
import { InspectorCurveNode } from './InspectorCurveNode';
Expand Down Expand Up @@ -48,6 +49,7 @@ const Inspector = ( { className }: {
selectedCurve,
stateSelectedNodes,
stateSelectedFxs,
stateSelectedChannel,
stateSelectedTimelineItems,
stateSelectedTimelineLabels,
settingsMode,
Expand All @@ -56,6 +58,7 @@ const Inspector = ( { className }: {
selectedCurve: state.curveEditor.selectedCurve,
stateSelectedNodes: state.curveEditor.selected.nodes,
stateSelectedFxs: state.curveEditor.selected.fxs,
stateSelectedChannel: state.timeline.selectedChannel,
stateSelectedTimelineItems: state.timeline.selected.items,
stateSelectedTimelineLabels: state.timeline.selected.labels,
settingsMode: state.settings.mode,
Expand Down Expand Up @@ -94,6 +97,10 @@ const Inspector = ( { className }: {
content = <InspectorLabel
name={ stateSelectedTimelineLabels[ 0 ] }
/>;
} else if ( stateSelectedChannel != null ) {
content = <InspectorChannel
channelName={ stateSelectedChannel }
/>;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { InspectorHeader } from './InspectorHeader';
import { InspectorHr } from './InspectorHr';
import { InspectorItem } from './InspectorItem';
import { NumberParam } from './NumberParam';
import { useDispatch, useSelector } from '../states/store';
import React from 'react';
import styled from 'styled-components';

// == styles =======================================================================================
const Root = styled.div`
`;

// == component ====================================================================================
interface Props {
className?: string;
channelName: string;
}

const InspectorChannel = ( props: Props ): JSX.Element | null => {
const { className, channelName } = props;
const dispatch = useDispatch();
const { automaton, stateChannel } = useSelector( ( state ) => ( {
automaton: state.automaton.instance,
stateChannel: state.automaton.channels[ channelName ],
} ) );
const channel = automaton?.getChannel( channelName ) ?? null;

if (
automaton == null ||
channel == null
) {
return null;
}

return (
<Root className={ className }>
<InspectorHeader text={ `Channel: ${ channelName }` } />

<InspectorHr />

<InspectorItem name="Init">
<NumberParam
type="float"
value={ stateChannel.init }
onChange={ ( value ) => channel.changeInit( value ) }
onSettle={ ( value, valuePrev ) => {
dispatch( {
type: 'History/Push',
description: 'Change Channel Init',
commands: [
{
type: 'channel/changeInit',
channel: channelName,
init: value,
initPrev: valuePrev,
}
],
} );
} }
/>
</InspectorItem>
</Root>
);
};

export { InspectorChannel };
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ const InspectorChannelItem = ( props: Props ): JSX.Element | null => {

return ( automaton && channel && stateItem && (
<Root className={ className }>
<InspectorHeader text={ 'Curve' } />
<InspectorHeader text={ `Item: ${ stateItem.curveId != null ? 'Curve' : 'Constant' }` } />

<InspectorHr />

Expand Down
12 changes: 12 additions & 0 deletions packages/automaton-with-gui/src/view/history/HistoryCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ export type HistoryCommand = {
item: string;
amp: number;
ampPrev: number;
} | {
type: 'channel/changeInit';
channel: string;
init: number;
initPrev: number;
} | {
type: 'curve/createNodeFromData';
curveId: string;
Expand Down Expand Up @@ -344,6 +349,13 @@ export function parseHistoryCommand( command: HistoryCommand ): {
redo: ( automaton ) => automaton.getChannel( command.channel )!
.changeCurveAmp( command.item, command.amp )
};
} else if ( command.type === 'channel/changeInit' ) {
return {
undo: ( automaton ) => automaton.getChannel( command.channel )!
.changeInit( command.initPrev ),
redo: ( automaton ) => automaton.getChannel( command.channel )!
.changeInit( command.init ),
};
} else if ( command.type === 'curve/createNodeFromData' ) {
return {
undo: ( automaton ) => automaton.getCurveById( command.curveId )!
Expand Down
8 changes: 8 additions & 0 deletions packages/automaton-with-gui/src/view/states/Automaton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface State {
length: number;
status: Status<ChannelStatusCode> | null;
items: { [ id: string ]: StateChannelItem };
init: number;
sortedItems: StateChannelItem[];
};
};
Expand Down Expand Up @@ -114,6 +115,10 @@ export type Action = {
type: 'Automaton/RemoveChannelItem';
channel: string;
id: string;
} | {
type: 'Automaton/ChangeChannelInit';
channel: string;
init: number;
} | {
type: 'Automaton/CreateCurve';
curveId: string;
Expand Down Expand Up @@ -223,6 +228,7 @@ export const reducer: Reducer<State, ContextAction> = ( state = initialState, ac
length: 1.0,
status: null,
items: {},
init: 0.0,
sortedItems: [],
};
} else if ( action.type === 'Automaton/RemoveChannel' ) {
Expand Down Expand Up @@ -277,6 +283,8 @@ export const reducer: Reducer<State, ContextAction> = ( state = initialState, ac
}

delete newState.channels[ action.channel ].items[ action.id ];
} else if ( action.type === 'Automaton/ChangeChannelInit' ) {
newState.channels[ action.channel ].init = action.init;
} else if ( action.type === 'Automaton/CreateCurve' ) {
newState.curves[ action.curveId ] = {
status: null,
Expand Down
2 changes: 1 addition & 1 deletion packages/automaton/src/Automaton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export class Automaton {
this.__time = t;

// update channels
const array = this.channels.map( ( channel ) => channel.consume( this.__time ) ).flat( 1 );
const array = this.channels.flatMap( ( channel ) => channel.consume( this.__time ) );
array.sort( ( [ a ], [ b ] ) => a - b ).forEach( ( [ _, func ] ) => func() );
}

Expand Down
Loading