const ModelScaler = { dialog: new Dialog({ id: 'scale', title: 'dialog.scale.title', darken: false, buttons: ['dialog.scale.confirm', 'dialog.cancel'], lines: [ `
` ], form: { origin: {label: 'data.origin', type: 'vector', dimensions: 3, value: [0, 0, 0]}, pivot_options: {label: ' ', nocolon: true, type: 'buttons', buttons: ['dialog.scale.element_pivot', 'dialog.scale.selection_center'], click(index) { ModelScaler.setPivot(['pivot', 'selection'][index]); }}, scale: {label: '', type: 'range', min: 0, max: 4, step: 0.01, value: 1, full_width: true, editable_range_label: true}, overflow_info: { condition: () => ModelScaler.overflow, type: 'info', text: 'dialog.scale.clipping' }, select_overflow: { condition: () => ModelScaler.overflow, type: 'buttons', buttons: ['dialog.scale.select_overflow'], click() { ModelScaler.selectOverflow(); } }, box_uv_warning: { condition: (data) => data.scale !== 1 && Project.box_uv && Texture.all.length, type: 'info', text: 'dialog.scale.box_uv_warning' } }, onFormChange() { ModelScaler.scaleAll(); }, onBuild() { this.object.querySelector('#model_scale_x_axis').addEventListener('change', e => {ModelScaler.scaleAll()}); this.object.querySelector('#model_scale_y_axis').addEventListener('change', e => {ModelScaler.scaleAll()}); this.object.querySelector('#model_scale_z_axis').addEventListener('change', e => {ModelScaler.scaleAll()}); }, onOpen() { setTimeout(() => { this.object.style.top = Interface.page_wrapper.offsetTop+'px'; }, 0); }, onConfirm() { ModelScaler.scaleAll(true); }, onCancel() { ModelScaler.cancel(); } }), overflow: null, getScaleGroups() { let groups = []; if (!Format.bone_rig) return groups; if (Group.selected) { Group.selected.forEachChild((g) => { groups.push(g); }, Group) } else if (Outliner.selected.length == Outliner.elements.length && Group.all.length) { groups = Group.all; } return groups; }, scaleAll(save, size) { let data = ModelScaler.dialog.getFormResult(); if (size === undefined) size = data.scale; let {origin} = data; let axis_enabled = ['x', 'y', 'z'].map(axis => document.getElementById(`model_scale_${axis}_axis`).checked); let overflow = []; Outliner.selected.forEach(function(obj) { obj.autouv = 0; origin.forEach(function(ogn, i) { if (axis_enabled[i]) { if (obj.from) { obj.from[i] = (obj.before.from[i] - obj.inflate - ogn) * size; obj.from[i] = obj.from[i] + obj.inflate + ogn; } if (obj.to) { obj.to[i] = (obj.before.to[i] + obj.inflate - ogn) * size; obj.to[i] = obj.to[i] - obj.inflate + ogn; if (Format.integer_size) { obj.to[i] = obj.from[i] + Math.round(obj.to[i] - obj.from[i]) } } if (obj.origin) { obj.origin[i] = (obj.before.origin[i] - ogn) * size; obj.origin[i] = obj.origin[i] + ogn; } if (obj instanceof Mesh) { for (let key in obj.vertices) { obj.vertices[key][i] = obj.before.vertices[key][i] * size; } } } else { if (obj.from) obj.from[i] = obj.before.from[i]; if (obj.to) obj.to[i] = obj.before.to[i]; if (obj.origin) obj.origin[i] = obj.before.origin[i]; if (obj instanceof Mesh) { for (let key in obj.vertices) { obj.vertices[key][i] = obj.before.vertices[key][i]; } } } }) if (obj instanceof Cube && Format.cube_size_limiter) { if (Format.cube_size_limiter.test(obj)) { overflow.push(obj); } if (!settings.deactivate_size_limit.value) { Format.cube_size_limiter.clamp(obj); } } if (save === true) { delete obj.before } if (obj instanceof Cube && obj.box_uv) { Canvas.updateUV(obj) } }) ModelScaler.getScaleGroups().forEach((g) => { g.origin[0] = g.old_origin[0] * size g.origin[1] = g.old_origin[1] * size g.origin[2] = g.old_origin[2] * size if (save === true) { delete g.old_origin } }, Group) if (overflow.length && Format.cube_size_limiter && !settings.deactivate_size_limit.value) { ModelScaler.overflow = overflow; } else { ModelScaler.overflow = null; } Canvas.updateView({ elements: Outliner.selected, element_aspects: {geometry: true, transform: true}, groups: ModelScaler.getScaleGroups(), group_aspects: {transform: true}, }) if (save === true) { Undo.finishEdit('Scale model') } }, cancel() { Outliner.selected.forEach(function(obj) { if (obj === undefined) return; if (obj.from) obj.from.V3_set(obj.before.from); if (obj.to) obj.to.V3_set(obj.before.to); if (obj.origin) obj.origin.V3_set(obj.before.origin); if (obj instanceof Mesh) { for (let key in obj.vertices) { obj.vertices[key].V3_set(obj.before.vertices[key]); } } delete obj.before if (obj instanceof Cube && obj.box_uv) { Canvas.updateUV(obj) } }) ModelScaler.getScaleGroups().forEach((g) => { g.origin[0] = g.old_origin[0] g.origin[1] = g.old_origin[1] g.origin[2] = g.old_origin[2] delete g.old_origin }, Group) Canvas.updateView({ elements: Outliner.selected, element_aspects: {geometry: true, transform: true}, groups: ModelScaler.getScaleGroups(), group_aspects: {transform: true}, }) }, setPivot(mode) { let center; if (mode === 'selection') { center = getSelectionCenter() } else { center = Cube.selected[0]?.origin || Mesh.selected[0]?.origin; } if (center) { ModelScaler.dialog.setFormValues({origin: center}); } }, selectOverflow() { ModelScaler.cancel() ModelScaler.dialog.hide(); Outliner.selected.empty(); ModelScaler.overflow.forEach(obj => { obj.selectLow() }) updateSelection(); }, } BARS.defineActions(function() { new Action('scale', { icon: 'settings_overscan', category: 'transform', condition: () => (Modes.edit && Outliner.elements.length), click() { if (Outliner.selected.length == 0) { Prop.active_panel = 'preview'; selectAll(); } Undo.initEdit({elements: Outliner.selected, outliner: Format.bone_rig}); Outliner.selected.forEach((obj) => { obj.before = { from: obj.from ? obj.from.slice() : undefined, to: obj.to ? obj.to.slice() : undefined, origin: obj.origin ? obj.origin.slice() : undefined } if (obj instanceof Mesh) { obj.before.vertices = {}; for (let key in obj.vertices) { obj.before.vertices[key] = obj.vertices[key].slice(); } } }) ModelScaler.getScaleGroups().forEach((g) => { g.old_origin = g.origin.slice(); }, Group, true) ModelScaler.dialog.show(); ModelScaler.overflow = null; let v = Format.centered_grid ? 0 : 8; let origin = Group.selected ? Group.selected.origin : [v, 0, v]; ModelScaler.dialog.setFormValues({ origin, scale: 1 }); ModelScaler.scaleAll(false, 1); } }) })