2019-07-18 00:02:07 +08:00
//Import
function setupDragHandlers ( ) {
Blockbench . addDragHandler (
'model' ,
2020-10-21 22:12:14 +08:00
{ extensions : Codec . getAllExtensions } ,
2019-07-18 00:02:07 +08:00
function ( files ) {
2021-08-19 05:49:18 +08:00
files . forEach ( file => {
loadModelFile ( file ) ;
} )
2019-07-18 00:02:07 +08:00
}
)
Blockbench . addDragHandler (
'style' ,
2021-09-08 19:04:14 +08:00
{ extensions : [ 'bbtheme' ] } ,
2019-07-18 00:02:07 +08:00
function ( files ) {
2019-12-16 03:04:31 +08:00
CustomTheme . import ( files [ 0 ] ) ;
2019-07-18 00:02:07 +08:00
}
)
2021-04-26 00:21:46 +08:00
Blockbench . addDragHandler (
'settings' ,
{ extensions : [ 'bbsettings' ] } ,
function ( files ) {
Settings . import ( files [ 0 ] ) ;
}
)
2019-07-18 00:02:07 +08:00
Blockbench . addDragHandler (
'plugin' ,
{ extensions : [ 'bbplugin' , 'js' ] } ,
function ( files ) {
2021-08-19 05:49:18 +08:00
files . forEach ( file => {
new Plugin ( ) . loadFromFile ( file , true ) ;
} )
2019-07-18 00:02:07 +08:00
}
)
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 ) {
2021-07-08 20:30:32 +08:00
var tex = Texture . all . findInArray ( 'uuid' , texture _li . attr ( 'texid' ) )
2019-07-18 00:02:07 +08:00
if ( tex ) {
tex . fromFile ( files [ 0 ] )
2020-03-11 05:19:17 +08:00
TickUpdates . selection = true ;
2019-07-18 00:02:07 +08:00
return ;
}
}
files . forEach ( function ( f ) {
new Texture ( ) . fromFile ( f ) . add ( ) . fillParticle ( )
} )
}
)
}
2021-08-19 05:49:18 +08:00
function loadModelFile ( file ) {
let existing _tab = isApp && ModelProject . all . find ( project => (
project . save _path == file . path || project . export _path == file . path
) )
if ( existing _tab ) {
existing _tab . select ( ) ;
return ;
}
let extension = pathToExtension ( file . path ) ;
// Text
for ( let 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
let model = autoParseJSON ( file . content ) ;
for ( let 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 ;
}
}
}
}
//Extruder
2019-07-18 00:02:07 +08:00
var Extruder = {
drawImage : function ( file ) {
Extruder . canvas = $ ( '#extrusion_canvas' ) . get ( 0 )
2021-06-25 00:56:32 +08:00
var ctx = Extruder . canvas . getContext ( '2d' )
2019-07-18 00:02:07 +08:00
setProgressBar ( 'extrusion_bar' , 0 )
$ ( '#scan_tolerance' ) . on ( 'input' , function ( ) {
$ ( '#scan_tolerance_label' ) . text ( $ ( this ) . val ( ) )
} )
showDialog ( 'image_extruder' )
Extruder . ext _img = new Image ( )
2020-11-08 03:48:58 +08:00
Extruder . ext _img . src = isApp ? file . path . replace ( /#/g , '%23' ) : file . content
2019-07-18 00:02:07 +08:00
Extruder . image _file = file
Extruder . ext _img . style . imageRendering = 'pixelated'
2021-06-25 00:56:32 +08:00
Extruder . canvas . style . imageRendering = 'pixelated'
2019-07-18 00:02:07 +08:00
Extruder . ext _img . onload = function ( ) {
2021-06-25 00:56:32 +08:00
let ratio = Extruder . ext _img . naturalWidth / Extruder . ext _img . naturalHeight ;
Extruder . canvas . width = 256 ;
Extruder . canvas . height = 256 / ratio ;
ctx . clearRect ( 0 , 0 , Extruder . canvas . width , Extruder . canvas . height ) ;
ctx . imageSmoothingEnabled = false ;
ctx . drawImage ( Extruder . ext _img , 0 , 0 , Extruder . canvas . width , Extruder . canvas . height ) ;
Extruder . width = Extruder . ext _img . naturalWidth ;
Extruder . height = Extruder . ext _img . naturalHeight ;
2019-07-18 00:02:07 +08:00
if ( Extruder . width > 128 ) return ;
var p = 0
ctx . beginPath ( ) ;
2021-06-25 00:56:32 +08:00
for ( var x = 0 ; x < Extruder . canvas . width ; x += 256 / Extruder . width ) {
2019-07-18 00:02:07 +08:00
ctx . moveTo ( 0.5 + x + p , p ) ;
ctx . lineTo ( 0.5 + x + p , 256 + p ) ;
}
2021-06-25 00:56:32 +08:00
for ( var x = 0 ; x < Extruder . canvas . height ; x += 256 / Extruder . width ) {
2019-07-18 00:02:07 +08:00
ctx . moveTo ( p , 0.5 + x + p ) ;
ctx . lineTo ( 256 + p , 0.5 + x + p ) ;
}
ctx . strokeStyle = "black" ;
ctx . stroke ( ) ;
}
//Grid
} ,
startConversion : function ( ) {
var scan _mode = $ ( 'select#scan_mode option:selected' ) . attr ( 'id' ) /*areas, lines, columns, pixels*/
var isNewProject = elements . length === 0 ;
var pixel _opacity _tolerance = parseInt ( $ ( '#scan_tolerance' ) . val ( ) )
//Undo
Undo . initEdit ( { elements : selected , outliner : true , textures : [ ] } )
var texture = new Texture ( ) . fromFile ( Extruder . image _file ) . add ( false ) . fillParticle ( )
//var ext_x, ext_y;
var ctx = Painter . getCanvas ( texture ) . getContext ( '2d' )
var c = document . createElement ( 'canvas' )
var ctx = c . getContext ( '2d' ) ;
c . width = Extruder . ext _img . naturalWidth ;
c . height = Extruder . ext _img . naturalHeight ;
ctx . drawImage ( Extruder . ext _img , 0 , 0 )
var image _data = ctx . getImageData ( 0 , 0 , c . width , c . height ) . data
var finished _pixels = { }
var cube _nr = 0 ;
var cube _name = texture . name . split ( '.' ) [ 0 ]
selected . empty ( )
//Scale Index
var scale _i = 1 ;
scale _i = 16 / Extruder . width ;
2021-06-25 00:56:32 +08:00
let uv _scale _x = Project . texture _width / Extruder . width ;
let uv _scale _y = Project . texture _height / Extruder . height ;
2019-07-18 00:02:07 +08:00
function isOpaquePixel ( px _x , px _y ) {
var opacity = image _data [ ( px _x + ctx . canvas . width * px _y ) * 4 + 3 ]
return Math . isBetween ( px _x , 0 , Extruder . width - 1 )
&& Math . isBetween ( px _y , 0 , Extruder . height - 1 )
&& opacity >= pixel _opacity _tolerance ;
}
function finishPixel ( x , y ) {
if ( finished _pixels [ x ] === undefined ) {
finished _pixels [ x ] = { }
}
finished _pixels [ x ] [ y ] = true
}
function isPixelFinished ( x , y ) {
return ( finished _pixels [ x ] !== undefined && finished _pixels [ x ] [ y ] === true )
}
//Scanning
let ext _y = 0 ;
while ( ext _y < Extruder . height ) {
let ext _x = 0 ;
while ( ext _x < Extruder . width ) {
if ( isPixelFinished ( ext _x , ext _y ) === false && isOpaquePixel ( ext _x , ext _y ) === true ) {
//Search From New Pixel
var loop = true ;
var rect = { x : ext _x , y : ext _y , x2 : ext _x , y2 : ext _y }
var safety _limit = 5000
//Expanding Loop
while ( loop === true && safety _limit ) {
var y _check , x _check , canExpandX , canExpandY ;
//Expand X
if ( scan _mode === 'areas' || scan _mode === 'lines' ) {
y _check = rect . y
x _check = rect . x2 + 1
canExpandX = true
while ( y _check <= rect . y2 ) {
//Check If Row is Free
if ( isOpaquePixel ( x _check , y _check ) === false || isPixelFinished ( x _check , y _check ) === true ) {
canExpandX = false ;
}
y _check += 1
}
if ( canExpandX === true ) {
rect . x2 += 1
}
} else {
canExpandX = false ;
}
//Expand Y
if ( scan _mode === 'areas' || scan _mode === 'columns' ) {
x _check = rect . x
y _check = rect . y2 + 1
canExpandY = true
while ( x _check <= rect . x2 ) {
//Check If Row is Free
if ( isOpaquePixel ( x _check , y _check ) === false || isPixelFinished ( x _check , y _check ) === true ) {
canExpandY = false
}
x _check += 1
}
if ( canExpandY === true ) {
rect . y2 += 1
}
} else {
canExpandY = false ;
}
//Conclusion
if ( canExpandX === false && canExpandY === false ) {
loop = false ;
}
safety _limit -- ;
}
//Draw Rectangle
var draw _x = rect . x
var draw _y = rect . y
while ( draw _y <= rect . y2 ) {
draw _x = rect . x
while ( draw _x <= rect . x2 ) {
finishPixel ( draw _x , draw _y )
draw _x ++ ;
}
draw _y ++ ;
}
var current _cube = new Cube ( {
name : cube _name + '_' + cube _nr ,
autouv : 0 ,
from : [ rect . x * scale _i , 0 , rect . y * scale _i ] ,
to : [ ( rect . x2 + 1 ) * scale _i , scale _i , ( rect . y2 + 1 ) * scale _i ] ,
faces : {
2021-06-25 00:56:32 +08:00
up : { uv : [ rect . x * uv _scale _x , rect . y * uv _scale _y , ( rect . x2 + 1 ) * uv _scale _x , ( rect . y2 + 1 ) * uv _scale _y ] , texture : texture } ,
down : { uv : [ rect . x * uv _scale _x , ( rect . y2 + 1 ) * uv _scale _y , ( rect . x2 + 1 ) * uv _scale _x , rect . y * uv _scale _y ] , texture : texture } ,
north : { uv : [ ( rect . x2 + 1 ) * uv _scale _x , rect . y * uv _scale _y , rect . x * uv _scale _x , ( rect . y + 1 ) * uv _scale _y ] , texture : texture } ,
south : { uv : [ rect . x * uv _scale _x , rect . y2 * uv _scale _y , ( rect . x2 + 1 ) * uv _scale _x , ( rect . y2 + 1 ) * uv _scale _y ] , texture : texture } ,
east : { uv : [ rect . x2 * uv _scale _x , rect . y * uv _scale _y , ( rect . x2 + 1 ) * uv _scale _x , ( rect . y2 + 1 ) * uv _scale _y ] , texture : texture , rotation : 90 } ,
west : { uv : [ rect . x * uv _scale _x , rect . y * uv _scale _y , ( rect . x + 1 ) * uv _scale _x , ( rect . y2 + 1 ) * uv _scale _y ] , texture : texture , rotation : 270 } ,
2019-07-18 00:02:07 +08:00
}
} ) . init ( )
selected . push ( current _cube )
cube _nr ++ ;
}
ext _x ++ ;
}
ext _y ++ ;
}
var group = new Group ( cube _name ) . init ( ) . addTo ( )
selected . forEach ( function ( s ) {
s . addTo ( group ) . init ( )
} )
2021-07-08 20:30:32 +08:00
Undo . finishEdit ( 'Add extruded texture' , { elements : selected , outliner : true , textures : [ Texture . all [ Texture . all . length - 1 ] ] } )
2019-07-18 00:02:07 +08:00
hideDialog ( )
}
}
//Export
function uploadSketchfabModel ( ) {
if ( elements . length === 0 ) {
return ;
}
var dialog = new Dialog ( {
id : 'sketchfab_uploader' ,
title : 'dialog.sketchfab_uploader.title' ,
width : 540 ,
form : {
2020-04-26 02:25:07 +08:00
token : { label : 'dialog.sketchfab_uploader.token' , value : settings . sketchfab _token . value , type : 'password' } ,
about _token : { type : 'info' , text : tl ( 'dialog.sketchfab_uploader.about_token' , [ '[sketchfab.com/settings/password](https://sketchfab.com/settings/password)' ] ) } ,
2019-07-18 00:02:07 +08:00
name : { label : 'dialog.sketchfab_uploader.name' } ,
description : { label : 'dialog.sketchfab_uploader.description' , type : 'textarea' } ,
tags : { label : 'dialog.sketchfab_uploader.tags' , placeholder : 'Tag1 Tag2' } ,
2020-03-05 03:56:17 +08:00
animations : { label : 'dialog.sketchfab_uploader.animations' , value : true , type : 'checkbox' , condition : ( Format . animation _mode && Animator . animations . length ) } ,
//color: {type: 'color', label: 'dialog.sketchfab_uploader.color'},
2019-12-16 03:04:31 +08:00
draft : { label : 'dialog.sketchfab_uploader.draft' , type : 'checkbox' } ,
// Category
2019-07-18 00:02:07 +08:00
divider : '_' ,
private : { label : 'dialog.sketchfab_uploader.private' , type : 'checkbox' } ,
password : { label : 'dialog.sketchfab_uploader.password' } ,
} ,
onConfirm : function ( formResult ) {
if ( formResult . token && ! formResult . name ) {
Blockbench . showQuickMessage ( 'message.sketchfab.name_or_token' , 1800 )
return ;
}
if ( ! formResult . tags . split ( ' ' ) . includes ( 'blockbench' ) ) {
formResult . tags += ' blockbench' ;
}
var data = new FormData ( )
data . append ( 'token' , formResult . token )
data . append ( 'name' , formResult . name )
data . append ( 'description' , formResult . description )
data . append ( 'tags' , formResult . tags )
2019-12-16 03:04:31 +08:00
data . append ( 'isPublished' , ! formResult . draft )
2020-03-05 03:56:17 +08:00
//data.append('background', JSON.stringify({color: formResult.color.toHexString()}))
2019-07-18 00:02:07 +08:00
data . append ( 'private' , formResult . private )
data . append ( 'password' , formResult . password )
data . append ( 'source' , 'blockbench' )
settings . sketchfab _token . value = formResult . token
2020-02-08 02:06:24 +08:00
Codecs . gltf . compile ( { animations : formResult . animations } , ( content ) => {
var blob = new Blob ( [ content ] , { type : "text/plain;charset=utf-8" } ) ;
var file = new File ( [ blob ] , 'model.gltf' )
2019-07-18 00:02:07 +08:00
data . append ( 'modelFile' , file )
$ . ajax ( {
url : 'https://api.sketchfab.com/v3/models' ,
data : data ,
cache : false ,
contentType : false ,
processData : false ,
type : 'POST' ,
success : function ( response ) {
Blockbench . showMessageBox ( {
title : tl ( 'message.sketchfab.success' ) ,
2020-01-24 01:53:36 +08:00
message :
2020-03-05 03:56:17 +08:00
` [ ${ formResult . name } on Sketchfab](https://sketchfab.com/models/ ${ response . uid } ) ` , //\n\n \n\n`+
2019-07-18 00:02:07 +08:00
icon : 'icon-sketchfab' ,
} )
} ,
error : function ( response ) {
Blockbench . showQuickMessage ( 'message.sketchfab.error' , 1500 )
console . error ( response ) ;
}
} )
} )
dialog . hide ( )
}
} )
dialog . show ( )
}
//Json
function compileJSON ( object , options ) {
if ( typeof options !== 'object' ) options = { }
function newLine ( tabs ) {
if ( options . small === true ) { return '' ; }
var s = '\n'
for ( var i = 0 ; i < tabs ; i ++ ) {
s += '\t'
}
return s ;
}
2021-01-20 00:59:17 +08:00
function escape ( string ) {
return string . replace ( /\\/g , '\\\\' ) . replace ( /"/g , '\\"' ) . replace ( /\n|\r\n/g , '\\n' ) . replace ( /\t/g , '\\t' )
}
2019-07-18 00:02:07 +08:00
function handleVar ( o , tabs ) {
var out = ''
if ( typeof o === 'string' ) {
//String
2021-01-20 00:59:17 +08:00
out += '"' + escape ( o ) + '"'
2019-07-18 00:02:07 +08:00
} else if ( typeof o === 'boolean' ) {
//Boolean
out += ( o ? 'true' : 'false' )
2020-08-05 22:39:26 +08:00
} else if ( o === null || o === Infinity || o === - Infinity ) {
//Null
out += 'null'
2019-07-18 00:02:07 +08:00
} else if ( typeof o === 'number' ) {
//Number
o = ( Math . round ( o * 100000 ) / 100000 ) . toString ( )
out += o
2021-09-21 00:45:02 +08:00
} else if ( o instanceof Array ) {
2019-07-18 00:02:07 +08:00
//Array
2021-09-21 00:45:02 +08:00
let has _content = false
let has _objects = ! ! o . find ( item => typeof item === 'object' ) ;
2019-07-18 00:02:07 +08:00
out += '['
for ( var i = 0 ; i < o . length ; i ++ ) {
var compiled = handleVar ( o [ i ] , tabs + 1 )
if ( compiled ) {
if ( has _content ) { out += ',' + ( breaks || options . small ? '' : ' ' ) }
2021-09-21 00:45:02 +08:00
if ( has _objects ) { out += newLine ( tabs ) }
2019-07-18 00:02:07 +08:00
out += compiled
has _content = true
}
}
2021-09-21 00:45:02 +08:00
if ( has _objects ) { out += newLine ( tabs - 1 ) }
2019-07-18 00:02:07 +08:00
out += ']'
} else if ( typeof o === 'object' ) {
//Object
var 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 )
if ( compiled ) {
if ( has _content ) { out += ',' + ( breaks || options . small ? '' : ' ' ) }
if ( breaks ) { out += newLine ( tabs ) }
2021-01-20 00:59:17 +08:00
out += '"' + escape ( key ) + '":' + ( options . small === true ? '' : ' ' )
2019-07-18 00:02:07 +08:00
out += compiled
has _content = true
}
}
}
if ( breaks && has _content ) { out += newLine ( tabs - 1 ) }
out += '}'
}
return out ;
}
return handleVar ( object , 1 )
}
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 ;
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 `
} )
console . log ( result . substr ( 0 , result . length - 1 ) + ' <-- HERE' )
}
console . error ( err )
var length = err . toString ( ) . split ( 'at position ' ) [ 1 ]
if ( length ) {
length = parseInt ( length )
var start = limitNumber ( length - 20 , 0 , Infinity )
logErrantPart ( data , start , 1 + length - start )
} else if ( err . toString ( ) . includes ( 'Unexpected end of JSON input' ) ) {
logErrantPart ( data , data . length - 10 , 10 )
}
Blockbench . showMessageBox ( {
translateKey : 'invalid_file' ,
icon : 'error' ,
message : tl ( 'message.invalid_file.message' , [ err ] )
} )
return ;
}
}
return data ;
}
BARS . defineActions ( function ( ) {
//Import
2019-08-18 00:26:14 +08:00
new Action ( 'open_model' , {
2019-07-18 00:02:07 +08:00
icon : 'assessment' ,
category : 'file' ,
2021-02-20 18:58:53 +08:00
keybind : new Keybind ( { key : 'o' , ctrl : true } ) ,
2019-07-18 00:02:07 +08:00
click : function ( ) {
2020-01-24 01:53:36 +08:00
var startpath ;
if ( isApp && recent _projects && recent _projects . length ) {
startpath = recent _projects [ 0 ] . path ;
if ( typeof startpath == 'string' ) {
startpath = startpath . split ( osfs ) ;
startpath . pop ( ) ;
startpath = startpath . join ( osfs ) ;
}
}
2019-07-18 00:02:07 +08:00
Blockbench . import ( {
2020-04-26 02:25:07 +08:00
resource _id : 'model' ,
2020-10-21 22:12:14 +08:00
extensions : Codec . getAllExtensions ( ) ,
2020-01-24 01:53:36 +08:00
type : 'Model' ,
2021-08-27 17:41:26 +08:00
startpath ,
multiple : true
2019-07-18 00:02:07 +08:00
} , function ( files ) {
2021-08-27 17:41:26 +08:00
files . forEach ( file => {
loadModelFile ( file ) ;
} )
2019-07-18 00:02:07 +08:00
} )
}
} )
2021-08-18 05:28:15 +08:00
new Action ( 'open_from_link' , {
icon : 'link' ,
category : 'file' ,
click ( ) {
Blockbench . textPrompt ( 'action.open_from_link' , '' , link => {
if ( link . match ( /https:\/\/blckbn.ch\// ) || link . length == 4 ) {
let code = link . replace ( /[/]+/g , '' ) . substr ( - 4 ) ;
$ . getJSON ( ` https://blckbn.ch/api/models/ ${ code } ` , ( model ) => {
Codecs . project . load ( model , { path : '' } ) ;
} ) . fail ( error => {
Blockbench . showQuickMessage ( 'message.invalid_link' )
} )
2021-08-27 21:48:32 +08:00
} else {
$ . getJSON ( link , ( model ) => {
Codecs . project . load ( model , { path : '' } ) ;
} ) . fail ( error => {
Blockbench . showQuickMessage ( 'message.invalid_link' )
} )
2021-08-18 05:28:15 +08:00
}
} , 'https://blckbn.ch/1234' )
}
} )
2019-08-18 00:26:14 +08:00
new Action ( 'extrude_texture' , {
2019-07-18 00:02:07 +08:00
icon : 'eject' ,
category : 'file' ,
2021-06-17 19:34:11 +08:00
condition : _ => Format && ! Project . box _uv ,
2019-07-18 00:02:07 +08:00
click : function ( ) {
Blockbench . import ( {
2020-04-26 02:25:07 +08:00
resource _id : 'texture' ,
2019-07-18 00:02:07 +08:00
extensions : [ 'png' ] ,
type : 'PNG Texture' ,
readtype : 'image'
} , function ( files ) {
if ( files . length ) {
showDialog ( 'image_extruder' )
Extruder . drawImage ( files [ 0 ] )
}
} )
}
} )
//Export
2019-08-18 00:26:14 +08:00
new Action ( 'export_over' , {
2019-07-18 00:02:07 +08:00
icon : 'save' ,
category : 'file' ,
2021-02-20 18:58:53 +08:00
keybind : new Keybind ( { key : 's' , ctrl : true } ) ,
2019-07-18 00:02:07 +08:00
click : function ( ) {
if ( isApp ) {
saveTextures ( )
2020-07-25 02:59:24 +08:00
if ( Format ) {
2021-05-05 19:54:41 +08:00
if ( Project . export _path && Format . codec && Format . codec . compile ) {
Format . codec . write ( Format . codec . compile ( ) , Project . export _path )
} else if ( Project . save _path ) {
Codecs . project . write ( Codecs . project . compile ( ) , Project . save _path ) ;
2021-04-13 02:58:33 +08:00
} else if ( Format . codec && Format . codec . export ) {
2019-07-18 00:02:07 +08:00
Format . codec . export ( )
2021-08-04 03:44:50 +08:00
} else {
Project . saved = true ;
2019-07-18 00:02:07 +08:00
}
}
2021-01-04 04:23:17 +08:00
if ( Format . animation _mode && Format . animation _files && Animation . all . length ) {
2020-09-28 04:11:37 +08:00
BarItems . save _all _animations . trigger ( ) ;
2019-07-18 00:02:07 +08:00
}
} else {
saveTextures ( )
2021-04-13 02:58:33 +08:00
if ( Format . codec && Format . codec . export ) {
2019-12-16 03:04:31 +08:00
Format . codec . export ( )
}
2019-07-18 00:02:07 +08:00
}
}
} )
2019-07-19 23:31:22 +08:00
if ( ! isApp ) {
2019-08-18 00:26:14 +08:00
new Action ( 'export_asset_archive' , {
2019-07-19 23:31:22 +08:00
icon : 'archive' ,
category : 'file' ,
condition : _ => Format && Format . codec ,
click : function ( ) {
var archive = new JSZip ( ) ;
var content = Format . codec . compile ( )
2020-03-05 03:56:17 +08:00
var name = ` ${ Format . codec . fileName ( ) } . ${ Format . codec . extension } `
archive . file ( name , content )
2021-07-08 20:30:32 +08:00
Texture . all . forEach ( tex => {
2019-07-19 23:31:22 +08:00
if ( tex . mode === 'bitmap' ) {
archive . file ( pathToName ( tex . name ) + '.png' , tex . source . replace ( 'data:image/png;base64,' , '' ) , { base64 : true } ) ;
}
2019-07-18 00:02:07 +08:00
} )
2019-07-19 23:31:22 +08:00
archive . generateAsync ( { type : 'blob' } ) . then ( content => {
Blockbench . export ( {
type : 'Zip Archive' ,
extensions : [ 'zip' ] ,
name : 'assets' ,
2021-05-05 19:54:41 +08:00
startpath : Project . export _path ,
2019-07-19 23:31:22 +08:00
content : content ,
savetype : 'zip'
} )
2021-05-05 19:54:41 +08:00
Project . saved = true ;
2019-07-19 23:31:22 +08:00
} )
}
} )
}
2019-08-18 00:26:14 +08:00
new Action ( 'upload_sketchfab' , {
2019-07-18 00:02:07 +08:00
icon : 'icon-sketchfab' ,
category : 'file' ,
click : function ( ev ) {
uploadSketchfabModel ( )
}
} )
2020-11-14 03:43:22 +08:00
new Action ( 'share_model' , {
icon : 'share' ,
condition : ( ) => Cube . all . length ,
click ( ) {
var dialog = new Dialog ( {
2021-02-24 16:37:15 +08:00
id : 'share_model' ,
title : 'dialog.share_model.title' ,
2020-11-14 03:43:22 +08:00
form : {
2021-02-24 16:37:15 +08:00
expire _time : { label : 'dialog.share_model.expire_time' , type : 'select' , default : '2d' , options : {
'10m' : tl ( 'dates.minutes' , [ 10 ] ) ,
'1h' : tl ( 'dates.hour' , [ 1 ] ) ,
'1d' : tl ( 'dates.day' , [ 1 ] ) ,
'2d' : tl ( 'dates.days' , [ 2 ] ) ,
'1w' : tl ( 'dates.week' , [ 1 ] ) ,
2021-04-11 19:14:14 +08:00
'2w' : tl ( 'dates.weeks' , [ 2 ] ) ,
2021-02-24 16:37:15 +08:00
} } ,
2021-03-06 02:03:19 +08:00
info : { type : 'info' , text : 'The model will be stored on the Blockbench servers for the duration specified above. [Learn more](https://blockbench.net/blockbench-model-sharing-service/)' }
2020-11-14 03:43:22 +08:00
} ,
2021-02-24 16:37:15 +08:00
buttons : [ 'generic.share' , 'dialog.cancel' ] ,
2020-11-14 03:43:22 +08:00
onConfirm : function ( formResult ) {
let expire _time = formResult . expire _time ;
let model = Codecs . project . compile ( { compressed : false } ) ;
$ . ajax ( {
url : 'https://blckbn.ch/api/model' ,
data : JSON . stringify ( { expire _time , model } ) ,
cache : false ,
contentType : 'application/json; charset=utf-8' ,
dataType : 'json' ,
type : 'POST' ,
success : function ( response ) {
let link = ` https://blckbn.ch/ ${ response . id } `
2021-03-06 02:03:19 +08:00
let link _dialog = new Dialog ( {
id : 'share_model_link' ,
title : 'dialog.share_model.title' ,
form : {
link : { type : 'text' , value : link }
} ,
buttons : [ 'action.copy' , 'dialog.close' ] ,
onConfirm ( ) {
link _dialog . hide ( ) ;
if ( isApp || navigator . clipboard ) {
Clipbench . setText ( link ) ;
Blockbench . showQuickMessage ( 'dialog.share_model.copied_to_clipboard' ) ;
} else {
Blockbench . showMessageBox ( {
title : 'dialog.share_model.title' ,
message : ` [ ${ link } ]( ${ link } ) ` ,
} )
}
}
} ) . show ( ) ;
2020-11-14 03:43:22 +08:00
} ,
error : function ( response ) {
2021-02-24 16:37:15 +08:00
Blockbench . showQuickMessage ( 'dialog.share_model.failed' , 1500 )
2020-11-14 03:43:22 +08:00
console . error ( response ) ;
}
} )
dialog . hide ( )
}
} )
dialog . show ( )
}
} )
2019-07-18 00:02:07 +08:00
} )