From 271a46bdb1e71c2df8bcf1e87d1e7edfc26ecb16 Mon Sep 17 00:00:00 2001 From: JannisX11 Date: Thu, 23 Jan 2020 18:53:36 +0100 Subject: [PATCH] v3.3.0 --- .travis.yml | 8 + css/dialogs.css | 10 + css/general.css | 34 +- css/panels.css | 141 +- css/setup.css | 35 + index.html | 45 +- js/animations.js | 602 ++++-- js/api.js | 50 +- js/blockbench.js | 104 +- js/copy_paste.js | 15 +- js/display_mode.js | 33 +- js/interface/actions.js | 42 +- js/interface/dialog.js | 14 + js/interface/interface.js | 4 +- js/interface/menu.js | 34 +- js/io/bbmodel.js | 8 +- js/io/bedrock.js | 13 +- js/io/io.js | 27 +- js/io/java_block.js | 7 + js/io/modded_entity.js | 8 +- js/io/obj.js | 4 +- js/io/optifine_jpm.js | 1 + js/io/skin.js | 4219 +++++++++++++++++++++++++++++++++++++ js/outliner/cube.js | 17 +- js/outliner/outliner.js | 26 +- js/plugin_loader.js | 3 +- js/preview/preview.js | 63 +- js/preview/transformer.js | 83 +- js/texturing/color.js | 30 +- js/texturing/painter.js | 345 +-- js/texturing/textures.js | 25 +- js/texturing/uv.js | 169 +- js/transform.js | 24 +- js/util.js | 3 +- lang/de.json | 27 +- lang/en.json | 27 + lang/es.json | 27 +- lang/fr.json | 37 +- lang/it.json | 27 +- lang/ja.json | 343 +-- lang/nl.json | 27 +- lang/pl.json | 27 +- lang/pt.json | 409 ++-- lang/ru.json | 27 +- lang/sv.json | 27 +- lang/zh.json | 75 +- lib/three_custom.js | 1 + package.json | 9 +- 48 files changed, 6330 insertions(+), 1006 deletions(-) create mode 100644 js/io/skin.js diff --git a/.travis.yml b/.travis.yml index 32f881a52..b9f200e67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,14 @@ matrix: os: osx script: electron-builder -w --x64 --publish=always + - name: "Windows 32" + os: osx + script: electron-builder -w --ia32 --publish=always -c.productName='Blockbench_32bit' + + - name: "Windows Portable" + os: osx + script: electron-builder --windows portable --x64 --publish=always -c.productName='Blockbench_portable' + - name: "Linux" os: linux script: diff --git a/css/dialogs.css b/css/dialogs.css index 734516cee..8d8a49748 100644 --- a/css/dialogs.css +++ b/css/dialogs.css @@ -156,6 +156,16 @@ dialog .form_bar_file:hover > .material-icons { opacity: 1; } + dialog .form_bar_radio { + display: flex; + } + dialog .form_bar_radio:hover { + color: var(--color-light); + } + dialog .form_bar_radio label { + flex-grow: 1; + padding: 3px 5px; + } /*Settings Dialog*/ dialog#settings { diff --git a/css/general.css b/css/general.css index 55be1b37d..182a37021 100644 --- a/css/general.css +++ b/css/general.css @@ -55,13 +55,13 @@ font-size: 0.94em; } .color_x { - color: #d50a0a; + color: var(--color-axis-x); } .color_y { - color: #23d400; + color: var(--color-axis-y); } .color_z { - color: #0894ed; + color: var(--color-axis-z); } .button { display: inline-block; @@ -224,6 +224,28 @@ margin-right: 6px; } + .annotation { + min-width: 40px; + max-width: 100%; + width: max-content; + position: absolute; + text-align: center; + background-color: var(--color-bright_ui); + color: var(--color-accent_text); + padding: 3px 8px; + pointer-events: none; + } + .annotation.transparent { + background: transparent; + font-weight: normal; + font-size: 1.2em; + padding: 0; + margin: -4px; + min-width: 15px; + color: var(--color-light); + text-shadow: 0 0 5px black; + } + .spinning { -webkit-animation: spin 2s linear infinite; -moz-animation: spin 2s linear infinite; @@ -239,7 +261,7 @@ } li.menu_bar_point { font-size: 17px; - padding: 0 10px; + padding: 0 8px; padding-top: 2px; display: inline-block; height: 100%; @@ -380,7 +402,9 @@ width: 100%; } .bar_select .bar_select_wrapper::before { - content: "\23F7"; + content: "\f0d7"; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; display: block; position: absolute; height: 12px; diff --git a/css/panels.css b/css/panels.css index e2a53e344..92378ea4d 100644 --- a/css/panels.css +++ b/css/panels.css @@ -86,11 +86,13 @@ width: 100%; overflow: hidden; position: absolute; + cursor: inherit; } .quad_canvas_wrapper { height: 50%; width: 50%; position: absolute; + cursor: inherit; } .quad_canvas_wrapper.qcw_x { border-right: 2px solid var(--color-grid); @@ -300,16 +302,14 @@ } } -/*Displaytabs*/ +/*Display*/ .tabs_small input[type="radio"]:checked+label { border-bottom: 3px solid var(--color-accent); } - .tabs_small input[type="radio"] { display: none; } - .tabs_small label { display: inline-block; height: 30px; @@ -326,33 +326,72 @@ div.tabs_small:not(.icon_bar) label { padding-top: 4px; } - .tabs_small { background-color: transparent; height: 30px; display: flex; } - .tabs_small label:hover { color: var(--color-light); } #display_sliders p { margin-top: 6px; } - -/*Bars*/ + #display_bar .tool, #display_ref_bar > div { + width: calc(100% / 8 - 2px); + max-width: 52px; + } + #display_ref_bar > div > label { + width: 100%; + } + .bar.slider_input_combo { + position: relative; + display: flex; + } .bar.slider_input_combo input.tool[type="range"] { - width: calc(100% - 67px); float: none; + flex-grow: 1; + flex-shrink: 1; } .bar.slider_input_combo input.tool[type="number"] { - margin-left: -2px; width: 60px; background-color: var(--color-back); float: none; + flex-grow: 0; + flex-shrink: 0; + } + + input#preset_name { + background-color: var(--color-back); + } + #create_preset .dialog_bar > * { + float: left; + margin-left: 8px; + } + #display_settings p { + padding-left: 6px; + } + div#display_crosshair:after { + content: ""; + width: 20px; + height: 2px; + background-color: var(--color-grid); + position: absolute; + margin-left: -9px; + margin-top: 9px; + } + div#display_crosshair { + width: 2px; + height: 20px; + background-color: var(--color-grid); + position: absolute; + top: calc(50% - 10px); + margin-left: 50%; + margin-right: auto; } + /*Outliner*/ #cubes_list { padding-top: 1px; @@ -638,7 +677,7 @@ height: 30px; width: 25%; } - .panel#keyframe .bar label { + .panel .bar.flex label { margin: 3px 8px; min-width: 20px; text-align: center; @@ -663,7 +702,30 @@ background-color: var(--color-back); height: calc(100% - 30px); } - #timeline_marker { + .timeline_marker { + position: absolute; + margin-left: -9px; + z-index: 5; + height: 10px; + width: 20px; + } + .timeline_marker::before { + content: ""; + position: absolute; + border-style: solid; + border-bottom-color: transparent !important; + border-left-color: transparent !important; + border-right-color: transparent !important; + border-width: 10px; + border-radius: 3px; + pointer-events: none; + border-color: inherit; + } + .timeline_marker:hover::before { + border-width: 11px; + margin-left: -1px; + } + #timeline_playhead { position: absolute; pointer-events: none; height: 26px; @@ -675,7 +737,7 @@ background-color: rgba(0, 0, 0, 0.2); z-index: 3; } - #timeline_marker_line { + #timeline_playhead_line { content: ""; display: block; position: absolute; @@ -865,6 +927,10 @@ margin-bottom: 0; position: relative; } + + body[mode=paint] #uv_frame { + cursor: crosshair !important; + } #uv_frame > img { position: absolute; pointer-events: none; @@ -872,6 +938,17 @@ height: 100%; top: 0; left: 0; + object-fit: cover; + object-position: 0 0; + } + div#uv_brush_outline { + border: 1px solid white; + width: 0; + height: 0; + border-radius: 50%; + position: absolute; + pointer-events: none; + mix-blend-mode: difference; } .uv_mapping_overlay { position: absolute; @@ -1016,46 +1093,6 @@ color: var(--color-light); } -/*Display*/ - #display_bar .tool, #display_ref_bar > div { - width: calc(100% / 8 - 2px); - max-width: 52px; - } - #display_ref_bar > div > label { - width: 100%; - } - .bar .tool.disp_range.scaleRange { - max-width: calc(100% - 109px); - } - input#preset_name { - background-color: var(--color-back); - } - #create_preset .dialog_bar > * { - float: left; - margin-left: 8px; - } - #display_settings p { - padding-left: 6px; - } - div#display_crosshair:after { - content: ""; - width: 20px; - height: 2px; - background-color: var(--color-grid); - position: absolute; - margin-left: -9px; - margin-top: 9px; - } - div#display_crosshair { - width: 2px; - height: 20px; - background-color: var(--color-grid); - position: absolute; - top: calc(50% - 10px); - margin-left: 50%; - margin-right: auto; - } - /*Color*/ .panel#color { diff --git a/css/setup.css b/css/setup.css index e5f6587d1..65c3b4400 100644 --- a/css/setup.css +++ b/css/setup.css @@ -309,6 +309,9 @@ --color-checkerboard: #2f3339; --color-close: #d62e3f; + --color-axis-x: #d50a0a; + --color-axis-y: #23d400; + --color-axis-z: #0894ed; --font-custom-main: ''; --font-custom-headline: ''; @@ -412,6 +415,10 @@ padding-left: 16px; font-weight: normal; } + button.disabled { + opacity: 0.5; + pointer-events: none; + } button:hover { background: var(--color-accent); color: var(--color-accent_text) !important; @@ -495,6 +502,19 @@ input[type=checkbox][disabled=disabled] { opacity: 0.6; } + input[type=radio]::before { + content: "\f111"; + font-family: 'Font Awesome 5 Free'; + font-weight: 300; + font-size: 15pt; + } + input[type=radio]:checked::before { + content: "\f192"; + } + input[type=radio][disabled=disabled] { + opacity: 0.6; + } + div.nslide { height: 28px; width: 100%; @@ -506,6 +526,21 @@ outline: none; background-color: var(--color-button); } + .tool.nslide_tool .nslide_overlay { + width: 100%; + position: relative; + pointer-events: none; + } + .color_corner { + position: absolute; + top: 0; + right: 0; + border-width: 4px; + border-style: solid; + border-color: transparent; + border-bottom-color: transparent !important; + border-left-color: transparent !important; + } #nslide_head { margin-top: 30px; color: var(--color-light); diff --git a/index.html b/index.html index 71e1c4e08..ab6376d1a 100644 --- a/index.html +++ b/index.html @@ -28,7 +28,7 @@ @@ -99,6 +99,7 @@ + @@ -773,23 +774,27 @@

dialog.settings.about

display.rotation

replay
-
- +
+ +

display.translation

replay
-
+
+

display.scale

replay
-
+
display.mirror
{{ slot.mirror[axis] ? 'check_box' : 'check_box_outline_blank' }} @@ -800,6 +805,7 @@

dialog.settings.about

step="0.01" value="0" @input="change(axis, 'scale')" @mousedown="start" @change="save"> +
@@ -829,15 +835,15 @@

dialog.settings.about

- +
- +
- +
@@ -852,6 +858,10 @@

dialog.settings.about

+
+ + +
@@ -924,8 +934,6 @@

dialog.settings.about

:key="color" v-bind:style="{'background-color': color}" v-bind:title="color" @click="setColor(color)" - @mousemove="hover_color = color" - @mouseleave="hover_color = ''" >
@@ -997,16 +1005,23 @@

dialog.settings.about

{{ t.text }}
-
+
-
  • @@ -1045,7 +1060,7 @@

    dialog.settings.about

    v-bind:class="[keyframe.channel, keyframe.selected?'selected':'']" v-bind:id="keyframe.uuid" v-on:click.stop="keyframe.select($event)" - v-on:dblclick="keyframe.callMarker()" + v-on:dblclick="keyframe.callPlayhead()" :title="tl('timeline.'+keyframe.channel)" @contextmenu.prevent="keyframe.showContextMenu($event)" > diff --git a/js/animations.js b/js/animations.js index 32e8dc3e4..8741c7e12 100644 --- a/js/animations.js +++ b/js/animations.js @@ -9,6 +9,7 @@ class Animation { this.anim_time_update = ''; this.length = 0; this.animators = {}; + this.markers = []; if (typeof data === 'object') { this.extend(data) } @@ -22,7 +23,7 @@ class Animation { if (data.bones && !data.animators) { data.animators = data.bones; } - if (data.animators) { + if (data.animators instanceof Object) { for (var key in data.animators) { var group = Group.all.findInArray( isUUID(key) ? 'uuid' : 'name', key ) if (group) { @@ -39,6 +40,11 @@ class Animation { } } } + if (data.markers instanceof Array) { + data.markers.forEach(marker => { + this.markers.push(new TimelineMarker(marker)); + }) + } return this; } getUndoCopy(options, save) { @@ -80,6 +86,7 @@ class Animation { }) Timeline.animators.purge(); Timeline.selected.empty(); + Timeline.vue._data.markers = this.markers; this.selected = true; this.playing = true; Animator.selected = this; @@ -240,6 +247,41 @@ class Animation { delete */ ]) +class TimelineMarker { + constructor(data) { + this.time = 0; + this.color = 0; + if (data) { + this.extend(data); + } + } + extend(data) { + Merge.number(this, data, 'color'); + Merge.number(this, data, 'time'); + } + callPlayhead() { + Timeline.setTime(this.time) + Animator.preview() + return this; + } + showContextMenu(event) { + this.menu.open(event, this); + return this; + } +} + TimelineMarker.prototype.menu = new Menu([ + {icon: 'flag', color: markerColors[0].standard, name: 'cube.color.'+markerColors[0].name, click: function(marker) {marker.color = 0;}}, + {icon: 'flag', color: markerColors[1].standard, name: 'cube.color.'+markerColors[1].name, click: function(marker) {marker.color = 1;}}, + {icon: 'flag', color: markerColors[2].standard, name: 'cube.color.'+markerColors[2].name, click: function(marker) {marker.color = 2;}}, + {icon: 'flag', color: markerColors[3].standard, name: 'cube.color.'+markerColors[3].name, click: function(marker) {marker.color = 3;}}, + {icon: 'flag', color: markerColors[4].standard, name: 'cube.color.'+markerColors[4].name, click: function(marker) {marker.color = 4;}}, + {icon: 'flag', color: markerColors[5].standard, name: 'cube.color.'+markerColors[5].name, click: function(marker) {marker.color = 5;}}, + {icon: 'flag', color: markerColors[6].standard, name: 'cube.color.'+markerColors[6].name, click: function(marker) {marker.color = 6;}}, + {icon: 'flag', color: markerColors[7].standard, name: 'cube.color.'+markerColors[7].name, click: function(marker) {marker.color = 7;}}, + {icon: 'delete', name: 'generic.delete', click: function(marker) { + if (Animator.selected) Animator.selected.markers.remove(marker); + }} + ]) class GeneralAnimator { constructor(uuid, animation) { this.animation = animation; @@ -595,6 +637,10 @@ class EffectAnimator extends GeneralAnimator { var media = new Audio(kf.file); media.volume = Math.clamp(settings.volume.value/100, 0, 1); media.play(); + Timeline.playing_sounds.push(media); + media.onended = function() { + Timeline.playing_sounds.remove(media); + } kf.cooldown = true; setTimeout(() => { @@ -620,6 +666,7 @@ class Keyframe { this.effect = ''; this.file = ''; this.locator = ''; + this.script = ''; this.instructions = ''; this.uuid = (uuid && isUUID(uuid)) ? uuid : guid(); if (typeof data === 'object') { @@ -655,11 +702,13 @@ class Keyframe { if (data.values) { data.effect = data.values.effect; data.locator = data.values.locator; + data.script = data.values.script; data.file = data.values.file; data.instructions = data.values.instructions; } Merge.string(this, data, 'effect') Merge.string(this, data, 'locator') + Merge.string(this, data, 'script') Merge.string(this, data, 'file') Merge.string(this, data, 'instructions') } @@ -815,7 +864,7 @@ class Keyframe { } return this; } - callMarker() { + callPlayhead() { Timeline.setTime(this.time) Animator.preview() return this; @@ -853,6 +902,7 @@ class Keyframe { } else if (this.channel == 'particle') { copy.effect = this.effect; copy.locator = this.locator; + copy.script = this.script; } else if (this.channel == 'sound') { copy.effect = this.effect; @@ -884,189 +934,191 @@ class Keyframe { 'copy', 'delete', ]) - -function updateKeyframeValue(obj) { - var axis = $(obj).attr('axis'); - var value = $(obj).val(); - Timeline.selected.forEach(function(kf) { - kf.set(axis, value); - }) - if (!['effect', 'locator'].includes(axis)) { - Animator.preview(); - } -} -function updateKeyframeSelection() { - var multi_channel = false; - var channel = false; - Timeline.selected.forEach((kf) => { - if (channel === false) { - channel = kf.channel - } else if (channel !== kf.channel) { - multi_channel = true +//Misc Functions + function updateKeyframeValue(obj) { + var axis = $(obj).attr('axis'); + var value = $(obj).val(); + Timeline.selected.forEach(function(kf) { + kf.set(axis, value); + }) + if (!['effect', 'locator', 'script'].includes(axis)) { + Animator.preview(); } - }) - $('.panel#keyframe .bar').hide(); - - if (Timeline.selected.length && !multi_channel) { - var first = Timeline.selected[0] - - $('#keyframe_type_label').text(tl('panel.keyframe.type', [tl('timeline.'+first.channel)] )) - - if (first.animator instanceof BoneAnimator) { - function _gt(axis) { - var n = first.get(axis); - if (typeof n == 'number') return trimFloatNumber(n); - return n; + } + function updateKeyframeSelection() { + var multi_channel = false; + var channel = false; + Timeline.selected.forEach((kf) => { + if (channel === false) { + channel = kf.channel + } else if (channel !== kf.channel) { + multi_channel = true } - $('#keyframe_bar_x, #keyframe_bar_y, #keyframe_bar_z').show(); - $('#keyframe_bar_w').toggle(first.channel === 'rotation' && first.isQuaternion) + }) + $('.panel#keyframe .bar').hide(); - $('#keyframe_bar_x input').val(_gt('x')); - $('#keyframe_bar_y input').val(_gt('y')); - $('#keyframe_bar_z input').val(_gt('z')); - if (first.channel === 'rotation' && first.isQuaternion) { - $('#keyframe_bar_w input').val(_gt('w')); - } - } else if (first.channel == 'particle') { - $('#keyframe_bar_effect').show(); - $('#keyframe_bar_effect input').val(first.get('effect')); - $('#keyframe_bar_locator').show(); - $('#keyframe_bar_locator input').val(first.get('locator')); + if (Timeline.selected.length && !multi_channel) { + var first = Timeline.selected[0] - } else if (first.channel == 'sound') { - $('#keyframe_bar_effect').show(); - $('#keyframe_bar_effect input').val(first.get('effect')); + $('#keyframe_type_label').text(tl('panel.keyframe.type', [tl('timeline.'+first.channel)] )) - } else if (first.channel == 'timeline') { - $('#keyframe_bar_instructions').show(); - $('#keyframe_bar_instructions textarea').val(first.get('instructions')); + if (first.animator instanceof BoneAnimator) { + function _gt(axis) { + var n = first.get(axis); + if (typeof n == 'number') return trimFloatNumber(n); + return n; + } + $('#keyframe_bar_x, #keyframe_bar_y, #keyframe_bar_z').show(); + $('#keyframe_bar_w').toggle(first.channel === 'rotation' && first.isQuaternion) + + $('#keyframe_bar_x input').val(_gt('x')); + $('#keyframe_bar_y input').val(_gt('y')); + $('#keyframe_bar_z input').val(_gt('z')); + if (first.channel === 'rotation' && first.isQuaternion) { + $('#keyframe_bar_w input').val(_gt('w')); + } + } else if (first.channel == 'particle') { + $('#keyframe_bar_effect').show(); + $('#keyframe_bar_effect input').val(first.get('effect')); + $('#keyframe_bar_locator').show(); + $('#keyframe_bar_locator input').val(first.get('locator')); + $('#keyframe_bar_script').show(); + $('#keyframe_bar_script input').val(first.get('script')); + + } else if (first.channel == 'sound') { + $('#keyframe_bar_effect').show(); + $('#keyframe_bar_effect input').val(first.get('effect')); + + } else if (first.channel == 'timeline') { + $('#keyframe_bar_instructions').show(); + $('#keyframe_bar_instructions textarea').val(first.get('instructions')); + } + BarItems.slider_keyframe_time.update() + } else { + $('#keyframe_type_label').text('') + $('#keyframe_bar_x, #keyframe_bar_y, #keyframe_bar_z, #keyframe_bar_w').hide() } - BarItems.slider_keyframe_time.update() - } else { - $('#keyframe_type_label').text('') - $('#keyframe_bar_x, #keyframe_bar_y, #keyframe_bar_z, #keyframe_bar_w').hide() + BARS.updateConditions() } - BARS.updateConditions() -} -function selectAllKeyframes() { - if (!Animator.selected) return; - var state = Timeline.selected.length !== Timeline.keyframes.length - Timeline.keyframes.forEach((kf) => { - if (state && !kf.selected) { - Timeline.selected.push(kf) - } else if (!state && kf.selected) { - Timeline.selected.remove(kf) - } - kf.selected = state - }) - updateKeyframeSelection() -} -function removeSelectedKeyframes() { - Undo.initEdit({keyframes: Timeline.selected}) - var i = Timeline.keyframes.length; - while (i > 0) { - i--; - let kf = Timeline.keyframes[i] - if (Timeline.selected.includes(kf)) { - kf.remove() - } - } - updateKeyframeSelection() - Animator.preview() - Undo.finishEdit('remove keyframes') -} -function findBedrockAnimation() { - var animation_path = ModelMeta.export_path.split(osfs) - var index = animation_path.lastIndexOf('models') - animation_path.splice(index) - var path1 = [...animation_path, 'animations', pathToName(ModelMeta.export_path)+'.json'].join(osfs) - var path2 = [...animation_path, 'animations', pathToName(ModelMeta.export_path).replace('.geo', '')+'.animation.json'].join(osfs) - if (fs.existsSync(path1)) { - Blockbench.read([path1], {}, (files) => { - Animator.loadFile(files[0]) - }) - } else if (fs.existsSync(path2)) { - Blockbench.read([path2], {}, (files) => { - Animator.loadFile(files[0]) + function selectAllKeyframes() { + if (!Animator.selected) return; + var state = Timeline.selected.length !== Timeline.keyframes.length + Timeline.keyframes.forEach((kf) => { + if (state && !kf.selected) { + Timeline.selected.push(kf) + } else if (!state && kf.selected) { + Timeline.selected.remove(kf) + } + kf.selected = state }) + updateKeyframeSelection() } -} - -Clipbench.setKeyframes = function() { - - var keyframes = Timeline.selected; - - Clipbench.keyframes = [] - if (!keyframes || keyframes.length === 0) { - return; - } - var first = keyframes[0]; - var single_animator; - keyframes.forEach(function(kf) { - if (kf.time < first.time) { - first = kf + function removeSelectedKeyframes() { + Undo.initEdit({keyframes: Timeline.selected}) + var i = Timeline.keyframes.length; + while (i > 0) { + i--; + let kf = Timeline.keyframes[i] + if (Timeline.selected.includes(kf)) { + kf.remove() + } } - if (single_animator && single_animator !== kf.animator.uuid) { - single_animator = false; - } else if (single_animator == undefined) { - single_animator = kf.animator.uuid; + updateKeyframeSelection() + Animator.preview() + Undo.finishEdit('remove keyframes') + } + function findBedrockAnimation() { + var animation_path = ModelMeta.export_path.split(osfs) + var index = animation_path.lastIndexOf('models') + animation_path.splice(index) + var path1 = [...animation_path, 'animations', pathToName(ModelMeta.export_path)+'.json'].join(osfs) + var path2 = [...animation_path, 'animations', pathToName(ModelMeta.export_path).replace('.geo', '')+'.animation.json'].join(osfs) + if (fs.existsSync(path1)) { + Blockbench.read([path1], {}, (files) => { + Animator.loadFile(files[0]) + }) + } else if (fs.existsSync(path2)) { + Blockbench.read([path2], {}, (files) => { + Animator.loadFile(files[0]) + }) } - }) + } +//Clipbench + Clipbench.setKeyframes = function() { + + var keyframes = Timeline.selected; - keyframes.forEach(function(kf) { - var copy = kf.getUndoCopy(); - copy.time_offset = kf.time - first.time; - if (single_animator != false) { - delete copy.animator; + Clipbench.keyframes = [] + if (!keyframes || keyframes.length === 0) { + return; } - Clipbench.keyframes.push(copy) - }) - if (isApp) { - clipboard.writeHTML(JSON.stringify({type: 'keyframes', content: Clipbench.keyframes})) - } -} -Clipbench.pasteKeyframes = function() { - if (isApp) { - var raw = clipboard.readHTML() - try { - var data = JSON.parse(raw) - if (data.type === 'keyframes' && data.content) { - Clipbench.keyframes = data.content + var first = keyframes[0]; + var single_animator; + keyframes.forEach(function(kf) { + if (kf.time < first.time) { + first = kf } - } catch (err) {} - } - if (Clipbench.keyframes && Clipbench.keyframes.length) { + if (single_animator && single_animator !== kf.animator.uuid) { + single_animator = false; + } else if (single_animator == undefined) { + single_animator = kf.animator.uuid; + } + }) - if (!Animator.selected) return; - var keyframes = []; - Undo.initEdit({keyframes}); - Timeline.selected.empty(); - Timeline.keyframes.forEach((kf) => { - kf.selected = false; + keyframes.forEach(function(kf) { + var copy = kf.getUndoCopy(); + copy.time_offset = kf.time - first.time; + if (single_animator != false) { + delete copy.animator; + } + Clipbench.keyframes.push(copy) }) - Clipbench.keyframes.forEach(function(data, i) { + if (isApp) { + clipboard.writeHTML(JSON.stringify({type: 'keyframes', content: Clipbench.keyframes})) + } + } + Clipbench.pasteKeyframes = function() { + if (isApp) { + var raw = clipboard.readHTML() + try { + var data = JSON.parse(raw) + if (data.type === 'keyframes' && data.content) { + Clipbench.keyframes = data.content + } + } catch (err) {} + } + if (Clipbench.keyframes && Clipbench.keyframes.length) { + + if (!Animator.selected) return; + var keyframes = []; + Undo.initEdit({keyframes}); + Timeline.selected.empty(); + Timeline.keyframes.forEach((kf) => { + kf.selected = false; + }) + Clipbench.keyframes.forEach(function(data, i) { - if (data.animator) { - var animator = Animator.selected.animators[data.animator]; - if (animator && !Timeline.animators.includes(animator)) { - animator.addToTimeline(); + if (data.animator) { + var animator = Animator.selected.animators[data.animator]; + if (animator && !Timeline.animators.includes(animator)) { + animator.addToTimeline(); + } + } else { + var animator = Timeline.selected_animator; + } + if (animator) { + var kf = animator.createKeyframe(data, Timeline.time + data.time_offset, data.channel, false, false) + keyframes.push(kf); + kf.selected = true; + Timeline.selected.push(kf); } - } else { - var animator = Timeline.selected_animator; - } - if (animator) { - var kf = animator.createKeyframe(data, Timeline.time + data.time_offset, data.channel, false, false) - keyframes.push(kf); - kf.selected = true; - Timeline.selected.push(kf); - } - }) - TickUpdates.keyframe_selection = true; - Animator.preview() - Undo.finishEdit('paste keyframes'); + }) + TickUpdates.keyframe_selection = true; + Animator.preview() + Undo.finishEdit('paste keyframes'); + } } -} const Animator = { possible_channels: {rotation: true, position: true, scale: true, sound: true, particle: true, timeline: true}, @@ -1224,6 +1276,7 @@ const Animator = { time: parseFloat(timestamp), effect: particle.effect, locator: particle.locator, + script: particle.pre_effect_script, }) } } @@ -1283,9 +1336,12 @@ const Animator = { if (!timecode.includes('.')) { timecode += '.0'; } + let script = kf.script || undefined; + if (script && !script.match(/;$/)) script += ';'; ani_tag.particle_effects[timecode] = { effect: kf.effect, - locator: kf.locator || undefined + locator: kf.locator || undefined, + pre_effect_script: kf.script || undefined }; }) animator.timeline.forEach(kf => { @@ -1344,6 +1400,7 @@ const Animator = { const Timeline = { animators: [], selected: [],//frames + playing_sounds: [], playback_speed: 100, time: 0, get second() {return Timeline.time}, @@ -1361,7 +1418,7 @@ const Timeline = { return }; - document.addEventListener('mousemove', Timeline.selector.move, false); + Timeline.selector.interval = setInterval(Timeline.selector.move, 1000/60); document.addEventListener('mouseup', Timeline.selector.end, false); var offset = $('#timeline_body_inner').offset(); @@ -1390,7 +1447,7 @@ const Timeline = { offset.left, offset.top, ] - var rect = getRectangle(R.start[0], R.start[1], e.clientX - R.panel_offset[0], e.clientY - R.panel_offset[1]) + var rect = getRectangle(R.start[0], R.start[1], mouse_pos.x - R.panel_offset[0], mouse_pos.y - R.panel_offset[1]) $('#timeline_selector') .css('width', rect.x + 'px') .css('height', rect.y + 'px') @@ -1434,22 +1491,21 @@ const Timeline = { var body = $('#timeline_body').get(0) var body_inner = $('#timeline_body_inner').get(0) - var top = e.clientY - R.panel_offset[1] - body.scrollTop; - var bot = body.scrollTop + body.clientHeight - (e.clientY - R.panel_offset[1]); - var lef = e.clientX - R.panel_offset[0] - body.scrollLeft - Timeline.vue._data.head_width; - var rig = body.clientWidth - (e.clientX - R.panel_offset[0] - body.scrollLeft); + var top = mouse_pos.y - R.panel_offset[1] - body.scrollTop; + var bot = body.scrollTop + body.clientHeight - (mouse_pos.y - R.panel_offset[1]); + var lef = mouse_pos.x - R.panel_offset[0] - body.scrollLeft - Timeline.vue._data.head_width; + var rig = body.clientWidth - (mouse_pos.x - R.panel_offset[0] - body.scrollLeft); if (top < 0) body.scrollTop = body.scrollTop - 5; if (bot < 0) body.scrollTop = Math.clamp(body.scrollTop + 5, 0, body_inner.clientHeight - body.clientHeight + 3); if (lef < 0) body.scrollLeft = body.scrollLeft - 5; if (rig < 0) body.scrollLeft = Math.clamp(body.scrollLeft + 5, 0, body_inner.clientWidth - body.clientWidth); - - }, end(e) { if (!Timeline.selector.selecting) return false; e.stopPropagation(); document.removeEventListener('mousemove', Timeline.selector.move); + clearInterval(Timeline.selector.interval); document.removeEventListener('mouseup', Timeline.selector.end); updateKeyframeSelection() @@ -1463,7 +1519,7 @@ const Timeline = { }, setTime(seconds, editing) { seconds = limitNumber(seconds, 0, 1000) - Timeline.vue._data.marker = seconds + Timeline.vue._data.playhead = seconds Timeline.time = seconds if (!editing) { Timeline.setTimecode(seconds) @@ -1471,9 +1527,9 @@ const Timeline = { Timeline.updateSize() //Scroll var scroll = $('#timeline_body').scrollLeft() - var marker = Timeline.time * Timeline.vue._data.size + 8 - if (marker < scroll || marker > scroll + $('#timeline_body').width() - Timeline.vue._data.head_width) { - $('#timeline_body').scrollLeft(marker-16) + var playhead = Timeline.time * Timeline.vue._data.size + 8 + if (playhead < scroll || playhead > scroll + $('#timeline_body').width() - Timeline.vue._data.head_width) { + $('#timeline_body').scrollLeft(playhead-16) } }, setTimecode(time) { @@ -1492,18 +1548,25 @@ const Timeline = { var fps = Math.clamp(settings.animation_snap.value, 1, 120); return Math.clamp(Math.round(time*fps)/fps, 0); }, + getStep() { + return 1/Math.clamp(settings.animation_snap.value, 1, 120); + }, setup() { $('#timeline_body').mousedown(Timeline.selector.down) - $('#timeline_time').mousedown(e => { - Timeline.dragging_marker = true; + $('#timeline_time').on('mousedown touchstart', e => { + if (e.which !== 1 && !event.changedTouches) return; + if (e.target.classList.contains('timeline_marker')) return; + convertTouchEvent(e); + Timeline.dragging_playhead = true; let time = (e.offsetX) / Timeline.vue._data.size Timeline.setTime(Timeline.snapTime(time)) Animator.preview() }) - $(document).mousemove(e => { - if (Timeline.dragging_marker) { - let offset = mouse_pos.x - $('#timeline_time').offset().left; + $(document).on('mousemove touchmove', e => { + if (Timeline.dragging_playhead) { + convertTouchEvent(e); + let offset = e.clientX - $('#timeline_time').offset().left; let time = Timeline.snapTime(offset / Timeline.vue._data.size) if (Timeline.time != time) { Timeline.setTime(time) @@ -1511,9 +1574,10 @@ const Timeline = { } } }) - .mouseup(e => { - if (Timeline.dragging_marker) { - delete Timeline.dragging_marker + .on('mouseup touchend', e => { + if (Timeline.dragging_playhead) { + delete Timeline.dragging_playhead + Timeline.pause(); } }) //Keyframe inputs @@ -1652,6 +1716,55 @@ const Timeline = { Undo.finishEdit('drag keyframes') } }) + $('#timeline_body .keyframe:not(.ui-draggable)').draggable({ + axis: 'x', + distance: 4, + helper: () => $('
    '), + start: function(event, ui) { + + var id = $(event.target).attr('id'); + var clicked = Timeline.keyframes.findInArray('uuid', id) + + if (!$(event.target).hasClass('selected') && !event.shiftKey && Timeline.selected.length != 0) { + clicked.select() + } else if (clicked && !clicked.selected) { + clicked.select({shiftKey: true}) + } + + Undo.initEdit({keyframes: Timeline.selected}) + Timeline.dragging_keyframes = true; + + var i = 0; + for (var kf of Timeline.selected) { + kf.time_before = kf.time + } + }, + drag: function(event, ui) { + var difference = (ui.position.left - ui.originalPosition.left - 8) / Timeline.vue._data.size; + var id = $(ui.helper).attr('id') + var snap_value = false + var nearest + + for (var kf of Timeline.selected) { + var t = limitNumber(kf.time_before + difference, 0, 256) + if (kf.uuid === id) { + ui.position.left = t * Timeline.vue._data.size + 8 + } + kf.time = Timeline.snapTime(t); + } + BarItems.slider_keyframe_time.update() + Animator.preview() + }, + stop: function(event, ui) { + var deleted = [] + for (var kf of Timeline.selected) { + delete kf.time_before; + kf.replaceOthers(deleted); + } + Undo.addKeyframeCasualties(deleted); + Undo.finishEdit('drag keyframes') + } + }) }, updateSize() { let size = Timeline.vue._data.size @@ -1674,7 +1787,7 @@ const Timeline = { else {step = 0.05} if (step < 1) { - var FPS = 1/Math.clamp(settings.animation_snap.value, 1, 120); + var FPS = Timeline.getStep(); step = Math.round(step/FPS) * FPS step = 1/Math.round(1/step) } @@ -1732,6 +1845,12 @@ const Timeline = { clearInterval(Animator.interval) Animator.interval = false } + Timeline.playing_sounds.forEach(media => { + if (!media.paused) { + media.pause(); + } + }) + Timeline.playing_sounds.empty(); }, get keyframes() { var keyframes = []; @@ -1800,8 +1919,9 @@ onVueSetup(function() { head_width: 170, timecodes: [], animators: Timeline.animators, + markers: [], focus_channel: null, - marker: Timeline.time + playhead: Timeline.time }, methods: { toggleAnimator(animator) { @@ -1816,7 +1936,7 @@ onVueSetup(function() { Blockbench.addDragHandler('animation', { extensions: ['animation.json'], readtype: 'text', - condition: () => Modes.animate, + condition: {modes: ['animate']}, }, function(files) { Animator.loadFile(files[0]) }) @@ -1825,7 +1945,7 @@ BARS.defineActions(function() { new Action('add_animation', { icon: 'fa-plus-circle', category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, click: function () { var animation = new Animation({ name: 'animation.' + (Project.geometry_name||'model') + '.new' @@ -1836,7 +1956,7 @@ BARS.defineActions(function() { new Action('load_animation_file', { icon: 'fa-file-video', category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, click: function () { var path = ModelMeta.export_path if (isApp) { @@ -1917,7 +2037,7 @@ BARS.defineActions(function() { }) new NumSlider('slider_animation_speed', { category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, get: function() { return Timeline.playback_speed; }, @@ -2047,18 +2167,25 @@ BARS.defineActions(function() { new Action('previous_keyframe', { icon: 'fa-arrow-circle-left', category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, click: function () { var time = Timeline.time; function getDelta(kf, abs) { return kf.time - time } + let animator = Timeline.selected_animator + || (Timeline.selected[0] && Timeline.selected[0].animator) + || Timeline.animators[0]; + let channel = Timeline.selected[0] ? Timeline.selected[0].channel : (animator && animator.channels[0]); + var matches = [] for (var kf of Timeline.keyframes) { - let delta = getDelta(kf) - if (delta < 0) { - matches.push(kf) + if ((!animator || animator == kf.animator) && (!channel || channel == kf.channel)) { + let delta = getDelta(kf) + if (delta < 0) { + matches.push(kf) + } } } matches.sort((a, b) => { @@ -2066,7 +2193,7 @@ BARS.defineActions(function() { }) var kf = matches[0] if (kf) { - kf.select().callMarker() + kf.select().callPlayhead() } else { if (Timeline.selected.length) { selectAllKeyframes() @@ -2080,18 +2207,25 @@ BARS.defineActions(function() { new Action('next_keyframe', { icon: 'fa-arrow-circle-right', category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, click: function () { var time = Timeline.time; function getDelta(kf, abs) { return kf.time - time } + let animator = Timeline.selected_animator + || (Timeline.selected[0] && Timeline.selected[0].animator) + || Timeline.animators[0]; + let channel = Timeline.selected[0] ? Timeline.selected[0].channel : (animator && animator.channels[0]); + var matches = [] for (var kf of Timeline.keyframes) { - let delta = getDelta(kf) - if (delta > 0) { - matches.push(kf) + if ((!animator || animator == kf.animator) && (!channel || channel == kf.channel)) { + let delta = getDelta(kf) + if (delta > 0) { + matches.push(kf) + } } } matches.sort((a, b) => { @@ -2099,15 +2233,44 @@ BARS.defineActions(function() { }) var kf = matches[0] if (kf) { - kf.select().callMarker() + kf.select().callPlayhead() } } }) + new Action('move_keyframe_back', { + icon: 'arrow_back', + category: 'transform', + condition: {modes: ['animate'], method: () => (!open_menu && Timeline.selected.length)}, + keybind: new Keybind({key: 37}), + click: function (e) { + Undo.initEdit({keyframes: Timeline.selected}) + Timeline.selected.forEach((kf) => { + kf.time = Timeline.snapTime(limitNumber(kf.time - Timeline.getStep(), 0, 1e4)) + }) + Animator.preview() + Undo.finishEdit('move keyframes') + } + }) + new Action('move_keyframe_forth', { + icon: 'arrow_forward', + category: 'transform', + condition: {modes: ['animate'], method: () => (!open_menu && Timeline.selected.length)}, + keybind: new Keybind({key: 39}), + click: function (e) { + Undo.initEdit({keyframes: Timeline.selected}) + Timeline.selected.forEach((kf) => { + kf.time = Timeline.snapTime(limitNumber(kf.time + Timeline.getStep(), 0, 1e4)) + }) + Animator.preview() + Undo.finishEdit('move keyframes') + } + }) + new Action('add_keyframe', { icon: 'add_circle', category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, keybind: new Keybind({key: 81, shift: null}), click: function (event) { var animator = Timeline.selected_animator; @@ -2123,10 +2286,37 @@ BARS.defineActions(function() { } }) + new Action('add_marker', { + icon: 'flag', + category: 'animation', + condition: {modes: ['animate']}, + keybind: new Keybind({key: 77}), + click: function (event) { + if (!Animator.selected) { + Blockbench.showQuickMessage('message.no_animation_selected') + return; + } + var time = Timeline.snapTime(); + var original_marker; + for (var m of Animator.selected.markers) { + if (Math.abs(m.time - time) < 0.01) { + original_marker = m; + break; + } + } + if (original_marker) { + Animator.selected.markers.remove(original_marker); + } else { + let marker = new TimelineMarker({time}); + Animator.selected.markers.push(marker); + } + } + }) + new Action('bring_up_all_animations', { icon: 'fa-sort-amount-up', category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, click: function () { for (var uuid in Animator.selected.animators) { var ba = Animator.selected.animators[uuid] @@ -2140,7 +2330,7 @@ BARS.defineActions(function() { new Action('clear_timeline', { icon: 'clear_all', category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, click: function () { Timeline.vue._data.animators.purge(); unselectAll(); @@ -2149,7 +2339,7 @@ BARS.defineActions(function() { new Action('select_effect_animator', { icon: 'fa-magic', category: 'animation', - condition: () => Animator.open, + condition: {modes: ['animate']}, click: function () { if (!Animator.selected) return; if (!Animator.selected.animators.effects) { diff --git a/js/api.js b/js/api.js index b0e8c1ad1..b02bffbc0 100644 --- a/js/api.js +++ b/js/api.js @@ -39,10 +39,55 @@ const Blockbench = { }, //Interface getIconNode(icon, color) { - var jq; + let node; if (typeof icon === 'function') { icon = icon() } + if (icon === undefined) { + //Missing + node = document.createElement('i'); + node.classList.add('material-icons', 'icon'); + node.innerText = 'help_outline'; + } else if (icon instanceof HTMLElement) { + //Node + node = icon + } else if (icon.substr(0, 2) === 'fa') { + //Font Awesome + node = document.createElement('i'); + node.classList.add('fa_big', 'icon'); + if (icon.substr(3, 1) === '.') { + node.classList.add(icon.substr(0, 3), icon.substr(4)); + } else { + node.classList.add('fa', icon); + } + } else if (icon.substr(0, 5) === 'icon-') { + //Icomoon + node = document.createElement('i'); + node.classList.add(icon, 'icon'); + } else if (icon.substr(0, 14) === 'data:image/png') { + //Data URL + node = document.createElement('img'); + node.classList.add('icon'); + node.src = icon; + } else { + //Material Icon + node = document.createElement('i'); + node.classList.add('material-icons', 'icon'); + node.innerText = icon; + } + if (color) { + if (color === 'x') { + node.classList.add('color_x'); + } else if (color === 'y') { + node.classList.add('color_y'); + } else if (color === 'z') { + node.classList.add('color_z'); + } else if (typeof color === 'string') { + node.style.color = color; + } + } + return node + /* if (icon === undefined) { //Missing jq = $('help_outline') @@ -78,6 +123,7 @@ const Blockbench = { } } return jq.get(0) + */ }, showQuickMessage(message, time) { $('#quick_message_box').remove() @@ -112,7 +158,7 @@ const Blockbench = { }, time ? time : 800) }, setStatusBarText(text) { - if (text) { + if (text !== undefined) { Prop.file_name = text } else { Prop.file_name = Prop.file_name_alt||'' diff --git a/js/blockbench.js b/js/blockbench.js index 37abdc4c0..1d5e84081 100644 --- a/js/blockbench.js +++ b/js/blockbench.js @@ -57,6 +57,7 @@ const Project = { _texture_width : 16, _texture_height : 16, ambientocclusion: true, + front_gui_light: false, get optional_box_uv() { return Format.optional_box_uv; } @@ -191,8 +192,6 @@ function updateSelection() { } } if (Cube.selected.length) { - main_uv.jquery.size.find('.uv_mapping_overlay').remove() - main_uv.loadData() $('.selection_only').css('visibility', 'visible') } else { if (Format.bone_rig && Group.selected) { @@ -204,6 +203,13 @@ function updateSelection() { $('.selection_only#element').css('visibility', 'visible') } } + if (Format.single_texture && Modes.paint) { + $('.selection_only#uv').css('visibility', 'visible') + } + } + if (Cube.selected.length || (Format.single_texture && Modes.paint)) { + main_uv.jquery.size.find('.uv_mapping_overlay').remove() + main_uv.loadData() } if (Modes.animate) { updateKeyframeSelection(); @@ -216,6 +222,9 @@ function updateSelection() { Canvas.updateOrigin(); Transformer.updateSelection(); Transformer.update(); + previews.forEach(preview => { + preview.updateAnnotations(); + }) BARS.updateConditions(); delete TickUpdates.selection; @@ -314,6 +323,8 @@ class Mode extends KeybindItem { Modes.selected = this; Modes[Modes.selected.id] = true; + document.body.setAttribute('mode', this.id); + $('#center > #preview').toggle(this.center_windows.includes('preview')); $('#center > #timeline').toggle(this.center_windows.includes('timeline')); $('#center > #start_screen').toggle(this.center_windows.includes('start_screen')); @@ -477,6 +488,95 @@ const TickUpdates = { } } +const FormatWizard = { + start() { + var dialog_1 = new Dialog({ + id: 'format_wizard_1', + title: 'format_wizard.title', + width: 540, + form: { + question: {type: 'text', text: 'Which platform do you want to create a model for?'}, + platform: {label: 'dialog.radio', type: 'radio', options: { + 'mcj': 'Minecraft: Java Edition', + 'mcbe': 'Minecraft: Bedrock Edition', + 'obj': 'Game Engine' + }}, + }, + onConfirm: function(formResult1) { + if (formResult1.platform == 'obj') { + + FormatWizard.result('free'); + + } else if (formResult1.platform == 'mcbe') { + var types = { + block: 'format_wizard.type.block', + item: 'format_wizard.type.item', + entity: 'format_wizard.type.entity', + } + } else { + var types = { + block: 'format_wizard.type.block', + item: 'format_wizard.type.item', + entity: 'format_wizard.type.entity', + armor: 'format_wizard.type.armor', + } + } + var dialog_2 = new Dialog({ + id: 'format_wizard_2', + title: 'format_wizard.title', + width: 540, + form: { + question: {type: 'text', text: 'What type of model do you want to edit?'}, + type: {label: 'dialog.radio', type: 'radio', options: types}, + }, + onConfirm: function(formResult2) { + if (formResult1.platform == 'mcj' && (formResult2.type == 'entity' || formResult2.type == 'armor')) { + + var dialog_3 = new Dialog({ + id: 'format_wizard_3', + title: 'format_wizard.title', + width: 540, + form: { + question: {type: 'text', text: 'What do you want to create the model for?'}, + product: {label: 'dialog.radio', type: 'radio', options: { + vanilla: '', + optifine: '', + modded: '', + }}, + }, + onConfirm: function(formResult3) { + switch (formResult3.product) { + case 'vanilla': + FormatWizard.result(''); break; + case 'optifine': + FormatWizard.result(formResult2.type == 'armor' ? 'java_armor' : 'optifine_entity'); break; + case 'modded': default: + FormatWizard.result('modded_entity'); break; + } + } + }).show(); + } else if (formResult1.platform == 'mcj') { + FormatWizard.result('java_block'); + } else { + switch (formResult2.type) { + case 'block': + FormatWizard.result('not_supported_yet'); break; + case 'item': + FormatWizard.result('not_supported_yet'); break; + default: + FormatWizard.result('bedrock'); break; + } + } + } + }).show(); + } + }).show(); + }, + result(result) { + + } +} + const entityMode = { hardcodes: {"geometry.chicken":{"body":{"rotation":[90,0,0]}},"geometry.llama":{"chest1":{"rotation":[0,90,0]},"chest2":{"rotation":[0,90,0]},"body":{"rotation":[90,0,0]}},"geometry.cow":{"body":{"rotation":[90,0,0]}},"geometry.sheep.sheared":{"body":{"rotation":[90,0,0]}},"geometry.sheep":{"body":{"rotation":[90,0,0]}},"geometry.phantom":{"body":{"rotation":[0,0,0]},"wing0":{"rotation":[0,0,5.7]},"wingtip0":{"rotation":[0,0,5.7]},"wing1":{"rotation":[0,0,-5.7]},"wingtip1":{"rotation":[0,0,-5.7]},"head":{"rotation":[11.5,0,0]},"tail":{"rotation":[0,0,0]},"tailtip":{"rotation":[0,0,0]}},"geometry.pig":{"body":{"rotation":[90,0,0]}},"geometry.ocelot":{"body":{"rotation":[90,0,0]},"tail1":{"rotation":[90,0,0]},"tail2":{"rotation":[90,0,0]}},"geometry.cat":{"body":{"rotation":[90,0,0]},"tail1":{"rotation":[90,0,0]},"tail2":{"rotation":[90,0,0]}},"geometry.turtle":{"eggbelly":{"rotation":[90,0,0]},"body":{"rotation":[90,0,0]}},"geometry.villager.witch":{"hat2":{"rotation":[-3,0,1.5]},"hat3":{"rotation":[-6,0,3]},"hat4":{"rotation":[-12,0,6]}},"geometry.pufferfish.mid":{"spines_top_front":{"rotation":[45,0,0]},"spines_top_back":{"rotation":[-45,0,0]},"spines_bottom_front":{"rotation":[-45,0,0]},"spines_bottom_back":{"rotation":[45,0,0]},"spines_left_front":{"rotation":[0,45,0]},"spines_left_back":{"rotation":[0,-45,0]},"spines_right_front":{"rotation":[0,-45,0]},"spines_right_back":{"rotation":[0,45,0]}},"geometry.pufferfish.large":{"spines_top_front":{"rotation":[45,0,0]},"spines_top_back":{"rotation":[-45,0,0]},"spines_bottom_front":{"rotation":[-45,0,0]},"spines_bottom_back":{"rotation":[45,0,0]},"spines_left_front":{"rotation":[0,45,0]},"spines_left_back":{"rotation":[0,-45,0]},"spines_right_front":{"rotation":[0,-45,0]},"spines_right_back":{"rotation":[0,45,0]}},"geometry.tropicalfish_a":{"leftFin":{"rotation":[0,-35,0]},"rightFin":{"rotation":[0,35,0]}},"geometry.tropicalfish_b":{"leftFin":{"rotation":[0,-35,0]},"rightFin":{"rotation":[0,35,0]}}}, } diff --git a/js/copy_paste.js b/js/copy_paste.js index 2561fbb9d..f7a61aef8 100644 --- a/js/copy_paste.js +++ b/js/copy_paste.js @@ -150,9 +150,8 @@ const Clipbench = { function iterate(obj, parent) { if (obj.children) { var copy = new Group(obj).addTo(parent).init() - if (Format.bone_rig) { - copy.createUniqueName(); - } + copy.createUniqueName(); + if (obj.children && obj.children.length) { obj.children.forEach((child) => { iterate(child, copy) @@ -160,7 +159,10 @@ const Clipbench = { } } else { var el = NonGroup.fromSave(obj).addTo(parent).selectLow(); - Canvas.adaptObjectPosition(el); + el.createUniqueName(); + if (el instanceof Cube) { + Canvas.adaptObjectPosition(el); + } } } iterate(Clipbench.group, target) @@ -168,9 +170,10 @@ const Clipbench = { } else if (Clipbench.elements && Clipbench.elements.length) { Clipbench.elements.forEach(function(obj) { - NonGroup.fromSave(obj).addTo(target).selectLow() + var el = NonGroup.fromSave(obj).addTo(target).selectLow(); + el.createUniqueName(); }) - updateSelection() + Canvas.updatePositions(); } Undo.finishEdit('paste', {outliner: true, elements: selected, selection: true}); } diff --git a/js/display_mode.js b/js/display_mode.js index 2ab644594..b7f7c7a34 100644 --- a/js/display_mode.js +++ b/js/display_mode.js @@ -1431,7 +1431,6 @@ enterDisplaySettings = function() { //Enterung Display Setting Mode, changes th display_preview.setNormalCamera() display_preview.camPers.position.set(-80, 40, -30) display_preview.camPers.setFocalLength(45) - lights.rotation.y = (Math.PI/4)*3 $('body').addClass('display_mode') $('#display_bar input#thirdperson_righthand').prop("checked", true) @@ -1512,6 +1511,10 @@ DisplayMode.updateDisplayBase = function(slot) { Transformer.center() } +DisplayMode.toggleGuiLight = function() { + Project.front_gui_light = !Project.front_gui_light; +} + DisplayMode.applyPreset = function(preset, all) { if (preset == undefined) return; @@ -1583,6 +1586,14 @@ DisplayMode.groundAnimation = function() { Transformer.center() if (ground_timer === 200) ground_timer = 0; } +DisplayMode.updateGUILight = function() { + if (!display_mode) return; + if (display_slot == 'gui' && Project.front_gui_light == true) { + lights.rotation.set(-Math.PI, 0.6, 0); + } else { + lights.rotation.set(0, Math.PI * 0.75, 0); + } +} function loadDisp(key) { //Loads The Menu and slider values, common for all Radio Buttons display_slot = key @@ -1600,9 +1611,10 @@ function loadDisp(key) { //Loads The Menu and slider values, common for all Radi } DisplayMode.vue._data.slot = display[key] DisplayMode.slot = display[key] - DisplayMode.updateDisplayBase() - Canvas.updateRenderSides() - + DisplayMode.updateDisplayBase(); + Canvas.updateRenderSides(); + DisplayMode.updateGUILight(); + Toolbars.display.update(); } DisplayMode.loadThirdRight = function() { //Loader loadDisp('thirdperson_righthand') @@ -1648,6 +1660,7 @@ DisplayMode.loadGUI = function() { //Loader display_preview.setOrthographicCamera(2) display_preview.camOrtho.position.set(0,0,32) displayReferenceObjects.bar(['inventory_nine', 'inventory_full', 'hud']) + BarItems.gui_light.set(Project.front_gui_light ? 'front' : 'side'); } DisplayMode.loadGround = function() { //Loader loadDisp('ground') @@ -1834,6 +1847,7 @@ onVueSetup(function() { DisplayMode.vue = new Vue({ el: '#display_sliders', data: { + axes: [0, 1, 2], slot: new DisplaySlot() }, methods: { @@ -1890,6 +1904,17 @@ BARS.defineActions(function() { condition: () => display_mode, click: function () {showDialog('create_preset')} }) + new BarSelect('gui_light', { + options: { + side: true, + front: true, + }, + condition: () => display_mode && display_slot === 'gui', + onChange: function(slider) { + Project.front_gui_light = slider.get() == 'front'; + DisplayMode.updateGUILight(); + } + }) }) })() \ No newline at end of file diff --git a/js/interface/actions.js b/js/interface/actions.js index 0fa3dd9da..6d2070597 100644 --- a/js/interface/actions.js +++ b/js/interface/actions.js @@ -22,6 +22,7 @@ class BarItem { this.description = tl('action.'+this.id+'.desc') if (this.description == key) this.description = ''; } + this.color = data.color this.node; this.condition = data.condition; this.nodes = [] @@ -164,7 +165,6 @@ class Action extends BarItem { this.type = 'action' //Icon this.icon = data.icon - this.color = data.color if (data.linked_setting) { this.description = tl('settings.'+data.linked_setting+'.desc') @@ -255,6 +255,7 @@ class Tool extends Action { this.alt_tool = data.alt_tool; this.modes = data.modes; this.selectFace = data.selectFace; + this.cursor = data.cursor; this.selectCubes = data.selectCubes !== false; this.paintTool = data.paintTool; this.transformerMode = data.transformerMode; @@ -368,7 +369,11 @@ class NumSlider extends Widget { this.keybind.shift = null; } var scope = this; + var css_color = 'xyz'.includes(this.color) ? `var(--color-axis-${this.color})` : this.color; this.node = $( `
    +
    +
    +
    ${this.name}
    `).get(0); @@ -398,6 +403,7 @@ class NumSlider extends Widget { }, stop: function() { delete scope.sliding; + Blockbench.setStatusBarText(); if (typeof scope.onAfter === 'function') { scope.onAfter(scope.value - scope.last_value) } @@ -414,6 +420,13 @@ class NumSlider extends Widget { if (e.keyCode !== 10 && e.keyCode !== 13) { scope.input() } + if (e.keyCode === 27) { + if (!scope.jq_inner.hasClass('editing')) return; + e.preventDefault(); + scope.jq_inner.removeClass('editing') + scope.jq_inner.attr('contenteditable', 'false') + scope.update() + } }) .focusout(function() { scope.stopInput() @@ -429,7 +442,7 @@ class NumSlider extends Widget { .dblclick(function(event) { if (event.target != this) return; scope.jq_inner.text('0'); - scope.input() + scope.stopInput() }); //Arrows @@ -478,8 +491,10 @@ class NumSlider extends Widget { this.pre = offset; if (!difference) return; - this.change(n => n + difference) - this.update() + + this.change(n => n + difference); + this.update(); + Blockbench.setStatusBarText(trimFloatNumber(this.value - this.last_value)); } input() { this.last_value = this.value; @@ -1037,7 +1052,7 @@ const BARS = { //Tools new Tool('move_tool', { - icon: 'fas fa-hand-paper', + icon: 'fas.fa-hand-paper', category: 'tools', selectFace: true, transformerMode: 'translate', @@ -1310,10 +1325,17 @@ const BARS = { 'add_cube', 'add_group', 'outliner_toggle', - 'cube_counter' + 'toggle_', + 'toggle_skin_layer' ], default_place: true }) + + //update 3.3 + if (!Toolbars.outliner.children.includes(BarItems.toggle_skin_layer)) { + Toolbars.outliner.add(BarItems.toggle_skin_layer, -1) + } + Toolbars.texturelist = new Toolbar({ id: 'texturelist', children: [ @@ -1419,7 +1441,8 @@ const BARS = { children: [ 'copy', 'paste', - 'add_display_preset' + 'add_display_preset', + 'gui_light' ], default_place: true }) @@ -1493,6 +1516,7 @@ const BARS = { 'timeline_focus', 'clear_timeline', 'select_effect_animator', + 'add_marker', '_', 'slider_animation_speed', 'previous_keyframe', @@ -1501,6 +1525,10 @@ const BARS = { ], default_place: true }) + //update 3.3 + if (!Toolbars.timeline.children.includes(BarItems.add_marker)) { + Toolbars.timeline.add(BarItems.add_marker, 3) + } //Tools Toolbars.main_tools = new Toolbar({ id: 'main_tools', diff --git a/js/interface/dialog.js b/js/interface/dialog.js index 308492fc2..1c3e70bf9 100644 --- a/js/interface/dialog.js +++ b/js/interface/dialog.js @@ -99,6 +99,17 @@ function Dialog(settings) { } bar.append(el) break; + case 'radio': + var el = $(`
    `) + for (var key in data.options) { + var name = tl(data.options[key]) + el.append(`
    + + +
    `) + } + bar.append(el) + break; case 'text': data.text = marked(tl(data.text)) bar.append(`

    ${data.text}

    `) @@ -228,6 +239,9 @@ function Dialog(settings) { case 'select': result[form_id] = jq_dialog.find('select#'+form_id+' > option:selected').attr('id') break; + case 'radio': + result[form_id] = jq_dialog.find('.form_part_radio#'+form_id+' input:checked').attr('id') + break; case 'number': result[form_id] = Math.clamp(parseFloat(jq_dialog.find('input#'+form_id).val())||0, data.min, data.max) break; diff --git a/js/interface/interface.js b/js/interface/interface.js index 7a78e00d1..89312bea9 100644 --- a/js/interface/interface.js +++ b/js/interface/interface.js @@ -869,7 +869,7 @@ var documentReady = new Promise((resolve, reject) => { //Donation reminder if (Blockbench.startup_count % 12 === 11) { addStartScreenSection({ - graphic: {type: 'icon', icon: 'fas fa-heart'}, + graphic: {type: 'icon', icon: 'fas.fa-heart'}, text: [ {type: 'h1', text: 'Donation'}, {text: 'Are you enjoying Blockbench? Consider donating to the project. Blockbench is 100% donation funded.'}, @@ -913,7 +913,7 @@ onVueSetup(function() { methods: { getDate(p) { if (p.day) { - var diff = Blockbench.openTime.dayOfYear() - p.day; + var diff = (365e10 + Blockbench.openTime.dayOfYear() - p.day) % 365; if (diff <= 0) { return tl('dates.today'); } else if (diff == 1) { diff --git a/js/interface/menu.js b/js/interface/menu.js index 143bb7f0d..7ec69e467 100644 --- a/js/interface/menu.js +++ b/js/interface/menu.js @@ -101,10 +101,9 @@ class Menu { } open(position, context) { - if (position instanceof TouchEvent) { + if (position && position.changedTouches) { convertTouchEvent(position); } - var scope = this; var ctxmenu = $(this.node) if (open_menu) { @@ -145,6 +144,7 @@ class Menu { } else if (typeof s === 'object') { if (BARS.condition(s.condition, context)) { + let child_count; if (typeof s.icon === 'function') { var icon = Blockbench.getIconNode(s.icon(context), s.color) } else { @@ -170,12 +170,15 @@ class Menu { getEntry(s2, childlist) }) var last = childlist.children().last() + child_count = childlist.children().length; if (last.length && last.hasClass('menu_separator')) { last.remove() } } } - parent.append(entry) + if (child_count !== 0 || typeof s.click === 'function') { + parent.append(entry) + } entry.mouseenter(function(e) { scope.hover(this, e) }) @@ -437,7 +440,6 @@ const MenuBar = { 'settings_window', 'plugins_window', 'edit_session', - 'update_window', 'reload' ]) new BarMenu('edit', [ @@ -571,6 +573,8 @@ const MenuBar = { 'copy', 'paste', 'select_all', + 'add_keyframe', + 'add_marker', 'reverse_keyframes', 'delete', '_', @@ -600,6 +604,28 @@ const MenuBar = { 'timelapse', ]}, ]) + new BarMenu('help', [ + {name: 'menu.help.discord', id: 'discord', icon: 'fab.fa-discord', click: () => { + Blockbench.openLink('http://discord.blockbench.net'); + }}, + {name: 'menu.help.report_issue', id: 'report_issue', icon: 'bug_report', click: () => { + Blockbench.openLink('https://github.com/JannisX11/blockbench/issues'); + }}, + {name: 'menu.help.plugin_documentation', id: 'plugin_documentation', icon: 'fa-book', click: () => { + Blockbench.openLink('https://jannisx11.github.io/blockbench-docs/'); + }}, + '_', + {name: 'menu.help.search_action', description: BarItems.action_control.description, id: 'search_action', icon: 'search', click: ActionControl.select}, + '_', + 'update_window', + {name: 'menu.help.donate', id: 'donate', icon: 'fas.fa-hand-holding-usd', click: () => { + Blockbench.openLink('https://blockbench.net/donate/'); + }}, + {name: 'menu.help.about', id: 'about', icon: 'info', click: () => { + Settings.open(); + setSettingsTab('credits'); + }} + ]) MenuBar.update() }, update() { diff --git a/js/io/bbmodel.js b/js/io/bbmodel.js index 29e1aafad..2a20b53d5 100644 --- a/js/io/bbmodel.js +++ b/js/io/bbmodel.js @@ -34,7 +34,10 @@ var codec = new Codec('project', { } if (Project.parent) { model.parent = Project.parent; + } + if (Format.id == 'java_block') { model.ambientocclusion = Project.ambientocclusion + model.front_gui_light = Project.front_gui_light; } model.resolution = { width: Project.texture_width || 16, @@ -148,7 +151,10 @@ var codec = new Codec('project', { } if (model.ambientocclusion !== undefined) { Project.ambientocclusion = !!model.ambientocclusion; - } + } + if (model.front_gui_light !== undefined) { + Project.front_gui_light = !!model.front_gui_light; + } if (model.resolution !== undefined) { Project.texture_width = model.resolution.width; Project.texture_height = model.resolution.height; diff --git a/js/io/bedrock.js b/js/io/bedrock.js index 535d27c3d..6429526ca 100644 --- a/js/io/bedrock.js +++ b/js/io/bedrock.js @@ -6,7 +6,7 @@ window.BedrockEntityManager = { try { var c = fs.readFileSync(path, 'utf-8'); if (typeof c === 'string') { - c = JSON.parse(c); + c = autoParseJSON(c, false); if (c && c[mce] && c[mce].description && typeof c[mce].description.geometry == 'object') { for (var key in c[mce].description.geometry) { var geoname = c[mce].description.geometry[key]; @@ -95,7 +95,7 @@ window.BedrockEntityManager = { singleButton: true }).show() $('#import_texture_list li').each((i, el) => { - $(el).css('background-image', `url("${ valid_textures_list[i].replace(/\\/g, '/') }")`) + $(el).css('background-image', `url("${ valid_textures_list[i].replace(/\\/g, '/') }?${Math.round(Math.random()*1e6)}")`) .click(() => { dialog.hide(); new Texture({keep_size: true}).fromPath(valid_textures_list[i]).add() @@ -444,11 +444,10 @@ var codec = new Codec('bedrock', { cube.origin[0] = -(cube.origin[0] + cube.size[0]) - if (!obj.origin.allEqual(0)) { - cube.pivot = obj.origin.slice(); - cube.pivot[0] *= -1 - } if (!obj.rotation.allEqual(0)) { + cube.pivot = obj.origin.slice(); + cube.pivot[0] *= -1; + cube.rotation = obj.rotation.slice(); cube.rotation.forEach(function(br, axis) { if (axis != 2) cube.rotation[axis] *= -1 @@ -545,7 +544,7 @@ var codec = new Codec('bedrock', { var model_id = 'geometry.'+Project.geometry_name; try { data = fs.readFileSync(path, 'utf-8'); - data = JSON.parse(data.replace(/\/\*[^(\*\/)]*\*\/|\/\/.*/g, '')) + data = autoParseJSON(data, false); if (data['minecraft:geometry'] instanceof Array == false) { throw 'Incompatible format'; } diff --git a/js/io/io.js b/js/io/io.js index b624d5b3c..fcf33ade2 100644 --- a/js/io/io.js +++ b/js/io/io.js @@ -35,6 +35,7 @@ class ModelFormat { this.canvas_limit = false; this.outliner_name_pattern = false; this.rotation_limit = false; + this.uv_rotation = false; this.display_mode = false; this.animation_mode = false; @@ -55,6 +56,7 @@ class ModelFormat { Merge.boolean(this, data, 'canvas_limit'); Merge.string(this, data, 'outliner_name_pattern'); Merge.boolean(this, data, 'rotation_limit'); + Merge.boolean(this, data, 'uv_rotation'); Merge.boolean(this, data, 'display_mode'); Merge.boolean(this, data, 'animation_mode'); } @@ -331,6 +333,7 @@ function resetProject() { Project.name = Project.parent = Project.geometry_name = Project.description = ''; Project.texture_width = Project.texture_height = 16; Project.ambientocclusion = true; + Project.front_gui_light = false; ModelMeta.save_path = ModelMeta.export_path = ModelMeta.animation_path = ModelMeta.name = ''; ModelMeta.saved = true; Prop.project_saved = true; @@ -702,7 +705,9 @@ function uploadSketchfabModel() { success: function(response) { Blockbench.showMessageBox({ title: tl('message.sketchfab.success'), - message: `[${formResult.name} on Sketchfab](https://sketchfab.com/models/${response.uid})`, + message: + `[${formResult.name} on Sketchfab](https://sketchfab.com/models/${response.uid})\n\n \n\n`+ + tl('message.sketchfab.setup_guide', '[Sketchfab Setup and Common Issues](https://blockbench.net/2020/01/22/sketchfab-setup-and-common-issues/)'), icon: 'icon-sketchfab', }) }, @@ -734,7 +739,7 @@ function compileJSON(object, options) { var out = '' if (typeof o === 'string') { //String - out += '"' + o.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n') + '"' + out += '"' + o.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\t/g, '\\t') + '"' } else if (typeof o === 'boolean') { //Boolean out += (o ? 'true' : 'false') @@ -841,6 +846,7 @@ BARS.defineActions(function() { bone_rig: true, centered_grid: false, optional_box_uv: true, + uv_rotation: true, }) //Project new Action('project_window', { @@ -943,7 +949,9 @@ BARS.defineActions(function() { var options = {}; for (var key in Formats) { - options[key] = Formats[key].name; + if (key !== Format.id && key !== 'skin') { + options[key] = Formats[key].name; + } } var dialog = new Dialog({ @@ -958,7 +966,6 @@ BARS.defineActions(function() { default: Format.id, options, }, - }, onConfirm: function(formResult) { var format = Formats[formResult.format] @@ -978,9 +985,19 @@ BARS.defineActions(function() { keybind: new Keybind({key: 79, ctrl: true}), condition: () => (!EditSession.active || EditSession.hosting), click: function () { + var startpath; + if (isApp && recent_projects && recent_projects.length) { + startpath = recent_projects[0].path; + if (typeof startpath == 'string') { + startpath = startpath.split(osfs); + startpath.pop(); + startpath = startpath.join(osfs); + } + } Blockbench.import({ extensions: ['json', 'jem', 'jpm', 'java', 'bbmodel'], - type: 'Model' + type: 'Model', + startpath }, function(files) { loadModelFile(files[0]); }) diff --git a/js/io/java_block.js b/js/io/java_block.js index e97b1f14d..153cbe505 100644 --- a/js/io/java_block.js +++ b/js/io/java_block.js @@ -179,6 +179,9 @@ var codec = new Codec('java_block', { if (checkExport('ambientocclusion', Project.ambientocclusion === false)) { blockmodel.ambientocclusion = false } + if (checkExport('front_gui_light', Project.front_gui_light)) { + blockmodel.gui_light = 'front'; + } if (Project.texture_width !== 16 || Project.texture_height !== 16) { blockmodel.texture_size = [Project.texture_width, Project.texture_height] } @@ -407,6 +410,9 @@ var codec = new Codec('java_block', { if (model.ambientocclusion === false) { Project.ambientocclusion = false; } + if (model.gui_light === 'front') { + Project.front_gui_light = true; + } if (add) { Undo.finishEdit('add block model') } @@ -421,6 +427,7 @@ var format = new ModelFormat({ canvas_limit: true, rotation_limit: true, optional_box_uv: true, + uv_rotation: true, display_mode: true, codec }) diff --git a/js/io/modded_entity.js b/js/io/modded_entity.js index 47e74a562..901d06db5 100644 --- a/js/io/modded_entity.js +++ b/js/io/modded_entity.js @@ -112,8 +112,12 @@ var codec = new Codec('modded_entity', { '\nimport net.minecraft.client.model.ModelBox;'+ `\nimport net.minecraft.client.model.${rendererName};`+ '\nimport net.minecraft.client.renderer.GlStateManager;'+ - '\nimport net.minecraft.entity.Entity;\n'+ - '\npublic class '+model_id+' extends ModelBase {' + '\nimport net.minecraft.entity.Entity;\n'; + if (ver == 1) { + model += '\npublic class '+model_id+' extends EntityModel {'; + } else { + model += '\npublic class '+model_id+' extends ModelBase {'; + } for (var r_id in renderers) { model += `\n private final ${rendererName} ${r_id};`; diff --git a/js/io/obj.js b/js/io/obj.js index eb681e13a..38d303b87 100644 --- a/js/io/obj.js +++ b/js/io/obj.js @@ -41,6 +41,8 @@ var codec = new Codec('obj', { output += 'mtllib ' + (options.mtl_name||'materials.mtl') +'\n'; + var scale = 1/16; + var parseMesh = function ( mesh ) { var nbVertex = 0; @@ -62,7 +64,7 @@ var codec = new Codec('obj', { var vertex = vertices[ i ].clone(); vertex.applyMatrix4( mesh.matrixWorld ); - output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + output += 'v ' + (vertex.x*scale) + ' ' + (vertex.y*scale) + ' ' + (vertex.z*scale) + '\n'; nbVertex ++; } // uvs diff --git a/js/io/optifine_jpm.js b/js/io/optifine_jpm.js index 65e906ae1..fbc632774 100644 --- a/js/io/optifine_jpm.js +++ b/js/io/optifine_jpm.js @@ -215,6 +215,7 @@ var part_format = new ModelFormat({ single_texture: true, integer_size: true, rotate_cubes: true, + optional_box_uv: true, codec: part_codec }) part_codec.format = part_format; diff --git a/js/io/skin.js b/js/io/skin.js new file mode 100644 index 000000000..6e08463f6 --- /dev/null +++ b/js/io/skin.js @@ -0,0 +1,4219 @@ +(function() { + +const skin_presets = {}; + +const codec = new Codec('skin_model', { + name: 'Skin Model', + remember: false, + compile(options) { + if (options === undefined) options = 0; + var entitymodel = { + name: Project.geometry_name.split('.')[0] + } + entitymodel.texturewidth = Project.texture_width; + entitymodel.textureheight = Project.texture_height; + var bones = [] + var cube_count = 0; + + var groups = getAllGroups(); + + groups.forEach(function(g) { + if (g.type !== 'group') return; + //Bone + var bone = {} + bone.name = g.name + if (g.parent.type === 'group') { + bone.parent = g.parent.name + } + bone.pivot = g.origin.slice() + bone.pivot[0] *= -1 + if (!g.rotation.allEqual(0)) { + bone.rotation = [ + -g.rotation[0], + -g.rotation[1], + g.rotation[2] + ] + } + if (g.reset) bone.reset = true; + if (g.mirror_uv) bone.mirror = true; + + //Elements + var cubes = [] + for (var obj of g.children) { + if (obj.export) { + if (obj instanceof Cube) { + + var cube = new oneLiner() + cube.name = obj.name; + if (obj.visibility == false) cube.visibility = false; + cube.origin = obj.from.slice() + cube.size = obj.size() + cube.origin[0] = -(cube.origin[0] + cube.size[0]) + cube.uv = obj.uv_offset + if (obj.inflate && typeof obj.inflate === 'number') { + cube.inflate = obj.inflate + } + if (obj.mirror_uv === !bone.mirror) { + cube.mirror = obj.mirror_uv + } + cubes.push(cube) + cube_count++; + + } + } + } + if (cubes.length) { + bone.cubes = cubes + } + bones.push(bone) + }) + + if (bones.length) { + entitymodel.bones = bones + } + return entitymodel + }, + parse(data, resolution, texture_path) { + Project.geometry_name = data.name; + Project.texture_width = data.texturewidth || 64; + Project.texture_height = data.textureheight || 64; + + var bones = {} + + if (data.bones) { + var included_bones = [] + data.bones.forEach(function(b) { + included_bones.push(b.name) + }) + data.bones.forEach(function(b, bi) { + var group = new Group({ + name: b.name, + origin: b.pivot, + rotation: b.rotation + }).init() + group.isOpen = true; + bones[b.name] = group + if (b.pivot) { + group.origin[0] *= -1 + } + group.rotation[0] *= -1; + group.rotation[1] *= -1; + + group.mirror_uv = b.mirror === true + group.reset = b.reset === true + + if (b.cubes) { + b.cubes.forEach(function(s) { + var base_cube = new Cube({name: s.name, visibility: s.visibility, autouv: 0, color: b.color}) + if (s.origin) { + base_cube.from = s.origin + base_cube.from[0] = -(base_cube.from[0] + s.size[0]) + if (s.size) { + base_cube.to[0] = s.size[0] + base_cube.from[0] + base_cube.to[1] = s.size[1] + base_cube.from[1] + base_cube.to[2] = s.size[2] + base_cube.from[2] + } + } + if (s.uv) { + base_cube.uv_offset[0] = s.uv[0] + base_cube.uv_offset[1] = s.uv[1] + } + if (s.inflate && typeof s.inflate === 'number') { + base_cube.inflate = s.inflate + } + if (s.mirror === undefined) { + base_cube.mirror_uv = group.mirror_uv + } else { + base_cube.mirror_uv = s.mirror === true + } + base_cube.addTo(group).init() + }) + } + if (b.children) { + b.children.forEach(function(cg) { + cg.addTo(group) + }) + } + if (b.locators) { + for (var key in b.locators) { + var coords = b.locators[key]; + coords[0] *= -1 + var locator = new Locator({from: coords, name: key}).addTo(group).init(); + } + } + var parent_group = 'root'; + if (b.parent) { + if (bones[b.parent]) { + parent_group = bones[b.parent] + } else { + data.bones.forEach(function(ib) { + if (ib.name === b.parent) { + ib.children && ib.children.length ? ib.children.push(group) : ib.children = [group] + } + }) + } + } + group.addTo(parent_group) + }) + } + if (texture_path) { + var texture = new Texture().fromPath(texture_path).add(false); + } else { + var texture = generateTemplate(Project.texture_width*resolution, Project.texture_height*resolution, data.name, data.eyes) + } + texture.load_callback = function() { + Modes.options.paint.select(); + } + loadTextureDraggable() + Canvas.updateAllBones() + setProjectTitle() + if (isApp && Project.geometry_name) { + BedrockEntityManager.initEntity() + } + updateSelection() + EditSession.initNewModel() + }, +}) + + + +const format = new ModelFormat({ + id: 'skin', + icon: 'icon-player', + bone_rig: true, + box_uv: true, + centered_grid: true, + single_texture: true, + integer_size: true, + codec, + onActivation() { + Modes.options.paint.select(); + } +}) +format.new = function() { + if (newProject(this)) { + skin_dialog.show(); + return true; + } +} + +function generateTemplate(width = 64, height = 64, name = 'name', eyes) { + + var texture = new Texture({ + mode: 'bitmap', + name: name+'.png' + }) + + var canvas = document.createElement('canvas') + canvas.width = width; + canvas.height = height; + + Cube.all.forEach(cube => { + TextureGenerator.paintCubeBoxTemplate(cube, texture, canvas); + }) + if (eyes) { + var res_multiple = canvas.width/Project.texture_width; + var ctx = canvas.getContext('2d'); + ctx.fillStyle = '#cdefff'; + eyes.forEach(eye => { + ctx.fillRect( + eye[0]*res_multiple, + eye[1]*res_multiple, + (eye[2]||2)*res_multiple, + (eye[3]||2)*res_multiple + ) + }) + } + var dataUrl = canvas.toDataURL(); + texture.fromDataURL(dataUrl).add(false); + return texture; +} + +const skin_dialog = new Dialog({ + title: tl('dialog.skin.title'), + id: 'image_editor', + form: { + model: { + label: 'dialog.skin.model', + type: 'select', + default: Format.id, + options: { + steve: 'Steve', + alex: 'Alex', + creeper: 'Creeper', + creeper: 'Creeper', + armor_stand: 'Armor Stand', + bat: 'Bat', + bee: 'Bee', + cat: 'Cat', + chicken: 'Chicken', + cod: 'Cod', + cow: 'Cow', + dolphin: 'Dolphin', + enderman: 'Enderman', + endermite: 'Endermite', + evoker: 'Evoker', + fox: 'Fox', + ghast: 'Ghast', + guardian: 'Guardian', + horse: 'Horse', + llama: 'Llama', + lavaslime: 'Lava Slime', + panda: 'Panda', + parrot: 'Parrot', + phantom: 'Phantom', + pig: 'Pig', + pillager: 'Pillager', + polarbear: 'Polarbear', + pufferfish: 'Pufferfish', + rabbit: 'Rabbit', + ravager: 'Ravager', + salmon: 'Salmon', + sheep: 'Sheep', + shield: 'Shield', + shulker: 'Shulker', + shulker_bullet: 'Shulker Bullet', + silverfish: 'Silverfish', + skeleton: 'Skeleton', + slime: 'Slime', + snowgolem: 'Snowgolem', + spider: 'Spider', + squid: 'Squid', + tropicalfish_a: 'Tropicalfish A', + tropicalfish_b: 'Tropicalfish B', + turtle: 'Turtle', + vex: 'Vex', + villager: 'Villager 1', + villager_v2: 'Villager 2', + vindicator: 'Vindicator', + witch: 'Witch', + witherBoss: 'Wither', + wolf: 'Wolf', + zombie: 'Zombie', + zombie_villager_1: 'Zombie Villager 1', + zombie_villager_2: 'Zombie Villager 2', + } + }, + resolution: {label: 'dialog.create_texture.resolution', type: 'select', value: 16, options: { + 16: '16x', + 32: '32x', + 64: '64x', + 128: '128x', + }}, + texture: { + label: 'dialog.skin.texture', + type: 'file', + extensions: ['png'], + filetype: 'PNG', + } + }, + draggable: true, + onConfirm(result) { + if (newProject(format)) { + var model = JSON.parse(skin_presets[result.model]); + codec.parse(model, result.resolution/16, result.texture); + } + this.hide(); + }, + onCancel() { + this.hide(); + Format = 0; + Modes.options.start.select(); + } +}); + + +BARS.defineActions(function() { + new Action('toggle_skin_layer', { + icon: 'layers_clear', + category: 'edit', + condition: () => Format.id == 'skin', + click: function () { + var edited = []; + Cube.all.forEach(cube => { + if (cube.name.toLowerCase().includes('layer')) { + edited.push(cube); + } + }) + if (!edited.length) return; + Undo.initEdit({elements: edited}); + value = !edited[0].visibility; + edited.forEach(cube => { + cube.visibility = value; + }) + Undo.finishEdit('toggle skin layer'); + Canvas.updateVisibility() + } + }) +}) + +skin_presets.steve = `{ + "name": "steve", + "texturewidth": 64, + "textureheight": 64, + "eyes": [ + [9, 11], + [13, 11] + ], + "bones": [ + { + "name": "Head", + "color": 1, + "pivot": [0, 24, 0], + "rotation": [-6, 5, 0], + "cubes": [ + {"name": "Head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}, + {"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5} + ] + }, + { + "name": "Body", + "color": 3, + "pivot": [0, 24, 0], + "cubes": [ + {"name": "Body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}, + {"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25} + ] + }, + { + "name": "Right Arm", + "color": 5, + "pivot": [-5, 22, 0], + "rotation": [-10, 0, 0], + "cubes": [ + {"name": "Right Arm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}, + {"name": "Right Arm Layer", "visibility": false, "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 32], "inflate": 0.25} + ] + }, + { + "name": "Left Arm", + "color": 0, + "pivot": [5, 22, 0], + "rotation": [12, 0, 0], + "cubes": [ + {"name": "Left Arm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [32, 48]}, + {"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [48, 48], "inflate": 0.25} + ] + }, + { + "name": "Right Leg", + "color": 6, + "pivot": [-1.9, 12, 0], + "rotation": [11, 0, 2], + "cubes": [ + {"name": "Right Leg", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}, + {"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25} + ] + }, + { + "name": "Left Leg", + "color": 7, + "pivot": [1.9, 12, 0], + "rotation": [-10, 0, -2], + "cubes": [ + {"name": "Left Leg", "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [16, 48]}, + {"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25} + ] + } + ] +}`; +skin_presets.alex = `{ + "name": "alex", + "texturewidth": 64, + "textureheight": 64, + "eyes": [ + [9, 11], + [13, 11] + ], + "bones": [ + { + "name": "Head", + "color": 1, + "pivot": [0, 24, 0], + "rotation": [-6, 5, 0], + "cubes": [ + {"name": "Head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}, + {"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5} + ] + }, + { + "name": "Body", + "color": 3, + "pivot": [0, 24, 0], + "cubes": [ + {"name": "Body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}, + {"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25} + ] + }, + { + "name": "Right Arm", + "color": 5, + "pivot": [-5, 22, 0], + "rotation": [-10, 0, 0], + "cubes": [ + {"name": "Right Arm", "origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 16]}, + {"name": "Right Sleeve", "visibility": false, "origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 32], "inflate": 0.25} + ] + }, + { + "name": "Left Arm", + "color": 0, + "pivot": [5, 22, 0], + "rotation": [12, 0, 0], + "cubes": [ + {"name": "Left Arm", "origin": [4, 12, -2], "size": [3, 12, 4], "uv": [32, 48]}, + {"name": "Left Sleeve", "visibility": false, "origin": [4, 12, -2], "size": [3, 12, 4], "uv": [48, 48], "inflate": 0.25} + ] + }, + { + "name": "Right Leg", + "color": 6, + "pivot": [-1.9, 12, 0], + "rotation": [11, 0, 2], + "cubes": [ + {"name": "Right Leg", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}, + {"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25} + ] + }, + { + "name": "Left Leg", + "color": 7, + "pivot": [1.9, 12, 0], + "rotation": [-10, 0, -2], + "cubes": [ + {"name": "Left Leg", "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [16, 48]}, + {"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25} + ] + } + ] +}`; +skin_presets.creeper = `{ + "name": "alex", + "texturewidth": 64, + "textureheight": 32, + "eyes": [ + [9, 10], + [13, 10] + ], + "bones": [ + { + "name": "body", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, 6, -2], "size": [8, 12, 4], "uv": [16, 16]} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 18, 0], + "cubes": [ + {"name": "head", "origin": [-4, 18, -4], "size": [8, 8, 8], "uv": [0, 0]} + ] + }, + { + "name": "leg0", + "parent": "body", + "pivot": [-2, 6, 4], + "cubes": [ + {"name": "leg0", "origin": [-4, 0, 2], "size": [4, 6, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg1", + "parent": "body", + "pivot": [2, 6, 4], + "cubes": [ + {"name": "leg1", "origin": [0, 0, 2], "size": [4, 6, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg2", + "parent": "body", + "pivot": [-2, 6, -4], + "cubes": [ + {"name": "leg2", "origin": [-4, 0, -6], "size": [4, 6, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg3", + "parent": "body", + "pivot": [2, 6, -4], + "cubes": [ + {"name": "leg3", "origin": [0, 0, -6], "size": [4, 6, 4], "uv": [0, 16]} + ] + } + ] +}`; +skin_presets.armor_stand = `{ + "name": "armor_stand", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "baseplate", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "baseplate", "origin": [-6, 0, -6], "size": [12, 1, 12], "uv": [0, 32]} + ] + }, + { + "name": "waist", + "parent": "baseplate", + "pivot": [0, 12, 0] + }, + { + "name": "body", + "parent": "waist", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-6, 21, -1.5], "size": [12, 3, 3], "uv": [0, 26]}, + {"name": "body", "origin": [-3, 14, -1], "size": [2, 7, 2], "uv": [16, 0]}, + {"name": "body", "origin": [1, 14, -1], "size": [2, 7, 2], "uv": [48, 16]}, + {"name": "body", "origin": [-4, 12, -1], "size": [8, 2, 2], "uv": [0, 48]} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-1, 24, -1], "size": [2, 7, 2], "uv": [0, 0]} + ] + }, + { + "name": "hat", + "parent": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "hat", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0]} + ] + }, + { + "name": "leftarm", + "parent": "body", + "pivot": [5, 22, 0], + "mirror": true, + "cubes": [ + {"name": "leftarm", "origin": [5, 12, -1], "size": [2, 12, 2], "uv": [32, 16]} + ] + }, + { + "name": "leftitem", + "parent": "leftarm", + "pivot": [6, 15, 1] + }, + { + "name": "leftleg", + "parent": "body", + "pivot": [1.9, 12, 0], + "mirror": true, + "cubes": [ + {"name": "leftleg", "origin": [0.9, 1, -1], "size": [2, 11, 2], "uv": [40, 16]} + ] + }, + { + "name": "rightarm", + "parent": "body", + "pivot": [-5, 22, 0], + "cubes": [ + {"name": "rightarm", "origin": [-7, 12, -1], "size": [2, 12, 2], "uv": [24, 0]} + ] + }, + { + "name": "rightitem", + "parent": "rightarm", + "pivot": [-6, 15, 1] + }, + { + "name": "rightleg", + "parent": "body", + "pivot": [-1.9, 12, 0], + "cubes": [ + {"name": "rightleg", "origin": [-2.9, 1, -1], "size": [2, 11, 2], "uv": [8, 0]} + ] + } + ] +}`; +skin_presets.bat = `{ + "name": "bat", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-3, 21, -3], "size": [6, 6, 6], "uv": [0, 0]} + ] + }, + { + "name": "rightEar", + "parent": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "rightEar", "origin": [-4, 26, -2], "size": [3, 4, 1], "uv": [24, 0]} + ] + }, + { + "name": "leftEar", + "parent": "head", + "pivot": [0, 24, 0], + "mirror": true, + "cubes": [ + {"name": "leftEar", "origin": [1, 26, -2], "size": [3, 4, 1], "uv": [24, 0]} + ] + }, + { + "name": "body", + "pivot": [0, 24, 0], + "rotation": [30, 0, 0], + "cubes": [ + {"name": "body", "origin": [-3, 8, -3], "size": [6, 12, 6], "uv": [0, 16]}, + {"name": "body", "origin": [-5, -8, 0], "size": [10, 16, 1], "uv": [0, 34]} + ] + }, + { + "name": "rightWing", + "parent": "body", + "pivot": [0, 24, 0], + "rotation": [0, -10, 0], + "cubes": [ + {"name": "rightWing", "origin": [-12, 7, 1.5], "size": [10, 16, 1], "uv": [42, 0]} + ] + }, + { + "name": "rightWingTip", + "parent": "rightWing", + "pivot": [-12, 23, 1.5], + "rotation": [0, -15, 0], + "cubes": [ + {"name": "rightWingTip", "origin": [-20, 10, 1.5], "size": [8, 12, 1], "uv": [24, 16]} + ] + }, + { + "name": "leftWing", + "parent": "body", + "pivot": [0, 24, 0], + "rotation": [0, 10, 0], + "mirror": true, + "cubes": [ + {"name": "leftWing", "origin": [2, 7, 1.5], "size": [10, 16, 1], "uv": [42, 0]} + ] + }, + { + "name": "leftWingTip", + "parent": "leftWing", + "pivot": [12, 23, 1.5], + "rotation": [0, 15, 0], + "mirror": true, + "cubes": [ + {"name": "leftWingTip", "origin": [12, 10, 1.5], "size": [8, 12, 1], "uv": [24, 16]} + ] + } + ] +}`; +skin_presets.bee = `{ + "name": "bee", + "texturewidth": 64, + "textureheight": 64, + "eyes": [ + [10, 13, 2, 3], + [15, 13, 2, 3] + ], + "bones": [ + { + "name": "body", + "pivot": [0.5, 5, 0], + "cubes": [ + {"name": "body", "origin": [-3, 2, -5], "size": [7, 7, 10], "uv": [0, 0]}, + {"name": "body", "origin": [2, 7, -8], "size": [1, 2, 3], "uv": [2, 0]}, + {"name": "body", "origin": [-2, 7, -8], "size": [1, 2, 3], "uv": [2, 3]} + ] + }, + { + "name": "stinger", + "parent": "body", + "pivot": [0.5, 6, 1], + "cubes": [ + {"name": "stinger", "origin": [0.5, 5, 5], "size": [0, 1, 2], "uv": [26, 7]} + ] + }, + { + "name": "rightwing_bone", + "parent": "body", + "pivot": [-1, 9, -3], + "rotation": [15, -15, 0], + "cubes": [ + {"name": "rightwing_bone", "origin": [-10, 9, -3], "size": [9, 0, 6], "uv": [0, 18]} + ] + }, + { + "name": "leftwing_bone", + "parent": "body", + "pivot": [2, 9, -3], + "rotation": [15, 15, 0], + "cubes": [ + {"name": "leftwing_bone", "origin": [2, 9, -3], "size": [9, 0, 6], "uv": [9, 24]} + ] + }, + { + "name": "leg_front", + "parent": "body", + "pivot": [2, 2, -2], + "cubes": [ + {"name": "leg_front", "origin": [-3, 0, -2], "size": [7, 2, 0], "uv": [26, 1]} + ] + }, + { + "name": "leg_mid", + "parent": "body", + "pivot": [2, 2, 0], + "cubes": [ + {"name": "leg_mid", "origin": [-3, 0, 0], "size": [7, 2, 0], "uv": [26, 3]} + ] + }, + { + "name": "leg_back", + "parent": "body", + "pivot": [2, 2, 2], + "cubes": [ + {"name": "leg_back", "origin": [-3, 0, 2], "size": [7, 2, 0], "uv": [26, 5]} + ] + } + ] +}`; +skin_presets.cat = `{ + "name": "cat", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "body", + "pivot": [0, 7, 1] + }, + { + "name": "belly", + "parent": "body", + "pivot": [0, 7, 1], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-2, -1, -2], "size": [4, 16, 6], "uv": [20, 0]} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 9, -9], + "cubes": [ + {"name": "head", "origin": [-2.5, 7, -12], "size": [5, 4, 5], "uv": [0, 0]}, + {"name": "head", "origin": [-1.5, 7.01562, -13], "size": [3, 2, 2], "uv": [0, 24]}, + {"name": "head", "origin": [-2, 11, -9], "size": [1, 1, 2], "uv": [0, 10]}, + {"name": "head", "origin": [1, 11, -9], "size": [1, 1, 2], "uv": [6, 10]} + ] + }, + { + "name": "tail1", + "parent": "body", + "pivot": [0, 9, 8], + "rotation": [45, 0, 0], + "cubes": [ + {"name": "tail1", "origin": [-0.5, 1, 8], "size": [1, 8, 1], "uv": [0, 15]} + ] + }, + { + "name": "tail2", + "parent": "tail1", + "pivot": [0, 1, 8], + "rotation": [45, 0, 0], + "cubes": [ + {"name": "tail2", "origin": [-0.5, -7, 8], "size": [1, 8, 1], "uv": [4, 15]} + ] + }, + { + "name": "backLegL", + "parent": "body", + "pivot": [1.1, 6, 7], + "cubes": [ + {"name": "backLegL", "origin": [0.1, 0, 6], "size": [2, 6, 2], "uv": [8, 13]} + ] + }, + { + "name": "backLegR", + "parent": "body", + "pivot": [-1.1, 6, 7], + "cubes": [ + {"name": "backLegR", "origin": [-2.1, 0, 6], "size": [2, 6, 2], "uv": [8, 13]} + ] + }, + { + "name": "frontLegL", + "parent": "body", + "pivot": [1.2, 10, -4], + "cubes": [ + {"name": "frontLegL", "origin": [0.2, 0.2, -5], "size": [2, 10, 2], "uv": [40, 0]} + ] + }, + { + "name": "frontLegR", + "parent": "body", + "pivot": [-1.2, 10, -4], + "cubes": [ + {"name": "frontLegR", "origin": [-2.2, 0.2, -5], "size": [2, 10, 2], "uv": [40, 0]} + ] + } + ] +}`; +skin_presets.chicken = `{ + "name": "chicken", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "body", + "pivot": [0, 8, 0], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-3, 4, -3], "size": [6, 8, 6], "uv": [0, 9]} + ] + }, + { + "name": "head", + "pivot": [0, 9, -4], + "cubes": [ + {"name": "head", "origin": [-2, 9, -6], "size": [4, 6, 3], "uv": [0, 0]} + ] + }, + { + "name": "comb", + "parent": "head", + "pivot": [0, 9, -4], + "cubes": [ + {"name": "comb", "origin": [-1, 9, -7], "size": [2, 2, 2], "uv": [14, 4]} + ] + }, + { + "name": "beak", + "parent": "head", + "pivot": [0, 9, -4], + "cubes": [ + {"name": "beak", "origin": [-2, 11, -8], "size": [4, 2, 2], "uv": [14, 0]} + ] + }, + { + "name": "leg0", + "pivot": [-2, 5, 1], + "cubes": [ + {"name": "leg0", "origin": [-3, 0, -2], "size": [3, 5, 3], "uv": [26, 0]} + ] + }, + { + "name": "leg1", + "pivot": [1, 5, 1], + "cubes": [ + {"name": "leg1", "origin": [0, 0, -2], "size": [3, 5, 3], "uv": [26, 0]} + ] + }, + { + "name": "wing0", + "pivot": [-3, 11, 0], + "cubes": [ + {"name": "wing0", "origin": [-4, 7, -3], "size": [1, 4, 6], "uv": [24, 13]} + ] + }, + { + "name": "wing1", + "pivot": [3, 11, 0], + "cubes": [ + {"name": "wing1", "origin": [3, 7, -3], "size": [1, 4, 6], "uv": [24, 13]} + ] + } + ] +}`; +skin_presets.cod = `{ + "name": "cod", + "texturewidth": 32, + "textureheight": 32, + "eyes": [ + [7, 9], + [11, 9] + ], + "bones": [ + { + "name": "body", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-1, 0, 1], "size": [2, 4, 7], "uv": [0, 0]}, + {"name": "body", "origin": [0, 4, 0], "size": [0, 1, 6], "uv": [20, -6]}, + {"name": "body", "origin": [0, -1, 3], "size": [0, 1, 2], "uv": [22, -1]} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 2, 0], + "cubes": [ + {"name": "head", "origin": [-0.9992, 1.0008, -3], "size": [2, 3, 1], "uv": [0, 0]}, + {"name": "head", "origin": [-1, 0, -2], "size": [2, 4, 3], "uv": [11, 0]} + ] + }, + { + "name": "leftFin", + "parent": "body", + "pivot": [1, 1, 0], + "rotation": [0, 0, 35], + "cubes": [ + {"name": "leftFin", "origin": [1, 0, 0], "size": [2, 1, 2], "uv": [24, 4]} + ] + }, + { + "name": "rightFin", + "parent": "body", + "pivot": [-1, 1, 0], + "rotation": [0, 0, -35], + "cubes": [ + {"name": "rightFin", "origin": [-3, 0, 0], "size": [2, 1, 2], "uv": [24, 1]} + ] + }, + { + "name": "tailfin", + "parent": "body", + "pivot": [0, 0, 8], + "cubes": [ + {"name": "tailfin", "origin": [0, 0, 8], "size": [0, 4, 6], "uv": [20, 1]} + ] + }, + { + "name": "waist", + "parent": "body", + "pivot": [0, 0, 0] + } + ] +}`; +skin_presets.cow = `{ + "name": "cow", + "texturewidth": 64, + "textureheight": 32, + "eyes": [ + [7, 9], + [11, 9] + ], + "bones": [ + { + "name": "body", + "pivot": [0, 19, 2], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-6, 11, -5], "size": [12, 18, 10], "uv": [18, 4]}, + {"name": "body", "origin": [-2, 11, -6], "size": [4, 6, 1], "uv": [52, 0]} + ] + }, + { + "name": "head", + "pivot": [0, 20, -8], + "cubes": [ + {"name": "head", "origin": [-4, 16, -14], "size": [8, 8, 6], "uv": [0, 0]}, + {"name": "head", "origin": [-5, 22, -12], "size": [1, 3, 1], "uv": [22, 0]}, + {"name": "head", "origin": [4, 22, -12], "size": [1, 3, 1], "uv": [22, 0]} + ] + }, + { + "name": "leg0", + "pivot": [-4, 12, 7], + "cubes": [ + {"name": "leg0", "origin": [-6, 0, 5], "size": [4, 12, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg1", + "pivot": [4, 12, 7], + "mirror": true, + "cubes": [ + {"name": "leg1", "origin": [2, 0, 5], "size": [4, 12, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg2", + "pivot": [-4, 12, -6], + "cubes": [ + {"name": "leg2", "origin": [-6, 0, -7], "size": [4, 12, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg3", + "pivot": [4, 12, -6], + "mirror": true, + "cubes": [ + {"name": "leg3", "origin": [2, 0, -7], "size": [4, 12, 4], "uv": [0, 16]} + ] + } + ] +}`; +skin_presets.dolphin = `{ + "name": "dolphin", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "body", + "pivot": [0, 0, -3], + "cubes": [ + {"name": "body", "origin": [-4, 0, -3], "size": [8, 7, 13], "uv": [0, 13]} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 0, -3], + "cubes": [ + {"name": "head", "origin": [-4, 0, -9], "size": [8, 7, 6], "uv": [0, 0]} + ] + }, + { + "name": "nose", + "parent": "head", + "pivot": [0, 0, -13], + "cubes": [ + {"name": "nose", "origin": [-1, 0, -13], "size": [2, 2, 4], "uv": [0, 13]} + ] + }, + { + "name": "tail", + "parent": "body", + "pivot": [0, 2.5, 11], + "cubes": [ + {"name": "tail", "origin": [-2, 0, 10], "size": [4, 5, 11], "uv": [0, 33]} + ] + }, + { + "name": "tail_fin", + "parent": "tail", + "pivot": [0, 2.5, 20], + "cubes": [ + {"name": "tail_fin", "origin": [-5, 2, 19], "size": [10, 1, 6], "uv": [0, 49]} + ] + }, + { + "name": "back_fin", + "parent": "body", + "pivot": [0, 7, 2], + "rotation": [-30, 0, 0], + "cubes": [ + {"name": "back_fin", "origin": [-0.5, 6.25, 1], "size": [1, 5, 4], "uv": [29, 0]} + ] + }, + { + "name": "left_fin", + "parent": "body", + "pivot": [3, 1, -1], + "rotation": [0, -25, 20], + "cubes": [ + {"name": "left_fin", "origin": [3, 1, -2.5], "size": [8, 1, 4], "uv": [40, 0]} + ] + }, + { + "name": "right_fin", + "parent": "body", + "pivot": [-3, 1, -1], + "rotation": [0, 25, -20], + "cubes": [ + {"name": "right_fin", "origin": [-11, 1, -2.5], "size": [8, 1, 4], "uv": [40, 6]} + ] + } + ] +}`; +skin_presets.enderman = `{ + "name": "enderman:geometry", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 40, -4], "size": [8, 8, 8], "uv": [0, 0], "inflate": -0.5}, + {"name": "head layer", "origin": [-4, 38, -4], "size": [8, 8, 8], "uv": [0, 16], "inflate": -0.5} + ] + }, + { + "name": "body", + "pivot": [0, 38, 0], + "cubes": [ + {"name": "body", "origin": [-4, 26, -2], "size": [8, 12, 4], "uv": [32, 16]} + ] + }, + { + "name": "rightArm", + "pivot": [-3, 36, 0], + "cubes": [ + {"name": "rightArm", "origin": [-6, 8, -1], "size": [2, 30, 2], "uv": [56, 0]} + ] + }, + { + "name": "leftArm", + "pivot": [5, 36, 0], + "mirror": true, + "cubes": [ + {"name": "leftArm", "origin": [4, 8, -1], "size": [2, 30, 2], "uv": [56, 0]} + ] + }, + { + "name": "rightLeg", + "pivot": [-2, 26, 0], + "cubes": [ + {"name": "rightLeg", "origin": [-3, -4, -1], "size": [2, 30, 2], "uv": [56, 0]} + ] + }, + { + "name": "leftLeg", + "pivot": [2, 26, 0], + "mirror": true, + "cubes": [ + {"name": "leftLeg", "origin": [1, -4, -1], "size": [2, 30, 2], "uv": [56, 0]} + ] + } + ] +}`; +skin_presets.endermite = `{ + "name": "endermite", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "section_2", + "pivot": [0, 0, 2.5], + "cubes": [ + {"name": "section_2", "origin": [-1.5, 0, 2.5], "size": [3, 3, 1], "uv": [0, 14]} + ] + }, + { + "name": "section_0", + "parent": "section_2", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "section_0", "origin": [-2, 0, -4.4], "size": [4, 3, 2], "uv": [0, 0]} + ] + }, + { + "name": "section_1", + "parent": "section_2", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "section_1", "origin": [-3, 0, -2.4], "size": [6, 4, 5], "uv": [0, 5]} + ] + }, + { + "name": "section_3", + "parent": "section_2", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "section_3", "origin": [-0.5, 0, 3.5], "size": [1, 2, 1], "uv": [0, 18]} + ] + } + ] +}`; +skin_presets.evoker = `{ + "name": "evoker", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, + {"name": "body", "origin": [-4, 6, -3], "size": [8, 18, 6], "uv": [0, 38], "inflate": 0.5} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} + ] + }, + { + "name": "nose", + "parent": "head", + "pivot": [0, 26, 0], + "cubes": [ + {"name": "nose", "origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]} + ] + }, + { + "name": "arms", + "parent": "body", + "pivot": [0, 22, 0], + "cubes": [ + {"name": "arms", "origin": [-8, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, + {"name": "arms", "origin": [4, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, + {"name": "arms", "origin": [-4, 16, -2], "size": [8, 4, 4], "uv": [40, 38]} + ] + }, + { + "name": "leg0", + "parent": "body", + "pivot": [-2, 12, 0], + "cubes": [ + {"name": "leg0", "origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "leg1", + "parent": "body", + "pivot": [2, 12, 0], + "mirror": true, + "cubes": [ + {"name": "leg1", "origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "rightArm", + "parent": "body", + "pivot": [-5, 22, 0], + "cubes": [ + {"name": "rightArm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} + ] + }, + { + "name": "rightItem", + "parent": "rightArm", + "pivot": [-5.5, 16, 0.5] + }, + { + "name": "leftArm", + "parent": "body", + "pivot": [5, 22, 0], + "mirror": true, + "cubes": [ + {"name": "leftArm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} + ] + } + ] +}`; +skin_presets.fox = `{ + "name": "fox", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "body", + "pivot": [0, 8, 0], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-3, 0, -3], "size": [6, 11, 6], "uv": [30, 15]} + ] + }, + { + "name": "head", + "pivot": [0, 8, -3], + "cubes": [ + {"name": "head", "origin": [-4, 4, -9], "size": [8, 6, 6], "uv": [0, 0]}, + {"name": "head", "origin": [-4, 10, -8], "size": [2, 2, 1], "uv": [0, 0]}, + {"name": "head", "origin": [2, 10, -8], "size": [2, 2, 1], "uv": [22, 0]}, + {"name": "head", "origin": [-2, 4, -12], "size": [4, 2, 3], "uv": [0, 24]}, + {"name": "head_sleeping", "visibility": false, "origin": [-4, 4, -9], "size": [8, 6, 6], "uv": [0, 12]} + ] + }, + { + "name": "leg0", + "pivot": [-3, 6, 6], + "cubes": [ + {"name": "leg0", "origin": [-3.005, 0, 5], "size": [2, 6, 2], "uv": [14, 24]} + ] + }, + { + "name": "leg1", + "pivot": [1, 6, 6], + "cubes": [ + {"name": "leg1", "origin": [1.005, 0, 5], "size": [2, 6, 2], "uv": [22, 24]} + ] + }, + { + "name": "leg2", + "pivot": [-3, 6, -1], + "cubes": [ + {"name": "leg2", "origin": [-3.005, 0, -2], "size": [2, 6, 2], "uv": [14, 24]} + ] + }, + { + "name": "leg3", + "pivot": [1, 6, -1], + "cubes": [ + {"name": "leg3", "origin": [1.005, 0, -2], "size": [2, 6, 2], "uv": [22, 24]} + ] + }, + { + "name": "tail", + "pivot": [0, 8, 7], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "tail", "origin": [-2, -2, 4.75], "size": [4, 9, 5], "uv": [28, 0]} + ] + } + ] +}`; +skin_presets.ghast = `{ + "name": "ghast", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "body", + "pivot": [0, 8, 0], + "cubes": [ + {"name": "body", "origin": [-8, 0, -8], "size": [16, 16, 16], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_0", + "parent": "body", + "pivot": [-3.8, 1, -5], + "cubes": [ + {"name": "tentacles_0", "origin": [-4.8, -8, -6], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_1", + "parent": "body", + "pivot": [1.3, 1, -5], + "cubes": [ + {"name": "tentacles_1", "origin": [0.3, -10, -6], "size": [2, 11, 2], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_2", + "parent": "body", + "pivot": [6.3, 1, -5], + "cubes": [ + {"name": "tentacles_2", "origin": [5.3, -7, -6], "size": [2, 8, 2], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_3", + "parent": "body", + "pivot": [-6.3, 1, 0], + "cubes": [ + {"name": "tentacles_3", "origin": [-7.3, -8, -1], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_4", + "parent": "body", + "pivot": [-1.3, 1, 0], + "cubes": [ + {"name": "tentacles_4", "origin": [-2.3, -12, -1], "size": [2, 13, 2], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_5", + "parent": "body", + "pivot": [3.8, 1, 0], + "cubes": [ + {"name": "tentacles_5", "origin": [2.8, -10, -1], "size": [2, 11, 2], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_6", + "parent": "body", + "pivot": [-3.8, 1, 5], + "cubes": [ + {"name": "tentacles_6", "origin": [-4.8, -11, 4], "size": [2, 12, 2], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_7", + "parent": "body", + "pivot": [1.3, 1, 5], + "cubes": [ + {"name": "tentacles_7", "origin": [0.3, -11, 4], "size": [2, 12, 2], "uv": [0, 0]} + ] + }, + { + "name": "tentacles_8", + "parent": "body", + "pivot": [6.3, 1, 5], + "cubes": [ + {"name": "tentacles_8", "origin": [5.3, -12, 4], "size": [2, 13, 2], "uv": [0, 0]} + ] + } + ] +}`; +skin_presets.guardian = `{ + "name": "guardian", + "texturewidth": 64, + "textureheight": 64, + "eyes": [ + [19, 21, 6, 3] + ], + "bones": [ + { + "name": "head", + "pivot": [0, 0, 0], + "mirror": true, + "cubes": [ + {"name": "head", "origin": [-6, 2, -8], "size": [12, 12, 16], "uv": [0, 0], "mirror": false}, + {"name": "head", "origin": [-8, 2, -6], "size": [2, 12, 12], "uv": [0, 28], "mirror": false}, + {"name": "head", "origin": [6, 2, -6], "size": [2, 12, 12], "uv": [0, 28]}, + {"name": "head", "origin": [-6, 14, -6], "size": [12, 2, 12], "uv": [16, 40]}, + {"name": "head", "origin": [-6, 0, -6], "size": [12, 2, 12], "uv": [16, 40]} + ] + }, + { + "name": "eye", + "parent": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "eye", "origin": [-1, 7, -8.25], "size": [2, 2, 1], "uv": [8, 0]} + ] + }, + { + "name": "tailpart0", + "parent": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "tailpart0", "origin": [-2, 6, 8], "size": [4, 4, 8], "uv": [40, 0]} + ] + }, + { + "name": "tailpart1", + "parent": "tailpart0", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "tailpart1", "origin": [-1.5, 7, 16], "size": [3, 3, 7], "uv": [0, 54]} + ] + }, + { + "name": "tailpart2", + "parent": "tailpart1", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "tailpart2", "origin": [-1, 8, 23], "size": [2, 2, 6], "uv": [41, 32]}, + {"name": "tailpart2", "origin": [0, 4.5, 26], "size": [1, 9, 9], "uv": [25, 19]} + ] + }, + { + "name": "spikepart0", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [0, 0, 45], + "cubes": [ + {"name": "spikepart0", "origin": [10.25, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart1", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [0, 0, -45], + "cubes": [ + {"name": "spikepart1", "origin": [-12.25, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart2", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [45, 0, 0], + "cubes": [ + {"name": "spikepart2", "origin": [-1, 19.5, -12.25], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart3", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [-45, 0, 0], + "cubes": [ + {"name": "spikepart3", "origin": [-1, 19.5, 10.5], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart4", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [0, 0, 135], + "cubes": [ + {"name": "spikepart4", "origin": [10.25, 42.5, -1], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart5", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [0, 0, -135], + "cubes": [ + {"name": "spikepart5", "origin": [-12.25, 42.5, -1], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart6", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [135, 0, 0], + "cubes": [ + {"name": "spikepart6", "origin": [-1, 43.5, -12.25], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart7", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [-135, 0, 0], + "cubes": [ + {"name": "spikepart7", "origin": [-1, 42.5, 10.25], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart8", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [90, -45, 0], + "cubes": [ + {"name": "spikepart8", "origin": [-1, 32.5, -17], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart9", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [90, 45, 0], + "cubes": [ + {"name": "spikepart8", "origin": [-1, 32.5, -17], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart10", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [90, -135, 0], + "cubes": [ + {"name": "spikepart8", "origin": [-1, 32.5, -17], "size": [2, 9, 2], "uv": [0, 0]} + ] + }, + { + "name": "spikepart11", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [90, 135, 0], + "cubes": [ + {"name": "spikepart8", "origin": [-1, 32.5, -17], "size": [2, 9, 2], "uv": [0, 0]} + ] + } + ] +}`; +skin_presets.horse = `{ + "name": "horse", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "Body", + "pivot": [0, 13, 9], + "cubes": [ + {"name": "Body", "origin": [-5, 11, -11], "size": [10, 10, 22], "uv": [0, 32]} + ] + }, + { + "name": "TailA", + "pivot": [0, 20, 11], + "rotation": [30, 0, 0], + "cubes": [ + {"name": "TailA", "origin": [-1.5, 6, 9], "size": [3, 14, 4], "uv": [42, 36]} + ] + }, + { + "name": "Leg1A", + "pivot": [3, 11, 9], + "cubes": [ + {"name": "Leg1A", "origin": [1, 0, 7], "size": [4, 11, 4], "uv": [48, 21], "mirror": true} + ] + }, + { + "name": "Leg2A", + "pivot": [-3, 11, 9], + "cubes": [ + {"name": "Leg2A", "origin": [-5, 0, 7], "size": [4, 11, 4], "uv": [48, 21]} + ] + }, + { + "name": "Leg3A", + "pivot": [3, 11, -9], + "cubes": [ + {"name": "Leg3A", "origin": [1, 0, -11], "size": [4, 11, 4], "uv": [48, 21], "mirror": true} + ] + }, + { + "name": "Leg4A", + "pivot": [-3, 11, -9], + "cubes": [ + {"name": "Leg4A", "origin": [-5, 0, -11], "size": [4, 11, 4], "uv": [48, 21]} + ] + }, + { + "name": "Head", + "pivot": [0, 28, -11], + "rotation": [30, 0, 0], + "cubes": [ + {"name": "Head", "origin": [-3, 28, -17], "size": [6, 5, 7], "uv": [0, 13]}, + {"name": "UMouth", "origin": [-2, 28, -22], "size": [4, 5, 5], "uv": [0, 25]} + ] + }, + { + "name": "Ear1", + "pivot": [0, 17, -8], + "rotation": [30, 0, 5], + "cubes": [ + {"name": "Ear1", "origin": [-0.5, 32, -5.01], "size": [2, 3, 1], "uv": [19, 16], "mirror": true} + ] + }, + { + "name": "Ear2", + "pivot": [0, 17, -8], + "rotation": [30, 0, -5], + "cubes": [ + {"name": "Ear2", "origin": [-1.5, 32, -5.01], "size": [2, 3, 1], "uv": [19, 16]} + ] + }, + { + "name": "MuleEarL", + "pivot": [0, 17, -8], + "rotation": [30, 0, 15], + "cubes": [ + {"name": "MuleEarL", "visibility": false, "origin": [-3, 32, -5.01], "size": [2, 7, 1], "uv": [0, 12], "mirror": true} + ] + }, + { + "name": "MuleEarR", + "pivot": [0, 17, -8], + "rotation": [30, 0, -15], + "cubes": [ + {"name": "MuleEarR", "visibility": false, "origin": [1, 32, -5.01], "size": [2, 7, 1], "uv": [0, 12]} + ] + }, + { + "name": "Neck", + "pivot": [0, 17, -8], + "rotation": [30, 0, 0], + "cubes": [ + {"name": "Neck", "origin": [-2, 16, -11], "size": [4, 12, 7], "uv": [0, 35]}, + {"name": "Mane", "origin": [-1, 17, -4], "size": [2, 16, 2], "uv": [56, 36]} + ] + }, + { + "name": "Bag1", + "pivot": [-5, 21, 11], + "rotation": [0, -90, 0], + "cubes": [ + {"name": "Bag1", "visibility": false, "origin": [-14, 13, 11], "size": [8, 8, 3], "uv": [26, 21]} + ] + }, + { + "name": "Bag2", + "pivot": [5, 21, 11], + "rotation": [0, 90, 0], + "cubes": [ + {"name": "Bag2", "visibility": false, "origin": [6, 13, 11], "size": [8, 8, 3], "uv": [26, 21], "mirror": true} + ] + }, + { + "name": "Saddle", + "pivot": [0, 22, 2], + "cubes": [ + {"name": "Saddle", "origin": [-5, 12, -3.5], "size": [10, 9, 9], "uv": [26, 0], "inflate": 0.5} + ] + }, + { + "name": "SaddleMouthL", + "pivot": [0, 17, -8], + "rotation": [30, 0, 0], + "cubes": [ + {"name": "SaddleMouthL", "origin": [2, 29, -14], "size": [1, 2, 2], "uv": [29, 5]} + ] + }, + { + "name": "SaddleMouthR", + "pivot": [0, 17, -8], + "rotation": [30, 0, 0], + "cubes": [ + {"name": "SaddleMouthR", "origin": [-3, 29, -14], "size": [1, 2, 2], "uv": [29, 5]} + ] + }, + { + "name": "SaddleMouthLine", + "pivot": [0, 17, -8], + "cubes": [ + {"name": "SaddleMouthLine", "origin": [3.1, 24, -19.5], "size": [0, 3, 16], "uv": [32, 2]} + ] + }, + { + "name": "SaddleMouthLineR", + "pivot": [0, 17, -8], + "cubes": [ + {"name": "SaddleMouthLineR", "origin": [-3.1, 24, -19.5], "size": [0, 3, 16], "uv": [32, 2]} + ] + }, + { + "name": "HeadSaddle", + "pivot": [0, 17, -8], + "rotation": [30, 0, 0], + "cubes": [ + {"name": "HeadSaddle", "origin": [-2, 28, -13], "size": [4, 5, 2], "uv": [19, 0], "inflate": 0.25}, + {"name": "HeadSaddle", "visibility": false, "origin": [-3, 28, -11], "size": [6, 5, 7], "uv": [0, 0], "inflate": 0.25} + ] + } + ] +}`; +skin_presets.llama = `{ + "name": "llama", + "texturewidth": 128, + "textureheight": 64, + "eyes": [ + [7, 21], + [11, 21] + ], + "bones": [ + { + "name": "head", + "pivot": [0, 17, -6], + "cubes": [ + {"name": "head", "origin": [-2, 27, -16], "size": [4, 4, 9], "uv": [0, 0]}, + {"name": "head", "origin": [-4, 15, -12], "size": [8, 18, 6], "uv": [0, 14]}, + {"name": "head", "origin": [-4, 33, -10], "size": [3, 3, 2], "uv": [17, 0]}, + {"name": "head", "origin": [1, 33, -10], "size": [3, 3, 2], "uv": [17, 0]} + ] + }, + { + "name": "chest1", + "pivot": [-8.5, 21, 3], + "rotation": [0, 90, 0], + "cubes": [ + {"name": "chest1", "origin": [-11.5, 13, 3], "size": [8, 8, 3], "uv": [45, 28]} + ] + }, + { + "name": "chest2", + "pivot": [5.5, 21, 3], + "rotation": [0, 90, 0], + "cubes": [ + {"name": "chest2", "origin": [2.5, 13, 3], "size": [8, 8, 3], "uv": [45, 41]} + ] + }, + { + "name": "body", + "pivot": [0, 19, 2], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-6, 11, -5], "size": [12, 18, 10], "uv": [29, 0]} + ] + }, + { + "name": "leg0", + "pivot": [-3.5, 14, 6], + "cubes": [ + {"name": "leg0", "origin": [-5.5, 0, 4], "size": [4, 14, 4], "uv": [29, 29]} + ] + }, + { + "name": "leg1", + "pivot": [3.5, 14, 6], + "cubes": [ + {"name": "leg1", "origin": [1.5, 0, 4], "size": [4, 14, 4], "uv": [29, 29]} + ] + }, + { + "name": "leg2", + "pivot": [-3.5, 14, -5], + "cubes": [ + {"name": "leg2", "origin": [-5.5, 0, -7], "size": [4, 14, 4], "uv": [29, 29]} + ] + }, + { + "name": "leg3", + "pivot": [3.5, 14, -5], + "cubes": [ + {"name": "leg3", "origin": [1.5, 0, -7], "size": [4, 14, 4], "uv": [29, 29]} + ] + } + ] +}`; +skin_presets.lavaslime = `{ + "name": "lavaslime", + "texturewidth": 64, + "textureheight": 32, + "eyes": [ + [33, 18, 2, 1], + [37, 18, 2, 1], + [33, 27, 2, 1], + [37, 27, 2, 1] + ], + "bones": [ + { + "name": "insideCube", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "insideCube", "origin": [-2, 2, -2], "size": [4, 4, 4], "uv": [0, 16]} + ] + }, + { + "name": "bodyCube_0", + "parent": "insideCube", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "bodyCube_0", "origin": [-4, 7, -4], "size": [8, 1, 8], "uv": [0, 0]} + ] + }, + { + "name": "bodyCube_1", + "parent": "insideCube", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "bodyCube_1", "origin": [-4, 6, -4], "size": [8, 1, 8], "uv": [0, 1]} + ] + }, + { + "name": "bodyCube_2", + "parent": "insideCube", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "bodyCube_2", "origin": [-4, 5, -4], "size": [8, 1, 8], "uv": [24, 10]} + ] + }, + { + "name": "bodyCube_3", + "parent": "insideCube", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "bodyCube_3", "origin": [-4, 4, -4], "size": [8, 1, 8], "uv": [24, 19]} + ] + }, + { + "name": "bodyCube_4", + "parent": "insideCube", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "bodyCube_4", "origin": [-4, 3, -4], "size": [8, 1, 8], "uv": [0, 4]} + ] + }, + { + "name": "bodyCube_5", + "parent": "insideCube", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "bodyCube_5", "origin": [-4, 2, -4], "size": [8, 1, 8], "uv": [0, 5]} + ] + }, + { + "name": "bodyCube_6", + "parent": "insideCube", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "bodyCube_6", "origin": [-4, 1, -4], "size": [8, 1, 8], "uv": [0, 6]} + ] + }, + { + "name": "bodyCube_7", + "parent": "insideCube", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "bodyCube_7", "origin": [-4, 0, -4], "size": [8, 1, 8], "uv": [0, 7]} + ] + } + ] +}`; +skin_presets.panda = `{ + "name": "panda", + "texturewidth": 64, + "textureheight": 64, + "eyes": [ + [11, 19, 2, 1], + [18, 19, 2, 1], + ], + "bones": [ + { + "name": "body", + "pivot": [0, 14, 0], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-9.5, 1, -6.5], "size": [19, 26, 13], "uv": [0, 25]} + ] + }, + { + "name": "head", + "pivot": [0, 12.5, -17], + "cubes": [ + {"name": "head", "origin": [-6.5, 7.5, -21], "size": [13, 10, 9], "uv": [0, 6]}, + {"name": "head", "origin": [-3.5, 7.5, -23], "size": [7, 5, 2], "uv": [45, 16]}, + {"name": "head", "origin": [-8.5, 16.5, -18], "size": [5, 4, 1], "uv": [52, 25]}, + {"name": "head", "origin": [3.5, 16.5, -18], "size": [5, 4, 1], "uv": [52, 25]} + ] + }, + { + "name": "leg0", + "pivot": [-5.5, 9, 9], + "cubes": [ + {"name": "leg0", "origin": [-8.5, 0, 6], "size": [6, 9, 6], "uv": [40, 0]} + ] + }, + { + "name": "leg1", + "pivot": [5.5, 9, 9], + "cubes": [ + {"name": "leg1", "origin": [2.5, 0, 6], "size": [6, 9, 6], "uv": [40, 0]} + ] + }, + { + "name": "leg2", + "pivot": [-5.5, 9, -9], + "cubes": [ + {"name": "leg2", "origin": [-8.5, 0, -12], "size": [6, 9, 6], "uv": [40, 0]} + ] + }, + { + "name": "leg3", + "pivot": [5.5, 9, -9], + "cubes": [ + {"name": "leg3", "origin": [2.5, 0, -12], "size": [6, 9, 6], "uv": [40, 0]} + ] + } + ] +}`; +skin_presets.parrot = `{ + "name": "parrot", + "texturewidth": 32, + "textureheight": 32, + "bones": [ + { + "name": "body", + "pivot": [0, 7.5, -3], + "rotation": [25, 0, 0], + "cubes": [ + {"name": "body", "origin": [-1.5, 1.5, -4.5], "size": [3, 6, 3], "uv": [2, 8]} + ] + }, + { + "name": "wing0", + "parent": "body", + "pivot": [1.5, 7.1, -2.8], + "rotation": [10, 0, 0], + "cubes": [ + {"name": "wing0", "origin": [1, 2.1, -4.3], "size": [1, 5, 3], "uv": [19, 8]} + ] + }, + { + "name": "wing1", + "parent": "body", + "pivot": [-1.5, 7.1, -2.8], + "rotation": [10, 0, 0], + "cubes": [ + {"name": "wing1", "origin": [-2, 2.1, -4.3], "size": [1, 5, 3], "uv": [19, 8]} + ] + }, + { + "name": "head", + "pivot": [0, 8.3, -2.8], + "cubes": [ + {"name": "head", "origin": [-1, 6.8, -3.8], "size": [2, 3, 2], "uv": [2, 2]}, + {"name": "head2", "origin": [-1, 9.8, -5.8], "size": [2, 1, 4], "uv": [10, 0]}, + {"name": "beak1", "origin": [-0.5, 7.8, -4.7], "size": [1, 2, 1], "uv": [11, 7]}, + {"name": "beak2", "origin": [-0.5, 8.1, -5.7], "size": [1, 1.7, 1], "uv": [16, 7]}, + {"name": "feather", "origin": [0, 9.1, -4.9], "size": [0, 5, 4], "uv": [2, 18]} + ] + }, + { + "name": "tail", + "pivot": [0, 2.9, 1.2], + "rotation": [50, 0, 0], + "cubes": [ + {"name": "tail", "origin": [-1.5, -0.1, 0.2], "size": [3, 4, 1], "uv": [22, 1]} + ] + }, + { + "name": "leg0", + "pivot": [1.5, 1, -0.5], + "cubes": [ + {"name": "leg0", "origin": [0.5, -0.5, -1.5], "size": [1, 2, 1], "uv": [14, 18]} + ] + }, + { + "name": "leg1", + "pivot": [-0.5, 1, -0.5], + "cubes": [ + {"name": "leg1", "origin": [-1.5, -0.5, -1.5], "size": [1, 2, 1], "uv": [14, 18]} + ] + } + ] +}`; +skin_presets.phantom = `{ + "name": "phantom", + "eyes": [ + [5, 6, 2, 1], + [10, 6, 2, 1], + ], + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-3, 23, -8], "size": [5, 3, 9], "uv": [0, 8]} + ] + }, + { + "name": "wing0", + "parent": "body", + "pivot": [2, 26, -8], + "rotation": [0, 0, 5], + "cubes": [ + {"name": "wing0", "origin": [2, 24, -8], "size": [6, 2, 9], "uv": [23, 12]} + ] + }, + { + "name": "wingtip0", + "parent": "wing0", + "pivot": [8, 26, -8], + "rotation": [0, 0, 10], + "cubes": [ + {"name": "wingtip0", "origin": [8, 25, -8], "size": [13, 1, 9], "uv": [16, 24]} + ] + }, + { + "name": "wing1", + "parent": "body", + "pivot": [-3, 26, -8], + "rotation": [0, 0, -5], + "mirror": true, + "cubes": [ + {"name": "wing1", "origin": [-9, 24, -8], "size": [6, 2, 9], "uv": [23, 12]} + ] + }, + { + "name": "wingtip1", + "parent": "wing1", + "pivot": [-9, 26, -8], + "rotation": [0, 0, -10], + "mirror": true, + "cubes": [ + {"name": "wingtip1", "origin": [-22, 25, -8], "size": [13, 1, 9], "uv": [16, 24]} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 23, -7], + "cubes": [ + {"name": "head", "origin": [-4, 22, -12], "size": [7, 3, 5], "uv": [0, 0]} + ] + }, + { + "name": "tail", + "parent": "body", + "pivot": [0, 26, 1], + "rotation": [-5, 0, 0], + "cubes": [ + {"name": "tail", "origin": [-2, 24, 1], "size": [3, 2, 6], "uv": [3, 20]} + ] + }, + { + "name": "tailtip", + "parent": "tail", + "pivot": [0, 25.5, 7], + "rotation": [-5, 0, 0], + "cubes": [ + {"name": "tailtip", "origin": [-1, 24.5, 7], "size": [1, 1, 6], "uv": [4, 29]} + ] + } + ] +}`; +skin_presets.pig = `{ + "name": "pig", + "texturewidth": 64, + "textureheight": 32, + "eyes": [ + [8, 11, 2, 1], + [14, 11, 2, 1] + ], + "bones": [ + { + "name": "body", + "pivot": [0, 13, 2], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-5, 7, -5], "size": [10, 16, 8], "uv": [28, 8]} + ] + }, + { + "name": "head", + "pivot": [0, 12, -6], + "cubes": [ + {"name": "head", "origin": [-4, 8, -14], "size": [8, 8, 8], "uv": [0, 0]}, + {"name": "head", "origin": [-2, 9, -15], "size": [4, 3, 1], "uv": [16, 16]} + ] + }, + { + "name": "leg0", + "pivot": [-3, 6, 7], + "cubes": [ + {"name": "leg0", "origin": [-5, 0, 5], "size": [4, 6, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg1", + "pivot": [3, 6, 7], + "mirror": true, + "cubes": [ + {"name": "leg1", "origin": [1, 0, 5], "size": [4, 6, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg2", + "pivot": [-3, 6, -5], + "cubes": [ + {"name": "leg2", "origin": [-5, 0, -7], "size": [4, 6, 4], "uv": [0, 16]} + ] + }, + { + "name": "leg3", + "pivot": [3, 6, -5], + "mirror": true, + "cubes": [ + {"name": "leg3", "origin": [1, 0, -7], "size": [4, 6, 4], "uv": [0, 16]} + ] + } + ] +}`; +skin_presets.pillager = `{ + "name": "pillager", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "waist", + "pivot": [0, 12, 0] + }, + { + "name": "body", + "parent": "waist", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, + {"name": "body", "origin": [-4, 6, -3], "size": [8, 18, 6], "uv": [0, 38], "inflate": 0.5} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} + ] + }, + { + "name": "nose", + "parent": "head", + "pivot": [0, 26, 0], + "cubes": [ + {"name": "nose", "origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]} + ] + }, + { + "name": "leftLeg", + "parent": "body", + "pivot": [2, 12, 0], + "cubes": [ + {"name": "leftLeg", "origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "rightLeg", + "parent": "body", + "pivot": [-2, 12, 0], + "mirror": true, + "cubes": [ + {"name": "rightLeg", "origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "rightarm", + "parent": "body", + "pivot": [-5, 22, 0], + "cubes": [ + {"name": "rightarm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} + ] + }, + { + "name": "leftarm", + "parent": "body", + "pivot": [5, 22, 0], + "mirror": true, + "cubes": [ + {"name": "leftarm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} + ] + } + ] +}`; +skin_presets.polarbear = `{ + "name": "polarbear", + "texturewidth": 128, + "textureheight": 64, + "bones": [ + { + "name": "body", + "pivot": [-2, 15, 12], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-7, 14, 5], "size": [14, 14, 11], "uv": [0, 19]}, + {"name": "body", "origin": [-6, 28, 5], "size": [12, 12, 10], "uv": [39, 0]} + ] + }, + { + "name": "head", + "pivot": [0, 14, -16], + "mirror": true, + "cubes": [ + {"name": "head", "origin": [-3.5, 10, -19], "size": [7, 7, 7], "uv": [0, 0], "mirror": false}, + {"name": "head", "origin": [-2.5, 10, -22], "size": [5, 3, 3], "uv": [0, 44], "mirror": false}, + {"name": "head", "origin": [-4.5, 16, -17], "size": [2, 2, 1], "uv": [26, 0], "mirror": false}, + {"name": "head", "origin": [2.5, 16, -17], "size": [2, 2, 1], "uv": [26, 0]} + ] + }, + { + "name": "leg0", + "pivot": [-4.5, 10, 6], + "cubes": [ + {"name": "leg0", "origin": [-6.5, 0, 4], "size": [4, 10, 8], "uv": [50, 22]} + ] + }, + { + "name": "leg1", + "pivot": [4.5, 10, 6], + "cubes": [ + {"name": "leg1", "origin": [2.5, 0, 4], "size": [4, 10, 8], "uv": [50, 22]} + ] + }, + { + "name": "leg2", + "pivot": [-3.5, 10, -8], + "cubes": [ + {"name": "leg2", "origin": [-5.5, 0, -10], "size": [4, 10, 6], "uv": [50, 40]} + ] + }, + { + "name": "leg3", + "pivot": [3.5, 10, -8], + "cubes": [ + {"name": "leg3", "origin": [1.5, 0, -10], "size": [4, 10, 6], "uv": [50, 40]} + ] + } + ] +}`; +skin_presets.pufferfish = `{ + "name": "pufferfish", + "texturewidth": 32, + "textureheight": 32, + "bones": [ + { + "name": "body_large", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0]} + ] + }, + { + "name": "leftFin", + "parent": "body_large", + "pivot": [4, 7, 3], + "cubes": [ + {"name": "leftFin", "origin": [4, 6, -2.9904], "size": [2, 1, 2], "uv": [24, 3]} + ] + }, + { + "name": "rightFin", + "parent": "body_large", + "pivot": [-4, 7, 1], + "cubes": [ + {"name": "rightFin", "origin": [-5.9968, 6, -2.992], "size": [2, 1, 2], "uv": [24, 0]} + ] + }, + { + "name": "spines_top_front", + "parent": "body_large", + "pivot": [-4, 8, -4], + "rotation": [45, 0, 0], + "cubes": [ + {"name": "spines_top_front", "origin": [-4, 8, -4], "size": [8, 1, 1], "uv": [14, 16]} + ] + }, + { + "name": "spines_top_mid", + "parent": "body_large", + "pivot": [0, 8, 0], + "cubes": [ + {"name": "spines_top_mid", "origin": [-4, 8, 0], "size": [8, 1, 1], "uv": [14, 16]} + ] + }, + { + "name": "spines_top_back", + "parent": "body_large", + "pivot": [0, 8, 4], + "rotation": [-45, 0, 0], + "cubes": [ + {"name": "spines_top_back", "origin": [-4, 8, 4], "size": [8, 1, 1], "uv": [14, 16]} + ] + }, + { + "name": "spines_bottom_front", + "parent": "body_large", + "pivot": [0, 0, -4], + "rotation": [-45, 0, 0], + "cubes": [ + {"name": "spines_bottom_front", "origin": [-4, -1, -4], "size": [8, 1, 1], "uv": [14, 19]} + ] + }, + { + "name": "spines_bottom_mid", + "parent": "body_large", + "pivot": [0, -1, 0], + "cubes": [ + {"name": "spines_bottom_mid", "origin": [-4, -1, 0], "size": [8, 1, 1], "uv": [14, 19]} + ] + }, + { + "name": "spines_bottom_back", + "parent": "body_large", + "pivot": [0, 0, 4], + "rotation": [45, 0, 0], + "cubes": [ + {"name": "spines_bottom_back", "origin": [-4, -1, 4], "size": [8, 1, 1], "uv": [14, 19]} + ] + }, + { + "name": "spines_left_front", + "parent": "body_large", + "pivot": [4, 0, -4], + "rotation": [0, 45, 0], + "cubes": [ + {"name": "spines_left_front", "origin": [4, 0, -4], "size": [1, 8, 1], "uv": [0, 16]} + ] + }, + { + "name": "spines_left_mid", + "parent": "body_large", + "pivot": [4, 0, 0], + "cubes": [ + {"name": "spines_left_mid", "origin": [4, 0, 0], "size": [1, 8, 1], "uv": [4, 16], "mirror": true} + ] + }, + { + "name": "spines_left_back", + "parent": "body_large", + "pivot": [4, 0, 4], + "rotation": [0, -45, 0], + "cubes": [ + {"name": "spines_left_back", "origin": [4, 0, 4], "size": [1, 8, 1], "uv": [8, 16], "mirror": true} + ] + }, + { + "name": "spines_right_front", + "parent": "body_large", + "pivot": [-4, 0, -4], + "rotation": [0, -45, 0], + "cubes": [ + {"name": "spines_right_front", "origin": [-5, 0, -4], "size": [1, 8, 1], "uv": [4, 16]} + ] + }, + { + "name": "spines_right_mid", + "parent": "body_large", + "pivot": [-4, 0, 0], + "cubes": [ + {"name": "spines_right_mid", "origin": [-5, 0, 0], "size": [1, 8, 1], "uv": [8, 16]} + ] + }, + { + "name": "spines_right_back", + "parent": "body_large", + "pivot": [-4, 0, 4], + "rotation": [0, 45, 0], + "cubes": [ + {"name": "spines_right_back", "origin": [-5, 0, 4], "size": [1, 8, 1], "uv": [8, 16]} + ] + }, + { + "name": "body_mid", + "pivot": [16, 0, 0], + "cubes": [ + {"name": "body", "origin": [13.5, 1, -2.5], "size": [5, 5, 5], "uv": [12, 22]} + ] + }, + { + "name": "leftFin", + "parent": "body_mid", + "pivot": [18.5, 5, 0.5], + "cubes": [ + {"name": "leftFin", "origin": [18.5, 4, -1.5], "size": [2, 1, 2], "uv": [24, 3]} + ] + }, + { + "name": "rightFin", + "parent": "body_mid", + "pivot": [13.5, 5, 0.5], + "cubes": [ + {"name": "rightFin", "origin": [11.5, 4, -1.5], "size": [2, 1, 2], "uv": [24, 0]} + ] + }, + { + "name": "spines_top_front", + "parent": "body_mid", + "pivot": [16, 6, -2.5], + "cubes": [ + {"name": "spines_top_front", "origin": [13.5, 6, -2.5], "size": [5, 1, 0], "uv": [19, 17]} + ] + }, + { + "name": "spines_top_back", + "parent": "body_mid", + "pivot": [16, 6, 2.5], + "cubes": [ + {"name": "spines_top_back", "origin": [13.5, 6, 2.5], "size": [5, 1, 0], "uv": [11, 17]} + ] + }, + { + "name": "spines_bottom_front", + "parent": "body_mid", + "pivot": [16, 1, -2.5], + "cubes": [ + {"name": "spines_bottom_front", "origin": [13.5, 0, -2.5], "size": [5, 1, 0], "uv": [18, 20]} + ] + }, + { + "name": "spines_bottom_back", + "parent": "body_mid", + "pivot": [16, 1, 2.5], + "rotation": [45, 0, 0], + "cubes": [ + {"name": "spines_bottom_back", "origin": [13.5, 0, 2.5], "size": [5, 1, 0], "uv": [18, 20]} + ] + }, + { + "name": "spines_left_front", + "parent": "body_mid", + "pivot": [18.5, 0, -2.5], + "rotation": [0, 45, 0], + "cubes": [ + {"name": "spines_left_front", "origin": [18.5, 1, -2.5], "size": [1, 5, 0], "uv": [1, 17]} + ] + }, + { + "name": "spines_left_back", + "parent": "body_mid", + "pivot": [18.5, 0, 2.5], + "rotation": [0, -45, 0], + "cubes": [ + {"name": "spines_left_back", "origin": [18.5, 1, 2.5], "size": [1, 5, 0], "uv": [1, 17]} + ] + }, + { + "name": "spines_right_front", + "parent": "body_mid", + "pivot": [13.5, 0, -2.5], + "rotation": [0, -45, 0], + "cubes": [ + {"name": "spines_right_front", "origin": [12.5, 1, -2.5], "size": [1, 5, 0], "uv": [5, 17]} + ] + }, + { + "name": "spines_right_back", + "parent": "body_mid", + "pivot": [13.5, 0, 2.5], + "rotation": [0, 45, 0], + "cubes": [ + {"name": "spines_right_back", "origin": [12.5, 1, 2.5], "size": [1, 5, 0], "uv": [9, 17]} + ] + }, + { + "name": "body_small", + "pivot": [-16, 0, 0], + "cubes": [ + {"name": "body", "origin": [-17.5, 0, -1.5], "size": [3, 2, 3], "uv": [0, 27]}, + {"name": "body", "origin": [-15.5, 2, -1.5], "size": [1, 1, 1], "uv": [24, 6]}, + {"name": "body", "origin": [-17.5, 2, -1.5], "size": [1, 1, 1], "uv": [28, 6]} + ] + }, + { + "name": "tailfin", + "parent": "body_small", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "tailfin", "origin": [-17.5, 1, 1.5], "size": [3, 0, 3], "uv": [-3, 0]} + ] + }, + { + "name": "leftFin", + "parent": "body_small", + "pivot": [6.5, 5, 0.5], + "cubes": [ + {"name": "leftFin", "origin": [-14.5, 0, -1.5], "size": [1, 1, 2], "uv": [25, 0], "mirror": true} + ] + }, + { + "name": "rightFin", + "parent": "body_small", + "pivot": [-6.5, 5, 0.5], + "cubes": [ + {"name": "rightFin", "origin": [-18.5, 0, -1.5], "size": [1, 1, 2], "uv": [25, 0]} + ] + } + ] +}`; +skin_presets.rabbit = `{ + "name": "rabbit", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "rearFootLeft", + "pivot": [3, 6.5, 3.7], + "mirror": true, + "cubes": [ + {"name": "rearFootLeft", "origin": [2, 0, 0], "size": [2, 1, 7], "uv": [8, 24]} + ] + }, + { + "name": "rearFootRight", + "pivot": [-3, 6.5, 3.7], + "mirror": true, + "cubes": [ + {"name": "rearFootRight", "origin": [-4, 0, 0], "size": [2, 1, 7], "uv": [26, 24]} + ] + }, + { + "name": "haunchLeft", + "pivot": [3, 6.5, 3.7], + "rotation": [-20, 0, 0], + "mirror": true, + "cubes": [ + {"name": "haunchLeft", "origin": [2, 2.5, 3.7], "size": [2, 4, 5], "uv": [16, 15]} + ] + }, + { + "name": "haunchRight", + "pivot": [-3, 6.5, 3.7], + "rotation": [-20, 0, 0], + "mirror": true, + "cubes": [ + {"name": "haunchRight", "origin": [-4, 2.5, 3.7], "size": [2, 4, 5], "uv": [30, 15]} + ] + }, + { + "name": "body", + "pivot": [0, 5, 8], + "rotation": [-20, 0, 0], + "mirror": true, + "cubes": [ + {"name": "body", "origin": [-3, 2, -2], "size": [6, 5, 10], "uv": [0, 0]} + ] + }, + { + "name": "frontLegLeft", + "pivot": [3, 7, -1], + "rotation": [-10, 0, 0], + "mirror": true, + "cubes": [ + {"name": "frontLegLeft", "origin": [2, 0, -2], "size": [2, 7, 2], "uv": [8, 15]} + ] + }, + { + "name": "frontLegRight", + "pivot": [-3, 7, -1], + "rotation": [-10, 0, 0], + "mirror": true, + "cubes": [ + {"name": "frontLegRight", "origin": [-4, 0, -2], "size": [2, 7, 2], "uv": [0, 15]} + ] + }, + { + "name": "head", + "pivot": [0, 8, -1], + "mirror": true, + "cubes": [ + {"name": "head", "origin": [-2.5, 8, -6], "size": [5, 4, 5], "uv": [32, 0]} + ] + }, + { + "name": "earRight", + "pivot": [0, 8, -1], + "rotation": [0, -15, 0], + "mirror": true, + "cubes": [ + {"name": "earRight", "origin": [-2.5, 12, -2], "size": [2, 5, 1], "uv": [58, 0]} + ] + }, + { + "name": "earLeft", + "pivot": [0, 8, -1], + "rotation": [0, 15, 0], + "mirror": true, + "cubes": [ + {"name": "earLeft", "origin": [0.5, 12, -2], "size": [2, 5, 1], "uv": [52, 0]} + ] + }, + { + "name": "tail", + "pivot": [0, 4, 7], + "rotation": [-20, 0, 0], + "mirror": true, + "cubes": [ + {"name": "tail", "origin": [-1.5, 2.5, 7], "size": [3, 3, 2], "uv": [52, 6]} + ] + }, + { + "name": "nose", + "pivot": [0, 8, -1], + "mirror": true, + "cubes": [ + {"name": "nose", "origin": [-0.5, 9.5, -6.5], "size": [1, 1, 1], "uv": [32, 9]} + ] + } + ] +}`; +skin_presets.ravager = `{ + "name": "ravager", + "texturewidth": 128, + "textureheight": 128, + "bones": [ + { + "name": "body", + "pivot": [0, 19, 2], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-7, 10, -2], "size": [14, 16, 20], "uv": [0, 55]}, + {"name": "body", "origin": [-6, -3, -2], "size": [12, 13, 18], "uv": [0, 91]} + ] + }, + { + "name": "neck", + "pivot": [0, 20, -20], + "cubes": [ + {"name": "neck", "origin": [-5, 21, -10], "size": [10, 10, 18], "uv": [68, 73]} + ] + }, + { + "name": "head", + "parent": "neck", + "pivot": [0, 28, -10], + "cubes": [ + {"name": "head", "origin": [-8, 14, -24], "size": [16, 20, 16], "uv": [0, 0]}, + {"name": "head", "origin": [-2, 12, -28], "size": [4, 8, 4], "uv": [0, 0]} + ] + }, + { + "name": "mouth", + "parent": "head", + "pivot": [0, 15, -10], + "cubes": [ + {"name": "mouth", "origin": [-8, 13, -24], "size": [16, 3, 16], "uv": [0, 36]} + ] + }, + { + "name": "horns", + "parent": "head", + "pivot": [-5, 27, -19], + "rotation": [60, 0, 0], + "cubes": [ + {"name": "horns", "origin": [-10, 27, -20], "size": [2, 14, 4], "uv": [74, 55]}, + {"name": "horns", "origin": [8, 27, -20], "size": [2, 14, 4], "uv": [74, 55]} + ] + }, + { + "name": "leg0", + "pivot": [-12, 30, 22], + "cubes": [ + {"name": "leg0", "origin": [-12, 0, 17], "size": [8, 37, 8], "uv": [96, 0]} + ] + }, + { + "name": "leg1", + "pivot": [4, 30, 22], + "cubes": [ + {"name": "leg1", "origin": [4, 0, 17], "size": [8, 37, 8], "uv": [96, 0]} + ] + }, + { + "name": "leg2", + "pivot": [-4, 26, -4], + "cubes": [ + {"name": "leg2", "origin": [-12, 0, -8], "size": [8, 37, 8], "uv": [64, 0]} + ] + }, + { + "name": "leg3", + "pivot": [-4, 26, -4], + "cubes": [ + {"name": "leg3", "origin": [4, 0, -8], "size": [8, 37, 8], "uv": [64, 0]} + ] + } + ] +}`; +skin_presets.salmon = `{ + "name": "salmon", + "texturewidth": 32, + "textureheight": 32, + "bones": [ + { + "name": "body_front", + "pivot": [0, 0, -4], + "cubes": [ + {"name": "body_front", "origin": [-1.5, 3.5, -4], "size": [3, 5, 8], "uv": [0, 0]} + ] + }, + { + "name": "body_back", + "parent": "body_front", + "pivot": [0, 0, 4], + "cubes": [ + {"name": "body_back", "origin": [-1.5, 3.5, 4], "size": [3, 5, 8], "uv": [0, 13]} + ] + }, + { + "name": "dorsal_back", + "parent": "body_back", + "pivot": [0, 5, 4], + "cubes": [ + {"name": "dorsal_back", "origin": [0, 8.5, 4], "size": [0, 2, 3], "uv": [2, 3]} + ] + }, + { + "name": "tailfin", + "parent": "body_back", + "pivot": [0, 0, 12], + "cubes": [ + {"name": "tailfin", "origin": [0, 3.5, 12], "size": [0, 5, 6], "uv": [20, 10]} + ] + }, + { + "name": "dorsal_front", + "parent": "body_front", + "pivot": [0, 5, 2], + "cubes": [ + {"name": "dorsal_front", "origin": [0, 8.5, 2], "size": [0, 2, 2], "uv": [4, 2]} + ] + }, + { + "name": "head", + "parent": "body_front", + "pivot": [0, 3, -4], + "cubes": [ + {"name": "head", "origin": [-1, 4.5, -7], "size": [2, 4, 3], "uv": [22, 0]} + ] + }, + { + "name": "leftFin", + "parent": "body_front", + "pivot": [1.5, 1, -4], + "rotation": [0, 0, 35], + "cubes": [ + {"name": "leftFin", "origin": [-0.50752, 3.86703, -4], "size": [2, 0, 2], "uv": [2, 0]} + ] + }, + { + "name": "rightFin", + "parent": "body_front", + "pivot": [-1.5, 1, -4], + "rotation": [0, 0, -35], + "cubes": [ + {"name": "rightFin", "origin": [-1.49258, 3.86703, -4], "size": [2, 0, 2], "uv": [-2, 0]} + ] + } + ] +}`; +skin_presets.sheep = `{ + "name": "sheep", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "body", + "pivot": [0, 19, 2], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, 13, -5], "size": [8, 16, 6], "uv": [28, 8]}, + {"name": "body", "origin": [-4, 13, -5], "size": [8, 16, 6], "uv": [28, 40], "inflate": 1.75} + ] + }, + { + "name": "head", + "pivot": [0, 18, -8], + "cubes": [ + {"name": "head", "origin": [-3, 16, -14], "size": [6, 6, 8], "uv": [0, 0]}, + {"name": "head", "origin": [-3, 16, -12], "size": [6, 6, 6], "uv": [0, 32], "inflate": 0.6} + ] + }, + { + "name": "leg0", + "pivot": [-3, 12, 7], + "cubes": [ + {"name": "leg0", "origin": [-5, 0, 5], "size": [4, 12, 4], "uv": [0, 16]}, + {"name": "leg0", "origin": [-5, 6, 5], "size": [4, 6, 4], "uv": [0, 48], "inflate": 0.5} + ] + }, + { + "name": "leg1", + "pivot": [3, 12, 7], + "cubes": [ + {"name": "leg1", "origin": [1, 0, 5], "size": [4, 12, 4], "uv": [0, 16]}, + {"name": "leg1", "origin": [1, 6, 5], "size": [4, 6, 4], "uv": [0, 48], "inflate": 0.5} + ] + }, + { + "name": "leg2", + "pivot": [-3, 12, -5], + "cubes": [ + {"name": "leg2", "origin": [-5, 0, -7], "size": [4, 12, 4], "uv": [0, 16]}, + {"name": "leg2", "origin": [-5, 6, -7], "size": [4, 6, 4], "uv": [0, 48], "inflate": 0.5} + ] + }, + { + "name": "leg3", + "pivot": [3, 12, -5], + "cubes": [ + {"name": "leg3", "origin": [1, 0, -7], "size": [4, 12, 4], "uv": [0, 16]}, + {"name": "leg3", "origin": [1, 6, -7], "size": [4, 6, 4], "uv": [0, 48], "inflate": 0.5} + ] + } + ] +}`; +skin_presets.shield = `{ + "name": "shield", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "shield", + "pivot": [1, 15.5, 3], + "cubes": [ + {"name": "shield", "origin": [0, 25, 0], "size": [2, 6, 6], "uv": [26, 0]}, + {"name": "shield", "origin": [-5, 17, -1], "size": [12, 22, 1], "uv": [0, 0]} + ] + } + ] +}`; +skin_presets.shulker = `{ + "name": "shulker", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "base", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "base", "origin": [-8, 0, -8], "size": [16, 8, 16], "uv": [0, 28]} + ] + }, + { + "name": "lid", + "parent": "base", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "lid", "origin": [-8, 13, -8], "size": [16, 12, 16], "uv": [0, 0]} + ] + }, + { + "name": "head", + "parent": "base", + "pivot": [0, 12, 0], + "cubes": [ + {"name": "head", "origin": [-3, 6, -3], "size": [6, 6, 6], "uv": [0, 52]} + ] + } + ] +}`; +skin_presets.shulker_bullet = `{ + "name": "shulker_bullet", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "body", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, -4, -1], "size": [8, 8, 2], "uv": [0, 0]}, + {"name": "body", "origin": [-1, -4, -4], "size": [2, 8, 8], "uv": [0, 10]}, + {"name": "body", "origin": [-4, -1, -4], "size": [8, 2, 8], "uv": [20, 0]} + ] + } + ] +}`; +skin_presets.silverfish = `{ + "name": "silverfish", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "bodyPart_2", + "pivot": [0, 4, 1], + "cubes": [ + {"name": "bodyPart_2", "origin": [-3, 0, -0.5], "size": [6, 4, 3], "uv": [0, 9]} + ] + }, + { + "name": "bodyPart_0", + "parent": "bodyPart_2", + "pivot": [0, 2, -3.5], + "cubes": [ + {"name": "bodyPart_0", "origin": [-1.5, 0, -4.5], "size": [3, 2, 2], "uv": [0, 0]} + ] + }, + { + "name": "bodyPart_1", + "parent": "bodyPart_2", + "pivot": [0, 3, -1.5], + "cubes": [ + {"name": "bodyPart_1", "origin": [-2, 0, -2.5], "size": [4, 3, 2], "uv": [0, 4]} + ] + }, + { + "name": "bodyLayer_2", + "parent": "bodyPart_1", + "pivot": [0, 5, -1.5], + "cubes": [ + {"name": "bodyLayer_2", "origin": [-3, 0, -3], "size": [6, 5, 2], "uv": [20, 18]} + ] + }, + { + "name": "bodyPart_3", + "parent": "bodyPart_2", + "pivot": [0, 3, 4], + "cubes": [ + {"name": "bodyPart_3", "origin": [-1.5, 0, 2.5], "size": [3, 3, 3], "uv": [0, 16]} + ] + }, + { + "name": "bodyPart_4", + "parent": "bodyPart_2", + "pivot": [0, 2, 7], + "cubes": [ + {"name": "bodyPart_4", "origin": [-1, 0, 5.5], "size": [2, 2, 3], "uv": [0, 22]} + ] + }, + { + "name": "bodyLayer_1", + "parent": "bodyPart_4", + "pivot": [0, 4, 7], + "cubes": [ + {"name": "bodyLayer_1", "origin": [-3, 0, 5.5], "size": [6, 4, 3], "uv": [20, 11]} + ] + }, + { + "name": "bodyPart_5", + "parent": "bodyPart_2", + "pivot": [0, 1, 9.5], + "cubes": [ + {"name": "bodyPart_5", "origin": [-1, 0, 8.5], "size": [2, 1, 2], "uv": [11, 0]} + ] + }, + { + "name": "bodyPart_6", + "parent": "bodyPart_2", + "pivot": [0, 1, 11.5], + "cubes": [ + {"name": "bodyPart_6", "origin": [-0.5, 0, 10.5], "size": [1, 1, 2], "uv": [13, 4]} + ] + }, + { + "name": "bodyLayer_0", + "parent": "bodyPart_2", + "pivot": [0, 8, 1], + "cubes": [ + {"name": "bodyLayer_0", "origin": [-5, 0, -0.5], "size": [10, 8, 3], "uv": [20, 0]} + ] + } + ] +}`; +skin_presets.skeleton = `{ + "name": "skeleton", + "texturewidth": 64, + "textureheight": 32, + "eyes": [ + [9, 12, 2, 1], + [13, 12, 2, 1] + ], + "bones": [ + { + "name": "waist", + "pivot": [0, 12, 0] + }, + { + "name": "body", + "parent": "waist", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]} + ] + }, + { + "name": "hat", + "parent": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "hat", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5} + ] + }, + { + "name": "rightArm", + "parent": "body", + "pivot": [-5, 22, 0], + "cubes": [ + {"name": "rightArm", "origin": [-6, 12, -1], "size": [2, 12, 2], "uv": [40, 16]} + ] + }, + { + "name": "rightItem", + "parent": "rightArm", + "pivot": [-6, 15, 1] + }, + { + "name": "leftArm", + "parent": "body", + "pivot": [5, 22, 0], + "mirror": true, + "cubes": [ + {"name": "leftArm", "origin": [4, 12, -1], "size": [2, 12, 2], "uv": [40, 16]} + ] + }, + { + "name": "leftItem", + "parent": "leftArm", + "pivot": [6, 15, 1] + }, + { + "name": "rightLeg", + "parent": "body", + "pivot": [-2, 12, 0], + "cubes": [ + {"name": "rightLeg", "origin": [-3, 0, -1], "size": [2, 12, 2], "uv": [0, 16]} + ] + }, + { + "name": "leftLeg", + "parent": "body", + "pivot": [2, 12, 0], + "mirror": true, + "cubes": [ + {"name": "leftLeg", "origin": [1, 0, -1], "size": [2, 12, 2], "uv": [0, 16]} + ] + } + ] +}`; +skin_presets.slime = `{ + "name": "slime", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "inner", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "cube", "origin": [-3, 1, -3], "size": [6, 6, 6], "uv": [0, 16]}, + {"name": "eye0", "origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0]}, + {"name": "eye1", "origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4]}, + {"name": "mouth", "origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]} + ] + }, + { + "name": "outer", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "cube layer", "visibility": false, "origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0]}, + {"name": "eye0 layer", "visibility": false, "origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0]}, + {"name": "eye1 layer", "visibility": false, "origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4]}, + {"name": "mouth layer", "visibility": false, "origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]} + ] + } + ] +}`; +skin_presets.snowgolem = `{ + "name": "snowgolem", + "texturewidth": 64, + "textureheight": 64, + "eyes": [ + [9, 11], + [13, 11] + ], + "bones": [ + { + "name": "piece2", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "piece2", "origin": [-6, 0, -6], "size": [12, 12, 12], "uv": [0, 36], "inflate": -0.5} + ] + }, + { + "name": "piece1", + "parent": "piece2", + "pivot": [0, 11, 0], + "cubes": [ + {"name": "piece1", "origin": [-5, 11, -5], "size": [10, 10, 10], "uv": [0, 16], "inflate": -0.5} + ] + }, + { + "name": "head", + "parent": "piece1", + "pivot": [0, 20, 0], + "cubes": [ + {"name": "head", "origin": [-4, 20, -4], "size": [8, 8, 8], "uv": [0, 0], "inflate": -0.5} + ] + }, + { + "name": "arm1", + "parent": "piece1", + "pivot": [0, 18, 0], + "rotation": [0, 0, 45], + "cubes": [ + {"name": "arm1", "origin": [1, 20, -1], "size": [12, 2, 2], "uv": [32, 0], "inflate": -0.5} + ] + }, + { + "name": "arm2", + "parent": "piece1", + "pivot": [0, 18, 0], + "rotation": [0, 0, 135], + "cubes": [ + {"name": "arm2", "origin": [1, 14, -1], "size": [12, 2, 2], "uv": [32, 0], "inflate": -0.5} + ] + } + ] +}`; +skin_presets.spider = `{ + "name": "spider", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "head", + "pivot": [0, 9, -3], + "cubes": [ + {"name": "head", "origin": [-4, 5, -11], "size": [8, 8, 8], "uv": [32, 4]} + ] + }, + { + "name": "body0", + "pivot": [0, 9, 0], + "cubes": [ + {"name": "body0", "origin": [-3, 6, -3], "size": [6, 6, 6], "uv": [0, 0]} + ] + }, + { + "name": "body1", + "pivot": [0, 9, 9], + "cubes": [ + {"name": "body1", "origin": [-5, 5, 3], "size": [10, 8, 12], "uv": [0, 12]} + ] + }, + { + "name": "leg0", + "pivot": [-4, 9, 2], + "rotation": [0, 45, -45], + "cubes": [ + {"name": "leg0", "origin": [-19, 8, 1], "size": [16, 2, 2], "uv": [18, 0]} + ] + }, + { + "name": "leg1", + "pivot": [4, 9, 2], + "rotation": [0, -45, 45], + "cubes": [ + {"name": "leg1", "origin": [3, 8, 1], "size": [16, 2, 2], "uv": [18, 0]} + ] + }, + { + "name": "leg2", + "pivot": [-4, 9, 1], + "rotation": [0, 15, -35], + "cubes": [ + {"name": "leg2", "origin": [-19, 8, 0], "size": [16, 2, 2], "uv": [18, 0]} + ] + }, + { + "name": "leg3", + "pivot": [4, 9, 1], + "rotation": [0, -15, 35], + "cubes": [ + {"name": "leg3", "origin": [3, 8, 0], "size": [16, 2, 2], "uv": [18, 0]} + ] + }, + { + "name": "leg4", + "pivot": [-4, 9, 0], + "rotation": [0, -15, -35], + "cubes": [ + {"name": "leg4", "origin": [-19, 8, -1], "size": [16, 2, 2], "uv": [18, 0]} + ] + }, + { + "name": "leg5", + "pivot": [4, 9, 0], + "rotation": [0, 15, 35], + "cubes": [ + {"name": "leg5", "origin": [3, 8, -1], "size": [16, 2, 2], "uv": [18, 0]} + ] + }, + { + "name": "leg6", + "pivot": [-4, 9, -1], + "rotation": [0, -45, -45], + "cubes": [ + {"name": "leg6", "origin": [-19, 8, -2], "size": [16, 2, 2], "uv": [18, 0]} + ] + }, + { + "name": "leg7", + "pivot": [4, 9, -1], + "rotation": [0, 45, 45], + "cubes": [ + {"name": "leg7", "origin": [3, 8, -2], "size": [16, 2, 2], "uv": [18, 0]} + ] + } + ] +}`; +skin_presets.squid = `{ + "name": "squid", + "texturewidth": 64, + "textureheight": 32, + "eyes": [ + [14, 18], + [20, 18] + ], + "bones": [ + { + "name": "body", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-6, -8, -6], "size": [12, 16, 12], "uv": [0, 0]} + ] + }, + { + "name": "tentacle1", + "pivot": [5, -7, 0], + "rotation": [0, 90, 0], + "cubes": [ + {"name": "tentacle1", "origin": [4, -25, -1], "size": [2, 18, 2], "uv": [48, 0]} + ] + }, + { + "name": "tentacle2", + "pivot": [3.5, -7, 3.5], + "rotation": [0, 45, 0], + "cubes": [ + {"name": "tentacle2", "origin": [2.5, -25, 2.5], "size": [2, 18, 2], "uv": [48, 0]} + ] + }, + { + "name": "tentacle3", + "pivot": [0, -7, 5], + "cubes": [ + {"name": "tentacle3", "origin": [-1, -25, 4], "size": [2, 18, 2], "uv": [48, 0]} + ] + }, + { + "name": "tentacle4", + "pivot": [-3.5, -7, 3.5], + "rotation": [0, -45, 0], + "cubes": [ + {"name": "tentacle4", "origin": [-4.5, -25, 2.5], "size": [2, 18, 2], "uv": [48, 0]} + ] + }, + { + "name": "tentacle5", + "pivot": [-5, -7, 0], + "rotation": [0, -90, 0], + "cubes": [ + {"name": "tentacle5", "origin": [-6, -25, -1], "size": [2, 18, 2], "uv": [48, 0]} + ] + }, + { + "name": "tentacle6", + "pivot": [-3.5, -7, -3.5], + "rotation": [0, -135, 0], + "cubes": [ + {"name": "tentacle6", "origin": [-4.5, -25, -4.5], "size": [2, 18, 2], "uv": [48, 0]} + ] + }, + { + "name": "tentacle7", + "pivot": [0, -7, -5], + "rotation": [0, -180, 0], + "cubes": [ + {"name": "tentacle7", "origin": [-1, -25, -6], "size": [2, 18, 2], "uv": [48, 0]} + ] + }, + { + "name": "tentacle8", + "pivot": [3.5, -7, -3.5], + "rotation": [0, -225, 0], + "cubes": [ + {"name": "tentacle8", "origin": [2.5, -25, -4.5], "size": [2, 18, 2], "uv": [48, 0]} + ] + } + ] +}`; +skin_presets.tropicalfish_a = `{ + "name": "tropicalfish_a", + "texturewidth": 32, + "textureheight": 32, + "bones": [ + { + "name": "body", + "pivot": [-0.5, 0, 0], + "cubes": [ + {"name": "body", "origin": [-1, 0, -3], "size": [2, 3, 6], "uv": [0, 0]}, + {"name": "body", "origin": [0, 3, -2.9992], "size": [0, 4, 6], "uv": [10, -6]} + ] + }, + { + "name": "tailfin", + "parent": "body", + "pivot": [0, 0, 3], + "cubes": [ + {"name": "tailfin", "origin": [0, 0, 3], "size": [0, 3, 4], "uv": [24, -4]} + ] + }, + { + "name": "leftFin", + "parent": "body", + "pivot": [0.5, 0, 1], + "rotation": [0, -35, 0], + "cubes": [ + {"name": "leftFin", "origin": [0.336, 0, -0.10594], "size": [2, 2, 0], "uv": [2, 12]} + ] + }, + { + "name": "rightFin", + "parent": "body", + "pivot": [-0.5, 0, 1], + "rotation": [0, 35, 0], + "cubes": [ + {"name": "rightFin", "origin": [-2.336, 0, -0.10594], "size": [2, 2, 0], "uv": [2, 16]} + ] + } + ] +}`; +skin_presets.tropicalfish_b = `{ + "name": "tropicalfish_b", + "texturewidth": 32, + "textureheight": 32, + "bones": [ + { + "name": "body", + "pivot": [-0.5, 0, 0], + "cubes": [ + {"name": "body", "origin": [-1, 0, -0.0008], "size": [2, 6, 6], "uv": [0, 20]}, + {"name": "body", "origin": [0, -5, -0.0008], "size": [0, 5, 6], "uv": [20, 21]}, + {"name": "body", "origin": [0, 6, -0.0008], "size": [0, 5, 6], "uv": [20, 10]} + ] + }, + { + "name": "tailfin", + "parent": "body", + "pivot": [0, 0, 6], + "cubes": [ + {"name": "tailfin", "origin": [0, 0.0008, 6], "size": [0, 6, 5], "uv": [21, 16]} + ] + }, + { + "name": "leftFin", + "parent": "body", + "pivot": [0.5, 0, 1], + "rotation": [0, -35, 0], + "cubes": [ + {"name": "leftFin", "origin": [2.05673, 0, 2.35152], "size": [2, 2, 0], "uv": [2, 12]} + ] + }, + { + "name": "rightFin", + "parent": "body", + "pivot": [-0.5, 0, 1], + "rotation": [0, 35, 0], + "cubes": [ + {"name": "rightFin", "origin": [-4.05673, 0, 2.35152], "size": [2, 2, 0], "uv": [2, 16]} + ] + } + ] +}`; +skin_presets.turtle = `{ + "name": "turtle", + "texturewidth": 128, + "textureheight": 64, + "bones": [ + { + "name": "body", + "pivot": [0, 13, -10], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-9.5, -10, -20], "size": [19, 20, 6], "uv": [6, 37]}, + {"name": "body", "origin": [-5.5, -8, -23], "size": [11, 18, 3], "uv": [30, 1]} + ] + }, + { + "name": "eggbelly", + "parent": "body", + "pivot": [0, 13, -10], + "cubes": [ + {"name": "eggbelly", "origin": [-4.5, -8, -24], "size": [9, 18, 1], "uv": [69, 33]} + ] + }, + { + "name": "head", + "pivot": [0, 5, -10], + "cubes": [ + {"name": "head", "origin": [-3, 1, -13], "size": [6, 5, 6], "uv": [2, 0]} + ] + }, + { + "name": "leg0", + "pivot": [-3.5, 2, 11], + "cubes": [ + {"name": "leg0", "origin": [-5.5, 1, 11], "size": [4, 1, 10], "uv": [0, 23]} + ] + }, + { + "name": "leg1", + "pivot": [3.5, 2, 11], + "cubes": [ + {"name": "leg1", "origin": [1.5, 1, 11], "size": [4, 1, 10], "uv": [0, 12]} + ] + }, + { + "name": "leg2", + "pivot": [-5, 3, -4], + "rotation": [0, 10, 0], + "cubes": [ + {"name": "leg2", "origin": [-18, 2, -6], "size": [13, 1, 5], "uv": [26, 30]} + ] + }, + { + "name": "leg3", + "pivot": [5, 3, -4], + "rotation": [0, -10, 0], + "cubes": [ + {"name": "leg3", "origin": [5, 2, -6], "size": [13, 1, 5], "uv": [26, 24]} + ] + } + ] +}`; +skin_presets.vex = `{ + "name": "vex", + "texturewidth": 64, + "textureheight": 64, + "eyes": [ + [9, 12, 2, 1], + [13, 12, 2, 1] + ], + "bones": [ + { + "name": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]} + ] + }, + { + "name": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} + ] + }, + { + "name": "rightArm", + "pivot": [-5, 22, 0], + "cubes": [ + {"name": "rightArm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} + ] + }, + { + "name": "rightItem", + "pivot": [-6, 13, 0] + }, + { + "name": "leftArm", + "pivot": [5, 22, 0], + "mirror": true, + "cubes": [ + {"name": "leftArm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} + ] + }, + { + "name": "leg0", + "pivot": [-1.9, 12, 0], + "cubes": [ + {"name": "leg0", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}, + {"name": "leg0", "origin": [-2.9, 3, -2], "size": [6, 10, 4], "uv": [32, 0]} + ] + }, + { + "name": "leftwing", + "pivot": [0, 24, 0], + "mirror": true, + "cubes": [ + {"name": "leftwing", "origin": [0, 12, 0], "size": [20, 12, 1], "uv": [0, 32]} + ] + }, + { + "name": "rightwing", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "rightwing", "origin": [-20, 12, 0], "size": [20, 12, 1], "uv": [0, 32]} + ] + } + ] +}`; +skin_presets.villager = `{ + "name": "villager", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} + ] + }, + { + "name": "nose", + "parent": "head", + "pivot": [0, 26, 0], + "cubes": [ + {"name": "nose", "origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]} + ] + }, + { + "name": "body", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, + {"name": "body", "origin": [-4, 6, -3], "size": [8, 18, 6], "uv": [0, 38], "inflate": 0.5} + ] + }, + { + "name": "arms", + "pivot": [0, 22, 0], + "rotation": [-45, 0, 0], + "cubes": [ + {"name": "arms", "origin": [-4, 16, -2], "size": [8, 4, 4], "uv": [40, 38]}, + {"name": "arms", "origin": [-8, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, + {"name": "arms", "origin": [4, 16, -2], "size": [4, 8, 4], "uv": [44, 22]} + ] + }, + { + "name": "leg0", + "pivot": [-2, 12, 0], + "cubes": [ + {"name": "leg0", "origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "leg1", + "pivot": [2, 12, 0], + "cubes": [ + {"name": "leg1", "origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + } + ] +}`; +skin_presets.villager_v2 = `{ + "name": "villager_v2", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "body", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, + {"name": "body", "origin": [-4, 6, -3], "size": [8, 18, 6], "uv": [0, 38], "inflate": 0.5} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} + ] + }, + { + "name": "helmet", + "parent": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "helmet", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [32, 0], "inflate": 0.5} + ] + }, + { + "name": "brim", + "parent": "head", + "pivot": [0, 24, 0], + "rotation": [-90, 0, 0], + "cubes": [ + {"name": "brim", "origin": [-8, 16, -6], "size": [16, 16, 1], "uv": [30, 47], "inflate": 0.1} + ] + }, + { + "name": "nose", + "parent": "head", + "pivot": [0, 26, 0], + "cubes": [ + {"name": "nose", "origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]} + ] + }, + { + "name": "arms", + "parent": "body", + "pivot": [0, 22, 0], + "rotation": [-45, 0, 0], + "cubes": [ + {"name": "arms", "origin": [-4, 16, -2], "size": [8, 4, 4], "uv": [40, 38]}, + {"name": "arms", "origin": [-8, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, + {"name": "arms", "origin": [4, 16, -2], "size": [4, 8, 4], "uv": [44, 22], "mirror": true} + ] + }, + { + "name": "leg0", + "parent": "body", + "pivot": [-2, 12, 0], + "cubes": [ + {"name": "leg0", "origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "leg1", + "parent": "body", + "pivot": [2, 12, 0], + "cubes": [ + {"name": "leg1", "origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22], "mirror": true} + ] + } + ] +}`; +skin_presets.vindicator = `{ + "name": "vindicator", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} + ] + }, + { + "name": "nose", + "parent": "head", + "pivot": [0, 26, 0], + "cubes": [ + {"name": "nose", "origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]} + ] + }, + { + "name": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, + {"name": "body", "origin": [-4, 6, -3], "size": [8, 18, 6], "uv": [0, 38], "inflate": 0.5} + ] + }, + { + "name": "arms", + "pivot": [0, 22, 0], + "cubes": [ + {"name": "arms", "origin": [-8, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, + {"name": "arms", "origin": [4, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, + {"name": "arms", "origin": [-4, 16, -2], "size": [8, 4, 4], "uv": [40, 38]} + ] + }, + { + "name": "leg0", + "pivot": [-2, 12, 0], + "cubes": [ + {"name": "leg0", "origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "leg1", + "pivot": [2, 12, 0], + "mirror": true, + "cubes": [ + {"name": "leg1", "origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "rightArm", + "pivot": [-5, 22, 0], + "cubes": [ + {"name": "rightArm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} + ] + }, + { + "name": "rightItem", + "parent": "rightArm", + "pivot": [-5.5, 16, 0.5] + }, + { + "name": "leftArm", + "pivot": [5, 22, 0], + "mirror": true, + "cubes": [ + {"name": "leftArm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} + ] + } + ] +}`; +skin_presets.witch = `{ + "name": "witch", + "texturewidth": 64, + "textureheight": 128, + "bones": [ + { + "name": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} + ] + }, + { + "name": "nose", + "parent": "head", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "nose", "origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]}, + {"name": "nose", "origin": [0, 25, -6.75], "size": [1, 1, 1], "uv": [0, 0], "inflate": -0.25} + ] + }, + { + "name": "hat", + "parent": "head", + "pivot": [-5, 32.03125, -5], + "cubes": [ + {"name": "hat", "origin": [-5, 32.05, -5], "size": [10, 2, 10], "uv": [0, 64]} + ] + }, + { + "name": "hat2", + "parent": "hat", + "pivot": [1.75, 32, 2], + "rotation": [-3, 0, 1.5], + "cubes": [ + {"name": "hat2", "origin": [-3.25, 33.5, -3], "size": [7, 4, 7], "uv": [0, 76]} + ] + }, + { + "name": "hat3", + "parent": "hat2", + "pivot": [1.75, 35, 2], + "rotation": [-6, 0, 3], + "cubes": [ + {"name": "hat3", "origin": [-1.5, 36.5, -1], "size": [4, 4, 4], "uv": [0, 87]} + ] + }, + { + "name": "hat4", + "parent": "hat3", + "pivot": [1.75, 38, 2], + "rotation": [-12, 0, 6], + "cubes": [ + {"name": "hat4", "origin": [0.25, 40, 1], "size": [1, 2, 1], "uv": [0, 95], "inflate": 0.25} + ] + }, + { + "name": "body", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, + {"name": "body", "origin": [-4, 6, -3], "size": [8, 18, 6], "uv": [0, 38], "inflate": 0.5} + ] + }, + { + "name": "arms", + "pivot": [0, 22, 0], + "rotation": [-45, 0, 0], + "cubes": [ + {"name": "arms", "origin": [-4, 16, -2], "size": [8, 4, 4], "uv": [40, 38]}, + {"name": "arms", "origin": [-8, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, + {"name": "arms", "origin": [4, 16, -2], "size": [4, 8, 4], "uv": [44, 22]} + ] + }, + { + "name": "leg0", + "pivot": [-2, 12, 0], + "cubes": [ + {"name": "leg0", "origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "leg1", + "pivot": [2, 12, 0], + "cubes": [ + {"name": "leg1", "origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + } + ] +}`; +skin_presets.witherBoss = `{ + "name": "witherBoss", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "upperBodyPart1", + "pivot": [0, 0, 0], + "cubes": [ + {"name": "upperBodyPart1", "origin": [-10, 17.1, -0.5], "size": [20, 3, 3], "uv": [0, 16]} + ] + }, + { + "name": "upperBodyPart2", + "parent": "upperBodyPart1", + "pivot": [-2, 17.1, -0.5], + "cubes": [ + {"name": "upperBodyPart2", "origin": [-2, 7.1, -0.5], "size": [3, 10, 3], "uv": [0, 22]}, + {"name": "upperBodyPart2", "origin": [-6, 13.6, 0], "size": [11, 2, 2], "uv": [24, 22]}, + {"name": "upperBodyPart2", "origin": [-6, 11.1, 0], "size": [11, 2, 2], "uv": [24, 22]}, + {"name": "upperBodyPart2", "origin": [-6, 8.6, 0], "size": [11, 2, 2], "uv": [24, 22]} + ] + }, + { + "name": "upperBodyPart3", + "parent": "upperBodyPart2", + "pivot": [0, 7, 0], + "rotation": [45, 0, 0], + "cubes": [ + {"name": "upperBodyPart3", "origin": [-2, 1, 0], "size": [3, 6, 3], "uv": [12, 22]} + ] + }, + { + "name": "head1", + "parent": "upperBodyPart1", + "pivot": [0, 20, 0], + "cubes": [ + {"name": "head1", "origin": [-4, 20, -4], "size": [8, 8, 8], "uv": [0, 0]} + ] + }, + { + "name": "head2", + "parent": "upperBodyPart1", + "pivot": [-9, 18, -1], + "cubes": [ + {"name": "head2", "origin": [-12, 18, -4], "size": [6, 6, 6], "uv": [32, 0]} + ] + }, + { + "name": "head3", + "parent": "upperBodyPart1", + "pivot": [9, 18, -1], + "cubes": [ + {"name": "head3", "origin": [6, 18, -4], "size": [6, 6, 6], "uv": [32, 0]} + ] + } + ] +}`; +skin_presets.wolf = `{ + "name": "wolf", + "texturewidth": 64, + "textureheight": 32, + "bones": [ + { + "name": "head", + "pivot": [-1, 10.5, -7], + "cubes": [ + {"name": "head", "origin": [-4, 7.5, -9], "size": [6, 6, 4], "uv": [0, 0]}, + {"name": "head", "origin": [-4, 13.5, -7], "size": [2, 2, 1], "uv": [16, 14]}, + {"name": "head", "origin": [0, 13.5, -7], "size": [2, 2, 1], "uv": [16, 14]}, + {"name": "head", "origin": [-2.5, 7.51563, -12], "size": [3, 3, 4], "uv": [0, 10]} + ] + }, + { + "name": "body", + "pivot": [0, 10, 2], + "rotation": [90, 0, 0], + "cubes": [ + {"name": "body", "origin": [-4, 3, -1], "size": [6, 9, 6], "uv": [18, 14]} + ] + }, + { + "name": "upperBody", + "pivot": [-1, 10, 2], + "rotation": [-90, 0, 0], + "cubes": [ + {"name": "upperBody", "origin": [-5, 2, -2], "size": [8, 6, 7], "uv": [21, 0]} + ] + }, + { + "name": "leg0", + "pivot": [-2.5, 8, 7], + "cubes": [ + {"name": "leg0", "origin": [-3.5, 0, 6], "size": [2, 8, 2], "uv": [0, 18]} + ] + }, + { + "name": "leg1", + "pivot": [0.5, 8, 7], + "cubes": [ + {"name": "leg1", "origin": [-0.5, 0, 6], "size": [2, 8, 2], "uv": [0, 18]} + ] + }, + { + "name": "leg2", + "pivot": [-2.5, 8, -4], + "cubes": [ + {"name": "leg2", "origin": [-3.5, 0, -5], "size": [2, 8, 2], "uv": [0, 18]} + ] + }, + { + "name": "leg3", + "pivot": [0.5, 8, -4], + "cubes": [ + {"name": "leg3", "origin": [-0.5, 0, -5], "size": [2, 8, 2], "uv": [0, 18]} + ] + }, + { + "name": "tail", + "pivot": [-1, 12, 8], + "rotation": [55, 0, 0], + "cubes": [ + {"name": "tail", "origin": [-2, 4, 7], "size": [2, 8, 2], "uv": [9, 18]} + ] + } + ] +}`; +skin_presets.zombie = `{ + "name": "zombie", + "texturewidth": 64, + "textureheight": 32, + "eyes": [ + [9, 12, 2, 1], + [13, 12, 2, 1] + ], + "bones": [ + { + "name": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 24, 0], + "rotation": [3, -10, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}, + {"name": "hat", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5} + ] + }, + { + "name": "rightArm", + "parent": "body", + "pivot": [-5, 22, 0], + "rotation": [-80, -5, 0], + "cubes": [ + {"name": "rightArm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} + ] + }, + { + "name": "rightItem", + "parent": "rightArm", + "pivot": [-6, 15, 1] + }, + { + "name": "leftArm", + "parent": "body", + "pivot": [5, 22, 0], + "rotation": [-75, 5, 0], + "mirror": true, + "cubes": [ + {"name": "leftArm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} + ] + }, + { + "name": "rightLeg", + "parent": "body", + "pivot": [-1.9, 12, 0], + "rotation": [-25, 0, 5], + "cubes": [ + {"name": "rightLeg", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]} + ] + }, + { + "name": "leftLeg", + "parent": "body", + "pivot": [1.9, 12, 0], + "rotation": [20, 0, 0], + "mirror": true, + "cubes": [ + {"name": "leftLeg", "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16]} + ] + } + ] +}`; +skin_presets.zombie_villager_1 = `{ + "name": "zombie_villager_1", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0], "inflate": 0.25}, + {"name": "head", "origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0], "inflate": 0.25} + ] + }, + { + "name": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, + {"name": "body", "origin": [-4, 6, -3], "size": [8, 18, 6], "uv": [0, 38], "inflate": 0.5} + ] + }, + { + "name": "waist", + "pivot": [0, 12, 0] + }, + { + "name": "rightArm", + "pivot": [-5, 22, 0], + "cubes": [ + {"name": "rightArm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [44, 38]} + ] + }, + { + "name": "rightItem", + "parent": "rightArm", + "pivot": [-6, 15, 1] + }, + { + "name": "leftArm", + "pivot": [5, 22, 0], + "mirror": true, + "cubes": [ + {"name": "leftArm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [44, 38]} + ] + }, + { + "name": "rightLeg", + "pivot": [-2, 12, 0], + "cubes": [ + {"name": "rightLeg", "origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "leftLeg", + "pivot": [2, 12, 0], + "mirror": true, + "cubes": [ + {"name": "leftLeg", "origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + } + ] +}`; +skin_presets.zombie_villager_2 = `{ + "name": "zombie_villager_2", + "texturewidth": 64, + "textureheight": 64, + "bones": [ + { + "name": "waist", + "pivot": [0, 12, 0] + }, + { + "name": "body", + "parent": "waist", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "body", "origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, + {"name": "body", "origin": [-4, 6, -3], "size": [8, 18, 6], "uv": [0, 38], "inflate": 0.5} + ] + }, + { + "name": "head", + "parent": "body", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "head", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0], "inflate": 0.25}, + {"name": "head", "origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0], "inflate": 0.25} + ] + }, + { + "name": "helmet", + "parent": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "helmet", "origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [32, 0], "inflate": 0.5} + ] + }, + { + "name": "brim", + "parent": "head", + "pivot": [0, 24, 0], + "cubes": [ + {"name": "brim", "origin": [-8, 16, -6], "size": [16, 16, 1], "uv": [30, 47], "inflate": 0.1} + ] + }, + { + "name": "rightArm", + "parent": "body", + "pivot": [-5, 22, 0], + "cubes": [ + {"name": "rightArm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [44, 22]} + ] + }, + { + "name": "rightItem", + "parent": "rightArm", + "pivot": [-6, 15, 1] + }, + { + "name": "leftArm", + "parent": "body", + "pivot": [5, 22, 0], + "mirror": true, + "cubes": [ + {"name": "leftArm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [44, 22]} + ] + }, + { + "name": "rightLeg", + "parent": "body", + "pivot": [-2, 12, 0], + "cubes": [ + {"name": "rightLeg", "origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + }, + { + "name": "leftLeg", + "parent": "body", + "pivot": [2, 12, 0], + "mirror": true, + "cubes": [ + {"name": "leftLeg", "origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} + ] + } + ] +}`; + +})() diff --git a/js/outliner/cube.js b/js/outliner/cube.js index e38dd5074..cf2bc6cf4 100644 --- a/js/outliner/cube.js +++ b/js/outliner/cube.js @@ -267,6 +267,7 @@ class Cube extends NonGroup { copy = { uv_offset: copy.uv_offset, faces: copy.faces, + mirror_uv: copy.mirror_uv, } } copy.uuid = this.uuid @@ -767,14 +768,14 @@ class Cube extends NonGroup { 'rename', 'update_autouv', {name: 'menu.cube.color', icon: 'color_lens', children: [ - {icon: 'bubble_chart', color: cubeColors[0].hex, name: 'cube.color.'+cubeColors[0].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(0)}, 'change color')}}, - {icon: 'bubble_chart', color: cubeColors[1].hex, name: 'cube.color.'+cubeColors[1].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(1)}, 'change color')}}, - {icon: 'bubble_chart', color: cubeColors[2].hex, name: 'cube.color.'+cubeColors[2].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(2)}, 'change color')}}, - {icon: 'bubble_chart', color: cubeColors[3].hex, name: 'cube.color.'+cubeColors[3].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(3)}, 'change color')}}, - {icon: 'bubble_chart', color: cubeColors[4].hex, name: 'cube.color.'+cubeColors[4].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(4)}, 'change color')}}, - {icon: 'bubble_chart', color: cubeColors[5].hex, name: 'cube.color.'+cubeColors[5].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(5)}, 'change color')}}, - {icon: 'bubble_chart', color: cubeColors[6].hex, name: 'cube.color.'+cubeColors[6].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(6)}, 'change color')}}, - {icon: 'bubble_chart', color: cubeColors[7].hex, name: 'cube.color.'+cubeColors[7].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(7)}, 'change color')}} + {icon: 'bubble_chart', color: markerColors[0].standard, name: 'cube.color.'+markerColors[0].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(0)}, 'change color')}}, + {icon: 'bubble_chart', color: markerColors[1].standard, name: 'cube.color.'+markerColors[1].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(1)}, 'change color')}}, + {icon: 'bubble_chart', color: markerColors[2].standard, name: 'cube.color.'+markerColors[2].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(2)}, 'change color')}}, + {icon: 'bubble_chart', color: markerColors[3].standard, name: 'cube.color.'+markerColors[3].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(3)}, 'change color')}}, + {icon: 'bubble_chart', color: markerColors[4].standard, name: 'cube.color.'+markerColors[4].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(4)}, 'change color')}}, + {icon: 'bubble_chart', color: markerColors[5].standard, name: 'cube.color.'+markerColors[5].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(5)}, 'change color')}}, + {icon: 'bubble_chart', color: markerColors[6].standard, name: 'cube.color.'+markerColors[6].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(6)}, 'change color')}}, + {icon: 'bubble_chart', color: markerColors[7].standard, name: 'cube.color.'+markerColors[7].name, click: function(cube) {cube.forSelected(function(obj){obj.setColor(7)}, 'change color')}} ]}, {name: 'menu.cube.texture', icon: 'collections', condition: () => !Project.single_texture, children: function() { var arr = [ diff --git a/js/outliner/outliner.js b/js/outliner/outliner.js index ada7d72e1..6f6a65db8 100644 --- a/js/outliner/outliner.js +++ b/js/outliner/outliner.js @@ -71,15 +71,15 @@ const Outliner = { } } //Colors -var cubeColors = [ - {hex: "#A2EBFF", name: 'light_blue'}, - {hex: "#FFF899", name: 'yellow'}, - {hex: "#E8BD7B", name: 'orange'}, - {hex: "#FFA7A4", name: 'red'}, - {hex: "#C5A6E8", name: 'purple'}, - {hex: "#A6C8FF", name: 'blue'}, - {hex: "#7BFFA3", name: 'green'}, - {hex: "#BDFFA6", name: 'lime'} +var markerColors = [ + {pastel: "#A2EBFF", standard: "#58C0FF", name: 'light_blue'}, + {pastel: "#FFF899", standard: "#F3D81A", name: 'yellow'}, + {pastel: "#E8BD7B", standard: "#EC9218", name: 'orange'}, + {pastel: "#FFA7A4", standard: "#FA565D", name: 'red'}, + {pastel: "#C5A6E8", standard: "#B55AF8", name: 'purple'}, + {pastel: "#A6C8FF", standard: "#4D89FF", name: 'blue'}, + {pastel: "#7BFFA3", standard: "#00CE71", name: 'green'}, + {pastel: "#BDFFA6", standard: "#AFFF62", name: 'lime'} ] class OutlinerElement { constructor(uuid) { @@ -264,6 +264,7 @@ class OutlinerElement { } } createUniqueName(arr) { + if (!Condition(this.needsUniqueName)) return; var scope = this; var others = this.constructor.all.slice(); if (arr && arr.length) { @@ -871,7 +872,8 @@ function stopRenameOutliner(save) { } } function toggleCubeProperty(key) { - var state = selected[0][key] + if (!Cube.selected.length) return; + var state = Cube.selected[0][key] if (typeof state === 'number') { state++; if (state === 3) { @@ -880,8 +882,8 @@ function toggleCubeProperty(key) { } else { state = !state } - Undo.initEdit({elements: selected}) - selected.forEach(cube => { + Undo.initEdit({elements: Cube.selected}) + Cube.selected.forEach(cube => { cube[key] = state; }) if (key === 'visibility') { diff --git a/js/plugin_loader.js b/js/plugin_loader.js index 8e3e50fb7..ce011a58c 100644 --- a/js/plugin_loader.js +++ b/js/plugin_loader.js @@ -391,10 +391,11 @@ BARS.defineActions(function() { icon: 'fa-file-code', category: 'blockbench', click: function () { + var startpath = localStorage.getItem('plugin_dev_path') || undefined; Blockbench.import({ extensions: ['js'], type: 'Blockbench Plugin', - startpath: localStorage.getItem('plugin_dev_path') + startpath }, function(files) { loadPluginFromFile(files[0]) }) diff --git a/js/preview/preview.js b/js/preview/preview.js index 63d64d840..47070e9e1 100644 --- a/js/preview/preview.js +++ b/js/preview/preview.js @@ -51,25 +51,31 @@ class Preview { this.controls.enableKeys = false; this.controls.zoomSpeed = 1.5; - this.annotations = []; - this.controls.onUpdate(() => { - setTimeout(() => { - this.annotations.forEach(tag => { + //Annotations + this.annotations = {}; + this.updateAnnotations = function() { + for (var key in scope.annotations) { + var tag = scope.annotations[key]; if (tag.object.visible) { - var pos = tag.object.toScreenPosition(this.camera, this.canvas); + var pos = tag.object.toScreenPosition(scope.camera, scope.canvas); $(tag.node).css('left', pos.x+'px'); $(tag.node).css('top', pos.y+'px'); } - }) - }, 6) - }) - this.addExampleTag = function() { - var obj = $('
    Hallo
    '); - obj.insertBefore(scope.canvas); - this.annotations.push({ - object: Cube.selected[0].mesh, - node: obj.get(0), - }) + } + } + this.controls.onUpdate(() => setTimeout(() => { + scope.updateAnnotations(); + }, 6)) + this.addAnnotation = function(key, tag) { + scope.annotations[key] = tag; + $(tag.node).insertBefore(scope.canvas); + scope.updateAnnotations(); + } + this.removeAnnotation = function(key) { + if (scope.annotations[key]) { + $(scope.annotations[key].node).detach(); + delete scope.annotations[key]; + } } this.resetCamera(true) @@ -338,11 +344,16 @@ class Preview { } //Controls click(event) { - event.preventDefault() - $(':focus').blur() - unselectInterface(event) + event.preventDefault(); + $(':focus').blur(); + unselectInterface(event); convertTouchEvent(event); this.static_rclick = event.which === 3 || event.type == 'touchstart'; + if (event.type == 'touchstart') { + this.rclick_cooldown = setTimeout(() => { + this.rclick_cooldown = true; + }, 420) + } quad_previews.current = this; if (Transformer.hoverAxis !== null || (!Keybinds.extra.preview_select.keybind.isTriggered(event) && event.which !== 0)) return; @@ -411,7 +422,7 @@ class Preview { } showContextMenu(event, force) { Prop.active_panel = 'preview'; - if (this.static_rclick && (event.which === 3 || event.type == 'touchend')) { + if (this.static_rclick && (event.which === 3 || (event.type == 'touchend' && this.rclick_cooldown == true))) { var data = this.raycast(event) if (Toolbox.selected.selectCubes && Modes.selected.selectCubes && data && data.cube) { data.cube.showContextMenu(event) @@ -419,6 +430,8 @@ class Preview { this.menu.open(event, this) } } + clearTimeout(this.rclick_cooldown); + delete this.rclick_cooldown; return this; } //Selection Rectangle @@ -757,6 +770,13 @@ class Preview { } }, 'image', false) }}, + {icon: 'fa-clipboard', name: 'menu.preview.background.clipboard', condition: isApp, click: function(preview) { + var image = clipboard.readImage().toDataURL(); + if (image.length > 32) { + preview.background.image = image; + preview.loadBackground(); + } + }}, {icon: 'photo_size_select_large', name: 'menu.preview.background.position', condition: has_background, click: function(preview) { preview.startMovingBackground() }}, @@ -1200,13 +1220,13 @@ function initCanvas() { this.tex.needsUpdate = true; } emptyMaterials = [] - cubeColors.forEach(function(s, i) { + markerColors.forEach(function(s, i) { var thismaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, vertexColors: THREE.FaceColors, map: tex }) - thismaterial.color.set(s.hex) + thismaterial.color.set(s.pastel) emptyMaterials.push(thismaterial) }) @@ -1239,6 +1259,7 @@ function initCanvas() { rot_origin.add(helper2) rot_origin.rotation.reorder('ZYX') + rot_origin.base_scale = new THREE.Vector3(1, 1, 1); setupGrid = true; diff --git a/js/preview/transformer.js b/js/preview/transformer.js index cdca97e35..cd7c53351 100644 --- a/js/preview/transformer.js +++ b/js/preview/transformer.js @@ -176,11 +176,14 @@ this.highlight = function ( axis ) { + var axis_letter = typeof axis === 'string' && axis.substr(-1).toLowerCase(); + this.traverse( function( child ) { if ( child.material && child.material.highlight ) { - - if ( child.name === axis) { + + + if ( child.name === axis && axis_letter && child.scale[axis_letter] < 5) { child.material.highlight( true ); @@ -225,7 +228,7 @@ THREE.TransformGizmo.call( this ); var arrowGeometry = new THREE.Geometry(); - var mesh = new THREE.Mesh( new THREE.CylinderGeometry( 0, 0.05, 0.2, 12, 1, false ) ); + var mesh = new THREE.Mesh( new THREE.CylinderGeometry( 0, 0.07, 0.2, 12, 1, false ) ); mesh.position.y = 0.5; mesh.updateMatrix(); @@ -629,6 +632,7 @@ var oldScale = 0; var oldScaleTranslation = 0; var positionSnapOffset = new THREE.Vector3() + var originalValue = null; var previousValue = 0; var tempScale = 1; @@ -727,6 +731,9 @@ scale = (6 / scope.camera.zoom) * (settings.origin_size.value / 50); } rot_origin.scale.set( scale, scale, scale ); + if (rot_origin.base_scale) { + rot_origin.scale.multiply(rot_origin.base_scale); + } if (scope.elements.length == 0) return; @@ -907,6 +914,34 @@ } } } + function displayDistance(number) { + Blockbench.setStatusBarText(trimFloatNumber(number)); + } + function extendTransformLine(long) { + + let axis = scope.axis.substr(-1).toLowerCase(); + let axisNumber = getAxisNumber(axis); + let main_gizmo = _gizmo[_mode].children[0]; + + switch (Toolbox.selected.transformerMode) { + default: + var line = main_gizmo.children[axisNumber*2]; + break; + case 'scale': + var line = main_gizmo.children[(axisNumber*2 + (scope.direction?1:0)) * 2]; + break; + case 'rotate': + var line = rot_origin; + break; + } + line.scale[axis] = long ? 20000 : 1; + if (Toolbox.selected.transformerMode !== 'rotate') { + line.position[axis] = long ? -10000 : (scope.direction?0:-1); + } else { + line.base_scale[axis] = long ? 20000 : 1; + } + _gizmo[ _mode ].highlight( scope.axis ); + } function onPointerHover( event ) { @@ -968,6 +1003,7 @@ offset.copy( planeIntersect.point ); previousValue = undefined Canvas.outlineObjects(selected) + extendTransformLine(true); } } } @@ -1105,7 +1141,6 @@ ik_solver.helper = new THREE.IKHelper(ik_solver.ik); scene.add(ik_solver.helper); - cl(ik_solver) setTimeout(_ => ik_solver.ik.solve(), 80)*/ @@ -1166,6 +1201,9 @@ var snap_factor = canvasGridSize(event.shiftKey, event.ctrlOrCmd) point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor; + if (originalValue === null) { + originalValue = point[axis]; + } if (previousValue === undefined) { previousValue = point[axis] @@ -1192,8 +1230,8 @@ Group.selected.forEachChild(g => { g.origin[axisNumber] += difference }, Group, true) - } + displayDistance(point[axis] - originalValue); selected.forEach(function(obj, i) { if (obj.movable) { obj.move(difference, axisNumber, _has_groups||!Format.bone_rig) @@ -1218,6 +1256,7 @@ obj.resize(point[axis], axisNumber, !scope.direction) } }) + displayDistance(point[axis] * (scope.direction ? 1 : -1)); scope.updateSelection() previousValue = point[axis] scope.hasChanged = true @@ -1229,7 +1268,9 @@ angle = Math.round(angle / snap) * snap if (Math.abs(angle) > 300) angle = angle > 0 ? -snap : snap; if (previousValue === undefined) previousValue = angle - + if (originalValue === null) { + originalValue = angle; + } if (previousValue !== angle) { beforeFirstChange(event) @@ -1237,6 +1278,7 @@ rotateOnAxis(n => (n + difference), axisNumber) Canvas.updatePositions(true) scope.updateSelection() + displayDistance(angle - originalValue); previousValue = angle scope.hasChanged = true } @@ -1245,6 +1287,9 @@ var snap_factor = canvasGridSize(event.shiftKey, event.ctrlOrCmd) point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor; + if (originalValue === null) { + originalValue = point[axis]; + } if (previousValue === undefined) { previousValue = point[axis] @@ -1270,6 +1315,7 @@ } }) } + displayDistance(point[axis] - originalValue); Canvas.updatePositions(true); if (Modes.animate) { Animator.preview(); @@ -1300,6 +1346,9 @@ } value = Math.round(value/round_num)*round_num if (previousValue === undefined) previousValue = value + if (originalValue === null) { + originalValue = value; + } if (value !== previousValue && Animator.selected && Animator.selected.getBoneAnimator()) { beforeFirstChange(event) @@ -1324,7 +1373,6 @@ var ik_solver = Transformer.ik_solver; ik_solver.target.position.copy(planeIntersect.point); - cl(ik_solver.target.position.toArray()); main_preview.render() @@ -1332,15 +1380,9 @@ ik_solver.copy_bones.forEach((copy_bone, i) => { var keyframe = scope.keyframes[i]; - cl(keyframe) if (keyframe) { var bone = copy_bone.original; var animator = Animator.selected.getBoneAnimator(bone); - cl(`-- ${keyframe.animator.group.name} --`) - cl(`${bone.name} - Absolute X: ${Math.radToDeg(copy_bone.rotation.x)}`) - cl(`${bone.name} - offset X: ${Math.radToDeg(copy_bone.last_rotation.x - copy_bone.rotation.x)}`) - cl(`${bone.name} - offset y: ${Math.radToDeg(copy_bone.last_rotation.y - copy_bone.rotation.y)}`) - cl(`${bone.name} - offset z: ${Math.radToDeg(copy_bone.last_rotation.z - copy_bone.rotation.z)}`) keyframe.offset('x', Math.radToDeg(copy_bone.last_rotation.x - copy_bone.rotation.x)); keyframe.offset('y', Math.radToDeg(copy_bone.last_rotation.y - copy_bone.rotation.y)); @@ -1356,6 +1398,7 @@ scope.keyframes[0].offset(axis, difference); scope.keyframes[0].select() } + displayDistance(value - originalValue); Animator.preview() previousValue = value @@ -1389,6 +1432,9 @@ } } if (previousValue === undefined) previousValue = value + if (originalValue === null) { + originalValue = value; + } if (value !== previousValue) { beforeFirstChange(event) @@ -1403,6 +1449,8 @@ } DisplayMode.slot.update() + displayDistance(value - originalValue); + previousValue = value scope.hasChanged = true } @@ -1421,8 +1469,13 @@ mouseUpEvent.mode = _mode; scope.dispatchEvent( mouseUpEvent ); - scope.orbit_controls.stopMovement() - outlines.children.length = 0 + scope.orbit_controls.stopMovement(); + outlines.children.length = 0; + originalValue = null; + + extendTransformLine(false); + + Blockbench.setStatusBarText(); if (Modes.id === 'edit' || Toolbox.selected.id == 'pivot_tool') { if (Toolbox.selected.id === 'resize_tool') { diff --git a/js/texturing/color.js b/js/texturing/color.js index ed76685f1..7129a0e2b 100644 --- a/js/texturing/color.js +++ b/js/texturing/color.js @@ -108,12 +108,14 @@ onVueSetup(() => { this.palette.splice(event.newIndex, 0, item); }, drop: function(event) { + /* var scope = this; setTimeout(() => { if ($('#palette_list:hover').length === 0) { scope.palette.splice(event.oldIndex, 1)[0] } }, 30) + */ }, setColor(color) { ColorPanel.set(color); @@ -186,9 +188,9 @@ onVueSetup(() => { ColorPanel.importPalette = function(string) { var colors = []; - var m_hex = string.match(/#[a-fA-F0-9]{6}/g) + var m_hex = string.match(/(#|FF)?[a-fA-F0-9]{6}/g) if (m_hex) m_hex.forEach(color => { - color = color.toLowerCase(); + color = color.substr(-6).toLowerCase(); colors.safePush(color); }) var m_rgb = string.match(/\(\s*\d{1,3},\s*\d{1,3},\s*\d{1,3}\s*\)/g) @@ -201,6 +203,11 @@ onVueSetup(() => { color = tinycolor(`rgb(${color.substr(1).replace(/ /g, ',')})`); colors.safePush(color.toHexString()); }) + var m_gpl = string.match(/\n\d{1,3} \d{1,3} \d{1,3}/g) + if (m_gpl) m_gpl.forEach(color => { + color = tinycolor(`rgb(${color.substr(1).replace(/ /g, ',')})`); + colors.safePush(color.toHexString()); + }) var dialog = new Dialog({ id: 'palette_import', title: 'action.import_palette', @@ -224,7 +231,7 @@ onVueSetup(() => { } Blockbench.addDragHandler('palette', { - extensions: ['bbpalette', 'css', 'txt', 'gpl'], + extensions: ['bbpalette', 'css', 'txt', 'gpl', 'hex'], readtype: 'text', element: '#color', propagate: true, @@ -235,24 +242,9 @@ onVueSetup(() => { }) Toolbars.palette.toPlace(); Toolbars.color_picker.toPlace(); - /* - Import Palette + drop (replace or add after current) - Export Palette - Add current color to palette - (restore default palette) - Generate palette from texture (replace or add after current) - blur_linear - */ }) - - - - - - - BARS.defineActions(function() { new Action('add_to_palette', { @@ -271,7 +263,7 @@ BARS.defineActions(function() { category: 'color', click: function () { Blockbench.import({ - extensions: ['bbpalette', 'css', 'txt', 'gpl'], + extensions: ['bbpalette', 'css', 'txt', 'gpl', 'hex'], type: 'Blockbench Palette' }, function(files) { if (files && files[0] && typeof files[0].content == 'string') { diff --git a/js/texturing/painter.js b/js/texturing/painter.js index b07b38030..1d8401ac2 100644 --- a/js/texturing/painter.js +++ b/js/texturing/painter.js @@ -11,6 +11,11 @@ const Painter = { if (!options.no_undo) { Undo.initEdit({textures: [texture], bitmap: true}) } + if (texture.mode === 'link') { + texture.source = 'data:image/png;base64,' + texture.getBase64() + texture.mode = 'bitmap' + texture.saved = false + } var instance = Painter.current[options.method === 'canvas' ? 'canvas' : 'image'] Painter.current[options.method === 'canvas' ? 'image' : 'canvas'] = undefined @@ -66,7 +71,6 @@ const Painter = { } } }, - setAlphaMatrix(tex, x, y, val) { if (!Painter.current.alpha_matrix) Painter.current.alpha_matrix = {} var mx = Painter.current.alpha_matrix; @@ -80,7 +84,6 @@ const Painter = { && Painter.current.alpha_matrix[tex.uuid][x] && Painter.current.alpha_matrix[tex.uuid][x][y]; }, - startBrushCanvas(data, e) { if (!data && Toolbox.selected.id == 'color_picker') { var preview = quad_previews.current @@ -191,7 +194,7 @@ const Painter = { } if (is_line) { - Painter.drawBrushLine(texture, x, y, event); + Painter.drawBrushLine(texture, x, y, event, false, uvTag); } else { Painter.current.x = Painter.current.y = 0 Painter.useBrush(texture, x, y, event, uvTag) @@ -554,6 +557,16 @@ const Painter = { this.bitmap.data[idx + 3] = color.a*opacity } }) + } +} +const TextureGenerator = { + face_data: { + up: {c1: '#b4d4e1', c2: '#ecf8fd', place: t => {return {x: t.posx+t.z, y: t.posy, w: t.x, h: t.z}}}, + down: {c1: '#536174', c2: '#6e788c', place: t => {return {x: t.posx+t.z+t.x, y: t.posy, w: t.x, h: t.z}}}, + east: {c1: '#43e88d', c2: '#7BFFA3', place: t => {return {x: t.posx, y: t.posy+t.z, w: t.z, h: t.y}}}, + north: {c1: '#5bbcf4', c2: '#7BD4FF', place: t => {return {x: t.posx+t.z, y: t.posy+t.z, w: t.x, h: t.y}}}, + west: {c1: '#f48686', c2: '#FFA7A4', place: t => {return {x: t.posx+t.z+t.x, y: t.posy+t.z, w: t.z, h: t.y}}}, + south: {c1: '#f8dd72', c2: '#FFF899', place: t => {return {x: t.posx+t.z+t.x+t.z,y: t.posy+t.z, w: t.x, h: t.y}}}, }, addBitmapDialog() { var dialog = new Dialog({ @@ -575,6 +588,7 @@ const Painter = { compress: {label: 'dialog.create_texture.compress', type: 'checkbox', value: true, condition: Project.box_uv}, power: {label: 'dialog.create_texture.power', type: 'checkbox', value: true}, double_use: {label: 'dialog.create_texture.double_use', type: 'checkbox', value: true, condition: Project.box_uv}, + box_uv: {label: 'dialog.project.box_uv', type: 'checkbox', value: false, condition: !Project.box_uv}, color: {label: 'data.color', type: 'color', colorpicker: Painter.background_color}, resolution: {label: 'dialog.create_texture.resolution', type: 'select', value: 16, options: { 16: '16', @@ -587,7 +601,7 @@ const Painter = { }, onConfirm: function(results2) { $.extend(results, results2) - Painter.addBitmap(results) + TextureGenerator.addBitmap(results) dialog2.hide() } }).show() @@ -604,7 +618,7 @@ const Painter = { }, onConfirm: function(results2) { $.extend(results, results2) - Painter.addBitmap(results) + TextureGenerator.addBitmap(results) dialog2.hide() } }).show() @@ -657,14 +671,18 @@ const Painter = { uv_only: true, uv_mode: true }) - if (Project.box_uv) { - Painter.generateTemplate(options, makeTexture) + if (Project.box_uv || options.box_uv) { + TextureGenerator.generateTemplate(options, makeTexture) + if (options.box_uv && !Project.box_uv) { + //todo: Undo Integration + Project.box_uv = true; + } } else { - Painter.generateFaceTemplate(options, makeTexture) + TextureGenerator.generateFaceTemplate(options, makeTexture) } } else { Undo.initEdit({textures: []}) - Painter.generateBlank(options.resolution, options.resolution, options.color, makeTexture) + TextureGenerator.generateBlank(options.resolution, options.resolution, options.color, makeTexture) } }, generateBlank(height, width, color, cb) { @@ -678,23 +696,24 @@ const Painter = { cb(canvas.toDataURL()) }, + boxUVCubeTemplate: function(obj, min_size) { + this.x = obj.size(0, true) || min_size; + this.y = obj.size(1, true) || min_size; + this.z = obj.size(2, true) || min_size; + this.posx = obj.uv_offset[0]; + this.posy = obj.uv_offset[1]; + this.obj = obj; + this.template_size = (obj.size(2, true) + obj.size(1, true))+ (obj.size(2, true) + obj.size(0, true))*2; + + this.height = this.z + this.y; + this.width = 2* (this.x + this.z); + return this; + }, generateTemplate(options, cb) { var res = options.resolution; var background_color = options.color; var texture = options.texture; var min_size = Project.box_uv ? 0 : 1; - function cubeTempl(obj) { - this.x = obj.size(0, true) || min_size; - this.y = obj.size(1, true) || min_size; - this.z = obj.size(2, true) || min_size; - this.obj = obj; - this.template_size = (obj.size(2, true) + obj.size(1, true))+ (obj.size(2, true) + obj.size(0, true))*2; - - this.height = this.z + this.y; - this.width = 2* (this.x + this.z); - return this; - } - var res_multiple = res / 16 var templates = []; var doubles = {}; @@ -707,7 +726,7 @@ const Painter = { while (i >= 0) { let obj = cubes[i] if (obj.visibility === true) { - var template = new cubeTempl(obj) + var template = new TextureGenerator.boxUVCubeTemplate(obj, min_size); if (options.double_use && Project.box_uv && textures.length) { var double_key = [...obj.uv_offset, ...obj.size(undefined, true), ].join('_') if (doubles[double_key]) { @@ -850,143 +869,17 @@ const Painter = { ctx.imageSmoothingEnabled = false; - function drawTemplateRectangle(border_color, color, face, coords) { - if (typeof background_color === 'string') { - border_color = background_color - color = undefined - } - ctx.fillStyle = border_color - ctx.fillRect( - coords.x*res_multiple, - coords.y*res_multiple, - coords.w*res_multiple, - coords.h*res_multiple - ) - if (coords.w*res_multiple > 2 && coords.h*res_multiple > 2 && color) { - ctx.fillStyle = color - ctx.fillRect( - coords.x * res_multiple + 1, - coords.y * res_multiple + 1, - coords.w * res_multiple - 2, - coords.h * res_multiple - 2 - ) - } - } - function drawTexture(face, coords) { - if (!Format.single_texture) { - if (face.texture === undefined || face.texture === null) return false; - texture = face.getTexture() - } - if (!texture || !texture.img) return false; - - ctx.save() - var uv = face.uv.slice(); - - if (face.direction === 'up') { - uv = [uv[2], uv[3], uv[0], uv[1]] - } else if (face.direction === 'down') { - uv = [uv[2], uv[1], uv[0], uv[3]] - } - - var src = getRectangle(uv[0], uv[1], uv[2], uv[3]) - var flip = [ - uv[0] > uv[2] ? -1 : 1, - uv[1] > uv[3] ? -1 : 1 - ] - if (flip[0] + flip[1] < 1) { - ctx.scale(flip[0], flip[1]) - } - if (face.rotation) { - ctx.rotate(Math.degToRad(face.rotation)) - let rot = face.rotation - - if (rot <= 180) flip[1] *= -1; - if (rot >= 180) flip[0] *= -1; - - while (rot > 0) { - [coords.x, coords.y] = [coords.y, coords.x]; - [coords.w, coords.h] = [coords.h, coords.w]; - rot -= 90; - } - } - ctx.drawImage( - texture.img, - src.ax/Project.texture_width * texture.img.naturalWidth, - src.ay/Project.texture_height * texture.img.naturalHeight, - src.x /Project.texture_width * texture.img.naturalWidth, - src.y /Project.texture_height * texture.img.naturalHeight, - coords.x*res_multiple*flip[0], - coords.y*res_multiple*flip[1], - coords.w*res_multiple*flip[0], - coords.h*res_multiple*flip[1] - ) - ctx.restore() - return true; - } - - var face_data = { - up: {c1: '#b4d4e1', c2: '#ecf8fd', place: t => {return {x: t.posx+t.z, y: t.posy, w: t.x, h: t.z}}}, - down: {c1: '#536174', c2: '#6e788c', place: t => {return {x: t.posx+t.z+t.x, y: t.posy, w: t.x, h: t.z}}}, - east: {c1: '#43e88d', c2: '#7BFFA3', place: t => {return {x: t.posx, y: t.posy+t.z, w: t.z, h: t.y}}}, - north: {c1: '#5bbcf4', c2: '#7BD4FF', place: t => {return {x: t.posx+t.z, y: t.posy+t.z, w: t.x, h: t.y}}}, - west: {c1: '#f48686', c2: '#FFA7A4', place: t => {return {x: t.posx+t.z+t.x, y: t.posy+t.z, w: t.z, h: t.y}}}, - south: {c1: '#f8dd72', c2: '#FFF899', place: t => {return {x: t.posx+t.z+t.x+t.z,y: t.posy+t.z, w: t.x, h: t.y}}}, - } - //Drawing - templates.forEach(function(t) { - let obj = t.obj - - for (var face in face_data) { - let d = face_data[face] - - if (!t.obj.faces[face].texture || - !drawTexture(t.obj.faces[face], d.place(t)) - ) { - drawTemplateRectangle(d.c1, d.c2, t.obj.faces[face], d.place(t)) - } - } - obj.uv_offset[0] = t.posx; - obj.uv_offset[1] = t.posy; - - if (t.duplicates) { - t.duplicates.forEach(t_2 => { - t_2.obj.uv_offset[0] = t.posx; - t_2.obj.uv_offset[1] = t.posy; - if (t_2.obj !== obj) { - t_2.obj.mirror_uv = t_2.obj.mirror_uv != obj.mirror_uv; - } - }) - } - obj.mirror_uv = false; + Project.texture_width = Project.texture_height = max_size; - if (!Project.box_uv) { - var size = obj.size(undefined, true); - size.forEach((n, i) => { - size[i] = n || min_size; - }) - - var face_list = [ - {face: 'north', fIndex: 10, from: [size[2], size[2]], size: [size[0], size[1]]}, - {face: 'east', fIndex: 0, from: [0, size[2]], size: [size[2], size[1]]}, - {face: 'south', fIndex: 8, from: [size[2]*2 + size[0], size[2]], size: [size[0], size[1]]}, - {face: 'west', fIndex: 2, from: [size[2] + size[0], size[2]], size: [size[2], size[1]]}, - {face: 'up', fIndex: 4, from: [size[2]+size[0], size[2]], size: [-size[0], -size[2]]}, - {face: 'down', fIndex: 6, from: [size[2]+size[0]*2, 0], size: [-size[0], size[2]]} - ] - face_list.forEach(function(f) { - - obj.faces[f.face].uv[0] = (f.from[0] + Math.floor(obj.uv_offset[0]+0.0000001)) / max_size * Project.texture_width; - obj.faces[f.face].uv[1] = (f.from[1] + Math.floor(obj.uv_offset[1]+0.0000001)) / max_size * Project.texture_height; - obj.faces[f.face].uv[2] = (f.from[0] + f.size[0] + Math.floor(obj.uv_offset[0]+0.0000001)) / max_size * Project.texture_width; - obj.faces[f.face].uv[3] = (f.from[1] + f.size[1] + Math.floor(obj.uv_offset[1]+0.0000001)) / max_size * Project.texture_height; - obj.faces[f.face].rotation = 0; - }) - } + templates.forEach(function(t) { + t.obj.uv_offset[0] = t.posx; + t.obj.uv_offset[1] = t.posy; + t.obj.mirror_uv = false; + TextureGenerator.paintCubeBoxTemplate(t.obj, texture, canvas, t); }) var dataUrl = canvas.toDataURL() var texture = cb(dataUrl) - Project.texture_width = Project.texture_height = max_size; if (texture && !Project.single_texture) { templates.forEach(function(t) { t.obj.applyTexture(texture, true) @@ -1002,6 +895,132 @@ const Painter = { uv_mode: true }) }, + boxUVdrawTemplateRectangle(border_color, color, face, coords, texture, canvas) { + if (typeof background_color === 'string') { + border_color = background_color + color = undefined + } + var res_multiple = canvas.width/Project.texture_width; + var ctx = canvas.getContext('2d'); + ctx.fillStyle = border_color; + ctx.fillRect( + coords.x*res_multiple, + coords.y*res_multiple, + coords.w*res_multiple, + coords.h*res_multiple + ) + if (coords.w*res_multiple > 2 && coords.h*res_multiple > 2 && color) { + ctx.fillStyle = color + ctx.fillRect( + coords.x * res_multiple + 1, + coords.y * res_multiple + 1, + coords.w * res_multiple - 2, + coords.h * res_multiple - 2 + ) + } + }, + boxUVdrawTexture(face, coords, texture, canvas) { + if (!Format.single_texture) { + if (face.texture === undefined || face.texture === null) return false; + texture = face.getTexture() + } + if (!texture || !texture.img) return false; + + var ctx = canvas.getContext('2d'); + var res_multiple = canvas.width/Project.texture_width; + ctx.save() + var uv = face.uv.slice(); + + if (face.direction === 'up') { + uv = [uv[2], uv[3], uv[0], uv[1]] + } else if (face.direction === 'down') { + uv = [uv[2], uv[1], uv[0], uv[3]] + } + + var src = getRectangle(uv[0], uv[1], uv[2], uv[3]) + var flip = [ + uv[0] > uv[2] ? -1 : 1, + uv[1] > uv[3] ? -1 : 1 + ] + if (flip[0] + flip[1] < 1) { + ctx.scale(flip[0], flip[1]) + } + if (face.rotation) { + ctx.rotate(Math.degToRad(face.rotation)) + let rot = face.rotation + + if (rot <= 180) flip[1] *= -1; + if (rot >= 180) flip[0] *= -1; + + while (rot > 0) { + [coords.x, coords.y] = [coords.y, coords.x]; + [coords.w, coords.h] = [coords.h, coords.w]; + rot -= 90; + } + } + ctx.drawImage( + texture.img, + src.ax/Project.texture_width * texture.img.naturalWidth, + src.ay/Project.texture_height * texture.img.naturalHeight, + src.x /Project.texture_width * texture.img.naturalWidth, + src.y /Project.texture_height * texture.img.naturalHeight, + coords.x*res_multiple*flip[0], + coords.y*res_multiple*flip[1], + coords.w*res_multiple*flip[0], + coords.h*res_multiple*flip[1] + ) + ctx.restore() + return true; + }, + paintCubeBoxTemplate(cube, texture, canvas, template) { + + if (!template) { + template = new TextureGenerator.boxUVCubeTemplate(cube, Project.box_uv ? 0 : 1); + } + + for (var face in TextureGenerator.face_data) { + let d = TextureGenerator.face_data[face] + + if (!cube.faces[face].texture || + !TextureGenerator.boxUVdrawTexture(cube.faces[face], d.place(template), texture, canvas) + ) { + TextureGenerator.boxUVdrawTemplateRectangle(d.c1, d.c2, cube.faces[face], d.place(template), texture, canvas) + } + } + + if (template && template.duplicates) { + template.duplicates.forEach(t_2 => { + t_2.obj.uv_offset[0] = cube.uv_offset[0]; + t_2.obj.uv_offset[1] = cube.uv_offset[1]; + if (t_2.obj !== cube) { + t_2.obj.mirror_uv = t_2.obj.mirror_uv != cube.mirror_uv; + } + }) + } + + if (!Project.box_uv) { + var size = cube.size(undefined, true); + size.forEach((n, i) => { + size[i] = n; + }) + + var face_list = [ + {face: 'north', fIndex: 10, from: [size[2], size[2]], size: [size[0], size[1]]}, + {face: 'east', fIndex: 0, from: [0, size[2]], size: [size[2], size[1]]}, + {face: 'south', fIndex: 8, from: [size[2]*2 + size[0], size[2]], size: [size[0], size[1]]}, + {face: 'west', fIndex: 2, from: [size[2] + size[0], size[2]], size: [size[2], size[1]]}, + {face: 'up', fIndex: 4, from: [size[2]+size[0], size[2]], size: [-size[0], -size[2]]}, + {face: 'down', fIndex: 6, from: [size[2]+size[0]*2, 0], size: [-size[0], size[2]]} + ] + face_list.forEach(function(f) { + cube.faces[f.face].uv[0] = (f.from[0] + Math.floor(cube.uv_offset[0]+0.0000001)) / canvas.width * Project.texture_width; + cube.faces[f.face].uv[1] = (f.from[1] + Math.floor(cube.uv_offset[1]+0.0000001)) / canvas.height * Project.texture_height; + cube.faces[f.face].uv[2] = (f.from[0]+f.size[0]+ Math.floor(cube.uv_offset[0]+0.0000001)) / canvas.width * Project.texture_width; + cube.faces[f.face].uv[3] = (f.from[1]+f.size[1]+ Math.floor(cube.uv_offset[1]+0.0000001)) / canvas.height * Project.texture_height; + cube.faces[f.face].rotation = 0; + }) + } + }, generateFaceTemplate(options, cb) { var res_multiple = options.resolution / 16; @@ -1197,15 +1216,6 @@ const Painter = { return true; } - var face_data = { - up: {c1: '#b4d4e1', c2: '#ecf8fd'}, - down: {c1: '#536174', c2: '#6e788c'}, - east: {c1: '#43e88d', c2: '#7BFFA3'}, - north: {c1: '#5bbcf4', c2: '#7BD4FF'}, - west: {c1: '#f48686', c2: '#FFA7A4'}, - south: {c1: '#f8dd72', c2: '#FFF899'}, - } - //Drawing face_list.forEach(function(ftemp) { let cube = ftemp.cube @@ -1215,7 +1225,7 @@ const Painter = { w: ftemp.width, h: ftemp.height } - var d = face_data[ftemp.face_key]; + var d = TextureGenerator.face_data[ftemp.face_key]; if (!ftemp.texture || !drawTexture(ftemp.face, pos) ) { @@ -1261,6 +1271,7 @@ BARS.defineActions(function() { category: 'tools', toolbar: 'brush', alt_tool: 'color_picker', + cursor: 'crosshair', selectFace: true, transformerMode: 'hidden', paintTool: true, @@ -1283,6 +1294,7 @@ BARS.defineActions(function() { category: 'tools', toolbar: 'brush', alt_tool: 'color_picker', + cursor: 'crosshair', selectFace: true, transformerMode: 'hidden', paintTool: true, @@ -1305,9 +1317,11 @@ BARS.defineActions(function() { toolbar: 'brush', selectFace: true, transformerMode: 'hidden', + cursor: 'crosshair', paintTool: true, allowWireframe: false, modes: ['paint'], + keybind: new Keybind({key: 69}), onCanvasClick: function(data) { Painter.startBrushCanvas(data, data.event) }, @@ -1323,6 +1337,7 @@ BARS.defineActions(function() { icon: 'colorize', category: 'tools', toolbar: 'brush', + cursor: 'crosshair', selectFace: true, transformerMode: 'hidden', paintTool: true, @@ -1360,10 +1375,10 @@ BARS.defineActions(function() { } }) - new Action('painting_grid', { name: tl('settings.painting_grid'), description: tl('settings.painting_grid.desc'), + label: true, icon: 'check_box', category: 'view', condition: () => Modes.paint, diff --git a/js/texturing/textures.js b/js/texturing/textures.js index b72406870..75d601595 100644 --- a/js/texturing/textures.js +++ b/js/texturing/textures.js @@ -561,9 +561,11 @@ class Texture { textures.splice(textures.indexOf(this), 1) if (!no_update) { Canvas.updateAllFaces() - $('#uv_frame').css('background', 'transparent') TextureAnimator.updateButton() hideDialog() + if (main_uv.texture == this) { + main_uv.displayTexture(); + } BARS.updateConditions() Undo.finishEdit('remove_textures', {textures: []}) } @@ -764,13 +766,12 @@ class Texture { var scope = this; if (!options) options = false; - if (scope.mode === 'link') { - scope.source = 'data:image/png;base64,' + scope.getBase64() - scope.mode = 'bitmap' - scope.saved = false - } if (cb) { - Painter.edit(scope, cb, options) + Painter.edit(scope, cb, options); + + } else if (scope.mode === 'link') { + scope.source = 'data:image/png;base64,' + scope.getBase64(); + scope.mode = 'bitmap'; } scope.saved = false; } @@ -1021,6 +1022,9 @@ TextureAnimator = { animated_tex.push(tex) } }) + if (animated_tex.includes(main_uv.texture)) { + main_uv.img.style.objectPosition = `0 -${main_uv.texture.currentFrame * main_uv.inner_height}px`; + } elements.forEach(function(obj) { var update = false for (var face in obj.faces) { @@ -1032,13 +1036,14 @@ TextureAnimator = { }) }, reset() { - TextureAnimator.stop() + TextureAnimator.stop(); textures.forEach(function(tex, i) { if (tex.frameCount) { tex.currentFrame = 0 $($('.texture').get(i)).find('img').css('margin-top', '0') } }) + main_uv.img.style.objectPosition = ''; while (i < elements.length) { Canvas.updateUV(elements[i], true) i++; @@ -1097,7 +1102,7 @@ BARS.defineActions(function() { category: 'textures', keybind: new Keybind({key: 84, ctrl: true, shift: true}), click: function () { - Painter.addBitmapDialog() + TextureGenerator.addBitmapDialog() } }) new Action('save_textures', { @@ -1106,7 +1111,7 @@ BARS.defineActions(function() { click: function () {saveTextures()} }) new Action('change_textures_folder', { - icon: 'fas fa-hdd', + icon: 'fas.fa-hdd', category: 'textures', condition: () => textures.length > 0, click: function () { diff --git a/js/texturing/uv.js b/js/texturing/uv.js index c8f48d850..9b05c291d 100644 --- a/js/texturing/uv.js +++ b/js/texturing/uv.js @@ -302,6 +302,24 @@ class UVEditor { return false; } }) + //Paint brush outline + var brush_outline = $('
    '); + scope.jquery.frame.on('mouseenter mousemove', e => { + if (Modes.paint && (['brush_tool', 'eraser'].includes(Toolbox.selected.id))) { + scope.jquery.frame.append(brush_outline); + var pixel_size = main_uv.getPixelSize(); + //pos + let left = (0.5 + Math.floor(e.offsetX / pixel_size)) * pixel_size; + let top = (0.5 + Math.floor(e.offsetY / pixel_size)) * pixel_size; + brush_outline.css('left', left+'px').css('top', top+'px'); + //size + var radius = (BarItems.slider_brush_size.get()-0.5) * pixel_size; + brush_outline.css('padding', radius+'px').css('margin', (-radius)+'px'); + } + }) + scope.jquery.frame.on('mouseleave', e => { + brush_outline.detach(); + }) this.setSize(this.size) return this; } @@ -409,7 +427,8 @@ class UVEditor { } } getTexture() { - return Cube.selected[0].faces[this.face].getTexture() + if (Format.single_texture) return textures[0]; + return Cube.selected[0].faces[this.face].getTexture(); } //Set setSize(input_size, cancel_load) { @@ -419,16 +438,14 @@ class UVEditor { this.jquery.frame.width(this.inner_width); this.jquery.viewport.width(size+8); this.jquery.main.width(size+8); - this.updateSize(); - if (old_size !== size) { - this.displayAllMappingOverlays(true) - } for (var id in this.sliders) { this.sliders[id].setWidth(size/(Project.box_uv?2:4)-1) } if (!cancel_load) { - this.loadData() + this.loadData(); + } else { + this.updateSize(); } return this; } @@ -437,7 +454,8 @@ class UVEditor { var size = zoomed_size - (zoomed_size % 16); this.zoom = size/this.size this.updateSize(); - this.displayFrame() + this.displayFrame(); + return this; } setGrid(value) { @@ -468,6 +486,12 @@ class UVEditor { this.inner_height/Project.texture_height/this.grid ]) this.displayMappingOverlay(); + this.updateAllMappingOverlays(); + if (this.texture && this.texture.currentFrame) { + this.img.style.objectPosition = `0 -${this.texture.currentFrame * this.inner_height}px`; + } else { + this.img.style.objectPosition = `0 0`; + } if (this.zoom > 1) { this.jquery.viewport.css('overflow', 'scroll scroll') @@ -565,11 +589,11 @@ class UVEditor { return false; } loadData() { - if (Cube.selected.length === 0) return; - var face = Cube.selected[0].faces[this.face] + if (Cube.selected.length === 0 && !Modes.paint) return; + var face = Cube.selected[0] && Cube.selected[0].faces[this.face]; //Set Rotation - BarItems.uv_rotation.set(face.rotation||0) + BarItems.uv_rotation.set((face && face.rotation)||0) this.displayTexture(face) this.displayFrame()//and transform info @@ -579,14 +603,12 @@ class UVEditor { if (Project.box_uv) { this.displayAllMappingOverlays() } - if (this.id !== 'main_uv') { - this.displayTools() - } if (this !== main_uv && this.face === main_uv.face) { main_uv.loadData() } } save() { + if (!Modes.edit) return; var scope = this; //Save UV from Frame to object @@ -641,8 +663,10 @@ class UVEditor { Undo.finishEdit('apply_texture') } displayTexture(face) { - if (!face) var face = Cube.selected[0].faces[this.face]; - var tex = face.getTexture() + if (!face && Cube.selected.length) { + var face = Cube.selected[0].faces[this.face]; + } + var tex = face ? face.getTexture() : textures[0]; if (!tex || typeof tex !== 'object' || (tex.error && tex.error != 2)) { main_uv.img.src = ''; this.img.style.display = 'none'; @@ -681,6 +705,7 @@ class UVEditor { } displayFrame() { var scope = this; + if (!Modes.edit) return; if (Project.box_uv) { var uvTag = this.getUVTag(Cube.selected[0]) @@ -764,10 +789,12 @@ class UVEditor { width = limitNumber(width *pixels + x, 0, scope.inner_width) - x; height = limitNumber(height*pixels + y, 0, scope.inner_height)- y; + var size_data = [x/pixels, y/pixels, width/pixels, height/pixels].join(','); + sides.append($(`
    `)) + background: ${color};" data-sizes="${size_data}">
    `)) } var size = cube.size(undefined, true); @@ -786,9 +813,11 @@ class UVEditor { var scope = this; var cycle = bbuid(4) if (this.showing_overlays) { - elements.forEach(cube => { + Cube.all.forEach(cube => { var size = cube.size(undefined, true) var hash = `${cube.uv_offset[0]}_${cube.uv_offset[1]}_${size[0]}_${size[1]}_${size[2]}` + if (scope.jquery.frame.find(`> .mapping_overlay_cube.${cycle}[size_hash="${hash}"]`).length) return; + var c = scope.jquery.frame.find(`> .mapping_overlay_cube:not(.${cycle})[size_hash="${hash}"]`).first() if (force_reload || !c.length) { var sides = scope.getMappingOverlay(cube, true) @@ -804,8 +833,33 @@ class UVEditor { $(scope.jquery.frame).find('.mapping_overlay_cube').remove() } } + updateAllMappingOverlays() { + var scope = this; + var pixels = scope.getPixelSize(); + if (this.showing_overlays) { + Cube.all.forEach(cube => { + var size = cube.size(undefined, true) + var hash = `${cube.uv_offset[0]}_${cube.uv_offset[1]}_${size[0]}_${size[1]}_${size[2]}` + var c = scope.jquery.frame.find(`> .mapping_overlay_cube[size_hash="${hash}"]`).first() + + c.children().each((i, side) => { + side = $(side) + var data = side.attr('data-sizes'); + data = data.split(','); + data.forEach((s, i) => { + data[i] = parseInt(s); + }) + side.css('left', (data[0] * pixels)+'px') + .css('top', (data[1] * pixels)+'px') + .css('width', (data[2] * pixels)+'px') + .css('height', (data[3] * pixels)+'px') + }) + }) + } + } //UI displaySliders() { + if (!Cube.selected.length) return; this.sliders.pos_x.update() this.sliders.pos_y.update() this.sliders.size_x.update() @@ -813,6 +867,7 @@ class UVEditor { } displayTools() { //Cullface + if (!Cube.selected.length) return; var face = Cube.selected[0].faces[this.face] BarItems.cullface.set(face.cullface||'off') BarItems.face_tint.setIcon(face.tint ? 'check_box' : 'check_box_outline_blank') @@ -942,7 +997,9 @@ class UVEditor { this.forCubes(obj => { scope.getFaces(event).forEach(function(side) { - var face = obj.faces[side]; + let face = obj.faces[side]; + let mirror_x = face.uv[0] > face.uv[2]; + let mirror_y = face.uv[1] > face.uv[3]; face.uv[0] = Math.min(face.uv[0], face.uv[2]); face.uv[1] = Math.min(face.uv[1], face.uv[3]); if (side == 'north' || side == 'south') { @@ -961,6 +1018,8 @@ class UVEditor { left2 *= scope.getResolution(0, face) / Project.texture_width; top2 *= scope.getResolution(1, face) / Project.texture_height; face.uv_size = [left2, top2]; + if (mirror_x) [face.uv[0], face.uv[2]] = [face.uv[2], face.uv[0]]; + if (mirror_y) [face.uv[1], face.uv[3]] = [face.uv[3], face.uv[1]]; }) obj.autouv = 0 Canvas.updateUV(obj) @@ -1098,9 +1157,7 @@ class UVEditor { if (val === 'off') val = false this.forCubes(obj => { if (val) { - obj.faces[scope.face].cullface = val - } else { - delete obj.faces[scope.face].cullface + obj.faces[scope.face].cullface = val || ''; } }) if (val) { @@ -1291,7 +1348,7 @@ class UVEditor { 'uv_maximize', 'uv_auto', 'uv_rel_auto', - {icon: 'rotate_90_degrees_ccw', condition: () => Format.id == 'java_block' || Format.id == 'free', name: 'menu.uv.mapping.rotation', children: function() { + {icon: 'rotate_90_degrees_ccw', condition: () => Format.uv_rotation, name: 'menu.uv.mapping.rotation', children: function() { var off = 'radio_button_unchecked' var on = 'radio_button_checked' return [ @@ -1337,15 +1394,63 @@ class UVEditor { } }, ]}}, - { - icon: (editor) => (editor.reference_face.tint ? 'check_box' : 'check_box_outline_blank'), - condition: () => !Project.box_uv, - name: 'menu.uv.tint', click: function(editor) { - Undo.initEdit({elements: Cube.selected, uv_only: true}) - editor.switchTint(Cube.selected[0].faces[editor.face].tint) - Undo.finishEdit('face_tint') - } - }, + 'face_tint', + {icon: 'flip_to_back', condition: () => Format.id == 'java_block', name: 'action.cullface', children: function(editor) { + var off = 'radio_button_unchecked'; + var on = 'radio_button_checked'; + return [ + {icon: (!editor.reference_face.cullface ? on : off), name: 'uv_editor.no_faces', click: function() { + Undo.initEdit({elements: Cube.selected, uv_only: true}) + editor.forCubes(obj => { + obj.faces[editor.face].cullface = ''; + }) + Undo.finishEdit('set cullface'); + }}, + {icon: (editor.reference_face.cullface == 'north' ? on : off), name: 'face.north', click: function() { + Undo.initEdit({elements: Cube.selected, uv_only: true}) + editor.forCubes(obj => { + obj.faces[editor.face].cullface = 'north'; + }) + Undo.finishEdit('set cullface'); + }}, + {icon: (editor.reference_face.cullface == 'south' ? on : off), name: 'face.south', click: function() { + Undo.initEdit({elements: Cube.selected, uv_only: true}) + editor.forCubes(obj => { + obj.faces[editor.face].cullface = 'south'; + }) + Undo.finishEdit('set cullface'); + }}, + {icon: (editor.reference_face.cullface == 'west' ? on : off), name: 'face.west', click: function() { + Undo.initEdit({elements: Cube.selected, uv_only: true}) + editor.forCubes(obj => { + obj.faces[editor.face].cullface = 'west'; + }) + Undo.finishEdit('set cullface'); + }}, + {icon: (editor.reference_face.cullface == 'east' ? on : off), name: 'face.east', click: function() { + Undo.initEdit({elements: Cube.selected, uv_only: true}) + editor.forCubes(obj => { + obj.faces[editor.face].cullface = 'east'; + }) + Undo.finishEdit('set cullface'); + }}, + {icon: (editor.reference_face.cullface == 'up' ? on : off), name: 'face.up', click: function() { + Undo.initEdit({elements: Cube.selected, uv_only: true}) + editor.forCubes(obj => { + obj.faces[editor.face].cullface = 'up'; + }) + Undo.finishEdit('set cullface'); + }}, + {icon: (editor.reference_face.cullface == 'down' ? on : off), name: 'face.down', click: function() { + Undo.initEdit({elements: Cube.selected, uv_only: true}) + editor.forCubes(obj => { + obj.faces[editor.face].cullface = 'down'; + }) + Undo.finishEdit('set cullface'); + }}, + 'auto_cullface' + ] + }}, {icon: 'collections', name: 'menu.uv.texture', condition: () => !Project.box_uv, children: function() { var arr = [ {icon: 'crop_square', name: 'menu.cube.texture.blank', click: function(editor, event) { @@ -1691,7 +1796,7 @@ BARS.defineActions(function() { new BarSlider('uv_rotation', { category: 'uv', - condition: () => !Project.box_uv && (Format.id == 'java_block' || Format.id == 'free') && Cube.selected.length, + condition: () => !Project.box_uv && Format.uv_rotation && Cube.selected.length, min: 0, max: 270, step: 90, width: 80, onBefore: () => { Undo.initEdit({elements: Cube.selected, uv_only: true}) diff --git a/js/transform.js b/js/transform.js index 9508268bf..1dc977039 100644 --- a/js/transform.js +++ b/js/transform.js @@ -678,6 +678,7 @@ BARS.defineActions(function() { new NumSlider('slider_pos_x', { name: tl('action.slider_pos', ['X']), description: tl('action.slider_pos.desc', ['X']), + color: 'x', condition: () => (selected.length && Modes.edit), get: function() { return selected[0].from[0] @@ -695,6 +696,7 @@ BARS.defineActions(function() { new NumSlider('slider_pos_y', { name: tl('action.slider_pos', ['Y']), description: tl('action.slider_pos.desc', ['Y']), + color: 'y', condition: () => (selected.length && Modes.edit), get: function() { return selected[0].from[1] @@ -712,6 +714,7 @@ BARS.defineActions(function() { new NumSlider('slider_pos_z', { name: tl('action.slider_pos', ['Z']), description: tl('action.slider_pos.desc', ['Z']), + color: 'z', condition: () => (selected.length && Modes.edit), get: function() { return selected[0].from[2] @@ -738,6 +741,7 @@ BARS.defineActions(function() { new NumSlider('slider_size_x', { name: tl('action.slider_size', ['X']), description: tl('action.slider_size.desc', ['X']), + color: 'x', condition: () => (Cube.selected.length && Modes.edit), get: function() { return Cube.selected[0].to[0] - Cube.selected[0].from[0] @@ -755,6 +759,7 @@ BARS.defineActions(function() { new NumSlider('slider_size_y', { name: tl('action.slider_size', ['Y']), description: tl('action.slider_size.desc', ['Y']), + color: 'y', condition: () => (Cube.selected.length && Modes.edit), get: function() { return Cube.selected[0].to[1] - Cube.selected[0].from[1] @@ -772,6 +777,7 @@ BARS.defineActions(function() { new NumSlider('slider_size_z', { name: tl('action.slider_size', ['Z']), description: tl('action.slider_size.desc', ['Z']), + color: 'z', condition: () => (Cube.selected.length && Modes.edit), get: function() { return Cube.selected[0].to[2] - Cube.selected[0].from[2] @@ -819,6 +825,7 @@ BARS.defineActions(function() { new NumSlider('slider_rotation_x', { name: tl('action.slider_rotation', ['X']), description: tl('action.slider_rotation.desc', ['X']), + color: 'x', condition: () => (Modes.edit && getRotationObject()), get: function() { if (Format.bone_rig && Group.selected) { @@ -843,6 +850,7 @@ BARS.defineActions(function() { new NumSlider('slider_rotation_y', { name: tl('action.slider_rotation', ['Y']), description: tl('action.slider_rotation.desc', ['Y']), + color: 'y', condition: () => (Modes.edit && getRotationObject()), get: function() { if (Format.bone_rig && Group.selected) { @@ -867,6 +875,7 @@ BARS.defineActions(function() { new NumSlider('slider_rotation_z', { name: tl('action.slider_rotation', ['Z']), description: tl('action.slider_rotation.desc', ['Z']), + color: 'z', condition: () => (Modes.edit && getRotationObject()), get: function() { if (Format.bone_rig && Group.selected) { @@ -920,6 +929,7 @@ BARS.defineActions(function() { new NumSlider('slider_origin_x', { name: tl('action.slider_origin', ['X']), description: tl('action.slider_origin.desc', ['X']), + color: 'x', condition: () => (Modes.edit || Modes.animate) && getRotationObject(), get: function() { if (Format.bone_rig && Group.selected) { @@ -942,6 +952,7 @@ BARS.defineActions(function() { new NumSlider('slider_origin_y', { name: tl('action.slider_origin', ['Y']), description: tl('action.slider_origin.desc', ['Y']), + color: 'y', condition: () => (Modes.edit || Modes.animate) && getRotationObject(), get: function() { if (Format.bone_rig && Group.selected) { @@ -964,6 +975,7 @@ BARS.defineActions(function() { new NumSlider('slider_origin_z', { name: tl('action.slider_origin', ['Z']), description: tl('action.slider_origin.desc', ['Z']), + color: 'z', condition: () => (Modes.edit || Modes.animate) && getRotationObject(), get: function() { if (Format.bone_rig && Group.selected) { @@ -1144,42 +1156,42 @@ BARS.defineActions(function() { new Action('move_up', { icon: 'arrow_upward', category: 'transform', - condition: () => (selected.length && !open_menu && Modes.id === 'edit'), + condition: {modes: ['edit'], method: () => (!open_menu && selected.length)}, keybind: new Keybind({key: 38, ctrl: null, shift: null}), click: function (e) {moveCubesRelative(-1, 2, e)} }) new Action('move_down', { icon: 'arrow_downward', category: 'transform', - condition: () => (selected.length && !open_menu && Modes.id === 'edit'), + condition: {modes: ['edit'], method: () => (!open_menu && selected.length)}, keybind: new Keybind({key: 40, ctrl: null, shift: null}), click: function (e) {moveCubesRelative(1, 2, e)} }) new Action('move_left', { icon: 'arrow_back', category: 'transform', - condition: () => (selected.length && !open_menu && Modes.id === 'edit'), + condition: {modes: ['edit'], method: () => (!open_menu && selected.length)}, keybind: new Keybind({key: 37, ctrl: null, shift: null}), click: function (e) {moveCubesRelative(-1, 0, e)} }) new Action('move_right', { icon: 'arrow_forward', category: 'transform', - condition: () => (selected.length && !open_menu && Modes.id === 'edit'), + condition: {modes: ['edit'], method: () => (!open_menu && selected.length)}, keybind: new Keybind({key: 39, ctrl: null, shift: null}), click: function (e) {moveCubesRelative(1, 0, e)} }) new Action('move_forth', { icon: 'keyboard_arrow_up', category: 'transform', - condition: () => (selected.length && !open_menu && Modes.id === 'edit'), + condition: {modes: ['edit'], method: () => (!open_menu && selected.length)}, keybind: new Keybind({key: 33, ctrl: null, shift: null}), click: function (e) {moveCubesRelative(-1, 1, e)} }) new Action('move_back', { icon: 'keyboard_arrow_down', category: 'transform', - condition: () => (selected.length && !open_menu && Modes.id === 'edit'), + condition: {modes: ['edit'], method: () => (!open_menu && selected.length)}, keybind: new Keybind({key: 34, ctrl: null, shift: null}), click: function (e) {moveCubesRelative(1, 1, e)} }) diff --git a/js/util.js b/js/util.js index 4754815b9..4d647ff80 100644 --- a/js/util.js +++ b/js/util.js @@ -332,8 +332,7 @@ Array.prototype.empty = function() { return this; } Array.prototype.purge = function() { - this.length = Math.clamp(this.length, 0, 1); - this.splice(0, 1) + this.splice(0, Infinity); return this; } Array.prototype.findInArray = function(key, value) { diff --git a/lang/de.json b/lang/de.json index 63234d5be..5e3c1359e 100644 --- a/lang/de.json +++ b/lang/de.json @@ -998,5 +998,30 @@ "action.export_entity": "Bedrock Entitymodell exportieren", "action.export_entity.desc": "Exportiert das Modell als ein Bedrock Entitymodell", "settings.highlight_cubes": "Elemente hervorheben", - "settings.highlight_cubes.desc": "Elemente erscheinen heller, wenn man die Maus über sie bewegt oder sie auswählt" + "settings.highlight_cubes.desc": "Elemente erscheinen heller, wenn man die Maus über sie bewegt oder sie auswählt", + "action.add_marker": "Marker setzen", + "action.add_marker.desc": "Setzt einen Marker in der Timeline", + "timeline.pre_effect_script": "Skript", + "format.skin": "Skin", + "format.skin.desc": "Bearbeite Spielerskins und Entity-Texturen", + "message.sketchfab.setup_guide": "Finde heraus, wie du Modelle auf Sketchfab einrichtest: %0", + "dialog.skin.title": "Skin erstellen", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Textur (Optional)", + "action.toggle_skin_layer": "Zweite Skin-Schicht umschalten", + "action.toggle_skin_layer.desc": "Aktiviert / Deaktiviert die Hut- und Kleidungsebene", + "action.gui_light": "Inventarbeleuchtung", + "action.gui_light.desc": "Wähle die Art der Beleuchtung des Gegenstands im Inventar", + "action.gui_light.side": "Seitliches Licht", + "action.gui_light.front": "Frontales Licht", + "action.move_keyframe_back": "Keyframe zurück bewegen", + "action.move_keyframe_forth": "Keyframe vorwärts bewegen", + "menu.help": "Hilfe", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Einen Bug Melden", + "menu.help.plugin_documentation": "Plugin API Dokumentation", + "menu.help.search_action": "Befehl suchen und ausführen", + "menu.help.donate": "Spenden", + "menu.help.about": "Über...", + "menu.preview.background.clipboard": "Aus Zwischenablage laden" } \ No newline at end of file diff --git a/lang/en.json b/lang/en.json index a1727aaa9..2e302d6aa 100644 --- a/lang/en.json +++ b/lang/en.json @@ -55,6 +55,8 @@ "format.free": "Free Model", "format.free.desc": "Model without restrictions for Unity etc.", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", "format.java_block": "Java Block/Item", "format.java_block.desc": "Block model for Java Edition. Size and rotations are limited.", "format.bedrock": "Bedrock Model", @@ -196,6 +198,7 @@ "message.sketchfab.name_or_token": "Please enter your Sketchfab token and a name", "message.sketchfab.success": "Uploaded model successfully", "message.sketchfab.error": "Failed to upload model to Sketchfab", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", "message.removed_faces": "Removed %0 faces", "message.add_to_palette": "Added to palette", "message.size_modifiers": "Hold down Ctrl or Shift to transform in smaller increments.", @@ -335,6 +338,10 @@ "dialog.model_stats.groups": "Groups", "dialog.model_stats.vertices": "Vertices", "dialog.model_stats.faces": "Faces", + + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", "dialog.settings.settings": "Settings", "dialog.settings.keybinds": "Keybindings", @@ -582,6 +589,8 @@ "action.eraser.desc": "Eraser tool to replace colors on a texture with transparency", "action.color_picker": "Color Picker", "action.color_picker.desc": "Tool to pick the color of pixels on your texture", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", "action.vertex_snap_tool": "Vertex Snap", "action.vertex_snap_tool.desc": "Move one cube to another cube by connecting two vertices", @@ -748,6 +757,10 @@ "action.add_display_preset": "New Preset", "action.add_display_preset.desc": "Add a new display setting preset.", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", "action.move_up": "Move Up", "action.move_up.desc": "Move the selected cubes up relative to the current camera angle", @@ -875,6 +888,10 @@ "action.slider_animation_speed.desc": "Playback speed of the timeline in percent", "action.add_keyframe": "Add Keyframe", "action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values", + "action.add_marker": "Set Marker", + "action.add_marker.desc": "Set a timeline marker", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", "action.previous_keyframe": "Previous Keyframe", "action.previous_keyframe.desc": "Jump to the previous keyframe", "action.next_keyframe": "Next Keyframe", @@ -897,6 +914,7 @@ "timeline.sound": "Sound", "timeline.effects": "Effects", "timeline.timeline": "Instructions", + "timeline.pre_effect_script": "Script", "menu.file": "File", "menu.edit": "Edit", @@ -905,6 +923,7 @@ "menu.display": "Display", "menu.animation": "Animation", "menu.view": "View", + "menu.help": "Help", "menu.file.new": "New", "menu.file.recent": "Recent", @@ -921,6 +940,13 @@ "menu.view.background": "Background", "menu.view.screenshot": "Screenshot", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.cube.color": "Marker Color", "menu.cube.texture": "Texture", "menu.cube.texture.transparent": "Transparent", @@ -947,6 +973,7 @@ "menu.preview.background": "Background", "menu.preview.background.load": "Load", + "menu.preview.background.clipboard": "Load from Clipboard", "menu.preview.background.position": "Position", "menu.preview.background.set_position": "Set Position", "menu.preview.background.lock": "Lock To Camera", diff --git a/lang/es.json b/lang/es.json index 9c91472db..48a09ab1f 100644 --- a/lang/es.json +++ b/lang/es.json @@ -998,5 +998,30 @@ "action.export_entity": "Exportar Entidad de Bedrock", "action.export_entity.desc": "Añadir el modelo actual como una entidad a un archivo mobs.json", "settings.highlight_cubes": "Resaltar Cubos", - "settings.highlight_cubes.desc": "Resaltar los cubos cuando pasas por encima de ellos o los seleccionas" + "settings.highlight_cubes.desc": "Resaltar los cubos cuando pasas por encima de ellos o los seleccionas", + "action.add_marker": "Poner Marcador", + "action.add_marker.desc": "Pone un marcador de línea de tiempo", + "timeline.pre_effect_script": "Guión\n", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/fr.json b/lang/fr.json index e8aedbd22..69c23c0bf 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -993,10 +993,35 @@ "menu.palette.load.default": "Par défaut", "panel.color.picker": "Sélecteur", "panel.color.palette": "Palette", - "generic.import": "Import", - "settings.brush_modifier.none": "None", - "action.export_entity": "Export Bedrock Entity", - "action.export_entity.desc": "Add the current model as an entity to a mobs.json file", - "settings.highlight_cubes": "Highlight Cubes", - "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them" + "generic.import": "Importer", + "settings.brush_modifier.none": "Aucun(e)", + "action.export_entity": "Exporter entité Bedrock", + "action.export_entity.desc": "Ajouter le modèle actuel comment entité à un fichier mobs.json", + "settings.highlight_cubes": "Surligner cubes", + "settings.highlight_cubes.desc": "Surligne les cubes que vous survolez ou sélectionnez", + "action.add_marker": "Définir un repère", + "action.add_marker.desc": "Définir un repère chronologique", + "timeline.pre_effect_script": "Scripte", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/it.json b/lang/it.json index 57587a5a5..6a4807336 100644 --- a/lang/it.json +++ b/lang/it.json @@ -998,5 +998,30 @@ "action.export_entity": "Export Bedrock Entity", "action.export_entity.desc": "Add the current model as an entity to a mobs.json file", "settings.highlight_cubes": "Highlight Cubes", - "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them" + "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them", + "action.add_marker": "Set Marker", + "action.add_marker.desc": "Set a timeline marker", + "timeline.pre_effect_script": "Script", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/ja.json b/lang/ja.json index 1ff7946af..b77088478 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -17,7 +17,7 @@ "keys.ctrl": "コントロール", "keys.shift": "シフト", "keys.alt": "Alt", - "keys.meta": "Ctrl", + "keys.meta": "Cmd", "keys.delete": "Delete", "keys.space": "スペース", "keys.leftclick": "左クリック", @@ -47,51 +47,51 @@ "keys.printscreen": "Prt Scr", "keys.pause": "Pause", "message.rotation_limit.title": "回転制限", - "message.rotation_limit.message": "回転は、Minecraftによって22.5度単位で制限されています。別の軸を回転すると、他の軸の回転がすべてクリアされます。自由回転が必要な場合は、\"回転制限\"を無効にしてください。", + "message.rotation_limit.message": "回転はMinecraftによって22.5度単位で制限されています。別の軸を回転すると他の軸の回転がすべてクリアされます。自由回転が必要な場合は、回転制限を無効にしてください", "message.file_not_found.title": "ファイルが見つかりませんでした", - "message.file_not_found.message": "ファイルを見つけることが出来ませんでした。ローカルデスクに保存されていることを確認してください。", + "message.file_not_found.message": "ファイルを見つけることが出来ませんでした。ローカルデスクに保存されていることを確認してください", "message.screenshot.title": "スクリーンショット", "message.screenshot.message": "スクリーンショットキャプチャー", "message.screenshot.clipboard": "クリップボード", - "message.screenshot.right_click": "スクリーンショット-右クリックでコピーします。", + "message.screenshot.right_click": "スクリーンショット-右クリックでコピーします", "message.invalid_file.title": "無効なファイル", "message.invalid_file.message": "モデルファイルを開くことが出来ませんでした:%0", "message.invalid_model.title": "無効なモデルファイル", - "message.invalid_model.message": "このファイルには有効なモデルデータが含まれていません。", + "message.invalid_model.message": "このファイルには有効なモデルデータが含まれていません", "message.child_model_only.title": "無効なモデル", "message.child_model_only.message": "このファイルは%0、無効なモデルを含んでいます", "message.drag_background.title": "ポジションの背景", - "message.drag_background.message": "背景をドラックして位置を移動します。Shiftキーを押しながら上下にドラックするとサイズが変わります。", + "message.drag_background.message": "背景をドラックして位置を移動します。Shiftキーを押しながら上下にドラックするとサイズが変わります", "message.unsaved_textures.title": "未保存テクスチャ", - "message.unsaved_textures.message": "モデルに、保存されていないテクスチャがあります。それらを保存し、正しいフォルダに入れてください。", + "message.unsaved_textures.message": "モデルに、保存されていないテクスチャがあります。それらを保存し正しいフォルダに入れてください", "message.model_clipping.title": "モデルが大きすぎます", - "message.model_clipping.message": "このモデルは、3×3×3より大きい立方体%0が含まれているため、Minecraftで使用できません。これを防ぐには、'制限されたキャンバス'を有効にしてください。", + "message.model_clipping.message": "このモデルは、3×3×3より大きい立方体%0が含まれているため、Minecraftで使用できません。これを防ぐには、制限されたキャンバスを有効にしてください", "message.loose_texture.title": "テクスチャを導入", - "message.loose_texture.message": "インポートされたテクスチャはリソースパックファイルに含まれていません。Minecraftはリソースパックファイルのtexturesフォルダ内のみテクスチャをロードできます。", + "message.loose_texture.message": "インポートされたテクスチャはリソースパックファイルに含まれていません Minecraftはリソースパックファイルのtexturesフォルダ内のみテクスチャをロードできます", "message.loose_texture.change": "パスを変更する", "message.update_res.title": "テクスチャの解像度", - "message.update_res.message": "プロジェクトの解像度をこのテクスチャの解像度に更新しますか?テクスチャの解像度が通常より高い場合は、「キャンセル」をクリックしてください。", + "message.update_res.message": "プロジェクトの解像度をこのテクスチャの解像度に更新しますか?テクスチャの解像度が通常より高い場合は「キャンセル」をクリックしてください", "message.update_res.update": "更新する", - "message.bedrock_overwrite_error.message": "このモデルは古いファイルと組み合わせることが出来ません。", + "message.bedrock_overwrite_error.message": "このモデルは古いファイルと組み合わせることが出来ません", "message.bedrock_overwrite_error.backup_overwrite": "バックアップの作成と上書き", - "message.bedrock_overwrite_error.overwrite": "上書きする", + "message.bedrock_overwrite_error.overwrite": "上書き", "message.close_warning.message": "モデルを保存しますか?", "message.close_warning.web": "保存が完了してません。本当に終了しますか?", "message.default_textures.title": "デフォルトテクスチャ", - "message.default_textures.message": "デフォルトのリソースパックのファイルを選択します。", - "message.default_textures.detail": "Minecraft jarまたはgoogleからデフォルトのリソースパックをダウンロードします。次に、\"textures\"フォルダを開きます。Blockbenchは、現在のリソースパックで見つからない場合はそこからテクスチャを取得しようとします。", + "message.default_textures.message": "デフォルトのリソースパックのファイルを選択します", + "message.default_textures.detail": "Minecraft jarまたはgoogleからデフォルトのリソースパックをダウンロードします。次に、\"textures\"フォルダを開きます。Blockbenchは、現在のリソースパックで見つからない場合はそこからテクスチャを取得しようとします", "message.default_textures.select": "デフォルトの\"textures\"フォルダを選択", "message.image_editor.title": "画像エディタを選択", "message.image_editor.file": "ファイルを選ぶ…", "message.image_editor.exe": "使用可能な画像エディタを選択", - "message.display_skin.title": "スキンを表示", - "message.display_skin.message": "コンピュータからスキンファイルを選択するか、プレイヤーIDを入力してください。", + "message.display_skin.title": "スキン", + "message.display_skin.message": "コンピュータからスキンファイルを選択するか、Minecraft IDを入力してください", "message.display_skin.upload": "スキンをアップロード", - "message.display_skin.name": "ユーザー名", + "message.display_skin.name": "MCID", "message.display_skin.reset": "リセット", - "message.invalid_plugin": "無効なプラグインファイルです。コンソールを参照してください。", - "message.load_plugin_app": "このプラグインでPCを変更しますか?信頼できるユーザーのプラグインのみを読み込みます。", - "message.load_plugin_web": "このプラグインをロードしますか?信頼できるユーザーのプラグインのみを読み込みます。", + "message.invalid_plugin": "無効なプラグインファイルです。コンソールを参照してください", + "message.load_plugin_app": "このプラグインでPCを変更しますか?信頼できるユーザーのプラグインのみを読み込みます", + "message.load_plugin_web": "このプラグインをロードしますか?信頼できるユーザーのプラグインのみを読み込みます", "message.preset_no_info": "プリセットにはこのスロットの情報が含まれていません", "message.restart_to_update": "Blockbenchを再起動し、変更を適用します", "message.save_file": "%0として保存しました", @@ -117,7 +117,7 @@ "dialog.extrude.opacity": "最小不透明度", "dialog.extrude.scan": "スキャンとインポート", "dialog.display_preset.title": "プリセットの設定", - "dialog.display_preset.message": "保存するスロットを選択してください。", + "dialog.display_preset.message": "保存するスロットを選択してください", "dialog.display_preset.create": "作成する", "dialog.select.title": "選択する", "dialog.select.new": "新しく選択する", @@ -141,7 +141,7 @@ "dialog.plugins.outdated": "新しいバージョンのBlockbenchが必要です", "dialog.plugins.web_only": "ウェブアプリのみ", "dialog.plugins.app_only": "デスクトップアプリのみ", - "dialog.plugins.author": "%0から", + "dialog.plugins.author": "%0", "dialog.plugins.show_less": "より少なく表示する", "dialog.entitylist.title": "エンティティモデルを開ける", "dialog.entitylist.text": "インポートするモデルを選択してください", @@ -149,7 +149,7 @@ "dialog.entitylist.cubes": "キューブ", "dialog.create_texture.folder": "フォルダ", "dialog.create_texture.template": "テンプレート", - "dialog.create_texture.resolution": "Resolution", + "dialog.create_texture.resolution": "解像度", "dialog.input.title": "入力", "dialog.update.title": "アップデート", "dialog.update.refresh": "リトライ", @@ -202,67 +202,67 @@ "settings.category.dialogs": "ダイアログ", "settings.category.export": "エクスポート", "settings.language": "言語", - "settings.language.desc": "インターフェイス言語。Blockbenchを再起動して変更を適用します。", + "settings.language.desc": "言語を変更します。Blockbenchを再起動して変更を適用します", "settings.show_actions": "アクションの表示", "settings.show_actions.desc": "ステータスバーにすべてのアクションを表示する", "settings.backup_interval": "バックアップ間隔", - "settings.backup_interval.desc": "自動バックアップの間隔(分)", + "settings.backup_interval.desc": "自動バックアップの間隔を設定します-分-", "settings.origin_size": "回転軸", - "settings.origin_size.desc": "回転軸のサイズ", - "settings.control_size": "軸制御サイズ", - "settings.control_size.desc": "軸3種の制御ツールのサイズ", + "settings.origin_size.desc": "回転軸のサイズを設定します", + "settings.control_size": "軸制御", + "settings.control_size.desc": "軸制御ツールのサイズを設定します", "settings.display_skin": "スキンを表示", "settings.display_skin.desc": "ディスプレイ参照プレイヤーモデルに使用されるスキン", "settings.shading": "シェーディング", - "settings.shading.desc": "シェーディングを有効にする", - "settings.texture_fps": "アニメーションテクスチャのFPS", - "settings.texture_fps.desc": "アニメーションテクスチャのフレーム/秒", + "settings.shading.desc": "シェーディングを有効にします", + "settings.texture_fps": "アニメーションテクスチャFPS", + "settings.texture_fps.desc": "アニメーションテクスチャのフレームレートを設定します", "settings.base_grid": "スモールグリッド", - "settings.base_grid.desc": "スモールグリッドと軸を表示する", + "settings.base_grid.desc": "スモールグリッドと軸を表示します", "settings.large_grid": "ラージグリッド", - "settings.large_grid.desc": "3×3のブロックグリッドを表示", + "settings.large_grid.desc": "3×3のブロックグリッドを表示します", "settings.full_grid": "フルラージグリッド", - "settings.full_grid.desc": "3×3の正確なグリッドを表示", + "settings.full_grid.desc": "3×3の正確なグリッドを表示します", "settings.large_box": "ラージボックス", - "settings.large_box.desc": "3×3のブロック境界を表示する", + "settings.large_box.desc": "3×3のブロック境界を表示します", "settings.display_grid": "ディスプレイモード", - "settings.display_grid.desc": "表示モードでグリッドを表示する", + "settings.display_grid.desc": "ディスプレイモードでグリッドを表示します", "settings.undo_limit": "巻き戻し制限", - "settings.undo_limit.desc": "巻き戻すステップ数", - "settings.local_move": "相対軸上を移動する", - "settings.local_move.desc": "回転した要素を独自の軸上で移動する", - "settings.canvas_unselect": "キャンバスをクリックして取り消す", - "settings.canvas_unselect.desc": "背景をクリックすると、すべての要素の選択が解除されるようにする", - "settings.paint_side_restrict": "ブラシを横に制限する", - "settings.paint_side_restrict.desc": "ブラシを現在の面のみにペイントするように制限する", + "settings.undo_limit.desc": "巻き戻せるステップの最大数を設定します", + "settings.local_move": "相対軸上を移動", + "settings.local_move.desc": "回転した要素を独自の軸上で移動します", + "settings.canvas_unselect": "キャンパスクリアー", + "settings.canvas_unselect.desc": "背景をクリックすると、すべての要素の選択が解除されるようにします", + "settings.paint_side_restrict": "ブラシ制限", + "settings.paint_side_restrict.desc": "ブラシを現在の面のみにペイントするように制限します", "settings.autouv": "自動UV", - "settings.autouv.desc": "デフォルトで自動UVを有効にする", - "settings.create_rename": "新しいキューブの名前を変更する", + "settings.autouv.desc": "自動UVを有効にします", + "settings.create_rename": "新しいキューブの名前を変更", "settings.create_rename.desc": "新しいキューブまたはグループを作成するときのフォーカス名", "settings.edit_size": "グリッド間隔幅", - "settings.edit_size.desc": "キューブがスナップするグリッドの間隔を変更する", - "settings.shift_size": "シフト間隔幅", - "settings.shift_size.desc": "シフトを押した時のグリッドの間隔を変更する", - "settings.ctrl_size": "Ctrl間隔幅", - "settings.ctrl_size.desc": "Ctrlを押した時のグリッドの間隔を変更する", + "settings.edit_size.desc": "キューブがスナップするグリッド間隔を変更します", + "settings.shift_size": "[shift]間隔幅", + "settings.shift_size.desc": "shiftキーのグリッド間隔を変更します", + "settings.ctrl_size": "[ctrl]間隔幅", + "settings.ctrl_size.desc": "controlキーのグリッドの間隔を変更します", "settings.negative_size": "マイナス値", - "settings.negative_size.desc": "サイズ変更ツールで、マイナス値を使用する", + "settings.negative_size.desc": "サイズ変更ツールでマイナス値を使用します", "settings.dialog_unsaved_textures": "未保存テクスチャ", - "settings.dialog_unsaved_textures.desc": "「未保存テクスチャ」のダイアログを表示する", + "settings.dialog_unsaved_textures.desc": "「未保存テクスチャ」のダイアログを表示します", "settings.dialog_larger_cubes": "モデルが大きすぎます", - "settings.dialog_larger_cubes.desc": "「モデルが大きすぎます」のダイアログを表示する", + "settings.dialog_larger_cubes.desc": "「モデルが大きすぎます」のダイアログを表示します", "settings.dialog_rotation_limit": "回転の限界", - "settings.dialog_rotation_limit.desc": "「回転の限界」のダイアログを表示する", + "settings.dialog_rotation_limit.desc": "「回転の限界」のダイアログを表示します", "settings.minifiedout": "エクスポートの縮小", "settings.minifiedout.desc": "JSONファイルを1行に書き込む", "settings.export_groups": "グループのエクスポート", - "settings.export_groups.desc": "グループをブロックモデルファイルに保存する", + "settings.export_groups.desc": "グループをブロックモデルファイルに保存します", "settings.credit": "クレジットコメント", "settings.credit.desc": "エクスポートされたファイルに信用できるコメントを追加する", "settings.default_path": "デフォルトパス", "settings.default_path.desc": "Blockbenchがデフォルトのテクスチャをロードするフォルダ", - "settings.image_editor": "エディターの画像", - "settings.image_editor.desc": "テクスチャを編集するデフォルト画像", + "settings.image_editor": "画像エディター", + "settings.image_editor.desc": "テクスチャを編集するエディター", "category.navigate": "ナビゲーション", "category.tools": "ツール", "category.file": "ファイル", @@ -316,7 +316,7 @@ "action.add_model.desc": "ファイルから現在のモデルに追加する", "action.extrude_texture": "テクスチャを押し出し", "action.extrude_texture.desc": "テクスチャを引き延ばしてモデルを作成する", - "action.export_blockmodel": "Blockmodelとしてエクスポート", + "action.export_blockmodel": ".jsonとしてエクスポート", "action.export_blockmodel.desc": "Minecraftブロックまたはアイテムモデルをエクスポートする", "action.export_optifine_part": "Optifine JPMとしてエクスポート", "action.export_optifine_part.desc": "OptiFine エンティティパーツのエクスポート", @@ -370,7 +370,7 @@ "action.select_window.desc": "そのプロパティに基づいてキューブを検索して選択する", "action.invert_selection": "選択範囲を反転", "action.invert_selection.desc": "現在のキューブの選択を反転する", - "action.select_all": "Select All", + "action.select_all": "全てを選択", "action.select_all.desc": "すべてのキューブを選択", "action.collapse_groups": "Collapse Groups", "action.collapse_groups.desc": "すべてのグループを折りたたむ", @@ -380,7 +380,7 @@ "action.center_all.desc": "キューブの中心を回転軸にする", "action.toggle_visibility": "可視化", "action.toggle_visibility.desc": "選択したキューブの表示を切り替えます", - "action.toggle_export": "エキスポート", + "action.toggle_export": "エクスポート", "action.toggle_export.desc": "選択したキューブのエクスポート設定を切り替えます", "action.toggle_autouv": "オートUV", "action.toggle_autouv.desc": "選択したキューブの自動UV設定を切り替えます", @@ -472,7 +472,7 @@ "menu.preview.fullview": "Full View", "menu.preview.stop_drag": "Stop Background Positioing", "menu.uv.mapping": "UVマッピング", - "menu.uv.mapping.export": "Export", + "menu.uv.mapping.export": "エクスポート", "menu.uv.mapping.rotation": "Rotation", "menu.uv.mapping.mirror_x": "Mirror X", "menu.uv.mapping.mirror_y": "Mirror Y", @@ -677,7 +677,7 @@ "panel.variable_placeholders.info": "プレビューする変数を 名前 = 値で表示する", "status_bar.vertex_distance": "間隔:%0", "dialog.create_gif.title": "GIF", - "dialog.create_gif.length": "長さ(秒)", + "dialog.create_gif.length": "長さ-秒-", "dialog.create_gif.fps": "FPS", "dialog.create_gif.compression": "圧縮率", "dialog.create_gif.play": "アニメーションを再生", @@ -692,7 +692,7 @@ "action.export_class_entity": "Java Entityをエクスポート", "action.export_class_entity.desc": "エンティティモデルをjava としてエクスポートする", "settings.seethrough_outline": "X-Rey アウトライン", - "settings.seethrough_outline.desc": "オブジェクトを通してアウトラインを表示する", + "settings.seethrough_outline.desc": "オブジェクトを通してアウトラインを表示します", "mode.edit": "Edit", "mode.paint": "Paint", "mode.display": "Display", @@ -700,7 +700,7 @@ "status_bar.recording_gif": "GIFの録音", "status_bar.processing_gif": "GIFの加工処理", "settings.backup_retain": "バックアップ保持期間", - "settings.backup_retain.desc": "Blockbenchがバックアップデーターを保持する期間を設定します", + "settings.backup_retain.desc": "Blockbenchがバックアップデーターを保持する期間を設定します-日-", "action.rotate_tool": "Rotate", "action.rotate_tool.desc": "選択中の要素を回転させることができます", "action.fill_tool": "Paint Bucket", @@ -715,7 +715,7 @@ "language_name": "英語", "message.plugin_reload": "%0プラグインをリロードしました", "settings.brightness": "輝度", - "settings.brightness.desc": "プレビューの明るさ設定(初期値50)", + "settings.brightness.desc": "プレビューの明るさ設定-初期値50-", "menu.preview.perspective.reset": "カメラをリセット", "action.fill_mode": "Fill Mode", "action.fill_mode.face": "Face", @@ -753,13 +753,13 @@ "dialog.sketchfab_uploader.description": "説明", "dialog.sketchfab_uploader.tags": "Tag", "settings.sketchfab_token": "Sketchfab Token", - "settings.sketchfab_token.desc": "BlockbenchにSketchfabアカウントへのアップロードを許可する", + "settings.sketchfab_token.desc": "BlockbenchにSketchfabアカウントへのアップロードを許可します", "panel.color": "Color", "data.origin": "原点", "message.sketchfab.success": "モデルのアップロードに成功", "message.sketchfab.error": "Sketchfab:モデルアップロードに失敗しました", - "settings.outliner_colors": "Outliner Colors", - "settings.outliner_colors.desc": "Outliner にキューブカラーを表示します", + "settings.outliner_colors": "オートラインカラー", + "settings.outliner_colors.desc": "オートライナーにキューブカラーを表示します", "action.upload_sketchfab.desc": "Sketchfab にモデルをアップロード", "action.element_colors": "Cube Colors", "action.element_colors.desc": "Outliner でキューブカラーを表示します", @@ -775,24 +775,24 @@ "dialog.create_texture.power": "二乗サイズ", "dialog.create_gif.turn": "ターンテーブルスピード", "action.edit_session": "セッション…", - "action.edit_session.desc": "他のクリエイターとセッションを通して共同作業が出来ます", + "action.edit_session.desc": "他のクリエイターとセッションを通して共同制作が出来ます", "action.reset_keyframe": "Reset Keyframe", "action.reset_keyframe.desc": "キー設定をすべてリセットします", "dialog.edit_session.title": "セッションを編集", "edit_session.username": "ユーザーネーム", "edit_session.token": "Token", - "edit_session.about": "セッションは、モデルを共同作業するために使用できます。セッションを作成してTokenを友達に送信し、友達はそれを使って参加することができます。", - "edit_session.join": "セッションに参加する", + "edit_session.about": "セッションは、モデルを共同制作できます。セッションを作成してTokenを友達に送信し、友達はそれを使って参加することができます。", + "edit_session.join": "セッションに参加", "edit_session.create": "セッションを作る", "edit_session.quit": "セッションをやめる", "edit_session.joined": "%0 に参加しました", "edit_session.left": "%0 から退出しました", - "edit_session.quit_session": "セッションから退出する", + "edit_session.quit_session": "セッションから退出", "edit_session.status": "ステータス", "edit_session.hosting": "ハウジング", "edit_session.connected": "セッションに接続する", - "dialog.sketchfab_uploader.private": "プライベート", - "dialog.sketchfab_uploader.password": "パスワード", + "dialog.sketchfab_uploader.private": "プライベート-Pro", + "dialog.sketchfab_uploader.password": "パスワード-Pro", "action.toggle_chat": "Toggle Chat", "action.toggle_chat.desc": "チャット履歴の表示をします", "action.uv_select_all": "Select All", @@ -814,7 +814,7 @@ "format.free": "Free Model", "format.free.desc": "スタンダードモデリング", "format.java_block": "Java block/item", - "format.java_block.desc": "Java Editionモデリング (サイズと回転は限られています)", + "format.java_block.desc": "Java Editionモデリング-サイズと回転は限られています", "format.bedrock": "Bedrock Model", "format.bedrock.desc": "統合版モデリング", "format.bedrock_old": "Bedrock Legacy Model", @@ -824,7 +824,7 @@ "format.optifine_entity": "OptiFine Entity", "format.optifine_entity.desc": "OptiFine カスタムエンティティモデリング", "keys.mouse": "マウス %0", - "message.cleared_blank_faces.title": "空白の面", + "message.cleared_blank_faces.title": "ブランク", "message.cleared_blank_faces.message": "%0個のテクスチャがない面を発見しました。それらをすべて削除しますか?", "message.wireframe.enabled": "ワイヤーフレームを有効にしました", "message.wireframe.disabled": "ワイヤーフレームを無効にしました", @@ -841,7 +841,7 @@ "settings.username": "ニックネーム", "settings.username.desc": "セッション用のニックネームを編集", "settings.painting_grid": "ペイントグリット", - "settings.painting_grid.desc": "キューブ上にグリットを表示する", + "settings.painting_grid.desc": "キューブ上にグリットを表示します", "action.slider_brush_min_opacity": "最小不透明度", "action.slider_brush_min_opacity.desc": "ブラシの最小不透明度", "action.convert_project": "プロジェクトを変換", @@ -872,7 +872,7 @@ "display.reference.crossbow": "クロスボウ", "dialog.settings.search_results": "検索", "settings.animation_snap": "アニメーションスナップ", - "settings.animation_snap.desc": "アニメーションライン1ステップの間隔幅", + "settings.animation_snap.desc": "アニメーションライン1ステップの間隔幅を設定します", "action.import_optifine_part": "OptiFine Part をインポート", "action.import_optifine_part.desc": "OptiFine エンティティモデルをインポートします", "data.locator": "ロケーター", @@ -886,22 +886,22 @@ "message.canvas_limit_error.message": "フォーマットによってキャンバスが48単位に制限されているため、アクションを正しく実行できませんでした。", "data.effect": "エフェクト", "generic.name": "名前", - "settings.recent_projects": "Recent Model Cap", + "settings.recent_projects": "最近のモデル", "settings.recent_projects.desc": "最近開いたモデルの最大数", "settings.volume": "ボリューム", - "settings.volume.desc": "アニメーションエフェクトを調整する", + "settings.volume.desc": "アニメーションのエフェクトを設定します", "action.change_keyframe_file": "ファイルを選択", "action.change_keyframe_file.desc": "オーディオファイルを選択して、効果音を視聴します", "action.clear_timeline": "タイムラインをクリアー", "action.clear_timeline.desc": "タイムライン上の未設定の骨格を削除する", "action.select_effect_animator": "アニメーションエフェクト", "action.select_effect_animator.desc": "タイムラインを開いてサウンドとエフェクトを追加します", - "action.timeline_focus": "Channel", + "action.timeline_focus": "チャンネル", "action.timeline_focus.desc": "タイムラインに表示するアニメーションチャンネルを選択します", "action.timeline_focus.all": "すべて", - "timeline.particle": "Particle", - "timeline.sound": "Sound", - "timeline.effects": "Effects", + "timeline.particle": "パーティクル", + "timeline.sound": "サウンド", + "timeline.effects": "エフェクト", "data.format": "フォーマット", "format.optifine_part": "OptiFine Part", "format.optifine_part.desc": "OptiFine エンティティパーツモデリング", @@ -919,84 +919,109 @@ "action.slider_origin": "Pivot %0", "action.slider_origin.desc": "%0軸上でピポットする", "action.rotate_cw": "Rotate %0 +90", - "action.rotate_cw.desc": "%0軸上で90°回転する", + "action.rotate_cw.desc": "%0軸上で90°回転します", "action.rotate_ccw": "Rotate %0 -90", - "action.rotate_ccw.desc": "%0軸上で-90°回転する", + "action.rotate_ccw.desc": "%0軸上で-90°回転します", "action.flip": "Flip %0", - "action.flip.desc": "%0軸上でフィリップする", + "action.flip.desc": "%0軸上でフィリップします", "action.center": "Center %0", - "action.center.desc": "Center the selected cubes on the %0 axis", + "action.center.desc": "選択したキューブを%0軸の中央に配置します", "action.bring_up_all_animations": "変更されたすべてのアニメーターをタイムラインに組み込みます", "panel.bone": "Bone", - "data.color": "Color", - "generic.export": "Export", - "generic.none": "None", - "status_bar.recording": "Recording Timelapse", - "message.add_to_palette": "Added to palette", - "message.size_modifiers": "Hold down Ctrl or Shift to transform in smaller increments.", - "message.checkerboard.enabled": "Checkerboard enabled", - "message.checkerboard.disabled": "Checkerboard disabled", - "message.timelapse_start": "Timelapse started", - "message.timelapse_stop": "Timelapse stopped", - "message.import_palette.replace_palette": "Replace old palette", - "message.import_palette.threshold": "Merge Threshold", - "dialog.timelapse.interval": "Interval (Seconds)", - "dialog.timelapse.source": "Source", - "dialog.timelapse.source.interface": "Interface", - "dialog.timelapse.source.locked": "Locked Angle", - "dialog.timelapse.destination": "Destination Folder", - "layout.color.checkerboard": "Checkerboard", - "layout.color.checkerboard.desc": "Background of canvas and UV editor", - "layout.font.code": "Code Font", - "layout.css": "Custom CSS", - "settings.category.paint": "Paint", - "settings.deactivate_size_limit": "Deactivate Size Limit", - "settings.deactivate_size_limit.desc": "Deactivate the size limit for specific model formats. WARNING: This can cause invalid models.", - "settings.brush_opacity_modifier": "Brush Opacity Modifier", - "settings.brush_opacity_modifier.desc": "Modify the brush opacity when using a stylus", - "settings.brush_size_modifier": "Brush Size Modifier", - "settings.brush_size_modifier.desc": "Modify the brush size when using a stylus", - "settings.brush_modifier.pressure": "Pressure", - "settings.brush_modifier.tilt": "Tilt", - "settings.class_export_version": "Modded Entity Export Version", - "settings.class_export_version.desc": "The format version for modded entity models", - "category.color": "Color", - "action.import_theme": "Import Theme", - "action.export_theme": "Export Theme", - "action.export_theme.desc": "Create a theme file based on the current settings", - "action.reset_theme": "Reset Theme", - "action.reset_theme.desc": "Reset to the default Blockbench theme", - "action.slider_color_h": "Hue", - "action.slider_color_s": "Saturation", - "action.slider_color_v": "Value", - "action.add_to_palette": "Add To Palette", - "action.add_to_palette.desc": "Add the selected color to the color palette", - "action.import_palette": "Import Palette", - "action.import_palette.desc": "Import a .bbpalette file", - "action.export_palette": "Export Palette", - "action.export_palette.desc": "Export palette as a .bbpalette file", - "action.generate_palette": "Generate Palette", - "action.generate_palette.desc": "Generate palette from a texture", - "action.sort_palette": "Sort Palette", - "action.sort_palette.desc": "Sort all colors on the palette by color and brightness", - "action.clear_palette": "Clear Palette", - "action.clear_palette.desc": "Remove all colors from the palette", - "action.toggle_checkerboard": "Toggle Checkerboard", - "action.toggle_checkerboard.desc": "Toggle the checkerboard background behind the preview or UV editor", - "action.timelapse": "Timelapse...", - "action.timelapse.desc": "Record a timelapse of your modeling process", - "action.add_keyframe": "Add Keyframe", - "action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values", - "action.bring_up_all_animations.desc": "Brings all modified animators into the timeline", - "timeline.timeline": "Instructions", - "menu.palette.load": "Load Palette", - "menu.palette.load.default": "Default", - "panel.color.picker": "Picker", - "panel.color.palette": "Palette", - "generic.import": "Import", - "settings.brush_modifier.none": "None", - "action.export_entity": "Export Bedrock Entity", - "action.export_entity.desc": "Add the current model as an entity to a mobs.json file", - "settings.highlight_cubes": "Highlight Cubes", - "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them" + "data.color": "カラー", + "generic.export": "エクスポート", + "generic.none": "なし", + "status_bar.recording": "タイムラプスを記録中…", + "message.add_to_palette": "パレットを追加", + "message.size_modifiers": "Shiftを押したままにすると、少しずつ変化します。", + "message.checkerboard.enabled": "チェッカーボードを有効", + "message.checkerboard.disabled": "チェッカーボードを無効", + "message.timelapse_start": "スタート", + "message.timelapse_stop": "ストップ", + "message.import_palette.replace_palette": "古いパレットを置き換えます", + "message.import_palette.threshold": "マージ", + "dialog.timelapse.interval": "インターバル-秒-", + "dialog.timelapse.source": "ソース", + "dialog.timelapse.source.interface": "インターフェース", + "dialog.timelapse.source.locked": "アングルを固定", + "dialog.timelapse.destination": "移動先のフォルダ", + "layout.color.checkerboard": "チェッカーボード", + "layout.color.checkerboard.desc": "キャンパスの背景とUVエディター", + "layout.font.code": "コードフォント", + "layout.css": "カスタム CSS", + "settings.category.paint": "ペイント", + "settings.deactivate_size_limit": "サイズ制限の削除", + "settings.deactivate_size_limit.desc": "モデルの最大サイズ制限を削除します", + "settings.brush_opacity_modifier": "ブラシ不透明度", + "settings.brush_opacity_modifier.desc": "ブラシの不透明度を変更します", + "settings.brush_size_modifier": "ブラシサイズ", + "settings.brush_size_modifier.desc": "ブラシの大きさを変更します", + "settings.brush_modifier.pressure": "筆圧", + "settings.brush_modifier.tilt": "チルト", + "settings.class_export_version": "エンティティエクスポートバージョン", + "settings.class_export_version.desc": "modエンティティモデルのバージョンを変更します", + "category.color": "カラー", + "action.import_theme": "テーマをインポート", + "action.export_theme": "テーマをエクスポート", + "action.export_theme.desc": "現在の設定に基づいてテーマファイルを作成します", + "action.reset_theme": "テーマをリセット", + "action.reset_theme.desc": "テーマをデフォルトに変更します", + "action.slider_color_h": "色相", + "action.slider_color_s": "彩度", + "action.slider_color_v": "値", + "action.add_to_palette": "パレットに追加", + "action.add_to_palette.desc": "パレットに選択したカラーを追加します", + "action.import_palette": "パレットをインポート", + "action.import_palette.desc": ".bbpalette をインポートします", + "action.export_palette": "パレットをエクスポート", + "action.export_palette.desc": ".bbpalette をエクスポートします", + "action.generate_palette": "パレットを生成", + "action.generate_palette.desc": "テクスチャからパレットを生成します", + "action.sort_palette": "ソート", + "action.sort_palette.desc": "パレット上のすべてのカラーを色と明るさで並べ替えます", + "action.clear_palette": "クリアー", + "action.clear_palette.desc": "パレット上のすべてのカラーを削除します", + "action.toggle_checkerboard": "チェッカーボードを固定", + "action.toggle_checkerboard.desc": "プレビューまたはUVエディターのチェッカーボードの背景を切り替えます", + "action.timelapse": "タイムラプス…", + "action.timelapse.desc": "モデリングプロセスのタイムラプスを記録します", + "action.add_keyframe": "キーフレームを追加", + "action.add_keyframe.desc": "キーフレームを自動的に追加します。 Shiftキーを押してデフォルト値を表示します", + "action.bring_up_all_animations.desc": "変更されたすべてのアニメーターをタイムラインに取り込みます", + "timeline.timeline": "取扱説明書", + "menu.palette.load": "パレットをロード", + "menu.palette.load.default": "デフォルト", + "panel.color.picker": "スポイト", + "panel.color.palette": "パレット", + "generic.import": "インポート", + "settings.brush_modifier.none": "なし", + "action.export_entity": "統合版Entityをエクスポート", + "action.export_entity.desc": "現在のモデルをエンティティとしてmobs.jsonファイルに追加します", + "settings.highlight_cubes": "ハイライトキューブ", + "settings.highlight_cubes.desc": "キューブにカーソルを合わせるか、選択するとキューブが強調表示します", + "action.add_marker": "マーカー", + "action.add_marker.desc": "タイムラインマーカーを設定します", + "timeline.pre_effect_script": "Script", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/nl.json b/lang/nl.json index 6478a97f0..039a0b971 100644 --- a/lang/nl.json +++ b/lang/nl.json @@ -998,5 +998,30 @@ "action.export_entity": "Exporteer Bedrock Entity", "action.export_entity.desc": "Voeg het huidige model als een enitity toe aan een mobs.json bestand", "settings.highlight_cubes": "Markeer Kubussen", - "settings.highlight_cubes.desc": "Markeer kubussen waneer je over ze heen beweegt of ze selecteert" + "settings.highlight_cubes.desc": "Markeer kubussen waneer je over ze heen beweegt of ze selecteert", + "action.add_marker": "Set Marker", + "action.add_marker.desc": "Set a timeline marker", + "timeline.pre_effect_script": "Script", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/pl.json b/lang/pl.json index d439d6a03..bd473cc22 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -998,5 +998,30 @@ "action.export_entity": "Export Bedrock Entity", "action.export_entity.desc": "Add the current model as an entity to a mobs.json file", "settings.highlight_cubes": "Highlight Cubes", - "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them" + "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them", + "action.add_marker": "Set Marker", + "action.add_marker.desc": "Set a timeline marker", + "timeline.pre_effect_script": "Script", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/pt.json b/lang/pt.json index a1b859764..0472c34fe 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -799,204 +799,229 @@ "action.uv_select_all.desc": "Seleciona todas as faces no diálogo de UV", "panel.chat": "Bate-papo", "edit_session.welcome": "Bem vindo à essa sessão de %0", - "dialog.yes": "Yes", - "dialog.no": "No", - "generic.remove": "Remove", + "dialog.yes": "Sim", + "dialog.no": "Não", + "generic.remove": "Remover", "generic.download": "Download", - "generic.search": "Search", - "dates.today": "Today", - "dates.yesterday": "Yesterday", - "dates.this_week": "This Week", - "dates.weeks_ago": "%0 weeks ago", - "mode.start": "Start", - "mode.start.new": "New", - "mode.start.recent": "Recent", - "format.free": "Free Model", - "format.free.desc": "Model without restrictions for Unity etc.", - "format.java_block": "Java Block/Item", - "format.java_block.desc": "Block model for Java Edition. Size and rotations are limited.", - "format.bedrock": "Bedrock Model", - "format.bedrock.desc": "Model for Bedrock Edition", - "format.bedrock_old": "Bedrock Legacy Model", - "format.bedrock_old.desc": "Pre-1.12 Bedrock Edition entity model", - "format.modded_entity": "Modded Entity", - "format.modded_entity.desc": "Entity model for mods. Can be exported as .java class files.", - "format.optifine_entity": "OptiFine Entity", - "format.optifine_entity.desc": "Custom entity model for OptiFine", - "keys.mouse": "Mouse Button %0", - "message.cleared_blank_faces.title": "Blank Faces", - "message.cleared_blank_faces.message": "Blockbench has found %0 cubes without any texture. Do you want to remove those elements?", - "message.wireframe.enabled": "Wireframe view enabled", - "message.wireframe.disabled": "Wireframe view disabled", - "dialog.project.box_uv": "Box UV", - "dialog.convert_project.title": "Convert Project", - "dialog.convert_project.text": "Are you sure you want to convert this project? You cannot undo this step.", - "dialog.create_texture.double_use": "Keep Multi Texture Occupancy", - "dialog.model_stats.title": "Model Stats", - "dialog.model_stats.cubes": "Cubes", - "dialog.model_stats.locators": "Locators", - "dialog.model_stats.groups": "Groups", - "dialog.model_stats.vertices": "Vertices", + "generic.search": "Pesquisa", + "dates.today": "Hoje", + "dates.yesterday": "Ontem", + "dates.this_week": "Esta semana", + "dates.weeks_ago": "%0 semanas atrás", + "mode.start": "Iniciar", + "mode.start.new": "Novo", + "mode.start.recent": "Recente", + "format.free": "Modelo Livre", + "format.free.desc": "Modelo sem restrições para Unity etc.", + "format.java_block": "Bloco/Item Java", + "format.java_block.desc": "Modelo de Bloco para a Edição Java. Tamanho e rotações, limitados.", + "format.bedrock": "Modelo Bedrock", + "format.bedrock.desc": "Modelo para a Bedrock Edition.", + "format.bedrock_old": "Modelo de Legado Bedrock Edition", + "format.bedrock_old.desc": "Modelo de entidade da versão anterior à Bedrock Edition.", + "format.modded_entity": "Entidade Modificada", + "format.modded_entity.desc": "Modelos de entidade para mods. Pode ser exportado como arquivos .java class.", + "format.optifine_entity": "Entidade OptiFine", + "format.optifine_entity.desc": "Modelo customizado de entidade para OptiFine.", + "keys.mouse": "Botão do Mouse %0", + "message.cleared_blank_faces.title": "Faces em branco", + "message.cleared_blank_faces.message": "O Blockbench encontrou %0 cubos sem nenhuma textura. Deseja remover esses elementos?", + "message.wireframe.enabled": "Visualização de estrutura de arame ativada", + "message.wireframe.disabled": "Visualização de estrutura de arame desativada", + "dialog.project.box_uv": "Caixa UV", + "dialog.convert_project.title": "Converter Projeto", + "dialog.convert_project.text": "Tem certeza de que deseja converter este projeto? Você não pode desfazer esta etapa.", + "dialog.create_texture.double_use": "Manter ocupação de textura múltipla", + "dialog.model_stats.title": "Status do Modelo", + "dialog.model_stats.cubes": "Cubos", + "dialog.model_stats.locators": "Localizadores", + "dialog.model_stats.groups": "Grupos", + "dialog.model_stats.vertices": "Vértices", "dialog.model_stats.faces": "Faces", - "settings.username": "Username", - "settings.username.desc": "Username for edit sessions", - "settings.painting_grid": "Painting Grid", - "settings.painting_grid.desc": "Show grid on textured cubes in paint mode", - "action.slider_brush_min_opacity": "Minimum Opacity", - "action.slider_brush_min_opacity.desc": "Minimum opacity of the noise brush in percent", - "action.convert_project": "Convert Project", - "action.convert_project.desc": "Converts the current project to a project for another model format", - "action.close_project": "Close Project", - "action.close_project.desc": "Closes the currently open project", - "action.export_bedrock": "Export Bedrock Geometry", - "action.export_bedrock.desc": "Export the model as a bedrock edition geometry file.", - "action.save_project": "Save Project", - "action.save_project.desc": "Saves the current model as a project file", - "action.save_project_as": "Save Project As", - "action.save_project_as.desc": "Saves the current model as a project file at a new location", - "action.export_over": "Overwrite Model", - "action.export_over.desc": "Saves the model, textures and animations by overwriting the files", - "action.add_locator": "Add Locator", - "action.add_locator.desc": "Adds a new locator to control positions of particles, leashes etc", - "action.sidebar_left": "Textures and UV", - "action.sidebar_left.desc": "Open the interface for UV and textures", - "action.sidebar_right": "Elements", - "action.sidebar_right.desc": "Open the interface to edit elements", - "action.uv_turn_mapping": "Turn Mapping", - "action.uv_turn_mapping.desc": "Turn the UV mapping around 90 degrees", - "action.remove_blank_faces": "Remove Blank Faces", - "action.remove_blank_faces.desc": "Deletes all untextured faces of the selection", - "menu.uv.select": "Select Cubes", - "web.download_app": "Download App", - "uv_editor.turned": "Turned Mapping", - "display.reference.crossbow": "Crossbow", - "dialog.settings.search_results": "Search Results", - "settings.animation_snap": "Animation Snap", - "settings.animation_snap.desc": "Snap interval for keyframes in the animation timeline in steps per second", - "action.import_optifine_part": "Import OptiFine Part", - "action.import_optifine_part.desc": "Import an entity part model for OptiFine", - "data.locator": "Locator", - "mode.start.no_recents": "No recently opened models", - "panel.element": "Element", - "panel.element.position": "Position", - "panel.element.size": "Size", - "panel.element.origin": "Pivot Point", - "panel.element.rotation": "Rotation", - "message.canvas_limit_error.title": "Canvas Limit Error", - "message.canvas_limit_error.message": "The action could not be performed correctly because the format limits the canvas to 48 units. Shift the pivot point to prevent this.", - "data.effect": "Effect", - "generic.name": "Name", - "settings.recent_projects": "Recent Model Cap", - "settings.recent_projects.desc": "Maximum number of recent models to remember", + "settings.username": "Nome de Usuário", + "settings.username.desc": "Nome de usuário para sessões de edição.", + "settings.painting_grid": "Grade de pintura", + "settings.painting_grid.desc": "Mostrar grade em cubos texturizados no modo de pintura.", + "action.slider_brush_min_opacity": "Opacidade Minima", + "action.slider_brush_min_opacity.desc": "Opacidade mínima do pincel de ruído em porcentagem.", + "action.convert_project": "Converter Projeto", + "action.convert_project.desc": "Converte o projeto atual em um projeto para outro formato de modelo.", + "action.close_project": "Fechar Projeto", + "action.close_project.desc": "Fecha o projeto aberto atualmente.", + "action.export_bedrock": "Exportar Geometria Bedrock", + "action.export_bedrock.desc": "Exporte o modelo como um arquivo de Geometria Bedrock Edition.", + "action.save_project": "Salvar o projeto", + "action.save_project.desc": "Salva o modelo atual como um arquivo de projeto.", + "action.save_project_as": "Salvar Projeto Como...", + "action.save_project_as.desc": "Salva o modelo atual como um arquivo de projeto em um novo local.", + "action.export_over": "Substituir Modelo", + "action.export_over.desc": "Salva o modelo, texturas e animações substituindo os arquivos.", + "action.add_locator": "Adicionar localizador", + "action.add_locator.desc": "Adiciona um novo localizador para controlar posições de partículas, cordas etc.", + "action.sidebar_left": "Texturas e UV", + "action.sidebar_left.desc": "Abre a interface para UV e texturas.", + "action.sidebar_right": "Elementos", + "action.sidebar_right.desc": "Abre a interface para editar elementos.", + "action.uv_turn_mapping": "Mapeamento de Giros", + "action.uv_turn_mapping.desc": "Gire o mapeamento UV em cerca de 90 graus.", + "action.remove_blank_faces": "Remover faces em branco", + "action.remove_blank_faces.desc": "Exclui todas as faces não texturizadas da seleção.", + "menu.uv.select": "Selecionar Cubos", + "web.download_app": "Baixar aplicativo", + "uv_editor.turned": "Mapeamento ativado", + "display.reference.crossbow": "Besta", + "dialog.settings.search_results": "Procurar Resultados", + "settings.animation_snap": "Snap de animação", + "settings.animation_snap.desc": "Intervalo de snap para quadros-chave na linha do tempo da animação em etapas por segundo.", + "action.import_optifine_part": "Importar parte OptiFine", + "action.import_optifine_part.desc": "Importar uma parte de modelo de entidade para o OptiFine.", + "data.locator": "Localizador", + "mode.start.no_recents": "Nenhum modelo aberto recentemente", + "panel.element": "Elemento", + "panel.element.position": "Posição", + "panel.element.size": "Tamanho", + "panel.element.origin": "Ponto de Pivô", + "panel.element.rotation": "Rotação", + "message.canvas_limit_error.title": "Erro de limite de tela", + "message.canvas_limit_error.message": "A ação não pôde ser executada corretamente porque o formato limita a tela a 48 unidades. Mude o ponto de articulação para evitar isso.", + "data.effect": "Efeito", + "generic.name": "Nome", + "settings.recent_projects": "Limite de modelo recente", + "settings.recent_projects.desc": "Número máximo de modelos recentes a serem lembrados.", "settings.volume": "Volume", - "settings.volume.desc": "Volume control for sound effects in animations", - "action.change_keyframe_file": "Select File", - "action.change_keyframe_file.desc": "Select an audio file to preview a sound effect.", - "action.clear_timeline": "Clear Timeline", - "action.clear_timeline.desc": "Clear all unselected bones from the timeline", - "action.select_effect_animator": "Animate Effects", - "action.select_effect_animator.desc": "Opens timeline to add sound and particle effects", - "action.timeline_focus": "Channel", - "action.timeline_focus.desc": "Select the animation channels to display in the timeline", - "action.timeline_focus.all": "All", - "timeline.particle": "Particle", - "timeline.sound": "Sound", - "timeline.effects": "Effects", - "data.format": "Format", - "format.optifine_part": "OptiFine Part", - "format.optifine_part.desc": "JPM part for OptiFine entity models", - "action.reverse_keyframes": "Reverse Keyframes", - "action.reverse_keyframes.desc": "Reverse the order of the selected keyframes", - "generic.help": "Help", - "message.removed_faces": "Removed %0 faces", - "dialog.sketchfab_uploader.draft": "Draft", - "action.slider_pos": "Move %0", - "action.slider_pos.desc": "Move cubes on the %0 axis", - "action.slider_size": "Size %0", - "action.slider_size.desc": "Resize cubes on the %0 axis", - "action.slider_rotation": "Rotate %0", - "action.slider_rotation.desc": "Rotate cubes on the %0 axis", - "action.slider_origin": "Pivot %0", - "action.slider_origin.desc": "Move pivot on the %0 axis", - "action.rotate_cw": "Rotate %0 +90", - "action.rotate_cw.desc": "Rotate the selected cubes 90° on the %0 axis", - "action.rotate_ccw": "Rotate %0 -90", - "action.rotate_ccw.desc": "Rotate the selected cubes -90° on the %0 axis", - "action.flip": "Flip %0", - "action.flip.desc": "Flip the selected cubes on the %0 axis", - "action.center": "Center %0", - "action.center.desc": "Center the selected cubes on the %0 axis", - "action.bring_up_all_animations": "Bring Up All Animations", - "panel.bone": "Bone", - "data.color": "Color", - "generic.export": "Export", - "generic.none": "None", - "status_bar.recording": "Recording Timelapse", - "message.add_to_palette": "Added to palette", - "message.size_modifiers": "Hold down Ctrl or Shift to transform in smaller increments.", - "message.checkerboard.enabled": "Checkerboard enabled", - "message.checkerboard.disabled": "Checkerboard disabled", - "message.timelapse_start": "Timelapse started", - "message.timelapse_stop": "Timelapse stopped", - "message.import_palette.replace_palette": "Replace old palette", - "message.import_palette.threshold": "Merge Threshold", - "dialog.timelapse.interval": "Interval (Seconds)", - "dialog.timelapse.source": "Source", + "settings.volume.desc": "Controle de volume para efeitos sonoros em animações.", + "action.change_keyframe_file": "Selecionar arquivo", + "action.change_keyframe_file.desc": "Selecione um arquivo de áudio para visualizar um efeito sonoro.", + "action.clear_timeline": "Limpar Linha do Tempo", + "action.clear_timeline.desc": "Limpar todos os ossos não selecionados da linha do tempo.", + "action.select_effect_animator": "Efeitos animados", + "action.select_effect_animator.desc": "Abre a linha do tempo para adicionar sons e efeitos de partículas.", + "action.timeline_focus": "Canal", + "action.timeline_focus.desc": "Selecione os canais de animação para exibir na linha do tempo.", + "action.timeline_focus.all": "Todos", + "timeline.particle": "Partícula", + "timeline.sound": "Som", + "timeline.effects": "Efeitos", + "data.format": "Formato", + "format.optifine_part": "Parte de OptiFine", + "format.optifine_part.desc": "Parte JPM para modelos de entidade OptiFine.", + "action.reverse_keyframes": "Quadros-chave reversos", + "action.reverse_keyframes.desc": "Inverter a ordem dos quadros-chave selecionados.", + "generic.help": "Ajuda", + "message.removed_faces": "%0 faces removidas", + "dialog.sketchfab_uploader.draft": "Esboço", + "action.slider_pos": "Mover %0", + "action.slider_pos.desc": "Mover cubos no eixo %0", + "action.slider_size": "Tamanho %0", + "action.slider_size.desc": "Redimensionar cubos no eixo %0.", + "action.slider_rotation": "Rodar %0", + "action.slider_rotation.desc": "Girar cubos no eixo %0", + "action.slider_origin": "Pivô %0", + "action.slider_origin.desc": "Mover o pivô no eixo %0", + "action.rotate_cw": "Girar %0 +90", + "action.rotate_cw.desc": "Gira os cubos selecionados 90 ° no eixo %0", + "action.rotate_ccw": "Rodar %0 -90", + "action.rotate_ccw.desc": "Gira os cubos selecionados -90° no eixo %0", + "action.flip": "Virar %0", + "action.flip.desc": "Vire os cubos selecionados no eixo %0", + "action.center": "Centro %0", + "action.center.desc": "Centralize os cubos selecionados no eixo %0", + "action.bring_up_all_animations": "Trazer todas as animações", + "panel.bone": "Osso", + "data.color": "Cor", + "generic.export": "Exportar", + "generic.none": "Nenhum", + "status_bar.recording": "Linha do Tempo de gravação", + "message.add_to_palette": "Adicionado à paleta", + "message.size_modifiers": "Mantenha pressionada a tecla Ctrl ou Shift para transformar em incrementos menores.", + "message.checkerboard.enabled": "Checkerboard ativado", + "message.checkerboard.disabled": "Checkerboard desativado", + "message.timelapse_start": "Timelapse iniciado", + "message.timelapse_stop": "Timelapse parado", + "message.import_palette.replace_palette": "Substituir paleta antiga", + "message.import_palette.threshold": "Limiar de mesclagem", + "dialog.timelapse.interval": "Intervalo (Segundos)", + "dialog.timelapse.source": "Fonte", "dialog.timelapse.source.interface": "Interface", - "dialog.timelapse.source.locked": "Locked Angle", - "dialog.timelapse.destination": "Destination Folder", + "dialog.timelapse.source.locked": "Ângulo bloqueado", + "dialog.timelapse.destination": "Pasta de destino", "layout.color.checkerboard": "Checkerboard", - "layout.color.checkerboard.desc": "Background of canvas and UV editor", - "layout.font.code": "Code Font", - "layout.css": "Custom CSS", - "settings.category.paint": "Paint", - "settings.deactivate_size_limit": "Deactivate Size Limit", - "settings.deactivate_size_limit.desc": "Deactivate the size limit for specific model formats. WARNING: This can cause invalid models.", - "settings.brush_opacity_modifier": "Brush Opacity Modifier", - "settings.brush_opacity_modifier.desc": "Modify the brush opacity when using a stylus", - "settings.brush_size_modifier": "Brush Size Modifier", - "settings.brush_size_modifier.desc": "Modify the brush size when using a stylus", - "settings.brush_modifier.pressure": "Pressure", - "settings.brush_modifier.tilt": "Tilt", - "settings.class_export_version": "Modded Entity Export Version", - "settings.class_export_version.desc": "The format version for modded entity models", - "category.color": "Color", - "action.import_theme": "Import Theme", - "action.export_theme": "Export Theme", - "action.export_theme.desc": "Create a theme file based on the current settings", - "action.reset_theme": "Reset Theme", - "action.reset_theme.desc": "Reset to the default Blockbench theme", - "action.slider_color_h": "Hue", - "action.slider_color_s": "Saturation", + "layout.color.checkerboard.desc": "Fundo de tela e editor UV", + "layout.font.code": "Código da fonte", + "layout.css": "CSS customizado", + "settings.category.paint": "Pintar", + "settings.deactivate_size_limit": "Desativar limite de tamanho", + "settings.deactivate_size_limit.desc": "Desative o limite de tamanho para formatos de modelo específicos. AVISO: Isso pode causar modelos inválidos.", + "settings.brush_opacity_modifier": "Modificador de opacidade do pincel", + "settings.brush_opacity_modifier.desc": "Modifique a opacidade do pincel ao usar uma caneta", + "settings.brush_size_modifier": "Modificador de tamanho de pincel", + "settings.brush_size_modifier.desc": "Modifique o tamanho do pincel ao usar uma caneta", + "settings.brush_modifier.pressure": "Pressão", + "settings.brush_modifier.tilt": "Inclinar", + "settings.class_export_version": "Versão de exportação de entidade modificada", + "settings.class_export_version.desc": "A versão do formato para modelos de entidade modificados.", + "category.color": "Cor", + "action.import_theme": "Importar Tema", + "action.export_theme": "Exportar Tema", + "action.export_theme.desc": "Crie um arquivo de tema com base nas configurações atuais", + "action.reset_theme": "Redefinir tema", + "action.reset_theme.desc": "Redefinir para o tema padrão do Blockbench", + "action.slider_color_h": "Matiz", + "action.slider_color_s": "Saturação", "action.slider_color_v": "Value", - "action.add_to_palette": "Add To Palette", - "action.add_to_palette.desc": "Add the selected color to the color palette", - "action.import_palette": "Import Palette", - "action.import_palette.desc": "Import a .bbpalette file", - "action.export_palette": "Export Palette", - "action.export_palette.desc": "Export palette as a .bbpalette file", - "action.generate_palette": "Generate Palette", - "action.generate_palette.desc": "Generate palette from a texture", - "action.sort_palette": "Sort Palette", - "action.sort_palette.desc": "Sort all colors on the palette by color and brightness", - "action.clear_palette": "Clear Palette", - "action.clear_palette.desc": "Remove all colors from the palette", - "action.toggle_checkerboard": "Toggle Checkerboard", - "action.toggle_checkerboard.desc": "Toggle the checkerboard background behind the preview or UV editor", + "action.add_to_palette": "Adicionar a Paleta", + "action.add_to_palette.desc": "Adicione a cor selecionada à paleta de cores", + "action.import_palette": "Importar Palete", + "action.import_palette.desc": "Importar um arquivo .bbpalette", + "action.export_palette": "Exportar Paleta", + "action.export_palette.desc": "Exportar a paleta com um arquivo .bbpalette", + "action.generate_palette": "Gerar Palete", + "action.generate_palette.desc": "Gerar paleta a partir de uma textura", + "action.sort_palette": "Classificar Paleta", + "action.sort_palette.desc": "Classifique todas as cores da paleta por cor e brilho", + "action.clear_palette": "Limpar Paleta", + "action.clear_palette.desc": "Remove todas as cores da paleta", + "action.toggle_checkerboard": "Alternar Checkerboard", + "action.toggle_checkerboard.desc": "Alterne o fundo do checkerboard atrás da visualização ou do editor UV", "action.timelapse": "Timelapse...", - "action.timelapse.desc": "Record a timelapse of your modeling process", - "action.add_keyframe": "Add Keyframe", - "action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values", - "action.bring_up_all_animations.desc": "Brings all modified animators into the timeline", - "timeline.timeline": "Instructions", - "menu.palette.load": "Load Palette", - "menu.palette.load.default": "Default", + "action.timelapse.desc": "Grave um timelapse do seu progresso de modelagem", + "action.add_keyframe": "Adicionar quadro-chave", + "action.add_keyframe.desc": "Adicione automaticamente um quadro-chave. Pressione shift para forçar os valores padrão", + "action.bring_up_all_animations.desc": "Traz todos os animadores modificados para a linha do tempo", + "timeline.timeline": "Instruções", + "menu.palette.load": "Carregar Paleta", + "menu.palette.load.default": "Padrão", "panel.color.picker": "Picker", - "panel.color.palette": "Palette", - "generic.import": "Import", - "settings.brush_modifier.none": "None", - "action.export_entity": "Export Bedrock Entity", - "action.export_entity.desc": "Add the current model as an entity to a mobs.json file", - "settings.highlight_cubes": "Highlight Cubes", - "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them" + "panel.color.palette": "Paleta", + "generic.import": "Importar", + "settings.brush_modifier.none": "Nenhum", + "action.export_entity": "Exportar Entidade Bedrock", + "action.export_entity.desc": "Inclua o modelo atual como uma entidade em um arquivo mobs.json", + "settings.highlight_cubes": "Destacar cubos", + "settings.highlight_cubes.desc": "Realce cubos quando você passa o mouse sobre eles ou os seleciona", + "action.add_marker": "Definir marcador", + "action.add_marker.desc": "Definir um marcador da linha do tempo", + "timeline.pre_effect_script": "Roteiro", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/ru.json b/lang/ru.json index 7677f6b4f..3c430e6b6 100644 --- a/lang/ru.json +++ b/lang/ru.json @@ -998,5 +998,30 @@ "action.export_entity": "Export Bedrock Entity", "action.export_entity.desc": "Add the current model as an entity to a mobs.json file", "settings.highlight_cubes": "Highlight Cubes", - "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them" + "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them", + "action.add_marker": "Set Marker", + "action.add_marker.desc": "Set a timeline marker", + "timeline.pre_effect_script": "Script", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/sv.json b/lang/sv.json index ca68a7891..b595b2b2c 100644 --- a/lang/sv.json +++ b/lang/sv.json @@ -998,5 +998,30 @@ "action.export_entity": "Export Bedrock Entity", "action.export_entity.desc": "Add the current model as an entity to a mobs.json file", "settings.highlight_cubes": "Highlight Cubes", - "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them" + "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them", + "action.add_marker": "Set Marker", + "action.add_marker.desc": "Set a timeline marker", + "timeline.pre_effect_script": "Script", + "format.skin": "Skin", + "format.skin.desc": "Edit player and entity skins", + "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0", + "dialog.skin.title": "Create Skin", + "dialog.skin.model": "Skin", + "dialog.skin.texture": "Texture (Optional)", + "action.toggle_skin_layer": "Toggle Skin Layer", + "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model", + "action.gui_light": "GUI Light", + "action.gui_light.desc": "Select the way the item is lit in the inventory", + "action.gui_light.side": "Side Light", + "action.gui_light.front": "Front Light", + "action.move_keyframe_back": "Move Keyframes Back", + "action.move_keyframe_forth": "Move Keyframes Forth", + "menu.help": "Help", + "menu.help.discord": "Discord Server", + "menu.help.report_issue": "Report an Issue", + "menu.help.plugin_documentation": "Plugin API Documentation", + "menu.help.search_action": "Search and Run Action", + "menu.help.donate": "Donate", + "menu.help.about": "About...", + "menu.preview.background.clipboard": "Load from Clipboard" } \ No newline at end of file diff --git a/lang/zh.json b/lang/zh.json index 06713339a..f57770a7c 100644 --- a/lang/zh.json +++ b/lang/zh.json @@ -37,31 +37,31 @@ "keys.down": "下方向键", "keys.pageup": "上翻页键", "keys.pagedown": "下翻页键", - "keys.plus": "加号", - "keys.comma": "逗号", - "keys.point": "点号", - "keys.minus": "减号", - "keys.cross": "斜杠", + "keys.plus": "加号(+)", + "keys.comma": "逗号(,)", + "keys.point": "点号(.)", + "keys.minus": "减号(-)", + "keys.cross": "斜杠(/)", "keys.end": "End键", "keys.pos1": "Home键", "keys.printscreen": "截屏键", "keys.pause": "暂停键", "message.rotation_limit.title": "旋转限制", - "message.rotation_limit.message": "受 Minecarft 的限制,仅允许旋转单个轴,且旋转角度限制为22.5° 的倍数。在不同的轴上旋转将清除其他轴上的旋转。如果您的模型需要自由旋转,请禁用“限制旋转”选项。", - "message.file_not_found.title": "未找到文件", + "message.rotation_limit.message": "受 Minecarft 的限制,仅允许旋转单个轴,且旋转角度限制为22.5° 。在不同的轴上旋转将清除其他轴上的旋转。如果您的模型需要自由旋转,请禁用“限制旋转”选项。", + "message.file_not_found.title": "未找到此文件,请重试", "message.file_not_found.message": "Blockbench 找不到该文件。请确保此文件为本地文件而不是云文件。", "message.screenshot.title": "屏幕截图", - "message.screenshot.message": "屏幕截取成功。", + "message.screenshot.message": "成功捕获屏幕截图", "message.screenshot.clipboard": "剪贴板", "message.screenshot.right_click": "屏幕截图 - 右键点击以复制", - "message.invalid_file.title": "无效的文件", + "message.invalid_file.title": "这是一个无效的文件!", "message.invalid_file.message": "无法打开模型文件:%0", "message.invalid_model.title": "无效的模型文件", - "message.invalid_model.message": "此文件缺少有效的模型数据", - "message.child_model_only.title": "空的子类模型", - "message.child_model_only.message": "此文件为 %0 的子类模型,不包含模型。", + "message.invalid_model.message": "此文件不包含有效的模型数据", + "message.child_model_only.title": "空的子模型", + "message.child_model_only.message": "此文件为 %0 的子模型,不包含模型。", "message.drag_background.title": "编辑背景", - "message.drag_background.message": "拖动背景可移动位置。按住 shift 并上下拖动可更改大小。", + "message.drag_background.message": "拖动背景以移动它的位置。按住shift键并上下拖动以更改其大小", "message.unsaved_textures.title": "未保存的贴图", "message.unsaved_textures.message": "您的模型中存在未保存的贴图。请确保它们存在于资源包里正确的文件夹中。", "message.model_clipping.title": "模型太大了", @@ -88,7 +88,7 @@ "message.display_skin.message": "选择本地皮肤文件或输入正版玩家名字以获取皮肤", "message.display_skin.upload": "上传皮肤", "message.display_skin.name": "用户名", - "message.display_skin.reset": "重置", + "message.display_skin.reset": "重启", "message.invalid_plugin": "无效的插件文件,请查看控制台", "message.load_plugin_app": "是否允许此插件更改您的PC?请仅加载您信任的插件。", "message.load_plugin_web": "您想加载这个插件吗?请仅加载您信任的插件。", @@ -128,8 +128,8 @@ "dialog.scale.title": "缩放模型", "dialog.scale.axis": "轴", "dialog.scale.scale": "比例", - "dialog.scale.clipping": "模型裁剪:您的模型超出了工作区的范围", - "dialog.scale.confirm": "确认缩放", + "dialog.scale.clipping": "模型裁剪:您的模型超出了工作区的范围,无法容纳", + "dialog.scale.confirm": "大小", "dialog.plugins.title": "插件", "dialog.plugins.installed": "已安装", "dialog.plugins.available": "可用", @@ -400,8 +400,8 @@ "action.zoom_reset.desc": "将缩放重置为默认的100%。", "action.reset_interface": "重置界面", "action.reset_interface.desc": "重置界面的尺寸和位置", - "action.toggle_wireframe": "切换线框图", - "action.toggle_wireframe.desc": "切换线框图显示模式", + "action.toggle_wireframe": "切换线框模式", + "action.toggle_wireframe.desc": "把立方体都显示成用线框成的立方体", "action.screenshot_model": "截图", "action.screenshot_model.desc": "从当前角度拍摄模型的裁剪截图", "action.screenshot_app": "截图当前应用界面", @@ -934,8 +934,8 @@ "status_bar.recording": "录像延时摄影", "message.add_to_palette": "添加到调色板", "message.size_modifiers": "按住Ctrl或Shift键操作以进行微调", - "message.checkerboard.enabled": "格子背景已启用", - "message.checkerboard.disabled": "格子背景已关闭", + "message.checkerboard.enabled": "透明背景已启用", + "message.checkerboard.disabled": "透明背景已关闭", "message.timelapse_start": "延时启动", "message.timelapse_stop": "延时关闭", "message.import_palette.replace_palette": "切换旧调色板", @@ -945,7 +945,7 @@ "dialog.timelapse.source.interface": "界面", "dialog.timelapse.source.locked": "锁定角", "dialog.timelapse.destination": "目标文件夹", - "layout.color.checkerboard": "格子背景", + "layout.color.checkerboard": "透明背景", "layout.color.checkerboard.desc": "画布和UV编辑器的背景", "layout.font.code": "代码字体", "layout.css": "自定义CSS", @@ -953,7 +953,7 @@ "settings.deactivate_size_limit": "取消大小限制", "settings.deactivate_size_limit.desc": "取消特定模型格式的大小限制,WARNING:这可能会导致模型无效", "settings.brush_opacity_modifier": "笔刷不透明度选择器", - "settings.brush_opacity_modifier.desc": "使用手写笔时修改画笔的不透明度", + "settings.brush_opacity_modifier.desc": "使用手写笔时修改笔刷的不透明度", "settings.brush_size_modifier": "笔刷大小选择器", "settings.brush_size_modifier.desc": "使用手写笔时修改画笔的大小", "settings.brush_modifier.pressure": "压感", @@ -981,8 +981,8 @@ "action.sort_palette.desc": "按颜色和亮度对调色板上所有的颜色进行排序", "action.clear_palette": "清理调色板", "action.clear_palette.desc": "从调色板中删除所有颜色", - "action.toggle_checkerboard": "切换格子背景", - "action.toggle_checkerboard.desc": "切换预览或UV编辑器的格子背景", + "action.toggle_checkerboard": "切换透明背景", + "action.toggle_checkerboard.desc": "切换预览或UV编辑器的透明背景", "action.timelapse": "延时...", "action.timelapse.desc": "记录你建模过程的延时", "action.add_keyframe": "添加关键帧", @@ -998,5 +998,30 @@ "action.export_entity": "导出基岩实体模型", "action.export_entity.desc": "将当前模型作为实体模型添加到mobs.json文件", "settings.highlight_cubes": "发光立方体", - "settings.highlight_cubes.desc": "鼠标悬停在立方体上或选择它们时,突出显示它们(发光)" + "settings.highlight_cubes.desc": "鼠标悬停在立方体上或选择它们时,突出显示它们(发光)", + "action.add_marker": "设置标记", + "action.add_marker.desc": "设置一个时间轴点标记", + "timeline.pre_effect_script": "脚本", + "format.skin": "皮肤", + "format.skin.desc": "编辑玩家和实体的皮肤", + "message.sketchfab.setup_guide": "想学习如何在Sketchfab中设置模型吗?读取%0!", + "dialog.skin.title": "创建皮肤", + "dialog.skin.model": "皮肤", + "dialog.skin.texture": "材质(Optional)", + "action.toggle_skin_layer": "切换皮肤层", + "action.toggle_skin_layer.desc": "切换皮肤模型的帽子和衣服层", + "action.gui_light": "GUI灯", + "action.gui_light.desc": "选择库存中物品的点亮方式", + "action.gui_light.side": "侧边灯光", + "action.gui_light.front": "前灯", + "action.move_keyframe_back": "将关键帧向后移动", + "action.move_keyframe_forth": "移动关键帧", + "menu.help": "帮助", + "menu.help.discord": "断开服务器连接", + "menu.help.report_issue": "向开发者报告问题", + "menu.help.plugin_documentation": "插件API文档", + "menu.help.search_action": "搜索此内容并执行操作", + "menu.help.donate": "给开发者捐款", + "menu.help.about": "关于本软件", + "menu.preview.background.clipboard": "从剪贴板加载内容" } \ No newline at end of file diff --git a/lib/three_custom.js b/lib/three_custom.js index 02295ef02..c4f859fb8 100644 --- a/lib/three_custom.js +++ b/lib/three_custom.js @@ -157,6 +157,7 @@ THREE.Object3D.prototype.toScreenPosition = function(camera, canvas) vector.x = ( vector.x * widthHalf ) + widthHalf; vector.y = - ( vector.y * heightHalf ) + heightHalf; + vector.divideScalar(window.devicePixelRatio); return { x: vector.x, diff --git a/package.json b/package.json index 7700b7e54..015ba6ea9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Blockbench", "description": "Model editing and animation software", - "version": "3.2.2", + "version": "3.3.0", "license": "MIT", "author": { "name": "JannisX11", @@ -61,9 +61,7 @@ }, "win": { "artifactName": "${productName}_${arch}_${version}.${ext}", - "target": [ - "nsis" - ] + "target": "nsis" }, "linux": { "artifactName": "${productName}_${version}.${ext}", @@ -77,7 +75,8 @@ "scripts": { "dist": "electron-builder --publish=always", "win64": "electron-builder -w --ia32 --publish=always", - "win32": "electron-builder -w --x64 --publish=always" + "win32": "electron-builder -w --x64 --publish=always", + "beta": "electron-builder --windows portable" }, "devDependencies": { "async": "^2.4.1",