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 { .dark_bordered {
height: 30px; height: 30px;
padding-left: 4px; padding-left: 4px;
padding-top: 1px;
background-color: var(--color-back); background-color: var(--color-back);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
} }

View File

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

View File

@ -1072,14 +1072,48 @@ const Animator = {
}).add() }).add()
//Bones //Bones
if (a.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) { function getKeyframeDataPoints(source) {
if (source instanceof Array) { if (source instanceof Array) {
source.forEach(processPlaceholderVariables);
return [{ return [{
x: source[0], x: source[0],
y: source[1], y: source[1],
z: source[2], z: source[2],
}] }]
} else if (['number', 'string'].includes(typeof source)) { } else if (['number', 'string'].includes(typeof source)) {
processPlaceholderVariables(source);
return [{ return [{
x: source, y: source, z: source 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.'); key = key.replace(/^v\./, 'variable.').replace(/^q\./, 'query.').replace(/^t\./, 'temp.').replace(/^c\./, 'context.');
if (key === variable && val !== undefined) { if (key === variable && val !== undefined) {
val = val.trim(); val = val.trim();
if (val.substr(0, 7) === 'button(') { if (val.match(/^(slider|toggle)\(/)) {
let args = val.substring(7, val.length - 1).split(/, */); let [type, content] = val.substring(0, val.length - 1).split(/\(/);
let [id] = args; let [id] = content.split(/\(|, */);
let button = Interface.Panels.variable_placeholders.inside_vue.buttons.find(b => b.id === id); id = id.replace(/['"]/g, '');
return button ? button.value : 0;
let button = Interface.Panels.variable_placeholders.inside_vue.buttons.find(b => b.id === id && b.type == type);
return button ? parseFloat(button.value) : 0;
} else { } else {
return val[0] == `'` ? val : Animator.MolangParser.parse(val); 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.forEach(b => old_values[b.id] = b.value);
this.buttons.empty(); this.buttons.empty();
let matches = this.text.toLowerCase().match(/button\(.+\)/g); let matches = this.text.toLowerCase().match(/(slider|toggle)\(.+\)/g);
if (matches) { if (matches) {
matches.forEach(match => { matches.forEach(match => {
let args = match.substring(7, match.length - 1).split(/, */); let [type, content] = match.substring(0, match.length - 1).split(/\(/);
let [id, type] = args; let [id, ...args] = content.split(/\(|, */);
id = id.replace(/['"]/g, '');
if (this.buttons.find(b => b.id == id)) return; if (this.buttons.find(b => b.id == id)) return;
if (type == 'bool' || type == 'float' || type == 'int') { if (type == 'slider') {
let step = type == 'float' ? 0.01 : 1; this.buttons.push({
if (type == 'float' && args[2]) step = parseFloat(args[2]); type,
if (type == 'int' && args[2]) step = Math.clamp(parseInt(args[2]), 1, Infinity); id,
value: old_values[id] || 0,
step: args[0],
min: args[1],
max: args[2]
})
} else {
this.buttons.push({ this.buttons.push({
type, type,
id, id,
value: old_values[id] || 0, value: old_values[id] || 0,
step,
min: args[3],
max: args[4]
}) })
} }
}) })
} }
}, },
changeButtonValue(button, event) { changeButtonValue(button, event) {
if (button.type == 'bool') { if (button.type == 'toggle') {
button.value = event.target.checked ? 1 : 0; button.value = event.target.checked ? 1 : 0;
} }
Animator.preview(); Animator.preview();
@ -1972,8 +2010,9 @@ Interface.definePanels(function() {
text(text) { text(text) {
if (Project && typeof text == 'string') { if (Project && typeof text == 'string') {
Project.variable_placeholders = text; Project.variable_placeholders = text;
this.updateButtons();
Project.variable_placeholder_buttons.replace(this.buttons);
} }
this.updateButtons();
} }
}, },
template: ` template: `
@ -1981,9 +2020,9 @@ Interface.definePanels(function() {
<ul id="placeholder_buttons"> <ul id="placeholder_buttons">
<li v-for="button in buttons" :key="button.id"> <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)"> <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> </li>
</ul> </ul>

View File

@ -176,6 +176,7 @@ class ModelProject {
Timeline.animators = Timeline.vue.animators = this.timeline_animators; 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.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; 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', { new Property(ModelProject, 'string', 'variable_placeholders', {
exposed: false, exposed: false,
}); });
new Property(ModelProject, 'array', 'variable_placeholder_buttons', {
exposed: false,
});
new Property(ModelProject, 'number', 'shadow_size', { new Property(ModelProject, 'number', 'shadow_size', {
label: 'dialog.project.shadow_size', label: 'dialog.project.shadow_size',
condition: {formats: ['optifine_entity']}, condition: {formats: ['optifine_entity']},