diff --git a/.travis.yml b/.travis.yml
index c9e4fc5a4..e4e6340ed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,6 +19,7 @@ jobs:
- name: "Linux"
os: linux
script:
+ - npm install electron@30.0.3
- npm run prepublish
- sudo apt-get install rpm
- electron-builder --publish=onTagOrDraft
diff --git a/css/panels.css b/css/panels.css
index 0047436e6..d868f3fa9 100644
--- a/css/panels.css
+++ b/css/panels.css
@@ -1280,7 +1280,7 @@
width: 144px;
flex-shrink: 0;
background-color: var(--color-back);
- z-index: 4;
+ z-index: 6;
border-bottom: 1px solid var(--color-border);
height: calc(100% + 1px);
}
diff --git a/js/animations/animation.js b/js/animations/animation.js
index 4eabbf23f..79455d41b 100644
--- a/js/animations/animation.js
+++ b/js/animations/animation.js
@@ -1794,180 +1794,4 @@ Interface.definePanels(function() {
'save_all_animations',
])
})
-
- new Panel('variable_placeholders', {
- icon: 'fas.fa-stream',
- condition: {modes: ['animate']},
- growable: true,
- resizable: true,
- default_position: {
- slot: 'left_bar',
- float_position: [0, 0],
- float_size: [300, 400],
- height: 400
- },
- component: {
- name: 'panel-placeholders',
- components: {VuePrismEditor},
- data() { return {
- text: '',
- buttons: []
- }},
- methods: {
- updateButtons() {
- let old_values = {};
- this.buttons.forEach(b => old_values[b.id] = b.value);
- this.buttons.empty();
-
- let text = this.text//.toLowerCase();
- let matches = text.matchAll(/(slider|toggle|impulse)\(.+\)/gi);
-
- for (let match of matches) {
- let [type, content] = match[0].substring(0, match[0].length - 1).split(/\(/);
- let [id, ...args] = content.split(/\(|, */);
- id = id.replace(/['"]/g, '');
- if (this.buttons.find(b => b.id == id)) return;
-
- let variable = text.substring(0, match.index).match(/[\w.-]+ *= *$/);
- variable = variable ? variable[0].replace(/[ =]+/g, '').replace(/^v\./i, 'variable.').replace(/^q\./i, 'query.').replace(/^t\./i, 'temp.').replace(/^c\./i, 'context.') : undefined;
-
- if (type == 'slider') {
- this.buttons.push({
- type,
- id,
- value: old_values[id] || 0,
- variable,
- step: isNaN(args[0]) ? undefined : parseFloat(args[0]),
- min: isNaN(args[1]) ? undefined : parseFloat(args[1]),
- max: isNaN(args[2]) ? undefined : parseFloat(args[2])
- })
- } else if (type == 'toggle') {
- this.buttons.push({
- type,
- id,
- value: old_values[id] || 0,
- variable,
- })
- } else if (type == 'impulse') {
- this.buttons.push({
- type,
- id,
- value: 0,
- variable,
- duration: parseFloat(args[0]) || 0.1
- })
- }
- }
- },
- changeButtonValue(button, event) {
- if (button.type == 'toggle') {
- button.value = event.target.checked ? 1 : 0;
- }
- if (button.type == 'impulse') {
- button.value = 1;
- setTimeout(() => {
- button.value = 0;
- }, Math.clamp(button.duration, 0, 1) * 1000);
- }
- if (button.variable) {
- delete Animator.MolangParser.variables[button.variable];
- }
- Animator.preview();
- },
- slideButton(button, e1) {
- convertTouchEvent(e1);
- let last_event = e1;
- let started = false;
- let move_calls = 0;
- let last_val = 0;
- let total = 0;
- let clientX = e1.clientX;
- function start() {
- started = true;
- if (!e1.touches && last_event == e1 && e1.target.requestPointerLock) e1.target.requestPointerLock();
- }
-
- function move(e2) {
- convertTouchEvent(e2);
- if (!started && Math.abs(e2.clientX - e1.clientX) > 5) {
- start()
- }
- if (started) {
- if (e1.touches) {
- clientX = e2.clientX;
- } else {
- let limit = move_calls <= 2 ? 1 : 100;
- clientX += Math.clamp(e2.movementX, -limit, limit);
- }
- let val = Math.round((clientX - e1.clientX) / 45);
- let difference = (val - last_val);
- if (!difference) return;
- if (button.step) {
- difference *= button.step;
- } else {
- difference *= canvasGridSize(e2.shiftKey || Pressing.overrides.shift, e2.ctrlOrCmd || Pressing.overrides.ctrl);
- }
-
-
- button.value = Math.clamp(Math.roundTo((parseFloat(button.value) || 0) + difference, 4), button.min, button.max);
-
- last_val = val;
- last_event = e2;
- total += difference;
- move_calls++;
-
- Animator.preview()
- Blockbench.setStatusBarText(trimFloatNumber(total));
- }
- }
- function off(e2) {
- if (document.exitPointerLock) document.exitPointerLock()
- removeEventListeners(document, 'mousemove touchmove', move);
- removeEventListeners(document, 'mouseup touchend', off);
- }
- addEventListeners(document, 'mouseup touchend', off);
- addEventListeners(document, 'mousemove touchmove', move);
- },
- autocomplete(text, position) {
- let test = Animator.autocompleteMolang(text, position, 'placeholders');
- return test;
- }
- },
- watch: {
- text(text) {
- if (Project && typeof text == 'string') {
- Project.variable_placeholders = text;
- this.updateButtons();
- Project.variable_placeholder_buttons.replace(this.buttons);
- }
- }
- },
- template: `
-
-
-
-
-
${tl('panel.variable_placeholders.info')}
-
-
-
- `
- }
- })
})
diff --git a/js/animations/animation_mode.js b/js/animations/animation_mode.js
index 209a3ce68..3c7d6a42d 100644
--- a/js/animations/animation_mode.js
+++ b/js/animations/animation_mode.js
@@ -1415,6 +1415,7 @@ Interface.definePanels(function() {
if (document.exitPointerLock) document.exitPointerLock()
removeEventListeners(document, 'mousemove touchmove', move);
removeEventListeners(document, 'mouseup touchend', off);
+ Blockbench.setStatusBarText();
}
addEventListeners(document, 'mouseup touchend', off);
addEventListeners(document, 'mousemove touchmove', move);
diff --git a/js/interface/settings.js b/js/interface/settings.js
index 98f0b12a0..02d574553 100644
--- a/js/interface/settings.js
+++ b/js/interface/settings.js
@@ -582,6 +582,10 @@ const Settings = {
settings.brush_opacity_modifier.set('none');
settings.brush_size_modifier.set('none');
})
+ let date = new Date();
+ if (date.getMonth() >= 5 && date.getDate() >= 13) {
+ settings.bedrock_uv_rotations.set(true);
+ }
},
setupProfiles() {
if (localStorage.getItem('settings_profiles') != null) {
diff --git a/js/io/formats/skin.js b/js/io/formats/skin.js
index fad4fc837..d1f7e7f30 100644
--- a/js/io/formats/skin.js
+++ b/js/io/formats/skin.js
@@ -1839,6 +1839,252 @@ skin_presets.boat = {
]
}`
};
+skin_presets.bogged = {
+ display_name: 'Bogged',
+ model: `{
+ "name": "bogged",
+ "texturewidth": 64,
+ "textureheight": 32,
+ "eyes": [
+ [9, 12, 2, 1],
+ [13, 12, 2, 1]
+ ],
+ "bones": [
+ {
+ "name": "body",
+ "pivot": [0, 24, 0],
+ "cubes": [
+ {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+ ]
+ },
+ {
+ "name": "waist",
+ "pivot": [0, 12, 0]
+ },
+ {
+ "name": "head",
+ "pivot": [0, 24, 0],
+ "cubes": [
+ {"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}
+ ]
+ },
+ {
+ "name": "mushrooms",
+ "parent": "head",
+ "pivot": [3, 31.5, 3],
+ "cubes": [
+ {"origin": [-6, 31, -3], "size": [6, 4, 0], "pivot": [-3, 32.5, -3], "rotation": [0, -45, 0], "uv": [50, 22]},
+ {"origin": [-6, 31, -3], "size": [6, 4, 0], "pivot": [-3, 32.5, -3], "rotation": [0, 45, 0], "uv": [50, 22]},
+ {"origin": [0, 31, 3], "size": [6, 4, 0], "pivot": [3, 31.5, 3], "rotation": [0, 45, 0], "uv": [50, 16]},
+ {"origin": [0, 31, 3], "size": [6, 4, 0], "pivot": [3, 31.5, 3], "rotation": [0, -45, 0], "uv": [50, 16]},
+ {"origin": [-5, 25, 3], "size": [6, 5, 0], "pivot": [-2, 25, 3], "rotation": [-90, 0, 45], "uv": [50, 27]},
+ {"origin": [-5, 25, 3], "size": [6, 5, 0], "pivot": [-2, 25, 3], "rotation": [-90, 0, 135], "uv": [50, 27]}
+ ]
+ },
+ {
+ "name": "hat",
+ "pivot": [0, 24, 0],
+ "cubes": [
+ {"origin": [-4, 24, -4], "size": [8, 8, 8], "inflate": 0.2, "uv": [32, 0], "layer": true}
+ ]
+ },
+ {
+ "name": "rightArm",
+ "pivot": [-5, 22, 0],
+ "cubes": [
+ {"origin": [-6, 12, -1], "size": [2, 12, 2], "uv": [40, 16]}
+ ]
+ },
+ {
+ "name": "rightItem",
+ "parent": "rightArm",
+ "pivot": [-6, 15, 1]
+ },
+ {
+ "name": "leftArm",
+ "pivot": [5, 22, 0],
+ "mirror": true,
+ "cubes": [
+ {"origin": [4, 12, -1], "size": [2, 12, 2], "uv": [40, 16], "mirror": true}
+ ]
+ },
+ {
+ "name": "leftItem",
+ "parent": "leftArm",
+ "pivot": [6, 15, 1]
+ },
+ {
+ "name": "rightLeg",
+ "pivot": [-2, 12, 0],
+ "cubes": [
+ {"origin": [-3, 0, -1], "size": [2, 12, 2], "uv": [0, 16]}
+ ]
+ },
+ {
+ "name": "leftLeg",
+ "pivot": [2, 12, 0],
+ "mirror": true,
+ "cubes": [
+ {"origin": [1, 0, -1], "size": [2, 12, 2], "uv": [0, 16], "mirror": true}
+ ]
+ }
+ ]
+ }`
+};
+skin_presets.bogged_layer = {
+ display_name: 'Bogged/Stray Layer',
+ model: `{
+ "name": "bogged_layer",
+ "texturewidth": 64,
+ "textureheight": 32,
+ "eyes": [
+ [9, 12, 2, 1],
+ [13, 12, 2, 1]
+ ],
+ "bones": [
+ {
+ "name": "body",
+ "pivot": [0, 24, 0],
+ "cubes": [
+ {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
+ ]
+ },
+ {
+ "name": "leftArm",
+ "parent": "body",
+ "pivot": [5, 22, 0],
+ "mirror": true,
+ "cubes": [
+ {"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16], "mirror": true}
+ ]
+ },
+ {
+ "name": "head",
+ "pivot": [0, 24, 0],
+ "cubes": [
+ {"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}
+ ]
+ },
+ {
+ "name": "hat",
+ "pivot": [0, 24, 0],
+ "cubes": [
+ {"origin": [-4, 24, -4], "size": [8, 8, 8], "inflate": 0.5, "uv": [32, 0], "layer": true, , "visibility": false}
+ ]
+ },
+ {
+ "name": "rightArm",
+ "pivot": [-5, 22, 0],
+ "cubes": [
+ {"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
+ ]
+ },
+ {
+ "name": "rightLeg",
+ "pivot": [-1.9, 12, 0],
+ "cubes": [
+ {"origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
+ ]
+ },
+ {
+ "name": "leftLeg",
+ "pivot": [1.9, 12, 0],
+ "mirror": true,
+ "cubes": [
+ {"origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16], "mirror": true}
+ ]
+ }
+ ]
+ }`
+};
+skin_presets.breeze = {
+ display_name: 'Breeze',
+ model: `{
+ "name": "breeze",
+ "texturewidth": 32,
+ "textureheight": 32,
+ "eyes": [
+ [7, 14, 3, 1],
+ [14, 14, 3, 1],
+ [6, 29, 5, 1],
+ [15, 29, 5, 1]
+ ],
+ "bones": [
+ {
+ "name": "body",
+ "pivot": [0, 0, 0]
+ },
+ {
+ "name": "rods",
+ "parent": "body",
+ "pivot": [0, 16, 0],
+ "cubes": [
+ {"origin": [-1, 11, -6], "size": [2, 8, 2], "pivot": [0, 19, -3], "rotation": [22.5, 0, 0], "uv": [0, 17]},
+ {"origin": [-3.59808, 11, -1.5], "size": [2, 8, 2], "pivot": [-2.59808, 19, 1.5], "rotation": [-157.5, 60, 180], "uv": [0, 17]},
+ {"origin": [1.59808, 11, -1.5], "size": [2, 8, 2], "pivot": [2.59808, 19, 1.5], "rotation": [-157.5, -60, 180], "uv": [0, 17]}
+ ]
+ },
+ {
+ "name": "head",
+ "parent": "body",
+ "pivot": [0, 20, 0],
+ "cubes": [
+ {"origin": [-4, 20, -4], "size": [8, 8, 8], "uv": [0, 0]}
+ ]
+ },
+ {
+ "name": "eyes",
+ "parent": "head",
+ "pivot": [0, 20, 0],
+ "cubes": [
+ {"origin": [-5, 22, -4.2], "size": [10, 3, 4], "uv": [4, 24], "layer": true}
+ ]
+ }
+ ]
+ }`
+}
+skin_presets.breeze_tornado = {
+ display_name: 'Breeze Tornado',
+ model: `{
+ "name": "breeze_wind",
+ "texturewidth": 128,
+ "textureheight": 128,
+ "bones": [
+ {
+ "name": "tornado_body",
+ "pivot": [0, 0, 0]
+ },
+ {
+ "name": "tornado_bottom",
+ "parent": "tornado_body",
+ "pivot": [0, 0, 0],
+ "cubes": [
+ {"origin": [-2.5, 0, -2.5], "size": [5, 7, 5], "uv": [1, 83]}
+ ]
+ },
+ {
+ "name": "tornado_mid",
+ "parent": "tornado_bottom",
+ "pivot": [0, 7, 0],
+ "cubes": [
+ {"origin": [-2.5, 7, -2.5], "size": [5, 6, 5], "uv": [49, 71]},
+ {"origin": [-4, 7, -4], "size": [8, 6, 8], "uv": [78, 32]},
+ {"origin": [-6, 7, -6], "size": [12, 6, 12], "uv": [74, 28]}
+ ]
+ },
+ {
+ "name": "tornado_top",
+ "parent": "tornado_mid",
+ "pivot": [0, 13, 0],
+ "cubes": [
+ {"origin": [-2.5, 13, -2.5], "size": [5, 8, 5], "uv": [105, 57]},
+ {"origin": [-6, 13, -6], "size": [12, 8, 12], "uv": [6, 6]},
+ {"origin": [-9, 13, -9], "size": [18, 8, 18], "uv": [0, 0]}
+ ]
+ }
+ ]
+ }`
+}
skin_presets.camel = {
display_name: 'Camel',
model: `{
@@ -5440,7 +5686,7 @@ skin_presets.silverfish = {
}`
};
skin_presets.skeleton = {
- display_name: 'Skeleton',
+ display_name: 'Skeleton/Stray',
model: `{
"name": "skeleton",
"texturewidth": 64,
diff --git a/js/texturing/textures.js b/js/texturing/textures.js
index 0e806a9fd..89842eea2 100644
--- a/js/texturing/textures.js
+++ b/js/texturing/textures.js
@@ -877,15 +877,17 @@ class Texture {
if (event instanceof Event) {
Prop.active_panel = 'textures';
}
- if (event && (event.shiftKey || event.ctrlKey)) {
- this.multi_selected = true;
- if (event.shiftKey) {
+ if (event && (event.shiftKey || event.ctrlOrCmd || Pressing.overrides.ctrl || Pressing.overrides.shift)) {
+ if (event.shiftKey || Pressing.overrides.shift) {
+ this.multi_selected = true;
let start_i = Texture.last_selected;
let end_i = Texture.all.indexOf(this);
if (start_i > end_i) [start_i, end_i] = [end_i, start_i];
for (let i = start_i+1; i < end_i; i++) {
Texture.all[i].multi_selected = true;
}
+ } else {
+ this.multi_selected = !this.multi_selected;
}
Texture.last_selected = Texture.all.indexOf(this);
return;
@@ -1097,10 +1099,9 @@ class Texture {
return this;
}
showContextMenu(event) {
- var scope = this;
- scope.select()
+ if (this != Texture.selected) this.select()
Prop.active_panel = 'textures'
- this.menu.open(event, scope)
+ this.menu.open(event, this)
}
openMenu() {
this.select();
diff --git a/package.json b/package.json
index 26fb41173..54a254402 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "Blockbench",
"description": "Low-poly modeling and animation software",
- "version": "4.10.2",
+ "version": "4.10.3",
"license": "GPL-3.0-or-later",
"author": {
"name": "JannisX11",
@@ -105,7 +105,7 @@
"publish-windows": "npm run bundle && electron-builder -w --publish=onTagOrDraft && node ./scripts/rename_portable.js && electron-builder --windows portable --publish=onTagOrDraft",
"pwa": "node ./scripts/generate_pwa.js",
"prepublish": "npm run bundle && npm run pwa",
- "webapp": "git checkout gh-pages && git merge master && git push && git checkout master"
+ "webapp": "git checkout gh-pages && git pull && git merge master && git push && git checkout master"
},
"devDependencies": {
"@electron/notarize": "^2.3.0",