mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-03-19 17:01:55 +08:00
Keyframe data points interface
This commit is contained in:
parent
4e0efa61f1
commit
2ab233434f
@ -497,14 +497,40 @@
|
||||
height: 30px;
|
||||
width: 25%;
|
||||
}
|
||||
#keyframe_type_label {
|
||||
display: flex;
|
||||
padding: 4px 8px;
|
||||
height: 30px;
|
||||
}
|
||||
#keyframe_type_label label {
|
||||
flex: 1 0 40px;
|
||||
}
|
||||
.keyframe_data_point_header {
|
||||
display: flex;
|
||||
padding: 2px 8px;
|
||||
height: 26px;
|
||||
}
|
||||
.keyframe_data_point_header label {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.flex_fill_line {
|
||||
flex: 1 0 0;
|
||||
border-bottom: 2px solid var(--color-text);
|
||||
height: 0;
|
||||
margin: 0 10px;
|
||||
margin-top: 11px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.panel#keyframe .bar.flex {
|
||||
height: auto;
|
||||
min-height: 30px;
|
||||
}
|
||||
.panel .bar.flex label {
|
||||
margin: 3px 8px;
|
||||
min-width: 20px;
|
||||
text-align: center;
|
||||
.panel#keyframe .bar.flex label {
|
||||
padding: 3px 10px;
|
||||
min-width: 20px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--color-button);
|
||||
}
|
||||
.panel#keyframe .bar input.dark_bordered {
|
||||
width: 100%;
|
||||
@ -521,8 +547,10 @@
|
||||
}
|
||||
.molang_input pre {
|
||||
padding: 2px;
|
||||
height: 100%;
|
||||
min-height: 28px;
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
cursor: default;
|
||||
}
|
||||
.molang_input pre code {
|
||||
|
@ -1237,12 +1237,12 @@ const Animator = {
|
||||
animation.animators.effects = new EffectAnimator(animation);
|
||||
}
|
||||
for (var timestamp in a.sound_effects) {
|
||||
var sound = a.sound_effects[timestamp];
|
||||
if (sound instanceof Array) sound = sound[0];
|
||||
var sounds = a.sound_effects[timestamp];
|
||||
if (sounds instanceof Array === false) sounds = [sounds];
|
||||
animation.animators.effects.addKeyframe({
|
||||
channel: 'sound',
|
||||
time: parseFloat(timestamp),
|
||||
effect: sound.effect,
|
||||
data_points: sounds
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1251,14 +1251,15 @@ const Animator = {
|
||||
animation.animators.effects = new EffectAnimator(animation);
|
||||
}
|
||||
for (var timestamp in a.particle_effects) {
|
||||
var particle = a.particle_effects[timestamp];
|
||||
if (particle instanceof Array) particle = particle[0];
|
||||
var particles = a.particle_effects[timestamp];
|
||||
if (particles instanceof Array === false) particles = [particles];
|
||||
particles.forEach(particle => {
|
||||
if (particle) particle.script = particle.pre_effect_script;
|
||||
})
|
||||
animation.animators.effects.addKeyframe({
|
||||
channel: 'particle',
|
||||
time: parseFloat(timestamp),
|
||||
effect: particle.effect,
|
||||
locator: particle.locator,
|
||||
script: particle.pre_effect_script,
|
||||
data_points: particles
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1272,7 +1273,7 @@ const Animator = {
|
||||
animation.animators.effects.addKeyframe({
|
||||
channel: 'timeline',
|
||||
time: parseFloat(timestamp),
|
||||
instructions
|
||||
data_points: [{instructions}]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,27 @@ class KeyframeDataPoint {
|
||||
case 'timeline': this.instructions = ''; break;
|
||||
}
|
||||
}
|
||||
extend(data) {
|
||||
if (data.values) {
|
||||
data.x = data.values.x;
|
||||
data.y = data.values.y;
|
||||
data.z = data.values.z;
|
||||
data.effect = data.values.effect;
|
||||
data.locator = data.values.locator;
|
||||
data.script = data.values.script;
|
||||
data.file = data.values.file;
|
||||
data.instructions = data.values.instructions;
|
||||
}
|
||||
if (this.x != undefined) Merge.string(this, data, 'x')
|
||||
if (this.y != undefined) Merge.string(this, data, 'y')
|
||||
if (this.z != undefined) Merge.string(this, data, 'z')
|
||||
if (this.effect != undefined) Merge.string(this, data, 'effect')
|
||||
if (this.locator != undefined) Merge.string(this, data, 'locator')
|
||||
if (this.script != undefined) Merge.string(this, data, 'script')
|
||||
if (this.file != undefined) Merge.string(this, data, 'file')
|
||||
if (this.instructions != undefined) Merge.string(this, data, 'instructions')
|
||||
}
|
||||
get x_string() {
|
||||
console.log(this.x)
|
||||
return typeof this.x == 'number' ? trimFloatNumber(this.x) : this.x;
|
||||
}
|
||||
set x_string(val) {
|
||||
@ -46,7 +65,6 @@ class Keyframe {
|
||||
this.transform = this.channel === 'rotation' || this.channel === 'position' || this.channel === 'scale';
|
||||
this.data_points.push(new KeyframeDataPoint(this));
|
||||
this.extend(data)
|
||||
console.log(data, this.get('x'))
|
||||
}
|
||||
}
|
||||
extend(data) {
|
||||
@ -60,36 +78,7 @@ class Keyframe {
|
||||
this.data_points.push(new KeyframeDataPoint(this));
|
||||
}
|
||||
let this_point = this.data_points[i];
|
||||
if (this.transform) {
|
||||
/*
|
||||
if (point.values != undefined) {
|
||||
if (typeof point.values == 'number' || typeof point.values == 'string') {
|
||||
point.x = point.y = point.z = point.values;
|
||||
|
||||
} else if (point.values instanceof Array) {
|
||||
point.x = point.values[0];
|
||||
point.y = point.values[1];
|
||||
point.z = point.values[2];
|
||||
point.w = point.values[3];
|
||||
}
|
||||
}*/
|
||||
Merge.string(this_point, point, 'x')
|
||||
Merge.string(this_point, point, 'y')
|
||||
Merge.string(this_point, point, 'z')
|
||||
} else {
|
||||
if (data.values) {
|
||||
data.effect = data.values.effect;
|
||||
data.locator = data.values.locator;
|
||||
data.script = data.values.script;
|
||||
data.file = data.values.file;
|
||||
data.instructions = data.values.instructions;
|
||||
}
|
||||
Merge.string(this_point, data, 'effect')
|
||||
Merge.string(this_point, data, 'locator')
|
||||
Merge.string(this_point, data, 'script')
|
||||
Merge.string(this_point, data, 'file')
|
||||
Merge.string(this_point, data, 'instructions')
|
||||
}
|
||||
this_point.extend(point)
|
||||
})
|
||||
}
|
||||
return this;
|
||||
@ -712,6 +701,27 @@ Interface.definePanels(function() {
|
||||
list.push(tl(`cube.color.${markerColors[this.keyframes[0].color].name}`))
|
||||
}*/
|
||||
return list.join(', ')
|
||||
},
|
||||
addDataPoint() {
|
||||
Undo.initEdit({keyframes: Timeline.selected})
|
||||
Timeline.selected.forEach(kf => {
|
||||
if ((kf.transform && kf.data_points.length <= 1) || kf.channel == 'particle' || kf.channel == 'sound') {
|
||||
kf.data_points.push(new KeyframeDataPoint(kf))
|
||||
kf.data_points.last().extend(kf.data_points[0])
|
||||
}
|
||||
})
|
||||
Animator.preview()
|
||||
Undo.finishEdit('add keyframe data point')
|
||||
},
|
||||
removeDataPoint(data_point) {
|
||||
Undo.initEdit({keyframes: Timeline.selected})
|
||||
Timeline.selected.forEach(kf => {
|
||||
if (kf.data_points.length >= 2) {
|
||||
kf.data_points.splice(data_point, 1);
|
||||
}
|
||||
})
|
||||
Animator.preview()
|
||||
Undo.finishEdit('remove keyframe data point')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -734,9 +744,27 @@ Interface.definePanels(function() {
|
||||
|
||||
<template v-if="channel != false">
|
||||
|
||||
<p id="keyframe_type_label">{{ tl('panel.keyframe.type', [getKeyframeInfos()]) }}</p>
|
||||
<div id="keyframe_type_label">
|
||||
<label>{{ tl('panel.keyframe.type', [getKeyframeInfos()]) }}</label>
|
||||
<div
|
||||
class="in_list_button"
|
||||
v-if="(keyframes[0].transform && keyframes[0].data_points.length <= 1) || channel == 'particle' || channel == 'sound'"
|
||||
v-on:click.stop="addDataPoint()"
|
||||
title="${ tl('panel.keyframe.add_data_point') }"
|
||||
>
|
||||
<i class="material-icons">add</i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-for="(data_point, data_point_i) of keyframes[0].data_points">
|
||||
<div v-for="(data_point, data_point_i) of keyframes[0].data_points" class="keyframe_data_point">
|
||||
|
||||
<div class="keyframe_data_point_header" v-if="keyframes[0].data_points.length > 1">
|
||||
<label>{{ keyframes[0].transform ? tl('panel.keyframe.' + (data_point_i ? 'post' : 'pre')) : (data_point_i + 1) }}</label>
|
||||
<div class="flex_fill_line"></div>
|
||||
<div class="in_list_button" v-on:click.stop="removeDataPoint(data_point)" title="${ tl('panel.keyframe.remove_data_point') }">
|
||||
<i class="material-icons">clear</i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bar flex" id="keyframe_bar_x" v-if="keyframes[0].animator instanceof BoneAnimator">
|
||||
<label class="color_x" style="font-weight: bolder">X</label>
|
||||
@ -752,20 +780,20 @@ Interface.definePanels(function() {
|
||||
</div>
|
||||
|
||||
<div class="bar flex" id="keyframe_bar_effect" v-if="channel == 'particle' || channel == 'sound'">
|
||||
<label>{{ tl('data.effect') }}</label>
|
||||
<input type="text" class="dark_bordered code keyframe_input tab_target" v-model="data_point.effect" @input="updateInput('effect', $event)">
|
||||
<label>${ tl('data.effect') }</label>
|
||||
<input type="text" class="dark_bordered code keyframe_input tab_target" v-model="data_point.effect" @input="updateInput('effect', $event.target.value, data_point_i)">
|
||||
</div>
|
||||
<div class="bar flex" id="keyframe_bar_locator" v-if="channel == 'particle'">
|
||||
<label>{{ tl('data.locator') }}</label>
|
||||
<input @focus="focus()" @focusout="focusout()" type="text" class="dark_bordered code keyframe_input tab_target" v-model="data_point.locator" @input="updateInput('locator', $event)">
|
||||
<label>${ tl('data.locator') }</label>
|
||||
<input @focus="focus()" @focusout="focusout()" type="text" class="dark_bordered code keyframe_input tab_target" v-model="data_point.locator" @input="updateInput('locator', $event.target.value, data_point_i)">
|
||||
</div>
|
||||
<div class="bar flex" id="keyframe_bar_script" v-if="channel == 'particle'">
|
||||
<label>{{ tl('timeline.pre_effect_script') }}</label>
|
||||
<vue-prism-editor class="molang_input dark_bordered keyframe_input tab_target" v-model="data_point.script" @change="updateInput('script', $event)" language="molang" :line-numbers="false" />
|
||||
<label>${ tl('timeline.pre_effect_script') }</label>
|
||||
<vue-prism-editor class="molang_input dark_bordered keyframe_input tab_target" v-model="data_point.script" @change="updateInput('script', $event, data_point_i)" language="molang" :line-numbers="false" />
|
||||
</div>
|
||||
<div class="bar" id="keyframe_bar_instructions" v-if="channel == 'timeline'">
|
||||
<label>{{ tl('timeline.timeline') }}</label>
|
||||
<vue-prism-editor class="molang_input dark_bordered keyframe_input tab_target" v-model="data_point.instructions" @change="updateInput('instructions', $event)" language="molang" :line-numbers="false" />
|
||||
<label>${ tl('timeline.timeline') }</label>
|
||||
<vue-prism-editor class="molang_input dark_bordered keyframe_input tab_target" v-model="data_point.instructions" @change="updateInput('instructions', $event, data_point_i)" language="molang" :line-numbers="false" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1156,6 +1156,10 @@
|
||||
"panel.animations": "Animations",
|
||||
"panel.keyframe": "Keyframe",
|
||||
"panel.keyframe.type": "Keyframe (%0)",
|
||||
"panel.keyframe.add_data_point": "Add Keyframe Data Point",
|
||||
"panel.keyframe.remove_data_point": "Remove Data Point",
|
||||
"panel.keyframe.pre": "Pre",
|
||||
"panel.keyframe.post": "Post",
|
||||
"panel.variable_placeholders": "Variable Placeholders",
|
||||
"panel.variable_placeholders.info": "List the variables you want to preview via name=value",
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user