mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-04-06 17:31:09 +08:00
Refactor codec, format and IO files
Add new format property animation_files
This commit is contained in:
parent
000823d1f1
commit
274334b111
@ -104,8 +104,10 @@
|
||||
<script src="js/animations/timeline.js"></script>
|
||||
<script src="js/plugin_loader.js"></script>
|
||||
|
||||
<script src="js/io/io.js"></script>
|
||||
<script src="js/io/format.js"></script>
|
||||
<script src="js/io/codec.js"></script>
|
||||
<script src="js/io/project.js"></script>
|
||||
<script src="js/io/io.js"></script>
|
||||
<script src="js/io/formats/bbmodel.js"></script>
|
||||
<script src="js/io/formats/java_block.js"></script>
|
||||
<script src="js/io/formats/bedrock.js"></script>
|
||||
|
212
js/io/codec.js
Normal file
212
js/io/codec.js
Normal file
@ -0,0 +1,212 @@
|
||||
const Codecs = {};
|
||||
class Codec {
|
||||
constructor(id, data) {
|
||||
if (!data) data = 0;
|
||||
this.id = id;
|
||||
Codecs[id] = this;
|
||||
this.name = data.name || 'Unknown Format';
|
||||
this.events = {};
|
||||
Merge.function(this, data, 'load');
|
||||
Merge.function(this, data, 'compile');
|
||||
Merge.function(this, data, 'parse');
|
||||
Merge.function(this, data, 'write');
|
||||
Merge.function(this, data, 'overwrite');
|
||||
Merge.function(this, data, 'export');
|
||||
Merge.function(this, data, 'fileName');
|
||||
Merge.function(this, data, 'afterSave');
|
||||
Merge.function(this, data, 'afterDownload');
|
||||
Merge.string(this, data, 'extension');
|
||||
Merge.boolean(this, data, 'remember');
|
||||
this.load_filter = data.load_filter;
|
||||
this.export_action = data.export_action;
|
||||
}
|
||||
//Import
|
||||
load(model, file, add) {
|
||||
if (!this.parse) return false;
|
||||
if (!add) {
|
||||
newProject(this.format)
|
||||
}
|
||||
if (file.path && isApp && this.remember && !file.no_file ) {
|
||||
var name = pathToName(file.path, true);
|
||||
ModelMeta.name = pathToName(name, false);
|
||||
ModelMeta.export_path = file.path;
|
||||
addRecentProject({
|
||||
name,
|
||||
path: file.path,
|
||||
icon: Format.icon
|
||||
})
|
||||
}
|
||||
this.parse(model, file.path)
|
||||
}
|
||||
//parse(model, path)
|
||||
|
||||
//Export
|
||||
compile() {
|
||||
this.dispatchEvent('compile', {content: ''})
|
||||
return '';
|
||||
}
|
||||
export() {
|
||||
var scope = this;
|
||||
Blockbench.export({
|
||||
resource_id: 'model',
|
||||
type: scope.name,
|
||||
extensions: [scope.extension],
|
||||
name: scope.fileName(),
|
||||
startpath: scope.startPath(),
|
||||
content: scope.compile(),
|
||||
custom_writer: isApp ? (a, b) => scope.write(a, b) : null,
|
||||
}, path => scope.afterDownload(path))
|
||||
}
|
||||
fileName() {
|
||||
return ModelMeta.name||Project.name||'model';
|
||||
}
|
||||
startPath() {
|
||||
return ModelMeta.export_path;
|
||||
}
|
||||
write(content, path) {
|
||||
var scope = this;
|
||||
if (fs.existsSync(path) && this.overwrite) {
|
||||
this.overwrite(content, path, path => scope.afterSave(path))
|
||||
} else {
|
||||
Blockbench.writeFile(path, {content}, path => scope.afterSave(path));
|
||||
}
|
||||
}
|
||||
//overwrite(content, path, cb)
|
||||
afterDownload(path) {
|
||||
if (this.remember) {
|
||||
Prop.project_saved = true;
|
||||
}
|
||||
Blockbench.showQuickMessage(tl('message.save_file', [path ? pathToName(path, true) : this.fileName()]));
|
||||
}
|
||||
afterSave(path) {
|
||||
var name = pathToName(path, true)
|
||||
if (Format.codec == this || this.id == 'project') {
|
||||
if (this.id == 'project') {
|
||||
ModelMeta.save_path = path;
|
||||
} else {
|
||||
ModelMeta.export_path = path;
|
||||
}
|
||||
ModelMeta.name = pathToName(path, false);
|
||||
Prop.project_saved = true;
|
||||
}
|
||||
if (this.remember) {
|
||||
addRecentProject({
|
||||
name,
|
||||
path: path,
|
||||
icon: this.id == 'project' ? 'icon-blockbench_file' : Format.icon
|
||||
});
|
||||
}
|
||||
Blockbench.showQuickMessage(tl('message.save_file', [name]));
|
||||
}
|
||||
//Events
|
||||
dispatchEvent(event_name, data) {
|
||||
var list = this.events[event_name]
|
||||
if (!list) return;
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
if (typeof list[i] === 'function') {
|
||||
list[i](data)
|
||||
}
|
||||
}
|
||||
}
|
||||
on(event_name, cb) {
|
||||
if (!this.events[event_name]) {
|
||||
this.events[event_name] = []
|
||||
}
|
||||
this.events[event_name].safePush(cb)
|
||||
}
|
||||
//Delete
|
||||
delete() {
|
||||
delete Codecs[this.id];
|
||||
if (this.format && this.format.codec == this) delete this.format.codec;
|
||||
}
|
||||
}
|
||||
Codec.getAllExtensions = function() {
|
||||
let extensions = [];
|
||||
for (var id in Codecs) {
|
||||
if (Codecs[id].load_filter && Codecs[id].load_filter.extensions) {
|
||||
extensions.safePush(...Codecs[id].load_filter.extensions);
|
||||
}
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
|
||||
//Import
|
||||
function setupDragHandlers() {
|
||||
Blockbench.addDragHandler(
|
||||
'model',
|
||||
{extensions: Codec.getAllExtensions},
|
||||
function(files) {
|
||||
loadModelFile(files[0])
|
||||
}
|
||||
)
|
||||
Blockbench.addDragHandler(
|
||||
'style',
|
||||
{extensions: ['bbstyle', 'bbtheme']},
|
||||
function(files) {
|
||||
CustomTheme.import(files[0]);
|
||||
}
|
||||
)
|
||||
Blockbench.addDragHandler(
|
||||
'plugin',
|
||||
{extensions: ['bbplugin', 'js']},
|
||||
function(files) {
|
||||
new Plugin().loadFromFile(files[0], true)
|
||||
}
|
||||
)
|
||||
Blockbench.addDragHandler(
|
||||
'texture',
|
||||
{extensions: ['png', 'tga'], propagate: true, readtype: 'image'},
|
||||
function(files, event) {
|
||||
var texture_li = $(event.target).parents('li.texture')
|
||||
if (texture_li.length) {
|
||||
var tex = textures.findInArray('uuid', texture_li.attr('texid'))
|
||||
if (tex) {
|
||||
tex.fromFile(files[0])
|
||||
TickUpdates.selection = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
files.forEach(function(f) {
|
||||
new Texture().fromFile(f).add().fillParticle()
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
function loadModelFile(file) {
|
||||
if (showSaveDialog()) {
|
||||
resetProject();
|
||||
|
||||
(function() {
|
||||
var extension = pathToExtension(file.path);
|
||||
// Text
|
||||
for (var id in Codecs) {
|
||||
let codec = Codecs[id];
|
||||
if (codec.load_filter && codec.load_filter.type == 'text') {
|
||||
if (codec.load_filter.extensions.includes(extension) && Condition(codec.load_filter.condition, file.content)) {
|
||||
codec.load(file.content, file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// JSON
|
||||
var model = autoParseJSON(file.content);
|
||||
for (var id in Codecs) {
|
||||
let codec = Codecs[id];
|
||||
if (codec.load_filter && codec.load_filter.type == 'json') {
|
||||
if (codec.load_filter.extensions.includes(extension) && Condition(codec.load_filter.condition, model)) {
|
||||
codec.load(model, file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
EditSession.initNewModel()
|
||||
if (!Format) {
|
||||
Modes.options.start.select()
|
||||
Modes.vue.$forceUpdate()
|
||||
Blockbench.dispatchEvent('close_project');
|
||||
}
|
||||
}
|
||||
}
|
231
js/io/format.js
Normal file
231
js/io/format.js
Normal file
@ -0,0 +1,231 @@
|
||||
var Format = 0;
|
||||
const Formats = {};
|
||||
const ModelMeta = {
|
||||
save_path: '',
|
||||
export_path: '',
|
||||
animation_path: '',
|
||||
_name: '',
|
||||
get name() {return this._name},
|
||||
set name(name) {
|
||||
this._name = name;
|
||||
Project.name = this._name;
|
||||
setProjectTitle(this._name)
|
||||
},
|
||||
get saved() {return Prop.project_saved},
|
||||
set saved(s) {Prop.project_saved = !!s},
|
||||
}
|
||||
|
||||
//Formats
|
||||
class ModelFormat {
|
||||
constructor(data) {
|
||||
Formats[data.id] = this;
|
||||
this.id = data.id;
|
||||
this.name = data.name || tl('format.'+this.id);
|
||||
this.description = data.description || tl('format.'+this.id+'.desc');
|
||||
this.show_on_start_screen = true;
|
||||
|
||||
this.box_uv = false;
|
||||
this.optional_box_uv = false;
|
||||
this.single_texture = false;
|
||||
this.animated_textures = false;
|
||||
this.bone_rig = false;
|
||||
this.centered_grid = false;
|
||||
this.rotate_cubes = false;
|
||||
this.integer_size = false;
|
||||
this.locators = false;
|
||||
this.canvas_limit = false;
|
||||
this.rotation_limit = false;
|
||||
this.uv_rotation = false;
|
||||
this.animation_files = false;
|
||||
this.display_mode = false;
|
||||
this.animation_mode = false;
|
||||
|
||||
this.codec = data.codec;
|
||||
this.onActivation = data.onActivation;
|
||||
this.onDeactivation = data.onDeactivation;
|
||||
Merge.string(this, data, 'icon');
|
||||
Merge.boolean(this, data, 'show_on_start_screen');
|
||||
|
||||
Merge.boolean(this, data, 'box_uv');
|
||||
Merge.boolean(this, data, 'optional_box_uv');
|
||||
Merge.boolean(this, data, 'single_texture');
|
||||
Merge.boolean(this, data, 'animated_textures');
|
||||
Merge.boolean(this, data, 'bone_rig');
|
||||
Merge.boolean(this, data, 'centered_grid');
|
||||
Merge.boolean(this, data, 'rotate_cubes');
|
||||
Merge.boolean(this, data, 'integer_size');
|
||||
Merge.boolean(this, data, 'locators');
|
||||
Merge.boolean(this, data, 'canvas_limit');
|
||||
Merge.boolean(this, data, 'rotation_limit');
|
||||
Merge.boolean(this, data, 'uv_rotation');
|
||||
Merge.boolean(this, data, 'animation_files');
|
||||
Merge.boolean(this, data, 'display_mode');
|
||||
Merge.boolean(this, data, 'animation_mode');
|
||||
}
|
||||
select(converting) {
|
||||
if (Format && typeof Format.onDeactivation == 'function') {
|
||||
Format.onDeactivation()
|
||||
}
|
||||
Format = this;
|
||||
if (typeof this.onActivation == 'function') {
|
||||
Format.onActivation()
|
||||
}
|
||||
if (!converting || !this.optional_box_uv) {
|
||||
Project.box_uv = Format.box_uv;
|
||||
}
|
||||
buildGrid()
|
||||
if (Format.centered_grid) {
|
||||
scene.position.set(0, 0, 0);
|
||||
} else {
|
||||
scene.position.set(-8, -8, -8);
|
||||
}
|
||||
Preview.all.forEach(preview => {
|
||||
if (preview.isOrtho && typeof preview.angle == 'number') {
|
||||
preview.loadAnglePreset(DefaultCameraPresets[preview.angle+1])
|
||||
}
|
||||
})
|
||||
uv_dialog.all_editors.forEach(editor => {
|
||||
editor.img.style.objectFit = Format.animated_textures ? 'cover' : 'fill';
|
||||
})
|
||||
for (var key in ModelProject.properties) {
|
||||
if (Project[key] == undefined) {
|
||||
ModelProject.properties[key].reset(Project);
|
||||
}
|
||||
}
|
||||
updateSelection()
|
||||
Modes.vue.$forceUpdate()
|
||||
updateInterfacePanels()
|
||||
updateShading();
|
||||
Canvas.updateRenderSides()
|
||||
return this;
|
||||
}
|
||||
new() {
|
||||
if (newProject(this)) {
|
||||
BarItems.project_window.click();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
convertTo() {
|
||||
|
||||
Undo.history.length = 0;
|
||||
Undo.index = 0;
|
||||
ModelMeta.export_path = '';
|
||||
|
||||
var old_format = Format
|
||||
this.select(true)
|
||||
Modes.options.edit.select()
|
||||
|
||||
//Bone Rig
|
||||
if (!Format.bone_rig && old_format.bone_rig) {
|
||||
Group.all.forEach(group => {
|
||||
group.rotation.V3_set(0, 0, 0);
|
||||
})
|
||||
}
|
||||
if (Format.bone_rig && !old_format.bone_rig) {
|
||||
var loose_stuff = []
|
||||
Outliner.root.forEach(el => {
|
||||
if (el instanceof Group == false) {
|
||||
loose_stuff.push(el)
|
||||
}
|
||||
})
|
||||
if (loose_stuff.length) {
|
||||
var root_group = new Group().init().addTo()
|
||||
loose_stuff.forEach(el => {
|
||||
el.addTo(root_group)
|
||||
})
|
||||
}
|
||||
if (!Project.geometry_name && Project.name) {
|
||||
Project.geometry_name = Project.name;
|
||||
}
|
||||
}
|
||||
if (Format.bone_rig) {
|
||||
Group.all.forEach(group => {
|
||||
group.createUniqueName();
|
||||
})
|
||||
}
|
||||
|
||||
//Rotate Cubes
|
||||
if (!Format.rotate_cubes && old_format.rotate_cubes) {
|
||||
Cube.all.forEach(cube => {
|
||||
cube.rotation.V3_set(0, 0, 0)
|
||||
})
|
||||
}
|
||||
|
||||
//Locators
|
||||
if (!Format.locators && old_format.locators) {
|
||||
Locator.all.slice().forEach(locator => {
|
||||
locator.remove()
|
||||
})
|
||||
}
|
||||
|
||||
//Canvas Limit
|
||||
if (Format.canvas_limit && !old_format.canvas_limit && !settings.deactivate_size_limit.value) {
|
||||
|
||||
Cube.all.forEach(function(s, i) {
|
||||
//Push elements into 3x3 block box
|
||||
[0, 1, 2].forEach(function(ax) {
|
||||
var overlap = s.to[ax] + s.inflate - 32
|
||||
if (overlap > 0) {
|
||||
//If positive site overlaps
|
||||
s.from[ax] -= overlap
|
||||
s.to[ax] -= overlap
|
||||
|
||||
if (16 + s.from[ax] - s.inflate < 0) {
|
||||
s.from[ax] = -16 + s.inflate
|
||||
}
|
||||
} else {
|
||||
overlap = s.from[ax] - s.inflate + 16
|
||||
if (overlap < 0) {
|
||||
s.from[ax] -= overlap
|
||||
s.to[ax] -= overlap
|
||||
|
||||
if (s.to[ax] + s.inflate > 32) {
|
||||
s.to[ax] = 32 - s.inflate
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//Rotation Limit
|
||||
if (Format.rotation_limit && !old_format.rotation_limit && Format.rotate_cubes) {
|
||||
Cube.all.forEach(cube => {
|
||||
if (!cube.rotation.allEqual(0)) {
|
||||
var axis = (cube.rotation_axis && getAxisNumber(cube.rotation_axis)) || 0;
|
||||
var angle = limitNumber( Math.round(cube.rotation[axis]/22.5)*22.5, -45, 45 );
|
||||
cube.rotation.V3_set(0, 0, 0)
|
||||
cube.rotation[axis] = angle;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Animation Mode
|
||||
if (!Format.animation_mode && old_format.animation_mode) {
|
||||
Animator.animations.length = 0;
|
||||
}
|
||||
Canvas.updateAllPositions()
|
||||
Canvas.updateAllBones()
|
||||
Canvas.updateAllFaces()
|
||||
updateSelection()
|
||||
EditSession.initNewModel()
|
||||
}
|
||||
delete() {
|
||||
delete Formats[this.id];
|
||||
if (this.codec && this.codec.format == this) delete this.codec.format;
|
||||
}
|
||||
}
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new ModelFormat({
|
||||
id: 'free',
|
||||
icon: 'icon-format_free',
|
||||
rotate_cubes: true,
|
||||
bone_rig: true,
|
||||
centered_grid: true,
|
||||
optional_box_uv: true,
|
||||
uv_rotation: true,
|
||||
animation_mode: true,
|
||||
codec: Codecs.project
|
||||
})
|
||||
})
|
@ -899,6 +899,7 @@ var format = new ModelFormat({
|
||||
bone_rig: true,
|
||||
centered_grid: true,
|
||||
animated_textures: true,
|
||||
animation_files: true,
|
||||
animation_mode: true,
|
||||
locators: true,
|
||||
codec,
|
||||
|
@ -476,6 +476,7 @@ var format = new ModelFormat({
|
||||
bone_rig: true,
|
||||
centered_grid: true,
|
||||
animated_textures: true,
|
||||
animation_files: true,
|
||||
animation_mode: true,
|
||||
locators: true,
|
||||
codec,
|
||||
|
360
js/io/io.js
360
js/io/io.js
@ -1,351 +1,3 @@
|
||||
var Format = 0;
|
||||
const Formats = {};
|
||||
const ModelMeta = {
|
||||
save_path: '',
|
||||
export_path: '',
|
||||
animation_path: '',
|
||||
_name: '',
|
||||
get name() {return this._name},
|
||||
set name(name) {
|
||||
this._name = name;
|
||||
Project.name = this._name;
|
||||
setProjectTitle(this._name)
|
||||
},
|
||||
get saved() {return Prop.project_saved},
|
||||
set saved(s) {Prop.project_saved = !!s},
|
||||
}
|
||||
|
||||
//Formats
|
||||
class ModelFormat {
|
||||
constructor(data) {
|
||||
Formats[data.id] = this;
|
||||
this.id = data.id;
|
||||
this.name = data.name || tl('format.'+this.id);
|
||||
this.description = data.description || tl('format.'+this.id+'.desc');
|
||||
this.show_on_start_screen = true;
|
||||
|
||||
this.box_uv = false;
|
||||
this.optional_box_uv = false;
|
||||
this.single_texture = false;
|
||||
this.animated_textures = false;
|
||||
this.bone_rig = false;
|
||||
this.centered_grid = false;
|
||||
this.rotate_cubes = false;
|
||||
this.integer_size = false;
|
||||
this.locators = false;
|
||||
this.canvas_limit = false;
|
||||
this.rotation_limit = false;
|
||||
this.uv_rotation = false;
|
||||
this.ro_mode = false;
|
||||
this.animation_mode = false;
|
||||
|
||||
this.codec = data.codec;
|
||||
this.onActivation = data.onActivation;
|
||||
this.onDeactivation = data.onDeactivation;
|
||||
Merge.string(this, data, 'icon');
|
||||
Merge.boolean(this, data, 'show_on_start_screen');
|
||||
|
||||
Merge.boolean(this, data, 'box_uv');
|
||||
Merge.boolean(this, data, 'optional_box_uv');
|
||||
Merge.boolean(this, data, 'single_texture');
|
||||
Merge.boolean(this, data, 'animated_textures');
|
||||
Merge.boolean(this, data, 'bone_rig');
|
||||
Merge.boolean(this, data, 'centered_grid');
|
||||
Merge.boolean(this, data, 'rotate_cubes');
|
||||
Merge.boolean(this, data, 'integer_size');
|
||||
Merge.boolean(this, data, 'locators');
|
||||
Merge.boolean(this, data, 'canvas_limit');
|
||||
Merge.boolean(this, data, 'rotation_limit');
|
||||
Merge.boolean(this, data, 'uv_rotation');
|
||||
Merge.boolean(this, data, 'display_mode');
|
||||
Merge.boolean(this, data, 'animation_mode');
|
||||
}
|
||||
select(converting) {
|
||||
if (Format && typeof Format.onDeactivation == 'function') {
|
||||
Format.onDeactivation()
|
||||
}
|
||||
Format = this;
|
||||
if (typeof this.onActivation == 'function') {
|
||||
Format.onActivation()
|
||||
}
|
||||
if (!converting || !this.optional_box_uv) {
|
||||
Project.box_uv = Format.box_uv;
|
||||
}
|
||||
buildGrid()
|
||||
if (Format.centered_grid) {
|
||||
scene.position.set(0, 0, 0);
|
||||
} else {
|
||||
scene.position.set(-8, -8, -8);
|
||||
}
|
||||
Preview.all.forEach(preview => {
|
||||
if (preview.isOrtho && typeof preview.angle == 'number') {
|
||||
preview.loadAnglePreset(DefaultCameraPresets[preview.angle+1])
|
||||
}
|
||||
})
|
||||
uv_dialog.all_editors.forEach(editor => {
|
||||
editor.img.style.objectFit = Format.animated_textures ? 'cover' : 'fill';
|
||||
})
|
||||
for (var key in ModelProject.properties) {
|
||||
if (Project[key] == undefined) {
|
||||
ModelProject.properties[key].reset(Project);
|
||||
}
|
||||
}
|
||||
updateSelection()
|
||||
Modes.vue.$forceUpdate()
|
||||
updateInterfacePanels()
|
||||
updateShading();
|
||||
Canvas.updateRenderSides()
|
||||
return this;
|
||||
}
|
||||
new() {
|
||||
if (newProject(this)) {
|
||||
BarItems.project_window.click();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
convertTo() {
|
||||
|
||||
Undo.history.length = 0;
|
||||
Undo.index = 0;
|
||||
ModelMeta.export_path = '';
|
||||
|
||||
var old_format = Format
|
||||
this.select(true)
|
||||
Modes.options.edit.select()
|
||||
|
||||
//Bone Rig
|
||||
if (!Format.bone_rig && old_format.bone_rig) {
|
||||
Group.all.forEach(group => {
|
||||
group.rotation.V3_set(0, 0, 0);
|
||||
})
|
||||
}
|
||||
if (Format.bone_rig && !old_format.bone_rig) {
|
||||
var loose_stuff = []
|
||||
Outliner.root.forEach(el => {
|
||||
if (el instanceof Group == false) {
|
||||
loose_stuff.push(el)
|
||||
}
|
||||
})
|
||||
if (loose_stuff.length) {
|
||||
var root_group = new Group().init().addTo()
|
||||
loose_stuff.forEach(el => {
|
||||
el.addTo(root_group)
|
||||
})
|
||||
}
|
||||
if (!Project.geometry_name && Project.name) {
|
||||
Project.geometry_name = Project.name;
|
||||
}
|
||||
}
|
||||
if (Format.bone_rig) {
|
||||
Group.all.forEach(group => {
|
||||
group.createUniqueName();
|
||||
})
|
||||
}
|
||||
|
||||
//Rotate Cubes
|
||||
if (!Format.rotate_cubes && old_format.rotate_cubes) {
|
||||
Cube.all.forEach(cube => {
|
||||
cube.rotation.V3_set(0, 0, 0)
|
||||
})
|
||||
}
|
||||
|
||||
//Locators
|
||||
if (!Format.locators && old_format.locators) {
|
||||
Locator.all.slice().forEach(locator => {
|
||||
locator.remove()
|
||||
})
|
||||
}
|
||||
|
||||
//Canvas Limit
|
||||
if (Format.canvas_limit && !old_format.canvas_limit && !settings.deactivate_size_limit.value) {
|
||||
|
||||
Cube.all.forEach(function(s, i) {
|
||||
//Push elements into 3x3 block box
|
||||
[0, 1, 2].forEach(function(ax) {
|
||||
var overlap = s.to[ax] + s.inflate - 32
|
||||
if (overlap > 0) {
|
||||
//If positive site overlaps
|
||||
s.from[ax] -= overlap
|
||||
s.to[ax] -= overlap
|
||||
|
||||
if (16 + s.from[ax] - s.inflate < 0) {
|
||||
s.from[ax] = -16 + s.inflate
|
||||
}
|
||||
} else {
|
||||
overlap = s.from[ax] - s.inflate + 16
|
||||
if (overlap < 0) {
|
||||
s.from[ax] -= overlap
|
||||
s.to[ax] -= overlap
|
||||
|
||||
if (s.to[ax] + s.inflate > 32) {
|
||||
s.to[ax] = 32 - s.inflate
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//Rotation Limit
|
||||
if (Format.rotation_limit && !old_format.rotation_limit && Format.rotate_cubes) {
|
||||
Cube.all.forEach(cube => {
|
||||
if (!cube.rotation.allEqual(0)) {
|
||||
var axis = (cube.rotation_axis && getAxisNumber(cube.rotation_axis)) || 0;
|
||||
var angle = limitNumber( Math.round(cube.rotation[axis]/22.5)*22.5, -45, 45 );
|
||||
cube.rotation.V3_set(0, 0, 0)
|
||||
cube.rotation[axis] = angle;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Animation Mode
|
||||
if (!Format.animation_mode && old_format.animation_mode) {
|
||||
Animator.animations.length = 0;
|
||||
}
|
||||
Canvas.updateAllPositions()
|
||||
Canvas.updateAllBones()
|
||||
Canvas.updateAllFaces()
|
||||
updateSelection()
|
||||
EditSession.initNewModel()
|
||||
}
|
||||
delete() {
|
||||
delete Formats[this.id];
|
||||
if (this.codec && this.codec.format == this) delete this.codec.format;
|
||||
}
|
||||
}
|
||||
const Codecs = {};
|
||||
class Codec {
|
||||
constructor(id, data) {
|
||||
if (!data) data = 0;
|
||||
this.id = id;
|
||||
Codecs[id] = this;
|
||||
this.name = data.name || 'Unknown Format';
|
||||
this.events = {};
|
||||
Merge.function(this, data, 'load');
|
||||
Merge.function(this, data, 'compile');
|
||||
Merge.function(this, data, 'parse');
|
||||
Merge.function(this, data, 'write');
|
||||
Merge.function(this, data, 'overwrite');
|
||||
Merge.function(this, data, 'export');
|
||||
Merge.function(this, data, 'fileName');
|
||||
Merge.function(this, data, 'afterSave');
|
||||
Merge.function(this, data, 'afterDownload');
|
||||
Merge.string(this, data, 'extension');
|
||||
Merge.boolean(this, data, 'remember');
|
||||
this.load_filter = data.load_filter;
|
||||
this.export_action = data.export_action;
|
||||
}
|
||||
//Import
|
||||
load(model, file, add) {
|
||||
if (!this.parse) return false;
|
||||
if (!add) {
|
||||
newProject(this.format)
|
||||
}
|
||||
if (file.path && isApp && this.remember && !file.no_file ) {
|
||||
var name = pathToName(file.path, true);
|
||||
ModelMeta.name = pathToName(name, false);
|
||||
ModelMeta.export_path = file.path;
|
||||
addRecentProject({
|
||||
name,
|
||||
path: file.path,
|
||||
icon: Format.icon
|
||||
})
|
||||
}
|
||||
this.parse(model, file.path)
|
||||
}
|
||||
//parse(model, path)
|
||||
|
||||
//Export
|
||||
compile() {
|
||||
this.dispatchEvent('compile', {content: ''})
|
||||
return '';
|
||||
}
|
||||
export() {
|
||||
var scope = this;
|
||||
Blockbench.export({
|
||||
resource_id: 'model',
|
||||
type: scope.name,
|
||||
extensions: [scope.extension],
|
||||
name: scope.fileName(),
|
||||
startpath: scope.startPath(),
|
||||
content: scope.compile(),
|
||||
custom_writer: isApp ? (a, b) => scope.write(a, b) : null,
|
||||
}, path => scope.afterDownload(path))
|
||||
}
|
||||
fileName() {
|
||||
return ModelMeta.name||Project.name||'model';
|
||||
}
|
||||
startPath() {
|
||||
return ModelMeta.export_path;
|
||||
}
|
||||
write(content, path) {
|
||||
var scope = this;
|
||||
if (fs.existsSync(path) && this.overwrite) {
|
||||
this.overwrite(content, path, path => scope.afterSave(path))
|
||||
} else {
|
||||
Blockbench.writeFile(path, {content}, path => scope.afterSave(path));
|
||||
}
|
||||
}
|
||||
//overwrite(content, path, cb)
|
||||
afterDownload(path) {
|
||||
if (this.remember) {
|
||||
Prop.project_saved = true;
|
||||
}
|
||||
Blockbench.showQuickMessage(tl('message.save_file', [path ? pathToName(path, true) : this.fileName()]));
|
||||
}
|
||||
afterSave(path) {
|
||||
var name = pathToName(path, true)
|
||||
if (Format.codec == this || this.id == 'project') {
|
||||
if (this.id == 'project') {
|
||||
ModelMeta.save_path = path;
|
||||
} else {
|
||||
ModelMeta.export_path = path;
|
||||
}
|
||||
ModelMeta.name = pathToName(path, false);
|
||||
Prop.project_saved = true;
|
||||
}
|
||||
if (this.remember) {
|
||||
addRecentProject({
|
||||
name,
|
||||
path: path,
|
||||
icon: this.id == 'project' ? 'icon-blockbench_file' : Format.icon
|
||||
});
|
||||
}
|
||||
Blockbench.showQuickMessage(tl('message.save_file', [name]));
|
||||
}
|
||||
//Events
|
||||
dispatchEvent(event_name, data) {
|
||||
var list = this.events[event_name]
|
||||
if (!list) return;
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
if (typeof list[i] === 'function') {
|
||||
list[i](data)
|
||||
}
|
||||
}
|
||||
}
|
||||
on(event_name, cb) {
|
||||
if (!this.events[event_name]) {
|
||||
this.events[event_name] = []
|
||||
}
|
||||
this.events[event_name].safePush(cb)
|
||||
}
|
||||
//Delete
|
||||
delete() {
|
||||
delete Codecs[this.id];
|
||||
if (this.format && this.format.codec == this) delete this.format.codec;
|
||||
}
|
||||
}
|
||||
Codec.getAllExtensions = function() {
|
||||
let extensions = [];
|
||||
for (var id in Codecs) {
|
||||
if (Codecs[id].load_filter && Codecs[id].load_filter.extensions) {
|
||||
extensions.safePush(...Codecs[id].load_filter.extensions);
|
||||
}
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
|
||||
//Import
|
||||
function setupDragHandlers() {
|
||||
Blockbench.addDragHandler(
|
||||
@ -818,18 +470,6 @@ function autoParseJSON(data, feedback) {
|
||||
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new ModelFormat({
|
||||
id: 'free',
|
||||
icon: 'icon-format_free',
|
||||
rotate_cubes: true,
|
||||
bone_rig: true,
|
||||
centered_grid: true,
|
||||
optional_box_uv: true,
|
||||
uv_rotation: true,
|
||||
animation_mode: true,
|
||||
codec: Codecs.project
|
||||
})
|
||||
|
||||
//Import
|
||||
new Action('open_model', {
|
||||
icon: 'assessment',
|
||||
|
Loading…
x
Reference in New Issue
Block a user