blockbench/js/api.js

734 lines
20 KiB
JavaScript
Raw Normal View History

2017-10-27 01:00:52 +08:00
class API {
constructor() {
this.elements = elements;
this.textures = textures;
this.isWeb = !isApp;
this.version = appVersion;
this.platform = 'web'
this.selection = selected;
this.flags = []
2018-10-18 01:50:25 +08:00
this.drag_handlers = {}
2018-03-29 02:48:11 +08:00
this.entity_mode = false
2017-10-27 01:00:52 +08:00
if (isApp) {
this.platform = require('os').platform()
if (this.platform.includes('win32') === true) osfs = '\\'
}
}
2018-10-18 01:50:25 +08:00
edit(aspects, cb) {
Undo.initEdit(aspects)
cb()
Undo.finishEdit()
2017-10-27 01:00:52 +08:00
}
2018-10-18 01:50:25 +08:00
reload() {
if (isApp) {
preventClosing = false
Blockbench.flags.push('allow_reload')
currentwindow.reload()
} else {
location.reload()
}
}
checkEntityMode() {
return Blockbench.entity_mode;
}
registerEdit() {
console.error('Blockbench.registerEdit is outdated. Please use Undo.initEdit and Undo.finishEdit')
}
//Interface
getIconNode(icon, color) {
var jq;
if (typeof icon === 'function') {
icon = icon()
}
if (icon === undefined) {
jq = $('<i class="material-icons icon">help_outline</i>')
} else if (icon instanceof HTMLElement) {
jq = $(icon)
} else if (icon.substr(0, 2) === 'fa') {
jq = $('<i class="icon fa fa_big ' + icon + '"></i>')
} else if (icon.substr(0, 5) === 'icon-') {
jq = $('<i class="' + icon + '"></i>')
} else if (icon.substr(0, 14) === 'data:image/png') {
jq = $('<img class="icon" src="'+icon+'">')
} else {
jq = $('<i class="material-icons icon">' + icon + '</i>')
}
if (color) {
if (color === 'x') {
jq.addClass('color_x')
} else if (color === 'y') {
jq.addClass('color_y')
} else if (color === 'z') {
jq.addClass('color_z')
} else if (typeof color === 'string') {
jq.css('color', color)
2017-10-27 01:00:52 +08:00
}
}
2018-10-18 01:50:25 +08:00
return jq.get(0)
}
showQuickMessage(message, time) {
var quick_message_box = $('<div id="quick_message_box" class="hidden"></div>')
$('body').append(quick_message_box)
quick_message_box.text(tl(message))
quick_message_box.fadeIn(100)
setTimeout(function() {
quick_message_box.fadeOut(100)
setTimeout(function() {
quick_message_box.remove()
}, 100)
}, time ? time : 1000)
2017-10-27 01:00:52 +08:00
}
2018-10-18 01:50:25 +08:00
showStatusMessage(message, time) {
var status_message = $('#status_message')
var status_name = $('#status_name')
status_message.text(tl(message))
status_name.hide(100)
status_message.show(100)
2017-10-27 01:00:52 +08:00
2018-10-18 01:50:25 +08:00
setTimeout(function() {
status_message.hide(100)
status_name.show(100)
}, time ? time : 600)
}
2017-10-27 01:00:52 +08:00
showMessage(message, location) {
if (location === 'status_bar') {
2018-10-18 01:50:25 +08:00
Blockbench.showStatusMessage(message)
2017-10-27 01:00:52 +08:00
} else if (location === 'center') {
2018-10-18 01:50:25 +08:00
Blockbench.showQuickMessage(message)
2017-10-27 01:00:52 +08:00
}
}
2017-11-17 05:23:41 +08:00
showMessageBox(options, cb) {
if (options.confirm === undefined) options.confirm = 0
if (options.cancel === undefined) options.cancel = 0
2018-10-18 01:50:25 +08:00
if (!options.buttons) options.buttons = [tl('dialog.ok')]
if (options.translateKey) {
if (!options.title) options.title = tl('message.'+options.translateKey+'.title')
if (!options.message) options.message = tl('message.'+options.translateKey+'.message')
}
2017-11-17 05:23:41 +08:00
var jq_dialog = $('<div class="dialog paddinged" style="width: auto;" id="message_box"><h2 class="dialog_handle">'+options.title+'</h2></div>')
jq_dialog.append('<div class="dialog_bar" style="height: auto; min-height: 56px; margin-bottom: 16px;">'+
options.message+'</div>'
)
2018-10-18 01:50:25 +08:00
if (options.icon) {
jq_dialog.find('.dialog_bar').prepend($(Blockbench.getIconNode(options.icon)).addClass('message_box_icon'))
}
2017-11-17 05:23:41 +08:00
var buttons = []
options.buttons.forEach(function(b, i) {
var btn = $('<button type="button" class="large">'+b+'</button>')
btn.click(function(e) {
hideDialog()
setTimeout(function() {
2018-10-18 01:50:25 +08:00
jq_dialog.remove()
},200)
if (cb) {
2018-03-29 02:48:11 +08:00
cb(i)
2018-10-18 01:50:25 +08:00
}
2017-11-17 05:23:41 +08:00
})
buttons.push(btn)
})
2018-10-18 01:50:25 +08:00
jq_dialog.hide = function() {
$(jq_dialog.find('button').get(options.cancel)).click()
}
2017-11-17 05:23:41 +08:00
buttons[options.confirm].addClass('confirm_btn')
buttons[options.cancel].addClass('cancel_btn')
jq_dialog.append($('<div class="dialog_bar"></div>').append(buttons))
2018-10-18 01:50:25 +08:00
jq_dialog.addClass('draggable')
jq_dialog.draggable({
handle: ".dialog_handle"
})
var x = ($(window).width()-540)/2
jq_dialog.css('left', x+'px')
jq_dialog.css('position', 'absolute')
2017-11-17 05:23:41 +08:00
$('#plugin_dialog_wrapper').append(jq_dialog)
2018-10-18 01:50:25 +08:00
$('.dialog').hide(0)
$('#blackout').fadeIn(100)
jq_dialog.fadeIn(100)
jq_dialog.css('top', limitNumber($(window).height()/2-jq_dialog.height()/2, 0, 100)+'px')
if (options.width) {
jq_dialog.css('width', options.width+'px')
} else {
jq_dialog.css('width', limitNumber(options.buttons.length*170+44, 380, 894)+'px')
}
setTimeout(function() {
$('.context_handler.ctx').removeClass('ctx')
}, 64)
open_dialog = 'message_box'
open_interface = 'message_box'
return jq_dialog
}
textPrompt(title, value, callback) {
showDialog('text_input')
$('#text_input h2').text(title)
$('#text_input input#text_input_field').val(value).select()
$('#text_input button.confirm_btn').off()
$('#text_input button.confirm_btn').click(function() {
var s = $('#text_input input#text_input_field').val()
if (callback !== undefined) {
callback(s)
}
})
}
addMenuEntry(name, icon, click) {
MenuBar.addAction({icon: icon, name: name, id: name, click: click}, 'filter')
2017-11-17 05:23:41 +08:00
}
2018-10-18 01:50:25 +08:00
removeMenuEntry(name) {
MenuBar.removeAction('filter.'+name)
}
openLink(link) {
if (isApp) {
shell.openExternal(link)
} else {
window.open(link)
}
}
//IO
import(options, cb) {
if (typeof options !== 'object') {options = {}}
//extensions
//type
//readtype
//multiple
//startpath
//title
//errorbox
2017-10-27 01:00:52 +08:00
2018-10-18 01:50:25 +08:00
if (isApp) {
var properties = []
if (options.multiple) {
properties.push('multiSelections')
}
if (options.extensions[0] === 'image/*') {
options.type = 'Images'
options.extensions = ['png', 'jpg', 'jpeg', 'bmp', 'tiff', 'tif', 'gif']
}
app.dialog.showOpenDialog(
currentwindow,
{
title: options.title ? options.title : '',
filters: [{
name: options.type ? options.type : options.extensions[0],
extensions: options.extensions
}],
2018-10-18 09:32:42 +08:00
properties: properties.length?properties:undefined,
2018-10-18 01:50:25 +08:00
defaultPath: options.startpath
},
function (fileNames) {
if (fileNames == undefined) return;
var results = [];
var result_count = 0;
var i = 0;
var errant;
while (i < fileNames.length) {
(function() {
var this_i = i;
var file = fileNames[i]
if (options.readtype === 'image') {
//
var extension = pathToExtension(file)
if (extension === 'tga') {
var targa_loader = new Targa()
targa_loader.open(file, () => {
results[this_i] = {
name: pathToName(file, true),
path: file,
content: targa_loader.getDataURL()
}
result_count++;
if (result_count === fileNames.length) {
cb(results)
}
})
} else {
results[this_i] = {
name: pathToName(file, true),
path: file
}
result_count++;
if (result_count === fileNames.length) {
cb(results)
}
}
} else /*text*/ {
fs.readFile(file, 'utf-8', function (err, data) {
if (err) {
console.log(err)
if (!errant && options.errorbox !== false) {
Blockbench.showMessageBox({
translateKey: 'file_not_found',
icon: 'error_outline'
})
}
errant = true
return;
}
if (data.charCodeAt(0) === 0xFEFF) {
data = data.substr(1)
}
results[this_i] = {
name: pathToName(file, true),
path: file,
content: data
}
result_count++;
if (result_count === fileNames.length) {
cb(results)
}
})
}
})()
i++;
2017-10-27 01:00:52 +08:00
}
2018-10-18 01:50:25 +08:00
2017-10-27 01:00:52 +08:00
})
} else {
2018-10-18 01:50:25 +08:00
$('<input '+
'type="file'+
'" accept=".'+(options.extensions ? options.extensions.join(',.'): '')+
'" multiple="'+(options.multiple === true)+
'">').change(function(e) {
var input = this;
var results = [];
var result_count = 0;
var i = 0;
while (i < input.files.length) {
(function() {
var file = input.files[i]
var reader = new FileReader()
reader.i = i
reader.onloadend = function() {
if (reader.result.byteLength) {
var arr = new Uint8Array(reader.result)
var targa_loader = new Targa()
targa_loader.load(arr)
var result = targa_loader.getDataURL()
} else {
var result = reader.result
}
results[this.i] = {
name: file.name,
path: file.name,
content: result
}
result_count++;
if (result_count === input.files.length) {
cb(results)
}
}
if (options.readtype === 'image') {
if (pathToExtension(file.name) === 'tga') {
reader.readAsArrayBuffer(file)
} else {
reader.readAsDataURL(file)
}
} else /*text*/ {
reader.readAsText(file)
}
i++;
})()
}
}).click()
2017-10-27 01:00:52 +08:00
}
}
2018-10-18 01:50:25 +08:00
export(options, cb) {
if (!options) return;
/*
type
extensions
name
content
startpath
savetype
custom_writer
*/
2017-10-27 01:00:52 +08:00
if (Blockbench.isWeb) {
2018-10-18 01:50:25 +08:00
var file_name = options.name + (options.extensions ? '.'+options.extensions[0] : '')
if (options.savetype === 'image') {
var download = document.createElement('a');
download.href = file_name
download.download = options.name;
if (Blockbench.browser === 'firefox') document.body.appendChild(download);
download.click();
if (Blockbench.browser === 'firefox') document.body.removeChild(download);
} else {
var blob = new Blob([options.content], {type: "text/plain;charset=utf-8"});
saveAs(blob, file_name, {autoBOM: true})
}
if (typeof cb === 'function') {
cb()
}
2017-10-27 01:00:52 +08:00
} else {
2018-10-18 01:50:25 +08:00
app.dialog.showSaveDialog(currentwindow, {
filters: [ {
name: options.type,
extensions: options.extensions
} ],
defaultPath: options.startpath !== 'Unknown' ? options.startpath : options.name
}, function (file_path) {
if (file_path === undefined) {
return;
}
if (options.savetype === 'image' && typeof options.content === 'string') {
if (options.content.substr(0, 10) === 'data:image') {
options.content = nativeImage.createFromDataURL(options.content).toPNG()
} else {
options.content = nativeImage.createFromPath(options.content).toPNG()
}
}
if (options.custom_writer) {
options.custom_writer(options.content, file_path)
} else {
fs.writeFile(file_path, options.content, function (err) {
if (err) {
console.log('Error exporting file: '+err)
return;
}
if (cb) {
cb(file_path)
}
})
}
})
}
}
//Flags
addFlag(flag) {
if (!this.hasFlag(flag)) {
this.flags.push(flag)
2017-10-27 01:00:52 +08:00
}
}
2018-10-18 01:50:25 +08:00
removeFlag(flag) {
this.flags.remove(flag)
}
hasFlag(flag) {
return this.flags.includes(flag)
}
//Events
2017-10-27 01:00:52 +08:00
dispatchEvent(event_name, event) {
if (!this.listeners) {
return;
}
var i = 0;
while (i < this.listeners.length) {
if (this.listeners[i].name === event_name) {
this.listeners[i].callback(event)
}
i++;
}
}
addListener(event_name, cb) {
if (!this.listeners) {
this.listeners = []
}
this.listeners.push({name: event_name, callback: cb})
}
removeListener(event_name, cb) {
if (!this.listeners) {
return;
}
var i = 0;
while (i < this.listeners.length) {
if (this.listeners[i].name === event_name && this.listeners[i].callback === cb) {
this.listeners.splice(i, 1)
}
i++;
}
}
2018-10-18 01:50:25 +08:00
//File Drag
addDragHandler(id, options, cb) {
var entry = {
cb: cb
2017-10-27 01:00:52 +08:00
}
2018-10-18 01:50:25 +08:00
if (options.extensions && options.extensions.length) {
entry.extensions = options.extensions
}
if (options.addClass !== false) entry.addClass = true;
if (options.propagate) entry.propagate = true;
if (options.readtype) entry.readtype = options.readtype;
if (options.errorbox) entry.errorbox = true;
if (options.element) entry.element = options.element;
this.drag_handlers[id] = entry
2017-10-27 01:00:52 +08:00
}
2018-10-18 01:50:25 +08:00
removeDragHandler(id) {
delete this.drag_handlers[id]
2017-10-27 01:00:52 +08:00
}
}
2018-10-18 01:50:25 +08:00
var Blockbench = new API()
2017-10-27 01:00:52 +08:00
function Dialog(settings) {
var scope = this;
this.title = settings.title
this.lines = settings.lines
this.id = settings.id
this.width = settings.width
this.fadeTime = settings.fadeTime
this.draggable = settings.draggable
this.singleButton = settings.singleButton
if (!parseInt(settings.fadeTime)) this.fadeTime = 200
this.hide = function() {
2018-10-18 01:50:25 +08:00
$('#blackout').fadeOut(this.fadeTime)
$(scope.object).fadeOut(this.fadeTime)
.find('.tool').detach()
open_dialog = false;
open_interface = false;
Prop.active_panel = undefined
setTimeout(function() {
$(scope.object).remove()
},this.fadeTime)
2017-10-27 01:00:52 +08:00
}
this.confirmEnabled = settings.confirmEnabled === false ? false : true
this.cancelEnabled = settings.cancelEnabled === false ? false : true
this.onConfirm = settings.onConfirm ? settings.onConfirm : this.hide
this.onCancel = settings.onCancel ? settings.onCancel : this.hide
this.object;
this.confirm = function() {
$(this.object).find('.confirm_btn:not([disabled])').click()
}
this.cancel = function() {
$(this.object).find('.cancel_btn:not([disabled])').click()
}
this.show = function() {
var jq_dialog = $('<div class="dialog paddinged" style="width: auto;" id="'+scope.id+'"><h2 class="dialog_handle">'+scope.title+'</h2></div>')
scope.object = jq_dialog.get(0)
2018-10-18 01:50:25 +08:00
var max_label_width = 0;
2017-10-27 01:00:52 +08:00
scope.lines.forEach(function(l) {
2018-10-18 01:50:25 +08:00
if (typeof l === 'object' && (l.label || l.widget)) {
var bar = $('<div class="dialog_bar"></div>')
if (l.label) {
bar.append('<label class="name_space_left">'+tl(l.label)+(l.nocolon?'':':')+'</label>')
max_label_width = Math.max(getStringWidth(tl(l.label)), max_label_width)
}
if (l.node) {
bar.append(l.node)
} else if (l.widget) {
var widget = l.widget
if (typeof l.widget === 'string') {
widget = BarItems[l.widget]
} else if (typeof l.widget === 'function') {
widget = l.widget()
}
bar.append(widget.getNode())
max_label_width = Math.max(getStringWidth(widget.name), max_label_width)
}
jq_dialog.append(bar)
} else {
jq_dialog.append(l)
}
2017-10-27 01:00:52 +08:00
})
2018-10-18 01:50:25 +08:00
if (max_label_width) {
document.styleSheets[0].insertRule('.dialog#'+this.id+' .dialog_bar label {width: '+(max_label_width+14)+'px}')
}
2017-10-27 01:00:52 +08:00
if (this.singleButton) {
jq_dialog.append('<div class="dialog_bar">' +
2018-10-18 01:50:25 +08:00
'<button type="button" class="large cancel_btn confirm_btn"'+ (this.confirmEnabled ? '' : ' disabled') +'>'+tl('dialog.close')+'</button>' +
'</div>')
2017-10-27 01:00:52 +08:00
} else {
jq_dialog.append(['<div class="dialog_bar">',
2018-10-18 01:50:25 +08:00
'<button type="button" class="large confirm_btn"'+ (this.confirmEnabled ? '' : ' disabled') +'>'+tl('dialog.confirm')+'</button>',
'<button type="button" class="large cancel_btn"'+ (this.cancelEnabled ? '' : ' disabled') +'>'+tl('dialog.cancel')+'</button>',
'</div>'].join(''))
}
jq_dialog.append('<div id="dialog_close_button" onclick="$(\'.dialog#\'+open_dialog).find(\'.cancel_btn:not([disabled])\').click()"><i class="material-icons">clear</i></div>')
2017-10-27 01:00:52 +08:00
$(this.object).find('.confirm_btn').click(this.onConfirm)
$(this.object).find('.cancel_btn').click(this.onCancel)
2018-10-18 01:50:25 +08:00
//Draggable
if (this.draggable !== false) {
jq_dialog.addClass('draggable')
jq_dialog.draggable({
handle: ".dialog_handle"
})
var x = ($(window).width()-540)/2
jq_dialog.css('left', x+'px')
jq_dialog.css('position', 'absolute')
}
2017-10-27 01:00:52 +08:00
$('#plugin_dialog_wrapper').append(jq_dialog)
2018-10-18 01:50:25 +08:00
$('.dialog').hide(0)
$('#blackout').fadeIn(scope.fadeTime)
jq_dialog.fadeIn(scope.fadeTime)
jq_dialog.css('top', limitNumber($(window).height()/2-jq_dialog.height()/2, 0, 100)+'px')
if (this.width) {
jq_dialog.css('width', this.width+'px')
}
setTimeout(function() {
$('.context_handler.ctx').removeClass('ctx')
}, 64)
open_dialog = scope.id
open_interface = scope
Prop.active_panel = 'dialog'
return this;
2017-10-27 01:00:52 +08:00
}
}
2018-10-18 01:50:25 +08:00
document.ondragover = function(event) {
event.preventDefault()
}
document.body.ondrop = function(event) {
event.preventDefault()
forDragHandlers(event, function(handler, el) {
var fileNames = event.dataTransfer.files
var input = this;
var results = [];
var result_count = 0;
var i = 0;
var errant;
while (i < fileNames.length) {
if (isApp) {
if (handler.readtype === 'image') {
var path = fileNames[i].path
//
results[i] = {
name: pathToName(path, true),
path: path
}
result_count++;
if (result_count === fileNames.length) {
handler.cb(results, event)
}
} else /*text*/ {
(function() {
var path = fileNames[i].path
var this_i = i;
fs.readFile(path, 'utf-8', function (err, data) {
if (err) {
console.log(err)
if (!errant && handler.errorbox !== false) {
Blockbench.showMessageBox({
translateKey: 'file_not_found',
icon: 'error_outline'
})
}
errant = true
return;
}
results[this_i] = {
name: pathToName(path, true),
path: path,
content: data
}
result_count++;
if (result_count === fileNames.length) {
handler.cb(results, event)
}
})
})()
}
2017-10-27 01:00:52 +08:00
} else {
2018-10-18 01:50:25 +08:00
(function() {
var file = fileNames[i]
var reader = new FileReader()
reader.i = i
reader.onloadend = function() {
results[this.i] = {
name: file.name,
path: file.name,
content: reader.result
}
result_count++;
if (result_count === fileNames.length) {
handler.cb(results, event)
}
}
if (handler.readtype === 'image') {
reader.readAsDataURL(file)
} else /*text*/ {
reader.readAsText(file)
}
})()
2017-10-27 01:00:52 +08:00
}
2018-10-18 01:50:25 +08:00
i++;
2017-10-27 01:00:52 +08:00
}
2018-10-18 01:50:25 +08:00
})
}
document.body.ondragenter = function(event) {
event.preventDefault()
forDragHandlers(event, function(handler, el) {
//$(el).css('background-color', 'red')
})
}
document.body.ondragleave = function(event) {
event.preventDefault()
forDragHandlers(event, function(handler, el) {
//$(el).css('background-color', '')
})
}
2017-10-27 01:00:52 +08:00
2018-10-18 01:50:25 +08:00
function forDragHandlers(event, cb) {
if (event.dataTransfer == undefined) {
return;
2017-10-27 01:00:52 +08:00
}
2018-10-18 01:50:25 +08:00
for (var id in Blockbench.drag_handlers) {
var handler = Blockbench.drag_handlers[id]
var el = undefined;
2017-10-27 01:00:52 +08:00
2018-10-18 01:50:25 +08:00
if (!handler.element) {
el = $('body').get(0)
2017-10-27 01:00:52 +08:00
2018-10-18 01:50:25 +08:00
} else if ($(handler.element).get(0) === event.target) {
el = event.target
2017-10-27 01:00:52 +08:00
2018-10-18 01:50:25 +08:00
} else if (typeof handler.element === 'string' && $(event.target).is(handler.element)) {
el = event.target
2017-10-27 01:00:52 +08:00
2018-10-18 01:50:25 +08:00
} else if (typeof handler.element === 'function') {
var result = handler.element()
if (result === true) {
el = $(event.target)
} else if ($(result).length) {
el = $(result).get(0)
}
} else if (handler.propagate) {
var parent = $(handler.element)
if (typeof handler.element === 'function' && !result) {
parent = $(handler.element())
}
if (parent && parent.has(event.target).length) {
el = parent
}
}
if (el &&
event.dataTransfer.files.length > 0 &&
event.dataTransfer.files[0].name &&
handler.extensions.includes( pathToExtension(event.dataTransfer.files[0].name) )
) {
cb(handler, el)
}
}
2017-10-27 01:00:52 +08:00
}