forked from perelman/contra-renderer
106 lines
4.6 KiB
TypeScript
106 lines
4.6 KiB
TypeScript
import { BalanceWeight, Facing, HandConnection, HandTo, PositionKind, facingAdjacent, facingRequireAdjacent } from "../interpreterCommon.js";
|
|
import { SemanticAnimationKind } from "../lowLevelMove.js";
|
|
import { Hand } from "../rendererConstants.js";
|
|
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, Variant, VariantCollection, moveInterpreters } from "./_moveInterpreter.js";
|
|
|
|
const moveName = "balance";
|
|
|
|
class BalanceSingleVariant extends SingleVariantMoveInterpreter<Balance, typeof moveName> {
|
|
private static readonly balanceOptions : [BalanceWeight, BalanceWeight | undefined, Hand | undefined][]= [
|
|
// TODO Any others?
|
|
[BalanceWeight.Forward, undefined, undefined],
|
|
[BalanceWeight.Forward, BalanceWeight.Backward, undefined],
|
|
// TODO Should be left/right/inside/outside hands?
|
|
[BalanceWeight.Forward, BalanceWeight.Backward, Hand.Left],
|
|
[BalanceWeight.Forward, BalanceWeight.Backward, Hand.Right],
|
|
[BalanceWeight.Right, BalanceWeight.Backward, undefined],
|
|
[BalanceWeight.Right, BalanceWeight.Left, undefined],
|
|
[BalanceWeight.Left, BalanceWeight.Right, undefined],
|
|
];
|
|
|
|
moveAsVariants(previousMoveVariant: string): VariantCollection {
|
|
const res = new Map<string, Variant>();
|
|
|
|
for (const [firstWeight, secondWeight, hand] of BalanceSingleVariant.balanceOptions) {
|
|
// If balancing someone, need to know by which hand.
|
|
if ((hand === undefined) !== (this.move.parameters.who === "everyone")) continue;
|
|
try {
|
|
res.set((firstWeight?.toString() ?? "") + (secondWeight?.toString() ?? "") + (hand === undefined ? "" : hand.toString() + "Hand"), {
|
|
lowLevelMoves: this.moveAsLowLevelMovesWeights(firstWeight, secondWeight, hand),
|
|
previousMoveVariant
|
|
});
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
moveAsLowLevelMovesWeights(firstWeight?: BalanceWeight, secondWeight?: BalanceWeight, hand?: Hand): LowLevelMovesForAllDancers {
|
|
if (this.move.parameters.who !== "everyone") {
|
|
return this.handlePairedMove(this.move.parameters.who, ({ startPos, withPos }) => {
|
|
// TODO Does this need to support balancing inside/outside hands? If so how to identify them?
|
|
const hands = hand === undefined ? startPos.hands : new Map<Hand, HandConnection>([[hand, {hand, to: HandTo.DancerForward}]]);
|
|
|
|
const facing = facingRequireAdjacent(startPos, withPos, this.move.move);
|
|
|
|
const startingPos = {...startPos, facing, hands};
|
|
|
|
return this.combine([
|
|
{
|
|
beats: this.moveInterpreter.balancePartBeats,
|
|
endPosition: { ...startingPos, balance: firstWeight, hands },
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
{
|
|
beats: this.moveInterpreter.balancePartBeats,
|
|
endPosition: { ...startingPos, balance: secondWeight, hands },
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
], startingPos);
|
|
});
|
|
} else {
|
|
return this.handleMove(({ startPos }) => {
|
|
// TODO Use who to determine facing?
|
|
// TODO Could be left to right, not back and forth?
|
|
// TODO How to determine hand... by next move, I guess?
|
|
if (startPos.kind === PositionKind.Circle && startPos.facing === Facing.CenterOfCircle) {
|
|
if (firstWeight === BalanceWeight.Left || firstWeight === BalanceWeight.Right || firstWeight === BalanceWeight.Backward
|
|
|| secondWeight === BalanceWeight.Left || secondWeight === BalanceWeight.Right || secondWeight === BalanceWeight.Backward) {
|
|
throw new Error("Balancing left or right in a circle is unsupported.");
|
|
}
|
|
}
|
|
|
|
return this.combine([
|
|
{
|
|
beats: this.moveInterpreter.balancePartBeats,
|
|
endPosition: { ...startPos, balance: firstWeight },
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
{
|
|
beats: this.moveInterpreter.balancePartBeats,
|
|
endPosition: { ...startPos, balance: secondWeight },
|
|
movementPattern: { kind: SemanticAnimationKind.Linear },
|
|
},
|
|
], startPos);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
class Balance extends MoveInterpreter<typeof moveName> {
|
|
public readonly balancePartBeats: number;
|
|
|
|
constructor(args: MoveInterpreterCtorArgs<typeof moveName>) {
|
|
super(args);
|
|
|
|
this.balancePartBeats = this.move.beats / 2;
|
|
}
|
|
|
|
buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter {
|
|
return new BalanceSingleVariant(this, startingPos);
|
|
}
|
|
}
|
|
|
|
moveInterpreters.set(moveName, Balance);
|