forked from perelman/contra-renderer
100 lines
4.0 KiB
TypeScript
100 lines
4.0 KiB
TypeScript
import { DanceRole, CoupleRole } from "../danceCommon.js";
|
|
import { SemanticPosition, Facing, HandConnection, HandTo, BalanceWeight, handsInLine, LongLines } from "../interpreterCommon.js";
|
|
import { Move } from "../libfigureMapper.js";
|
|
import { SemanticAnimationKind } from "../lowLevelMove.js";
|
|
import { Hand } from "../rendererConstants.js";
|
|
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, PartialLowLevelMove, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, Variant, VariantCollection, moveInterpreters } from "./_moveInterpreter.js";
|
|
|
|
const moveName: Move["move"] = "box circulate";
|
|
|
|
class BoxCirculateSingleVariant extends SingleVariantMoveInterpreter<BoxCirculate, typeof moveName> {
|
|
moveAsVariants(previousMoveVariant: string): VariantCollection {
|
|
const res = new Map<string, Variant>();
|
|
|
|
for (const crossPartway of (this.move.note?.includes("catch") ? [true] : [true, false])) {
|
|
try {
|
|
res.set(crossPartway ? "CrossPartway" : "Normal", {
|
|
lowLevelMoves: this.moveAsLowLevelMovesCross(crossPartway),
|
|
previousMoveVariant
|
|
});
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
moveAsLowLevelMovesCross(crossPartway: boolean): LowLevelMovesForAllDancers {
|
|
const circulateRight: boolean = this.move.parameters.hand;
|
|
const whoCrosses = this.move.parameters.who;
|
|
return this.handleCircleMove(({ id, startPos }) => {
|
|
let isCrossing: boolean;
|
|
switch (whoCrosses) {
|
|
case "gentlespoons":
|
|
isCrossing = id.danceRole === DanceRole.Lark;
|
|
break;
|
|
case "ladles":
|
|
isCrossing = id.danceRole === DanceRole.Robin;
|
|
break;
|
|
case "ones":
|
|
isCrossing = id.coupleRole === CoupleRole.Ones;
|
|
break;
|
|
case "twos":
|
|
isCrossing = id.coupleRole === CoupleRole.Twos;
|
|
break;
|
|
case "first corners":
|
|
case "second corners":
|
|
throw "first/second corner leading box circulate doesn't make sense?";
|
|
}
|
|
|
|
// Starts in long wavy lines.
|
|
const startingPos: SemanticPosition = {
|
|
...startPos,
|
|
facing: isCrossing ? startPos.which.facingAcross() : startPos.which.facingOut(),
|
|
hands: new Map<Hand, HandConnection>([
|
|
[Hand.Left, { hand: Hand.Left, to: HandTo.DancerLeft }],
|
|
[Hand.Right, { hand: Hand.Right, to: HandTo.DancerRight }],
|
|
]),
|
|
balance: undefined,
|
|
longLines: undefined,
|
|
dancerDistance: undefined,
|
|
};
|
|
const balance: PartialLowLevelMove[] = this.move.parameters.bal ? [
|
|
{
|
|
beats: 2,
|
|
endPosition: { ...startingPos, balance: circulateRight ? BalanceWeight.Right : BalanceWeight.Left },
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
{
|
|
beats: 2,
|
|
endPosition: { ...startingPos, balance: BalanceWeight.Backward },
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
] : [];
|
|
const circulate: PartialLowLevelMove = {
|
|
beats: this.move.beats - (this.move.parameters.bal ? 4 : 0),
|
|
endPosition: {
|
|
...startingPos,
|
|
which: isCrossing ? startingPos.which.swapAcross() : startingPos.which.swapUpAndDown(),
|
|
facing: isCrossing ? startingPos.facing : startingPos.facing === Facing.Right ? Facing.Left : Facing.Right,
|
|
longLines: isCrossing && crossPartway ? LongLines.Center : undefined,
|
|
},
|
|
movementPattern: {
|
|
// TODO Not sure loop should really be linear...
|
|
kind: SemanticAnimationKind.Linear,
|
|
minRotation: isCrossing ? undefined : circulateRight ? 180 : -180,
|
|
handsDuring: "None",
|
|
}
|
|
};
|
|
return this.combine([...balance, circulate], startingPos);
|
|
});
|
|
}
|
|
}
|
|
|
|
class BoxCirculate extends MoveInterpreter<typeof moveName> {
|
|
buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter {
|
|
return new BoxCirculateSingleVariant(this, startingPos);
|
|
}
|
|
}
|
|
|
|
moveInterpreters.set(moveName, BoxCirculate); |