Compare commits
4 Commits
c4462b0f50
...
239bc60500
Author | SHA1 | Date | |
---|---|---|---|
239bc60500 | |||
e240b690f4 | |||
2631bad801 | |||
5de6db868b |
|
@ -140,6 +140,26 @@ function danceAsLowLevelMoves(moves: Move[], startingVariants: AllVariantsForMov
|
|||
if (move.progression) numProgessions++;
|
||||
}
|
||||
|
||||
// If there's multiple variants, check if there's fewer that flow into the first move.
|
||||
if (currentVariantMoves.size !== 1) {
|
||||
let newMoves: VariantCollection | undefined;
|
||||
try {
|
||||
newMoves = allVariantsForMove({ move: moves[0], nextMove: moves[1], startingVariants: currentVariants, numProgessions });
|
||||
} catch {
|
||||
newMoves = undefined;
|
||||
}
|
||||
if (newMoves) {
|
||||
const firstMoveVariants = [...newMoves.values()].map(v => v.previousMoveVariant);
|
||||
if (firstMoveVariants.length > 0) {
|
||||
for (const variant of [...currentVariantMoves.keys()]) {
|
||||
if (!firstMoveVariants.includes(variant)) {
|
||||
currentVariantMoves.delete(variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const res = [...currentVariantMoves.values()].at(-1)!;
|
||||
if (currentVariantMoves.size !== 1) {
|
||||
res.get(DancerIdentity.OnesRobin)![0].interpreterError = "Expected exactly one variant. Found "
|
||||
|
@ -156,12 +176,15 @@ function danceAsLowLevelMoves(moves: Move[], startingVariants: AllVariantsForMov
|
|||
if (!lowLevelMoves[i].endPosition) throw "endPosition is undefined";
|
||||
lowLevelMoves[i].endPosition = lowLevelMoves[i + 1].startPosition;
|
||||
if (!lowLevelMoves[i].endPosition) throw "endPosition is undefined now";
|
||||
// TODO Exactly what is the StandStill fixup needed for? Can it be handled in other ways? Should it be rotation only?
|
||||
/*
|
||||
if (lowLevelMoves[i].movementPattern.kind === SemanticAnimationKind.StandStill) {
|
||||
lowLevelMoves[i].startPosition = lowLevelMoves[i].endPosition;
|
||||
if (i > 0) {
|
||||
lowLevelMoves[i - 1].endPosition = lowLevelMoves[i].startPosition;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
// If progression isn't detected properly, do nothing.
|
||||
if (progressionInSets === 0) {
|
||||
|
|
|
@ -349,6 +349,10 @@ export class ShortLinesPosition {
|
|||
return this.isLeft() ? Facing.Right : Facing.Left;
|
||||
}
|
||||
|
||||
public isToLeftOf(otherPos: ShortLinesPosition): boolean {
|
||||
return this.enumValue < otherPos.enumValue;
|
||||
}
|
||||
|
||||
public toString() : string {
|
||||
return this.enumValue.toString();
|
||||
}
|
||||
|
@ -519,4 +523,84 @@ export function handToDancerToSideInCircleFacingUpOrDown(which: CirclePosition):
|
|||
? [Hand.Right, { hand: Hand.Left, to: HandTo.DancerRight }]
|
||||
: [Hand.Left, { hand: Hand.Right, to: HandTo.DancerLeft }]
|
||||
]);
|
||||
}
|
||||
|
||||
export function facingAdjacent(pos: SemanticPosition, otherPos: SemanticPosition): Facing | undefined {
|
||||
if (pos.kind !== otherPos.kind) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (pos.kind === PositionKind.ShortLines) {
|
||||
if (otherPos.kind !== PositionKind.ShortLines) {
|
||||
return undefined;
|
||||
}
|
||||
if ((pos.setOffset ?? 0) !== (otherPos.setOffset ?? 0)) {
|
||||
return undefined;
|
||||
}
|
||||
if ((pos.lineOffset ?? 0) !== (otherPos.lineOffset ?? 0)) {
|
||||
if (pos.which === ShortLinesPosition.FarLeft && otherPos.which === ShortLinesPosition.FarRight
|
||||
&& ((pos.lineOffset ?? 0) - 1) === (otherPos.lineOffset ?? 0)) {
|
||||
return Facing.Left;
|
||||
} else if (pos.which === ShortLinesPosition.FarRight && otherPos.which === ShortLinesPosition.FarLeft
|
||||
&& ((pos.lineOffset ?? 0) + 1) === (otherPos.lineOffset ?? 0)) {
|
||||
return Facing.Right;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (otherPos.which.isToLeftOf(pos.which)) {
|
||||
return Facing.Left;
|
||||
} else {
|
||||
return Facing.Right;
|
||||
}
|
||||
} else if (pos.kind === PositionKind.Circle) {
|
||||
if (otherPos.kind !== PositionKind.Circle) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if ((pos.lineOffset ?? 0) !== (otherPos.lineOffset ?? 0)) {
|
||||
// TODO
|
||||
return undefined;
|
||||
}
|
||||
if ((pos.setOffset ?? 0) !== (otherPos.setOffset ?? 0)) {
|
||||
// TODO
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (pos.which.leftRightSide() === otherPos.which.leftRightSide()) {
|
||||
if (pos.which.topBottomSide() === otherPos.which.topBottomSide()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if ((pos.lineOffset ?? 0) !== (otherPos.lineOffset ?? 0)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if ((pos.setOffset ?? 0) === (otherPos.setOffset ?? 0)) {
|
||||
return pos.which.facingUpOrDown();
|
||||
} else if (((pos.setOffset ?? 0) + 1) === (otherPos.setOffset ?? 0) && pos.which.isTop()) {
|
||||
return Facing.Up;
|
||||
} else if (((pos.setOffset ?? 0) - 1) === (otherPos.setOffset ?? 0) && !pos.which.isTop()) {
|
||||
return Facing.Down;
|
||||
}
|
||||
} else if (pos.which.topBottomSide() === otherPos.which.topBottomSide()) {
|
||||
if ((pos.setOffset ?? 0) === (otherPos.setOffset ?? 0)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if ((pos.lineOffset ?? 0) !== (otherPos.lineOffset ?? 0)) {
|
||||
return pos.which.facingAcross();
|
||||
} else if (((pos.lineOffset ?? 0) + 1) === (otherPos.lineOffset ?? 0) && pos.which.isLeft()) {
|
||||
return Facing.Left;
|
||||
} else if (((pos.lineOffset ?? 0) - 1) === (otherPos.lineOffset ?? 0) && !pos.which.isLeft()) {
|
||||
return Facing.Right;
|
||||
}
|
||||
} else {
|
||||
// Opposite corners of circle.
|
||||
return undefined;
|
||||
}
|
||||
} else {
|
||||
throw new Error("Unexpected PositionKind: " + otherPos.kind);
|
||||
}
|
||||
}
|
|
@ -77,6 +77,8 @@ export type SemanticAnimation = {
|
|||
|
||||
// If true, move in close while rotating.
|
||||
close: boolean,
|
||||
|
||||
facing?: animation.RotationAnimationFacing,
|
||||
} | {
|
||||
kind: SemanticAnimationKind.Swing,
|
||||
|
||||
|
@ -292,7 +294,7 @@ function SemanticToSetPosition(semantic: SemanticPosition): DancerSetPosition {
|
|||
&& (semantic.balance === BalanceWeight.Backward || semantic.balance === BalanceWeight.Forward)) {
|
||||
balanceOffset = {
|
||||
x: 0,
|
||||
y: position.y * (
|
||||
y: Math.sign(position.y) * (
|
||||
semantic.balance === BalanceWeight.Forward
|
||||
? -balanceAmount
|
||||
: balanceAmount)
|
||||
|
@ -352,9 +354,9 @@ function SemanticToSetPosition(semantic: SemanticPosition): DancerSetPosition {
|
|||
case HandTo.DancerRight:
|
||||
return OffsetPlus({ x: +1, y: 0 }, balanceHandAdjustment);
|
||||
case HandTo.DancerForward:
|
||||
const armLength = yAmount + (semantic.balance === BalanceWeight.Backward ? balanceAmount : 0);
|
||||
const armLength = yAmount + (semantic.balance === BalanceWeight.Backward ? balanceAmount : semantic.balance === BalanceWeight.Forward ? -balanceAmount : 0);
|
||||
if (hand === connection.hand) {
|
||||
return { x: 0, y: +armLength/2 };
|
||||
return { x: 0, y: +armLength };
|
||||
} else {
|
||||
return { x: dancerWidth / 2 * (hand === Hand.Left ? -1 : +1), y: +armLength };
|
||||
}
|
||||
|
@ -655,7 +657,7 @@ function animateLowLevelMoveWithoutSlide(move: LowLevelMove): animation.Animatio
|
|||
width: 1,
|
||||
height: 1,
|
||||
},
|
||||
facing: animation.RotationAnimationFacing.Forward,
|
||||
facing: move.movementPattern.facing ?? animation.RotationAnimationFacing.Forward,
|
||||
closer: move.movementPattern.close ? {
|
||||
transitionBeats: 1,
|
||||
minDistance: 1,
|
||||
|
|
|
@ -428,7 +428,7 @@ displaySettingsDiv.appendChild(debugRenderLabel);
|
|||
wrapperDiv.appendChild(displaySettingsDiv);
|
||||
|
||||
// Default dance is Two Hearts in Time by Isaac Banner. Selected arbitrarily.
|
||||
const defaultDanceTitle = "Two Hearts in Time";
|
||||
const defaultDanceTitle = "March for Andrea";
|
||||
|
||||
const danceList = document.createElement('select');
|
||||
for (const [idx, dance] of danceLibrary.dances.entries()) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { CoupleRole, DanceRole, DancerIdentity, ExtendedDancerIdentity } from "../danceCommon.js";
|
||||
import { CirclePosition, CircleSideOrCenter, PositionKind, SemanticPosition } from "../interpreterCommon.js";
|
||||
import { CirclePosition, CircleSideOrCenter, DancerDistance, PositionKind, SemanticPosition } from "../interpreterCommon.js";
|
||||
import { Move, chooser_pairz } from "../libfigureMapper.js";
|
||||
import { LowLevelMove, SemanticAnimation, SemanticAnimationKind } from "../lowLevelMove.js";
|
||||
|
||||
|
@ -44,12 +44,25 @@ export abstract class SingleVariantMoveInterpreter<T extends MoveInterpreter<N>,
|
|||
constructor(moveInterpreter: T, startingPos: SemanticPositionsForAllDancers) {
|
||||
this.moveInterpreter = moveInterpreter;
|
||||
this.startingPos = startingPos;
|
||||
|
||||
if (!this.allowStartingClose()) {
|
||||
for (const [id, startPos] of this.startingPos) {
|
||||
if (startPos.dancerDistance && startPos.dancerDistance !== DancerDistance.Normal) {
|
||||
throw new Error("Can not start " + this.move.move + " at dancerDistance " + startPos.dancerDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get move() : Move & { move: N } {
|
||||
return this.moveInterpreter.move;
|
||||
}
|
||||
|
||||
allowStartingClose(): boolean {
|
||||
// Swings can end close, but most moves can't start close, so do this check by default for all moves.
|
||||
return false;
|
||||
}
|
||||
|
||||
moveAsLowLevelMoves(): LowLevelMovesForAllDancers {
|
||||
throw new Error("You must implement either moveAsLowLevelMoves() or moveAsVariants().");
|
||||
}
|
||||
|
|
|
@ -1,39 +1,101 @@
|
|||
import { BalanceWeight } from "../interpreterCommon.js";
|
||||
import { BalanceWeight, Facing, HandConnection, HandTo, PositionKind, facingAdjacent } from "../interpreterCommon.js";
|
||||
import { SemanticAnimationKind } from "../lowLevelMove.js";
|
||||
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, moveInterpreters } from "./_moveInterpreter.js";
|
||||
import { Hand } from "../rendererConstants.js";
|
||||
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, Variant, VariantCollection, moveInterpreters } from "./_moveInterpreter.js";
|
||||
|
||||
class BalanceSingleVariant extends SingleVariantMoveInterpreter<Balance, "balance"> {
|
||||
moveAsLowLevelMoves(): LowLevelMovesForAllDancers {
|
||||
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?
|
||||
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],
|
||||
];
|
||||
|
||||
return this.combine([
|
||||
{
|
||||
beats: this.moveInterpreter.forwardBeats,
|
||||
endPosition: { ...startPos, balance: BalanceWeight.Forward },
|
||||
movementPattern: { kind: SemanticAnimationKind.Linear },
|
||||
},
|
||||
{
|
||||
beats: this.moveInterpreter.backwardBeats,
|
||||
endPosition: { ...startPos, balance: BalanceWeight.Backward },
|
||||
movementPattern: { kind: SemanticAnimationKind.Linear },
|
||||
},
|
||||
], startPos);
|
||||
});
|
||||
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 = facingAdjacent(startPos, withPos);
|
||||
if (facing === undefined) {
|
||||
throw new Error("Not adjacent to paired dancer.");
|
||||
}
|
||||
|
||||
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<"balance"> {
|
||||
public readonly forwardBeats: number;
|
||||
public readonly backwardBeats: number;
|
||||
public readonly balancePartBeats: number;
|
||||
|
||||
constructor(args: MoveInterpreterCtorArgs<"balance">) {
|
||||
super(args);
|
||||
|
||||
this.forwardBeats = this.move.beats / 2;
|
||||
this.backwardBeats = this.move.beats - this.forwardBeats;
|
||||
this.balancePartBeats = this.move.beats / 2;
|
||||
}
|
||||
|
||||
buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { BalanceWeight, Facing, HandConnection, HandTo, PositionKind, SemanticPosition } from "../interpreterCommon.js";
|
||||
import { BalanceWeight, Facing, HandConnection, HandTo, PositionKind, SemanticPosition, handsInCircle } from "../interpreterCommon.js";
|
||||
import { Move } from "../libfigureMapper.js";
|
||||
import { LowLevelMove, SemanticAnimationKind } from "../lowLevelMove.js";
|
||||
import { Hand } from "../rendererConstants.js";
|
||||
|
@ -11,14 +11,11 @@ export function balanceCircleInAndOut(move: Move, startPos: SemanticPosition, ba
|
|||
}
|
||||
|
||||
balanceBeats ??= 4;
|
||||
const balancePartBeats = balanceBeats/2;
|
||||
const balancePartBeats = balanceBeats / 2;
|
||||
|
||||
const holdingHandsInCircle: SemanticPosition = {...startPos,
|
||||
facing: Facing.CenterOfCircle,
|
||||
hands: new Map<Hand, HandConnection>([
|
||||
[Hand.Left, { hand: Hand.Right, to: HandTo.LeftInCircle }],
|
||||
[Hand.Right, { hand: Hand.Left, to: HandTo.RightInCircle }],
|
||||
]),
|
||||
hands: handsInCircle,
|
||||
};
|
||||
const circleBalancedIn: SemanticPosition = {...holdingHandsInCircle,
|
||||
balance: BalanceWeight.Forward,
|
||||
|
|
|
@ -18,6 +18,10 @@ class BoxTheGnatSingleVariant extends SingleVariantMoveInterpreter<BoxTheGnat, t
|
|||
const balancePartBeats = balanceBeats / 2;
|
||||
const twirlBeats = this.move.beats - balanceBeats;
|
||||
|
||||
if (startPos.hands && startPos.hands.get(Hand.Right) === undefined && startPos.hands.get(Hand.Left)?.hand === Hand.Left) {
|
||||
throw new Error(this.move.move + " shouldn't start with holding left hands. Something went wrong.");
|
||||
}
|
||||
|
||||
// TODO Adjust facing?
|
||||
const startPosition = { ...startPos, hands: new Map<Hand, HandConnection>([[hand, { hand, to: HandTo.DancerForward }]]) };
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { RotationAnimationFacing } from "../animation.js";
|
||||
import { Move } from "../libfigureMapper.js";
|
||||
import { SemanticAnimationKind } from "../lowLevelMove.js";
|
||||
import { Hand } from "../rendererConstants.js";
|
||||
|
@ -6,6 +7,10 @@ import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpre
|
|||
const moveName: Move["move"] = "butterfly whirl";
|
||||
|
||||
class ButterflyWhirlSingleVariant extends SingleVariantMoveInterpreter<ButterflyWhirl, typeof moveName> {
|
||||
override allowStartingClose(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
moveAsLowLevelMoves(): LowLevelMovesForAllDancers {
|
||||
return this.handleCircleMove(({ startPos }) => {
|
||||
return this.combine([{
|
||||
|
@ -14,8 +19,10 @@ class ButterflyWhirlSingleVariant extends SingleVariantMoveInterpreter<Butterfly
|
|||
movementPattern: {
|
||||
kind: SemanticAnimationKind.RotateAround,
|
||||
around: startPos.which.leftRightSide(),
|
||||
// TODO hand around isn't the same as allemande...
|
||||
byHand: startPos.which.isOnLeftLookingAcross() ? Hand.Right : Hand.Left,
|
||||
facing: startPos.which.isOnLeftLookingAcross()
|
||||
? RotationAnimationFacing.Forward
|
||||
: RotationAnimationFacing.Backward,
|
||||
close: true,
|
||||
minAmount: 360,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Facing, handsInCircle } from "../interpreterCommon.js";
|
||||
import { DancerDistance, Facing, handsInCircle } from "../interpreterCommon.js";
|
||||
import { Move } from "../libfigureMapper.js";
|
||||
import { SemanticAnimationKind } from "../lowLevelMove.js";
|
||||
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, moveInterpreters } from "./_moveInterpreter.js";
|
||||
|
|
|
@ -22,6 +22,9 @@ class DownTheHallSingleVariant extends SingleVariantMoveInterpreter<DownTheHall,
|
|||
}
|
||||
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?
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Facing, SemanticPosition } from "../interpreterCommon.js";
|
||||
import { DancerDistance, Facing, SemanticPosition } from "../interpreterCommon.js";
|
||||
import { SemanticAnimationKind, LowLevelMove } from "../lowLevelMove.js";
|
||||
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, PartialLowLevelMove, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, moveInterpreters } from "./_moveInterpreter.js";
|
||||
import { balanceCircleInAndOut } from "./balanceTheRing.js";
|
||||
|
|
|
@ -9,7 +9,7 @@ const moveName: Move["move"] = "roll away";
|
|||
class RollAwaySingleVariant extends SingleVariantMoveInterpreter<RollAway, typeof moveName> {
|
||||
moveAsLowLevelMoves(): LowLevelMovesForAllDancers {
|
||||
// TODO maybe can roll away in short lines?
|
||||
return this.handleCirclePairedMove(this.move.parameters.who, ({ id, startPos, withPos }) => {
|
||||
return this.handleCirclePairedMove(this.move.parameters.whom, ({ id, startPos, withPos }) => {
|
||||
let isRoller: boolean;
|
||||
switch (this.move.parameters.who) {
|
||||
case "gentlespoons":
|
||||
|
|
|
@ -33,6 +33,10 @@ const swingEndValues: SwingEnd[] = [
|
|||
];
|
||||
|
||||
class SwingSingleVariant extends SingleVariantMoveInterpreter<Swing, typeof moveName> {
|
||||
override allowStartingClose(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
moveAsVariants(previousMoveVariant: string): VariantCollection {
|
||||
const res = new Map<string, Variant>();
|
||||
|
||||
|
@ -204,10 +208,12 @@ class Swing extends MoveInterpreter<typeof moveName> {
|
|||
? 2
|
||||
: this.move.beats / 4;
|
||||
this.swingBeats = this.move.beats - this.balancePartBeats * 2;
|
||||
break;
|
||||
case "meltdown":
|
||||
this.balancePartBeats = 0;
|
||||
this.meltdownBeats = this.move.beats >= 8 ? 4 : this.move.beats / 2;
|
||||
this.swingBeats = this.move.beats - this.meltdownBeats;
|
||||
break;
|
||||
default:
|
||||
throw new Error ("Unknown swing prefix: " + this.move.parameters.prefix);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user