Compare commits

..

2 Commits

2 changed files with 109 additions and 25 deletions

View File

@ -991,7 +991,11 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
endSet += startPos.which.isLeft() ? +1 : -1;
break;
}
const startPosition = { ...startPos, hands: new Map<Hand, HandConnection>([[hand, { hand, to }]]) };
const startPosition = {
...startPos,
hands: new Map<Hand, HandConnection>([[hand, { hand, to }]]),
facing: startPos.which.facingAcross(),
};
const turnTo = hand === Hand.Right ? HandTo.DancerRight : HandTo.DancerLeft;
@ -1030,10 +1034,11 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
})
], startPosition);
} else {
const startingPos = { ...startPos, facing: startPos.which.facingAcross() };
return combine([
{
beats: pullBeats,
endPosition: startPos,
endPosition: startingPos,
movementPattern: {
kind: SemanticAnimationKind.StandStill,
}
@ -1041,7 +1046,7 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
{
beats: turnBeats,
endPosition: {
...startPos,
...startingPos,
// TODO Does CourtesyTurn always end in same position?
which: startPos.which,
},
@ -1049,7 +1054,7 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
kind: SemanticAnimationKind.CourtesyTurn,
}
}
], startPos);
], startingPos);
}
});
@ -1426,17 +1431,22 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
const centerShoulder = firstPassInCenter === move.parameters.shoulder ? Hand.Right : Hand.Left;
const endsShoulder = centerShoulder.opposite();
return handleMove(({ id, startPos }) => {
const endsInCircle = startPos.kind === PositionKind.Circle;
type HeyStep = {
kind: "Loop" | "CenterPass" | "EndsPass",
kind: "StandStill" | "Loop" | "CenterPass" | "EndsPassIn" | "EndsPassOut",
endPosition: SemanticPosition,
}
function heyStepToPartialLowLevelMove(heyStep: HeyStep): PartialLowLevelMove & { heyStep: HeyStep } {
return {
beats: heyPartBeats,
// TODO use circle positions on ends? ... unless hey ends in a box the gnat or similar...
endPosition: heyStep.endPosition,
movementPattern: heyStep.kind === "Loop" ? {
movementPattern: heyStep.kind === "StandStill" ? {
kind: SemanticAnimationKind.StandStill,
} : heyStep.kind === "Loop" ? {
// TODO Loop should probably be its own kind? Or RotateAround?
kind: SemanticAnimationKind.Linear,
minRotation: endsShoulder === Hand.Right ? +180 : -180,
} : {
kind: SemanticAnimationKind.PassBy,
around: heyStep.kind === "CenterPass" ? "Center" : heyStep.endPosition.which.leftRightSide(),
@ -1446,31 +1456,73 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
heyStep,
};
}
function continueHey(prevStep: HeyStep, isLast: boolean): HeyStep {
function continueHey(prevStep: HeyStep, stepsLeft: number): HeyStep {
// Continuing hey so everyone is either passing (in center or on ends) or looping on ends.
if (prevStep.endPosition.kind === PositionKind.Circle) {
// Hasn't started hey yet, passing on ends to enter hey.
return {
kind: "EndsPass",
endPosition: {
kind: PositionKind.ShortLines,
which: prevStep.endPosition.which.isLeft() ? ShortLinesPosition.MiddleLeft : ShortLinesPosition.MiddleRight,
facing: prevStep.endPosition.which.facingAcross(),
setOffset: prevStep.endPosition.setOffset,
lineOffset: prevStep.endPosition.lineOffset,
},
if (prevStep.endPosition.facing === prevStep.endPosition.which.facingAcross()) {
if (stepsLeft === 0) {
return {
kind: "StandStill",
endPosition: prevStep.endPosition,
}
}
return {
kind: "EndsPassIn",
endPosition: {
kind: PositionKind.ShortLines,
which: prevStep.endPosition.which.isLeft() ? ShortLinesPosition.MiddleLeft : ShortLinesPosition.MiddleRight,
facing: prevStep.endPosition.which.facingAcross(),
setOffset: prevStep.endPosition.setOffset,
lineOffset: prevStep.endPosition.lineOffset,
},
}
}
else {
if (stepsLeft === 1 && !endsInCircle) {
return {
kind: "Loop",
endPosition: {
kind: PositionKind.ShortLines,
which: prevStep.endPosition.which.isLeft() ? ShortLinesPosition.FarLeft : ShortLinesPosition.FarRight,
facing: prevStep.endPosition.which.facingAcross(),
setOffset: prevStep.endPosition.setOffset,
lineOffset: prevStep.endPosition.lineOffset,
},
}
}
return {
kind: "Loop",
endPosition: {
...prevStep.endPosition,
which: prevStep.endPosition.which.swapUpAndDown(),
facing: prevStep.endPosition.which.facingAcross()
},
}
}
}
else if (prevStep.endPosition.kind === PositionKind.ShortLines) {
const isFacingSide = prevStep.endPosition.facing === prevStep.endPosition.which.facingSide();
if (!prevStep.endPosition.which.isMiddle() && !isFacingSide) {
const inMiddle = prevStep.endPosition.which.isMiddle();
if (!inMiddle && !isFacingSide) {
return {
kind: "Loop",
endPosition: { ...prevStep.endPosition, facing: prevStep.endPosition.which.facingSide() },
}
} else {
} else if (inMiddle && isFacingSide) {
return {
kind: isFacingSide ? "EndsPass" : "CenterPass",
kind: "EndsPassOut",
endPosition: {
...prevStep.endPosition,
kind: PositionKind.Circle,
which: prevStep.endPosition.which.isLeft()
? (endsShoulder === Hand.Right ? CirclePosition.TopLeft : CirclePosition.BottomLeft)
: (endsShoulder === Hand.Right ? CirclePosition.BottomRight : CirclePosition.TopRight),
},
}
}
else {
return {
kind: isFacingSide ? (inMiddle ? "EndsPassOut" : "EndsPassIn") : "CenterPass",
endPosition: {
...prevStep.endPosition,
which: isFacingSide ? prevStep.endPosition.which.swapOnSide() : prevStep.endPosition.which.swapSides()
@ -1485,18 +1537,49 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
let firstHeyStep: HeyStep;
let startingPos: SemanticPosition;
if (firstPassInCenter) {
if (startPos.kind !== PositionKind.Circle) {
throw new Error("Hey starting in center not from circle is unsupported.");
}
const inCenterFirst = findPairOpposite(move.parameters.who, id) !== null;
// TODO This is probably the most common kind of hey, definitely top priority.
throw new Error("Hey starting passing in center is unsupported.");
startingPos = {
kind: startPos.kind,
which: startPos.which,
facing: startPos.which.isLeft() ? Facing.Right : Facing.Left,
setOffset: startPos.setOffset,
lineOffset: startPos.lineOffset,
};
if (inCenterFirst) {
firstHeyStep = {
kind: "CenterPass",
endPosition: {
kind: PositionKind.ShortLines,
which: startPos.which.isLeft() ? ShortLinesPosition.MiddleRight : ShortLinesPosition.MiddleLeft,
facing: startingPos.facing,
setOffset: startPos.setOffset,
lineOffset: startPos.lineOffset,
}
};
} else {
firstHeyStep = {
kind: "StandStill",
endPosition: startingPos,
}
}
} else {
if (startPos.kind !== PositionKind.ShortLines) {
throw new Error("Hey with first pass on ends must start approximately in short lines.");
}
const startFacing = startPos.which.facingSide();
startingPos = { ...startPos, facing: startFacing, hands: undefined };
startingPos = {
kind: startPos.kind,
which: startPos.which,
facing: startFacing,
setOffset: startPos.setOffset,
lineOffset: startPos.lineOffset,
};
firstHeyStep = {
kind: "EndsPass",
kind: startingPos.which.isMiddle() ? "EndsPassOut" : "EndsPassIn",
endPosition: { ...startingPos, which: startPos.which.swapOnSide() },
}
}
@ -1504,7 +1587,7 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
const heySteps: HeyStep[] = [firstHeyStep];
for(let i = 1; i < heyParts; i++) {
const isLast = i === heyParts - 1;
const nextHeyStep = continueHey(heySteps[i - 1], isLast);
const nextHeyStep = continueHey(heySteps[i - 1], heyParts - i - 1);
heySteps.push(nextHeyStep);
}
return combine(heySteps.map(heyStepToPartialLowLevelMove), { ...startingPos, hands: undefined });

View File

@ -92,6 +92,7 @@ updateCanvasSettings({});
const bpmSelector = document.createElement('input');
bpmSelector.type = 'number';
bpmSelector.value = '180';
bpmSelector.step = '20';
bpmSelector.id = 'bpm';
bpmSelector.style.width = '4em';
const bpmLabel = document.createElement('label');