mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-04-06 17:31:09 +08:00
Merge branch 'patch' into vite
This commit is contained in:
commit
fdd15ce9bb
@ -80,17 +80,22 @@ export class Toolbar {
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Builds the toolbar from data
|
||||
* @param {object} data Data used to build the toolbar
|
||||
* @param {boolean} force If true, customization data will be ignored. Used when resetting toolbar
|
||||
*/
|
||||
build(data, force) {
|
||||
var scope = this;
|
||||
//Items
|
||||
this.children.length = 0;
|
||||
var items = data.children
|
||||
if (!force && BARS.stored[scope.id] && typeof BARS.stored[scope.id] === 'object') {
|
||||
items = BARS.stored[scope.id]
|
||||
if (!force && BARS.stored[this.id] && typeof BARS.stored[this.id] === 'object') {
|
||||
items = BARS.stored[this.id];
|
||||
if (data.children) {
|
||||
// Add new actions to existing toolbars
|
||||
// Add new actions (newly added via bb update) to existing toolbars
|
||||
data.children.forEach((key, index) => {
|
||||
if (typeof key == 'string' && key.length > 1 && !items.includes(key) && !Keybinds.stored[key] && BarItems[key]) {
|
||||
if (typeof key == 'string' && key.length > 1 && !items.includes(key) && !Keybinds.stored[key] && BARS.stored._known?.includes(key) == false && BarItems[key]) {
|
||||
// Figure out best index based on item before. Otherwise use index from original array
|
||||
let prev_index = items.indexOf(data.children[index-1]);
|
||||
if (prev_index != -1) index = prev_index+1;
|
||||
@ -100,7 +105,7 @@ export class Toolbar {
|
||||
}
|
||||
}
|
||||
if (items && items instanceof Array) {
|
||||
var content = $(scope.node).find('div.content')
|
||||
var content = $(this.node).find('div.content')
|
||||
content.children().detach()
|
||||
for (var itemPosition = 0; itemPosition < items.length; itemPosition++) {
|
||||
let item = items[itemPosition];
|
||||
@ -112,7 +117,10 @@ export class Toolbar {
|
||||
|
||||
continue;
|
||||
}
|
||||
if (typeof item == 'string') item = BarItems[item]
|
||||
if (typeof item == 'string') {
|
||||
BARS.stored._known?.safePush(item);
|
||||
item = BarItems[item];
|
||||
}
|
||||
|
||||
if (item) {
|
||||
item.pushToolbar(this);
|
||||
@ -127,8 +135,8 @@ export class Toolbar {
|
||||
}
|
||||
}
|
||||
}
|
||||
$(scope.node).toggleClass('no_wrap', this.no_wrap)
|
||||
$(scope.node).toggleClass('vertical', this.vertical)
|
||||
$(this.node).toggleClass('no_wrap', this.no_wrap)
|
||||
$(this.node).toggleClass('vertical', this.vertical)
|
||||
if (data.default_place) {
|
||||
this.toPlace(this.id)
|
||||
}
|
||||
@ -294,7 +302,10 @@ export class Toolbar {
|
||||
}
|
||||
})
|
||||
BARS.stored[this.id] = arr;
|
||||
if (arr.equals(this.default_children)) {
|
||||
let identical_to_default = this.default_children.length == arr.length && this.default_children.allAre((item, i) => {
|
||||
return arr[i] == item || (typeof arr[i] == 'string' && arr[i].startsWith(item));
|
||||
})
|
||||
if (identical_to_default) {
|
||||
delete BARS.stored[this.id];
|
||||
}
|
||||
// Temporary fix
|
||||
@ -325,7 +336,9 @@ Toolbar.prototype.menu = new Menu([
|
||||
])
|
||||
|
||||
export const BARS = {
|
||||
stored: {},
|
||||
stored: {
|
||||
_known: []
|
||||
},
|
||||
editing_bar: undefined,
|
||||
action_definers: [],
|
||||
condition: Condition,
|
||||
@ -687,6 +700,9 @@ export const BARS = {
|
||||
stored = JSON.parse(stored)
|
||||
if (typeof stored === 'object') {
|
||||
BARS.stored = stored;
|
||||
if (!BARS.stored._known) {
|
||||
BARS.stored._known = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -808,9 +824,6 @@ export const BARS = {
|
||||
}
|
||||
})
|
||||
}
|
||||
Blockbench.onUpdateTo('4.4.0-beta.0', () => {
|
||||
delete BARS.stored.brush;
|
||||
})
|
||||
Toolbars.brush = new Toolbar({
|
||||
id: 'brush',
|
||||
no_wrap: true,
|
||||
|
@ -262,7 +262,7 @@ var codec = new Codec('project', {
|
||||
if (Animation.all.length) {
|
||||
model.animations = [];
|
||||
Animation.all.forEach(a => {
|
||||
model.animations.push(a.getUndoCopy({bone_names: true, absolute_paths: options.absolute_paths}, true))
|
||||
model.animations.push(a.getUndoCopy({absolute_paths: options.absolute_paths}, true))
|
||||
})
|
||||
}
|
||||
if (AnimationController.all.length) {
|
||||
|
143
js/io/io.js
143
js/io/io.js
@ -487,149 +487,6 @@ export const Extruder = {
|
||||
Undo.finishEdit('Add extruded texture', {elements: selected, outliner: true, textures: [Texture.all[Texture.all.length-1]]})
|
||||
}
|
||||
}
|
||||
//Json
|
||||
export function compileJSON(object, options = {}) {
|
||||
let indentation = options.indentation;
|
||||
if (typeof indentation !== 'string') {
|
||||
switch (settings.json_indentation.value) {
|
||||
case 'spaces_4': indentation = ' '; break;
|
||||
case 'spaces_2': indentation = ' '; break;
|
||||
case 'tabs': default: indentation = '\t'; break;
|
||||
}
|
||||
}
|
||||
function newLine(tabs) {
|
||||
if (options.small === true) {return '';}
|
||||
let s = '\n';
|
||||
for (let i = 0; i < tabs; i++) {
|
||||
s += indentation;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function escape(string) {
|
||||
return string.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n|\r\n/g, '\\n').replace(/\t/g, '\\t')
|
||||
}
|
||||
function handleVar(o, tabs, breaks = true) {
|
||||
var out = ''
|
||||
if (typeof o === 'string') {
|
||||
//String
|
||||
out += '"' + escape(o) + '"'
|
||||
} else if (typeof o === 'boolean') {
|
||||
//Boolean
|
||||
out += (o ? 'true' : 'false')
|
||||
} else if (o === null || o === Infinity || o === -Infinity) {
|
||||
//Null
|
||||
out += 'null'
|
||||
} else if (typeof o === 'number') {
|
||||
//Number
|
||||
o = (Math.round(o*100000)/100000).toString()
|
||||
out += o
|
||||
} else if (o instanceof Array) {
|
||||
//Array
|
||||
let has_content = false
|
||||
let multiline = !!o.find(item => typeof item === 'object');
|
||||
if (!multiline) {
|
||||
let length = 0;
|
||||
o.forEach(item => {
|
||||
length += typeof item === 'string' ? (item.length+4) : 3;
|
||||
});
|
||||
if (length > 140) multiline = true;
|
||||
}
|
||||
out += '['
|
||||
for (var i = 0; i < o.length; i++) {
|
||||
var compiled = handleVar(o[i], tabs+1)
|
||||
if (compiled) {
|
||||
if (has_content) {out += ',' + ((options.small || multiline) ? '' : ' ')}
|
||||
if (multiline) {out += newLine(tabs)}
|
||||
out += compiled
|
||||
has_content = true
|
||||
}
|
||||
}
|
||||
if (multiline) {out += newLine(tabs-1)}
|
||||
out += ']'
|
||||
} else if (typeof o === 'object') {
|
||||
//Object
|
||||
breaks = breaks && o.constructor.name !== 'oneLiner';
|
||||
var has_content = false
|
||||
out += '{'
|
||||
for (var key in o) {
|
||||
if (o.hasOwnProperty(key)) {
|
||||
var compiled = handleVar(o[key], tabs+1, breaks)
|
||||
if (compiled) {
|
||||
if (has_content) {out += ',' + (breaks || options.small?'':' ')}
|
||||
if (breaks) {out += newLine(tabs)}
|
||||
out += '"' + escape(key) + '":' + (options.small === true ? '' : ' ')
|
||||
out += compiled
|
||||
has_content = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (breaks && has_content) {out += newLine(tabs-1)}
|
||||
out += '}'
|
||||
}
|
||||
return out;
|
||||
}
|
||||
let file = handleVar(object, 1);
|
||||
if ((settings.final_newline.value && options.final_newline != false) || options.final_newline == true) {
|
||||
file += '\n';
|
||||
}
|
||||
return file;
|
||||
}
|
||||
export function autoParseJSON(data, feedback) {
|
||||
if (data.substr(0, 4) === '<lz>') {
|
||||
data = LZUTF8.decompress(data.substr(4), {inputEncoding: 'StorageBinaryString'})
|
||||
}
|
||||
if (data.charCodeAt(0) === 0xFEFF) {
|
||||
data = data.substr(1)
|
||||
}
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (err1) {
|
||||
data = data.replace(/\/\*[^(\*\/)]*\*\/|\/\/.*/g, '')
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (err) {
|
||||
if (feedback === false) return;
|
||||
if (data.match(/\n\r?[><]{7}/)) {
|
||||
Blockbench.showMessageBox({
|
||||
title: 'message.invalid_file.title',
|
||||
icon: 'fab.fa-git-alt',
|
||||
message: 'message.invalid_file.merge_conflict'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let error_part = '';
|
||||
function logErrantPart(whole, start, length) {
|
||||
var line = whole.substr(0, start).match(/\n/gm)
|
||||
line = line ? line.length+1 : 1
|
||||
var result = '';
|
||||
var lines = whole.substr(start, length).split(/\n/gm)
|
||||
lines.forEach((s, i) => {
|
||||
result += `#${line+i} ${s}\n`
|
||||
})
|
||||
error_part = result.substr(0, result.length-1) + ' <-- HERE';
|
||||
console.log(error_part);
|
||||
}
|
||||
console.error(err)
|
||||
var length = err.toString().split('at position ')[1]
|
||||
if (length) {
|
||||
length = parseInt(length)
|
||||
var start = limitNumber(length-32, 0, Infinity)
|
||||
|
||||
logErrantPart(data, start, 1+length-start)
|
||||
} else if (err.toString().includes('Unexpected end of JSON input')) {
|
||||
|
||||
logErrantPart(data, data.length-16, 10)
|
||||
}
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_file',
|
||||
icon: 'error',
|
||||
message: tl('message.invalid_file.message', [err]) + (error_part ? `\n\n\`\`\`\n${error_part}\n\`\`\`` : '')
|
||||
})
|
||||
return;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
BARS.defineActions(function() {
|
||||
|
@ -20,6 +20,7 @@ import "./preview/OrbitControls"
|
||||
|
||||
import './languages'
|
||||
import "./util/util"
|
||||
import "./util/json"
|
||||
import "./util/three_custom"
|
||||
import "./util/math_util"
|
||||
import "./util/array_util"
|
||||
|
161
js/util/json.js
Normal file
161
js/util/json.js
Normal file
@ -0,0 +1,161 @@
|
||||
export function compileJSON(object, options = {}) {
|
||||
let indentation = options.indentation;
|
||||
if (typeof indentation !== 'string') {
|
||||
switch (settings.json_indentation.value) {
|
||||
case 'spaces_4': indentation = ' '; break;
|
||||
case 'spaces_2': indentation = ' '; break;
|
||||
case 'tabs': default: indentation = '\t'; break;
|
||||
}
|
||||
}
|
||||
function newLine(tabs) {
|
||||
if (options.small === true) {return '';}
|
||||
let s = '\n';
|
||||
for (let i = 0; i < tabs; i++) {
|
||||
s += indentation;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function escape(string) {
|
||||
if (string.includes('\\')) {
|
||||
string = string.replace(/\\/g, '\\\\');
|
||||
}
|
||||
if (string.includes('"')) {
|
||||
string = string.replace(/"/g, '\\"');
|
||||
}
|
||||
if (string.includes('\n')) {
|
||||
string = string.replace(/\n|\r\n/g, '\\n');
|
||||
}
|
||||
if (string.includes('\t')) {
|
||||
string = string.replace(/\t/g, '\\t');
|
||||
}
|
||||
return string;
|
||||
}
|
||||
function handleVar(o, tabs, breaks = true) {
|
||||
var out = ''
|
||||
let type = typeof o;
|
||||
if (type === 'string') {
|
||||
//String
|
||||
out += '"' + escape(o) + '"'
|
||||
} else if (type === 'boolean') {
|
||||
//Boolean
|
||||
out += (o ? 'true' : 'false')
|
||||
} else if (o === null || o === Infinity || o === -Infinity) {
|
||||
//Null
|
||||
out += 'null'
|
||||
} else if (type === 'number') {
|
||||
//Number
|
||||
o = (Math.round(o*100000)/100000).toString()
|
||||
if (o == 'NaN') o = null
|
||||
out += o
|
||||
} else if (o instanceof Array) {
|
||||
//Array
|
||||
let has_content = false
|
||||
let multiline = !!o.find(item => typeof item === 'object');
|
||||
if (!multiline) {
|
||||
let length = 0;
|
||||
o.forEach(item => {
|
||||
length += typeof item === 'string' ? (item.length+4) : 3;
|
||||
});
|
||||
if (length > 140) multiline = true;
|
||||
}
|
||||
out += '['
|
||||
for (var i = 0; i < o.length; i++) {
|
||||
var compiled = handleVar(o[i], tabs+1)
|
||||
if (compiled) {
|
||||
if (has_content) {out += ',' + ((options.small || multiline) ? '' : ' ')}
|
||||
if (multiline) {out += newLine(tabs)}
|
||||
out += compiled
|
||||
has_content = true
|
||||
}
|
||||
}
|
||||
if (multiline) {out += newLine(tabs-1)}
|
||||
out += ']'
|
||||
} else if (type === 'object') {
|
||||
//Object
|
||||
breaks = breaks && o.constructor.name !== 'oneLiner';
|
||||
var has_content = false
|
||||
out += '{'
|
||||
for (var key in o) {
|
||||
if (o.hasOwnProperty(key)) {
|
||||
var compiled = handleVar(o[key], tabs+1, breaks)
|
||||
if (compiled) {
|
||||
if (has_content) {out += ',' + (breaks || options.small?'':' ')}
|
||||
if (breaks) {out += newLine(tabs)}
|
||||
out += '"' + escape(key) + '":' + (options.small === true ? '' : ' ')
|
||||
out += compiled
|
||||
has_content = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (breaks && has_content) {out += newLine(tabs-1)}
|
||||
out += '}'
|
||||
}
|
||||
return out;
|
||||
}
|
||||
let file = handleVar(object, 1);
|
||||
if ((settings.final_newline.value && options.final_newline != false) || options.final_newline == true) {
|
||||
file += '\n';
|
||||
}
|
||||
return file;
|
||||
}
|
||||
export function autoParseJSON(data, feedback) {
|
||||
if (data.substr(0, 4) === '<lz>') {
|
||||
data = LZUTF8.decompress(data.substr(4), {inputEncoding: 'StorageBinaryString'})
|
||||
}
|
||||
if (data.charCodeAt(0) === 0xFEFF) {
|
||||
data = data.substr(1)
|
||||
}
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (err1) {
|
||||
data = data.replace(/\/\*[^(\*\/)]*\*\/|\/\/.*/g, '')
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (err) {
|
||||
if (feedback === false) return;
|
||||
if (data.match(/\n\r?[><]{7}/)) {
|
||||
Blockbench.showMessageBox({
|
||||
title: 'message.invalid_file.title',
|
||||
icon: 'fab.fa-git-alt',
|
||||
message: 'message.invalid_file.merge_conflict'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let error_part = '';
|
||||
function logErrantPart(whole, start, length) {
|
||||
var line = whole.substr(0, start).match(/\n/gm)
|
||||
line = line ? line.length+1 : 1
|
||||
var result = '';
|
||||
var lines = whole.substr(start, length).split(/\n/gm)
|
||||
lines.forEach((s, i) => {
|
||||
result += `#${line+i} ${s}\n`
|
||||
})
|
||||
error_part = result.substr(0, result.length-1) + ' <-- HERE';
|
||||
console.log(error_part);
|
||||
}
|
||||
console.error(err)
|
||||
var length = err.toString().split('at position ')[1]
|
||||
if (length) {
|
||||
length = parseInt(length)
|
||||
var start = limitNumber(length-32, 0, Infinity)
|
||||
|
||||
logErrantPart(data, start, 1+length-start)
|
||||
} else if (err.toString().includes('Unexpected end of JSON input')) {
|
||||
|
||||
logErrantPart(data, data.length-16, 10)
|
||||
}
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_file',
|
||||
icon: 'error',
|
||||
message: tl('message.invalid_file.message', [err]) + (error_part ? `\n\n\`\`\`\n${error_part}\n\`\`\`` : '')
|
||||
})
|
||||
return;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
Object.assign(window, {
|
||||
compileJSON,
|
||||
autoParseJSON,
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user