mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-03-31 17:21:07 +08:00
Merge branch 'patch'
This commit is contained in:
commit
1083f1ada2
@ -1940,7 +1940,7 @@ span.controller_state_section_info {
|
||||
--color-uv-background: transparent;
|
||||
--uv-line-width: 1px;
|
||||
}
|
||||
#uv_frame.overlay_mode * {
|
||||
#uv_frame.overlay_mode .uv_face {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@ -2700,6 +2700,9 @@ span.controller_state_section_info {
|
||||
margin: 2px 4px 0 4px;
|
||||
width: calc(100% - 8px);
|
||||
}
|
||||
#center #panel_color .sp-top.sp-cf {
|
||||
height: var(--height);
|
||||
}
|
||||
/* Skin Pose */
|
||||
#skin_pose_selector {
|
||||
display: flex;
|
||||
|
BIN
icon_maskable.png
Normal file
BIN
icon_maskable.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
@ -229,6 +229,7 @@ const Timeline = {
|
||||
},
|
||||
revealTime(time) {
|
||||
let body = document.getElementById('timeline_body');
|
||||
if (!body) return;
|
||||
var scroll = body.scrollLeft;
|
||||
var playhead = time * Timeline.vue._data.size + 8;
|
||||
if (playhead < scroll || playhead > scroll + document.getElementById('timeline_vue').clientWidth - Timeline.vue._data.head_width) {
|
||||
|
@ -2136,8 +2136,13 @@ BARS.defineActions(function() {
|
||||
|
||||
let player_skin_setup = false;
|
||||
function updateBase(mode) {
|
||||
let root_has_binding = Outliner.root.find(g => g instanceof Group && g.bedrock_binding)
|
||||
if (mode == 'attachable_first') {
|
||||
Project.model_3d.position.set(-20, 21, 0);
|
||||
if (root_has_binding) {
|
||||
Project.model_3d.position.set(-20, 21, 0);
|
||||
} else {
|
||||
Project.model_3d.position.set(-8, 6, -18);
|
||||
}
|
||||
Project.model_3d.rotation.set(
|
||||
Math.degToRad(-95),
|
||||
Math.degToRad(45),
|
||||
@ -2151,8 +2156,13 @@ BARS.defineActions(function() {
|
||||
|
||||
if (mode == 'attachable_third') {
|
||||
let angle = Math.degToRad(15);
|
||||
let arm_offset = Reusable.vec1.set(1, -31, 1).applyAxisAngle(Reusable.vec2.set(1, 0, 0), angle);
|
||||
Project.model_3d.position.set(5, 22, 0).add(arm_offset);
|
||||
if (root_has_binding) {
|
||||
let arm_offset = Reusable.vec1.set(1, -31, 1).applyAxisAngle(Reusable.vec2.set(1, 0, 0), angle);
|
||||
Project.model_3d.position.set(5, 22, 0).add(arm_offset);
|
||||
} else {
|
||||
let arm_offset = Reusable.vec1.set(1, -7, 1).applyAxisAngle(Reusable.vec2.set(1, 0, 0), angle);
|
||||
Project.model_3d.position.set(5, 22, 0).add(arm_offset);
|
||||
}
|
||||
Project.model_3d.rotation.set(angle, 0, 0);
|
||||
player_preview_model.enable()
|
||||
|
||||
|
@ -66,3 +66,5 @@ Blockbench.DisplaySlot = DisplaySlot;
|
||||
Blockbench.Reusable = Reusable;
|
||||
|
||||
Blockbench.Texture = Texture;
|
||||
Blockbench.TextureLayer = TextureLayer;
|
||||
Blockbench.SharedActions = SharedActions;
|
||||
|
@ -295,7 +295,7 @@ function buildForm(dialog) {
|
||||
case 'save':
|
||||
if (data.type == 'folder' && !isApp) break;
|
||||
|
||||
let input = $(`<input class="dark_bordered half" class="focusable_input" type="text" id="${form_id}" disabled>`);
|
||||
let input = $(`<input class="dark_bordered half" class="focusable_input" type="text" id="${form_id}" style="pointer-events: none;" disabled>`);
|
||||
input[0].value = settings.streamer_mode.value ? `[${tl('generic.redacted')}]` : data.value || '';
|
||||
let input_wrapper = $('<div class="input_wrapper"></div>');
|
||||
input_wrapper.append(input);
|
||||
@ -588,7 +588,7 @@ window.Dialog = class Dialog {
|
||||
}
|
||||
return form_result;
|
||||
}
|
||||
setFormValues(values) {
|
||||
setFormValues(values, update = true) {
|
||||
for (let form_id in this.form) {
|
||||
let data = this.form[form_id];
|
||||
if (values[form_id] != undefined && typeof data == 'object' && data.bar) {
|
||||
@ -642,7 +642,7 @@ window.Dialog = class Dialog {
|
||||
}
|
||||
}
|
||||
}
|
||||
this.updateFormValues();
|
||||
if (update) this.updateFormValues();
|
||||
}
|
||||
getFormResult() {
|
||||
let result = {}
|
||||
|
@ -746,6 +746,9 @@ Interface.CustomElements.SelectInput = function(id, data) {
|
||||
let value = data.value || data.default || Object.keys(options)[0];
|
||||
let select = Interface.createElement('bb-select', {id, class: 'half', value: value}, getNameFor(options[value]));
|
||||
function setKey(key, options) {
|
||||
if (!options) {
|
||||
options = typeof data.options == 'function' ? data.options() : data.options;
|
||||
}
|
||||
value = key;
|
||||
select.setAttribute('value', key);
|
||||
select.textContent = getNameFor(options[key]);
|
||||
|
@ -847,6 +847,16 @@ addEventListeners(document, 'keydown mousedown', function(e) {
|
||||
ReferenceImageMode.deactivate();
|
||||
used = true;
|
||||
}
|
||||
} else if (Prop.active_panel == 'uv' && Modes.paint && Texture.selected && Texture.selected.selection.is_custom) {
|
||||
if (Keybinds.extra.cancel.keybind.isTriggered(e)) {
|
||||
SharedActions.run('unselect_all', e);
|
||||
used = true;
|
||||
}
|
||||
} else if (Modes.paint && TextureLayer.selected && TextureLayer.selected.in_limbo) {
|
||||
if (Keybinds.extra.confirm.keybind.isTriggered(e)) {
|
||||
TextureLayer.selected.resolveLimbo(false);
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
if (ActionControl.open) {
|
||||
used = ActionControl.handleKeys(e) || used
|
||||
|
@ -758,7 +758,7 @@ function setupMobilePanelSelector() {
|
||||
let panel_b = Panels[key];
|
||||
if (panel_b.slot == 'bottom') {
|
||||
$(panel_b.node).detach();
|
||||
panel_b.slot = 'left_bar';
|
||||
panel_b.position_data.slot = 'left_bar';
|
||||
}
|
||||
}
|
||||
if (panel) {
|
||||
|
@ -21,7 +21,7 @@ const SharedActions = {
|
||||
|
||||
return {
|
||||
delete() {
|
||||
lsit.remove(handler);
|
||||
list.remove(handler);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -336,7 +336,7 @@ const CustomTheme = {
|
||||
CustomTheme.data.colors[scope_key] = last_color;
|
||||
field.spectrum('set', last_color);
|
||||
},
|
||||
beforeShow(a, b) {
|
||||
beforeShow() {
|
||||
last_color = CustomTheme.data.colors[scope_key];
|
||||
field.spectrum('set', last_color);
|
||||
}
|
||||
|
@ -598,10 +598,10 @@ var codec = new Codec('project', {
|
||||
ani.uuid = guid();
|
||||
}
|
||||
if (base_ani.animators) {
|
||||
for (let key in animators) {
|
||||
for (let key in base_ani.animators) {
|
||||
if (uuid_map[key]) {
|
||||
animators[uuid_map[key]] = animators[key];
|
||||
delete animators[key];
|
||||
base_ani.animators[uuid_map[key]] = base_ani.animators[key];
|
||||
delete base_ani.animators[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1137,7 +1137,7 @@ var codec = new Codec('bedrock', {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (data && index !== undefined) {
|
||||
if (data) {
|
||||
|
||||
if (Group.all.find(group => group.bedrock_binding)) {
|
||||
data.format_version = '1.16.0';
|
||||
|
@ -126,16 +126,50 @@ new ModelFormat('image', {
|
||||
]
|
||||
},
|
||||
new() {
|
||||
if (newProject(this)) {
|
||||
TextureGenerator.addBitmapDialog(() => {
|
||||
setTimeout(() => {
|
||||
Undo.history.empty();
|
||||
Undo.index = 0;
|
||||
UVEditor.vue.centerView();
|
||||
}, 1);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
newProject(this);
|
||||
let callback = () => {
|
||||
setTimeout(() => {
|
||||
Undo.history.empty();
|
||||
Undo.index = 0;
|
||||
UVEditor.vue.centerView();
|
||||
}, 1);
|
||||
};
|
||||
let size_presets = {
|
||||
'': 'Unset',
|
||||
'16x16': '16 x 16',
|
||||
'32x32': '32 x 32',
|
||||
'64x64': '64 x 64',
|
||||
'128x128': '128 x 128',
|
||||
'256x256': '256 x 256',
|
||||
'512x512': '512 x 512',
|
||||
'1920x1080': '1920 x 1080',
|
||||
};
|
||||
let previous_size_preset = '';
|
||||
let dialog = new Dialog({
|
||||
id: 'add_bitmap',
|
||||
title: tl('action.create_texture'),
|
||||
buttons: ['dialog.confirm'],
|
||||
form: {
|
||||
name: {label: 'generic.name', value: 'texture'},
|
||||
section2: "_",
|
||||
|
||||
size_preset:{label: 'dialog.create_texture.resolution', type: 'select', options: size_presets},
|
||||
resolution: {label: 'dialog.create_texture.resolution', type: 'vector', dimensions: 2, value: [16, 16], min: 1, max: 2048},
|
||||
color: {label: 'data.color', type: 'color', colorpicker: TextureGenerator.background_color, toggle_enabled: true, toggle_default: false},
|
||||
},
|
||||
onFormChange(result) {
|
||||
console.log(result)
|
||||
if (result.size_preset && result.size_preset != previous_size_preset) {
|
||||
let size = result.size_preset.split('x').map(v => parseInt(v));
|
||||
dialog.setFormValues({resolution: size}, false);
|
||||
}
|
||||
previous_size_preset = result.size_preset;
|
||||
},
|
||||
onConfirm: function(results) {
|
||||
results.type = 'blank';
|
||||
TextureGenerator.addBitmap(results, callback);
|
||||
}
|
||||
}).show();
|
||||
},
|
||||
onActivation() {
|
||||
Interface.preview.classList.add('image_mode');
|
||||
|
@ -160,7 +160,7 @@ codec.export = null;
|
||||
codec.rebuild = function(model_id, pose) {
|
||||
let [preset_id, variant] = model_id.split('.');
|
||||
let preset = skin_presets[preset_id];
|
||||
let model = JSON.parse(preset.model || (variant == 'java' ? preset.model_java : preset.model_bedrock));
|
||||
let model = JSON.parse(preset.model || (variant == 'java' ? preset.model_java : preset.model_bedrock) || preset[variant]);
|
||||
codec.parse(model, undefined, undefined, pose && pose !== 'none');
|
||||
if (pose && pose !== 'none') {
|
||||
setTimeout(() => {
|
||||
@ -245,6 +245,7 @@ function generateTemplate(width = 64, height = 64, cubes, name = 'name', eyes, l
|
||||
}
|
||||
|
||||
const model_options = {};
|
||||
let selected_model = '';
|
||||
const skin_dialog = new Dialog({
|
||||
title: tl('dialog.skin.title'),
|
||||
id: 'skin',
|
||||
@ -254,7 +255,7 @@ const skin_dialog = new Dialog({
|
||||
type: 'select',
|
||||
options: model_options
|
||||
},
|
||||
variant: {
|
||||
game_edition: {
|
||||
label: 'dialog.skin.variant',
|
||||
type: 'inline_select',
|
||||
default: 'java_edition',
|
||||
@ -263,7 +264,17 @@ const skin_dialog = new Dialog({
|
||||
bedrock_edition: 'Bedrock Edition',
|
||||
},
|
||||
condition(form) {
|
||||
return !skin_presets[form.model].model;
|
||||
return skin_presets[form.model].model_bedrock;
|
||||
}
|
||||
},
|
||||
variant: {
|
||||
label: 'dialog.skin.variant',
|
||||
type: 'select',
|
||||
options() {
|
||||
return (selected_model && skin_presets[selected_model].variants) || {}
|
||||
},
|
||||
condition(form) {
|
||||
return skin_presets[form.model].variants;
|
||||
}
|
||||
},
|
||||
resolution: {label: 'dialog.create_texture.resolution', type: 'select', value: 16, options: {
|
||||
@ -287,7 +298,19 @@ const skin_dialog = new Dialog({
|
||||
pose: {type: 'checkbox', label: 'dialog.skin.pose', value: true, condition: form => (!!skin_presets[form.model].pose)},
|
||||
layer_template: {type: 'checkbox', label: 'dialog.skin.layer_template', value: false}
|
||||
},
|
||||
draggable: true,
|
||||
onFormChange(result) {
|
||||
selected_model = result.model;
|
||||
let variants = skin_presets[result.model].variants;
|
||||
if (variants) {
|
||||
for (let key in variants) {
|
||||
if (!result.variant || !variants[result.variant]) {
|
||||
result.variant = key;
|
||||
skin_dialog.setFormValues({variant: key}, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onConfirm(result) {
|
||||
if (result.model == 'flat_texture') {
|
||||
if (result.texture) {
|
||||
@ -299,9 +322,22 @@ const skin_dialog = new Dialog({
|
||||
} else {
|
||||
if (newProject(format)) {
|
||||
let preset = skin_presets[result.model];
|
||||
let model = JSON.parse(preset.model || (result.variant == 'java_edition' ? preset.model_java : preset.model_bedrock));
|
||||
let raw_model;
|
||||
if (preset.model_bedrock) {
|
||||
raw_model = result.game_edition == 'java_edition' ? preset.model_java : preset.model_bedrock;
|
||||
} else if (preset.variants) {
|
||||
raw_model = preset.variants[result.variant].model;
|
||||
} else {
|
||||
raw_model = preset.model;
|
||||
}
|
||||
let model = JSON.parse(raw_model);
|
||||
codec.parse(model, result.resolution/16, result.texture, result.pose, result.layer_template);
|
||||
Project.skin_model = result.model + '.' + (result.variant == 'java_edition' ? 'java' : 'bedrock');
|
||||
Project.skin_model = result.model;
|
||||
if (preset.model_bedrock) {
|
||||
Project.skin_model += '.' + (result.game_edition == 'java_edition' ? 'java' : 'bedrock');
|
||||
} else if (preset.variants) {
|
||||
Project.skin_model += '.' + result.variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1192,84 +1228,173 @@ skin_presets.banner = {
|
||||
skin_presets.bat = {
|
||||
display_name: 'Bat',
|
||||
pose: true,
|
||||
model: `{
|
||||
"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]}
|
||||
variants: {
|
||||
new: {
|
||||
name: 'New',
|
||||
model: `{
|
||||
"name": "bat_v2",
|
||||
"texturewidth": 32,
|
||||
"textureheight": 32,
|
||||
"eyes": [
|
||||
[1, 10, 2, 1],
|
||||
[5, 10, 2, 1]
|
||||
],
|
||||
"bones": [
|
||||
{
|
||||
"name": "Head",
|
||||
"pivot": [0, 7, 0],
|
||||
"cubes": [
|
||||
{"origin": [-2, 7, -1], "size": [4, 3, 2], "uv": [0, 7]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rightEar",
|
||||
"parent": "Head",
|
||||
"pivot": [-1.5, 9, 0],
|
||||
"cubes": [
|
||||
{"origin": [-4, 8, 0], "size": [3, 5, 0], "uv": [1, 15]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "leftEar",
|
||||
"parent": "Head",
|
||||
"pivot": [1.1, 10, 0],
|
||||
"cubes": [
|
||||
{"origin": [1, 8, 0], "size": [3, 5, 0], "uv": [8, 15]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"pivot": [0, 7, 0],
|
||||
"cubes": [
|
||||
{"origin": [-1.5, 2, -1], "size": [3, 5, 2], "uv": [0, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "feet",
|
||||
"parent": "body",
|
||||
"pivot": [0, 2, 0],
|
||||
"cubes": [
|
||||
{"origin": [-1.5, 0, 0], "size": [3, 2, 0], "uv": [16, 16]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rightWing",
|
||||
"parent": "body",
|
||||
"pivot": [-1.5, 7, 0],
|
||||
"cubes": [
|
||||
{"origin": [-3.5, 2, 0], "size": [2, 7, 0], "uv": [12, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rightWingTip",
|
||||
"parent": "rightWing",
|
||||
"pivot": [-3.5, 7, 0],
|
||||
"cubes": [
|
||||
{"origin": [-9.5, 1, 0], "size": [6, 8, 0], "uv": [16, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "leftWing",
|
||||
"parent": "body",
|
||||
"pivot": [1.5, 7, 0],
|
||||
"cubes": [
|
||||
{"origin": [1.5, 2, 0], "size": [2, 7, 0], "uv": [12, 7]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "leftWingTip",
|
||||
"parent": "leftWing",
|
||||
"pivot": [3.5, 7, 0],
|
||||
"cubes": [
|
||||
{"origin": [3.5, 1, 0], "size": [6, 8, 0], "uv": [16, 8]}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rightEar",
|
||||
"parent": "Head",
|
||||
"pivot": [0, 24, 0],
|
||||
"cubes": [
|
||||
{"name": "rightEar", "origin": [-4, 26, -2], "size": [3, 4, 1], "uv": [24, 0]}
|
||||
}`
|
||||
},
|
||||
old: {
|
||||
name: 'Old',
|
||||
model: `{
|
||||
"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],
|
||||
"pose": [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],
|
||||
"pose": [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],
|
||||
"pose": [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],
|
||||
"pose": [0, 15, 0],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "leftWingTip", "origin": [12, 10, 1.5], "size": [8, 12, 1], "uv": [24, 16]}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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],
|
||||
"pose": [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],
|
||||
"pose": [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],
|
||||
"pose": [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],
|
||||
"pose": [0, 15, 0],
|
||||
"mirror": true,
|
||||
"cubes": [
|
||||
{"name": "leftWingTip", "origin": [12, 10, 1.5], "size": [8, 12, 1], "uv": [24, 16]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`
|
||||
}`
|
||||
},
|
||||
}
|
||||
};
|
||||
skin_presets.bed = {
|
||||
display_name: 'Bed',
|
||||
|
@ -943,6 +943,10 @@ BARS.defineActions(function() {
|
||||
rotation: cube.rotation,
|
||||
vertices: []
|
||||
})
|
||||
let rotation_euler = new THREE.Euler(0, 0, 0, 'ZYX').fromArray(cube.rotation.map(Math.degToRad));
|
||||
rotation_euler.reorder('XYZ');
|
||||
mesh.rotation.V3_set(rotation_euler.toArray().map(r => Math.roundTo(Math.radToDeg(r), 4)));
|
||||
|
||||
var adjustedFrom = cube.from.slice();
|
||||
var adjustedTo = cube.to.slice();
|
||||
adjustFromAndToForInflateAndStretch(adjustedFrom, adjustedTo, cube);
|
||||
|
16
js/modes.js
16
js/modes.js
@ -62,15 +62,17 @@ class Mode extends KeybindItem {
|
||||
}
|
||||
|
||||
UVEditor.beforeMoving();
|
||||
for (let id in Panels) {
|
||||
let old_pos_data = Panels[id].position_data;
|
||||
Panels[id].position_data = Interface.getModeData().panels[id];
|
||||
if (!Panels[id].position_data) {
|
||||
Panels[id].position_data = Interface.getModeData().panels[id] = JSON.parse(JSON.stringify(old_pos_data))
|
||||
if (!Blockbench.isMobile) {
|
||||
for (let id in Panels) {
|
||||
let old_pos_data = Panels[id].position_data;
|
||||
Panels[id].position_data = Interface.getModeData().panels[id];
|
||||
if (!Panels[id].position_data) {
|
||||
Panels[id].position_data = Interface.getModeData().panels[id] = JSON.parse(JSON.stringify(old_pos_data))
|
||||
}
|
||||
Panels[id].updateSlot();
|
||||
}
|
||||
Panels[id].updateSlot();
|
||||
updateSidebarOrder();
|
||||
}
|
||||
updateSidebarOrder();
|
||||
|
||||
Canvas.updateRenderSides()
|
||||
if (this.tool && BarItems[this.tool] && Condition(BarItems[this.tool])) {
|
||||
|
@ -311,11 +311,11 @@ const PredicateOverrideEditor = {
|
||||
<select-input v-model="generator.type" :options="available_predicate_options" @input="updateGeneratorType()" />
|
||||
|
||||
<label>${tl('dialog.predicate_overrides.variants')}</label>
|
||||
<numeric-input v-model.number="generator.variants" class="dark_bordered" min="1" step="1" style="width: 70px;" />
|
||||
<numeric-input v-model.number="generator.variants" min="1" step="1" style="width: 70px;" />
|
||||
|
||||
<template v-if="generator.type == 'custom_model_data'">
|
||||
<label>${tl('dialog.predicate_overrides.start_value')}</label>
|
||||
<numeric-input v-model.number="generator.start_value" min="0" step="1" class="dark_bordered" style="width: 45px;" />
|
||||
<numeric-input v-model.number="generator.start_value" min="0" step="1" style="width: 45px;" />
|
||||
</template>
|
||||
|
||||
<label>${tl('dialog.predicate_overrides.model')}</label>
|
||||
|
@ -2085,7 +2085,7 @@ BARS.defineActions(function() {
|
||||
new Toggle('toggle_all_grids', {
|
||||
name: tl('settings.grids'),
|
||||
description: tl('settings.grids.desc'),
|
||||
icon: 'grid',
|
||||
icon: 'grid_on',
|
||||
category: 'view',
|
||||
linked_setting: 'grids',
|
||||
condition: () => !Modes.paint
|
||||
|
@ -820,6 +820,9 @@ const ReferenceImageMode = {
|
||||
})
|
||||
files.forEach(file => {
|
||||
let ref = new ReferenceImage({source: file.content, name: file.name});
|
||||
if (Format.image_editor) {
|
||||
ref.layer = 'viewport';
|
||||
}
|
||||
if (save_mode == 'project') {
|
||||
ref.addAsReference(true);
|
||||
} else {
|
||||
|
@ -111,14 +111,20 @@ Interface.definePanels(() => {
|
||||
})
|
||||
],
|
||||
onResize() {
|
||||
Interface.Panels.color.vue.width = 0;
|
||||
Panels.color.vue.width = 0;
|
||||
Vue.nextTick(() => {
|
||||
let disp_before = this.vue.$refs.square_picker.style.display;
|
||||
this.vue.$refs.square_picker.style.display = 'none';
|
||||
let max = this.isInSidebar()
|
||||
? 1000
|
||||
: Math.min(1000, (this.height - this.vue.$el.clientHeight - this.handle.clientHeight) * (this.vue.picker_type == 'box' ? 1.25 : 1));
|
||||
Interface.Panels.color.vue.width = Math.clamp(this.width, 100, max);
|
||||
Panels.color.vue.width = Math.clamp(this.width, 100, 1000);
|
||||
if (!this.isInSidebar()) {
|
||||
if (this.vue.picker_type == 'box') {
|
||||
let height = this.height - this.vue.$el.clientHeight - this.handle.clientHeight - 6;
|
||||
Panels.color.vue.picker_height = Math.clamp(height, 100, 1000);
|
||||
} else {
|
||||
let max = Math.min(1000, (this.height - this.vue.$el.clientHeight - this.handle.clientHeight) * (this.vue.picker_type == 'box' ? 1.25 : 1));
|
||||
Interface.Panels.color.vue.width = Math.clamp(this.width, 100, max);
|
||||
}
|
||||
}
|
||||
this.vue.$refs.square_picker.style.display = disp_before;
|
||||
Vue.nextTick(() => {
|
||||
$('#main_colorpicker').spectrum('reflow');
|
||||
@ -128,6 +134,7 @@ Interface.definePanels(() => {
|
||||
component: {
|
||||
data: {
|
||||
width: 100,
|
||||
picker_height: 100,
|
||||
open_tab: StateMemory.color_picker_tab || 'picker',
|
||||
picker_type: Settings.get('color_wheel') ? 'wheel' : 'box',
|
||||
main_color: '#ffffff',
|
||||
@ -152,10 +159,6 @@ Interface.definePanels(() => {
|
||||
history: (saved_colors && saved_colors.history instanceof Array) ? saved_colors.history : []
|
||||
},
|
||||
methods: {
|
||||
togglePickerType() {
|
||||
settings.color_wheel.set(!settings.color_wheel.value);
|
||||
Panels.color.onResize();
|
||||
},
|
||||
colorPickerMenu(event) {
|
||||
new Menu('color_picker_menu', [
|
||||
{
|
||||
@ -165,9 +168,11 @@ Interface.definePanels(() => {
|
||||
children: [
|
||||
{name: 'menu.color_picker.picker_type.square', icon: Settings.get('color_wheel') ? 'far.fa-circle' : 'far.fa-dot-circle', click: () => {
|
||||
settings.color_wheel.set(false);
|
||||
Panels.color.onResize();
|
||||
}},
|
||||
{name: 'menu.color_picker.picker_type.wheel', icon: Settings.get('color_wheel') ? 'far.fa-dot-circle' : 'far.fa-circle', click: () => {
|
||||
settings.color_wheel.set(true);
|
||||
Panels.color.onResize();
|
||||
}}
|
||||
]
|
||||
},
|
||||
@ -347,7 +352,7 @@ Interface.definePanels(() => {
|
||||
|
||||
</div>
|
||||
<div v-show="open_tab == 'picker' || open_tab == 'both'" @wheel="onMouseWheel($event)">
|
||||
<div v-show="picker_type == 'box'" ref="square_picker" :style="{maxWidth: width + 'px'}">
|
||||
<div v-show="picker_type == 'box'" ref="square_picker" :style="{maxWidth: width + 'px', '--height': picker_height + 'px'}">
|
||||
<input id="main_colorpicker">
|
||||
</div>
|
||||
<color-wheel v-if="picker_type == 'wheel' && width" :value="selected_color" @input="changeColor" :width="width" :height="width"></color-wheel>
|
||||
|
@ -11,9 +11,7 @@ const Painter = {
|
||||
if (!options.no_undo && !options.no_undo_init) {
|
||||
Undo.initEdit({textures: [texture], bitmap: true})
|
||||
}
|
||||
if (texture.mode === 'link') {
|
||||
texture.convertToInternal();
|
||||
}
|
||||
if (!texture.internal) texture.convertToInternal();
|
||||
|
||||
let edit_name = options.no_undo ? null : (options.edit_name || 'Edit texture');
|
||||
let {canvas, ctx, offset} = texture.getActiveCanvas();
|
||||
@ -2036,6 +2034,7 @@ SharedActions.add('paste', {
|
||||
|
||||
Undo.initEdit({textures: [texture], bitmap: true});
|
||||
if (!texture.layers_enabled) {
|
||||
texture.flags.add('temporary_layers');
|
||||
texture.activateLayers(false);
|
||||
}
|
||||
let offset = Clipbench.image ? [Math.clamp(Clipbench.image.x, 0, texture.width), Math.clamp(Clipbench.image.y, 0, texture.height)] : undefined;
|
||||
@ -2093,17 +2092,19 @@ SharedActions.add('duplicate', {
|
||||
copy_canvas.width = rect.width;
|
||||
copy_canvas.height = rect.height;
|
||||
|
||||
selection.maskCanvas(copy_ctx, offset);
|
||||
copy_ctx.drawImage(canvas, -rect.start_x, -rect.start_y);
|
||||
selection.maskCanvas(copy_ctx, [rect.start_x, rect.start_y]);
|
||||
copy_ctx.drawImage(canvas, -rect.start_x + offset[0], -rect.start_y + offset[1]);
|
||||
|
||||
canvas = copy_canvas;
|
||||
offset = [rect.start_x, rect.start_y];
|
||||
}
|
||||
|
||||
Undo.initEdit({textures: [texture], bitmap: true});
|
||||
if (!texture.layers_enabled) {
|
||||
texture.flags.add('temporary_layers');
|
||||
texture.activateLayers(false);
|
||||
}
|
||||
let new_layer = new TextureLayer({name: layer.name + ' - copy', offset}, texture);
|
||||
let new_layer = new TextureLayer({name: layer ? (layer.name + ' - copy') : 'selection', offset}, texture);
|
||||
let image_data = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
|
||||
new_layer.setSize(canvas.width, canvas.height);
|
||||
new_layer.ctx.putImageData(image_data, 0, 0);
|
||||
@ -2115,7 +2116,6 @@ SharedActions.add('duplicate', {
|
||||
Undo.finishEdit('Duplicate texture selection');
|
||||
updateInterfacePanels();
|
||||
BARS.updateConditions();
|
||||
|
||||
}
|
||||
})
|
||||
SharedActions.add('delete', {
|
||||
@ -2206,11 +2206,13 @@ BARS.defineActions(function() {
|
||||
} else if (before) {
|
||||
a = 0;
|
||||
}
|
||||
} else if (opacity < 1) {
|
||||
} else if (opacity < 1 || blend_mode != BlendModes.default) {
|
||||
let before = Painter.getAlphaMatrix(texture, px, py);
|
||||
let new_val = (before||0);
|
||||
if (before) {
|
||||
if (a > before) {
|
||||
a = Math.clamp(a, 0, (opacity - before) / (1 - before));
|
||||
} else if (before) {
|
||||
a = 0;
|
||||
}
|
||||
new_val = new_val + (1-new_val) * a;
|
||||
if (new_val > before || before == undefined) Painter.setAlphaMatrix(texture, px, py, new_val);
|
||||
|
@ -145,7 +145,7 @@ const TextureGenerator = {
|
||||
TextureGenerator.generateColorMapTemplate(options, makeTexture);
|
||||
} else {
|
||||
Undo.initEdit({textures: [], selected_texture: true})
|
||||
TextureGenerator.generateBlank(options.resolution[1], options.resolution[0], options.color, makeTexture)
|
||||
TextureGenerator.generateBlank(options.resolution[1], options.resolution[0], options.color, makeTexture);
|
||||
}
|
||||
},
|
||||
generateBlank(height, width, color, cb) {
|
||||
@ -158,8 +158,14 @@ const TextureGenerator = {
|
||||
ctx.fillStyle = new tinycolor(color).toRgbString();
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
}
|
||||
|
||||
cb(canvas.toDataURL())
|
||||
let texture = cb(canvas.toDataURL());
|
||||
texture.uv_width = width;
|
||||
texture.uv_height = height;
|
||||
if (Format.per_texture_uv_size) {
|
||||
Project.texture_width = width;
|
||||
Project.texture_height = height;
|
||||
}
|
||||
return texture;
|
||||
},
|
||||
//constructors
|
||||
boxUVCubeTemplate: function(obj, min_size) {
|
||||
@ -1717,10 +1723,10 @@ const TextureGenerator = {
|
||||
changeUVResolution(width, height, texture) {
|
||||
let factor_x = width / Project.getUVWidth(texture);
|
||||
let factor_y = height / Project.getUVHeight(texture);
|
||||
if (!Format.per_texture_uv_size) {
|
||||
Project.texture_width = width;
|
||||
Project.texture_height = height;
|
||||
}
|
||||
|
||||
Project.texture_width = width;
|
||||
Project.texture_height = height;
|
||||
|
||||
if (texture) {
|
||||
texture.uv_width = width;
|
||||
texture.uv_height = height;
|
||||
|
@ -1276,11 +1276,13 @@ class Texture {
|
||||
// Nothing
|
||||
} else if (formResult.fill === 'repeat' && Format.animated_textures && formResult.size[0] < formResult.size[1]) {
|
||||
// Animated
|
||||
} else if ((Format.single_texture || Texture.all.length == 1)) {
|
||||
} else if (Format.single_texture || Texture.all.length == 1 || Format.per_texture_uv_size) {
|
||||
|
||||
if (Format.per_texture_uv_size) {
|
||||
this.uv_width = Project.texture_width * (formResult.size[0] / old_width);
|
||||
this.uv_height = Project.texture_height * (formResult.size[1] / old_height);
|
||||
scope.uv_width = scope.uv_width * (formResult.size[0] / old_width);
|
||||
scope.uv_height = scope.uv_height * (formResult.size[1] / old_height);
|
||||
Project.texture_width = scope.uv_width;
|
||||
Project.texture_height = scope.uv_height;
|
||||
} else {
|
||||
Undo.current_save.uv_mode = {
|
||||
box_uv: Project.box_uv,
|
||||
@ -1663,6 +1665,7 @@ class Texture {
|
||||
}
|
||||
}
|
||||
updateChangesAfterEdit() {
|
||||
if (!this.internal) this.convertToInternal();
|
||||
if (this.layers_enabled) {
|
||||
this.updateLayerChanges(true);
|
||||
} else {
|
||||
@ -1700,17 +1703,14 @@ class Texture {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
edit(cb, options) {
|
||||
var scope = this;
|
||||
if (!options) options = false;
|
||||
|
||||
edit(cb, options = 0) {
|
||||
if (cb) {
|
||||
Painter.edit(scope, cb, options);
|
||||
Painter.edit(this, cb, options);
|
||||
|
||||
} else if (scope.mode === 'link') {
|
||||
} else if (this.mode === 'link') {
|
||||
this.convertToInternal();
|
||||
}
|
||||
scope.saved = false;
|
||||
this.saved = false;
|
||||
}
|
||||
}
|
||||
Texture.prototype.menu = new Menu([
|
||||
|
@ -2102,7 +2102,7 @@ Interface.definePanels(function() {
|
||||
: Math.floor(Math.clamp(UVEditor.panel.width - 8, 64, 1e5));
|
||||
this.width = size;
|
||||
if (Format.image_editor) {
|
||||
this.height = Interface.center_screen.clientHeight - 38;
|
||||
this.height = Interface.preview.clientHeight - 38;
|
||||
if (Blockbench.isMobile) {
|
||||
let panel = Interface.getBottomPanel();
|
||||
if (panel) this.height -= panel.height;
|
||||
@ -3762,7 +3762,7 @@ Interface.definePanels(function() {
|
||||
<template v-for="element in getDisplayedUVElements()">
|
||||
|
||||
<template v-if="element.type == 'cube' && !element.box_uv">
|
||||
<div class="cube_uv_face"
|
||||
<div class="cube_uv_face uv_face"
|
||||
v-for="(face, key) in element.faces" :key="element.uuid + ':' + key"
|
||||
v-if="(face.getTexture() == texture || texture == 0) && face.texture !== null && (display_uv !== 'selected_faces' || selected_faces.includes(key))"
|
||||
:title="face_names[key]"
|
||||
@ -3799,7 +3799,7 @@ Interface.definePanels(function() {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-else-if="element.type == 'cube'" class="cube_box_uv"
|
||||
<div v-else-if="element.type == 'cube'" class="cube_box_uv uv_face"
|
||||
:key="element.uuid"
|
||||
@mousedown.prevent="dragFace(null, $event)"
|
||||
@touchstart.prevent="dragFace(null, $event)"
|
||||
@ -3814,7 +3814,7 @@ Interface.definePanels(function() {
|
||||
</div>
|
||||
|
||||
<template v-if="element.type == 'mesh'">
|
||||
<div class="mesh_uv_face"
|
||||
<div class="mesh_uv_face uv_face"
|
||||
v-for="(face, key) in filterMeshFaces(element.faces)" :key="element.uuid + ':' + key"
|
||||
v-if="face.vertices.length > 2 && (display_uv !== 'selected_faces' || selected_faces.includes(key)) && face.getTexture() == texture"
|
||||
:class="{selected: selected_faces.includes(key)}"
|
||||
|
@ -14,7 +14,7 @@
|
||||
"sizes": "1024x1024"
|
||||
},
|
||||
{
|
||||
"src": "icon_full.png",
|
||||
"src": "icon_maskable.png",
|
||||
"type": "image/png",
|
||||
"sizes": "256x256",
|
||||
"purpose": "maskable"
|
||||
|
Loading…
x
Reference in New Issue
Block a user