Finish variable placeholder inputs

Auto generate variable placeholder inputs from animation
This commit is contained in:
JannisX11 2022-01-24 20:49:38 +01:00
parent 0f0c85b376
commit de0668f3ec
4 changed files with 65 additions and 24 deletions

View File

@ -75,6 +75,7 @@
.dark_bordered {
height: 30px;
padding-left: 4px;
padding-top: 1px;
background-color: var(--color-back);
border: 1px solid var(--color-border);
}

View File

@ -718,9 +718,6 @@
height: 26px;
margin-top: 2px;
}
#placeholder_buttons li label {
vertical-align: text-bottom;
}

View File

@ -1072,14 +1072,48 @@ const Animator = {
}).add()
//Bones
if (a.bones) {
let existing_variables = [
'query.anim_time',
'query.life_time',
'query.delta_time',
'query.camera_rotation',
'query.rotation_to_camera',
'query.distance_from_camera',
'query.lod_index',
'query.camera_distance_range_lerp',
];
function processPlaceholderVariables(text) {
if (typeof text !== 'string') return;
text = text.replace(/v\./, 'variable.').replace(/q\./, 'query.').replace(/t\./, 'temp.').replace(/c\./, 'context.').toLowerCase();
let matches = text.match(/(query|variable|context|temp)\.\w+/gi);
if (!matches) return;
matches.forEach(match => {
let panel_vue = Interface.Panels.variable_placeholders.inside_vue;
if (existing_variables.includes(match)) return;
if (panel_vue.text.split('\n').find(line => line.substr(0, match.length) == match)) return;
let [space, name] = match.split(/\./);
if (panel_vue.text != '' && panel_vue.text.substr(-1) !== '\n') panel_vue.text += '\n';
if (name == 'modified_distance_moved') {
panel_vue.text += `${match} = time * 8`;
} else if (name.match(/is_|has_|can_|blocking/)) {
panel_vue.text += `${match} = toggle('${name}')`;
} else {
panel_vue.text += `${match} = slider('${name}')`;
}
})
}
function getKeyframeDataPoints(source) {
if (source instanceof Array) {
source.forEach(processPlaceholderVariables);
return [{
x: source[0],
y: source[1],
z: source[2],
}]
} else if (['number', 'string'].includes(typeof source)) {
processPlaceholderVariables(source);
return [{
x: source, y: source, z: source
}]
@ -1420,14 +1454,15 @@ Animator.MolangParser.variableHandler = function (variable) {
key = key.replace(/^v\./, 'variable.').replace(/^q\./, 'query.').replace(/^t\./, 'temp.').replace(/^c\./, 'context.');
if (key === variable && val !== undefined) {
val = val.trim();
if (val.substr(0, 7) === 'button(') {
let args = val.substring(7, val.length - 1).split(/, */);
let [id] = args;
let button = Interface.Panels.variable_placeholders.inside_vue.buttons.find(b => b.id === id);
return button ? button.value : 0;
if (val.match(/^(slider|toggle)\(/)) {
let [type, content] = val.substring(0, val.length - 1).split(/\(/);
let [id] = content.split(/\(|, */);
id = id.replace(/['"]/g, '');
let button = Interface.Panels.variable_placeholders.inside_vue.buttons.find(b => b.id === id && b.type == type);
return button ? parseFloat(button.value) : 0;
} else {
return val[0] == `'` ? val : Animator.MolangParser.parse(val);
@ -1936,33 +1971,36 @@ Interface.definePanels(function() {
this.buttons.forEach(b => old_values[b.id] = b.value);
this.buttons.empty();
let matches = this.text.toLowerCase().match(/button\(.+\)/g);
let matches = this.text.toLowerCase().match(/(slider|toggle)\(.+\)/g);
if (matches) {
matches.forEach(match => {
let args = match.substring(7, match.length - 1).split(/, */);
let [id, type] = args;
let [type, content] = match.substring(0, match.length - 1).split(/\(/);
let [id, ...args] = content.split(/\(|, */);
id = id.replace(/['"]/g, '');
if (this.buttons.find(b => b.id == id)) return;
if (type == 'bool' || type == 'float' || type == 'int') {
let step = type == 'float' ? 0.01 : 1;
if (type == 'float' && args[2]) step = parseFloat(args[2]);
if (type == 'int' && args[2]) step = Math.clamp(parseInt(args[2]), 1, Infinity);
if (type == 'slider') {
this.buttons.push({
type,
id,
value: old_values[id] || 0,
step: args[0],
min: args[1],
max: args[2]
})
} else {
this.buttons.push({
type,
id,
value: old_values[id] || 0,
step,
min: args[3],
max: args[4]
})
}
})
}
},
changeButtonValue(button, event) {
if (button.type == 'bool') {
if (button.type == 'toggle') {
button.value = event.target.checked ? 1 : 0;
}
Animator.preview();
@ -1972,8 +2010,9 @@ Interface.definePanels(function() {
text(text) {
if (Project && typeof text == 'string') {
Project.variable_placeholders = text;
this.updateButtons();
Project.variable_placeholder_buttons.replace(this.buttons);
}
this.updateButtons();
}
},
template: `
@ -1981,9 +2020,9 @@ Interface.definePanels(function() {
<ul id="placeholder_buttons">
<li v-for="button in buttons" :key="button.id">
<input v-if="button.type == 'bool'" type="checkbox" :value="button.value == 1" @change="changeButtonValue(button, $event)">
<input v-if="button.type == 'toggle'" type="checkbox" :value="button.value == 1" @change="changeButtonValue(button, $event)" :id="'placeholder_button_'+button.id">
<input v-else type="number" class="dark_bordered" :step="button.step" :min="button.min" :max="button.max" v-model="button.value" @input="changeButtonValue(button, $event)">
<label>{{ button.id }}</label>
<label :for="'placeholder_button_'+button.id">{{ button.id }}</label>
</li>
</ul>

View File

@ -176,6 +176,7 @@ class ModelProject {
Timeline.animators = Timeline.vue.animators = this.timeline_animators;
Interface.Panels.variable_placeholders.inside_vue.text = this.variable_placeholders.toString();
Interface.Panels.variable_placeholders.inside_vue.buttons.replace(this.variable_placeholder_buttons);
Interface.Panels.skin_pose.inside_vue.pose = this.skin_pose;
@ -365,6 +366,9 @@ new Property(ModelProject, 'vector', 'visible_box', {
new Property(ModelProject, 'string', 'variable_placeholders', {
exposed: false,
});
new Property(ModelProject, 'array', 'variable_placeholder_buttons', {
exposed: false,
});
new Property(ModelProject, 'number', 'shadow_size', {
label: 'dialog.project.shadow_size',
condition: {formats: ['optifine_entity']},