Molang syntax highlighting in keyframe panel

This commit is contained in:
JannisX11 2020-09-13 15:34:12 +02:00
parent 53871c4bc7
commit 687bf00a1b
5 changed files with 137 additions and 90 deletions

View File

@ -457,20 +457,76 @@
margin-top: 4px;
}
/* Keyframe Panel */
.panel#keyframe .tabs_small label {
font-size: 1em;
height: 30px;
width: 25%;
}
.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 input.dark_bordered {
width: calc(100% - 45px);
width: 100%;
flex-shrink: 1;
}
.molang_input {
overflow-y: hidden;
min-height: 30px;
height: auto;
}
.molang_input pre {
padding: 2px;
min-height: 28px;
background-color: transparent;
cursor: default;
}
.molang_input pre code {
color: #bec2ca;
padding: 0;
cursor: auto;
}
.molang_input pre .token.punctuation {
color: #5ba8c5
}
.molang_input pre .token.operator, .molang_input pre .token.keyword {
color: #fc2f40
}
.molang_input pre .token.number, .molang_input pre .token.boolean {
color: #b99cff
}
.molang_input pre .token.function-name {
color: #94e400
}
.molang_input pre .token.selector {
color: #92dcff;
}
/*Timeline*/
#timeline {
display: block;

View File

@ -42,6 +42,7 @@
<script src="lib/gif.js"></script>
<script src="lib/prism.js"></script>
<script src="lib/VuePrismEditor.min.js"></script>
<script src="lib/molang-prism-syntax.js"></script>
<script src="lib/lzutf8.js"></script>
<script src="lib/peer.min.js"></script>
<script src="lib/marked.min.js"></script>
@ -803,42 +804,6 @@
</div>
<div id="keyframe" class="panel">
<div class="toolbar_wrapper keyframe"></div>
<p class="tl" id="keyframe_type_label"></p>
<div class="bar flex" id="keyframe_bar_x">
<label class="color_x" style="font-weight: bolder">X</label>
<input type="text" id="keyframe_x" class="dark_bordered code keyframe_input tab_target" axis="x" oninput="updateKeyframeValue(this)">
</div>
<div class="bar flex" id="keyframe_bar_y">
<label class="color_y" style="font-weight: bolder">Y</label>
<input type="text" id="keyframe_y" class="dark_bordered code keyframe_input tab_target" axis="y" oninput="updateKeyframeValue(this)">
</div>
<div class="bar flex" id="keyframe_bar_z">
<label class="color_z" style="font-weight: bolder">Z</label>
<input type="text" id="keyframe_z" class="dark_bordered code keyframe_input tab_target" axis="z" oninput="updateKeyframeValue(this)">
</div>
<div class="bar flex" id="keyframe_bar_w">
<label>W</label>
<input type="text" id="keyframe_w" class="dark_bordered code keyframe_input tab_target" axis="w" oninput="updateKeyframeValue(this)">
</div>
<div class="bar flex" id="keyframe_bar_effect">
<label class="tl">data.effect</label>
<input type="text" id="keyframe_effect" class="dark_bordered code keyframe_input tab_target" axis="effect" oninput="updateKeyframeValue(this)">
</div>
<div class="bar flex" id="keyframe_bar_locator">
<label class="tl">data.locator</label>
<input type="text" id="keyframe_locator" class="dark_bordered code keyframe_input tab_target" axis="locator" oninput="updateKeyframeValue(this)">
</div>
<div class="bar flex" id="keyframe_bar_script">
<label class="tl">timeline.pre_effect_script</label>
<input type="text" id="keyframe_script" class="dark_bordered code keyframe_input tab_target" axis="script" oninput="updateKeyframeValue(this)">
</div>
<div class="bar" id="keyframe_bar_instructions">
<label class="tl">timeline.timeline</label>
<textarea id="keyframe_instructions" style="height: 90px;" class="code keyframe_input tab_target" axis="instructions" oninput="updateKeyframeValue(this)"></textarea>
</div>
</div>
<div id="variable_placeholders" class="panel grow">
<p class="tl">panel.variable_placeholders.info</p>

View File

@ -342,9 +342,7 @@ class Keyframe {
])
// Misc Functions
function updateKeyframeValue(obj) {
var axis = $(obj).attr('axis');
var value = $(obj).val();
function updateKeyframeValue(axis, value) {
Timeline.selected.forEach(function(kf) {
kf.set(axis, value);
})
@ -353,57 +351,8 @@ function updateKeyframeValue(obj) {
}
}
function updateKeyframeSelection() {
var multi_channel = false;
var channel = false;
Timeline.selected.forEach((kf) => {
if (channel === false) {
channel = kf.channel
} else if (channel !== kf.channel) {
multi_channel = true
}
})
$('.panel#keyframe .bar').hide();
if (Timeline.selected.length && !multi_channel) {
var first = Timeline.selected[0]
$('#keyframe_type_label').text(tl('panel.keyframe.type', [tl('timeline.'+first.channel)] ))
if (first.animator instanceof BoneAnimator) {
function _gt(axis) {
var n = first.get(axis);
if (typeof n == 'number') return trimFloatNumber(n);
return n;
}
$('#keyframe_bar_x, #keyframe_bar_y, #keyframe_bar_z').show();
$('#keyframe_bar_w').toggle(first.channel === 'rotation' && first.isQuaternion)
$('#keyframe_bar_x input').val(_gt('x'));
$('#keyframe_bar_y input').val(_gt('y'));
$('#keyframe_bar_z input').val(_gt('z'));
if (first.channel === 'rotation' && first.isQuaternion) {
$('#keyframe_bar_w input').val(_gt('w'));
}
} else if (first.channel == 'particle') {
$('#keyframe_bar_effect').show();
$('#keyframe_bar_effect input').val(first.get('effect'));
$('#keyframe_bar_locator').show();
$('#keyframe_bar_locator input').val(first.get('locator'));
$('#keyframe_bar_script').show();
$('#keyframe_bar_script input').val(first.get('script'));
} else if (first.channel == 'sound') {
$('#keyframe_bar_effect').show();
$('#keyframe_bar_effect input').val(first.get('effect'));
} else if (first.channel == 'timeline') {
$('#keyframe_bar_instructions').show();
$('#keyframe_bar_instructions textarea').val(first.get('instructions'));
}
if (Timeline.selected.length) {
BarItems.slider_keyframe_time.update()
} else {
$('#keyframe_type_label').text('')
$('#keyframe_bar_x, #keyframe_bar_y, #keyframe_bar_z, #keyframe_bar_w').hide()
}
BARS.updateConditions()
Blockbench.dispatchEvent('update_keyframe_selection');

View File

@ -379,12 +379,79 @@ function setupPanels() {
`
}
})
console.log(Timeline)
Interface.Panels.keyframe = new Panel({
id: 'keyframe',
icon: 'timeline',
condition: {modes: ['animate']},
toolbars: {
head: Toolbars.keyframe
},
component: {
name: 'panel-keyframe',
components: {VuePrismEditor},
data() { return {
keyframes: Timeline.selected
}},
methods: {
updateInput(axis, value) {
updateKeyframeValue(axis, value)
}
},
computed: {
channel() {
var channel = false;
for (var kf of this.keyframes) {
if (channel === false) {
channel = kf.channel
} else if (channel !== kf.channel) {
channel = false
break;
}
}
return channel;
}
},
template: `
<div>
<div class="toolbar_wrapper keyframe"></div>
<template v-if="channel != false">
<p id="keyframe_type_label">{{ tl('panel.keyframe.type', [tl('timeline.'+channel)]) }}</p>
<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>
<vue-prism-editor class="molang_input dark_bordered keyframe_input tab_target" :value="keyframes[0].x.toString()" v-model="keyframes[0].x" @change="updateInput('x', $event)" language="molang" :line-numbers="false" />
</div>
<div class="bar flex" id="keyframe_bar_y" v-if="keyframes[0].animator instanceof BoneAnimator">
<label class="color_y" style="font-weight: bolder">Y</label>
<vue-prism-editor class="molang_input dark_bordered keyframe_input tab_target" :value="keyframes[0].y.toString()" v-model="keyframes[0].y" @change="updateInput('y', $event)" language="molang" :line-numbers="false" />
</div>
<div class="bar flex" id="keyframe_bar_z" v-if="keyframes[0].animator instanceof BoneAnimator">
<label class="color_z" style="font-weight: bolder">Z</label>
<vue-prism-editor class="molang_input dark_bordered keyframe_input tab_target" :value="keyframes[0].z.toString()" v-model="keyframes[0].z" @change="updateInput('z', $event)" language="molang" :line-numbers="false" />
</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="keyframes[0].effect" @input="updateInput('effect', $event)">
</div>
<div class="bar flex" id="keyframe_bar_locator" v-if="channel == 'particle'">
<label>{{ tl('data.locator') }}</label>
<input type="text" class="dark_bordered code keyframe_input tab_target" v-model="keyframes[0].locator" @input="updateInput('locator', $event)">
</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="keyframes[0].script" @change="updateInput('script', $event)" 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="keyframes[0].instructions" @change="updateInput('instructions', $event)" language="molang" :line-numbers="false" />
</div>
</template>
</div>
`
}
})
Interface.Panels.variable_placeholders = new Panel({

View File

@ -0,0 +1,10 @@
Prism.languages.molang = {
'string': /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
'function-name': /\b(?!\d)math\.\w+(?=[\t ]*\()/i,
'selector': /\b(?!\d)(query|variable|temp|math)\.\w+/i,
'boolean': /\b(?:true|false)\b/i,
'number': /(?:\b\d+(?:\.\d+)?(?:[ed][+-]\d+)?|&h[a-f\d]+)\b[%&!#]?/i,
'operator': /--|\+\+|>>=?|<<=?|<>|[-+*/\\<>]=?|[:^=?]|\b(?:and|mod|not|or)\b/i,
'keyword': /\b(Return)\b/i,
'punctuation': /[.,;()[\]{}]/,
};