Skip to content

Commit df00e95

Browse files
committed
Add toggle for moving elements individually with position sliders
Closes JannisX11/hytale-blockbench-plugin#187
1 parent 0f9ac06 commit df00e95

6 files changed

Lines changed: 86 additions & 50 deletions

File tree

js/interface/toolbars.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,8 @@ export const BARS = {
526526
children: [
527527
'slider_pos_x',
528528
'slider_pos_y',
529-
'slider_pos_z'
529+
'slider_pos_z',
530+
'position_slider_per_element'
530531
]
531532
})
532533
Toolbars.element_size = new Toolbar({

js/modeling/transform.js

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,7 @@ export function centerElements(axis, update) {
292292
}
293293

294294
//Move
295-
export function moveElementsInSpace(difference, axis) {
296-
let space = getEditTransformSpace();
295+
export function moveElementsInSpace(difference, axis, space = getEditTransformSpace()) {
297296
let groups;
298297
if (Format.bone_rig && Group.first_selected && (Group.multi_selected.length > 1 || Group.first_selected.matchesSelection())) {
299298
groups = Group.multi_selected;
@@ -833,7 +832,36 @@ BARS.defineActions(function() {
833832
category: 'edit'
834833
})
835834

835+
function getParentTransformSpace() {
836+
if (Format.bone_rig && Group.first_selected && Group.first_selected.matchesSelection()) {
837+
if (Group.first_selected.parent instanceof Group) {
838+
return Group.first_selected.parent;
839+
} else {
840+
return 0;
841+
}
842+
}
843+
let bone = 0;
844+
if (Outliner.selected.length) {
845+
bone = Outliner.selected[0].parent;
846+
} else if (Group.first_selected && Group.first_selected.parent instanceof Group) {
847+
bone = Group.first_selected.parent;
848+
}
849+
for (var el of Outliner.selected) {
850+
if (el.parent !== bone) {
851+
bone = 0;
852+
break;
853+
}
854+
}
855+
return bone instanceof OutlinerNode ? bone : 0;
856+
}
836857
function moveOnAxis(modify, axis) {
858+
if (toggle_pos_per_element.value == false) {
859+
let old_value = getPos(axis);
860+
let new_value = modify(old_value);
861+
moveElementsInSpace(new_value - old_value, axis, getParentTransformSpace());
862+
updateSelection();
863+
return;
864+
}
837865
Outliner.selected.forEach(function(obj, i) {
838866
let space_offset = 0;
839867
if (settings.local_position_values.value &&
@@ -887,6 +915,9 @@ BARS.defineActions(function() {
887915
TickUpdates.selection = true;
888916
}
889917
function getPos(axis) {
918+
if (toggle_pos_per_element.value == false && Group.first_selected) {
919+
return Group.first_selected.origin[axis];
920+
}
890921
let element = Outliner.selected[0];
891922
let value = 0;
892923
if ((element instanceof Mesh || element instanceof SplineMesh) && element.getSelectedVertices().length) {
@@ -910,72 +941,74 @@ BARS.defineActions(function() {
910941
}
911942
return value;
912943
}
913-
new NumSlider('slider_pos_x', {
914-
name: tl('action.slider_pos', ['X']),
915-
description: tl('action.slider_pos.desc', ['X']),
916-
color: 'x',
944+
const slider_pos_common_options = {
917945
category: 'transform',
918-
condition: () => (selected.length && Modes.edit),
946+
condition: () => (Outliner.selected.length && Modes.edit),
919947
getInterval: getSpatialInterval,
920-
get: function() {
921-
return getPos(0);
922-
},
923-
change: function(modify) {
924-
moveOnAxis(modify, 0)
925-
},
926948
onBefore: function() {
927-
Undo.initEdit({elements: selected})
949+
Undo.initEdit({
950+
elements: Outliner.selected,
951+
groups: toggle_pos_per_element.value ? [] : Group.all.filter(g => g.selected)
952+
})
928953
},
929954
onAfter: function() {
930955
Undo.finishEdit('Change element position')
931956
autoFixMeshEdit()
932957
}
958+
}
959+
new NumSlider('slider_pos_x', {
960+
name: tl('action.slider_pos', ['X']),
961+
description: tl('action.slider_pos.desc', ['X']),
962+
color: 'x',
963+
get() {
964+
return getPos(0);
965+
},
966+
change(modify) {
967+
moveOnAxis(modify, 0)
968+
},
969+
...slider_pos_common_options
933970
})
934971
new NumSlider('slider_pos_y', {
935972
name: tl('action.slider_pos', ['Y']),
936973
description: tl('action.slider_pos.desc', ['Y']),
937974
color: 'y',
938-
category: 'transform',
939-
condition: () => (selected.length && Modes.edit),
940-
getInterval: getSpatialInterval,
941-
get: function() {
975+
get() {
942976
return getPos(1);
943977
},
944-
change: function(modify) {
978+
change(modify) {
945979
moveOnAxis(modify, 1)
946980
},
947-
onBefore: function() {
948-
Undo.initEdit({elements: selected})
949-
},
950-
onAfter: function() {
951-
Undo.finishEdit('Change element position')
952-
autoFixMeshEdit()
953-
}
981+
...slider_pos_common_options
954982
})
955983
new NumSlider('slider_pos_z', {
956984
name: tl('action.slider_pos', ['Z']),
957985
description: tl('action.slider_pos.desc', ['Z']),
958986
color: 'z',
959-
category: 'transform',
960-
condition: () => (selected.length && Modes.edit),
961-
getInterval: getSpatialInterval,
962-
get: function() {
987+
get() {
963988
return getPos(2);
964989
},
965-
change: function(modify) {
990+
change(modify) {
966991
moveOnAxis(modify, 2)
967992
},
968-
onBefore: function() {
969-
Undo.initEdit({elements: selected})
970-
},
971-
onAfter: function() {
972-
Undo.finishEdit('Change element position')
973-
autoFixMeshEdit()
974-
}
993+
...slider_pos_common_options
975994
})
976995
let slider_vector_pos = [BarItems.slider_pos_x, BarItems.slider_pos_y, BarItems.slider_pos_z];
977996
slider_vector_pos.forEach(slider => slider.slider_vector = slider_vector_pos);
978997

998+
let toggle_pos_per_element = new Toggle('position_slider_per_element', {
999+
icon: 'shuffle',
1000+
default: false,
1001+
category: 'transform',
1002+
condition: slider_pos_common_options.condition,
1003+
onChange() {
1004+
if (Condition(BarItems.slider_pos_x.condition)) {
1005+
BarItems.slider_pos_x.update();
1006+
BarItems.slider_pos_y.update();
1007+
BarItems.slider_pos_z.update();
1008+
}
1009+
}
1010+
})
1011+
9791012

9801013
function resizeOnAxis(modify, axis) {
9811014
Outliner.selected.forEach(function(obj, i) {

js/modeling/transform/edit_transform.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function displayDistance(number) {
66
}
77

88
export function getEditTransformSpace() {
9-
if (!selected.length && (!Group.first_selected || !Format.bone_rig)) return;
9+
if (!Outliner.selected.length && (!Group.first_selected || !Format.bone_rig)) return;
1010

1111
let input_space;
1212
switch (Toolbox.selected.id) {
@@ -17,20 +17,20 @@ export function getEditTransformSpace() {
1717

1818
if (Toolbox.selected == BarItems.rotate_tool && Format.rotation_limit) return 2;
1919

20-
if (input_space == 'local' && selected.length && selected[0].getTypeBehavior('rotatable') && (!Format.bone_rig || !Group.first_selected)) {
20+
if (input_space == 'local' && Outliner.selected.length && Outliner.selected[0].getTypeBehavior('rotatable') && (!Format.bone_rig || !Group.first_selected)) {
2121
let is_local = true;
2222
if (Format.bone_rig) {
23-
for (var el of selected) {
24-
if (el.parent !== selected[0].parent) {
23+
for (var el of Outliner.selected) {
24+
if (el.parent !== Outliner.selected[0].parent) {
2525
is_local = false;
2626
break;
2727
}
2828
}
2929
}
3030
if (is_local) {
31-
for (var el of selected) {
32-
if (el.rotation !== selected[0].rotation &&
33-
!(el.rotation instanceof Array && el.rotation.equals(selected[0].rotation))
31+
for (var el of Outliner.selected) {
32+
if (el.rotation !== Outliner.selected[0].rotation &&
33+
!(el.rotation instanceof Array && el.rotation.equals(Outliner.selected[0].rotation))
3434
) {
3535
is_local = false;
3636
break;
@@ -217,9 +217,9 @@ new TransformerModule('edit', {
217217
if (tool_id === 'resize_tool' || tool_id === 'stretch_tool') {
218218
Outliner.selected.forEach(function(obj) {
219219
if (obj instanceof Mesh || obj instanceof SplineMesh) {
220-
obj.oldVertices = {};
220+
obj.temp_data.oldVertices = {};
221221
for (let key in obj.vertices) {
222-
obj.oldVertices[key] = obj.vertices[key].slice();
222+
obj.temp_data.oldVertices[key] = obj.vertices[key].slice();
223223
}
224224
} else if (obj.getTypeBehavior('resizable')) {
225225
obj.temp_data.old_size = typeof obj.size == 'function' ? obj.size() : obj.size.slice();

js/outliner/types/mesh.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ export class Mesh extends OutlinerElement {
903903
TickUpdates.selection = true;
904904
}
905905
resize(val, axis, negative, allow_negative, bidirectional) {
906-
let source_vertices = typeof val == 'number' ? this.oldVertices : this.vertices;
906+
let source_vertices = typeof val == 'number' ? this.temp_data.oldVertices : this.vertices;
907907
let selected_vertices = Project.mesh_selection[this.uuid]?.vertices || Object.keys(this.vertices);
908908
let range = [Infinity, -Infinity];
909909
let {vec1, vec2} = Reusable;

js/outliner/types/spline_mesh.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ export class SplineMesh extends OutlinerElement {
917917
}
918918
// Taken nearly as-is from Mesh
919919
resize(val, axis, negative, allow_negative, bidirectional) {
920-
let source_vertices = typeof val == 'number' ? this.oldVertices : this.vertices;
920+
let source_vertices = typeof val == 'number' ? this.temp_data.oldVertices : this.vertices;
921921
let selected_vertices = Project.spline_selection[this.uuid]?.vertices || Object.keys(this.vertices);
922922
let range = [Infinity, -Infinity];
923923
let { vec1, vec2 } = Reusable;

lang/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,8 @@
13451345

13461346
"action.slider_pos": "Position %0",
13471347
"action.slider_pos.desc": "Move elements on the %0 axis",
1348+
"action.position_slider_per_element": "Move Individual Positions",
1349+
"action.position_slider_per_element.desc": "When enabled, using the position sliders changes individual positions per element. When disabled, the whole selection moves in the selected transform space.",
13481350
"action.slider_size": "Size %0",
13491351
"action.slider_size.desc": "Resize elements on the %0 axis",
13501352
"action.slider_inflate": "Inflate",

0 commit comments

Comments
 (0)