forked from perelman/contra-renderer
96 lines
4.5 KiB
TypeScript
96 lines
4.5 KiB
TypeScript
import { Facing, ShortLinesPosition, PositionKind, CirclePosition, SemanticPosition, HandConnection, HandTo, oppositeFacing } from "../interpreterCommon.js";
|
|
import { Move } from "../libfigureMapper.js";
|
|
import { SemanticAnimationKind } from "../lowLevelMove.js";
|
|
import { Hand } from "../rendererConstants.js";
|
|
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, moveInterpreters } from "./_moveInterpreter.js";
|
|
|
|
const moveName: Move["move"] = "down the hall";
|
|
|
|
class DownTheHallSingleVariant extends SingleVariantMoveInterpreter<DownTheHall, typeof moveName> {
|
|
moveAsLowLevelMoves(): LowLevelMovesForAllDancers {
|
|
if (this.move.parameters.who !== "everyone") {
|
|
throw new Error("Don't know what it means for not everyone to go down the hall.");
|
|
}
|
|
if (this.move.parameters.moving !== "all") {
|
|
throw new Error("Not sure what it means for not all to be moving in down the hall.");
|
|
}
|
|
if (this.move.parameters.ender !== "turn-alone" && this.move.parameters.ender !== "turn-couple") {
|
|
throw new Error("Unsupported down the hall ender: " + this.move.parameters.ender);
|
|
}
|
|
if (this.move.parameters.facing === "forward then backward") {
|
|
throw new Error("Not sure what " + this.move.parameters.facing + " means for down the hall.");
|
|
}
|
|
return this.handleMove(({ startPos }) => {
|
|
const startFacing = this.move.parameters.facing === "backward" ? Facing.Up : Facing.Down;
|
|
if (startPos.facing !== startFacing && (startPos.facing === Facing.Up || startPos.facing === Facing.Down)) {
|
|
throw new Error("Started facing the wrong direction.");
|
|
}
|
|
const startWhich: ShortLinesPosition = startPos.kind === PositionKind.ShortLines
|
|
? startPos.which
|
|
// TODO Is this always the right way to convert circle to short lines?
|
|
// (Does it even matter except for dance starting formations?)
|
|
: new Map<CirclePosition, ShortLinesPosition>([
|
|
[CirclePosition.TopLeft, ShortLinesPosition.FarLeft],
|
|
[CirclePosition.BottomLeft, ShortLinesPosition.MiddleLeft],
|
|
[CirclePosition.BottomRight, ShortLinesPosition.MiddleRight],
|
|
[CirclePosition.TopRight, ShortLinesPosition.FarRight],
|
|
]).get(startPos.which)!;
|
|
const startingPos: SemanticPosition & { kind: PositionKind.ShortLines, setOffset: number } = {
|
|
kind: PositionKind.ShortLines,
|
|
facing: startFacing,
|
|
which: startWhich,
|
|
hands: startWhich.isMiddle() ? new Map<Hand, HandConnection>([
|
|
[Hand.Left, { hand: Hand.Left, to: HandTo.DancerLeft }],
|
|
[Hand.Right, { hand: Hand.Right, to: HandTo.DancerRight }],
|
|
]) : new Map<Hand, HandConnection>([
|
|
startWhich.isLeft() === (this.move.parameters.facing === "backward")
|
|
? [Hand.Left, { hand: Hand.Left, to: HandTo.DancerLeft }]
|
|
: [Hand.Right, { hand: Hand.Right, to: HandTo.DancerRight }]
|
|
]),
|
|
setOffset: startPos.setOffset ?? 0,
|
|
lineOffset: startPos.lineOffset,
|
|
};
|
|
|
|
return this.combine([
|
|
{
|
|
beats: 4,
|
|
endPosition: {
|
|
...startingPos,
|
|
setOffset: startingPos.setOffset + 1
|
|
},
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
{
|
|
beats: this.move.beats - 4,
|
|
endPosition: {
|
|
...startingPos,
|
|
setOffset: startingPos.setOffset + 1,
|
|
facing: oppositeFacing(startFacing),
|
|
which: this.move.parameters.ender === "turn-alone" ? startWhich : startWhich.swapOnSide(),
|
|
},
|
|
movementPattern: this.move.parameters.ender === "turn-couple"
|
|
? {
|
|
kind: SemanticAnimationKind.TwirlSwap,
|
|
around: startWhich.leftRightSide(),
|
|
// !== is NXOR, each of these booleans being flipped flips which hand to use.
|
|
hand: startWhich.isMiddle() !== (startWhich.isLeft() !== (this.move.parameters.facing === "forward"))
|
|
? Hand.Left
|
|
: Hand.Right
|
|
}
|
|
: {
|
|
kind: SemanticAnimationKind.Linear,
|
|
minRotation: startWhich.isMiddle() === startWhich.isLeft() ? -180 : +180,
|
|
},
|
|
},
|
|
], startingPos);
|
|
});
|
|
}
|
|
}
|
|
|
|
class DownTheHall extends MoveInterpreter<typeof moveName> {
|
|
buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter {
|
|
return new DownTheHallSingleVariant(this, startingPos);
|
|
}
|
|
}
|
|
|
|
moveInterpreters.set(moveName, DownTheHall); |