Implement feature to preview texture changes

Move timeline setup controls into separate actions
Allow spacers at start and end of toolbars
This commit is contained in:
JannisX11 2022-01-31 20:06:47 +01:00
parent c7b6348532
commit 9dcf166f6f
8 changed files with 98 additions and 59 deletions

View File

@ -1004,7 +1004,8 @@
.animator_channel_bar .channel_head .text_button .channel_mute {
font-size: 11pt;
}
.animator_channel_bar .channel_head .text_button .fa-eye-slash {
.animator_channel_bar .channel_head .text_button .fa-eye-slash,
.animator_channel_bar .channel_head .text_button .fa-volume-mute {
color: var(--color-subtle_text);
}
.channel_head span {

View File

@ -1004,6 +1004,16 @@ const Animator = {
}
}
})
Interface.Panels.variable_placeholders.inside_vue.text.split('\n').forEach(line => {
line = line.replace(/ +/g, '');
if (!line) return;
let [key, value] = line.split(/=\s*(.+)/);
if (key == 'preview.texture') {
let tex_index = parseInt(Animator.MolangParser.parse(value));
let texture = Texture.all[tex_index % Texture.all.length];
if (texture) texture.select();
}
});
if (Group.selected || NullObject.selected[0]) {
Transformer.updateSelection()
@ -1217,6 +1227,15 @@ const Animator = {
for (var timestamp in a.timeline) {
var entry = a.timeline[timestamp];
var script = entry instanceof Array ? entry.join('\n') : entry;
if (typeof script == 'string') {
let panel_vue = Interface.Panels.variable_placeholders.inside_vue;
let tex_variables = script.match(/(v|variable)\.texture\w*\s*=/);
if (tex_variables && !panel_vue.text.includes('preview.texture =')) {
if (panel_vue.text != '' && panel_vue.text.substr(-1) !== '\n') panel_vue.text += '\n';
panel_vue.text += `preview.texture = ${tex_variables[0].replace(/\s*=$/, '')}`
}
}
animation.animators.effects.addKeyframe({
channel: 'timeline',
time: parseFloat(timestamp),

View File

@ -562,54 +562,8 @@ const Timeline = {
'select_all',
'fold_all_animations',
'_',
{
name: 'menu.timeline.setups',
icon: 'folder_special',
children() {
return Project.timeline_setups.map(setup => {
return {
name: setup.name,
icon: 'star_outline',
children: [
{icon: 'check_circle', name: 'menu.preview.angle.load', click() {
Timeline.vue._data.animators.purge();
unselectAll();
setup.animators.forEach(uuid => {
var ba = Animation.selected.animators[uuid]
if (ba) ba.addToTimeline();
})
Timeline.vue.channels.position = !!setup.channels.position;
Timeline.vue.channels.rotation = !!setup.channels.rotation;
Timeline.vue.channels.scale = !!setup.channels.scale;
Timeline.vue.channels.hide_empty = !!setup.channels.hide_empty;
}},
{icon: 'delete', name: 'generic.delete', click() {
Project.timeline_setups.remove(setup);
}}
]
}
})
}
},
{
name: 'menu.timeline.save_setup',
description: 'menu.timeline.save_setup.desc',
icon: 'star',
async click() {
let name = await Blockbench.textPrompt('generic.name', 'Timeline Setup');
let setup = {
name: name || 'Setup',
channels: {
position: Timeline.vue.channels.position,
rotation: Timeline.vue.channels.rotation,
scale: Timeline.vue.channels.scale,
hide_empty: Timeline.vue.channels.hide_empty
},
animators: Timeline.animators.map(animator => animator.uuid),
};
Project.timeline_setups.push(setup);
}
},
'timeline_setups',
'save_timeline_setup',
'bring_up_all_animations',
'clear_timeline',
'_',
@ -1345,4 +1299,58 @@ BARS.defineActions(function() {
}
}
})
new Action('timeline_setups', {
name: 'menu.timeline.setups',
icon: 'folder_special',
children() {
return Project.timeline_setups.map(setup => {
return {
name: setup.name,
icon: 'star_outline',
children: [
{icon: 'check_circle', name: 'menu.preview.angle.load', click() {
Timeline.vue._data.animators.purge();
unselectAll();
setup.animators.forEach(uuid => {
var ba = Animation.selected.animators[uuid]
if (ba) ba.addToTimeline();
})
Timeline.vue.channels.position = !!setup.channels.position;
Timeline.vue.channels.rotation = !!setup.channels.rotation;
Timeline.vue.channels.scale = !!setup.channels.scale;
Timeline.vue.channels.hide_empty = !!setup.channels.hide_empty;
}},
{icon: 'delete', name: 'generic.delete', click() {
Project.timeline_setups.remove(setup);
}}
]
}
})
},
click(e) {
new Menu(this.children()).open(e.target);
}
})
new Action('save_timeline_setup', {
name: 'menu.timeline.save_setup',
description: 'menu.timeline.save_setup.desc',
icon: 'star',
async click() {
let name = await Blockbench.textPrompt('generic.name', 'Timeline Setup');
let setup = {
name: name || 'Setup',
channels: {
position: Timeline.vue.channels.position,
rotation: Timeline.vue.channels.rotation,
scale: Timeline.vue.channels.scale,
hide_empty: Timeline.vue.channels.hide_empty
},
animators: Timeline.animators.map(animator => animator.uuid),
};
Project.timeline_setups.push(setup);
}
})
})

View File

@ -601,6 +601,7 @@ class NullObjectAnimator extends BoneAnimator {
class EffectAnimator extends GeneralAnimator {
constructor(animation) {
super(null, animation);
this.last_displayed_time = 0;
this.name = tl('timeline.effects')
this.selected = false;
@ -667,6 +668,17 @@ class EffectAnimator extends GeneralAnimator {
}
})
}
if (!this.muted.timeline) {
this.timeline.forEach(kf => {
if ((kf.time > this.last_displayed_time && kf.time <= Timeline.time) || Math.epsilon(kf.time, Timeline.time, 0.01)) {
let script = kf.data_points[0].script;
Animator.MolangParser.parse(script);
}
})
}
this.last_displayed_time = Timeline.time;
}
startPreviousSounds() {
if (!this.muted.sound) {
@ -698,5 +710,5 @@ class EffectAnimator extends GeneralAnimator {
EffectAnimator.prototype.channels = {
particle: {name: tl('timeline.particle'), mutable: true, max_data_points: 1000},
sound: {name: tl('timeline.sound'), mutable: true, max_data_points: 1000},
timeline: {name: tl('timeline.timeline'), mutable: false, max_data_points: 1},
timeline: {name: tl('timeline.timeline'), mutable: true, max_data_points: 1},
}

View File

@ -1292,10 +1292,10 @@ class Toolbar {
this.children.forEach(function(item, i) {
if (typeof item === 'string') {
var last = content.find('> :last-child')
if (last.length === 0 || last.hasClass('toolbar_separator') || i == scope.children.length-1) {
let type = item[0] == '_' ? 'border' : (item[0] == '+' ? 'spacer' : 'linebreak');
if ((last.length === 0 || last.hasClass('toolbar_separator') || i == scope.children.length-1) && type !== 'spacer') {
return this;
}
let type = item[0] == '_' ? 'border' : (item[0] == '+' ? 'spacer' : 'linebreak');
let sep = separators[type].shift();
if (sep) {
content.append(sep);
@ -1315,7 +1315,7 @@ class Toolbar {
}
})
var last = content.find('> :last-child')
if (last.length && last.hasClass('toolbar_separator')) {
if (last.length && last.hasClass('toolbar_separator') && !last.hasClass('spacer')) {
last.remove()
}
return this;

View File

@ -176,7 +176,7 @@ Math.lerp = function(a, b, m) {
Math.isBetween = function(number, limit1, limit2) {
return (number - limit1) * (number - limit2) <= 0
}
Math.epsilon = function(a, b, epsilon) {
Math.epsilon = function(a, b, epsilon = 0.001) {
return Math.abs(b - a) < epsilon
}
Math.trimDeg = function(a) {

File diff suppressed because one or more lines are too long

View File

@ -1293,6 +1293,9 @@
"action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values",
"action.add_marker": "Set Marker",
"action.add_marker.desc": "Set a timeline marker",
"action.timeline_setups": "Timeline Setups",
"action.save_timeline_setup": "Save Timeline Setup...",
"action.save_timeline_setup.desc": "Save a preset for the currently selected animators and channels",
"action.move_keyframe_back": "Move Keyframes Back",
"action.move_keyframe_forth": "Move Keyframes Forth",
"action.previous_keyframe": "Previous Keyframe",
@ -1469,10 +1472,6 @@
"menu.animation_file.unload": "Unload Animation File",
"menu.animation_file.import_remaining": "Import Remaining Animations",
"menu.timeline.setups": "Timeline Setups",
"menu.timeline.save_setup": "Save Timeline Setup...",
"menu.timeline.save_setup.desc": "Save a preset for the currently selected animators and channels",
"menu.keyframe.quaternion": "Quaternion",
"menu.mobile_keyboard.disable_all": "Disable All",