Pixel-Composer/scripts/node_export/node_export.gml

487 lines
14 KiB
Plaintext
Raw Normal View History

2023-02-28 09:43:01 +01:00
function Node_create_Export(_x, _y, _group = noone) {
2022-01-13 05:24:03 +01:00
var path = "";
2023-01-17 08:11:55 +01:00
if(!LOADING && !APPENDING && !CLONING) {
2023-02-28 09:43:01 +01:00
path = get_save_filename(".png", "export");
key_release();
2022-01-13 05:24:03 +01:00
}
2022-12-13 09:20:36 +01:00
var node = new Node_Export(_x, _y, _group);
2022-01-13 05:24:03 +01:00
node.inputs[| 1].setValue(path);
2022-12-13 09:20:36 +01:00
//ds_list_add(PANEL_GRAPH.nodes_list, node);
2022-01-13 05:24:03 +01:00
return node;
}
2023-01-17 08:11:55 +01:00
enum NODE_EXPORT_FORMAT {
single,
sequence,
gif,
}
2023-02-28 09:43:01 +01:00
function Node_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
2022-01-13 05:24:03 +01:00
name = "Export";
2023-02-28 09:43:01 +01:00
preview_channel = 1;
2023-01-17 08:11:55 +01:00
2022-01-13 05:24:03 +01:00
playing = false;
played = 0;
2023-02-14 05:32:32 +01:00
inputs[| 0] = nodeValue("Surface", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, 0);
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 1] = nodeValue("Paths", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "")
2022-01-13 05:24:03 +01:00
.setDisplay(VALUE_DISPLAY.path_save, ["*.png", ""])
2023-03-07 14:29:47 +01:00
.setVisible(true);
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 2] = nodeValue("Template", self, JUNCTION_CONNECT.input, VALUE_TYPE.text, "%d%n")
.rejectArray();
2022-01-13 05:24:03 +01:00
2023-02-28 09:43:01 +01:00
format_single = ["Single image", "Image sequence", "Animation"];
format_array = ["Multiple images", "Image sequences", "Animation"];
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 3] = nodeValue("Type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
2023-03-05 07:16:44 +01:00
.setDisplay(VALUE_DISPLAY.enum_scroll, format_single, { update_hover: false })
2023-02-14 05:32:32 +01:00
.rejectArray();
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 4] = nodeValue("Template guides", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
2022-01-13 05:24:03 +01:00
.setDisplay(VALUE_DISPLAY.label,
@"%d Directory
%1d Goes up 1 level
%n File name
%f Frame
2022-11-03 11:44:49 +01:00
%i Array index" );
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 5] = nodeValue("Loop", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true)
.setVisible(false)
.rejectArray();
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 6] = nodeValue("Frame optimization", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false)
.setVisible(false)
.rejectArray();
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 7] = nodeValue("Color merge", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.02)
2022-01-13 05:24:03 +01:00
.setDisplay(VALUE_DISPLAY.slider, [0, 1, 0.01])
2023-02-14 05:32:32 +01:00
.setVisible(false)
.rejectArray();
2023-01-01 02:06:02 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 8] = nodeValue("Framerate", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 30)
.rejectArray();
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
format_image = [ ".png", ".jpg", ".webp" ];
format_animation = [ ".gif", ".webp" ];
inputs[| 9] = nodeValue("Format", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
2023-03-05 07:16:44 +01:00
.setDisplay(VALUE_DISPLAY.enum_scroll, format_image, { update_hover: false })
2023-02-14 05:32:32 +01:00
.rejectArray();
inputs[| 10] = nodeValue("Quality", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 80)
.setDisplay(VALUE_DISPLAY.slider, [0, 100, 1])
.rejectArray();
2023-02-14 11:40:24 +01:00
2023-03-02 07:59:14 +01:00
inputs[| 11] = nodeValue("Sequence begin", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
2023-02-14 11:40:24 +01:00
outputs[| 0] = nodeValue("Loop exit", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0);
2023-02-28 09:43:01 +01:00
outputs[| 1] = nodeValue("Preview", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone)
.setVisible(false);
2022-01-13 05:24:03 +01:00
input_display_list = [
2023-02-14 05:32:32 +01:00
["Export", false], 0, 1, 2, 4,
["Format ", false], 3, 9,
2023-03-02 07:59:14 +01:00
["Settings", false], 8, 5, 6, 7, 10, 11,
2022-01-13 05:24:03 +01:00
];
2023-03-08 12:14:01 +01:00
directory = DIRECTORY + "temp/" + string(irandom_range(100000, 999999));
converter = working_directory + "ImageMagick/convert.exe";
magick = working_directory + "ImageMagick/magick.exe";
webp = working_directory + "webp/webpmux.exe";
2023-02-14 05:32:32 +01:00
2022-01-13 05:24:03 +01:00
static onValueUpdate = function(_index) {
var form = inputs[| 3].getValue();
2023-02-14 05:32:32 +01:00
if(_index == 3)
inputs[| 9].setValue(0);
2022-12-10 05:06:01 +01:00
if(_index == 3 && form == 1)
2022-11-03 11:44:49 +01:00
inputs[| 2].setValue("%d%n%3f%i");
2023-02-14 05:32:32 +01:00
}
static renderWebp = function(temp_path, target_path) {
var _path = file_find_first(temp_path + "*.png", 0);
var frames = [];
while(_path != "") {
var _frame = "\"" + temp_path + string_replace_all(_path, ".png", "") + ".webp\"";
var _pathTemp = "\"" + temp_path + _path + "\"";
var shell_cmd = _pathTemp + " -define webp:lossless=true " + _frame;
array_push(frames, _frame);
execute_shell(magick, shell_cmd);
_path = file_find_next();
}
var rate = inputs[| 8].getValue();
var framerate = round(1 / rate * 1000);
var cmd = "";
for( var i = 0; i < array_length(frames); i++ )
cmd += "-frame " + frames[i] + " +" + string(framerate) + "+0+0+1 ";
cmd += "-bgcolor 0,0,0,0 ";
cmd += "-o \"" + target_path + "\"";
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
execute_shell(webp, cmd);
2023-04-10 20:02:59 +02:00
var noti = log_message("EXPORT", "Export webp as " + target_path, THEME.noti_icon_tick, COLORS._main_value_positive, false);
2023-02-14 05:32:32 +01:00
noti.path = filename_dir(target_path);
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
2022-01-13 05:24:03 +01:00
}
static renderGif = function(temp_path, target_path) {
var loop = inputs[| 5].getValue();
var opti = inputs[| 6].getValue();
var fuzz = inputs[| 7].getValue();
2023-01-01 02:06:02 +01:00
var rate = inputs[| 8].getValue();
2023-01-01 02:06:02 +01:00
var framerate = 100 / rate;
2022-01-13 05:24:03 +01:00
var loop_str = loop? 0 : 1;
var shell_cmd = "-delay " + string(framerate) +
" -alpha set" +
" -dispose previous" +
" -loop " + string(loop_str);
if(opti) {
shell_cmd += " -fuzz " + string(fuzz * 100) + "%" +
" -layers OptimizeFrame" +
" -layers OptimizeTransparency";
}
shell_cmd += " " + temp_path +
" " + target_path;
2022-12-22 03:09:55 +01:00
2023-02-14 05:32:32 +01:00
execute_shell(converter, shell_cmd);
2022-12-21 02:30:23 +01:00
2023-04-10 20:02:59 +02:00
var noti = log_message("EXPORT", "Export gif as " + target_path, THEME.noti_icon_tick, COLORS._main_value_positive, false);
2022-12-22 03:09:55 +01:00
noti.path = filename_dir(target_path);
2023-01-17 08:11:55 +01:00
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
2022-12-22 03:09:55 +01:00
2022-12-21 02:30:23 +01:00
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
2022-01-13 05:24:03 +01:00
}
static pathString = function(path, suff, index = 0) {
2023-03-02 07:59:14 +01:00
var form = inputs[| 3].getValue();
var strt = inputs[| 11].getValue();
2022-01-13 05:24:03 +01:00
var s = "", i = 1, ch, ch_s;
var len = string_length(suff);
while(i <= len) {
ch = string_char_at(suff, i);
if(ch == "%") {
i++;
var res = false, str = "";
do {
ch_s = string_char_at(suff, i);
switch(ch_s) {
case "f" :
var float_str = string_digits(str);
if(float_str != "") {
var float_val = string_digits(float_str);
2023-03-02 07:59:14 +01:00
var str_val = max(float_val - string_length(string(ANIMATOR.current_frame + strt)), 0);
2022-01-13 05:24:03 +01:00
repeat(str_val)
s += "0";
}
2023-03-02 07:59:14 +01:00
s += string(ANIMATOR.current_frame + strt);
2022-01-13 05:24:03 +01:00
res = true;
break;
case "i" :
s += string(index);
res = true;
break;
case "d" :
2023-03-08 12:14:01 +01:00
var dir = filename_dir(path) + "/";
2022-01-13 05:24:03 +01:00
var float_str = string_digits(str);
if(float_str != "") {
var float_val = string_digits(float_str);
var dir_s = "";
2023-03-08 12:14:01 +01:00
var sep = string_splice(dir, "/");
2022-01-13 05:24:03 +01:00
for(var j = 0; j < array_length(sep) - float_val; j++) {
2023-03-08 12:14:01 +01:00
dir_s += sep[j] + "/";
2022-01-13 05:24:03 +01:00
}
s += dir_s;
} else
s += dir;
res = true;
break;
case "n" :
var ext = filename_ext(path);
s += string_replace(filename_name(path), ext, "");
res = true;
break;
default :
str += ch_s;
}
i++;
} until(i > string_length(suff) || res);
} else {
s += ch;
i++;
}
}
2023-02-14 05:32:32 +01:00
s += ".png";
2022-01-13 05:24:03 +01:00
return s;
}
2023-02-14 05:32:32 +01:00
static save_surface = function(_surf, _path) {
var form = inputs[| 3].getValue();
if(form == NODE_EXPORT_FORMAT.gif) {
2023-03-19 09:17:39 +01:00
surface_save_safe(_surf, _path);
2023-02-14 05:32:32 +01:00
return _path;
}
var extd = inputs[| 9].getValue();
var qual = inputs[| 10].getValue();
var ext = array_safe_get(format_image, extd, ".png");
2023-04-10 20:02:59 +02:00
var _pathOut = _path;
2023-03-08 12:14:01 +01:00
var _pathTemp = directory + "/" + string(irandom_range(10000, 99999)) + ".png";
2023-02-14 05:32:32 +01:00
switch(ext) {
case ".png":
2023-03-19 09:17:39 +01:00
surface_save_safe(_surf, _path);
2023-02-14 05:32:32 +01:00
break;
2023-04-10 20:02:59 +02:00
2023-02-14 05:32:32 +01:00
case ".jpg":
2023-03-19 09:17:39 +01:00
surface_save_safe(_surf, _pathTemp);
2023-02-14 05:32:32 +01:00
_pathOut = "\"" + string_replace_all(_path, ".png", "") + ".jpg\"";
_pathTemp = "\"" + _pathTemp + "\"";
var shell_cmd = _pathTemp + " -quality " + string(qual) + " " + _pathOut;
print(shell_cmd)
execute_shell(magick, shell_cmd);
break;
2023-04-10 20:02:59 +02:00
2023-02-14 05:32:32 +01:00
case ".webp":
2023-03-19 09:17:39 +01:00
surface_save_safe(_surf, _pathTemp);
2023-02-14 05:32:32 +01:00
_pathOut = "\"" + string_replace_all(_path, ".png", "") + ".webp\"";
_pathTemp = "\"" + _pathTemp + "\"";
var shell_cmd = _pathTemp + " -quality " + string(qual) + " -define webp:lossless=true " + _pathOut;
execute_shell(magick, shell_cmd);
break;
}
return _pathOut;
}
2023-02-28 09:43:01 +01:00
static export = function() {
2022-01-13 05:24:03 +01:00
var surf = inputs[| 0].getValue();
var path = inputs[| 1].getValue();
var suff = inputs[| 2].getValue();
var form = inputs[| 3].getValue();
var _ts = current_time;
if(is_array(surf)) {
2023-01-17 08:11:55 +01:00
var p = "";
2022-01-13 05:24:03 +01:00
for(var i = 0; i < array_length(surf); i++) {
var _surf = surf[i];
2022-09-21 06:09:40 +02:00
if(!is_surface(_surf)) continue;
2023-01-17 08:11:55 +01:00
if(form == NODE_EXPORT_FORMAT.gif) {
2023-03-08 12:14:01 +01:00
p = directory + "/" + string(i) + "/" + string_lead_zero(ANIMATOR.current_frame, 5) + ".png";
2023-02-14 05:32:32 +01:00
} else {
2022-09-21 06:09:40 +02:00
if(is_array(path) && array_length(path) == array_length(surf))
p = pathString(path[ safe_mod(i, array_length(path)) ], suff, i);
else
p = pathString(path, suff, i);
2022-01-13 05:24:03 +01:00
}
2022-09-21 06:09:40 +02:00
2023-02-14 05:32:32 +01:00
p = save_surface(_surf, p);
2022-01-13 05:24:03 +01:00
}
2023-01-17 08:11:55 +01:00
2023-02-14 05:32:32 +01:00
if(form != NODE_EXPORT_FORMAT.gif) {
2023-04-10 20:02:59 +02:00
var noti = log_message("EXPORT", "Export " + string(array_length(surf)) + " images complete.", THEME.noti_icon_tick, COLORS._main_value_positive, false);
2023-01-17 08:11:55 +01:00
noti.path = filename_dir(p);
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
2022-01-13 05:24:03 +01:00
2023-01-17 08:11:55 +01:00
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
}
} else if(is_surface(surf)) {
var p = path;
if(is_array(path)) p = path[0];
2022-01-13 05:24:03 +01:00
2023-01-17 08:11:55 +01:00
if(form == NODE_EXPORT_FORMAT.gif)
2023-03-08 12:14:01 +01:00
p = directory + "/" + string_lead_zero(ANIMATOR.current_frame, 5) + ".png";
2023-01-17 08:11:55 +01:00
else
p = pathString(p, suff);
2023-03-12 02:28:21 +01:00
//print("Exporting " + p);
2023-02-14 05:32:32 +01:00
p = save_surface(surf, p);
2022-12-21 02:30:23 +01:00
2023-02-14 05:32:32 +01:00
if(form != NODE_EXPORT_FORMAT.gif) {
2023-04-10 20:02:59 +02:00
var noti = log_message("EXPORT", "Export image as " + p, THEME.noti_icon_tick, COLORS._main_value_positive, false);
2023-01-17 08:11:55 +01:00
noti.path = filename_dir(p);
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
2022-12-22 03:09:55 +01:00
2023-01-17 08:11:55 +01:00
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
}
2022-01-13 05:24:03 +01:00
}
}
2023-03-28 06:58:28 +02:00
insp1UpdateTooltip = "Export";
insp1UpdateIcon = [ THEME.sequence_control, 1, COLORS._main_value_positive ];
2023-02-14 05:32:32 +01:00
insp2UpdateTooltip = "Export All";
insp2UpdateIcon = [ THEME.play_all, 0, COLORS._main_value_positive ];
2023-03-28 06:58:28 +02:00
static onInspector1Update = function() {
2023-02-28 09:43:01 +01:00
if(isInLoop()) UPDATE |= RENDER_TYPE.full;
2023-02-14 13:44:46 +01:00
else doInspectorAction();
2023-02-14 05:32:32 +01:00
}
static onInspector2Update = function() {
var key = ds_map_find_first(NODE_MAP);
repeat(ds_map_size(NODE_MAP)) {
var node = NODE_MAP[? key];
key = ds_map_find_next(NODE_MAP, key);
if(!node.active) continue;
if(instanceof(node) != "Node_Export") continue;
2023-02-14 13:44:46 +01:00
node.doInspectorAction();
2023-02-14 05:32:32 +01:00
}
2023-02-14 11:40:24 +01:00
2023-02-28 09:43:01 +01:00
if(isInLoop()) UPDATE |= RENDER_TYPE.full;
2023-02-14 05:32:32 +01:00
}
2023-02-14 13:44:46 +01:00
static doInspectorAction = function() {
2022-01-26 13:02:30 +01:00
if(LOADING || APPENDING) return;
2022-01-13 05:24:03 +01:00
var path = inputs[| 1].getValue();
if(path == "") return;
2023-01-17 08:11:55 +01:00
var form = inputs[| 3].getValue();
2022-01-13 05:24:03 +01:00
2023-01-17 08:11:55 +01:00
if(form == NODE_EXPORT_FORMAT.single) {
2022-01-13 05:24:03 +01:00
export();
2023-01-17 08:11:55 +01:00
return;
}
playing = true;
played = 0;
ANIMATOR.real_frame = -1;
ANIMATOR.current_frame = -1;
ANIMATOR.is_playing = true;
ANIMATOR.rendering = true;
2023-02-14 05:32:32 +01:00
if(directory_exists(directory))
directory_destroy(directory);
directory_create(directory);
2022-01-13 05:24:03 +01:00
}
2022-12-23 04:45:52 +01:00
2023-02-14 05:32:32 +01:00
static step = function() {
2022-12-23 04:45:52 +01:00
var surf = inputs[| 0].getValue();
2023-02-14 05:32:32 +01:00
if(is_array(surf)) {
inputs[| 3].display_data = format_array;
inputs[| 3].editWidget.data_list = format_array;
} else {
inputs[| 3].display_data = format_single;
inputs[| 3].editWidget.data_list = format_single;
}
2022-12-23 04:45:52 +01:00
2023-02-28 09:43:01 +01:00
outputs[| 1].setValue(surf);
2022-12-23 04:45:52 +01:00
var anim = inputs[| 3].getValue();
2023-02-14 05:32:32 +01:00
var extn = inputs[| 9].getValue();
2023-03-02 07:59:14 +01:00
inputs[| 5].setVisible(anim == 2);
inputs[| 6].setVisible(anim == 2);
inputs[| 7].setVisible(anim == 2);
inputs[| 8].setVisible(anim == 2);
inputs[| 11].setVisible(anim == 1);
2023-02-14 05:32:32 +01:00
if(anim == NODE_EXPORT_FORMAT.gif) {
inputs[| 9].display_data = format_animation;
inputs[| 9].editWidget.data_list = format_animation;
inputs[| 10].setVisible(extn == 1);
} else {
inputs[| 9].display_data = format_image;
inputs[| 9].editWidget.data_list = format_image;
inputs[| 10].setVisible(extn != 0);
}
2023-02-14 11:40:24 +01:00
2023-02-14 13:44:46 +01:00
outputs[| 0].visible = isInLoop();
2023-02-14 05:32:32 +01:00
}
static update = function(frame = ANIMATOR.current_frame) {
var anim = inputs[| 3].getValue();
2023-02-14 11:40:24 +01:00
if(anim == NODE_EXPORT_FORMAT.single) {
2023-02-19 02:13:19 +01:00
if(isInLoop()) export();
2023-02-14 11:40:24 +01:00
return;
}
2022-12-23 04:45:52 +01:00
if(!ANIMATOR.is_playing) {
playing = false;
return;
}
if(!ANIMATOR.frame_progress || !playing || ANIMATOR.current_frame <= -1)
return;
2023-03-12 02:28:21 +01:00
2022-12-23 04:45:52 +01:00
export();
2023-02-19 02:13:19 +01:00
2022-12-23 04:45:52 +01:00
if(ANIMATOR.current_frame < ANIMATOR.frames_total - 1)
return;
2023-02-14 05:32:32 +01:00
if(anim != NODE_EXPORT_FORMAT.gif)
2022-12-23 04:45:52 +01:00
return;
2023-02-14 05:32:32 +01:00
var surf = inputs[| 0].getValue();
2022-12-23 04:45:52 +01:00
var path = inputs[| 1].getValue();
var suff = inputs[| 2].getValue();
2023-02-14 05:32:32 +01:00
var extd = inputs[| 9].getValue();
2022-12-23 04:45:52 +01:00
var temp_path, target_path;
if(is_array(surf)) {
for(var i = 0; i < array_length(surf); i++) {
2023-03-08 12:14:01 +01:00
temp_path = directory + "/" + string(i) + "/" + "*.png";
2022-12-23 04:45:52 +01:00
if(is_array(path))
target_path = pathString(path[ safe_mod(i, array_length(path)) ], suff, i);
else
target_path = pathString(path, suff, i);
2023-02-14 05:32:32 +01:00
if(extd == 0) {
target_path = string_replace(target_path, ".png", ".gif");
renderGif("\"" + temp_path + "\"", "\"" + target_path + "\"");
} else if(extd == 1) {
target_path = string_replace(target_path, ".png", ".webp");
renderWebp(temp_path, target_path);
}
2022-12-23 04:45:52 +01:00
}
} else {
2023-02-14 05:32:32 +01:00
target_path = pathString(path, suff);
if(extd == 0) {
target_path = string_replace(target_path, ".png", ".gif");
2023-03-08 12:14:01 +01:00
renderGif("\"" + directory + "/*.png\"", "\"" + target_path + "\"");
2023-02-14 05:32:32 +01:00
} else if(extd == 1) {
target_path = string_replace(target_path, ".png", ".webp");
2023-03-08 12:14:01 +01:00
renderWebp(directory + "/", target_path);
2023-02-14 05:32:32 +01:00
}
2022-12-23 04:45:52 +01:00
}
2023-02-14 05:32:32 +01:00
//directory_destroy(directory);
2022-12-23 04:45:52 +01:00
}
2022-01-13 05:24:03 +01:00
}