blockbench/js/io/formats/bedrock_old.js
JannisX11 e3ac34f4c5 Fix typo in splash screen
Fix Update Notification button not working
Split event for new project / setup project
Fix issue where deleting theme files would cause error pop up on start
Fix issue with field in texture generator dialog toggling on input
(caused by underlying bug in Condition system)
Fix wrong icon in "Display UV" option
Fix new cubes not updating position
2021-10-20 22:55:54 +02:00

505 lines
13 KiB
JavaScript

(function() {
function parseGeometry(data) {
if (data === undefined) {
pe_list_data.forEach(function(s) {
if (s.selected === true) {
data = s
}
})
if (data == undefined) {
data = pe_list_data[0]
}
}
codec.dispatchEvent('parse', {model: data.object});
Project.geometry_name = data.name.replace(/^geometry\./, '');
Project.texture_width = data.object.texturewidth || 64;
Project.texture_height = data.object.textureheight || 64;
if (typeof data.object.visible_bounds_width == 'number' && typeof data.object.visible_bounds_height == 'number') {
Project.visible_box[0] = Math.max(Project.visible_box[0], data.object.visible_bounds_width || 0);
Project.visible_box[1] = Math.max(Project.visible_box[1], data.object.visible_bounds_height || 0);
if (data.object.visible_bounds_offset && typeof data.object.visible_bounds_offset[1] == 'number') {
Project.visible_box[2] = data.object.visible_bounds_offset[1] || 0;
}
}
var bones = {}
if (data.object.bones) {
var included_bones = []
data.object.bones.forEach(function(b) {
included_bones.push(b.name)
})
data.object.bones.forEach(function(b, bi) {
var group = new Group({
name: b.name,
origin: b.pivot,
rotation: b.rotation,
material: b.material,
color: Group.all.length%8
}).init()
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: b.name, autouv: 0, color: group.color})
if (s.origin) {
base_cube.from.V3_set(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, rotation;
if (b.locators[key] instanceof Array) {
coords = b.locators[key];
} else {
coords = b.locators[key].offset;
rotation = b.locators[key].rotation;
}
coords[0] *= -1
var locator = new Locator({from: coords, name: key, rotation}).addTo(group).init();
}
}
var parent_group = 'root';
if (b.parent) {
if (bones[b.parent]) {
parent_group = bones[b.parent]
} else {
data.object.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)
})
}
codec.dispatchEvent('parsed', {model: data.object});
pe_list_data.length = 0;
hideDialog()
loadTextureDraggable()
Canvas.updateAllBones()
setProjectTitle()
if (isApp && Project.geometry_name) {
Project.BedrockEntityManager.initEntity()
}
updateSelection()
}
var codec = new Codec('bedrock_old', {
name: 'Bedrock Entity Model',
extension: 'json',
remember: true,
load_filter: {
type: 'json',
extensions: ['json'],
condition(model) {
return (model.format_version && compareVersions('1.12.0', model.format_version)) ||
Object.keys(model).find(s => s.match(/^geometry\./));
}
},
compile(options) {
if (options === undefined) options = {}
var entitymodel = {}
entitymodel.texturewidth = Project.texture_width;
entitymodel.textureheight = Project.texture_height;
var bones = []
var visible_box = new THREE.Box3()
var groups = getAllGroups();
var loose_elements = [];
Outliner.root.forEach(obj => {
if (obj.type === 'cube' || obj.type == 'locator') {
loose_elements.push(obj)
}
})
if (loose_elements.length) {
let group = new Group({
name: 'bb_main'
});
group.children.push(...loose_elements);
group.is_catch_bone = true;
group.createUniqueName();
groups.splice(0, 0, group);
}
groups.forEach(function(g) {
if (g.type !== 'group') return;
if (!settings.export_empty_groups.value && !g.children.find(child => child.export)) 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 && Project.box_uv) bone.mirror = true;
if (g.material) bone.material = g.material;
//Elements
var cubes = []
var locators = {};
for (var obj of g.children) {
if (obj.export) {
if (obj instanceof Cube) {
var template = new oneLiner()
template.origin = obj.from.slice()
template.size = obj.size()
template.origin[0] = -(template.origin[0] + template.size[0])
template.uv = obj.uv_offset
if (obj.inflate && typeof obj.inflate === 'number') {
template.inflate = obj.inflate
}
if (obj.mirror_uv === !bone.mirror) {
template.mirror = obj.mirror_uv
}
//Visible Bounds
var mesh = obj.mesh
if (mesh) {
visible_box.expandByObject(mesh)
}
cubes.push(template)
} else if (obj instanceof Locator) {
locators[obj.name] = obj.from.slice();
locators[obj.name][0] *= -1;
}
}
}
if (cubes.length) {
bone.cubes = cubes
}
if (Object.keys(locators).length) {
bone.locators = locators
}
bones.push(bone)
})
if (bones.length && options.visible_box !== false) {
let visible_box = calculateVisibleBox();
entitymodel.visible_bounds_width = visible_box[0] || 0;
entitymodel.visible_bounds_height = visible_box[1] || 0;
entitymodel.visible_bounds_offset = [0, visible_box[2] || 0, 0]
}
if (bones.length) {
entitymodel.bones = bones
}
this.dispatchEvent('compile', {model: entitymodel, options});
if (options.raw) {
return entitymodel
} else {
var model_name = 'geometry.' + (Project.geometry_name||'unknown')
return autoStringify({
format_version: '1.10.0',
[model_name]: entitymodel
})
}
},
parse(data, path) {
pe_list_data.length = 0
var geometries = []
for (var key in data) {
if (typeof data[key] === 'object') {
geometries.push(key);
}
}
if (geometries.length === 1) {
parseGeometry({object: data[geometries[0]], name: geometries[0]})
return;
}
$('#pe_search_bar').val('')
if (pe_list && pe_list._data) {
pe_list._data.search_term = ''
}
function create_thumbnail(model_entry, isize) {
var included_bones = []
model_entry.object.bones.forEach(function(b) {
included_bones.push(b.name)
})
new Jimp(48, 48, 0x00000000, function(err, image) {
model_entry.object.bones.forEach(function(b) {
var rotation = b.rotation
if (!rotation || rotation[0] === undefined) {
if (entityMode.hardcodes[model_entry.name] && entityMode.hardcodes[model_entry.name][b.name]) {
rotation = entityMode.hardcodes[model_entry.name][b.name].rotation
}
}
if (b.cubes) {
b.cubes.forEach(function(c) {
if (c.origin && c.size) {
//Do cube
var inflate = c.inflate||0
var coords = {
x: (c.origin[2]-inflate)*isize+24,
y: 40-(c.origin[1]+c.size[1]+inflate)*isize,
w: (c.size[2]+2*inflate)*isize,
h: (c.size[1]+2*inflate)*isize
}
var shade = (limitNumber(c.origin[0], -24, 24)+24)/48*255
var color = parseInt('0xffffff'+shade.toString(16))
coords.x = limitNumber(coords.x, 0, 47)
coords.y = limitNumber(coords.y, 0, 47)
coords.w = limitNumber(coords.w, 0, 47 - coords.x)
coords.h = limitNumber(coords.h, 0, 47 - coords.y)
if (coords.h > 0 && coords.w > 0) {
if (rotation && rotation[0] !== 0 && b.pivot) {
Painter.drawRotatedRectangle(
image,
0xffffff88,
coords,
b.pivot[2]*isize+24,
40-b.pivot[1]*isize,
-rotation[0]
)
} else {
Painter.drawRectangle(image, 0xffffff88, coords)
}
}
}
})
}
})
//Send
image.getBase64("image/png", function(a, dataUrl){
model_entry.icon = dataUrl
})
})
}
for (var key in data) {
if (key.includes('geometry.') && data.hasOwnProperty(key)) {
var base_model = {name: key, bonecount: 0, cubecount: 0, selected: false, object: data[key], icon: false}
var oversize = 2;
var words = key.replace(/:.*/g, '').replace('geometry.', '').split(/[\._]/g)
words.forEach(function(w, wi) {
words[wi] = capitalizeFirstLetter(w)
})
base_model.title = words.join(' ')
if (data[key].bones) {
base_model.bonecount = data[key].bones.length
data[key].bones.forEach(function(b) {
if (b.cubes) {
base_model.cubecount += b.cubes.length
b.cubes.forEach(function(c) {
if (c.origin && c.size && (c.origin[2] < -12 || c.origin[2] + c.size[2] > 12 || c.origin[1] + c.size[1] > 22) && oversize === 2) oversize = 1
if (c.origin && c.size && (c.origin[2] < -24 || c.origin[2] + c.size[2] > 24)) oversize = 0.5
})
}
})
if (typeof base_model.cubecount !== 'number') {
base_model.cubecount = '[E]'
} else if (base_model.cubecount > 0) {
create_thumbnail(base_model, oversize)
}
}
pe_list_data.push(base_model)
}
}
if (pe_list == undefined) {
pe_list = new Vue({
el: '#pe_list',
data: {
search_term: '',
list: pe_list_data
},
methods: {
selectE: function(item, event) {
var index = pe_list_data.indexOf(item)
pe_list_data.forEach(function(s) {
s.selected = false;
})
pe_list_data[index].selected = true
},
open() {
parseGeometry()
},
tl
},
computed: {
searched() {
return this.list.filter(item => {
return item.name.toUpperCase().includes(this.search_term)
})
}
}
})
}
showDialog('entity_import')
$('#pe_list').css('max-height', (window.innerHeight - 320) +'px')
$('input#pe_search_bar').select()
$('#entity_import .confirm_btn').off('click')
$('#entity_import .confirm_btn').on('click', (e) => {
parseGeometry()
})
},
export() {
var scope = this;
Blockbench.export({
resource_id: 'model',
type: this.name,
extensions: [this.extension],
name: this.fileName(),
startpath: this.startPath(),
content: this.compile({raw: isApp}),
custom_writer: isApp ? (a, path) => scope.overwrite(a, path, () => scope.afterSave(path)) : null,
})
},
overwrite(content, path, cb) {
var model_name = 'geometry.' + (Project.geometry_name.replace(/^geometry\./, '')||'unknown')
var data;
try {
data = fs.readFileSync(path, 'utf-8')
} catch (err) {}
var obj = {
format_version: '1.10.0'
}
if (data) {
try {
obj = autoParseJSON(data, false)
} catch (err) {
err = err+''
var answer = electron.dialog.showMessageBoxSync(currentwindow, {
type: 'warning',
buttons: [
tl('message.bedrock_overwrite_error.backup_overwrite'),
tl('message.bedrock_overwrite_error.overwrite'),
tl('dialog.cancel')
],
title: 'Blockbench',
message: tl('message.bedrock_overwrite_error.message'),
detail: err,
noLink: false
})
if (answer === 0) {
var backup_file_name = pathToName(path, true) + ' backup ' + new Date().toLocaleString().split(':').join('_')
backup_file_name = path.replace(pathToName(path, false), backup_file_name)
fs.writeFile(backup_file_name, data, function (err2) {
if (err2) {
console.log('Error saving backup model: ', err2)
}
})
}
if (answer === 2) {
return;
}
}
if (typeof obj === 'object') {
for (var key in obj) {
if (obj.hasOwnProperty(key) &&
obj[key].bones &&
typeof obj[key].bones === 'object' &&
obj[key].bones.constructor.name === 'Array'
) {
obj[key].bones.forEach(function(bone) {
if (typeof bone.cubes === 'object' &&
bone.cubes.constructor.name === 'Array'
) {
bone.cubes.forEach(function(c, ci) {
bone.cubes[ci] = new oneLiner(c)
})
}
})
}
}
}
}
obj[model_name] = this.compile({raw: true});
content = autoStringify(obj);
Blockbench.writeFile(path, {content}, cb);
}
})
var format = new ModelFormat({
id: 'bedrock_old',
extension: 'json',
icon: 'icon-format_bedrock_legacy',
show_on_start_screen: false,
box_uv: true,
single_texture: true,
bone_rig: true,
centered_grid: true,
animated_textures: true,
animation_files: true,
animation_mode: true,
locators: true,
codec,
})
//Object.defineProperty(format, 'single_texture', {get: _ => !settings.layered_textures.value})
codec.format = format;
BARS.defineActions(function() {
codec.export_action = new Action({
id: 'export_entity',
icon: format.icon,
category: 'file',
condition: () => Format == format,
click: function () {
codec.export()
}
})
})
})()