diff --git a/index.html b/index.html
index 34937a2a..a0846194 100644
--- a/index.html
+++ b/index.html
@@ -104,8 +104,10 @@
-
+
+
+
diff --git a/js/io/codec.js b/js/io/codec.js
new file mode 100644
index 00000000..5885baac
--- /dev/null
+++ b/js/io/codec.js
@@ -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');
+ }
+ }
+}
diff --git a/js/io/format.js b/js/io/format.js
new file mode 100644
index 00000000..7f913a93
--- /dev/null
+++ b/js/io/format.js
@@ -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
+ })
+})
diff --git a/js/io/formats/bedrock.js b/js/io/formats/bedrock.js
index e9548891..be1a0644 100644
--- a/js/io/formats/bedrock.js
+++ b/js/io/formats/bedrock.js
@@ -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,
diff --git a/js/io/formats/bedrock_old.js b/js/io/formats/bedrock_old.js
index 336670d7..a858cc80 100644
--- a/js/io/formats/bedrock_old.js
+++ b/js/io/formats/bedrock_old.js
@@ -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,
diff --git a/js/io/io.js b/js/io/io.js
index c06b2b38..728fb0eb 100644
--- a/js/io/io.js
+++ b/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',