forked from perelman/contra-renderer
106 lines
4.4 KiB
TypeScript
106 lines
4.4 KiB
TypeScript
import { PositionKind, SemanticPosition, Facing, BalanceWeight, handsInLine, CircleSide, handsInLongLines } from "../interpreterCommon.js";
|
|
import { SemanticAnimationKind } from "../lowLevelMove.js";
|
|
import { Hand } from "../rendererConstants.js";
|
|
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, PartialLowLevelMove, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, moveInterpreters } from "./_moveInterpreter.js";
|
|
|
|
const moveName = "Rory O'More";
|
|
class RoryOMoreSingleVariant extends SingleVariantMoveInterpreter<RoryOMore, typeof moveName> {
|
|
moveAsLowLevelMoves(): LowLevelMovesForAllDancers {
|
|
|
|
// TODO Could be in long or short lines.
|
|
return this.handleMove(({ startPos }) => {
|
|
const startingPos: SemanticPosition = {
|
|
...startPos,
|
|
hands: handsInLine({ wavy: true, which: startPos.which, facing: startPos.facing })
|
|
};
|
|
|
|
let endPos: SemanticPosition;
|
|
if (startPos.kind === PositionKind.ShortLines) {
|
|
if (startPos.facing !== Facing.Up && startPos.facing !== Facing.Down) {
|
|
throw new Error("To be in short wavy lines, must be facing up or down, not " + startPos.facing);
|
|
}
|
|
const { newPos: endWhich, wrap } = startPos.which.shiftWithWrap(this.moveInterpreter.dir, startPos.facing);
|
|
const endLineOffset = !wrap
|
|
? startPos.lineOffset
|
|
: (startPos.lineOffset ?? 0) + wrap;
|
|
if (wrap) {
|
|
startingPos.hands = handsInLongLines(true)
|
|
}
|
|
endPos = {
|
|
...startPos,
|
|
which: endWhich,
|
|
hands: handsInLine({ wavy: true, which: endWhich, facing: startPos.facing }),
|
|
lineOffset: endLineOffset,
|
|
};
|
|
} else {
|
|
if (startPos.facing !== Facing.Left && startPos.facing !== Facing.Right) {
|
|
throw new Error("To be in long wavy lines, must be facing left or right, not " + startPos.facing);
|
|
}
|
|
const endWhich = startPos.which.swapUpAndDown();
|
|
const sideTowards = (startPos.facing === Facing.Right)
|
|
=== (this.moveInterpreter.dir === Hand.Left)
|
|
? CircleSide.Bottom
|
|
: CircleSide.Top;
|
|
const endSetOffset = sideTowards === endWhich.topBottomSide()
|
|
? startPos.setOffset
|
|
: (startPos.setOffset ?? 0) + (sideTowards === CircleSide.Bottom ? +1 : -1);
|
|
endPos = {
|
|
...startPos,
|
|
which: endWhich,
|
|
hands: handsInLine({ wavy: true, which: endWhich, facing: startPos.facing }),
|
|
setOffset: endSetOffset,
|
|
};
|
|
}
|
|
|
|
const maybeBalance: PartialLowLevelMove[] = (this.move.parameters.bal ? [
|
|
{
|
|
beats: this.moveInterpreter.balPartBeats,
|
|
endPosition: { ...startingPos, balance: this.moveInterpreter.dir === Hand.Left ? BalanceWeight.Left : BalanceWeight.Right },
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
{
|
|
beats: this.moveInterpreter.balPartBeats,
|
|
endPosition: { ...startingPos, balance: this.moveInterpreter.dir === Hand.Left ? BalanceWeight.Right : BalanceWeight.Left },
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
] : []);
|
|
|
|
return this.combine([...maybeBalance,
|
|
{
|
|
beats: this.moveInterpreter.roryBeats,
|
|
endPosition: endPos,
|
|
movementPattern: {
|
|
kind: SemanticAnimationKind.Linear,
|
|
minRotation: this.moveInterpreter.dir === Hand.Right ? +360 : -360,
|
|
handsDuring: "None",
|
|
},
|
|
}
|
|
], startingPos);
|
|
});
|
|
}
|
|
}
|
|
|
|
class RoryOMore extends MoveInterpreter<typeof moveName> {
|
|
public readonly dir: Hand;
|
|
public readonly balPartBeats: number;
|
|
public readonly roryBeats: number;
|
|
|
|
constructor(args: MoveInterpreterCtorArgs<typeof moveName>) {
|
|
super(args);
|
|
|
|
if (this.move.parameters.who !== "everyone") {
|
|
throw new Error(this.move.move + " that doesn't include everyone is unsupported.");
|
|
}
|
|
|
|
this.dir = this.move.parameters.slide ? Hand.Left : Hand.Right;
|
|
const balBeats = this.move.parameters.bal ? this.move.beats / 2 : 0;
|
|
this.balPartBeats = balBeats / 2;
|
|
this.roryBeats = this.move.beats - balBeats;
|
|
}
|
|
|
|
buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter {
|
|
return new RoryOMoreSingleVariant(this, startingPos);
|
|
}
|
|
}
|
|
|
|
moveInterpreters.set(moveName, RoryOMore); |