mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-21 07:55:55 +00:00
Timeline animation clips (#122)
This is a super initial version of animation clips in timeline. https://github.com/storytold/storyteller-bevy/assets/10376144/b649162b-8758-4662-bfb9-6a492563b9f7 https://github.com/storytold/storyteller-bevy/assets/10376144/a5815685-bf52-4413-8828-d86051bf850a --------- Co-authored-by: Danny McGee <dannymcgee@gmail.com>
This commit is contained in:
@@ -149,7 +149,8 @@ export class AnimEditorElement extends LitElement
|
||||
let min = Infinity
|
||||
let max = -Infinity;
|
||||
for (const keyframe of Object.keys(this.keyframes)) {
|
||||
let time = this.keyframes[keyframe].time;
|
||||
const current = this.keyframes[keyframe];
|
||||
let time = current.time;
|
||||
if (typeof time != "number") {
|
||||
continue;
|
||||
}
|
||||
@@ -159,6 +160,12 @@ export class AnimEditorElement extends LitElement
|
||||
if (time < min) {
|
||||
min = time;
|
||||
}
|
||||
if ("duration" in current) {
|
||||
const end_time = time + current.duration;
|
||||
if (end_time > max) {
|
||||
max = end_time
|
||||
}
|
||||
}
|
||||
}
|
||||
this.clipStart = Math.max(min, 0.);
|
||||
this.clipEnd = Math.max(max, min);
|
||||
@@ -210,13 +217,20 @@ export class AnimEditorElement extends LitElement
|
||||
let closest_keyframe = -1 * Infinity;
|
||||
|
||||
for (const keyframe of Object.keys(this.keyframes)) {
|
||||
const time = this.keyframes[keyframe]?.time;
|
||||
const current = this.keyframes[keyframe];
|
||||
const time = current?.time;
|
||||
if (!time || typeof time != "number") {
|
||||
continue;
|
||||
}
|
||||
if (time < pos && time > closest_keyframe) {
|
||||
closest_keyframe = time;
|
||||
}
|
||||
if ("duration" in current) {
|
||||
const end_time = time + current.duration;
|
||||
if (end_time < pos && end_time > closest_keyframe) {
|
||||
closest_keyframe = end_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closest_keyframe < 0) {
|
||||
@@ -233,13 +247,20 @@ export class AnimEditorElement extends LitElement
|
||||
let closest_keyframe = Infinity;
|
||||
|
||||
for (const keyframe of Object.keys(this.keyframes)) {
|
||||
const time = this.keyframes[keyframe]?.time;
|
||||
const current = this.keyframes[keyframe];
|
||||
const time = current?.time;
|
||||
if (!time || typeof time != "number") {
|
||||
continue;
|
||||
}
|
||||
if (time > pos && time < closest_keyframe) {
|
||||
closest_keyframe = time;
|
||||
}
|
||||
if ("duration" in current) {
|
||||
const end_time = time + current.duration;
|
||||
if (end_time > pos && end_time < closest_keyframe) {
|
||||
closest_keyframe = end_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closest_keyframe > this.clipEnd) {
|
||||
|
||||
@@ -136,3 +136,27 @@
|
||||
background: #0FF; // TODO
|
||||
}
|
||||
}
|
||||
|
||||
.clip {
|
||||
position: absolute;
|
||||
transform: translateX(-4.5px);
|
||||
--clip-name: "";
|
||||
height: 12px;
|
||||
|
||||
&::before {
|
||||
content: var(--clip-name);
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 12px;
|
||||
background: #AAA;
|
||||
color: black;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.selected::before {
|
||||
background: #0FF; // TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,23 +406,50 @@ export class AnimTimelineElement extends LitElement {
|
||||
([id]) => id,
|
||||
([id, keyframe]) => {
|
||||
let row = this.track_animation_target_ordered[keyframe.target];
|
||||
return html`
|
||||
<div id=${id}
|
||||
class=${classMap({
|
||||
keyframe: true,
|
||||
selected: this._selectedKeyframe === id
|
||||
})}
|
||||
style=${styleMap({
|
||||
left: `${100 * (keyframe.time - this.rangeStart) / range}%`,
|
||||
gridRow: row + 2,
|
||||
})}
|
||||
tabindex="-1"
|
||||
${drag({
|
||||
move: event => this.onKeyframeDrag(id, event),
|
||||
})}
|
||||
@click=${() => this.selectKeyframe(id)}
|
||||
></div>
|
||||
`;
|
||||
if ("clip" in keyframe) {
|
||||
let clip = keyframe.clip;
|
||||
let duration = keyframe.duration;
|
||||
let time = keyframe.time;
|
||||
|
||||
return html`
|
||||
<div id=${id}
|
||||
class=${classMap({
|
||||
clip: true,
|
||||
selected: this._selectedKeyframe === id
|
||||
})}
|
||||
style=${styleMap({
|
||||
left: `${100 * (time - this.rangeStart) / range}%`,
|
||||
right: `${100 * (this.rangeEnd - (time + duration)) / range}%`,
|
||||
gridRow: row + 2,
|
||||
'--clip-name': `"${clip}"`,
|
||||
})}
|
||||
tabindex="-1"
|
||||
${drag({
|
||||
move: event => this.onKeyframeDrag(id, event),
|
||||
})}
|
||||
@click=${() => this.selectKeyframe(id)}
|
||||
>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
return html`
|
||||
<div id=${id}
|
||||
class=${classMap({
|
||||
keyframe: true,
|
||||
selected: this._selectedKeyframe === id
|
||||
})}
|
||||
style=${styleMap({
|
||||
left: `${100 * (keyframe.time - this.rangeStart) / range}%`,
|
||||
gridRow: row + 2,
|
||||
})}
|
||||
tabindex="-1"
|
||||
${drag({
|
||||
move: event => this.onKeyframeDrag(id, event),
|
||||
})}
|
||||
@click=${() => this.selectKeyframe(id)}
|
||||
></div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,12 @@ $hierarchy-width: 290px;
|
||||
--timeline-height: max-content;
|
||||
}
|
||||
|
||||
.debug-mode {
|
||||
.studio-scene {
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
||||
@@ -56,6 +56,8 @@ export class AppElement extends LitElement {
|
||||
@state() resizingPanel = false;
|
||||
@state() inspectorWidth = 320;
|
||||
|
||||
@state() debugMode = false;
|
||||
|
||||
@state() sidebars: Array<{ title: string, name: string}> = [{title: 'Hierarchy', name: 'hierarchy'}];
|
||||
|
||||
@state() currentSidebar : string = 'hierarchy';
|
||||
@@ -103,6 +105,11 @@ export class AppElement extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
@on("window:debug-mode-toggled")
|
||||
onDebugModeToggled({detail: { debugModeActive }}: studio.DebugModeToggled ): void {
|
||||
this.debugMode = debugModeActive;
|
||||
}
|
||||
|
||||
onPanelResizeStart(): void {
|
||||
this.resizingPanel = true;
|
||||
}
|
||||
@@ -133,7 +140,7 @@ export class AppElement extends LitElement {
|
||||
|
||||
protected override render() {
|
||||
return html`
|
||||
<sts-canvas-provider class="app-root">
|
||||
<sts-canvas-provider class=${classMap({"app-root": true, "debug-mode": this.debugMode})}>
|
||||
<sts-scene-data-provider>
|
||||
<sts-overlay-provider>
|
||||
<sts-iframe-messaging-bridge></sts-iframe-messaging-bridge>
|
||||
|
||||
Reference in New Issue
Block a user