mirror of
https://github.com/JannisX11/blockbench.git
synced 2024-11-21 01:13:37 +08:00
New UV editor progress
This commit is contained in:
parent
40cd728b00
commit
c4265189bd
@ -1114,6 +1114,7 @@
|
||||
#uv_viewport {
|
||||
height: 320px;
|
||||
width: 320px;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
@ -1176,10 +1177,14 @@
|
||||
.cube_uv_face {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: var(--width);
|
||||
height: var(--height);
|
||||
cursor: move;
|
||||
border: 2px solid var(--color-grid);
|
||||
border: 2px solid var(--color-text);
|
||||
box-sizing: border-box;
|
||||
background-color: rgba(50, 70, 240, 0.14);
|
||||
text-align: center;
|
||||
color: var(--color-subtle_text);
|
||||
}
|
||||
.cube_uv_face:hover {
|
||||
border-color: var(--color-light);
|
||||
@ -1188,6 +1193,42 @@
|
||||
}
|
||||
.cube_uv_face.selected {
|
||||
border-color: var(--color-accent);
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.uv_resize_side {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.uv_resize_side.horizontal {
|
||||
cursor: n-resize;
|
||||
height: 6px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
.uv_resize_side.vertical {
|
||||
cursor: w-resize;
|
||||
width: 6px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
.uv_resize_corner {
|
||||
position: absolute;
|
||||
margin: -6px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
background-color: var(--color-text);
|
||||
z-index: 3;
|
||||
}
|
||||
.uv_resize_corner.uv_c_nw {cursor: nw-resize;}
|
||||
.uv_resize_corner.uv_c_ne {cursor: ne-resize;}
|
||||
.uv_resize_corner.uv_c_sw {cursor: sw-resize;}
|
||||
.uv_resize_corner.uv_c_se {cursor: se-resize;}
|
||||
|
||||
#uv_seleced_faces {
|
||||
display: flex;
|
||||
}
|
||||
#uv_seleced_faces li {
|
||||
padding: 0 5px;
|
||||
}
|
||||
/*
|
||||
#uv_size {
|
||||
|
@ -156,6 +156,9 @@ function updateSelection(options = {}) {
|
||||
function selectAll() {
|
||||
if (Modes.animate) {
|
||||
selectAllKeyframes()
|
||||
} else if (Prop.active_panel == 'uv') {
|
||||
UVEditor.selectAll()
|
||||
|
||||
} else if (Modes.edit || Modes.paint) {
|
||||
if (Outliner.selected.length < Outliner.elements.length) {
|
||||
if (Outliner.root.length == 1) {
|
||||
|
@ -58,7 +58,7 @@ class ModelProject {
|
||||
get texture_height() {return this._texture_height}
|
||||
set texture_width(n) {
|
||||
n = parseInt(n)||16
|
||||
Vue.nextTick(updateProjectResolution)
|
||||
if (this.selected) Vue.nextTick(updateProjectResolution)
|
||||
this._texture_width = n;
|
||||
}
|
||||
get optional_box_uv() {
|
||||
@ -66,7 +66,7 @@ class ModelProject {
|
||||
}
|
||||
set texture_height(n) {
|
||||
n = parseInt(n)||16
|
||||
Vue.nextTick(updateProjectResolution)
|
||||
if (this.selected) Vue.nextTick(updateProjectResolution)
|
||||
this._texture_height = n;
|
||||
}
|
||||
get name() {
|
||||
@ -174,6 +174,7 @@ class ModelProject {
|
||||
UVEditor.vue.elements = this.selected_elements;
|
||||
UVEditor.vue.selected_vertices = this.selected_vertices;
|
||||
UVEditor.vue.selected_faces = this.selected_faces;
|
||||
UVEditor.vue.box_uv = this.box_uv;
|
||||
|
||||
Interface.Panels.textures.inside_vue.textures = Texture.all;
|
||||
scene.add(this.model_3d);
|
||||
@ -202,6 +203,7 @@ class ModelProject {
|
||||
setProjectTitle(this.name);
|
||||
setStartScreen(!Project);
|
||||
updateInterface();
|
||||
updateProjectResolution();
|
||||
Vue.nextTick(() => {
|
||||
loadTextureDraggable();
|
||||
})
|
||||
|
@ -711,6 +711,7 @@ const UVEditor = {
|
||||
}
|
||||
matches.forEach(s => {
|
||||
selected.safePush(s)
|
||||
console.log(s.size(), face_match)
|
||||
});
|
||||
updateSelection();
|
||||
}
|
||||
@ -1046,10 +1047,6 @@ const UVEditor = {
|
||||
return this;
|
||||
},
|
||||
updateInterface() {
|
||||
for (var key in this.sliders) {
|
||||
var slider = this.sliders[key]
|
||||
slider.node.style.setProperty('display', BARS.condition(slider.condition)?'block':'none')
|
||||
}
|
||||
this.jquery.size.resizable('option', 'disabled', Project.box_uv)
|
||||
},
|
||||
contextMenu() {
|
||||
@ -1092,8 +1089,7 @@ const UVEditor = {
|
||||
Canvas.updateUV(obj)
|
||||
})
|
||||
this.displaySliders()
|
||||
this.displayFrame()
|
||||
this.disableAutoUV()
|
||||
this.vue.$forceUpdate()
|
||||
},
|
||||
slideSize(modify, axis) {
|
||||
var scope = this
|
||||
@ -1109,14 +1105,25 @@ const UVEditor = {
|
||||
}
|
||||
})
|
||||
this.displaySliders()
|
||||
this.displayFrame()
|
||||
this.disableAutoUV()
|
||||
this.vue.$forceUpdate()
|
||||
},
|
||||
getResolution(axis, texture) {
|
||||
return axis ? Project.texture_height : Project.texture_width;
|
||||
},
|
||||
|
||||
//Events
|
||||
selectAll() {
|
||||
let selected_before = this.vue.selected_faces.length;
|
||||
this.vue.mappable_elements.forEach(element => {
|
||||
for (let key in element.faces) {
|
||||
this.vue.selected_faces.safePush(key);
|
||||
}
|
||||
})
|
||||
if (selected_before == this.vue.selected_faces.length) {
|
||||
this.vue.selected_faces.empty();
|
||||
}
|
||||
},
|
||||
disableAutoUV() {
|
||||
this.forCubes(obj => {
|
||||
obj.autouv = 0
|
||||
@ -1492,16 +1499,10 @@ const UVEditor = {
|
||||
this.loadData()
|
||||
this.message('uv_editor.reset')
|
||||
},
|
||||
select() {
|
||||
if (UVEditor.cube_faces.includes(this.id) === false) return;
|
||||
UVEditor.selection = [this.id]
|
||||
UVEditor.updateSelection()
|
||||
},
|
||||
|
||||
// Dialog
|
||||
|
||||
isSetup: false,
|
||||
single: false,
|
||||
clipboard: null,
|
||||
cube_faces: ['north', 'south', 'west', 'east', 'up', 'down'],
|
||||
selection: [],
|
||||
@ -1522,18 +1523,6 @@ const UVEditor = {
|
||||
}
|
||||
UVEditor.updateSelection()
|
||||
},
|
||||
selectAll: function() {
|
||||
if (UVEditor.selection.length === 6) {
|
||||
UVEditor.selection.empty()
|
||||
} else {
|
||||
UVEditor.selection = UVEditor.cube_faces.slice()
|
||||
}
|
||||
UVEditor.updateSelection()
|
||||
},
|
||||
selectNone: function() {
|
||||
UVEditor.selection = []
|
||||
UVEditor.updateSelection()
|
||||
},
|
||||
forSelection: function(cb, event, ...args) {
|
||||
if (open_dialog === false) {
|
||||
UVEditor[cb](event, ...args)
|
||||
@ -1785,9 +1774,7 @@ BARS.defineActions(function() {
|
||||
},
|
||||
onChange: function(slider) {
|
||||
var value = slider.get().replace(/x/, '');
|
||||
UVEditor.all_editors.forEach(editor => {
|
||||
editor.setGrid(value);
|
||||
});
|
||||
UVEditor.setGrid(value);
|
||||
}
|
||||
})
|
||||
/*
|
||||
@ -1979,7 +1966,7 @@ Interface.definePanels(function() {
|
||||
height: 320,
|
||||
zoom: 1,
|
||||
checkerboard: settings.uv_checkerboard.value,
|
||||
texture: '',
|
||||
texture: 0,
|
||||
|
||||
project_resolution: [16, 16],
|
||||
elements: [],
|
||||
@ -2018,9 +2005,11 @@ Interface.definePanels(function() {
|
||||
this.$refs.viewport.scrollLeft = Math.round(this.$refs.viewport.scrollLeft * (size / old_size));
|
||||
this.$refs.viewport.scrollTop = Math.round(this.$refs.viewport.scrollTop * (size / old_size));
|
||||
|
||||
/*for (var id in UVEditor.sliders) {
|
||||
UVEditor.sliders[id].setWidth(size/(Project.box_uv?2:4)-1)
|
||||
}*/
|
||||
for (var id in UVEditor.sliders) {
|
||||
var slider = UVEditor.sliders[id];
|
||||
slider.setWidth(size/(Project.box_uv?2:4)-1)
|
||||
slider.node.style.setProperty('display', BARS.condition(slider.condition)?'block':'none')
|
||||
}
|
||||
},
|
||||
setMode(mode) {
|
||||
this.mode = mode;
|
||||
@ -2040,12 +2029,11 @@ Interface.definePanels(function() {
|
||||
}
|
||||
}
|
||||
if (texture == null) {
|
||||
this.texture = null;
|
||||
UVEditor.texture = null;
|
||||
this.texture = UVEditor.texture = null;
|
||||
} else if (texture instanceof Texture) {
|
||||
this.texture = (!texture.error || texture.error == 2) ? texture.source : '';
|
||||
this.texture = texture;
|
||||
} else {
|
||||
this.texture = '';
|
||||
this.texture = UVEditor.texture = 0;
|
||||
}
|
||||
},
|
||||
onMouseWheel(event) {
|
||||
@ -2099,8 +2087,10 @@ Interface.definePanels(function() {
|
||||
contextMenu(event) {
|
||||
UVEditor.menu.open(event);
|
||||
},
|
||||
selectFace(key, event, element) {
|
||||
if (event.shiftKey || event.ctrlOrCmd || Pressing.overrides.shift || Pressing.overrides.ctrl) {
|
||||
selectFace(key, event, keep_selection) {
|
||||
if (keep_selection && this.selected_faces.includes(key)) {
|
||||
|
||||
} else if (event.shiftKey || event.ctrlOrCmd || Pressing.overrides.shift || Pressing.overrides.ctrl) {
|
||||
if (this.selected_faces.includes(key)) {
|
||||
this.selected_faces.remove(key);
|
||||
} else {
|
||||
@ -2123,6 +2113,8 @@ Interface.definePanels(function() {
|
||||
},
|
||||
dragFace(face_key, event) {
|
||||
if (event.which == 2 || event.which == 3) return;
|
||||
|
||||
this.selectFace(face_key, event, true);
|
||||
let scope = this;
|
||||
let elements = this.mappable_elements;
|
||||
Undo.initEdit({elements, uv_only: true})
|
||||
@ -2155,8 +2147,8 @@ Interface.definePanels(function() {
|
||||
let step_x = (scope.inner_width / UVEditor.getResolution(0) / UVEditor.grid);
|
||||
let step_y = (scope.inner_height / UVEditor.getResolution(1) / UVEditor.grid);
|
||||
|
||||
pos[0] = Math.round((e1.clientX - event.clientX) / step_x);
|
||||
pos[1] = Math.round((e1.clientY - event.clientY) / step_y);
|
||||
pos[0] = Math.round((e1.clientX - event.clientX) / step_x) / UVEditor.grid;
|
||||
pos[1] = Math.round((e1.clientY - event.clientY) / step_y) / UVEditor.grid;
|
||||
|
||||
if (pos[0] != last_pos[0] || pos[1] != last_pos[1]) {
|
||||
|
||||
@ -2165,18 +2157,10 @@ Interface.definePanels(function() {
|
||||
})
|
||||
last_pos.replace(pos);
|
||||
}
|
||||
/*
|
||||
var p = ui.position;
|
||||
var o = ui.originalPosition;
|
||||
p.left = o.left + (p.left - o.left);
|
||||
p.top = o.top + (p.top - o.top);
|
||||
p.left = limitNumber(p.left, 0, scope.inner_width-scope.jquery.size.width()+1);
|
||||
p.top = limitNumber(p.top, 0, scope.inner_height-scope.jquery.size.height()+1);
|
||||
p.left = Math.round(p.left / step_x) * step_x;
|
||||
p.top = Math.round(p.top / step_y) * step_y;*/
|
||||
UVEditor.displaySliders();
|
||||
UVEditor.loadData();
|
||||
UVEditor.vue.$forceUpdate();
|
||||
Canvas.updateView({elements: scope.mappable_elements, element_aspects: {uv: true}});
|
||||
}
|
||||
|
||||
function stop(e1) {
|
||||
@ -2188,11 +2172,86 @@ Interface.definePanels(function() {
|
||||
addEventListeners(document, 'mousemove touchmove', drag);
|
||||
addEventListeners(document, 'mouseup touchend', stop);
|
||||
},
|
||||
resizeFace(face_key, event, x_side, y_side) {
|
||||
if (event.which == 2 || event.which == 3) return;
|
||||
let scope = this;
|
||||
let elements = this.mappable_elements;
|
||||
Undo.initEdit({elements, uv_only: true})
|
||||
|
||||
let pos = [0, 0];
|
||||
let last_pos = [0, 0];
|
||||
let offset = function(element, x, y) {
|
||||
scope.selected_faces.forEach(key => {
|
||||
if (element.faces[key] && element instanceof Cube) {
|
||||
if (x_side == -1) element.faces[key].uv[0] += x;
|
||||
if (y_side == -1) element.faces[key].uv[1] += y;
|
||||
if (x_side == 1) element.faces[key].uv[2] += x;
|
||||
if (y_side == 1) element.faces[key].uv[3] += y;
|
||||
}
|
||||
})
|
||||
element.uv_offset[0] += x;
|
||||
element.uv_offset[1] += y;
|
||||
}
|
||||
|
||||
function drag(e1) {
|
||||
|
||||
let step_x = (scope.inner_width / UVEditor.getResolution(0) / UVEditor.grid);
|
||||
let step_y = (scope.inner_height / UVEditor.getResolution(1) / UVEditor.grid);
|
||||
|
||||
pos[0] = Math.round((e1.clientX - event.clientX) / step_x) / UVEditor.grid;
|
||||
pos[1] = Math.round((e1.clientY - event.clientY) / step_y) / UVEditor.grid;
|
||||
|
||||
if (pos[0] != last_pos[0] || pos[1] != last_pos[1]) {
|
||||
|
||||
elements.forEach(element => {
|
||||
offset(element, pos[0] - last_pos[0], pos[1] - last_pos[1])
|
||||
})
|
||||
last_pos.replace(pos);
|
||||
}
|
||||
UVEditor.displaySliders();
|
||||
UVEditor.loadData();
|
||||
UVEditor.vue.$forceUpdate();
|
||||
Canvas.updateView({elements: scope.mappable_elements, element_aspects: {uv: true}});
|
||||
}
|
||||
|
||||
function stop() {
|
||||
removeEventListeners(document, 'mousemove touchmove', drag);
|
||||
removeEventListeners(document, 'mouseup touchend', stop);
|
||||
UVEditor.disableAutoUV()
|
||||
Undo.finishEdit('Resize UV')
|
||||
}
|
||||
addEventListeners(document, 'mousemove touchmove', drag);
|
||||
addEventListeners(document, 'mouseup touchend', stop);
|
||||
},
|
||||
|
||||
openFaceMenu(event) {
|
||||
let faces = [];
|
||||
this.mappable_elements.forEach(element => {
|
||||
for (let key in element.faces) {
|
||||
if (faces.find(item => item.id == key)) continue;
|
||||
faces.push({
|
||||
id: key,
|
||||
name: this.face_names[key],
|
||||
icon: this.selected_faces.includes(key) ? 'check_box' : 'check_box_outline_blank',
|
||||
click: () => {
|
||||
this.selected_faces.splice(0, Infinity, key);
|
||||
//UVEditor.loadData()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
new Menu(faces).open(this.$refs.seleced_faces)
|
||||
},
|
||||
|
||||
toPixels(uv_coord, offset = 0) {
|
||||
return (uv_coord / this.project_resolution[0] * this.inner_width + offset) + 'px'
|
||||
}
|
||||
},
|
||||
/*
|
||||
Extra Info
|
||||
Selected Faces
|
||||
Pointer Coords
|
||||
*/
|
||||
template: `
|
||||
<div class="UVEditor" ref="main" :class="{checkerboard_trigger: checkerboard}" id="UVEditor">
|
||||
|
||||
@ -2202,6 +2261,12 @@ Interface.definePanels(function() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bar">
|
||||
<ul v-if="!box_uv" id="uv_seleced_faces" ref="seleced_faces" @click="openFaceMenu($event)">
|
||||
<li v-for="key in selected_faces">{{ face_names[key] }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="uv_viewport"
|
||||
@contextmenu="contextMenu($event)"
|
||||
@mousedown="onMouseDown($event)"
|
||||
@ -2219,12 +2284,28 @@ Interface.definePanels(function() {
|
||||
<template v-if="!box_uv">
|
||||
<div class="cube_uv_face"
|
||||
v-for="(face, key) in element.faces" :key="key"
|
||||
v-if="face.getTexture() == texture"
|
||||
:title="face_names[key]"
|
||||
:class="{selected: selected_faces.includes(key)}"
|
||||
@click="selectFace(key, $event, element)"
|
||||
@mousedown.prevent="dragFace(key, $event)"
|
||||
:style="{left: toPixels(Math.min(face.uv[0], face.uv[2])), top: toPixels(Math.min(face.uv[1], face.uv[3])), width: toPixels(Math.abs(face.uv_size[0])), height: toPixels(Math.abs(face.uv_size[1]))}"
|
||||
:style="{
|
||||
left: toPixels(Math.min(face.uv[0], face.uv[2]), -1),
|
||||
top: toPixels(Math.min(face.uv[1], face.uv[3]), -1),
|
||||
'--width': toPixels(Math.abs(face.uv_size[0]), 2),
|
||||
'--height': toPixels(Math.abs(face.uv_size[1]), 2),
|
||||
}"
|
||||
>
|
||||
<template v-if="selected_faces.includes(key)">
|
||||
{{ face_names[key] || '' }}
|
||||
<div class="uv_resize_side horizontal" @mousedown.stop="resizeFace(key, $event, 0, -1)" style="width: var(--width)"></div>
|
||||
<div class="uv_resize_side horizontal" @mousedown.stop="resizeFace(key, $event, 0, 1)" style="top: var(--height); width: var(--width)"></div>
|
||||
<div class="uv_resize_side vertical" @mousedown.stop="resizeFace(key, $event, -1, 0)" style="height: var(--height)"></div>
|
||||
<div class="uv_resize_side vertical" @mousedown.stop="resizeFace(key, $event, 1, 0)" style="left: var(--width); height: var(--height)"></div>
|
||||
<div class="uv_resize_corner uv_c_nw" @mousedown.stop="resizeFace(key, $event, -1, -1)" style="left: 0; top: 0"></div>
|
||||
<div class="uv_resize_corner uv_c_ne" @mousedown.stop="resizeFace(key, $event, 1, -1)" style="left: var(--width); top: 0"></div>
|
||||
<div class="uv_resize_corner uv_c_sw" @mousedown.stop="resizeFace(key, $event, -1, 1)" style="left: 0; top: var(--height)"></div>
|
||||
<div class="uv_resize_corner uv_c_se" @mousedown.stop="resizeFace(key, $event, 1, 1)" style="left: var(--width); top: var(--height)"></div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -2239,7 +2320,7 @@ Interface.definePanels(function() {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<img style="object-fit: cover; object-position: 0px 0px;" v-if="texture" :src="texture">
|
||||
<img style="object-fit: cover; object-position: 0px 0px;" v-if="texture && texture.error != 1" :src="texture.source">
|
||||
</div>
|
||||
</div>
|
||||
<div class="bar uv_editor_sliders" ref="slider_bar" style="margin-left: 2px;">
|
||||
@ -2268,12 +2349,12 @@ Interface.definePanels(function() {
|
||||
UVEditor.sliders.pos_x = new NumSlider({
|
||||
id: 'uv_slider_pos_x',
|
||||
private: true,
|
||||
condition: function() {return true},
|
||||
condition: () => UVEditor.vue.selected_faces.length,
|
||||
get: function() {
|
||||
if (Project.box_uv && Cube.selected[0]) {
|
||||
return trimFloatNumber(Cube.selected[0].uv_offset[0])
|
||||
} else if (Cube.selected[0]) {
|
||||
var face_uv = Cube.selected[0].faces[UVEditor.face].uv
|
||||
var face_uv = Cube.selected[0].faces[UVEditor.vue.selected_faces[0]].uv
|
||||
if (face_uv) {
|
||||
return trimFloatNumber(face_uv[0])
|
||||
}
|
||||
@ -2291,12 +2372,12 @@ Interface.definePanels(function() {
|
||||
UVEditor.sliders.pos_y = new NumSlider({
|
||||
id: 'uv_slider_pos_y',
|
||||
private: true,
|
||||
condition: function() {return true},
|
||||
condition: () => UVEditor.vue.selected_faces.length,
|
||||
get: function() {
|
||||
if (Project.box_uv && Cube.selected[0]) {
|
||||
return trimFloatNumber(Cube.selected[0].uv_offset[1])
|
||||
} else if (Cube.selected[0]) {
|
||||
var face_uv = Cube.selected[0].faces[UVEditor.face].uv
|
||||
var face_uv = Cube.selected[0].faces[UVEditor.vue.selected_faces[0]].uv
|
||||
if (face_uv) {
|
||||
return trimFloatNumber(face_uv[1])
|
||||
}
|
||||
@ -2314,7 +2395,7 @@ Interface.definePanels(function() {
|
||||
UVEditor.sliders.size_x = new NumSlider({
|
||||
id: 'uv_slider_size_x',
|
||||
private: true,
|
||||
condition: function() {return !Project.box_uv},
|
||||
condition: () => (!Project.box_uv && Cube.selected[0]),
|
||||
get: function() {
|
||||
if (!Project.box_uv && Cube.selected[0]) {
|
||||
var face_uv = Cube.selected[0].faces[UVEditor.face].uv
|
||||
@ -2335,7 +2416,7 @@ Interface.definePanels(function() {
|
||||
UVEditor.sliders.size_y = new NumSlider({
|
||||
id: 'uv_slider_size_y',
|
||||
private: true,
|
||||
condition: function() {return !Project.box_uv},
|
||||
condition: () => (!Project.box_uv && Cube.selected[0]),
|
||||
get: function() {
|
||||
if (!Project.box_uv && Cube.selected[0]) {
|
||||
var face_uv = Cube.selected[0].faces[UVEditor.face].uv
|
||||
|
Loading…
Reference in New Issue
Block a user