From 9f7fe3719d6611c42cd008bc3d8ee8a334f62b79 Mon Sep 17 00:00:00 2001 From: Jannis Date: Sun, 9 Jul 2023 10:53:04 +0200 Subject: [PATCH 1/7] Fix #1891 Cannot add reference images in orthographic Fix reference image error --- js/interface/dialog.js | 1 - js/preview/reference_images.js | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/js/interface/dialog.js b/js/interface/dialog.js index fec71b36..328eff76 100644 --- a/js/interface/dialog.js +++ b/js/interface/dialog.js @@ -939,7 +939,6 @@ window.MessageBox = class MessageBox extends Dialog { close(button, result, event) { if (this.callback) { let allow_close = this.callback(button, result, event); - console.log(allow_close) if (allow_close === false) return; } this.hide(); diff --git a/js/preview/reference_images.js b/js/preview/reference_images.js index 69fc27f1..de0ca580 100644 --- a/js/preview/reference_images.js +++ b/js/preview/reference_images.js @@ -100,7 +100,7 @@ class ReferenceImage { } addAsReference(save) { Project.reference_images.push(this); - if (Preview.selected && Preview.selected.isOrtho) this.changeLayer('blueprint'); + if (Preview.selected && Preview.selected.angle) this.changeLayer('blueprint'); this.scope = 'project'; this.update(); if (save) this.save(); @@ -108,7 +108,7 @@ class ReferenceImage { } addAsGlobalReference(save) { ReferenceImage.global.push(this); - if (Preview.selected && Preview.selected.isOrtho) this.changeLayer('blueprint'); + if (Preview.selected && Preview.selected.angle) this.changeLayer('blueprint'); this.scope = 'global'; this.update(); if (save) this.save(); @@ -256,7 +256,7 @@ class ReferenceImage { pos_x += preview.width/2; pos_y += preview.height/2; - if (quad_previews.enabled) { + if (Preview.split_screen.enabled) { pos_x += preview.node.parentElement.offsetLeft; pos_y += preview.node.parentElement.offsetTop; } From 4499aa9880ae6af0304974900fd8810d0cc5db73 Mon Sep 17 00:00:00 2001 From: Jannis Date: Sun, 9 Jul 2023 11:05:52 +0200 Subject: [PATCH 2/7] Fix issue with mesh size sliders --- js/modeling/transform_gizmo.js | 2 +- js/outliner/mesh.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/js/modeling/transform_gizmo.js b/js/modeling/transform_gizmo.js index 3afa2b97..b3b450c6 100644 --- a/js/modeling/transform_gizmo.js +++ b/js/modeling/transform_gizmo.js @@ -1300,7 +1300,7 @@ } }) displayDistance(move_value * (scope.direction ? 1 : -1)); - scope.updateSelection() + updateSelection() previousValue = move_value scope.hasChanged = true } diff --git a/js/outliner/mesh.js b/js/outliner/mesh.js index 76669237..1ed3eaa1 100644 --- a/js/outliner/mesh.js +++ b/js/outliner/mesh.js @@ -536,6 +536,7 @@ class Mesh extends OutlinerElement { getSize(axis, selection_only) { if (selection_only) { let selected_vertices = Project.mesh_selection[this.uuid]?.vertices || Object.keys(this.vertices); + if (!selected_vertices.length) return 0; let range = [Infinity, -Infinity]; let {vec1, vec2} = Reusable; let rotation_inverted = new THREE.Euler().copy(Transformer.rotation_selection).invert(); From 81c2cecb3a5863a1abb84b3453b959370b9855bf Mon Sep 17 00:00:00 2001 From: Jannis Date: Sun, 9 Jul 2023 11:13:12 +0200 Subject: [PATCH 3/7] Fix #1940 desktop only plugins with with URL query Fix start screen slideshow not working on older browsers --- js/interface/start_screen.js | 2 +- js/web.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/interface/start_screen.js b/js/interface/start_screen.js index f600ada8..9ccee0f1 100644 --- a/js/interface/start_screen.js +++ b/js/interface/start_screen.js @@ -329,7 +329,7 @@ onVueSetup(function() { this.updateThumbnails(); setInterval(() => { - if (this.show_splash_screen && this.slideshow_autoplay && this.$el.checkVisibility()) { + if (this.show_splash_screen && this.slideshow_autoplay && this.$el.offsetParent) { slideshow_timer += 1; if (slideshow_timer == 24) { diff --git a/js/web.js b/js/web.js index 6cc51fa1..0e71a5ab 100644 --- a/js/web.js +++ b/js/web.js @@ -80,7 +80,7 @@ async function loadInfoFromURL() { if (Blockbench.queries.plugins) { let plugin_ids = Blockbench.queries.plugins.split(/,/); let plugins = plugin_ids.map(id => Plugins.all.find(plugin => plugin.id == id)) - .filter(p => p instanceof Plugin && p.installed == false && p.isInstallable()); + .filter(p => p instanceof Plugin && p.installed == false && p.isInstallable() == true); if (plugins.length) { await new Promise(resolve => { let form = { From 3e24f5b04e1d0f79c1e690da1f1d6ae0c7e9fe41 Mon Sep 17 00:00:00 2001 From: JannisX11 Date: Sun, 9 Jul 2023 14:26:41 +0200 Subject: [PATCH 4/7] Fix #1939 3D brush outline on deformed UV quads --- js/outliner/mesh.js | 10 ++++++---- js/util/util.js | 13 +++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/js/outliner/mesh.js b/js/outliner/mesh.js index 1ed3eaa1..d9ca6300 100644 --- a/js/outliner/mesh.js +++ b/js/outliner/mesh.js @@ -235,14 +235,16 @@ class MeshFace extends Face { if (this.mesh.faces[fkey] == this) return fkey; } } - UVToLocal(uv, vertices = this.vertices) { + UVToLocal(uv, vertices = this.getSortedVertices()) { let vert_a = vertices[0]; let vert_b = vertices[1]; let vert_c = vertices[2]; + if (vertices[3]) { - let dist_1 = Math.abs(Math.pow(uv[0] - this.uv[vertices[1]][0], 2) + Math.pow(uv[1] - this.uv[vertices[1]][1], 2)); - let dist_2 = Math.abs(Math.pow(uv[0] - this.uv[vertices[3]][0], 2) + Math.pow(uv[1] - this.uv[vertices[3]][1], 2)); - if (dist_1 > dist_2) { + let is_in_tri = pointInTriangle(uv, this.uv[vert_a], this.uv[vert_b], this.uv[vert_c]); + + if (!is_in_tri) { + vert_a = vertices[0]; vert_b = vertices[2]; vert_c = vertices[3]; } diff --git a/js/util/util.js b/js/util/util.js index f7a13f13..7fdb8bf4 100644 --- a/js/util/util.js +++ b/js/util/util.js @@ -515,6 +515,19 @@ function lineIntersectsReactangle(p1, p2, rect_start, rect_end) { || intersectLines(p1, p2, [rect_end[0], rect_end[1]], [rect_end[0], rect_start[1]]) || intersectLines(p1, p2, [rect_end[0], rect_end[1]], [rect_start[0], rect_end[1]]) } +function pointInTriangle(pt, v1, v2, v3) { + function sign(p1, p2, p3) { + return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1]); + } + let d1 = sign(pt, v1, v2); + let d2 = sign(pt, v2, v3); + let d3 = sign(pt, v3, v1); + + let has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0); + let has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0); + + return !(has_neg && has_pos); +} function cameraTargetToRotation(position, target) { let spherical = new THREE.Spherical(); From 2fb1972b2cff38c14ac17a5ecdb3e6b4cd82f5ff Mon Sep 17 00:00:00 2001 From: JannisX11 Date: Sun, 9 Jul 2023 14:32:08 +0200 Subject: [PATCH 5/7] Fix #1937 Mirror modelling mesh selection issue --- js/modeling/mirror_modeling.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/js/modeling/mirror_modeling.js b/js/modeling/mirror_modeling.js index 62dc7d44..d078287d 100644 --- a/js/modeling/mirror_modeling.js +++ b/js/modeling/mirror_modeling.js @@ -78,9 +78,6 @@ const MirrorModeling = { let edit_side = MirrorModeling.getEditSide(); // Delete all vertices on the non-edit side let deleted_vertices = {}; - let selected_vertices = mesh.getSelectedVertices(true); - //let selected_vertices = mesh.getSelectedEdges(true); - let selected_faces = mesh.getSelectedFaces(true); let deleted_vertices_by_position = {}; function positionKey(position) { return position.map(p => Math.roundTo(p, 2)).join(','); From f6fb8f68c5f687520247eb27dd619b6d955baeaf Mon Sep 17 00:00:00 2001 From: JannisX11 Date: Sun, 9 Jul 2023 21:27:34 +0200 Subject: [PATCH 6/7] Fix #1936 Mirror modeling leaves element behind --- js/io/project.js | 1 + js/modeling/mirror_modeling.js | 72 +++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/js/io/project.js b/js/io/project.js index d936165e..00bb800e 100644 --- a/js/io/project.js +++ b/js/io/project.js @@ -304,6 +304,7 @@ class ModelProject { Animator.MolangParser.context = {}; scene.remove(this.model_3d); OutlinerNode.uuids = {}; + MirrorModeling.cached_elements = {}; Format = 0; Project = 0; Undo = 0; diff --git a/js/modeling/mirror_modeling.js b/js/modeling/mirror_modeling.js index d078287d..b879acae 100644 --- a/js/modeling/mirror_modeling.js +++ b/js/modeling/mirror_modeling.js @@ -16,7 +16,7 @@ const MirrorModeling = { }, createClone(original, undo_aspects) { // Create or update clone - var center = Format.centered_grid ? 0 : 8; + let center = Format.centered_grid ? 0 : 8; let mirror_element = MirrorModeling.cached_elements[original.uuid]?.counterpart; let element_before_snapshot; @@ -202,47 +202,54 @@ const MirrorModeling = { Blockbench.on('init_edit', ({aspects}) => { if (!BarItems.mirror_modeling.value) return; - if (!aspects.elements) return; - MirrorModeling.cached_elements = {}; - MirrorModeling.outliner_snapshot = aspects.outliner ? null : compileGroups(true); - let edit_side = MirrorModeling.getEditSide(); + if (aspects.elements) { + MirrorModeling.cached_elements = {}; + MirrorModeling.outliner_snapshot = aspects.outliner ? null : compileGroups(true); + let edit_side = MirrorModeling.getEditSide(); - aspects.elements.forEach((element) => { - if (element.allow_mirror_modeling) { - let is_centered = MirrorModeling.isCentered(element); + aspects.elements.forEach((element) => { + if (element.allow_mirror_modeling) { + let is_centered = MirrorModeling.isCentered(element); - let data = MirrorModeling.cached_elements[element.uuid] = {is_centered}; - if (!is_centered) { - data.is_original = Math.sign(element.getWorldCenter().x) != edit_side; - data.counterpart = Painter.getMirrorElement(element, [1, 0, 0]); - if (!data.counterpart) data.is_original = true; + let data = MirrorModeling.cached_elements[element.uuid] = {is_centered}; + if (!is_centered) { + data.is_original = Math.sign(element.getWorldCenter().x) != edit_side; + data.counterpart = Painter.getMirrorElement(element, [1, 0, 0]); + if (!data.counterpart) data.is_original = true; + } } - } - }) - - setTimeout(() => {MirrorModeling.cached_elements = {}}, 10_000); + }) + } }) Blockbench.on('finish_edit', ({aspects}) => { if (!BarItems.mirror_modeling.value) return; - if (!aspects.elements) return; - aspects.elements = aspects.elements.slice(); - let static_elements_copy = aspects.elements.slice(); - static_elements_copy.forEach((element) => { - if (element.allow_mirror_modeling) { - let is_centered = MirrorModeling.isCentered(element); + if (aspects.elements) { + aspects.elements = aspects.elements.slice(); + let static_elements_copy = aspects.elements.slice(); + static_elements_copy.forEach((element) => { + if (element.allow_mirror_modeling) { + let is_centered = MirrorModeling.isCentered(element); - if (is_centered && element instanceof Mesh) { - // Complete other side of mesh - MirrorModeling.createLocalSymmetry(element); + if (is_centered && element instanceof Mesh) { + // Complete other side of mesh + MirrorModeling.createLocalSymmetry(element); + } + if (is_centered) { + let mirror_element = MirrorModeling.cached_elements[element.uuid]?.counterpart; + if (mirror_element) { + MirrorModeling.insertElementIntoUndo(mirror_element, Undo.current_save.aspects, mirror_element.getUndoCopy()); + mirror_element.remove(); + aspects.elements.remove(mirror_element); + } + } else { + // Construct clone at other side of model + MirrorModeling.createClone(element, aspects); + } } - if (!is_centered) { - // Construct clone at other side of model - MirrorModeling.createClone(element, aspects); - } - } - }) + }) + } }) // Element property on cube and mesh @@ -256,6 +263,7 @@ BARS.defineActions(() => { category: 'edit', condition: {modes: ['edit']}, onChange() { + MirrorModeling.cached_elements = {}; updateSelection(); } }) From 0f05c2784a60a7b058540e0421608ce6a424c218 Mon Sep 17 00:00:00 2001 From: JannisX11 Date: Sun, 9 Jul 2023 23:06:39 +0200 Subject: [PATCH 7/7] Allow navigating UV editor + timeline with viewport pan key Closes #1792 --- js/animations/timeline.js | 8 ++++++-- js/interface/menu.js | 7 +++++++ js/texturing/uv.js | 10 +++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/js/animations/timeline.js b/js/animations/timeline.js index 873fff00..7217b5b5 100644 --- a/js/animations/timeline.js +++ b/js/animations/timeline.js @@ -245,8 +245,8 @@ const Timeline = { return 1/Math.clamp(Animation.selected ? Animation.selected.snapping : settings.animation_snap.value, 1, 120); }, setup() { - $('#timeline_body').on('mousedown', e => { - if (e.which === 2) { + document.getElementById('timeline_body').addEventListener('mousedown', e => { + if (e.which === 2 || Keybinds.extra.preview_drag.keybind.isTriggered(e)) { let pos = [e.clientX, e.clientY]; let timeline = e.currentTarget; function move(e2) { @@ -259,6 +259,9 @@ const Timeline = { function stop(e2) { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', stop); + if (e.which == 3 && Math.pow(e.clientX - pos[0], 2) + Math.pow(e.clientY - pos[1], 2) > 40) { + preventContextMenu(); + } } document.addEventListener('mousemove', move); document.addEventListener('mouseup', stop); @@ -583,6 +586,7 @@ const Timeline = { }, showMenu(event) { if (event.target.nodeName == 'KEYFRAME' || event.target.parentElement.nodeName == 'KEYFRAME') return; + if (Blockbench.hasFlag('no_context_menu')) return; Timeline.menu.open(event, event); }, menu: new Menu([ diff --git a/js/interface/menu.js b/js/interface/menu.js index 3a27e74c..cc9d3fac 100644 --- a/js/interface/menu.js +++ b/js/interface/menu.js @@ -646,3 +646,10 @@ class Menu { rm_item.menus.remove(scope) } } + +function preventContextMenu() { + Blockbench.addFlag('no_context_menu'); + setTimeout(() => { + Blockbench.removeFlag('no_context_menu'); + }, 20); +} diff --git a/js/texturing/uv.js b/js/texturing/uv.js index cafa262a..e2fbca6b 100644 --- a/js/texturing/uv.js +++ b/js/texturing/uv.js @@ -2275,7 +2275,7 @@ Interface.definePanels(function() { let original_margin = scope.getFrameMargin(); let offset = $(scope.$refs.viewport).offset(); UVEditor.total_zoom_offset = [6, 6]; - if (event.which === 2 || (event.touches && !Toolbox.selected.paintTool && event.target.id == 'uv_frame')) { + if (event.which === 2 || Keybinds.extra.preview_drag.keybind.isTriggered(event) || (event.touches && !Toolbox.selected.paintTool && event.target.id == 'uv_frame')) { // Drag if (event.touches) { event.clientX = event.touches[0].clientX; @@ -2285,8 +2285,8 @@ Interface.definePanels(function() { let margin = this.getFrameMargin(); let margin_center = [this.width/2, this.height/2]; let original = [ - viewport.scrollLeft, - viewport.scrollTop + viewport.scrollLeft - 5, + viewport.scrollTop - 5 ]; function dragMouseWheel(e2) { if (e2.touches) { @@ -2323,6 +2323,9 @@ Interface.definePanels(function() { function dragMouseWheelStop(e) { removeEventListeners(document, 'mousemove touchmove', dragMouseWheel); removeEventListeners(document, 'mouseup touchend', dragMouseWheelStop); + if (e.which == 3 && Math.pow(viewport.scrollLeft - original[0], 2) + Math.pow(viewport.scrollTop - original[1], 2) > 50) { + preventContextMenu(); + } } addEventListeners(document, 'mousemove touchmove', dragMouseWheel); addEventListeners(document, 'mouseup touchend', dragMouseWheelStop); @@ -2458,6 +2461,7 @@ Interface.definePanels(function() { }, contextMenu(event) { setActivePanel('uv'); + if (Blockbench.hasFlag('no_context_menu')) return; UVEditor.menu.open(event); }, selectTextureMenu(event) {