Refactor panels
This commit is contained in:
parent
d34031eaaa
commit
f130efd421
@ -1,6 +1,12 @@
|
||||
.panel {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
/*Panel*/
|
||||
.panel {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.panel.grow > .panel_inside {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/*Display*/
|
||||
|
||||
|
123
index.html
123
index.html
@ -69,7 +69,6 @@
|
||||
<script src="js/interface/dialog.js"></script>
|
||||
<script src="js/copy_paste.js"></script>
|
||||
<script src="js/undo.js"></script>
|
||||
<script src="js/edit_sessions.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
if (isApp === true) {
|
||||
@ -81,6 +80,9 @@
|
||||
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/file_system.js"></script>
|
||||
<script src="js/interface/panels.js"></script>
|
||||
<script src="js/interface/interface.js"></script>
|
||||
<script src="js/edit_sessions.js"></script>
|
||||
<script src="js/outliner/outliner.js"></script>
|
||||
<script src="js/outliner/group.js"></script>
|
||||
<script src="js/outliner/cube.js"></script>
|
||||
@ -91,8 +93,6 @@
|
||||
<script src="js/transform.js"></script>
|
||||
<script src="js/texturing/textures.js"></script>
|
||||
<script src="js/texturing/uv.js"></script>
|
||||
<script src="js/interface/panels.js"></script>
|
||||
<script src="js/interface/interface.js"></script>
|
||||
<script src="js/texturing/painter.js"></script>
|
||||
<script src="js/texturing/texture_generator.js"></script>
|
||||
<script src="js/texturing/color.js"></script>
|
||||
@ -735,117 +735,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="display" class="panel">
|
||||
<div class="toolbar_wrapper display"></div>
|
||||
<p class="tl">display.slot</p>
|
||||
<div id="display_bar" class="bar tabs_small icon_bar">
|
||||
<input class="hidden" type="radio" name="display" id="thirdperson_righthand" checked>
|
||||
<label class="tool" for="thirdperson_righthand" onclick="DisplayMode.loadThirdRight()"><div class="tooltip tl">display.slot.third_right</div><i class="material-icons">accessibility</i></label>
|
||||
<input class="hidden" type="radio" name="display" id="thirdperson_lefthand">
|
||||
<label class="tool" for="thirdperson_lefthand" onclick="DisplayMode.loadThirdLeft()"><div class="tooltip tl">display.slot.third_left</div><i class="material-icons">accessibility</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="firstperson_righthand">
|
||||
<label class="tool" for="firstperson_righthand" onclick="DisplayMode.loadFirstRight()"><div class="tooltip tl">display.slot.first_right</div><i class="material-icons">person</i></label>
|
||||
<input class="hidden" type="radio" name="display" id="firstperson_lefthand">
|
||||
<label class="tool" for="firstperson_lefthand" onclick="DisplayMode.loadFirstLeft()"><div class="tooltip tl">display.slot.first_left</div><i class="material-icons">person</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="head">
|
||||
<label class="tool" for="head" onclick="DisplayMode.loadHead()"><div class="tooltip tl">display.slot.head</div><i class="material-icons">sentiment_satisfied</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="ground">
|
||||
<label class="tool" for="ground" onclick="DisplayMode.loadGround()"><div class="tooltip tl">display.slot.ground</div><i class="icon-ground"></i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="fixed">
|
||||
<label class="tool" for="fixed" onclick="DisplayMode.loadFixed()"><div class="tooltip tl">display.slot.frame</div><i class="material-icons">filter_frames</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="gui">
|
||||
<label class="tool" for="gui" onclick="DisplayMode.loadGUI()"><div class="tooltip tl">display.slot.gui</div><i class="material-icons">border_style</i></label>
|
||||
</div>
|
||||
<p class="reference_model_bar tl">display.reference</p>
|
||||
<div id="display_ref_bar" class="bar tabs_small reference_model_bar">
|
||||
</div>
|
||||
|
||||
<div id="display_sliders">
|
||||
|
||||
<p class="tl">display.rotation</p><div class="tool head_right" v-on:click="resetChannel('rotation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar slider_input_combo" v-for="axis in axes">
|
||||
<input type="range" class="tool disp_range" v-model.number="slot.rotation[axis]" v-bind:trigger_type="'rotation.'+axis"
|
||||
min="-180" max="180" step="1" value="0"
|
||||
@input="change(axis, 'rotation')" @mousedown="start" @change="save">
|
||||
<input lang="en" type="number" class="tool disp_text" v-model.number="slot.rotation[axis]" min="-180" max="180" step="0.5" value="0" @input="change(axis, 'rotation');save()" @mousedown="start">
|
||||
<div class="color_corner" :style="{'border-color': `var(--color-axis-${getAxisLetter(axis)})`}"></div>
|
||||
</div>
|
||||
|
||||
<p class="tl">display.translation</p><div class="tool head_right" v-on:click="resetChannel('translation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar slider_input_combo" v-for="axis in axes">
|
||||
<input type="range" class="tool disp_range" v-model.number="slot.translation[axis]" v-bind:trigger_type="'translation.'+axis"
|
||||
v-bind:min="Math.abs(slot.translation[axis]) < 10 ? -20 : (slot.translation[axis] > 0 ? -70*3+10 : -80)"
|
||||
v-bind:max="Math.abs(slot.translation[axis]) < 10 ? 20 : (slot.translation[axis] < 0 ? 70*3-10 : 80)"
|
||||
v-bind:step="Math.abs(slot.translation[axis]) < 10 ? 0.25 : 1"
|
||||
value="0" @input="change(axis, 'translation')" @mousedown="start" @change="save">
|
||||
<input lang="en" type="number" class="tool disp_text" v-model.number="slot.translation[axis]" min="-80" max="80" step="0.5" value="0" @input="change(axis, 'translation');save()" @mousedown="start">
|
||||
<div class="color_corner" :style="{'border-color': `var(--color-axis-${getAxisLetter(axis)})`}"></div>
|
||||
</div>
|
||||
|
||||
<p class="tl">display.scale</p><div class="tool head_right" v-on:click="resetChannel('scale')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar slider_input_combo" v-for="axis in axes">
|
||||
<div class="tool display_scale_invert" v-on:click="invert(axis)">
|
||||
<div class="tooltip tl">display.mirror</div>
|
||||
<i class="material-icons">{{ slot.mirror[axis] ? 'check_box' : 'check_box_outline_blank' }}</i>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" v-model.number="slot.scale[axis]" v-bind:trigger_type="'scale.'+axis" v-bind:id="'scale_range_'+axis"
|
||||
v-bind:min="slot.scale[axis] > 1 ? -2 : 0"
|
||||
v-bind:max="slot.scale[axis] > 1 ? 4 : 2"
|
||||
step="0.01"
|
||||
value="0" @input="change(axis, 'scale')" @mousedown="start" @change="save">
|
||||
<input type="number" class="tool disp_text" v-model.number="slot.scale[axis]" min="0" max="4" step="0.01" value="0" @input="change(axis, 'scale');save()" @mousedown="start">
|
||||
<div class="color_corner" :style="{'border-color': `var(--color-axis-${getAxisLetter(axis)})`}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="textures" class="panel grow">
|
||||
<div class="toolbar_wrapper texturelist"></div>
|
||||
<ul id="texture_list" class="list">
|
||||
<li
|
||||
v-for="texture in textures"
|
||||
v-bind:class="{ selected: texture.selected, particle: texture.particle}"
|
||||
v-bind:texid="texture.uuid"
|
||||
:key="texture.uuid"
|
||||
class="texture"
|
||||
v-on:click.stop="texture.select($event)"
|
||||
v-on:dblclick="texture.openMenu($event)"
|
||||
@contextmenu.prevent.stop="texture.showContextMenu($event)"
|
||||
>
|
||||
<div class="texture_icon_wrapper">
|
||||
<img v-bind:texid="texture.id" v-bind:src="texture.source" class="texture_icon" width="48px" alt="" v-if="texture.show_icon" />
|
||||
<i class="material-icons texture_error" v-bind:title="texture.getErrorMessage()" v-if="texture.error">error_outline</i>
|
||||
<i class="texture_movie fa fa_big fa-film" title="Animated Texture" v-if="texture.frameCount > 1"></i>
|
||||
</div>
|
||||
<div class="texture_description_wrapper">
|
||||
<div class="texture_name">{{ texture.name }}</div>
|
||||
<div class="texture_res">{{ texture.error
|
||||
? texture.getErrorMessage()
|
||||
: texture.width + ' x ' + texture.height + 'px'
|
||||
}}</div>
|
||||
</div>
|
||||
<i class="material-icons texture_visibility_icon" v-if="texture.particle">bubble_chart</i>
|
||||
<i class="material-icons texture_particle_icon clickable"
|
||||
v-bind:class="{icon_off: !texture.visible}"
|
||||
v-if="Project.layered_textures"
|
||||
@click="texture.toggleVisibility()"
|
||||
@dblclick.stop
|
||||
>
|
||||
{{ texture.visible ? 'visibility' : 'visibility_off' }}
|
||||
</i>
|
||||
<i class="material-icons texture_save_icon" v-bind:class="{clickable: !texture.saved}" @click="texture.save()">
|
||||
<template v-if="texture.saved">check_circle</template>
|
||||
<template v-else>save</template>
|
||||
</i>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="right_bar" class="sidebar">
|
||||
|
||||
@ -911,12 +800,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outliner" class="panel grow">
|
||||
<div class="toolbar_wrapper outliner"></div>
|
||||
<ul id="cubes_list" class="list">
|
||||
<vue-tree :option="option"></vue-tree>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="center">
|
||||
<div id="preview">
|
||||
|
@ -1460,3 +1460,133 @@ BARS.defineActions(function() {
|
||||
})*/
|
||||
|
||||
})
|
||||
|
||||
Interface.definePanels(function() {
|
||||
|
||||
Interface.Panels.animations = new Panel({
|
||||
id: 'animations',
|
||||
icon: 'movie',
|
||||
condition: {modes: ['animate']},
|
||||
toolbars: {
|
||||
head: Toolbars.animations
|
||||
},
|
||||
component: {
|
||||
name: 'panel-animations',
|
||||
data() { return {
|
||||
animations: Animator.animations,
|
||||
files_folded: {}
|
||||
}},
|
||||
methods: {
|
||||
toggle(key) {
|
||||
this.files_folded[key] = !this.files_folded[key];
|
||||
this.$forceUpdate();
|
||||
},
|
||||
saveFile(key, file) {
|
||||
if (key && isApp) {
|
||||
file.animations.forEach(animation => {
|
||||
animation.save();
|
||||
})
|
||||
} else {
|
||||
|
||||
}
|
||||
},
|
||||
addAnimation(path) {
|
||||
let other_animation = Animation.all.find(a => a.path == path)
|
||||
console.log(path, other_animation)
|
||||
new Animation({
|
||||
name: other_animation && other_animation.name.replace(/\w+$/, 'new'),
|
||||
path
|
||||
}).add(true).propertiesDialog()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
files() {
|
||||
let files = {};
|
||||
this.animations.forEach(animation => {
|
||||
let key = animation.path || '';
|
||||
if (!files[key]) files[key] = {
|
||||
animations: [],
|
||||
name: animation.path ? pathToName(animation.path, true) : 'Unsaved',
|
||||
saved: true
|
||||
};
|
||||
if (!animation.saved) files[key].saved = false;
|
||||
files[key].animations.push(animation);
|
||||
})
|
||||
return files;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="toolbar_wrapper animations"></div>
|
||||
<ul id="animations_list" class="list">
|
||||
<li v-for="(file, key) in files" :key="key" class="animation_file">
|
||||
<div class="animation_file_head" v-on:click.stop="toggle(key)">
|
||||
<i v-on:click.stop="toggle(key)" class="icon-open-state fa" :class=\'{"fa-angle-right": files_folded[key], "fa-angle-down": !files_folded[key]}\'></i>
|
||||
<label>{{ file.name }}</label>
|
||||
<div class="in_list_button" v-if="!file.saved" v-on:click.stop="saveFile(key, file)">
|
||||
<i class="material-icons">save</i>
|
||||
</div>
|
||||
<div class="in_list_button" v-on:click.stop="addAnimation(key)">
|
||||
<i class="material-icons">add</i>
|
||||
</div>
|
||||
</div>
|
||||
<ul v-if="!files_folded[key]">
|
||||
<li
|
||||
v-for="animation in file.animations"
|
||||
v-bind:class="{ selected: animation.selected }"
|
||||
v-bind:anim_id="animation.uuid"
|
||||
class="animation"
|
||||
v-on:click.stop="animation.select()"
|
||||
v-on:dblclick.stop="animation.propertiesDialog()"
|
||||
:key="animation.uuid"
|
||||
@contextmenu.prevent.stop="animation.showContextMenu($event)"
|
||||
>
|
||||
<i class="material-icons">movie</i>
|
||||
<label>{{ animation.name }}</label>
|
||||
<div class="in_list_button" v-bind:class="{unclickable: animation.saved}" v-on:click.stop="animation.save()">
|
||||
<i v-if="animation.saved" class="material-icons">check_circle</i>
|
||||
<i v-else class="material-icons">save</i>
|
||||
</div>
|
||||
<div class="in_list_button" v-on:click.stop="animation.togglePlayingState()">
|
||||
<i v-if="animation.playing" class="fa_big far fa-play-circle"></i>
|
||||
<i v-else class="fa_big far fa-circle"></i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
})
|
||||
|
||||
Interface.Panels.variable_placeholders = new Panel({
|
||||
id: 'variable_placeholders',
|
||||
icon: 'fas.fa-stream',
|
||||
condition: {modes: ['animate']},
|
||||
growable: true,
|
||||
toolbars: {
|
||||
},
|
||||
component: {
|
||||
name: 'panel-placeholders',
|
||||
components: {VuePrismEditor},
|
||||
data() { return {
|
||||
text: ''
|
||||
}},
|
||||
template: `
|
||||
<div style="flex-grow: 1; display: flex; flex-direction: column;">
|
||||
<p>{{ tl('panel.variable_placeholders.info') }}</p>
|
||||
<vue-prism-editor
|
||||
id="var_placeholder_area"
|
||||
class="molang_input dark_bordered tab_target"
|
||||
v-model="text"
|
||||
language="molang"
|
||||
:line-numbers="false"
|
||||
style="flex-grow: 1;"
|
||||
onkeyup="Animator.preview()"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -641,3 +641,90 @@ BARS.defineActions(function() {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Interface.definePanels(function() {
|
||||
|
||||
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) {
|
||||
console.log(this.keyframes[0].x)
|
||||
updateKeyframeValue(axis, value)
|
||||
},
|
||||
getKeyframeInfos() {
|
||||
let list = [tl('timeline.'+this.channel)];
|
||||
if (this.keyframes.length > 1) list.push(this.keyframes.length);
|
||||
/*if (this.keyframes[0].color >= 0) {
|
||||
list.push(tl(`cube.color.${markerColors[this.keyframes[0].color].name}`))
|
||||
}*/
|
||||
return list.join(', ')
|
||||
}
|
||||
},
|
||||
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', [getKeyframeInfos()]) }}</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 @focus="focus()" @focusout="focusout()" 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>
|
||||
`
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -2,7 +2,6 @@ var osfs = '/'
|
||||
var selected = [];
|
||||
var prev_side = 'north';
|
||||
var uv_clipboard;
|
||||
var outliner, texturelist;
|
||||
var pe_list_data = []
|
||||
var open_dialog = false;
|
||||
var open_interface = false;
|
||||
|
@ -91,25 +91,6 @@ onVueSetup.funcs.forEach((func) => {
|
||||
}
|
||||
})
|
||||
|
||||
$('#cubes_list').droppable({
|
||||
greedy: true,
|
||||
accept: 'div.outliner_object',
|
||||
tolerance: 'pointer',
|
||||
hoverClass: 'drag_hover',
|
||||
drop: function(event, ui) {
|
||||
var item = Outliner.root.findRecursive('uuid', $(ui.draggable).parent().attr('id'))
|
||||
dropOutlinerObjects(item, undefined, event)
|
||||
}
|
||||
})
|
||||
$('#cubes_list').contextmenu(function(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
Interface.Panels.outliner.menu.show(event)
|
||||
})
|
||||
$('#texture_list').contextmenu(function(event) {
|
||||
Interface.Panels.textures.menu.show(event)
|
||||
})
|
||||
|
||||
updateProjectResolution()
|
||||
|
||||
setupInterface()
|
||||
|
@ -1864,60 +1864,6 @@ function updateDisplaySkin() {
|
||||
//displayReferenceObjects.refmodels.player.material
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
DisplayMode.vue = new Vue({
|
||||
el: '#display_sliders',
|
||||
data: {
|
||||
axes: [0, 1, 2],
|
||||
slot: new DisplaySlot()
|
||||
},
|
||||
methods: {
|
||||
isMirrored: (axis) => {
|
||||
if (display[display_slot]) {
|
||||
return display[display_slot].scale[axis] < 0;
|
||||
}
|
||||
},
|
||||
change: (axis, channel) => {
|
||||
if (channel === 'scale') {
|
||||
var val = limitNumber(DisplayMode.slot.scale[axis], 0, 4)
|
||||
DisplayMode.slot.scale[axis] = val;
|
||||
if (Pressing.shift) {
|
||||
DisplayMode.slot.scale[0] = val;
|
||||
DisplayMode.slot.scale[1] = val;
|
||||
DisplayMode.slot.scale[2] = val;
|
||||
}
|
||||
} else if (channel === 'translation') {
|
||||
DisplayMode.slot.translation[axis] = limitNumber(DisplayMode.slot.translation[axis], -80, 80)||0;
|
||||
} else {
|
||||
DisplayMode.slot.rotation[axis] = Math.trimDeg(DisplayMode.slot.rotation[axis])||0;
|
||||
}
|
||||
DisplayMode.updateDisplayBase()
|
||||
},
|
||||
resetChannel: (channel) => {
|
||||
var v = channel === 'scale' ? 1 : 0;
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
DisplayMode.slot.extend({[channel]: [v, v, v]})
|
||||
if (channel === 'scale') {
|
||||
DisplayMode.slot.extend({mirror: [false, false, false]})
|
||||
}
|
||||
Undo.finishEdit('reset display')
|
||||
},
|
||||
invert: (axis) => {
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
DisplayMode.slot.mirror[axis] = !DisplayMode.slot.mirror[axis];
|
||||
DisplayMode.slot.update()
|
||||
Undo.finishEdit('mirror display')
|
||||
},
|
||||
start: () => {
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
},
|
||||
save: () => {
|
||||
Undo.finishEdit('change_display')
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action('add_display_preset', {
|
||||
icon: 'add',
|
||||
@ -1983,4 +1929,139 @@ BARS.defineActions(function() {
|
||||
})
|
||||
})
|
||||
|
||||
Interface.definePanels(function() {
|
||||
|
||||
Interface.Panels.display = new Panel({
|
||||
id: 'display',
|
||||
icon: 'tune',
|
||||
condition: {modes: ['display']},
|
||||
toolbars: {
|
||||
head: Toolbars.display
|
||||
},
|
||||
component: {
|
||||
name: 'panel-keyframe',
|
||||
components: {VuePrismEditor},
|
||||
data() {return {
|
||||
axes: [0, 1, 2],
|
||||
slot: new DisplaySlot()
|
||||
}},
|
||||
methods: {
|
||||
isMirrored: (axis) => {
|
||||
if (display[display_slot]) {
|
||||
return display[display_slot].scale[axis] < 0;
|
||||
}
|
||||
},
|
||||
change: (axis, channel) => {
|
||||
if (channel === 'scale') {
|
||||
var val = limitNumber(DisplayMode.slot.scale[axis], 0, 4)
|
||||
DisplayMode.slot.scale[axis] = val;
|
||||
if (Pressing.shift) {
|
||||
DisplayMode.slot.scale[0] = val;
|
||||
DisplayMode.slot.scale[1] = val;
|
||||
DisplayMode.slot.scale[2] = val;
|
||||
}
|
||||
} else if (channel === 'translation') {
|
||||
DisplayMode.slot.translation[axis] = limitNumber(DisplayMode.slot.translation[axis], -80, 80)||0;
|
||||
} else {
|
||||
DisplayMode.slot.rotation[axis] = Math.trimDeg(DisplayMode.slot.rotation[axis])||0;
|
||||
}
|
||||
DisplayMode.updateDisplayBase()
|
||||
},
|
||||
resetChannel: (channel) => {
|
||||
var v = channel === 'scale' ? 1 : 0;
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
DisplayMode.slot.extend({[channel]: [v, v, v]})
|
||||
if (channel === 'scale') {
|
||||
DisplayMode.slot.extend({mirror: [false, false, false]})
|
||||
}
|
||||
Undo.finishEdit('reset display')
|
||||
},
|
||||
invert: (axis) => {
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
DisplayMode.slot.mirror[axis] = !DisplayMode.slot.mirror[axis];
|
||||
DisplayMode.slot.update()
|
||||
Undo.finishEdit('mirror display')
|
||||
},
|
||||
start: () => {
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
},
|
||||
save: () => {
|
||||
Undo.finishEdit('change_display')
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="toolbar_wrapper display"></div>
|
||||
<p>${ tl('display.slot') }</p>
|
||||
<div id="display_bar" class="bar tabs_small icon_bar">
|
||||
<input class="hidden" type="radio" name="display" id="thirdperson_righthand" checked>
|
||||
<label class="tool" for="thirdperson_righthand" onclick="DisplayMode.loadThirdRight()"><div class="tooltip">${ tl('display.slot.third_right') }</div><i class="material-icons">accessibility</i></label>
|
||||
<input class="hidden" type="radio" name="display" id="thirdperson_lefthand">
|
||||
<label class="tool" for="thirdperson_lefthand" onclick="DisplayMode.loadThirdLeft()"><div class="tooltip">${ tl('display.slot.third_left') }</div><i class="material-icons">accessibility</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="firstperson_righthand">
|
||||
<label class="tool" for="firstperson_righthand" onclick="DisplayMode.loadFirstRight()"><div class="tooltip">${ tl('display.slot.first_right') }</div><i class="material-icons">person</i></label>
|
||||
<input class="hidden" type="radio" name="display" id="firstperson_lefthand">
|
||||
<label class="tool" for="firstperson_lefthand" onclick="DisplayMode.loadFirstLeft()"><div class="tooltip">${ tl('display.slot.first_left') }</div><i class="material-icons">person</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="head">
|
||||
<label class="tool" for="head" onclick="DisplayMode.loadHead()"><div class="tooltip">${ tl('display.slot.head') }</div><i class="material-icons">sentiment_satisfied</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="ground">
|
||||
<label class="tool" for="ground" onclick="DisplayMode.loadGround()"><div class="tooltip">${ tl('display.slot.ground') }</div><i class="icon-ground"></i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="fixed">
|
||||
<label class="tool" for="fixed" onclick="DisplayMode.loadFixed()"><div class="tooltip">${ tl('display.slot.frame') }</div><i class="material-icons">filter_frames</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="gui">
|
||||
<label class="tool" for="gui" onclick="DisplayMode.loadGUI()"><div class="tooltip">${ tl('display.slot.gui') }</div><i class="material-icons">border_style</i></label>
|
||||
</div>
|
||||
<p class="reference_model_bar">${ tl('display.reference') }</p>
|
||||
<div id="display_ref_bar" class="bar tabs_small reference_model_bar">
|
||||
</div>
|
||||
|
||||
<div id="display_sliders">
|
||||
|
||||
<p>${ tl('display.rotation') }</p><div class="tool head_right" v-on:click="resetChannel('rotation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar slider_input_combo" v-for="axis in axes">
|
||||
<input type="range" class="tool disp_range" v-model.number="slot.rotation[axis]" v-bind:trigger_type="'rotation.'+axis"
|
||||
min="-180" max="180" step="1" value="0"
|
||||
@input="change(axis, 'rotation')" @mousedown="start" @change="save">
|
||||
<input lang="en" type="number" class="tool disp_text" v-model.number="slot.rotation[axis]" min="-180" max="180" step="0.5" value="0" @input="change(axis, 'rotation');save()" @mousedown="start">
|
||||
<div class="color_corner" :style="{'border-color': \`var(--color-axis-\${getAxisLetter(axis)})\`}"></div>
|
||||
</div>
|
||||
|
||||
<p>${ tl('display.translation') }</p><div class="tool head_right" v-on:click="resetChannel('translation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar slider_input_combo" v-for="axis in axes">
|
||||
<input type="range" class="tool disp_range" v-model.number="slot.translation[axis]" v-bind:trigger_type="'translation.'+axis"
|
||||
v-bind:min="Math.abs(slot.translation[axis]) < 10 ? -20 : (slot.translation[axis] > 0 ? -70*3+10 : -80)"
|
||||
v-bind:max="Math.abs(slot.translation[axis]) < 10 ? 20 : (slot.translation[axis] < 0 ? 70*3-10 : 80)"
|
||||
v-bind:step="Math.abs(slot.translation[axis]) < 10 ? 0.25 : 1"
|
||||
value="0" @input="change(axis, 'translation')" @mousedown="start" @change="save">
|
||||
<input lang="en" type="number" class="tool disp_text" v-model.number="slot.translation[axis]" min="-80" max="80" step="0.5" value="0" @input="change(axis, 'translation');save()" @mousedown="start">
|
||||
<div class="color_corner" :style="{'border-color': \`var(--color-axis-\${getAxisLetter(axis)})\`}"></div>
|
||||
</div>
|
||||
|
||||
<p>${ tl('display.scale') }</p><div class="tool head_right" v-on:click="resetChannel('scale')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar slider_input_combo" v-for="axis in axes">
|
||||
<div class="tool display_scale_invert" v-on:click="invert(axis)">
|
||||
<div class="tooltip">${ tl('display.mirror') }</div>
|
||||
<i class="material-icons">{{ slot.mirror[axis] ? 'check_box' : 'check_box_outline_blank' }}</i>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" v-model.number="slot.scale[axis]" v-bind:trigger_type="'scale.'+axis" v-bind:id="'scale_range_'+axis"
|
||||
v-bind:min="slot.scale[axis] > 1 ? -2 : 0"
|
||||
v-bind:max="slot.scale[axis] > 1 ? 4 : 2"
|
||||
step="0.01"
|
||||
value="0" @input="change(axis, 'scale')" @mousedown="start" @change="save">
|
||||
<input type="number" class="tool disp_text" v-model.number="slot.scale[axis]" min="0" max="4" step="0.01" value="0" @input="change(axis, 'scale');save()" @mousedown="start">
|
||||
<div class="color_corner" :style="{'border-color': \`var(--color-axis-\${getAxisLetter(axis)})\`}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
})
|
||||
DisplayMode.vue = Interface.Panels.display.inside_vue;
|
||||
})
|
||||
|
||||
})()
|
@ -427,4 +427,40 @@ BARS.defineActions(function() {
|
||||
category: 'blockbench',
|
||||
click: () => (Chat.toggle())
|
||||
})
|
||||
})
|
||||
|
||||
Interface.definePanels(function() {
|
||||
|
||||
Interface.Panels.chat = new Panel({
|
||||
id: 'chat',
|
||||
icon: 'chat',
|
||||
condition: {method() {return EditSession.active}},
|
||||
toolbars: {},
|
||||
onResize: t => {
|
||||
},
|
||||
menu: new Menu([
|
||||
'toggle_chat'
|
||||
]),
|
||||
component: {
|
||||
data() {return Chat},
|
||||
template: `
|
||||
<div>
|
||||
<div class="bar next_to_title" id="chat_title_bar"></div>
|
||||
<ul id="chat_history" v-if="expanded">
|
||||
<li v-for="msg in history">
|
||||
<b v-if="msg.showAuthor()" v-bind:class="{self: msg.self}">{{ msg.author }}:</b>
|
||||
<span class="text" v-bind:style="{color: msg.hex || 'inherit'}" v-html="msg.html"></span>
|
||||
<span class="timestamp">{{ msg.timestamp }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="chat_bar">
|
||||
<input type="text" id="chat_input" class="dark_bordered f_left" maxlength="512">
|
||||
<i class="material-icons" onclick="Chat.send()">send</i>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
})
|
||||
BarItems.toggle_chat.toElement('#chat_title_bar')
|
||||
|
||||
})
|
@ -167,6 +167,10 @@ const Interface = {
|
||||
status_bar: {},
|
||||
Panels: {}
|
||||
}
|
||||
Interface.panel_definers = []
|
||||
Interface.definePanels = function(callback) {
|
||||
Interface.panel_definers.push(callback);
|
||||
}
|
||||
|
||||
//Misc
|
||||
function unselectInterface(event) {
|
||||
|
@ -181,36 +181,7 @@ function setupPanels() {
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//Panels
|
||||
Interface.Panels.uv = new Panel({
|
||||
id: 'uv',
|
||||
icon: 'photo_size_select_large',
|
||||
condition: {modes: ['edit', 'paint']},
|
||||
toolbars: {
|
||||
bottom: Toolbars.main_uv
|
||||
},
|
||||
onResize: function() {
|
||||
let size = limitNumber($(this.node).width()-10, 64, 1200)
|
||||
size = Math.floor(size/16)*16
|
||||
main_uv.setSize(size)
|
||||
}
|
||||
})
|
||||
Interface.Panels.textures = new Panel({
|
||||
id: 'textures',
|
||||
icon: 'fas.fa-images',
|
||||
condition: {modes: ['edit', 'paint']},
|
||||
toolbars: {
|
||||
head: Toolbars.texturelist
|
||||
},
|
||||
menu: new Menu([
|
||||
'import_texture',
|
||||
'create_texture',
|
||||
'reload_textures',
|
||||
'change_textures_folder',
|
||||
'save_textures'
|
||||
])
|
||||
})
|
||||
Interface.Panels.element = new Panel({
|
||||
id: 'element',
|
||||
icon: 'fas.fa-cube',
|
||||
@ -242,277 +213,12 @@ function setupPanels() {
|
||||
`
|
||||
}
|
||||
})
|
||||
Interface.Panels.outliner = new Panel({
|
||||
id: 'outliner',
|
||||
icon: 'list_alt',
|
||||
condition: {modes: ['edit', 'paint', 'animate']},
|
||||
toolbars: {
|
||||
head: Toolbars.outliner
|
||||
},
|
||||
onResize: t => {
|
||||
getAllOutlinerObjects().forEach(o => o.updateElement())
|
||||
},
|
||||
menu: new Menu([
|
||||
'add_cube',
|
||||
'add_group',
|
||||
'_',
|
||||
'sort_outliner',
|
||||
'select_all',
|
||||
'collapse_groups',
|
||||
'element_colors',
|
||||
'outliner_toggle'
|
||||
])
|
||||
})
|
||||
Interface.Panels.chat = new Panel({
|
||||
id: 'chat',
|
||||
icon: 'chat',
|
||||
condition: {method() {return EditSession.active}},
|
||||
toolbars: {},
|
||||
onResize: t => {
|
||||
},
|
||||
menu: new Menu([
|
||||
'toggle_chat'
|
||||
]),
|
||||
component: {
|
||||
data() {return Chat},
|
||||
template: `
|
||||
<div>
|
||||
<div class="bar next_to_title" id="chat_title_bar"></div>
|
||||
<ul id="chat_history" v-if="expanded">
|
||||
<li v-for="msg in history">
|
||||
<b v-if="msg.showAuthor()" v-bind:class="{self: msg.self}">{{ msg.author }}:</b>
|
||||
<span class="text" v-bind:style="{color: msg.hex || 'inherit'}" v-html="msg.html"></span>
|
||||
<span class="timestamp">{{ msg.timestamp }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="chat_bar">
|
||||
<input type="text" id="chat_input" class="dark_bordered f_left" maxlength="512">
|
||||
<i class="material-icons" onclick="Chat.send()">send</i>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
||||
Interface.panel_definers.forEach((definer) => {
|
||||
if (typeof definer === 'function') {
|
||||
definer()
|
||||
}
|
||||
})
|
||||
BarItems.toggle_chat.toElement('#chat_title_bar')
|
||||
|
||||
Interface.Panels.animations = new Panel({
|
||||
id: 'animations',
|
||||
icon: 'movie',
|
||||
condition: {modes: ['animate']},
|
||||
toolbars: {
|
||||
head: Toolbars.animations
|
||||
},
|
||||
component: {
|
||||
name: 'panel-animations',
|
||||
data() { return {
|
||||
animations: Animator.animations,
|
||||
files_folded: {}
|
||||
}},
|
||||
methods: {
|
||||
toggle(key) {
|
||||
this.files_folded[key] = !this.files_folded[key];
|
||||
this.$forceUpdate();
|
||||
},
|
||||
saveFile(key, file) {
|
||||
if (key && isApp) {
|
||||
file.animations.forEach(animation => {
|
||||
animation.save();
|
||||
})
|
||||
} else {
|
||||
|
||||
}
|
||||
},
|
||||
addAnimation(path) {
|
||||
let other_animation = Animation.all.find(a => a.path == path)
|
||||
console.log(path, other_animation)
|
||||
new Animation({
|
||||
name: other_animation && other_animation.name.replace(/\w+$/, 'new'),
|
||||
path
|
||||
}).add(true).propertiesDialog()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
files() {
|
||||
let files = {};
|
||||
this.animations.forEach(animation => {
|
||||
let key = animation.path || '';
|
||||
if (!files[key]) files[key] = {
|
||||
animations: [],
|
||||
name: animation.path ? pathToName(animation.path, true) : 'Unsaved',
|
||||
saved: true
|
||||
};
|
||||
if (!animation.saved) files[key].saved = false;
|
||||
files[key].animations.push(animation);
|
||||
})
|
||||
return files;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="toolbar_wrapper animations"></div>
|
||||
<ul id="animations_list" class="list">
|
||||
<li v-for="(file, key) in files" :key="key" class="animation_file">
|
||||
<div class="animation_file_head" v-on:click.stop="toggle(key)">
|
||||
<i v-on:click.stop="toggle(key)" class="icon-open-state fa" :class=\'{"fa-angle-right": files_folded[key], "fa-angle-down": !files_folded[key]}\'></i>
|
||||
<label>{{ file.name }}</label>
|
||||
<div class="in_list_button" v-if="!file.saved" v-on:click.stop="saveFile(key, file)">
|
||||
<i class="material-icons">save</i>
|
||||
</div>
|
||||
<div class="in_list_button" v-on:click.stop="addAnimation(key)">
|
||||
<i class="material-icons">add</i>
|
||||
</div>
|
||||
</div>
|
||||
<ul v-if="!files_folded[key]">
|
||||
<li
|
||||
v-for="animation in file.animations"
|
||||
v-bind:class="{ selected: animation.selected }"
|
||||
v-bind:anim_id="animation.uuid"
|
||||
class="animation"
|
||||
v-on:click.stop="animation.select()"
|
||||
v-on:dblclick.stop="animation.propertiesDialog()"
|
||||
:key="animation.uuid"
|
||||
@contextmenu.prevent.stop="animation.showContextMenu($event)"
|
||||
>
|
||||
<i class="material-icons">movie</i>
|
||||
<label>{{ animation.name }}</label>
|
||||
<div class="in_list_button" v-bind:class="{unclickable: animation.saved}" v-on:click.stop="animation.save()">
|
||||
<i v-if="animation.saved" class="material-icons">check_circle</i>
|
||||
<i v-else class="material-icons">save</i>
|
||||
</div>
|
||||
<div class="in_list_button" v-on:click.stop="animation.togglePlayingState()">
|
||||
<i v-if="animation.playing" class="fa_big far fa-play-circle"></i>
|
||||
<i v-else class="fa_big far fa-circle"></i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
})
|
||||
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) {
|
||||
console.log(this.keyframes[0].x)
|
||||
updateKeyframeValue(axis, value)
|
||||
},
|
||||
getKeyframeInfos() {
|
||||
let list = [tl('timeline.'+this.channel)];
|
||||
if (this.keyframes.length > 1) list.push(this.keyframes.length);
|
||||
/*if (this.keyframes[0].color >= 0) {
|
||||
list.push(tl(`cube.color.${markerColors[this.keyframes[0].color].name}`))
|
||||
}*/
|
||||
return list.join(', ')
|
||||
}
|
||||
},
|
||||
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', [getKeyframeInfos()]) }}</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 @focus="focus()" @focusout="focusout()" 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({
|
||||
id: 'variable_placeholders',
|
||||
icon: 'fas.fa-stream',
|
||||
condition: {modes: ['animate']},
|
||||
growable: true,
|
||||
toolbars: {
|
||||
},
|
||||
component: {
|
||||
name: 'panel-placeholders',
|
||||
components: {VuePrismEditor},
|
||||
data() { return {
|
||||
text: ''
|
||||
}},
|
||||
template: `
|
||||
<div style="flex-grow: 1; display: flex; flex-direction: column;">
|
||||
<p>{{ tl('panel.variable_placeholders.info') }}</p>
|
||||
<vue-prism-editor
|
||||
id="var_placeholder_area"
|
||||
class="molang_input dark_bordered tab_target"
|
||||
v-model="text"
|
||||
language="molang"
|
||||
:line-numbers="false"
|
||||
style="flex-grow: 1;"
|
||||
onkeyup="Animator.preview()"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
})
|
||||
Interface.Panels.display = new Panel({
|
||||
id: 'display',
|
||||
icon: 'tune',
|
||||
condition: {modes: ['display']},
|
||||
toolbars: {
|
||||
head: Toolbars.display
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Interface.data.left_bar.forEach((id) => {
|
||||
if (Interface.Panels[id]) {
|
||||
@ -536,6 +242,7 @@ function setupPanels() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setActivePanel(panel) {
|
||||
Prop.active_panel = panel
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ class ModelProject {
|
||||
Prop.added_models = 0;
|
||||
Canvas.updateAll();
|
||||
Outliner.vue.$forceUpdate();
|
||||
texturelist.$forceUpdate();
|
||||
Interface.Panels.textures.inside_vue.$forceUpdate();
|
||||
Undo.history.empty();
|
||||
Undo.index = 0;
|
||||
Undo.current_save = null;
|
||||
@ -232,7 +232,7 @@ BARS.defineActions(function() {
|
||||
Texture.all.forEach((tex, i) => {
|
||||
tex.visible = i < 3
|
||||
})
|
||||
texturelist.$forceUpdate()
|
||||
Interface.Panels.textures.inside_vue.$forceUpdate()
|
||||
Canvas.updateLayeredTextures();
|
||||
}
|
||||
}
|
||||
|
@ -905,25 +905,6 @@ function toggleCubeProperty(key) {
|
||||
}
|
||||
|
||||
|
||||
onVueSetup(function() {
|
||||
Outliner.vue = new Vue({
|
||||
el: '#cubes_list',
|
||||
data: {
|
||||
option: {
|
||||
root: {
|
||||
name: 'Model',
|
||||
isParent: true,
|
||||
isOpen: true,
|
||||
selected: false,
|
||||
onOpened: function () {},
|
||||
select: function() {},
|
||||
children: Outliner.root
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action('outliner_toggle', {
|
||||
icon: 'view_stream',
|
||||
@ -1056,3 +1037,70 @@ BARS.defineActions(function() {
|
||||
click: function () {selectAll()}
|
||||
})
|
||||
})
|
||||
|
||||
Interface.definePanels(function() {
|
||||
|
||||
Interface.Panels.outliner = new Panel({
|
||||
id: 'outliner',
|
||||
icon: 'list_alt',
|
||||
condition: {modes: ['edit', 'paint', 'animate']},
|
||||
toolbars: {
|
||||
head: Toolbars.outliner
|
||||
},
|
||||
growable: true,
|
||||
onResize: t => {
|
||||
getAllOutlinerObjects().forEach(o => o.updateElement())
|
||||
},
|
||||
component: {
|
||||
name: 'panel-keyframe',
|
||||
components: {VuePrismEditor},
|
||||
data() { return {
|
||||
root: {
|
||||
name: 'Model',
|
||||
isParent: true,
|
||||
isOpen: true,
|
||||
selected: false,
|
||||
onOpened: function () {},
|
||||
select: function() {},
|
||||
children: Outliner.root
|
||||
}
|
||||
}},
|
||||
methods: {
|
||||
openMenu(event) {
|
||||
Interface.Panels.outliner.menu.show(event)
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="toolbar_wrapper outliner"></div>
|
||||
<ul id="cubes_list" class="list" @contextmenu.stop.prevent="openMenu($event)">
|
||||
<vue-tree :root="root"></vue-tree>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
menu: new Menu([
|
||||
'add_cube',
|
||||
'add_group',
|
||||
'_',
|
||||
'sort_outliner',
|
||||
'select_all',
|
||||
'collapse_groups',
|
||||
'element_colors',
|
||||
'outliner_toggle'
|
||||
])
|
||||
})
|
||||
Outliner.vue = Interface.Panels.outliner.inside_vue;
|
||||
|
||||
$('#cubes_list').droppable({
|
||||
greedy: true,
|
||||
accept: 'div.outliner_object',
|
||||
tolerance: 'pointer',
|
||||
hoverClass: 'drag_hover',
|
||||
drop: function(event, ui) {
|
||||
var item = Outliner.root.findRecursive('uuid', $(ui.draggable).parent().attr('id'))
|
||||
console.log('drop')
|
||||
dropOutlinerObjects(item, undefined, event)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -77,11 +77,14 @@
|
||||
Vue.component('vue-tree-item', VueTreeItem);
|
||||
|
||||
var VueTree = Vue.extend({
|
||||
template: '<div class="vue-tree"><ul>' +
|
||||
'<tree-item :node.sync="option.root"></tree-item>' +
|
||||
'</ul></div>',
|
||||
template: `
|
||||
<div class="vue-tree">
|
||||
<ul>
|
||||
<tree-item :node.sync="root"></tree-item>
|
||||
</ul>
|
||||
</div>`,
|
||||
props: {
|
||||
option: {
|
||||
root: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
@ -90,4 +93,5 @@
|
||||
}
|
||||
});
|
||||
Vue.component('vue-tree', VueTree);
|
||||
})();
|
||||
|
||||
})();
|
||||
|
@ -44,7 +44,7 @@ function colorDistance(color1, color2) {
|
||||
'#ea323c','#c42430','#891e2b','#571c27',
|
||||
]
|
||||
}
|
||||
onVueSetup(() => {
|
||||
Interface.definePanels(() => {
|
||||
ColorPanel = Interface.Panels.color = new Panel({
|
||||
id: 'color',
|
||||
icon: 'palette',
|
||||
|
@ -1230,16 +1230,6 @@ TextureAnimator = {
|
||||
}
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
texturelist = new Vue({
|
||||
el: '#texture_list',
|
||||
data: {
|
||||
textures: Texture.all
|
||||
}
|
||||
})
|
||||
texturelist._data.elements = textures
|
||||
})
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action('import_texture', {
|
||||
icon: 'library_add',
|
||||
@ -1346,3 +1336,78 @@ BARS.defineActions(function() {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Interface.definePanels(function() {
|
||||
|
||||
Interface.Panels.textures = new Panel({
|
||||
id: 'textures',
|
||||
icon: 'fas.fa-images',
|
||||
growable: true,
|
||||
condition: {modes: ['edit', 'paint']},
|
||||
toolbars: {
|
||||
head: Toolbars.texturelist
|
||||
},
|
||||
component: {
|
||||
name: 'panel-keyframe',
|
||||
components: {VuePrismEditor},
|
||||
data() { return {
|
||||
textures: Texture.all
|
||||
}},
|
||||
methods: {
|
||||
openMenu(event) {
|
||||
Interface.Panels.textures.menu.show(event)
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="toolbar_wrapper texturelist"></div>
|
||||
<ul id="texture_list" class="list" @contextmenu.stop.prevent="openMenu($event)">
|
||||
<li
|
||||
v-for="texture in textures"
|
||||
v-bind:class="{ selected: texture.selected, particle: texture.particle}"
|
||||
v-bind:texid="texture.uuid"
|
||||
:key="texture.uuid"
|
||||
class="texture"
|
||||
v-on:click.stop="texture.select($event)"
|
||||
v-on:dblclick="texture.openMenu($event)"
|
||||
@contextmenu.prevent.stop="texture.showContextMenu($event)"
|
||||
>
|
||||
<div class="texture_icon_wrapper">
|
||||
<img v-bind:texid="texture.id" v-bind:src="texture.source" class="texture_icon" width="48px" alt="" v-if="texture.show_icon" />
|
||||
<i class="material-icons texture_error" v-bind:title="texture.getErrorMessage()" v-if="texture.error">error_outline</i>
|
||||
<i class="texture_movie fa fa_big fa-film" title="Animated Texture" v-if="texture.frameCount > 1"></i>
|
||||
</div>
|
||||
<div class="texture_description_wrapper">
|
||||
<div class="texture_name">{{ texture.name }}</div>
|
||||
<div class="texture_res">{{ texture.error
|
||||
? texture.getErrorMessage()
|
||||
: texture.width + ' x ' + texture.height + 'px'
|
||||
}}</div>
|
||||
</div>
|
||||
<i class="material-icons texture_visibility_icon" v-if="texture.particle">bubble_chart</i>
|
||||
<i class="material-icons texture_particle_icon clickable"
|
||||
v-bind:class="{icon_off: !texture.visible}"
|
||||
v-if="Project.layered_textures"
|
||||
@click="texture.toggleVisibility()"
|
||||
@dblclick.stop
|
||||
>
|
||||
{{ texture.visible ? 'visibility' : 'visibility_off' }}
|
||||
</i>
|
||||
<i class="material-icons texture_save_icon" v-bind:class="{clickable: !texture.saved}" @click="texture.save()">
|
||||
<template v-if="texture.saved">check_circle</template>
|
||||
<template v-else>save</template>
|
||||
</i>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
menu: new Menu([
|
||||
'import_texture',
|
||||
'create_texture',
|
||||
'reload_textures',
|
||||
'change_textures_folder',
|
||||
'save_textures'
|
||||
])
|
||||
})
|
||||
})
|
||||
|
@ -2246,3 +2246,21 @@ BARS.defineActions(function() {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Interface.definePanels(function() {
|
||||
|
||||
Interface.Panels.uv = new Panel({
|
||||
id: 'uv',
|
||||
icon: 'photo_size_select_large',
|
||||
selection_only: true,
|
||||
condition: {modes: ['edit', 'paint']},
|
||||
toolbars: {
|
||||
bottom: Toolbars.main_uv
|
||||
},
|
||||
onResize: function() {
|
||||
let size = limitNumber($(this.node).width()-10, 64, 1200)
|
||||
size = Math.floor(size/16)*16
|
||||
main_uv.setSize(size)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user