Compare commits

...

2 Commits

4 changed files with 87 additions and 63 deletions

View File

@ -89,7 +89,7 @@ export class LinearAnimationSegment extends AnimationSegment {
export interface AnimationTransitionFlags { export interface AnimationTransitionFlags {
rotation?: boolean; rotation?: boolean;
hands?: boolean; hands?: boolean;
handsDuring?: "Actual" | "None" | "Start" | "End"; handsDuring?: "Actual" | "None" | "Start" | "End" | Map<Hand, Offset>;
} }
export class TransitionAnimationSegment extends AnimationSegment { export class TransitionAnimationSegment extends AnimationSegment {
private readonly actualAnimation: AnimationSegment; private readonly actualAnimation: AnimationSegment;
@ -122,27 +122,29 @@ export class TransitionAnimationSegment extends AnimationSegment {
const transitionEnd = this.actualAnimation.interpolateRotation(1 - this.endTransitionProgress); const transitionEnd = this.actualAnimation.interpolateRotation(1 - this.endTransitionProgress);
if (actualEnd > actualStart) { if (actualEnd > actualStart) {
while (transitionStart < this.startRotation) { while (transitionStart <= this.startRotation - 180) {
this.startRotation -= 360; this.startRotation -= 360;
} }
while (transitionEnd > this.endRotation) { while (transitionEnd >= this.endRotation + 180) {
this.endRotation += 360; this.endRotation += 360;
} }
} else if (actualEnd < actualStart) { } else if (actualEnd < actualStart) {
while (transitionStart > this.startRotation) { while (transitionStart >= this.startRotation + 180) {
this.startRotation += 360; this.startRotation += 360;
} }
while (transitionEnd < this.endRotation) { while (transitionEnd <= this.endRotation - 180) {
this.endRotation -= 360; this.endRotation -= 360;
} }
} else { }
while (transitionStart - this.startRotation < 180) {
// Transitions should be short adjustments, not spins.
while (transitionStart - this.startRotation < -180) {
this.startRotation -= 360; this.startRotation -= 360;
} }
while (transitionStart - this.startRotation > 180) { while (transitionStart - this.startRotation > 180) {
this.startRotation += 360; this.startRotation += 360;
} }
while (transitionEnd - this.endRotation < 180) { while (transitionEnd - this.endRotation < -180) {
this.endRotation -= 360; this.endRotation -= 360;
} }
while (transitionEnd - this.endRotation > 180) { while (transitionEnd - this.endRotation > 180) {
@ -150,7 +152,6 @@ export class TransitionAnimationSegment extends AnimationSegment {
} }
} }
} }
}
override interpolateOffset(progress: number): Offset { override interpolateOffset(progress: number): Offset {
return this.actualAnimation.interpolateOffset(progress); return this.actualAnimation.interpolateOffset(progress);
@ -185,6 +186,8 @@ export class TransitionAnimationSegment extends AnimationSegment {
? startHand ? startHand
: this.flags.handsDuring === "End" : this.flags.handsDuring === "End"
? endHand ? endHand
: this.flags.handsDuring instanceof Map
? this.flags.handsDuring.get(hand)
: (() => { throw "Unexpected handsDuring: " + this.flags.handsDuring; })(); : (() => { throw "Unexpected handsDuring: " + this.flags.handsDuring; })();
if (this.flags.hands) { if (this.flags.hands) {
@ -238,8 +241,9 @@ export class RotationAnimationSegment extends AnimationSegment {
private readonly startFacing: Rotation; private readonly startFacing: Rotation;
private readonly closer?: Closer; private readonly closer?: Closer;
private readonly hands: Map<Hand, HandAnimation>; private readonly hands: Map<Hand, HandAnimation>;
private readonly centerRelativeTo: number;
constructor({ beats, startPosition, endPosition, rotation, around, facing, closer, hands }: { constructor({ beats, startPosition, endPosition, rotation, around, facing, closer, hands, centerRelativeTo }: {
beats: number; beats: number;
startPosition: DancerSetPosition; startPosition: DancerSetPosition;
endPosition: DancerSetPosition; endPosition: DancerSetPosition;
@ -248,6 +252,7 @@ export class RotationAnimationSegment extends AnimationSegment {
facing: RotationAnimationFacing; facing: RotationAnimationFacing;
closer?: CloserDuringRotation; closer?: CloserDuringRotation;
hands?: Map<Hand, HandAnimation>; hands?: Map<Hand, HandAnimation>;
centerRelativeTo?: number;
}) { }) {
super(beats, startPosition, endPosition); super(beats, startPosition, endPosition);
@ -268,6 +273,7 @@ export class RotationAnimationSegment extends AnimationSegment {
} }
this.startRotation = positionToDegrees(startPosition.position); this.startRotation = positionToDegrees(startPosition.position);
this.startFacing = startPosition.rotation; this.startFacing = startPosition.rotation;
this.centerRelativeTo = centerRelativeTo ?? this.startFacing;
const actualRotation = normalizeRotation(positionToDegrees(endPosition.position) - this.startRotation, const actualRotation = normalizeRotation(positionToDegrees(endPosition.position) - this.startRotation,
rotation); rotation);
this.endRotation = this.startRotation + actualRotation; this.endRotation = this.startRotation + actualRotation;
@ -311,14 +317,13 @@ export class RotationAnimationSegment extends AnimationSegment {
return super.interpolateRotation(progress); return super.interpolateRotation(progress);
} else { } else {
const degrees = interpolateLinear(progress, this.startRotation, this.endRotation); const degrees = interpolateLinear(progress, this.startRotation, this.endRotation);
let rotation : number;
switch (this.facing) { switch (this.facing) {
case RotationAnimationFacing.Start: case RotationAnimationFacing.Start:
return this.startFacing; return this.startFacing;
case RotationAnimationFacing.Center: case RotationAnimationFacing.Center:
return degrees - 90; return degrees - 90;
case RotationAnimationFacing.CenterRelative: case RotationAnimationFacing.CenterRelative:
return degrees - this.startRotation + this.startFacing; return degrees - this.startRotation + this.centerRelativeTo;
case RotationAnimationFacing.Forward: case RotationAnimationFacing.Forward:
return degrees + 180; return degrees + 180;
case RotationAnimationFacing.Backward: case RotationAnimationFacing.Backward:

View File

@ -697,7 +697,7 @@ function moveAsLowLevelMoves({ move, nextMove, startingPos, numProgessions }: {
return combine([ return combine([
prevEnd => ({ prevEnd => ({
beats: meltdownBeats, beats: meltdownBeats,
endPosition: prevEnd, endPosition: {...prevEnd, dancerDistance: DancerDistance.Compact },
movementPattern: { movementPattern: {
kind: SemanticAnimationKind.RotateAround, kind: SemanticAnimationKind.RotateAround,
minAmount: 360, minAmount: 360,

View File

@ -324,5 +324,5 @@ export type SemanticPosition = {
facing: Facing, facing: Facing,
hands?: Map<Hand, HandConnection>, hands?: Map<Hand, HandConnection>,
balance?: BalanceWeight, balance?: BalanceWeight,
dancerDistance?: DancerDistance.Normal | DancerDistance.SwingLark | DancerDistance.SwingRobin, dancerDistance?: DancerDistance,
}; };

View File

@ -170,6 +170,30 @@ function CenterOf(sideOrCenter: CircleSideOrCenter, setOffset?: number, lineOffs
return { x: setCenter.x + xOffset, y: setCenter.y + yOffset }; return { x: setCenter.x + xOffset, y: setCenter.y + yOffset };
} }
function swingHandPosition(role: DancerDistance.SwingLark | DancerDistance.SwingRobin, hand: Hand): Offset {
if (role === DancerDistance.SwingLark) {
if (hand === Hand.Left) {
return { x: 0, y: Math.sqrt(1 / 2) };
}
else {
return { x: 0.8, y: 0.5 };
}
} else /* role === DancerDistance.SwingRobin */ {
if (hand === Hand.Left) {
return { x: -0.8, y: 0.5 };
}
else {
return { x: 0, y: Math.sqrt(1 / 2) };
};
}
}
function swingHandPositions(role: DancerDistance.SwingLark | DancerDistance.SwingRobin): Map<Hand, Offset> {
return new Map<Hand, Offset>([
[Hand.Left, swingHandPosition(role, Hand.Left)],
[Hand.Right, swingHandPosition(role, Hand.Right)],
]);
}
function SemanticToSetPosition(semantic: SemanticPosition): DancerSetPosition { function SemanticToSetPosition(semantic: SemanticPosition): DancerSetPosition {
let rotation: number; let rotation: number;
@ -211,8 +235,6 @@ function SemanticToSetPosition(semantic: SemanticPosition): DancerSetPosition {
yAmount = 1; yAmount = 1;
break; break;
case DancerDistance.Compact: case DancerDistance.Compact:
yAmount = 0.75;
break;
case DancerDistance.SwingLark: case DancerDistance.SwingLark:
case DancerDistance.SwingRobin: case DancerDistance.SwingRobin:
yAmount = 0.5; yAmount = 0.5;
@ -286,8 +308,8 @@ function SemanticToSetPosition(semantic: SemanticPosition): DancerSetPosition {
position = OffsetPlus(position, balanceOffset, setOffset); position = OffsetPlus(position, balanceOffset, setOffset);
const isFacingUpOrDown = semantic.facing === Facing.Up || semantic.facing === Facing.Down; const isFacingUpOrDown = semantic.facing === Facing.Up || semantic.facing === Facing.Down;
if (semantic.dancerDistance === DancerDistance.SwingLark) { if (semantic.dancerDistance === DancerDistance.SwingLark || semantic.dancerDistance == DancerDistance.SwingRobin) {
if (isFacingUpOrDown) { if (isFacingUpOrDown == (semantic.dancerDistance === DancerDistance.SwingLark)) {
rotation -= 45; rotation -= 45;
} else { } else {
rotation += 45; rotation += 45;
@ -296,21 +318,8 @@ function SemanticToSetPosition(semantic: SemanticPosition): DancerSetPosition {
return { return {
position, position,
rotation, rotation,
leftArmEnd: { x: 0, y: Math.sqrt(1/2)}, leftArmEnd: swingHandPosition(semantic.dancerDistance, Hand.Left),
rightArmEnd: { x: 0.8, y: 0.5 }, rightArmEnd: swingHandPosition(semantic.dancerDistance, Hand.Right),
};
} else if (semantic.dancerDistance === DancerDistance.SwingRobin) {
if (isFacingUpOrDown) {
rotation += 45;
} else {
rotation -= 45;
}
return {
position,
rotation,
leftArmEnd: { x: -0.8, y: 0.5 },
rightArmEnd: { x: 0, y: Math.sqrt(1/2) },
}; };
} }
@ -325,10 +334,11 @@ function SemanticToSetPosition(semantic: SemanticPosition): DancerSetPosition {
case HandTo.DancerRight: case HandTo.DancerRight:
return OffsetPlus({ x: +1, y: 0 }, balanceHandAdjustment); return OffsetPlus({ x: +1, y: 0 }, balanceHandAdjustment);
case HandTo.DancerForward: case HandTo.DancerForward:
const armLength = yAmount + (semantic.balance === BalanceWeight.Backward ? balanceAmount : 0);
if (hand === connection.hand) { if (hand === connection.hand) {
return { x: 0, y: +0.5 }; return { x: 0, y: +armLength/2 };
} else { } else {
return { x: dancerWidth / 2 * (hand === Hand.Left ? -1 : +1), y: +1 }; return { x: dancerWidth / 2 * (hand === Hand.Left ? -1 : +1), y: +armLength };
} }
case HandTo.LeftInCircle: case HandTo.LeftInCircle:
case HandTo.RightInCircle: case HandTo.RightInCircle:
@ -572,13 +582,13 @@ export function animateLowLevelMove(move: LowLevelMove): animation.AnimationSegm
rotation: move.movementPattern.minAmount, rotation: move.movementPattern.minAmount,
around: { around: {
center: rotateCenter, center: rotateCenter,
width: setWidth / 5, width: 1,
height: setHeight / 5, height: 1,
}, },
facing: animation.RotationAnimationFacing.Center, facing: animation.RotationAnimationFacing.Forward,
closer: move.movementPattern.close ? { closer: move.movementPattern.close ? {
transitionBeats: 1, transitionBeats: 1,
minDistance: setWidth, minDistance: 1,
} : undefined, } : undefined,
hands hands
}), }),
@ -611,22 +621,31 @@ export function animateLowLevelMove(move: LowLevelMove): animation.AnimationSegm
}); });
return [ return [
new animation.LinearAnimationSegment({ new animation.TransitionAnimationSegment({
beats: 1, actualAnimation: new animation.RotationAnimationSegment({
beats: move.beats - 2,
startPosition: startSetPosition, startPosition: startSetPosition,
endPosition: swingStart,
}),
new animation.RotationAnimationSegment({
beats: move.beats - 3,
startPosition: swingStart,
endPosition: beforeUnfold, endPosition: beforeUnfold,
rotation: move.movementPattern.minAmount, rotation: move.movementPattern.minAmount,
around: { around: {
center: rotateSwingCenter, center: rotateSwingCenter,
width: setWidth / 5, width: 1,
height: setHeight / 5, height: 1,
}, },
facing: animation.RotationAnimationFacing.CenterRelative closer: {
minDistance: 1,
transitionBeats: 1,
},
facing: animation.RotationAnimationFacing.CenterRelative,
centerRelativeTo: startSetPosition.rotation + ((move.startPosition.facing === Facing.Up || move.startPosition.facing === Facing.Down) === (dancerDistance === DancerDistance.SwingLark) ? -45 : +45)
}),
flags: {
rotation: true,
hands: true,
handsDuring: swingHandPositions(dancerDistance),
},
startTransitionBeats: 1,
endTransitionBeats: 0,
}), }),
new animation.LinearAnimationSegment({ new animation.LinearAnimationSegment({
beats: 1, beats: 1,