mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-04-06 17:31:09 +08:00
Merge branch 'patch'
This commit is contained in:
commit
b22df10302
@ -1218,6 +1218,10 @@
|
||||
}
|
||||
|
||||
/* Placeholders */
|
||||
ul#placeholder_buttons {
|
||||
max-height: 32%;
|
||||
overflow: auto;
|
||||
}
|
||||
#placeholder_buttons li {
|
||||
padding: 0px 8px;
|
||||
height: 30px;
|
||||
|
@ -1470,8 +1470,8 @@ Interface.definePanels(function() {
|
||||
<ul id="placeholder_buttons">
|
||||
<li v-for="button in buttons" :key="button.id" :class="{placeholder_slider: button.type == 'slider'}" @click="button.type == 'impulse' && changeButtonValue(button, $event)" :buttontype="button.type">
|
||||
<i v-if="button.type == 'impulse'" class="material-icons">play_arrow</i>
|
||||
<input v-if="button.type == 'toggle'" type="checkbox" class="tab_target" :value="button.value == 1" @change="changeButtonValue(button, $event)" :id="'placeholder_button_'+button.id">
|
||||
<numeric-input v-if="button.type == 'slider'" class="dark_bordered tab_target" :step="button.step" :min="button.min" :max="button.max" v-model="button.value" @input="changeButtonValue(button, $event)" />
|
||||
<input v-if="button.type == 'toggle'" type="checkbox" :value="button.value == 1" @change="changeButtonValue(button, $event)" :id="'placeholder_button_'+button.id">
|
||||
<numeric-input v-if="button.type == 'slider'" :step="button.step" :min="button.min" :max="button.max" v-model="button.value" @input="changeButtonValue(button, $event)" />
|
||||
<label :for="'placeholder_button_'+button.id" @mousedown="slideButton(button, $event)" @touchstart="slideButton(button, $event)">{{ button.id }}</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -931,7 +931,7 @@ Interface.definePanels(() => {
|
||||
|
||||
let padding = 16;
|
||||
let min_size = 2.4;
|
||||
let unit_size = Math.clamp(max-min, min_size, 1e4);
|
||||
let unit_size = Math.clamp(max-min, min_size, Timeline.graph_editor_limit);
|
||||
this.graph_size = (clientHeight - 2*padding) / unit_size;
|
||||
let blend = Math.clamp(1 - (max-min) / min_size, 0, 1)
|
||||
this.graph_offset = clientHeight - padding + (this.graph_size * (min - unit_size/2 * blend ) );
|
||||
|
@ -310,7 +310,13 @@ Object.assign(Blockbench, {
|
||||
saveAs(blob, file_name)
|
||||
|
||||
} else {
|
||||
var blob = new Blob([options.content], {type: "text/plain;charset=utf-8"});
|
||||
let type = 'text/plain;charset=utf-8';
|
||||
if (file_name.endsWith('json')) {
|
||||
type = 'application/json;charset=utf-8';
|
||||
} else if (file_name.endsWith('bbmodel')) {
|
||||
type = 'model/vnd.blockbench.bbmodel';
|
||||
}
|
||||
var blob = new Blob([options.content], {type});
|
||||
saveAs(blob, file_name, {autoBOM: true})
|
||||
}
|
||||
|
||||
|
@ -1534,17 +1534,21 @@ class Toolbar {
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Builds the toolbar from data
|
||||
* @param {object} data Data used to build the toolbar
|
||||
* @param {boolean} force If true, customization data will be ignored. Used when resetting toolbar
|
||||
*/
|
||||
build(data, force) {
|
||||
var scope = this;
|
||||
//Items
|
||||
this.children.length = 0;
|
||||
var items = data.children
|
||||
if (!force && BARS.stored[scope.id] && typeof BARS.stored[scope.id] === 'object') {
|
||||
items = BARS.stored[scope.id]
|
||||
if (!force && BARS.stored[this.id] && typeof BARS.stored[this.id] === 'object') {
|
||||
items = BARS.stored[this.id];
|
||||
if (data.children) {
|
||||
// Add new actions to existing toolbars
|
||||
// Add new actions (newly added via bb update) to existing toolbars
|
||||
data.children.forEach((key, index) => {
|
||||
if (typeof key == 'string' && key.length > 1 && !items.includes(key) && !Keybinds.stored[key] && BarItems[key]) {
|
||||
if (typeof key == 'string' && key.length > 1 && !items.includes(key) && !Keybinds.stored[key] && BARS.stored._known?.includes(key) == false && BarItems[key]) {
|
||||
// Figure out best index based on item before. Otherwise use index from original array
|
||||
let prev_index = items.indexOf(data.children[index-1]);
|
||||
if (prev_index != -1) index = prev_index+1;
|
||||
@ -1554,7 +1558,7 @@ class Toolbar {
|
||||
}
|
||||
}
|
||||
if (items && items instanceof Array) {
|
||||
var content = $(scope.node).find('div.content')
|
||||
var content = $(this.node).find('div.content')
|
||||
content.children().detach()
|
||||
for (var itemPosition = 0; itemPosition < items.length; itemPosition++) {
|
||||
let item = items[itemPosition];
|
||||
@ -1566,7 +1570,10 @@ class Toolbar {
|
||||
|
||||
continue;
|
||||
}
|
||||
if (typeof item == 'string') item = BarItems[item]
|
||||
if (typeof item == 'string') {
|
||||
BARS.stored._known?.safePush(item);
|
||||
item = BarItems[item];
|
||||
}
|
||||
|
||||
if (item) {
|
||||
item.pushToolbar(this);
|
||||
@ -1581,8 +1588,8 @@ class Toolbar {
|
||||
}
|
||||
}
|
||||
}
|
||||
$(scope.node).toggleClass('no_wrap', this.no_wrap)
|
||||
$(scope.node).toggleClass('vertical', this.vertical)
|
||||
$(this.node).toggleClass('no_wrap', this.no_wrap)
|
||||
$(this.node).toggleClass('vertical', this.vertical)
|
||||
if (data.default_place) {
|
||||
this.toPlace(this.id)
|
||||
}
|
||||
@ -1748,7 +1755,10 @@ class Toolbar {
|
||||
}
|
||||
})
|
||||
BARS.stored[this.id] = arr;
|
||||
if (arr.equals(this.default_children)) {
|
||||
let identical_to_default = this.default_children.length == arr.length && this.default_children.allAre((item, i) => {
|
||||
return arr[i] == item || (typeof arr[i] == 'string' && arr[i].startsWith(item));
|
||||
})
|
||||
if (identical_to_default) {
|
||||
delete BARS.stored[this.id];
|
||||
}
|
||||
// Temporary fix
|
||||
@ -1779,7 +1789,9 @@ Toolbar.prototype.menu = new Menu([
|
||||
])
|
||||
|
||||
const BARS = {
|
||||
stored: {},
|
||||
stored: {
|
||||
_known: []
|
||||
},
|
||||
editing_bar: undefined,
|
||||
action_definers: [],
|
||||
condition: Condition,
|
||||
@ -2145,6 +2157,9 @@ const BARS = {
|
||||
stored = JSON.parse(stored)
|
||||
if (typeof stored === 'object') {
|
||||
BARS.stored = stored;
|
||||
if (!BARS.stored._known) {
|
||||
BARS.stored._known = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2266,9 +2281,6 @@ const BARS = {
|
||||
}
|
||||
})
|
||||
}
|
||||
Blockbench.onUpdateTo('4.4.0-beta.0', () => {
|
||||
delete BARS.stored.brush;
|
||||
})
|
||||
Toolbars.brush = new Toolbar({
|
||||
id: 'brush',
|
||||
no_wrap: true,
|
||||
|
@ -687,6 +687,7 @@ window.ToolConfig = class ToolConfig extends Dialog {
|
||||
}
|
||||
save() {
|
||||
localStorage.setItem(`tool_config.${this.id}`, JSON.stringify(this.options));
|
||||
return this;
|
||||
}
|
||||
changeOptions(options) {
|
||||
for (let key in options) {
|
||||
@ -696,6 +697,7 @@ window.ToolConfig = class ToolConfig extends Dialog {
|
||||
this.form.setValues(options);
|
||||
}
|
||||
this.save();
|
||||
return this;
|
||||
}
|
||||
close(button, event) {
|
||||
this.save();
|
||||
@ -712,6 +714,7 @@ window.ToolConfig = class ToolConfig extends Dialog {
|
||||
this.object.style.top = (anchor_position.top+anchor.offsetHeight) + 'px';
|
||||
this.object.style.left = Math.clamp(anchor_position.left - 30, 0, window.innerWidth-this.object.clientWidth - (this.title ? 0 : 30)) + 'px';
|
||||
}
|
||||
return this;
|
||||
}
|
||||
build() {
|
||||
if (this.object) this.object.remove();
|
||||
|
@ -348,8 +348,9 @@ class InputForm extends EventSystem {
|
||||
linked_ratio_toggle.addEventListener('click', event => {
|
||||
data.linked_ratio = !data.linked_ratio;
|
||||
if (data.linked_ratio) {
|
||||
updateInputs(vector_inputs[0]);
|
||||
scope.updateValues();
|
||||
initial_value = vector_inputs.map(v => v.value);
|
||||
// updateInputs(vector_inputs[0]);
|
||||
// scope.updateValues();
|
||||
}
|
||||
updateState();
|
||||
})
|
||||
|
@ -332,15 +332,11 @@ var codec = new Codec('project', {
|
||||
if (options.raw) {
|
||||
return model;
|
||||
} else if (options.compressed) {
|
||||
var json_string = JSON.stringify(model);
|
||||
var json_string = compileJSON(model, {small: true});
|
||||
var compressed = '<lz>'+LZUTF8.compress(json_string, {outputEncoding: 'StorageBinaryString'});
|
||||
return compressed;
|
||||
} else {
|
||||
if (Settings.get('minify_bbmodel') || options.minify) {
|
||||
return JSON.stringify(model);
|
||||
} else {
|
||||
return compileJSON(model);
|
||||
}
|
||||
return compileJSON(model, {small: Settings.get('minify_bbmodel') || options.minify});
|
||||
}
|
||||
},
|
||||
parse(model, path) {
|
||||
|
@ -1051,6 +1051,7 @@ function getFormatVersion() {
|
||||
}
|
||||
}
|
||||
for (let cube of Cube.all) {
|
||||
if (cube.box_uv) continue;
|
||||
for (let fkey in cube.faces) {
|
||||
if (cube.faces[fkey].rotation) return '1.21.0';
|
||||
}
|
||||
|
@ -2589,6 +2589,88 @@ skin_presets.cow = {
|
||||
]
|
||||
}`
|
||||
};
|
||||
skin_presets.creaking = {
|
||||
display_name: 'Creaking',
|
||||
model: `{
|
||||
"name": "creaking",
|
||||
"texturewidth": 64,
|
||||
"textureheight": 64,
|
||||
"eyes": [
|
||||
[6, 8, 3, 1],
|
||||
[9, 10, 3, 1],
|
||||
[7, 13, 3, 1]
|
||||
],
|
||||
"bones": [
|
||||
{
|
||||
"name": "root",
|
||||
"pivot": [0, 0, 0]
|
||||
},
|
||||
{
|
||||
"name": "upperBody",
|
||||
"parent": "root",
|
||||
"pivot": [-1, 19, 0]
|
||||
},
|
||||
{
|
||||
"name": "head",
|
||||
"parent": "upperBody",
|
||||
"pivot": [-4, 30, 0],
|
||||
"cubes": [
|
||||
{"origin": [-7, 30, -3], "size": [6, 10, 6], "uv": [0, 0]},
|
||||
{"origin": [-7, 40, -3], "size": [6, 3, 6], "uv": [28, 31]},
|
||||
{"origin": [-1, 29, 0], "size": [9, 14, 0], "uv": [12, 40]},
|
||||
{"origin": [-16, 30, 0], "size": [9, 14, 0], "uv": [34, 12]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"parent": "upperBody",
|
||||
"pivot": [-1, 26, 1],
|
||||
"cubes": [
|
||||
{"origin": [-1, 16, -2], "size": [6, 13, 5], "uv": [0, 16]},
|
||||
{"origin": [-7, 23, -2], "size": [6, 7, 5], "uv": [24, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rightArm",
|
||||
"parent": "upperBody",
|
||||
"pivot": [-8, 28.5, 1.5],
|
||||
"cubes": [
|
||||
{"origin": [-10, 9, 0], "size": [3, 21, 3], "uv": [22, 13]},
|
||||
{"origin": [-10, 5, 0], "size": [3, 4, 3], "uv": [46, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "leftArm",
|
||||
"parent": "upperBody",
|
||||
"pivot": [5, 28, 0.5],
|
||||
"cubes": [
|
||||
{"origin": [5, 13, -1], "size": [3, 16, 3], "uv": [30, 40]},
|
||||
{"origin": [5, 29, -1], "size": [3, 4, 3], "uv": [52, 12]},
|
||||
{"origin": [5, 9, -1], "size": [3, 4, 3], "uv": [52, 19]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "leftLeg",
|
||||
"parent": "root",
|
||||
"pivot": [1.5, 16, 0.5],
|
||||
"cubes": [
|
||||
{"origin": [0, 0, -1], "size": [3, 16, 3], "uv": [42, 40]},
|
||||
{"origin": [0, 0.3, -4], "size": [5, 0, 9], "uv": [45, 55]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rightLeg",
|
||||
"parent": "root",
|
||||
"pivot": [-1, 17.5, 0.5],
|
||||
"cubes": [
|
||||
{"origin": [-4, 0, -1], "size": [3, 19, 3], "uv": [0, 34]},
|
||||
{"origin": [-6, 0.3, -4], "size": [5, 0, 9], "uv": [45, 46]},
|
||||
{"origin": [-4, 19, -1], "size": [3, 3, 3], "uv": [12, 34]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`
|
||||
};
|
||||
skin_presets.creeper = {
|
||||
display_name: 'Creeper',
|
||||
model: `{
|
||||
|
@ -2208,9 +2208,9 @@ BARS.defineActions(function() {
|
||||
Mesh.selected.forEach(mesh => {
|
||||
let original_vertices = mesh.getSelectedVertices().slice();
|
||||
let selected_edges = mesh.getSelectedEdges(true);
|
||||
let selected_face_keys = mesh.getSelectedFaces();
|
||||
let new_vertices;
|
||||
let new_face_keys = [];
|
||||
let selected_face_keys = mesh.getSelectedFaces();
|
||||
if (original_vertices.length && (BarItems.selection_mode.value == 'vertex' || BarItems.selection_mode.value == 'edge')) {
|
||||
selected_face_keys.empty();
|
||||
}
|
||||
@ -2379,13 +2379,13 @@ BARS.defineActions(function() {
|
||||
if (vertices.length == 2) delete mesh.faces[selected_face_keys[face_index]];
|
||||
})
|
||||
|
||||
// Create Face between extruded edges
|
||||
// Create Faces for extruded edges
|
||||
let new_faces = [];
|
||||
selected_edges.forEach(edge => {
|
||||
let face, sorted_vertices;
|
||||
for (let fkey in mesh.faces) {
|
||||
let face2 = mesh.faces[fkey];
|
||||
let vertices = face2.getSortedVertices();
|
||||
let vertices = face2.vertices;
|
||||
if (vertices.includes(edge[0]) && vertices.includes(edge[1])) {
|
||||
face = face2;
|
||||
sorted_vertices = vertices;
|
||||
@ -2400,6 +2400,9 @@ BARS.defineActions(function() {
|
||||
let new_face = new MeshFace(mesh, face).extend({
|
||||
vertices: [a, b, c, d]
|
||||
});
|
||||
if (new_face.getAngleTo(face) > 90) {
|
||||
new_face.invert();
|
||||
}
|
||||
let [face_key] = mesh.addFaces(new_face);
|
||||
new_face_keys.push(face_key);
|
||||
new_faces.push(new_face);
|
||||
|
@ -296,8 +296,14 @@ const MirrorModeling = {
|
||||
[new_face_key] = mesh.addFaces(new_face);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
let selected_vertices = mesh.getSelectedVertices(true);
|
||||
selected_vertices.replace(selected_vertices.filter(vkey => mesh.vertices[vkey]));
|
||||
let selected_edges = mesh.getSelectedEdges(true);
|
||||
selected_edges.replace(selected_edges.filter(edge => edge.allAre(vkey => mesh.vertices[vkey])));
|
||||
let selected_faces = mesh.getSelectedFaces(true);
|
||||
selected_faces.replace(selected_faces.filter(fkey => mesh.faces[fkey]));
|
||||
|
||||
let {preview_controller} = mesh;
|
||||
preview_controller.updateGeometry(mesh);
|
||||
preview_controller.updateFaces(mesh);
|
||||
|
@ -25,8 +25,7 @@ class Collection {
|
||||
if (Modes.animate && Animation.selected && !(event?.ctrlOrCmd || Pressing.overrides.ctrl)) {
|
||||
Timeline.animators.empty();
|
||||
}
|
||||
for (let uuid of this.children) {
|
||||
let node = OutlinerNode.uuids[uuid];
|
||||
for (let node of this.getChildren()) {
|
||||
if (Modes.animate && Animation.selected) {
|
||||
if (node.constructor.animator) {
|
||||
let animator = Animation.selected.getBoneAnimator(node);
|
||||
|
@ -563,7 +563,7 @@ new Property(Group, 'string', 'bedrock_binding', {condition: {formats: ['bedrock
|
||||
new Property(Group, 'array', 'cem_animations', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'boolean', 'cem_attach', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'number', 'cem_scale', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'string', 'texture', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'string', 'texture', {condition: {features: ['per_group_texture']}});
|
||||
//new Property(Group, 'vector2', 'texture_size', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'vector', 'skin_original_origin', {condition: {formats: ['skin']}});
|
||||
new Property(Group, 'number', 'color');
|
||||
|
@ -1136,6 +1136,10 @@ new NodePreviewController(Mesh, {
|
||||
|
||||
Mesh.preview_controller.updatePixelGrid(element);
|
||||
|
||||
if (Project.view_mode == 'wireframe' && this.fixWireframe) {
|
||||
this.fixWireframe(element);
|
||||
}
|
||||
|
||||
this.dispatchEvent('update_geometry', {element});
|
||||
},
|
||||
updateFaces(element) {
|
||||
@ -1447,5 +1451,20 @@ new NodePreviewController(Mesh, {
|
||||
mesh.add(box);
|
||||
|
||||
this.dispatchEvent('update_painting_grid', {element});
|
||||
},
|
||||
fixWireframe(element) {
|
||||
let geometry_orig = element.mesh.geometry;
|
||||
if (!geometry_orig) return;
|
||||
let geometry_clone = element.mesh.geometry.clone();
|
||||
element.mesh.geometry = geometry_clone;
|
||||
geometry_orig.dispose();
|
||||
}
|
||||
})
|
||||
|
||||
Blockbench.dispatchEvent('change_view_mode', ({view_mode}) => {
|
||||
if (view_mode == 'wireframe') {
|
||||
for (let mesh of Mesh.selected) {
|
||||
Mesh.preview_controller.fixWireframe(mesh);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -854,7 +854,9 @@ function moveOutlinerSelectionTo(item, target, event, order) {
|
||||
Outliner.root.forEach(node => {
|
||||
if (node instanceof Group) {
|
||||
node.forEachChild(child => {
|
||||
if (child.selected && !child.parent.selected) items.push(child);
|
||||
if (child.selected && !child.parent.selected && !target.isChildOf?.(child)) {
|
||||
items.push(child);
|
||||
}
|
||||
}, null, true);
|
||||
} else if (node.selected) {
|
||||
items.push(node);
|
||||
@ -884,6 +886,9 @@ function moveOutlinerSelectionTo(item, target, event, order) {
|
||||
}
|
||||
} else {
|
||||
item.preview_controller.updateTransform(item);
|
||||
if (Format.per_group_texture && item.preview_controller.updateFaces) {
|
||||
item.preview_controller.updateFaces(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2209,6 +2209,7 @@ BARS.defineActions(function() {
|
||||
material: {name: true, icon: 'pages', condition: () => ((!Toolbox.selected.allowed_view_modes || Toolbox.selected.allowed_view_modes.includes('material')) && TextureGroup.all.find(tg => tg.is_material))},
|
||||
},
|
||||
onChange() {
|
||||
let previous_view_mode = Project.view_mode;
|
||||
Project.view_mode = this.value;
|
||||
Canvas.updateViewMode();
|
||||
if (Modes.id === 'animate') {
|
||||
@ -2221,6 +2222,9 @@ BARS.defineActions(function() {
|
||||
if (icon_node) icon_node.replaceWith(icon);
|
||||
}
|
||||
})
|
||||
if (Project.view_mode != previous_view_mode) {
|
||||
Blockbench.dispatchEvent('change_view_mode', {view_mode: Project.view_mode, previous_view_mode});
|
||||
}
|
||||
//Blockbench.showQuickMessage(tl('action.view_mode') + ': ' + tl('action.view_mode.' + this.value));
|
||||
}
|
||||
})
|
||||
|
@ -349,14 +349,19 @@ class ReferenceImage {
|
||||
(e2.clientX - e1.clientX) * multiplier,
|
||||
(e2.clientY - e1.clientY) * multiplier,
|
||||
];
|
||||
this.size[0] = Math.max(original_size[0] + offset[0] * sign_x, 48);
|
||||
let zoom_level = this.getZoomLevel();
|
||||
let max_size = [
|
||||
32 / zoom_level,
|
||||
24 / zoom_level
|
||||
];
|
||||
this.size[0] = Math.max(original_size[0] + offset[0] * sign_x, max_size[0]);
|
||||
this.position[0] = original_position[0] + offset[0] / 2, 0;
|
||||
|
||||
if (!e2.ctrlOrCmd && !Pressing.overrides.ctrl) {
|
||||
offset[1] = sign_y * (this.size[0] / this.aspect_ratio - original_size[1]);
|
||||
}
|
||||
|
||||
this.size[1] = Math.max(original_size[1] + offset[1] * sign_y, 32);
|
||||
this.size[1] = Math.max(original_size[1] + offset[1] * sign_y, max_size[1]);
|
||||
this.position[1] = original_position[1] + offset[1] / 2, 0;
|
||||
|
||||
if (this.layer !== 'blueprint') {
|
||||
|
@ -4225,7 +4225,15 @@ Interface.definePanels(function() {
|
||||
startInputMaterialInstance(event) {
|
||||
Undo.initEdit({elements: Cube.selected, uv_only: true})
|
||||
},
|
||||
endInputMaterialInstance(event) {
|
||||
endInputMaterialInstance(event, fkey) {
|
||||
let value = this.mappable_elements[0]?.faces[fkey]?.material_name;
|
||||
if (typeof value == 'string') {
|
||||
for (let element of this.mappable_elements) {
|
||||
if (element.faces[fkey]) {
|
||||
element.faces[fkey].material_name = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Undo.finishEdit('Change material instances');
|
||||
},
|
||||
showInfoBox(title, text) {
|
||||
@ -4329,7 +4337,7 @@ Interface.definePanels(function() {
|
||||
title="${tl('uv_editor.face_properties.material_instance')}"
|
||||
v-model="mappable_elements[0].faces[key].material_name"
|
||||
@focus="startInputMaterialInstance($event)"
|
||||
@focusout="endInputMaterialInstance($event)"
|
||||
@focusout="endInputMaterialInstance($event, key)"
|
||||
>
|
||||
</template>
|
||||
</li>
|
||||
|
48
js/undo.js
48
js/undo.js
@ -77,7 +77,7 @@ class UndoSystem {
|
||||
return entry;
|
||||
}
|
||||
initSelection(aspects) {
|
||||
if (!settings.undo_selections.value || Blockbench.hasFlag('loading_selection_save')) return;
|
||||
if (!settings.undo_selections.value || Blockbench.hasFlag('loading_selection_save') || Project.EditSession) return;
|
||||
|
||||
if (this.current_selection_save) return;
|
||||
this.current_selection_save = new UndoSystem.selectionSave(aspects);
|
||||
@ -85,7 +85,7 @@ class UndoSystem {
|
||||
return this.current_selection_save;
|
||||
}
|
||||
finishSelection(message, aspects) {
|
||||
if (!settings.undo_selections.value || Blockbench.hasFlag('loading_selection_save')) return;
|
||||
if (!settings.undo_selections.value || Blockbench.hasFlag('loading_selection_save') || Project.EditSession) return;
|
||||
|
||||
if (!this.current_selection_save) return;
|
||||
aspects = aspects || this.current_selection_save.aspects;
|
||||
@ -192,10 +192,14 @@ class UndoSystem {
|
||||
this.index--;
|
||||
|
||||
var entry = this.history[this.index];
|
||||
if (entry.before) entry.before.load(entry.post);
|
||||
if (entry.selection_before) entry.selection_before.load(entry.selection_post);
|
||||
if (Project.EditSession && remote !== true) {
|
||||
Project.EditSession.sendAll('command', 'undo')
|
||||
if (entry.before) {
|
||||
this.loadSave(entry.before, entry.post);
|
||||
}
|
||||
if (entry.selection_before instanceof UndoSystem.selectionSave) {
|
||||
entry.selection_before.load(entry.selection_post);
|
||||
}
|
||||
if (Project.EditSession && remote !== true && entry.type != 'selection') {
|
||||
Project.EditSession.sendAll('command', 'undo');
|
||||
}
|
||||
Blockbench.dispatchEvent('undo', {entry})
|
||||
}
|
||||
@ -209,15 +213,19 @@ class UndoSystem {
|
||||
|
||||
var entry = this.history[this.index]
|
||||
this.index++;
|
||||
if (entry.post) entry.post.load(entry.before);
|
||||
if (entry.selection_post) entry.selection_post.load(entry.selection_before);
|
||||
if (Project.EditSession && remote !== true) {
|
||||
Project.EditSession.sendAll('command', 'redo')
|
||||
if (entry.post) {
|
||||
this.loadSave(entry.post, entry.before);
|
||||
}
|
||||
if (entry.selection_post instanceof UndoSystem.selectionSave) {
|
||||
entry.selection_post.load(entry.selection_before);
|
||||
}
|
||||
if (Project.EditSession && remote !== true && entry.type != 'selection') {
|
||||
Project.EditSession.sendAll('command', 'redo');
|
||||
}
|
||||
Blockbench.dispatchEvent('redo', {entry})
|
||||
}
|
||||
remoteEdit(entry) {
|
||||
this.loadSave(entry.post, entry.before, 'session')
|
||||
this.loadSave(entry.post, entry.before, 'session');
|
||||
|
||||
if (entry.save_history !== false) {
|
||||
delete this.current_save;
|
||||
@ -242,12 +250,23 @@ class UndoSystem {
|
||||
return false;
|
||||
}
|
||||
loadSave(save, reference, mode) {
|
||||
if (save instanceof UndoSystem.save == false) {
|
||||
save = new UndoSystem.save().fromJSON(save);
|
||||
}
|
||||
save.load(reference, mode);
|
||||
}
|
||||
}
|
||||
UndoSystem.save = class {
|
||||
constructor(aspects) {
|
||||
|
||||
if (aspects) {
|
||||
this.fromState(aspects);
|
||||
}
|
||||
}
|
||||
fromJSON(data) {
|
||||
Object.assign(this, data);
|
||||
return this;
|
||||
}
|
||||
fromState(aspects) {
|
||||
var scope = this;
|
||||
this.aspects = aspects;
|
||||
|
||||
@ -380,6 +399,7 @@ UndoSystem.save = class {
|
||||
}
|
||||
|
||||
Blockbench.dispatchEvent('create_undo_save', {save: this, aspects})
|
||||
return this;
|
||||
}
|
||||
load(reference, mode) {
|
||||
let is_session = mode === 'session';
|
||||
@ -803,7 +823,7 @@ UndoSystem.selectionSave = class {
|
||||
if (element instanceof Mesh) {
|
||||
this.geometry[element.uuid] = {
|
||||
faces: element.getSelectedFaces().slice(),
|
||||
edges: element.getSelectedEdges().slice(),
|
||||
edges: element.getSelectedEdges().map(edge => edge.slice()),
|
||||
vertices: element.getSelectedVertices().slice(),
|
||||
}
|
||||
} else if (element instanceof Cube && !element.box_uv) {
|
||||
@ -854,7 +874,7 @@ UndoSystem.selectionSave = class {
|
||||
|
||||
unselectAllElements();
|
||||
if (this.elements) {
|
||||
Outliner.selected.replace(this.elements.map(uuid => OutlinerNode.uuids[uuid]));
|
||||
Outliner.selected.replace(this.elements.map(uuid => OutlinerNode.uuids[uuid]).filter(element => element instanceof OutlinerElement));
|
||||
}
|
||||
if (this.groups) {
|
||||
for (let uuid of this.groups) {
|
||||
|
@ -111,6 +111,7 @@ Object.defineProperty(Array.prototype, "equals", {enumerable: false});
|
||||
//Array Vector
|
||||
Array.prototype.V3_set = function(x, y, z) {
|
||||
if (x instanceof Array) return this.V3_set(...x);
|
||||
if (x instanceof THREE.Vector3) return this.V3_set(x.x, x.y, x.z);
|
||||
if (y === undefined && z === undefined) z = y = x;
|
||||
this[0] = parseFloat(x)||0;
|
||||
this[1] = parseFloat(y)||0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user