This commit is contained in:
Tanasart 2024-04-18 12:12:31 +07:00
parent 79f6f5fb36
commit 1431137e82
52 changed files with 7442 additions and 102 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:48:00
// 2024-04-18 12:06:16
function canvas_brush() constructor {
brush_sizing = false;
brush_sizing_s = 0;

View file

@ -1,4 +1,4 @@
// 2024-04-14 10:09:02
// 2024-04-14 12:48:00
function canvas_brush() constructor {
brush_sizing = false;
brush_sizing_s = 0;

View file

@ -0,0 +1,25 @@
// 2024-04-18 12:09:37
globalvar PEN_USE, PEN_CONTACT, PEN_RELEASED, PEN_PRESSURE;
globalvar PEN_X, PEN_Y, PEN_X_DELTA, PEN_Y_DELTA;
globalvar PEN_RIGHT_CLICK, PEN_RIGHT_PRESS, PEN_RIGHT_RELEASE;
PEN_USE = false;
PEN_X = 0;
PEN_Y = 0;
PEN_X_DELTA = 0;
PEN_Y_DELTA = 0;
PEN_CONTACT = false;
PEN_PRESSURE = 0;
PEN_RIGHT_CLICK = false;
PEN_RIGHT_PRESS = false;
PEN_RIGHT_RELEASE = false;
function __initPen() {
var c = tabletstuff_get_init_error_code();
if (c != tabletstuff_error_none)
show_error("Unable to initialize TabletStuff. Code=" + tabletstuff_error_to_string(c), true);
}

View file

@ -0,0 +1,25 @@
// 2024-04-18 11:51:43
globalvar PEN_USE, PEN_CONTACT, PEN_RELEASED, PEN_PRESSURE;
globalvar PEN_X, PEN_Y, PEN_X_DELTA, PEN_Y_DELTA;
globalvar PEN_RIGHT_CLICK, PEN_RIGHT_PRESS, PEN_RIGHT_RELEASE;
PEN_USE = false;
PEN_X = 0;
PEN_Y = 0;
PEN_X_DELTA = 0;
PEN_Y_DELTA = 0;
PEN_CONTACT = false;
PEN_PRESSURE = 0;
PEN_RIGHT_CLICK = false;
PEN_RIGHT_PRESS = false;
PEN_RIGHT_RELEASE = false;
function __initPen() {
var c = tabletstuff_get_init_error_code();
if (c != tabletstuff_error_none)
show_error("Unable to initialize TabletStuff. Code=" + tabletstuff_error_to_string(c), true);
}

View file

@ -0,0 +1,133 @@
// 2024-04-18 12:09:27
function buttonGroup(_data, _onClick) : widget() constructor {
data = _data;
onClick = _onClick;
display_button = false;
buttonSpr = [ THEME.button_left, THEME.button_middle, THEME.button_right ];
fColor = COLORS._main_text;
current_selecting = 0;
tooltips = [];
for(var i = 0; i < array_length(data); i++)
buttons[i] = button(-1);
sb_small = new scrollBox(data, _onClick);
static setFont = function(font) {
self.font = font;
return self;
}
static setTooltips = function(tt) { tooltips = tt; return self; }
static trigger = function() {
if(current_selecting + 1 >= array_length(data))
onClick(0);
else
onClick(current_selecting + 1);
}
static setInteract = function(interactable = noone) {
self.interactable = interactable;
for(var i = 0; i < array_length(data); i++)
buttons[i].interactable = interactable;
sb_small.interactable = interactable;
}
static register = function(parent = noone) {
if(display_button) {
array_push(WIDGET_ACTIVE, self);
self.parent = parent;
} else
sb_small.register(parent);
}
static drawParam = function(params) {
setParam(params);
sb_small.setParam(params);
return draw(params.x, params.y, params.w, params.h, params.data, params.m, params.rx, params.ry);
}
static draw = function(_x, _y, _w, _h, _selecting, _m, _rx = 0, _ry = 0) {
x = _x;
y = _y;
w = _w;
h = _h;
current_selecting = _selecting;
while(is_array(current_selecting))
current_selecting = array_safe_get_fast(current_selecting, 0);
hovering = hover && point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
var amo = array_length(data);
var ww = _w / amo;
var total_width = 0;
draw_set_font(font);
for(var i = 0; i < amo; i++) {
if(is_string(data[i]))
total_width += string_width(data[i]) + ui(32);
}
display_button = total_width < _w;
if(display_button) {
var bx = _x;
var draw_sel = noone;
for(var i = 0; i < amo; i++) {
buttons[i].setFocusHover(active, hover);
buttons[i].tooltip = array_safe_get(tooltips, i, "");
var spr = i == 0 ? buttonSpr[0] : (i == amo - 1? buttonSpr[2] : buttonSpr[1]);
if(_selecting == i) {
draw_sprite_stretched(spr, 2, floor(bx), _y, ceil(ww), _h);
draw_sel = [spr, bx];
} else {
buttons[i].draw(floor(bx), _y, ceil(ww), _h, _m, spr);
if(buttons[i].clicked) onClick(i);
}
if(is_string(data[i])) {
draw_set_text(font, fa_center, fa_center, fColor);
draw_text(bx + ww / 2, _y + _h / 2, data[i]);
} else if(sprite_exists(data[i])) {
draw_sprite_ui_uniform(data[i], i, bx + ww / 2, _y + _h / 2);
}
bx += ww;
}
if(draw_sel != noone)
draw_sprite_stretched_ext(draw_sel[0], 3, draw_sel[1], _y, ww, _h, COLORS._main_accent, 1);
if(point_in_rectangle(_m[0], _m[1], _x, _y, _x + w, _y + _h)) {
if(is_array(data) && key_mod_press(SHIFT)) {
var len = array_length(data);
if(len) {
if(mouse_wheel_down()) onClick(safe_mod(_selecting + 1 + len, len));
if(mouse_wheel_up()) onClick(safe_mod(_selecting - 1 + len, len));
}
}
}
} else {
sb_small.setFocusHover(active, hover);
sb_small.draw(_x, _y, _w, _h, data[_selecting], _m, _rx, _ry);
}
if(WIDGET_CURRENT == self)
draw_sprite_stretched_ext(THEME.widget_selecting, 0, x - ui(3), y - ui(3), w + ui(6), h + ui(6), COLORS._main_accent, 1);
resetFocus();
return h;
}
static clone = function() { #region
var cln = new buttonGroup(data, onClick);
return cln;
} #endregion
}

View file

@ -0,0 +1,133 @@
// 2024-04-18 08:59:10
function buttonGroup(_data, _onClick) : widget() constructor {
data = _data;
onClick = _onClick;
display_button = false;
buttonSpr = [ THEME.button_left, THEME.button_middle, THEME.button_right ];
fColor = COLORS._main_text;
current_selecting = 0;
tooltips = [];
for(var i = 0; i < array_length(data); i++)
buttons[i] = button(-1);
sb_small = new scrollBox(data, _onClick);
static setFont = function(font) {
self.font = font;
return self;
}
static setTooltips = function(tt) { tooltips = tt; return self; }
static trigger = function() {
if(current_selecting + 1 >= array_length(data))
onClick(0);
else
onClick(current_selecting + 1);
}
static setInteract = function(interactable = noone) {
self.interactable = interactable;
for(var i = 0; i < array_length(data); i++)
buttons[i].interactable = interactable;
sb_small.interactable = interactable;
}
static register = function(parent = noone) {
if(display_button) {
array_push(WIDGET_ACTIVE, self);
self.parent = parent;
} else
sb_small.register(parent);
}
static drawParam = function(params) {
setParam(params);
sb_small.setParam(params);
return draw(params.x, params.y, params.w, params.h, params.data, params.m, params.rx, params.ry);
}
static draw = function(_x, _y, _w, _h, _selecting, _m, _rx = 0, _ry = 0) {
x = _x;
y = _y;
w = _w;
h = _h;
current_selecting = _selecting;
while(is_array(current_selecting))
current_selecting = array_safe_get_fast(current_selecting, 0);
hovering = hover && point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
var amo = array_length(data);
var ww = _w / amo;
var total_width = 0;
draw_set_font(font);
for(var i = 0; i < amo; i++) {
if(is_string(data[i]))
total_width += string_width(data[i]) + ui(32);
}
display_button = total_width < _w;
if(display_button) {
var bx = _x;
var draw_sel = noone;
for(var i = 0; i < amo; i++) {
buttons[i].setFocusHover(active, hover);
buttons[i].tooltip = array_safe_get(tooltips, i, "");
var spr = i == 0 ? buttonSpr[0] : (i == amo - 1? buttonSpr[2] : buttonSpr[1]);
if(_selecting == i) {
draw_sprite_stretched(spr, 2, floor(bx), _y, ceil(ww), _h);
draw_sel = [spr, bx];
} else {
buttons[i].draw(floor(bx), _y, ceil(ww), _h, _m, spr);
if(buttons[i].clicked) onClick(i);
}
if(is_string(data[i])) {
draw_set_text(font, fa_center, fa_center, fColor);
draw_text(bx + ww / 2, _y + _h / 2, data[i]);
} else if(sprite_exists(data[i])) {
draw_sprite_ui_uniform(data[i], i, bx + ww / 2, _y + _h / 2);
}
bx += ww;
}
if(draw_sel != noone)
draw_sprite_stretched_ext(draw_sel[0], 3, draw_sel[1], _y, ww, _h, COLORS._main_accent, 1);
if(point_in_rectangle(_m[0], _m[1], _x, _y, _x + w, _y + _h)) {
if(is_array(data) && key_mod_press(SHIFT)) {
var len = array_length(data);
if(len) {
if(mouse_wheel_down()) onClick(safe_mod(_selecting + 1 + len, len));
if(mouse_wheel_up()) onClick(safe_mod(_selecting - 1 + len, len));
}
}
}
} else {
sb_small.setFocusHover(active, hover);
sb_small.draw(_x, _y, _w, _h, data[_selecting], _m, _rx, _ry);
}
if(WIDGET_CURRENT == self)
draw_sprite_stretched_ext(THEME.widget_selecting, 0, x - ui(3), y - ui(3), w + ui(6), h + ui(6), COLORS._main_accent, 1);
resetFocus();
return h;
}
static clone = function() { #region
var cln = new buttonGroup(data, onClick);
return cln;
} #endregion
}

View file

@ -1,4 +1,4 @@
// 2024-04-15 17:50:18
// 2024-04-18 12:09:16
function canvas_draw_point_size(brush, _x, _y, _draw = false) { #region
if(brush.brush_surface == noone) {
@ -136,16 +136,33 @@ function canvas_draw_ellp_size(brush, _x0, _y0, _x1, _y1, _fill) { #region
return;
}
var _min_x = min(_x0, _x1) - 1;
var _max_x = max(_x0, _x1);
var _min_y = min(_y0, _y1) - 1;
var _max_y = max(_y0, _y1);
draw_set_circle_precision(64);
var _min_x = min(_x0, _x1) - 0.5;
var _max_x = max(_x0, _x1) - 0.5;
var _min_y = min(_y0, _y1) - 0.5;
var _max_y = max(_y0, _y1) - 0.5;
if(_fill) {
draw_set_circle_precision(64);
draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
if(brush.brush_surface == noone) {
if(_fill) draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
if(brush.brush_size == 1) {
draw_ellipse(_min_x, _min_y, _max_x, _max_y, 1);
} else if(brush.brush_size < global.FIX_POINTS_AMOUNT) {
var fx = global.FIX_POINTS[brush.brush_size];
for( var i = 0, n = array_length(fx); i < n; i++ )
draw_ellipse(_min_x + fx[i][0], _min_y + fx[i][1], _max_x + fx[i][0], _max_y + fx[i][1], 1);
} else {
draw_ellipse(_min_x, _min_y, _max_x, _max_y, brush.brush_size);
}
return;
}
if(_fill) draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
var samp = 64;
var cx = (_min_x + _max_x) / 2;
var cy = (_min_y + _max_y) / 2;

View file

@ -1,4 +1,4 @@
// 2024-04-15 17:50:17
// 2024-04-18 08:58:48
function canvas_draw_point_size(brush, _x, _y, _draw = false) { #region
if(brush.brush_surface == noone) {
@ -136,16 +136,33 @@ function canvas_draw_ellp_size(brush, _x0, _y0, _x1, _y1, _fill) { #region
return;
}
var _min_x = min(_x0, _x1) - 1;
var _max_x = max(_x0, _x1);
var _min_y = min(_y0, _y1) - 1;
var _max_y = max(_y0, _y1);
draw_set_circle_precision(64);
var _min_x = min(_x0, _x1) - 0.5;
var _max_x = max(_x0, _x1) - 0.5;
var _min_y = min(_y0, _y1) - 0.5;
var _max_y = max(_y0, _y1) - 0.5;
if(_fill) {
draw_set_circle_precision(64);
draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
if(brush.brush_surface == noone) {
if(_fill) draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
if(brush.brush_size == 1) {
draw_ellipse(_min_x, _min_y, _max_x, _max_y, 1);
} else if(brush.brush_size < global.FIX_POINTS_AMOUNT) {
var fx = global.FIX_POINTS[brush.brush_size];
for( var i = 0, n = array_length(fx); i < n; i++ )
draw_ellipse(_min_x + fx[i][0], _min_y + fx[i][1], _max_x + fx[i][0], _max_y + fx[i][1], 1);
} else {
draw_ellipse(_min_x, _min_y, _max_x, _max_y, brush.brush_size);
}
return;
}
if(_fill) draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
var samp = 64;
var cx = (_min_x + _max_x) / 2;
var cy = (_min_y + _max_y) / 2;

View file

@ -1,4 +1,4 @@
// 2024-04-16 15:02:26
// 2024-04-18 12:08:52
function canvas_tool_node(canvas, node) : canvas_tool() constructor {
self.canvas = canvas;
@ -23,25 +23,34 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
surface_reset_shader();
static destroy = function() {
noti_warning("Selected node has no surface output.");
if(applySelection) canvas.tool_selection.apply();
canvas.nodeTool = noone;
surface_free_safe(maskedSurface);
cleanUp();
}
static cleanUp = function() {
surface_free_safe(targetSurface);
surface_free_safe(maskedSurface);
nodeObject.destroy();
if(is_struct(nodeObject)) {
if(is_instanceof(nodeObject, Node))
nodeObject.destroy();
else {
var keys = struct_get_names(nodeObject);
for (var i = 0, n = array_length(keys); i < n; i++)
if(is_instanceof(nodeObject[$ keys[i]], Node))
nodeObject[$ keys[i]].destroy();
}
}
}
nodeObject = node.build(0, 0);
if(nodeObject == noone || !is_instanceof(nodeObject, Node)) {
noti_warning("Not tools only allows a single node.");
destroy();
return;
}
@ -66,6 +75,7 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
}
if(outputJunction == noone) {
noti_warning("Selected node has no surface output.");
destroy();
return;
}

View file

@ -1,4 +1,4 @@
// 2024-04-16 15:02:19
// 2024-04-17 08:13:29
function canvas_tool_node(canvas, node) : canvas_tool() constructor {
self.canvas = canvas;
@ -23,25 +23,34 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
surface_reset_shader();
static destroy = function() {
noti_warning("Selected node has no surface output.");
if(applySelection) canvas.tool_selection.apply();
canvas.nodeTool = noone;
surface_free_safe(maskedSurface);
cleanUp();
}
static cleanUp = function() {
surface_free_safe(targetSurface);
surface_free_safe(maskedSurface);
nodeObject.destroy();
if(is_struct(nodeObject)) {
if(is_instanceof(nodeObject, Node))
nodeObject.destroy();
else {
var keys = struct_get_names(nodeObject);
for (var i = 0, n = array_length(keys); i < n; i++)
if(is_instanceof(nodeObject[$ keys[i]], Node))
nodeObject[$ keys[i]].destroy();
}
}
}
nodeObject = node.build(0, 0);
if(nodeObject == noone || !is_instanceof(nodeObject, Node)) {
noti_warning("Not tools only allows a single node.");
destroy();
return;
}
@ -66,6 +75,7 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
}
if(outputJunction == noone) {
noti_warning("Selected node has no surface output.");
destroy();
return;
}

View file

@ -1,4 +1,4 @@
// 2024-04-15 19:18:42
// 2024-04-18 12:08:45
function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
self.selector = selector;
@ -230,15 +230,18 @@ function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
selection_sy = pos_y;
selection_mx = mouse_cur_x;
selection_my = mouse_cur_y;
}
}
if(key_press(vk_delete)) {
is_selected = false;
surface_free(selection_surface);
}
if(key_press(ord("C"), MOD_KEY.ctrl)) copySelection();
} else if(key_press(vk_escape)) {
apply();
} else if(key_press(ord("C"), MOD_KEY.ctrl)) copySelection();
} #endregion
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region

View file

@ -1,4 +1,4 @@
// 2024-04-15 19:18:37
// 2024-04-18 09:09:57
function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
self.selector = selector;
@ -230,15 +230,18 @@ function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
selection_sy = pos_y;
selection_mx = mouse_cur_x;
selection_my = mouse_cur_y;
}
}
if(key_press(vk_delete)) {
is_selected = false;
surface_free(selection_surface);
}
if(key_press(ord("C"), MOD_KEY.ctrl)) copySelection();
} else if(key_press(vk_escape)) {
apply();
} else if(key_press(ord("C"), MOD_KEY.ctrl)) copySelection();
} #endregion
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region

View file

@ -1,8 +1,10 @@
// 2024-04-16 10:03:25
// 2024-04-18 12:08:38
function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection(selector) constructor {
self.tool_attribute = toolAttr;
selecting = false;
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
mouse_cur_x = round((_mx - _x) / _s - 0.5);
@ -14,7 +16,7 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
var _fill_type = tool_attribute.fill8;
if(!selector.is_select_drag && mouse_press(mb_left, active)) {
selecting = true;
canvas_buffer = node.canvas_buffer;
preview_index = node.preview_index;
@ -58,7 +60,8 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
if(node.selection_tool_after != noone)
node.selection_tool_after.toggle();
node.selection_tool_after = noone;
}
} else
selector.apply();
}
}

View file

@ -1,8 +1,10 @@
// 2024-04-16 10:03:18
// 2024-04-18 09:15:40
function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection(selector) constructor {
self.tool_attribute = toolAttr;
selecting = false;
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
mouse_cur_x = round((_mx - _x) / _s - 0.5);
@ -14,7 +16,7 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
var _fill_type = tool_attribute.fill8;
if(!selector.is_select_drag && mouse_press(mb_left, active)) {
selecting = true;
canvas_buffer = node.canvas_buffer;
preview_index = node.preview_index;
@ -58,7 +60,8 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
if(node.selection_tool_after != noone)
node.selection_tool_after.toggle();
node.selection_tool_after = noone;
}
} else
selector.apply();
}
}

View file

@ -0,0 +1,81 @@
// 2024-04-18 12:08:32
function checkBoxGroup(sprs, _onClick) : widget() constructor {
self.sprs = sprs;
self.size = sprite_get_number(sprs);
onClick = _onClick;
holding = noone;
tooltips = [];
static trigger = function(ind, val) { onClick(ind, val); }
static setTooltips = function(tt) { tooltips = tt; return self; }
static drawParam = function(params) {
setParam(params);
return draw(params.x, params.y, params.data, params.m, params.s);
}
static draw = function(_x, _y, _value, _m, ss = ui(28), halign = fa_left, valign = fa_top) {
x = _x;
y = _y;
w = ss * size;
h = ss;
var _dx, _dy;
switch(halign) {
case fa_left: _dx = _x; break;
case fa_center: _dx = _x - ss / 2; break;
case fa_right: _dx = _x - ss; break;
}
switch(valign) {
case fa_top: _dy = _y; break;
case fa_center: _dy = _y - ss / 2; break;
case fa_bottom: _dy = _y - ss; break;
}
if(mouse_release(mb_left))
holding = noone;
var aa = interactable * 0.25 + 0.75;
for( var i = 0; i < size; i++ ) {
var spr = i == 0 ? THEME.button_left : (i == size - 1? THEME.button_right : THEME.button_middle);
var ind = _value[i] * 2;
if(hover && point_in_rectangle(_m[0], _m[1], _dx, _dy, _dx + ss, _dy + ss)) {
ind = 1
TOOLTIP = array_safe_get(tooltips, i, "");
if(holding != noone)
trigger(i, holding);
if(mouse_press(mb_left, active)) {
trigger(i, !_value[i]);
holding = _value[i];
}
} else
if(mouse_press(mb_left)) deactivate();
draw_sprite_stretched_ext(spr, ind, _dx, _dy, ss, ss, c_white, aa);
if(_value[i])
draw_sprite_stretched_ext(spr, 3, _dx, _dy, ss, ss, COLORS._main_accent, 1);
draw_sprite_ext(sprs, i, _dx + ss / 2, _dy + ss / 2, 1, 1, 0, c_white, 0.5 + _value[i] * 0.5);
_dx += ss;
}
if(WIDGET_CURRENT == self)
draw_sprite_stretched_ext(THEME.widget_selecting, 0, _dx - ui(3), _dy - ui(3), ss + ui(6), ss + ui(6), COLORS._main_accent, 1);
resetFocus();
return h;
}
static clone = function() { #region
var cln = new checkBoxGroup(sprs, onClick);
return cln;
} #endregion
}

View file

@ -0,0 +1,81 @@
// 2024-04-18 08:59:03
function checkBoxGroup(sprs, _onClick) : widget() constructor {
self.sprs = sprs;
self.size = sprite_get_number(sprs);
onClick = _onClick;
holding = noone;
tooltips = [];
static trigger = function(ind, val) { onClick(ind, val); }
static setTooltips = function(tt) { tooltips = tt; return self; }
static drawParam = function(params) {
setParam(params);
return draw(params.x, params.y, params.data, params.m, params.s);
}
static draw = function(_x, _y, _value, _m, ss = ui(28), halign = fa_left, valign = fa_top) {
x = _x;
y = _y;
w = ss * size;
h = ss;
var _dx, _dy;
switch(halign) {
case fa_left: _dx = _x; break;
case fa_center: _dx = _x - ss / 2; break;
case fa_right: _dx = _x - ss; break;
}
switch(valign) {
case fa_top: _dy = _y; break;
case fa_center: _dy = _y - ss / 2; break;
case fa_bottom: _dy = _y - ss; break;
}
if(mouse_release(mb_left))
holding = noone;
var aa = interactable * 0.25 + 0.75;
for( var i = 0; i < size; i++ ) {
var spr = i == 0 ? THEME.button_left : (i == size - 1? THEME.button_right : THEME.button_middle);
var ind = _value[i] * 2;
if(hover && point_in_rectangle(_m[0], _m[1], _dx, _dy, _dx + ss, _dy + ss)) {
ind = 1
TOOLTIP = array_safe_get(tooltips, i, "");
if(holding != noone)
trigger(i, holding);
if(mouse_press(mb_left, active)) {
trigger(i, !_value[i]);
holding = _value[i];
}
} else
if(mouse_press(mb_left)) deactivate();
draw_sprite_stretched_ext(spr, ind, _dx, _dy, ss, ss, c_white, aa);
if(_value[i])
draw_sprite_stretched_ext(spr, 3, _dx, _dy, ss, ss, COLORS._main_accent, 1);
draw_sprite_ext(sprs, i, _dx + ss / 2, _dy + ss / 2, 1, 1, 0, c_white, 0.5 + _value[i] * 0.5);
_dx += ss;
}
if(WIDGET_CURRENT == self)
draw_sprite_stretched_ext(THEME.widget_selecting, 0, _dx - ui(3), _dy - ui(3), ss + ui(6), ss + ui(6), COLORS._main_accent, 1);
resetFocus();
return h;
}
static clone = function() { #region
var cln = new checkBoxGroup(sprs, onClick);
return cln;
} #endregion
}

View file

@ -1,4 +1,4 @@
// 2024-04-16 08:32:52
// 2024-04-18 12:08:21
#region save
globalvar LOADING, CLONING, CLONING_GROUP;
globalvar CONNECTION_CONFLICT, LOADING_VERSION;
@ -39,7 +39,7 @@
LATEST_VERSION = 11600;
VERSION = 11700;
SAVE_VERSION = 11690;
VERSION_STRING = "1.17.rc1";
VERSION_STRING = "1.17.rc3";
BUILD_NUMBER = 11700;
globalvar HOTKEYS, HOTKEY_CONTEXT;

View file

@ -1,4 +1,4 @@
// 2024-04-15 17:50:18
// 2024-04-18 12:08:17
#region save
globalvar LOADING, CLONING, CLONING_GROUP;
globalvar CONNECTION_CONFLICT, LOADING_VERSION;
@ -39,7 +39,7 @@
LATEST_VERSION = 11600;
VERSION = 11700;
SAVE_VERSION = 11690;
VERSION_STRING = "1.17.rc1";
VERSION_STRING = "1.17.rc3";
BUILD_NUMBER = 11700;
globalvar HOTKEYS, HOTKEY_CONTEXT;

View file

@ -0,0 +1,341 @@
// 2024-04-18 12:08:08
function LOAD(safe = false) { #region
if(DEMO) return false;
var path = get_open_filename("Pixel Composer project (.pxc)|*.pxc;*.cpxc", "");
key_release();
if(path == "") return;
if(filename_ext(path) != ".json" && filename_ext(path) != ".pxc") return;
gc_collect();
var proj = LOAD_PATH(path, false, safe);
} #endregion
function TEST_PATH(path) { #region
TESTING = true;
TEST_ERROR = true;
PROJECT.cleanup();
PROJECT = new Project();
PANEL_GRAPH.setProject(PROJECT);
LOAD_AT(path);
} #endregion
function LOAD_PATH(path, readonly = false, safe_mode = false) { #region
for( var i = 0, n = array_length(PROJECTS); i < n; i++ )
if(PROJECTS[i].path == path) return;
var _PROJECT = PROJECT;
PROJECT = new Project();
if(_PROJECT == noone) {
PROJECTS = [ PROJECT ];
} else if(_PROJECT.path == "" && !_PROJECT.modified) {
var ind = array_find(PROJECTS, _PROJECT);
if(ind == -1) ind = 0;
PROJECTS[ind] = PROJECT;
if(!IS_CMD) PANEL_GRAPH.setProject(PROJECT);
} else {
if(!IS_CMD) {
var graph = new Panel_Graph(PROJECT);
PANEL_GRAPH.panel.setContent(graph, true);
PANEL_GRAPH = graph;
}
array_push(PROJECTS, PROJECT);
}
var res = LOAD_AT(path, readonly);
if(!res) return false;
PROJECT.safeMode = safe_mode;
if(!IS_CMD)
setFocus(PANEL_GRAPH.panel);
return PROJECT;
} #endregion
function LOAD_AT(path, readonly = false, override = false) { #region
static log = false;
CALL("load");
printIf(log, $"========== Loading {path} =========="); var t0 = get_timer(), t1 = get_timer();
if(DEMO) return false;
if(!file_exists_empty(path)) {
log_warning("LOAD", $"File not found: {path}");
return false;
}
if(filename_ext(path) != ".json" && filename_ext(path) != ".pxc" && filename_ext(path) != ".cpxc") {
log_warning("LOAD", "File not a valid PROJECT");
return false;
}
LOADING = true;
if(override) {
nodeCleanUp();
clearPanel();
setPanel();
if(!TESTING)
instance_destroy(_p_dialog);
ds_list_clear(ERRORS);
}
printIf(log, $" > Check file : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
var temp_path = TEMPDIR;
directory_verify(temp_path);
var temp_file_path = TEMPDIR + string(UUID_generate(6));
if(file_exists_empty(temp_file_path)) file_delete(temp_file_path);
file_copy(path, temp_file_path);
PROJECT.readonly = readonly;
SET_PATH(PROJECT, path);
printIf(log, $" > Create temp : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
var _load_content;
var _ext = filename_ext(path);
var s;
if(_ext == ".pxc") {
var f = file_text_open_read(path);
s = file_text_read_all(f);
file_text_close(f);
} else if(_ext == ".cpxc") {
var b = buffer_decompress(buffer_load(path));
s = buffer_read(b, buffer_string);
}
_load_content = json_try_parse(s);
printIf(log, $" > Load struct : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
if(struct_has(_load_content, "version")) {
var _v = _load_content.version;
PROJECT.version = _v;
LOADING_VERSION = _v;
if(PREFERENCES.notify_load_version && floor(_v) != floor(SAVE_VERSION)) {
var warn = $"File version mismatch : loading file version {_v} to Pixel Composer {SAVE_VERSION}";
log_warning("LOAD", warn);
}
} else {
var warn = $"File version mismatch : loading old format to Pixel Composer {SAVE_VERSION}";
log_warning("LOAD", warn);
}
printIf(log, $" > Load meta : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
var create_list = ds_list_create();
if(struct_has(_load_content, "nodes")) {
try {
var _node_list = _load_content.nodes;
for(var i = 0, n = array_length(_node_list); i < n; i++) {
var _node = nodeLoad(_node_list[i]);
if(_node) ds_list_add(create_list, _node);
}
} catch(e) {
log_warning("LOAD", exception_print(e));
}
}
printIf(log, $" > Load nodes : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
if(struct_has(_load_content, "animator")) {
var _anim_map = _load_content.animator;
PROJECT.animator.frames_total = struct_try_get(_anim_map, "frames_total", 30);
PROJECT.animator.framerate = struct_try_get(_anim_map, "framerate", 30);
PROJECT.animator.frame_range = struct_try_get(_anim_map, "frame_range", noone);
}
} catch(e) {
log_warning("LOAD, animator", exception_print(e));
}
if(struct_has(_load_content, "onion_skin"))
struct_override(PROJECT.onion_skin, _load_content.onion_skin);
if(struct_has(_load_content, "previewGrid"))
struct_override(PROJECT.previewGrid, _load_content.previewGrid);
if(struct_has(_load_content, "graphGrid"))
struct_override(PROJECT.graphGrid, _load_content.graphGrid);
if(struct_has(_load_content, "attributes"))
struct_override(PROJECT.attributes, _load_content.attributes);
PROJECT.setPalette();
if(struct_has(_load_content, "notes")) {
PROJECT.notes = array_create(array_length(_load_content.notes));
for( var i = 0, n = array_length(_load_content.notes); i < n; i++ )
PROJECT.notes[i] = new Note.deserialize(_load_content.notes[i]);
}
try {
if(struct_has(_load_content, "metadata"))
PROJECT.meta.deserialize(_load_content.metadata);
} catch(e) {
log_warning("LOAD, metadata", exception_print(e));
}
PROJECT.globalNode = new Node_Global();
try {
if(struct_has(_load_content, "global"))
PROJECT.globalNode.deserialize(_load_content.global);
else if(struct_has(_load_content, "global_node"))
PROJECT.globalNode.deserialize(_load_content.global_node);
} catch(e) {
log_warning("LOAD, global", exception_print(e));
}
try {
if(struct_has(_load_content, "addon")) {
var _addon = _load_content.addon;
PROJECT.addons = _addon;
struct_foreach(_addon, function(_name, _value) { addonLoad(_name, false); });
} else
PROJECT.addons = {};
} catch(e) {
log_warning("LOAD, addon", exception_print(e));
}
printIf(log, $" > Load data : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
ds_queue_clear(CONNECTION_CONFLICT);
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].loadGroup();
} catch(e) {
log_warning("LOAD, group", exception_print(e));
return false;
}
printIf(log, $" > Load group : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].postDeserialize();
} catch(e) {
log_warning("LOAD, deserialize", exception_print(e));
}
printIf(log, $" > Deserialize: {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].applyDeserialize();
} catch(e) {
log_warning("LOAD, apply deserialize", exception_print(e));
}
printIf(log, $" > Apply deserialize : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].preConnect();
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].connect();
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].postConnect();
} catch(e) {
log_warning("LOAD, connect", exception_print(e));
}
printIf(log, $" > Connect : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
if(!ds_queue_empty(CONNECTION_CONFLICT)) {
var pass = 0;
try {
while(++pass < 4 && !ds_queue_empty(CONNECTION_CONFLICT)) {
var size = ds_queue_size(CONNECTION_CONFLICT);
log_message("LOAD", $"[Connect] {size} Connection conflict(s) detected (pass: {pass})");
repeat(size) ds_queue_dequeue(CONNECTION_CONFLICT).connect();
repeat(size) ds_queue_dequeue(CONNECTION_CONFLICT).postConnect();
Render();
}
if(!ds_queue_empty(CONNECTION_CONFLICT))
log_warning("LOAD", "Some connection(s) is unsolved. This may caused by render node not being update properly, or image path is broken.");
} catch(e) {
log_warning("LOAD, connect solver", exception_print(e));
}
}
printIf(log, $" > Conflict : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].postLoad();
} catch(e) {
log_warning("LOAD, connect", exception_print(e));
}
printIf(log, $" > Post load : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].clearInputCache();
} catch(e) {
log_warning("LOAD, connect", exception_print(e));
}
printIf(log, $" > Clear cache : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
RENDER_ALL_REORDER
LOADING = false;
PROJECT.modified = false;
log_message("FILE", "load " + path, THEME.noti_icon_file_load);
log_console("Loaded project: " + path);
if(!IS_CMD) PANEL_MENU.setNotiIcon(THEME.noti_icon_file_load);
refreshNodeMap();
printIf(log, $" > Refresh map : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
if(struct_has(_load_content, "timelines") && !array_empty(_load_content.timelines.contents))
PROJECT.timelines.deserialize(_load_content.timelines);
printIf(log, $" > Timeline : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
if(!IS_CMD) run_in(1, PANEL_GRAPH.toCenterNode);
printIf(log, $"========== Load {ds_map_size(PROJECT.nodeMap)} nodes completed in {(get_timer() - t0) / 1000} ms ==========");
return true;
} #endregion
function __IMPORT_ZIP() { #region
var path = get_open_filename("Pixel Composer portable project (.zip)|*.zip", "");
var _fname = filename_name_only(path);
var _fext = filename_ext(path);
if(_fext != ".zip") return false;
directory_verify(TEMPDIR + "proj/");
var _dir = TEMPDIR + "proj/" + _fname;
directory_create(_dir);
zip_unzip(path, _dir);
var _f = file_find_first(_dir + "/*.pxc", fa_none);
var _proj = $"{_dir}/{_f}";
print(_proj);
if(!file_exists_empty(_proj)) return false;
LOAD_PATH(_proj, true);
} #endregion

View file

@ -0,0 +1,341 @@
// 2024-04-18 11:54:26
function LOAD(safe = false) { #region
if(DEMO) return false;
var path = get_open_filename("Pixel Composer project (.pxc)|*.pxc;*.cpxc", "");
key_release();
if(path == "") return;
if(filename_ext(path) != ".json" && filename_ext(path) != ".pxc") return;
gc_collect();
var proj = LOAD_PATH(path, false, safe);
} #endregion
function TEST_PATH(path) { #region
TESTING = true;
TEST_ERROR = true;
PROJECT.cleanup();
PROJECT = new Project();
PANEL_GRAPH.setProject(PROJECT);
LOAD_AT(path);
} #endregion
function LOAD_PATH(path, readonly = false, safe_mode = false) { #region
for( var i = 0, n = array_length(PROJECTS); i < n; i++ )
if(PROJECTS[i].path == path) return;
var _PROJECT = PROJECT;
PROJECT = new Project();
if(_PROJECT == noone) {
PROJECTS = [ PROJECT ];
} else if(_PROJECT.path == "" && !_PROJECT.modified) {
var ind = array_find(PROJECTS, _PROJECT);
if(ind == -1) ind = 0;
PROJECTS[ind] = PROJECT;
if(!IS_CMD) PANEL_GRAPH.setProject(PROJECT);
} else {
if(!IS_CMD) {
var graph = new Panel_Graph(PROJECT);
PANEL_GRAPH.panel.setContent(graph, true);
PANEL_GRAPH = graph;
}
array_push(PROJECTS, PROJECT);
}
var res = LOAD_AT(path, readonly);
if(!res) return false;
PROJECT.safeMode = safe_mode;
if(!IS_CMD)
setFocus(PANEL_GRAPH.panel);
return PROJECT;
} #endregion
function LOAD_AT(path, readonly = false, override = false) { #region
static log = false;
CALL("load");
printIf(log, $"========== Loading {path} =========="); var t0 = get_timer(), t1 = get_timer();
if(DEMO) return false;
if(!file_exists_empty(path)) {
log_warning("LOAD", $"File not found: {path}");
return false;
}
if(filename_ext(path) != ".json" && filename_ext(path) != ".pxc" && filename_ext(path) != ".cpxc") {
log_warning("LOAD", "File not a valid PROJECT");
return false;
}
LOADING = true;
if(override) {
nodeCleanUp();
clearPanel();
setPanel();
if(!TESTING)
instance_destroy(_p_dialog);
ds_list_clear(ERRORS);
}
printIf(log, $" > Check file : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
var temp_path = TEMPDIR;
directory_verify(temp_path);
var temp_file_path = TEMPDIR + string(UUID_generate(6));
if(file_exists_empty(temp_file_path)) file_delete(temp_file_path);
file_copy(path, temp_file_path);
PROJECT.readonly = readonly;
SET_PATH(PROJECT, path);
printIf(log, $" > Create temp : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
var _load_content;
var _ext = filename_ext(path);
var s;
if(_ext == ".pxc") {
var f = file_text_open_read(path);
s = file_text_read_all(f);
file_text_close(f);
} else if(_ext == ".cpxc") {
var b = buffer_decompress(buffer_load(path));
s = buffer_read(b, buffer_string);
}
_load_content = json_try_parse(s);
printIf(log, $" > Load struct : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
if(struct_has(_load_content, "version")) {
var _v = _load_content.version;
PROJECT.version = _v;
LOADING_VERSION = _v;
if(PREFERENCES.notify_load_version && floor(_v) != floor(SAVE_VERSION)) {
var warn = $"File version mismatch : loading file version {_v} to Pixel Composer {SAVE_VERSION}";
log_warning("LOAD", warn);
}
} else {
var warn = $"File version mismatch : loading old format to Pixel Composer {SAVE_VERSION}";
log_warning("LOAD", warn);
}
printIf(log, $" > Load meta : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
var create_list = ds_list_create();
if(struct_has(_load_content, "nodes")) {
try {
var _node_list = _load_content.nodes;
for(var i = 0, n = array_length(_node_list); i < n; i++) {
var _node = nodeLoad(_node_list[i]);
if(_node) ds_list_add(create_list, _node);
}
} catch(e) {
log_warning("LOAD", exception_print(e));
}
}
printIf(log, $" > Load nodes : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
if(struct_has(_load_content, "animator")) {
var _anim_map = _load_content.animator;
PROJECT.animator.frames_total = struct_try_get(_anim_map, "frames_total", 30);
PROJECT.animator.framerate = struct_try_get(_anim_map, "framerate", 30);
PROJECT.animator.frame_range = struct_try_get(_anim_map, "frame_range", noone);
}
} catch(e) {
log_warning("LOAD, animator", exception_print(e));
}
if(struct_has(_load_content, "onion_skin"))
struct_override(PROJECT.onion_skin, _load_content.onion_skin);
if(struct_has(_load_content, "previewGrid"))
struct_override(PROJECT.previewGrid, _load_content.previewGrid);
if(struct_has(_load_content, "graphGrid"))
struct_override(PROJECT.graphGrid, _load_content.graphGrid);
if(struct_has(_load_content, "attributes"))
struct_override(PROJECT.attributes, _load_content.attributes);
PROJECT.setPalette();
if(struct_has(_load_content, "notes")) {
PROJECT.notes = array_create(array_length(_load_content.notes));
for( var i = 0, n = array_length(_load_content.notes); i < n; i++ )
PROJECT.notes[i] = new Note.deserialize(_load_content.notes[i]);
}
try {
if(struct_has(_load_content, "metadata"))
PROJECT.meta.deserialize(_load_content.metadata);
} catch(e) {
log_warning("LOAD, metadata", exception_print(e));
}
PROJECT.globalNode = new Node_Global();
try {
if(struct_has(_load_content, "global"))
PROJECT.globalNode.deserialize(_load_content.global);
else if(struct_has(_load_content, "global_node"))
PROJECT.globalNode.deserialize(_load_content.global_node);
} catch(e) {
log_warning("LOAD, global", exception_print(e));
}
try {
if(struct_has(_load_content, "addon")) {
var _addon = _load_content.addon;
PROJECT.addons = _addon;
struct_foreach(_addon, function(_name, _value) { addonLoad(_name, false); });
} else
PROJECT.addons = {};
} catch(e) {
log_warning("LOAD, addon", exception_print(e));
}
printIf(log, $" > Load data : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
ds_queue_clear(CONNECTION_CONFLICT);
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].loadGroup();
} catch(e) {
log_warning("LOAD, group", exception_print(e));
return false;
}
printIf(log, $" > Load group : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].postDeserialize();
} catch(e) {
log_warning("LOAD, deserialize", exception_print(e));
}
printIf(log, $" > Deserialize: {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].applyDeserialize();
} catch(e) {
log_warning("LOAD, apply deserialize", exception_print(e));
}
printIf(log, $" > Apply deserialize : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].preConnect();
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].connect();
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].postConnect();
} catch(e) {
log_warning("LOAD, connect", exception_print(e));
}
printIf(log, $" > Connect : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
if(!ds_queue_empty(CONNECTION_CONFLICT)) {
var pass = 0;
try {
while(++pass < 4 && !ds_queue_empty(CONNECTION_CONFLICT)) {
var size = ds_queue_size(CONNECTION_CONFLICT);
log_message("LOAD", $"[Connect] {size} Connection conflict(s) detected (pass: {pass})");
repeat(size) ds_queue_dequeue(CONNECTION_CONFLICT).connect();
repeat(size) ds_queue_dequeue(CONNECTION_CONFLICT).postConnect();
Render();
}
if(!ds_queue_empty(CONNECTION_CONFLICT))
log_warning("LOAD", "Some connection(s) is unsolved. This may caused by render node not being update properly, or image path is broken.");
} catch(e) {
log_warning("LOAD, connect solver", exception_print(e));
}
}
printIf(log, $" > Conflict : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].postLoad();
} catch(e) {
log_warning("LOAD, connect", exception_print(e));
}
printIf(log, $" > Post load : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
try {
for(var i = 0; i < ds_list_size(create_list); i++)
create_list[| i].clearInputCache();
} catch(e) {
log_warning("LOAD, connect", exception_print(e));
}
printIf(log, $" > Clear cache : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
RENDER_ALL_REORDER
LOADING = false;
PROJECT.modified = false;
log_message("FILE", "load " + path, THEME.noti_icon_file_load);
log_console("Loaded project: " + path);
if(!IS_CMD) PANEL_MENU.setNotiIcon(THEME.noti_icon_file_load);
refreshNodeMap();
printIf(log, $" > Refresh map : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
if(struct_has(_load_content, "timelines") && !array_empty(_load_content.timelines.contents))
PROJECT.timelines.deserialize(_load_content.timelines);
printIf(log, $" > Timeline : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();
if(!IS_CMD) run_in(1, PANEL_GRAPH.toCenterNode);
printIf(log, $"========== Load {ds_map_size(PROJECT.nodeMap)} nodes completed in {(get_timer() - t0) / 1000} ms ==========");
return true;
} #endregion
function __IMPORT_ZIP() { #region
var path = get_open_filename("Pixel Composer portable project (.zip)|*.zip", "");
var _fname = filename_name_only(path);
var _fext = filename_ext(path);
if(_fext != ".zip") return false;
directory_verify(TEMPDIR + "proj/");
var _dir = TEMPDIR + "proj/" + _fname;
directory_create(_dir);
zip_unzip(path, _dir);
var _f = file_find_first(_dir + "/*.pxc", fa_none);
var _proj = $"{_dir}/{_f}";
print(_proj);
if(!file_exists_empty(_proj)) return false;
LOAD_PATH(_proj, true);
} #endregion

View file

@ -0,0 +1,74 @@
// 2024-04-18 08:44:11
function Node_Atlas(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Pixel Expand";
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 1] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
active_index = 1;
inputs[| 2] = nodeValue("Method", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Radial", "Scan" ]);
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [ 1, 0, 2 ];
temp_surface = array_create(2);
attribute_surface_depth();
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var _surf = _data[0];
var _meth = _data[2];
var _dim = surface_get_dimension(_data[0]);
for( var i = 0; i < 2; i++ ) temp_surface[i] = surface_verify(temp_surface[i], _dim[0], _dim[1]);
if(_meth == 0) {
var _bg = 0;
var _itr = ceil(max(_dim[0], _dim[1]) / 64);
surface_set_shader(temp_surface[!_bg]);
draw_surface_safe(_surf);
surface_reset_shader();
repeat(_itr) {
surface_set_shader(temp_surface[_bg], sh_atlas);
shader_set_f("dimension", _dim);
draw_surface(temp_surface[!_bg], 0, 0);
surface_reset_shader();
_bg = !_bg;
}
surface_set_shader(_outSurf);
draw_surface_safe(temp_surface[!_bg]);
surface_reset_shader();
} else if(_meth == 1) {
surface_set_shader(temp_surface[0], sh_atlas_scan);
shader_set_f("dimension", _dim);
shader_set_f("iteration", _dim[0]);
shader_set_i("axis", 0);
draw_surface_safe(_surf);
surface_reset_shader();
surface_set_shader(temp_surface[1], sh_atlas_scan);
shader_set_f("dimension", _dim);
shader_set_f("iteration", _dim[1]);
shader_set_i("axis", 1);
draw_surface_safe(temp_surface[0]);
surface_reset_shader();
surface_set_shader(_outSurf);
draw_surface_safe(temp_surface[1]);
surface_reset_shader();
}
return _outSurf;
} #endregion
}

View file

@ -0,0 +1,74 @@
// 2024-04-18 08:40:55
function Node_Atlas(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Pixel Expand";
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 1] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
active_index = 1;
inputs[| 2] = nodeValue("Method", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Radial", "Scan" ]);
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [ 1, 0, 2 ];
temp_surface = array_create(2);
attribute_surface_depth();
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var _surf = _data[0];
var _meth = _data[2];
var _dim = surface_get_dimension(_data[0]);
for( var i = 0; i < 2; i++ ) temp_surface[i] = surface_verify(temp_surface[i], _dim[0], _dim[1]);
if(_meth == 0) {
var _bg = 0;
var _itr = ceil(max(_dim[0], _dim[1]) / 64);
surface_set_shader(temp_surface[!_bg]);
draw_surface_safe(_surf);
surface_reset_shader();
repeat(_itr) {
surface_set_shader(temp_surface[_bg], sh_atlas);
shader_set_f("dimension", _dim);
draw_surface(temp_surface[!_bg], 0, 0);
surface_reset_shader();
_bg = !_bg;
}
surface_set_shader(_outSurf);
draw_surface_safe(temp_surface[!_bg]);
surface_reset_shader();
} else if(_meth == 1) {
surface_set_shader(temp_surface[0], sh_atlas_scan);
shader_set_f("dimension", _dim);
shader_set_f("iteration", _dim[0]);
shader_set_i("axis", 0);
draw_surface_safe(_surf);
surface_reset_shader();
surface_set_shader(temp_surface[1], sh_atlas_scan);
shader_set_f("dimension", _dim);
shader_set_f("iteration", _dim[1]);
shader_set_i("axis", 1);
draw_surface_safe(temp_surface[0]);
surface_reset_shader();
surface_set_shader(_outSurf);
draw_surface_safe(temp_surface[1]);
surface_reset_shader();
}
return _outSurf;
} #endregion
}

View file

@ -1,4 +1,4 @@
// 2024-04-16 14:17:00
// 2024-04-18 12:08:01
function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Canvas";
color = COLORS.node_blend_canvas;
@ -215,10 +215,12 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
tool_attribute.drawLayer = 0;
tool_attribute.pickColor = c_white;
tool_drawLayer_edit = new buttonGroup( [ THEME.canvas_draw_layer, THEME.canvas_draw_layer, THEME.canvas_draw_layer ], function(val) { tool_attribute.drawLayer = val; });
tool_drawLayer_edit = new buttonGroup( [ THEME.canvas_draw_layer, THEME.canvas_draw_layer, THEME.canvas_draw_layer ], function(val) { tool_attribute.drawLayer = val; })
.setTooltips( [ "Draw on top", "Draw behind", "Draw inside" ] );
tool_attribute.mirror = [ false, false, false ];
tool_mirror_edit = new checkBoxGroup( THEME.canvas_mirror, function(ind, val) { tool_attribute.mirror[ind] = val; });
tool_mirror_edit = new checkBoxGroup( THEME.canvas_mirror, function(ind, val) { tool_attribute.mirror[ind] = val; })
.setTooltips( [ "Toggle diagonal", "", "" ] );
tool_settings = [ [ "", tool_channel_edit, "channel", tool_attribute ],
[ "", tool_drawLayer_edit, "drawLayer", tool_attribute ],
@ -513,12 +515,12 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
surface_clear(drawing_surface);
} #endregion
function surface_store_buffers(index = preview_index) { #region
static surface_store_buffers = function(index = preview_index) { #region
for( var i = 0; i < attributes.frames; i++ )
surface_store_buffer(i);
} #endregion
function surface_store_buffer(index = preview_index) { #region
static surface_store_buffer = function(index = preview_index) { #region
if(index >= attributes.frames) return;
buffer_delete(canvas_buffer[index]);
@ -818,6 +820,42 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
draw_surface_ext_safe(preview_draw_mask, 0, 0, 1, 1, 0, c_white, 1);
shader_reset();
draw_set_color(COLORS._main_accent);
if(tool_selection.is_selected) {
var _spx = tool_selection.selection_position[0];
var _spy = tool_selection.selection_position[1];
var _spw = tool_selection.selection_size[0];
var _sph = tool_selection.selection_size[1];
var _x0 = _x + _spx * _s;
var _x1 = _x + (_spx + _spw) * _s;
var _xc = _x + (_spx + _spw / 2) * _s;
var _y0 = _y + _spy * _s;
var _y1 = _y + (_spy + _sph) * _s;
var _yc = _y + (_spy + _sph / 2) * _s;
if(tool_attribute.mirror[1]) draw_line(_xc, _y0, _xc, _y1);
if(tool_attribute.mirror[2]) draw_line(_x0, _yc, _x1, _yc);
} else {
var _x0 = _x;
var _x1 = _x + _dim[0] * _s;
var _xc = _x + _dim[0] / 2 * _s;
var _y0 = _y;
var _y1 = _y + _dim[1] * _s;
var _yc = _y + _dim[1] / 2 * _s;
if(tool_attribute.mirror[0] == false) {
if(tool_attribute.mirror[1]) draw_line(_xc, _y0, _xc, _y1);
if(tool_attribute.mirror[2]) draw_line(_x0, _yc, _x1, _yc);
} else {
if(tool_attribute.mirror[1]) draw_line(_x0, _y1, _x1, _y0);
if(tool_attribute.mirror[2]) draw_line(_x0, _y0, _x1, _y1);
}
}
if(_tool) _tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
#endregion
@ -917,8 +955,6 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
}
} #endregion
static getPreviewValues = function() { return nodeTool == noone || nodeTool.applySelection? output_surface : noone; }
static doSerialize = function(_map) { #region
surface_store_buffers();
var _buff = array_create(attributes.frames);

View file

@ -1,4 +1,4 @@
// 2024-04-16 14:16:53
// 2024-04-18 10:49:51
function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Canvas";
color = COLORS.node_blend_canvas;
@ -215,10 +215,12 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
tool_attribute.drawLayer = 0;
tool_attribute.pickColor = c_white;
tool_drawLayer_edit = new buttonGroup( [ THEME.canvas_draw_layer, THEME.canvas_draw_layer, THEME.canvas_draw_layer ], function(val) { tool_attribute.drawLayer = val; });
tool_drawLayer_edit = new buttonGroup( [ THEME.canvas_draw_layer, THEME.canvas_draw_layer, THEME.canvas_draw_layer ], function(val) { tool_attribute.drawLayer = val; })
.setTooltips( [ "Draw on top", "Draw behind", "Draw inside" ] );
tool_attribute.mirror = [ false, false, false ];
tool_mirror_edit = new checkBoxGroup( THEME.canvas_mirror, function(ind, val) { tool_attribute.mirror[ind] = val; });
tool_mirror_edit = new checkBoxGroup( THEME.canvas_mirror, function(ind, val) { tool_attribute.mirror[ind] = val; })
.setTooltips( [ "Toggle diagonal", "", "" ] );
tool_settings = [ [ "", tool_channel_edit, "channel", tool_attribute ],
[ "", tool_drawLayer_edit, "drawLayer", tool_attribute ],
@ -513,12 +515,12 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
surface_clear(drawing_surface);
} #endregion
function surface_store_buffers(index = preview_index) { #region
static surface_store_buffers = function(index = preview_index) { #region
for( var i = 0; i < attributes.frames; i++ )
surface_store_buffer(i);
} #endregion
function surface_store_buffer(index = preview_index) { #region
static surface_store_buffer = function(index = preview_index) { #region
if(index >= attributes.frames) return;
buffer_delete(canvas_buffer[index]);
@ -818,6 +820,42 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
draw_surface_ext_safe(preview_draw_mask, 0, 0, 1, 1, 0, c_white, 1);
shader_reset();
draw_set_color(COLORS._main_accent);
if(tool_selection.is_selected) {
var _spx = tool_selection.selection_position[0];
var _spy = tool_selection.selection_position[1];
var _spw = tool_selection.selection_size[0];
var _sph = tool_selection.selection_size[1];
var _x0 = _x + _spx * _s;
var _x1 = _x + (_spx + _spw) * _s;
var _xc = _x + (_spx + _spw / 2) * _s;
var _y0 = _y + _spy * _s;
var _y1 = _y + (_spy + _sph) * _s;
var _yc = _y + (_spy + _sph / 2) * _s;
if(tool_attribute.mirror[1]) draw_line(_xc, _y0, _xc, _y1);
if(tool_attribute.mirror[2]) draw_line(_x0, _yc, _x1, _yc);
} else {
var _x0 = _x;
var _x1 = _x + _dim[0] * _s;
var _xc = _x + _dim[0] / 2 * _s;
var _y0 = _y;
var _y1 = _y + _dim[1] * _s;
var _yc = _y + _dim[1] / 2 * _s;
if(tool_attribute.mirror[0] == false) {
if(tool_attribute.mirror[1]) draw_line(_xc, _y0, _xc, _y1);
if(tool_attribute.mirror[2]) draw_line(_x0, _yc, _x1, _yc);
} else {
if(tool_attribute.mirror[1]) draw_line(_x0, _y1, _x1, _y0);
if(tool_attribute.mirror[2]) draw_line(_x0, _y0, _x1, _y1);
}
}
if(_tool) _tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
#endregion
@ -917,8 +955,6 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
}
} #endregion
static getPreviewValues = function() { return nodeTool == noone || nodeTool.applySelection? output_surface : noone; }
static doSerialize = function(_map) { #region
surface_store_buffers();
var _buff = array_create(attributes.frames);

View file

@ -0,0 +1,110 @@
// 2024-04-18 12:07:51
function Node_Outline(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Outline";
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 1] = nodeValue("Width", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setMappable(15);
inputs[| 2] = nodeValue("Color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white);
inputs[| 3] = nodeValue("Blend", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, 0, "Blend outline color with the original color.");
inputs[| 4] = nodeValue("Blend alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
.setDisplay(VALUE_DISPLAY.slider)
.setMappable(16);
inputs[| 5] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
.setDisplay(VALUE_DISPLAY.enum_button, ["Inside", "Outside"]);
inputs[| 6] = nodeValue("Anti aliasing", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, 0);
inputs[| 7] = nodeValue("Oversample mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "How to deal with pixel outside the surface.\n - Empty: Use empty pixel\n - Clamp: Repeat edge pixel\n - Repeat: Repeat texture.")
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Clamp", "Repeat" ]);
inputs[| 8] = nodeValue("Start", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "Shift outline inside, outside the shape.")
.setMappable(17);
inputs[| 9] = nodeValue("Mask", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 10] = nodeValue("Mix", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
.setDisplay(VALUE_DISPLAY.slider);
inputs[| 11] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
active_index = 11;
inputs[| 12] = nodeValue("Crop border", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
__init_mask_modifier(9); // inputs 13, 14
//////////////////////////////////////////////////////////////////////////////////////////////////
inputs[| 15] = nodeValueMap("Width map", self);
inputs[| 16] = nodeValueMap("Blend alpha map", self);
inputs[| 17] = nodeValueMap("Start map", self);
//////////////////////////////////////////////////////////////////////////////////////////////////
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
outputs[| 1] = nodeValue("Outline", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [ 11,
["Surfaces", true], 0, 9, 10, 13, 14,
["Outline", false], 1, 15, 5, 8, 17, 12,
["Render", false], 2, 6,
["Blend", true, 3], 4, 16,
];
attribute_surface_depth();
attribute_oversample();
static step = function() { #region
var _side = getInputData(5);
inputs[| 12].setVisible(_side == 0);
__step_mask_modifier();
inputs[| 1].mappableStep();
inputs[| 4].mappableStep();
inputs[| 8].mappableStep();
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var ww = surface_get_width_safe(_data[0]);
var hh = surface_get_height_safe(_data[0]);
var cl = _data[2];
var blend = _data[3];
var side = _data[5];
var aa = _data[6];
var sam = struct_try_get(attributes, "oversample");
var _crop = _data[12];
surface_set_shader(_outSurf, sh_outline);
shader_set_f("dimension", ww, hh);
shader_set_f_map("borderSize", _data[1], _data[15], inputs[| 1]);
shader_set_f_map("borderStart", _data[8], _data[17], inputs[| 8]);
shader_set_color("borderColor", cl);
shader_set_i("side", side);
shader_set_i("is_aa", aa);
shader_set_i("outline_only", _output_index);
shader_set_i("is_blend", blend);
shader_set_f_map("blend_alpha", _data[4], _data[16], inputs[| 4]);
shader_set_i("sampleMode", sam);
shader_set_i("crop_border", _crop);
draw_surface_safe(_data[0]);
surface_reset_shader();
__process_mask_modifier(_data);
_outSurf = mask_apply(_data[0], _outSurf, _data[9], _data[10]);
return _outSurf;
} #endregion
}

View file

@ -0,0 +1,110 @@
// 2024-04-17 19:15:17
function Node_Outline(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Outline";
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 1] = nodeValue("Width", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setMappable(15);
inputs[| 2] = nodeValue("Color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white);
inputs[| 3] = nodeValue("Blend", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, 0, "Blend outline color with the original color.");
inputs[| 4] = nodeValue("Blend alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
.setDisplay(VALUE_DISPLAY.slider)
.setMappable(16);
inputs[| 5] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
.setDisplay(VALUE_DISPLAY.enum_button, ["Inside", "Outside"]);
inputs[| 6] = nodeValue("Anti-aliasing", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, 0);
inputs[| 7] = nodeValue("Oversample mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "How to deal with pixel outside the surface.\n - Empty: Use empty pixel\n - Clamp: Repeat edge pixel\n - Repeat: Repeat texture.")
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Clamp", "Repeat" ]);
inputs[| 8] = nodeValue("Start", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "Shift outline inside, outside the shape.")
.setMappable(17);
inputs[| 9] = nodeValue("Mask", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 10] = nodeValue("Mix", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
.setDisplay(VALUE_DISPLAY.slider);
inputs[| 11] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
active_index = 11;
inputs[| 12] = nodeValue("Crop border", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
__init_mask_modifier(9); // inputs 13, 14
//////////////////////////////////////////////////////////////////////////////////////////////////
inputs[| 15] = nodeValueMap("Width map", self);
inputs[| 16] = nodeValueMap("Blend alpha map", self);
inputs[| 17] = nodeValueMap("Start map", self);
//////////////////////////////////////////////////////////////////////////////////////////////////
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
outputs[| 1] = nodeValue("Outline", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [ 11,
["Surfaces", true], 0, 9, 10, 13, 14,
["Outline", false], 1, 15, 5, 8, 17, 12,
["Render", false], 2, 6,
["Blend", true, 3], 4, 16,
];
attribute_surface_depth();
attribute_oversample();
static step = function() { #region
var _side = getInputData(5);
inputs[| 12].setVisible(_side == 0);
__step_mask_modifier();
inputs[| 1].mappableStep();
inputs[| 4].mappableStep();
inputs[| 8].mappableStep();
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var ww = surface_get_width_safe(_data[0]);
var hh = surface_get_height_safe(_data[0]);
var cl = _data[2];
var blend = _data[3];
var side = _data[5];
var aa = _data[6];
var sam = struct_try_get(attributes, "oversample");
var _crop = _data[12];
surface_set_shader(_outSurf, sh_outline);
shader_set_f("dimension", ww, hh);
shader_set_f_map("borderSize", _data[1], _data[15], inputs[| 1]);
shader_set_f_map("borderStart", _data[8], _data[17], inputs[| 8]);
shader_set_color("borderColor", cl);
shader_set_i("side", side);
shader_set_i("is_aa", aa);
shader_set_i("outline_only", _output_index);
shader_set_i("is_blend", blend);
shader_set_f_map("blend_alpha", _data[4], _data[16], inputs[| 4]);
shader_set_i("sampleMode", sam);
shader_set_i("crop_border", _crop);
draw_surface_safe(_data[0]);
surface_reset_shader();
__process_mask_modifier(_data);
_outSurf = mask_apply(_data[0], _outSurf, _data[9], _data[10]);
return _outSurf;
} #endregion
}

View file

@ -0,0 +1,356 @@
// 2024-04-18 12:07:41
enum NODE_SHAPE_TYPE { rectangle, elipse, regular, star, arc, teardrop, cross, leaf, crescent, donut }
#region create
global.node_shape_keys = [ "rectangle", "ellipse", "regular polygon", "star", "arc", "teardrop", "cross", "leaf", "crescent", "donut" ];
array_append(global.node_shape_keys, [ "square", "circle", "triangle", "pentagon", "hexagon", "ring" ]);
function Node_create_Shape(_x, _y, _group = noone, _param = {}) { #region
var query = struct_try_get(_param, "query", "");
var node = new Node_Shape(_x, _y, _group);
var ind = -1;
switch(query) {
case "square" : ind = 0; break;
case "circle" : ind = 1; break;
case "triangle" : ind = 2; node.inputs[| 4].setValue(3); break;
case "pentagon" : ind = 2; node.inputs[| 4].setValue(5); break;
case "hexagon" : ind = 2; node.inputs[| 4].setValue(6); break;
case "ring" : ind = 9; break;
default : ind = array_find(global.node_shape_keys, query);
}
if(ind >= 0) node.inputs[| 2].setValue(ind);
return node;
}
#endregion
function Node_Shape(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Shape";
onSurfaceSize = function() { return getInputData(0, DEF_SURF); };
inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF )
.setDisplay(VALUE_DISPLAY.vector);
inputs[| 1] = nodeValue("Background", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
var _types = [ "Rectangle", "Ellipse", "Regular polygon", "Star", "Arc", "Teardrop", "Cross", "Leaf", "Crescent", "Donut" ];
for( var i = 0, n = array_length(_types); i < n; i++ )
_types[i] = new scrollItem(_types[i], s_node_shape_type, i);
inputs[| 2] = nodeValue("Shape", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_scroll, _types);
inputs[| 3] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, DEF_AREA_REF)
.setUnitRef(onSurfaceSize, VALUE_UNIT.reference)
.setDisplay(VALUE_DISPLAY.area, { onSurfaceSize, useShape : false });
inputs[| 4] = nodeValue("Sides", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 3)
.setVisible(false);
inputs[| 5] = nodeValue("Inner radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5)
.setDisplay(VALUE_DISPLAY.slider)
.setVisible(false);
inputs[| 6] = nodeValue("Anti-aliasing", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 7] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
.setDisplay(VALUE_DISPLAY.rotation);
inputs[| 8] = nodeValue("Angle range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 180 ])
.setDisplay(VALUE_DISPLAY.rotation_range);
inputs[| 9] = nodeValue("Corner radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] });
inputs[| 10] = nodeValue("Shape color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white);
inputs[| 11] = nodeValue("Background color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_black);
inputs[| 12] = nodeValue("Height", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 13] = nodeValue("Start radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
.setDisplay(VALUE_DISPLAY.slider)
.setVisible(false);
inputs[| 14] = nodeValue("Shape path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone)
.setVisible(true, true);
inputs[| 15] = nodeValue("Positioning Mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Area", "Center + Scale", "Full Image" ])
inputs[| 16] = nodeValue("Center", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ DEF_SURF_W / 2, DEF_SURF_H / 2 ] )
.setDisplay(VALUE_DISPLAY.vector)
.setUnitRef(onSurfaceSize);
inputs[| 17] = nodeValue("Half Size", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ DEF_SURF_W / 2, DEF_SURF_H / 2 ] )
.setDisplay(VALUE_DISPLAY.vector)
.setUnitRef(onSurfaceSize);
inputs[| 18] = nodeValue("Tile", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 19] = nodeValue("Shape Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.rotation);
inputs[| 20] = nodeValue("Level", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 1 ])
.setDisplay(VALUE_DISPLAY.slider_range);
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [
["Output", false], 0, 6,
["Transform", false], 15, 3, 16, 17, 19,
["Shape", false], 14, 2, 9, 4, 13, 5, 7, 8,
["Render", true], 10, 12, 20, 18,
["Background", true, 1], 11,
];
temp_surface = [ noone ];
attribute_surface_depth();
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
var _path = getInputData(14);
if(_path != noone && struct_has(_path, "getPointRatio")) return;
var _type = getInputData(15);
if(_type == 0) {
inputs[| 3].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
} else if(_type == 1) {
var _pos = getInputData(16);
var _px = _x + _pos[0] * _s;
var _py = _y + _pos[1] * _s;
inputs[| 16].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
inputs[| 17].drawOverlay(hover, active, _px, _py, _s, _mx, _my, _snx, _sny);
}
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var _dim = _data[0];
var _bg = _data[1];
var _shape = _data[2];
var _aa = _data[6];
var _corner = _data[9];
var _color = _data[10];
var _df = _data[12];
var _path = _data[14];
var _bgC = _data[11];
var _bgcol = _bg? colToVec4(_data[11]) : [0, 0, 0, 0];
var _posTyp = _data[15];
var _tile = _data[18];
var _rotat = _data[19];
var _level = _data[20];
var _center = [ 0, 0 ];
var _scale = [ 0, 0 ];
switch(_posTyp) {
case 0 :
var _area = _data[3];
_center = [ _area[0] / _dim[0], _area[1] / _dim[1] ];
_scale = [ _area[2] / _dim[0], _area[3] / _dim[1] ];
break;
case 1 :
var _posit = _data[16];
var _scal = _data[17];
_center = [ _posit[0] / _dim[0], _posit[1] / _dim[1] ];
_scale = [ _scal[0] / _dim[0], _scal[1] / _dim[1] ];
break;
case 2 :
_center = [ 0.5, 0.5 ];
_scale = [ 0.5, 0.5 ];
break;
}
inputs[| 3].setVisible(_posTyp == 0);
inputs[| 16].setVisible(_posTyp == 1);
inputs[| 17].setVisible(_posTyp == 1);
inputs[| 4].setVisible(true);
inputs[| 5].setVisible(true);
inputs[| 6].setVisible(_path == noone);
inputs[| 7].setVisible(true);
inputs[| 8].setVisible(true);
inputs[| 9].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 15].setVisible(true);
_outSurf = surface_verify(_outSurf, _dim[0], _dim[1], attrDepth());
if(_path != noone && struct_has(_path, "getPointRatio")) { #region
inputs[| 3].setVisible(false);
inputs[| 4].setVisible(false);
inputs[| 5].setVisible(false);
inputs[| 7].setVisible(false);
inputs[| 8].setVisible(false);
inputs[| 9].setVisible(false);
inputs[| 13].setVisible(false);
inputs[| 15].setVisible(false);
surface_set_target(_outSurf);
if(_bg) draw_clear_alpha(0, 1);
else DRAW_CLEAR
var points = [];
var segCount = _path.getSegmentCount();
if(segCount) {
var quality = 8;
var sample = quality * segCount;
for( var i = 0; i < sample; i++ ) {
var t = i / sample;
var pos = _path.getPointRatio(t);
array_push(points, pos);
}
var triangles = polygon_triangulate(points);
draw_set_color(_color);
draw_primitive_begin(pr_trianglelist);
for( var i = 0, n = array_length(triangles); i < n; i++ ) {
var tri = triangles[i];
var p0 = tri[0];
var p1 = tri[1];
var p2 = tri[2];
draw_vertex(p0.x, p0.y);
draw_vertex(p1.x, p1.y);
draw_vertex(p2.x, p2.y);
}
draw_primitive_end();
}
surface_reset_target();
return _outSurf;
} #endregion
surface_set_shader(_outSurf, sh_shape);
if(_bg) draw_clear_alpha(0, 1);
else DRAW_CLEAR
inputs[| 4].setVisible(false);
inputs[| 5].setVisible(false);
inputs[| 7].setVisible(false);
inputs[| 8].setVisible(false);
inputs[| 9].setVisible(false);
inputs[| 13].setVisible(false);
inputs[| 18].setVisible( true);
switch(_shape) { #region
case NODE_SHAPE_TYPE.rectangle :
inputs[| 9].setVisible( true);
inputs[| 18].setVisible(false);
break;
case NODE_SHAPE_TYPE.elipse :
break;
case NODE_SHAPE_TYPE.regular :
inputs[| 4].setVisible(true);
inputs[| 7].setVisible(true);
inputs[| 9].setVisible(true);
shader_set_i("sides", _data[4]);
shader_set_f("angle", degtorad(_data[7]));
break;
case NODE_SHAPE_TYPE.star :
inputs[| 4].setVisible(true);
inputs[| 5].setVisible(true);
inputs[| 7].setVisible(true);
inputs[| 9].setVisible(true);
inputs[| 5].name = "Inner radius";
shader_set_i("sides", _data[4]);
shader_set_f("angle", degtorad(_data[7]));
shader_set_f("inner", _data[5]);
break;
case NODE_SHAPE_TYPE.arc :
inputs[| 5].setVisible(true);
inputs[| 8].setVisible(true);
inputs[| 5].name = "Inner radius";
var ar = _data[8];
var center = degtorad(ar[0] + ar[1]) / 2;
var range = degtorad(ar[0] - ar[1]) / 2;
shader_set_f("angle", center);
shader_set_f("angle_range", [ sin(range), cos(range) ] );
shader_set_f("inner", _data[5] / 2);
break;
case NODE_SHAPE_TYPE.teardrop :
inputs[| 5].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 5].name = "End radius";
inputs[| 13].name = "Start radius";
shader_set_f("edRad", _data[ 5]);
shader_set_f("stRad", _data[13]);
break;
case NODE_SHAPE_TYPE.cross :
inputs[| 9].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 13].name = "Outer radius";
shader_set_f("outer", _data[13]);
break;
case NODE_SHAPE_TYPE.leaf :
inputs[| 5].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 5].name = "Inner radius";
inputs[| 13].name = "Outer radius";
shader_set_f("inner", _data[ 5]);
shader_set_f("outer", _data[13]);
break;
case NODE_SHAPE_TYPE.crescent :
inputs[| 5].setVisible(true);
inputs[| 7].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 5].name = "Shift";
inputs[| 13].name = "Inner circle";
shader_set_f("outer", _data[ 5]);
shader_set_f("angle", -degtorad(_data[7]));
shader_set_f("inner", _data[13]);
break;
case NODE_SHAPE_TYPE.donut :
inputs[| 13].setVisible(true);
inputs[| 13].name = "Inner circle";
shader_set_f("inner", _data[13]);
break;
} #endregion
shader_set_f("dimension", _dim);
shader_set_i("shape", _shape);
shader_set_f("bgColor", _bgcol);
shader_set_i("aa", _aa);
shader_set_i("drawDF", _df);
shader_set_f("dfLevel", _level);
shader_set_i("tile", _tile);
shader_set_f("corner", _corner);
shader_set_f("center", _center);
shader_set_f("scale", _scale );
shader_set_f("rotation", degtorad(_rotat));
draw_sprite_stretched_ext(s_fx_pixel, 0, 0, 0, _dim[0], _dim[1], _color, _color_get_alpha(_color));
surface_reset_shader();
return _outSurf;
} #endregion
}

View file

@ -0,0 +1,356 @@
// 2024-04-17 19:15:10
enum NODE_SHAPE_TYPE { rectangle, elipse, regular, star, arc, teardrop, cross, leaf, crescent, donut }
#region create
global.node_shape_keys = [ "rectangle", "ellipse", "regular polygon", "star", "arc", "teardrop", "cross", "leaf", "crescent", "donut" ];
array_append(global.node_shape_keys, [ "square", "circle", "triangle", "pentagon", "hexagon", "ring" ]);
function Node_create_Shape(_x, _y, _group = noone, _param = {}) { #region
var query = struct_try_get(_param, "query", "");
var node = new Node_Shape(_x, _y, _group);
var ind = -1;
switch(query) {
case "square" : ind = 0; break;
case "circle" : ind = 1; break;
case "triangle" : ind = 2; node.inputs[| 4].setValue(3); break;
case "pentagon" : ind = 2; node.inputs[| 4].setValue(5); break;
case "hexagon" : ind = 2; node.inputs[| 4].setValue(6); break;
case "ring" : ind = 9; break;
default : ind = array_find(global.node_shape_keys, query);
}
if(ind >= 0) node.inputs[| 2].setValue(ind);
return node;
}
#endregion
function Node_Shape(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Shape";
onSurfaceSize = function() { return getInputData(0, DEF_SURF); };
inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF )
.setDisplay(VALUE_DISPLAY.vector);
inputs[| 1] = nodeValue("Background", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
var _types = [ "Rectangle", "Ellipse", "Regular polygon", "Star", "Arc", "Teardrop", "Cross", "Leaf", "Crescent", "Donut" ];
for( var i = 0, n = array_length(_types); i < n; i++ )
_types[i] = new scrollItem(_types[i], s_node_shape_type, i);
inputs[| 2] = nodeValue("Shape", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_scroll, _types);
inputs[| 3] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, DEF_AREA_REF)
.setUnitRef(onSurfaceSize, VALUE_UNIT.reference)
.setDisplay(VALUE_DISPLAY.area, { onSurfaceSize, useShape : false });
inputs[| 4] = nodeValue("Sides", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 3)
.setVisible(false);
inputs[| 5] = nodeValue("Inner radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5)
.setDisplay(VALUE_DISPLAY.slider)
.setVisible(false);
inputs[| 6] = nodeValue("Anti-aliasing", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 7] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
.setDisplay(VALUE_DISPLAY.rotation);
inputs[| 8] = nodeValue("Angle range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 180 ])
.setDisplay(VALUE_DISPLAY.rotation_range);
inputs[| 9] = nodeValue("Corner radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] });
inputs[| 10] = nodeValue("Shape color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white);
inputs[| 11] = nodeValue("Background color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_black);
inputs[| 12] = nodeValue("Height", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 13] = nodeValue("Start radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
.setDisplay(VALUE_DISPLAY.slider)
.setVisible(false);
inputs[| 14] = nodeValue("Shape path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone)
.setVisible(true, true);
inputs[| 15] = nodeValue("Positioning Mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Area", "Center + Scale", "Full Image" ])
inputs[| 16] = nodeValue("Center", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ DEF_SURF_W / 2, DEF_SURF_H / 2 ] )
.setDisplay(VALUE_DISPLAY.vector)
.setUnitRef(onSurfaceSize);
inputs[| 17] = nodeValue("Half Size", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ DEF_SURF_W / 2, DEF_SURF_H / 2 ] )
.setDisplay(VALUE_DISPLAY.vector)
.setUnitRef(onSurfaceSize);
inputs[| 18] = nodeValue("Tile", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 19] = nodeValue("Shape Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.rotation);
inputs[| 20] = nodeValue("Level", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 1 ])
.setDisplay(VALUE_DISPLAY.slider_range);
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [
["Output", false], 0, 6,
["Transform", false], 15, 3, 16, 17, 19,
["Shape", false], 14, 2, 9, 4, 13, 5, 7, 8,
["Render", true], 10, 12, 20, 18,
["Background", true, 1], 11,
];
temp_surface = [ noone ];
attribute_surface_depth();
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
var _path = getInputData(14);
if(_path != noone && struct_has(_path, "getPointRatio")) return;
var _type = getInputData(15);
if(_type == 0) {
inputs[| 3].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
} else if(_type == 1) {
var _pos = getInputData(16);
var _px = _x + _pos[0] * _s;
var _py = _y + _pos[1] * _s;
inputs[| 16].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
inputs[| 17].drawOverlay(hover, active, _px, _py, _s, _mx, _my, _snx, _sny);
}
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var _dim = _data[0];
var _bg = _data[1];
var _shape = _data[2];
var _aa = _data[6];
var _corner = _data[9];
var _color = _data[10];
var _df = _data[12];
var _path = _data[14];
var _bgC = _data[11];
var _bgcol = _bg? colToVec4(_data[11]) : [0, 0, 0, 0];
var _posTyp = _data[15];
var _tile = _data[18];
var _rotat = _data[19];
var _level = _data[20];
var _center = [ 0, 0 ];
var _scale = [ 0, 0 ];
switch(_posTyp) {
case 0 :
var _area = _data[3];
_center = [ _area[0] / _dim[0], _area[1] / _dim[1] ];
_scale = [ _area[2] / _dim[0], _area[3] / _dim[1] ];
break;
case 1 :
var _posit = _data[16];
var _scal = _data[17];
_center = [ _posit[0] / _dim[0], _posit[1] / _dim[1] ];
_scale = [ _scal[0] / _dim[0], _scal[1] / _dim[1] ];
break;
case 2 :
_center = [ 0.5, 0.5 ];
_scale = [ 0.5, 0.5 ];
break;
}
inputs[| 3].setVisible(_posTyp == 0);
inputs[| 16].setVisible(_posTyp == 1);
inputs[| 17].setVisible(_posTyp == 1);
inputs[| 4].setVisible(true);
inputs[| 5].setVisible(true);
inputs[| 6].setVisible(_path == noone);
inputs[| 7].setVisible(true);
inputs[| 8].setVisible(true);
inputs[| 9].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 15].setVisible(true);
_outSurf = surface_verify(_outSurf, _dim[0], _dim[1], attrDepth());
if(_path != noone && struct_has(_path, "getPointRatio")) { #region
inputs[| 3].setVisible(false);
inputs[| 4].setVisible(false);
inputs[| 5].setVisible(false);
inputs[| 7].setVisible(false);
inputs[| 8].setVisible(false);
inputs[| 9].setVisible(false);
inputs[| 13].setVisible(false);
inputs[| 15].setVisible(false);
surface_set_target(_outSurf);
if(_bg) draw_clear_alpha(0, 1);
else DRAW_CLEAR
var points = [];
var segCount = _path.getSegmentCount();
if(segCount) {
var quality = 8;
var sample = quality * segCount;
for( var i = 0; i < sample; i++ ) {
var t = i / sample;
var pos = _path.getPointRatio(t);
array_push(points, pos);
}
var triangles = polygon_triangulate(points);
draw_set_color(_color);
draw_primitive_begin(pr_trianglelist);
for( var i = 0, n = array_length(triangles); i < n; i++ ) {
var tri = triangles[i];
var p0 = tri[0];
var p1 = tri[1];
var p2 = tri[2];
draw_vertex(p0.x, p0.y);
draw_vertex(p1.x, p1.y);
draw_vertex(p2.x, p2.y);
}
draw_primitive_end();
}
surface_reset_target();
return _outSurf;
} #endregion
surface_set_shader(_outSurf, sh_shape);
if(_bg) draw_clear_alpha(0, 1);
else DRAW_CLEAR
inputs[| 4].setVisible(false);
inputs[| 5].setVisible(false);
inputs[| 7].setVisible(false);
inputs[| 8].setVisible(false);
inputs[| 9].setVisible(false);
inputs[| 13].setVisible(false);
inputs[| 18].setVisible( true);
switch(_shape) { #region
case NODE_SHAPE_TYPE.rectangle :
inputs[| 9].setVisible( true);
inputs[| 18].setVisible(false);
break;
case NODE_SHAPE_TYPE.elipse :
break;
case NODE_SHAPE_TYPE.regular :
inputs[| 4].setVisible(true);
inputs[| 7].setVisible(true);
inputs[| 9].setVisible(true);
shader_set_i("sides", _data[4]);
shader_set_f("angle", degtorad(_data[7]));
break;
case NODE_SHAPE_TYPE.star :
inputs[| 4].setVisible(true);
inputs[| 5].setVisible(true);
inputs[| 7].setVisible(true);
inputs[| 9].setVisible(true);
inputs[| 5].name = "Inner radius";
shader_set_i("sides", _data[4]);
shader_set_f("angle", degtorad(_data[7]));
shader_set_f("inner", _data[5]);
break;
case NODE_SHAPE_TYPE.arc :
inputs[| 5].setVisible(true);
inputs[| 8].setVisible(true);
inputs[| 5].name = "Inner radius";
var ar = _data[8];
var center = degtorad(ar[0] + ar[1]) / 2;
var range = degtorad(ar[0] - ar[1]) / 2;
shader_set_f("angle", center);
shader_set_f("angle_range", [ sin(range), cos(range) ] );
shader_set_f("inner", _data[5] / 2);
break;
case NODE_SHAPE_TYPE.teardrop :
inputs[| 5].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 5].name = "End radius";
inputs[| 13].name = "Start radius";
shader_set_f("edRad", _data[ 5]);
shader_set_f("stRad", _data[13]);
break;
case NODE_SHAPE_TYPE.cross :
inputs[| 9].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 13].name = "Outer radius";
shader_set_f("outer", _data[13]);
break;
case NODE_SHAPE_TYPE.leaf :
inputs[| 5].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 5].name = "Inner radius";
inputs[| 13].name = "Outer radius";
shader_set_f("inner", _data[ 5]);
shader_set_f("outer", _data[13]);
break;
case NODE_SHAPE_TYPE.crescent :
inputs[| 5].setVisible(true);
inputs[| 7].setVisible(true);
inputs[| 13].setVisible(true);
inputs[| 5].name = "Shift";
inputs[| 13].name = "Inner circle";
shader_set_f("outer", _data[ 5]);
shader_set_f("angle", -degtorad(_data[7]));
shader_set_f("inner", _data[13]);
break;
case NODE_SHAPE_TYPE.donut :
inputs[| 13].setVisible(true);
inputs[| 13].name = "Inner circle";
shader_set_f("inner", _data[13]);
break;
} #endregion
shader_set_f("dimension", _dim);
shader_set_i("shape", _shape);
shader_set_f("bgColor", _bgcol);
shader_set_i("aa", _aa);
shader_set_i("drawDF", _df);
shader_set_f("dfLevel", _level);
shader_set_i("tile", _tile);
shader_set_f("corner", _corner);
shader_set_f("center", _center);
shader_set_f("scale", _scale );
shader_set_f("rotation", degtorad(_rotat));
draw_sprite_stretched_ext(s_fx_pixel, 0, 0, 0, _dim[0], _dim[1], _color, _color_get_alpha(_color));
surface_reset_shader();
return _outSurf;
} #endregion
}

View file

@ -1,4 +1,4 @@
// 2024-04-15 17:50:18
// 2024-04-17 07:56:45
#region preference
globalvar PREFERENCES, PREFERENCES_DEF, HOTKEYS_DATA;
PREFERENCES = {};

View file

@ -1,4 +1,4 @@
// 2024-04-15 17:50:17
// 2024-04-15 17:50:18
#region preference
globalvar PREFERENCES, PREFERENCES_DEF, HOTKEYS_DATA;
PREFERENCES = {};

View file

@ -0,0 +1,749 @@
// 2024-04-18 12:07:15
enum TEXTBOX_INPUT {
text,
number
}
function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
onRelease = noone;
align = _input == TEXTBOX_INPUT.number? fa_center : fa_left;
hide = false;
color = COLORS._main_text;
boxColor = c_white;
format = TEXT_AREA_FORMAT._default;
precision = 5;
suffix = "";
no_empty = true;
auto_update = false;
slidable = false;
sliding = false;
slide_delta = 0;
slide_int = false;
slide_speed = 1 / 10;
slide_snap = 0;
slide_range = noone;
curr_range = [ 0, 1 ];
slider_def_val = 0;
slider_cur_val = 0;
label = "";
starting_char = 1;
_current_text = "";
_input_text = "";
_last_text = "";
current_value = "";
_disp_text = "";
cursor = 0;
cursor_pos = 0;
cursor_pos_y = 0;
cursor_pos_to = 0;
cursor_select = -1;
disp_x = 0;
disp_x_to = 0;
disp_x_min = 0;
disp_x_max = 0;
click_block = 0;
use_range = false;
range_min = 0;
range_max = 0;
disp_text_fx = [];
sprite_index = -1;
text_surface = surface_create(1, 1);
shake_amount = 0;
static setOnRelease = function(release) { onRelease = release; return self; }
static modifyValue = function(value) { #region
if(input == TEXTBOX_INPUT.number) {
if(use_range) value = clamp(value, range_min, range_max);
}
onModify(value);
} #endregion
static setSlidable = function(slideStep = slide_speed, _slide_int = false, _slide_range = noone) { #region
slidable = true;
slide_speed = is_array(slideStep)? slideStep[0] : slideStep;
slide_snap = is_array(slideStep)? slideStep[1] : 0;
slide_int = _slide_int;
slide_range = _slide_range;
return self;
} #endregion
static setRange = function(_rng_min, _rng_max) { #region
use_range = true;
range_min = _rng_min;
range_max = _rng_max;
return self;
} #endregion
static setFont = function(font) { #region
self.font = font;
return self;
} #endregion
static setLabel = function(label) { #region
self.label = label;
return self;
} #endregion
static setPrecision = function(precision) { #region
self.precision = precision;
return self;
} #endregion
static setEmpty = function() { #region
no_empty = false;
return self;
} #endregion
static activate = function() { #region
WIDGET_CURRENT = self;
WIDGET_CURRENT_SCROLL = parent;
parentFocus();
_input_text = _current_text;
_last_text = _current_text;
cursor = string_length(_current_text);
cursor_select = 0;
click_block = 1;
KEYBOARD_STRING = "";
keyboard_lastkey = -1;
if(PEN_USE) keyboard_virtual_show(input == TEXTBOX_INPUT.number? kbv_type_numbers : kbv_type_default, kbv_returnkey_default, kbv_autocapitalize_none, true);
} #endregion
static deactivate = function() { #region
if(WIDGET_CURRENT != self) return;
apply();
if(is_callable(onRelease))
apply(true);
WIDGET_CURRENT = noone;
UNDO_HOLDING = false;
if(PEN_USE) keyboard_virtual_hide();
} #endregion
static onKey = function(key) { #region
if(KEYBOARD_PRESSED == vk_left) {
if(key_mod_press(SHIFT)) {
if(cursor_select == -1)
cursor_select = cursor;
} else if(cursor_select != -1)
cursor_select = -1;
move_cursor(-1);
}
if(KEYBOARD_PRESSED == vk_right) {
if(key_mod_press(SHIFT)) {
if(cursor_select == -1)
cursor_select = cursor;
} else if(cursor_select != -1)
cursor_select = -1;
move_cursor(1);
}
} #endregion
static apply = function(release = false) { #region
var _input_text_current = _input_text;
disp_x_to = 0;
if(input == TEXTBOX_INPUT.number)
_input_text_current = evaluateFunction(_input_text);
if(no_empty && _input_text_current == "")
_input_text_current = _last_text;
current_value = _input_text_current;
if(release) {
if(is_callable(onRelease)) {
var _modi = onRelease(_input_text_current);
if(_modi && IS_PATREON) shake_amount = PREFERENCES.textbox_shake / 4;
return _modi;
}
} else {
if(is_callable(onModify)) {
var _modi = onModify(_input_text_current);
if(_modi && IS_PATREON) shake_amount = PREFERENCES.textbox_shake / 4;
return _modi;
}
}
if(IS_PATREON) shake_amount = PREFERENCES.textbox_shake / 4;
return false;
} #endregion
static move_cursor = function(delta) { #region
var ll = string_length(_input_text) + 1;
cursor = safe_mod(cursor + delta + ll, ll);
} #endregion
static editText = function() { #region
var edited = false;
#region text editor
if(key_mod_press(CTRL) && keyboard_check_pressed(ord("A"))) {
cursor_select = 0;
cursor = string_length(_input_text);
} else if(key_mod_press(CTRL) && (keyboard_check_pressed(ord("C")) || keyboard_check_pressed(ord("X")))) {
if(cursor_select != -1) {
var minc = min(cursor, cursor_select);
var maxc = max(cursor, cursor_select);
clipboard_set_text(string_copy(_input_text, minc + 1, maxc - minc));
}
} else {
if(key_mod_press(CTRL) && keyboard_check_pressed(ord("V"))) {
KEYBOARD_STRING = clipboard_get_text();
edited = true;
}
if(keyboard_check_pressed(vk_escape) || keyboard_check_pressed(vk_enter)) {
} else if(KEYBOARD_PRESSED == vk_backspace) {
if(cursor_select == -1) {
var str_before, str_after;
if(key_mod_press(CTRL)) {
var _c = cursor - 1;
while(_c > 0) {
var ch = string_char_at(_input_text, _c);
if(breakCharacter(ch)) break;
_c--;
}
str_before = string_copy(_input_text, 1, _c);
str_after = string_copy(_input_text, cursor + 1, string_length(_input_text) - cursor);
cursor = _c + 1;
} else {
str_before = string_copy(_input_text, 1, cursor - 1);
str_after = string_copy(_input_text, cursor + 1, string_length(_input_text) - cursor);
}
_input_text = str_before + str_after;
} else {
var minc = min(cursor, cursor_select);
var maxc = max(cursor, cursor_select);
var str_before = string_copy(_input_text, 1, minc);
var str_after = string_copy(_input_text, maxc + 1, string_length(_input_text) - maxc);
cursor = minc + 1;
_input_text = str_before + str_after;
}
edited = true;
cursor_select = -1;
move_cursor(-1);
} else if(KEYBOARD_PRESSED == vk_delete || (keyboard_check_pressed(ord("X")) && key_mod_press(CTRL) && cursor_select != -1)) {
if(cursor_select == -1) {
var str_before = string_copy(_input_text, 1, cursor);
var str_after = string_copy(_input_text, cursor + 2, string_length(_input_text) - cursor - 1);
_input_text = str_before + str_after;
} else {
var minc = min(cursor, cursor_select);
var maxc = max(cursor, cursor_select);
var str_before = string_copy(_input_text, 1, minc);
var str_after = string_copy(_input_text, maxc + 1, string_length(_input_text) - maxc);
cursor = minc;
_input_text = str_before + str_after;
}
edited = true;
cursor_select = -1;
} else if(KEYBOARD_STRING != "") {
var ch = KEYBOARD_STRING;
if(cursor_select == -1) {
var str_before = string_copy(_input_text, 1, cursor);
var str_after = string_copy(_input_text, cursor + 1, string_length(_input_text) - cursor);
_input_text = str_before + ch + str_after;
move_cursor(string_length(ch));
} else {
var minc = min(cursor, cursor_select);
var maxc = max(cursor, cursor_select);
var str_before = string_copy(_input_text, 1, minc);
var str_after = string_copy(_input_text, maxc + 1, string_length(_input_text) - maxc);
_input_text = str_before + ch + str_after;
cursor = minc + string_length(ch);
}
edited = true;
cursor_select = -1;
}
}
KEYBOARD_STRING = "";
keyboard_lastkey = -1;
#endregion
if(keyboard_check_pressed(vk_left)) onKey(vk_left);
if(keyboard_check_pressed(vk_right)) onKey(vk_right);
if(input == TEXTBOX_INPUT.number) {
var _inc = 1;
if(key_mod_press(CTRL)) _inc *= 10;
if(key_mod_press(ALT)) _inc /= 10;
if(KEYBOARD_PRESSED == vk_up || keyboard_check_pressed(vk_up)) { _input_text = string(toNumber(_input_text) + _inc); apply(); }
if(KEYBOARD_PRESSED == vk_down || keyboard_check_pressed(vk_down)) { _input_text = string(toNumber(_input_text) - _inc); apply(); }
}
if(edited) {
typing = 100;
if(IS_PATREON) {
shake_amount = PREFERENCES.textbox_shake;
repeat(PREFERENCES.textbox_particle) spawn_particle(rx + cursor_pos, ry + cursor_pos_y + random(16), 8);
}
}
if(keyboard_check_pressed(vk_home)) {
if(key_mod_press(SHIFT)) {
if(cursor_select == -1)
cursor_select = cursor;
} else
cursor_select = -1;
move_cursor(-cursor);
} else if(keyboard_check_pressed(vk_end)) {
if(key_mod_press(SHIFT)) {
if(cursor_select == -1)
cursor_select = cursor;
} else
cursor_select = -1;
move_cursor(string_length(_input_text) - cursor);
} else if(keyboard_check_pressed(vk_escape)) {
_input_text = _last_text;
deactivate();
} else if(keyboard_check_pressed(vk_enter)) {
deactivate();
} else if(auto_update && (edited || keyboard_check_pressed(vk_anykey))) {
apply();
}
} #endregion
static display_text = function(_x, _y, _text, _w, _m = -1) { #region
draw_set_alpha(0.5 + 0.5 * interactable);
_y += ui(1); //Huh?
var cc = color;
if(sliding == 2) cc = COLORS._main_accent
draw_set_text(font, fa_left, fa_top, cc);
draw_text_add(_x + disp_x, _y, _text + suffix);
draw_set_alpha(1);
_disp_text = _text;
var _xx = _x + disp_x;
var _mm = _m;
var target = -999;
if(!sliding && selecting) {
for( var i = 1; i <= string_length(_text); i++ ) {
var _ch = string_char_at(_text, i);
var _chw = string_width(_ch);
if(_mm < _xx + _chw / 2) {
target = i - 1;
break;
} else if(_mm < _xx + _chw) {
target = i;
break;
}
_xx += _chw;
}
if(target != -999) {
if(!click_block) {
if(mouse_press(mb_left, active)) {
cursor_select = target;
cursor = target;
} else if(mouse_click(mb_left, active) && cursor != target)
cursor = target;
}
}
if(mouse_release(mb_left, active))
click_block = false;
}
} #endregion
static drawParam = function(params) { #region
setParam(params);
return draw(params.x, params.y, params.w, params.h, params.data, params.m, params.halign, params.valign);
} #endregion
static draw = function(_x, _y, _w, _h, _text = "", _m = mouse_ui, halign = fa_left, valign = fa_top) { #region
x = _x;
y = _y;
w = _w;
h = _h;
hovering = false;
if(shake_amount != 0) {
_x += irandom_range(-shake_amount, shake_amount);
_y += irandom_range(-shake_amount, shake_amount);
if(shake_amount) shake_amount--;
}
var drawText = selecting || _h >= line_get_height(font);
switch(halign) {
case fa_left: _x = _x; break;
case fa_center: _x = _x - _w / 2; break;
case fa_right: _x = _x - _w; break;
}
switch(valign) {
case fa_top: _y = _y; break;
case fa_center: _y = _y - _h / 2; break;
case fa_bottom: _y = _y - _h; break;
}
var _bs = min(h, ui(32));
if(_w - _bs > ui(100) && side_button) {
side_button.setFocusHover(active, hover);
side_button.draw(_x + _w - _bs, _y + _h / 2 - _bs / 2, _bs, _bs, _m, THEME.button_hide);
_w -= _bs + ui(4);
}
var _raw_text = _text;
_text = string_real(_text);
_current_text = _text;
var tb_surf_x = _x + ui(8);
var tb_surf_y = _y;
var tx = _x;
switch(align) {
case fa_left : tx = _x + ui(8); break;
case fa_center : tx = _x + _w / 2; break;
case fa_right : tx = _x + _w - ui(8); break;
}
if(drawText) {
var _update = !surface_valid(text_surface, _w - ui(16), _h);
if(_update) text_surface = surface_verify(text_surface, _w - ui(16), _h);
}
if(!hide) {
draw_sprite_stretched_ext(THEME.textbox, 3, _x, _y, _w, _h, boxColor, 1);
if(slide_range != noone) {
var _minn = slide_range[0];
var _maxx = slide_range[1];
var _rang = abs(_maxx - _minn);
var _currVal = toNumber(_current_text);
if(sliding != 2) {
curr_range[0] = (_currVal >= _minn)? _minn : _minn - ceil(abs(_currVal - _minn) / _rang) * _rang;
curr_range[1] = (_currVal <= _maxx)? _maxx : _maxx + ceil(abs(_currVal - _maxx) / _rang) * _rang;
}
var lw = _w * (_currVal - curr_range[0]) / (curr_range[1] - curr_range[0]);
draw_sprite_stretched_ext(THEME.textbox, 4, _x, _y, lw, _h, boxColor, 1);
}
}
if(_w > ui(48)) {
if(sliding == 2) {
var _ax0 = _x + ui(10);
var _ax1 = _x + _w - ui(10);
var _ay = _y + _h / 2;
draw_sprite_ui_uniform(THEME.arrow, 2, _ax0, _ay, 1, COLORS._main_accent, 1);
draw_sprite_ui_uniform(THEME.arrow, 0, _ax1, _ay, 1, COLORS._main_accent, 1);
} else if(label != "") {
draw_set_text(font, fa_left, fa_center, COLORS._main_text_sub);
draw_set_alpha(0.5);
draw_text_add(_x + ui(8), _y + _h / 2, label);
draw_set_alpha(1);
}
}
disp_x = lerp_float(disp_x, disp_x_to, 5);
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
if(sliding > 0) { #region slide
slide_delta += PEN_USE? PEN_X_DELTA : window_mouse_get_delta_x();
slide_delta += PEN_USE? PEN_Y_DELTA : window_mouse_get_delta_y();
if(sliding == 1 && abs(slide_delta) > 8) {
deactivate();
var _defval = toNumber(_current_text);
slider_def_val = _defval;
slider_cur_val = _defval;
CURSOR_LOCK_X = mouse_mx;
CURSOR_LOCK_Y = mouse_my;
sliding = 2;
}
if(sliding == 2) {
MOUSE_BLOCK = true;
CURSOR_LOCK = true;
if(mouse_check_button_pressed(mb_right)) {
_input_text = string_real(slider_def_val);
sliding = 0;
apply();
deactivate();
UNDO_HOLDING = false;
} else {
var _s = slide_speed;
var _mdx = PEN_USE? PEN_X_DELTA : window_mouse_get_delta_x();
var _mdy = PEN_USE? PEN_Y_DELTA : window_mouse_get_delta_y();
var _dx = abs(_mdx) > abs(_mdy)? _mdx : -_mdy;
if(key_mod_press(CTRL) && !slide_snap) _s *= 10;
if(key_mod_press(ALT)) _s /= 10;
slider_cur_val += _dx * _s;
if(slide_range != noone)
slider_cur_val = clamp(slider_cur_val, curr_range[0], curr_range[1]);
var _val = value_snap(slider_cur_val, _s);
if(key_mod_press(CTRL) && slide_snap) _val = value_snap(slider_cur_val, slide_snap);
if(slide_int) _val = round(_val);
if(abs(_val) < _s * 4) _val = 0;
_input_text = string_real(_val);
if(apply()) UNDO_HOLDING = true;
}
if(mouse_release(mb_left)) {
deactivate();
if(onRelease != noone) apply(true);
}
}
if(mouse_release(mb_left)) {
sliding = 0;
_update = true;
UNDO_HOLDING = false;
}
} #endregion
if(selecting) {
if(sprite_index == -1) draw_sprite_stretched_ext(THEME.textbox, 2, _x, _y, _w, _h, COLORS._main_accent, 1);
else draw_sprite_stretched(THEME.textbox, sprite_index, _x, _y, _w, _h);
editText();
#region multiplier
if(_w > ui(80) && input == TEXTBOX_INPUT.number) {
draw_set_alpha(0.5);
if(hover && point_in_rectangle(_m[0], _m[1], _x + _w - ui(32), _y, _x + _w, _y + _h)) {
draw_set_alpha(1);
if(mouse_press(mb_left, active)) {
if(key_mod_press(ALT)) _input_text = string_real(toNumber(_input_text) / 2);
else _input_text = string_real(toNumber(_input_text) * 2);
apply();
if(IS_PATREON) shake_amount = PREFERENCES.textbox_shake;
}
}
draw_set_text(f_p0b, fa_center, fa_center, COLORS._main_text_sub);
if(key_mod_press(ALT)) draw_text_add(_x + _w - ui(16), _y + _h / 2, "/2");
else draw_text_add(_x + _w - ui(16), _y + _h / 2, "x2");
draw_set_alpha(1);
}
#endregion
#region draw
var txt = _input_text;
draw_set_text(font, fa_left, fa_top);
var tw = string_width(txt);
var th = string_height(txt == ""? "l" : txt);
var cs = string_copy(txt, 1, cursor);
var c_w = string_width(cs);
var c_y0 = _y + _h / 2 - th / 2;
var c_y1 = _y + _h / 2 + th / 2;
switch(align) {
case fa_left :
disp_x_min = -max(0, tw - _w + ui(16 + 8));
disp_x_max = 0;
break;
case fa_center :
disp_x_min = -max(0, tw - _w + ui(16 + 8)) / 2;
disp_x_max = max(0, tw - _w + ui(16 + 8)) / 2;
tx -= tw / 2;
break;
case fa_right :
disp_x_min = 0;
disp_x_max = max(0, tw - _w + ui(16 + 8));
tx -= tw;
break;
}
cursor_pos_to = disp_x + tx + c_w;
if(cursor_pos_to < _x)
disp_x_to += _w - ui(16);
if(cursor_pos_to > _x + _w - ui(16))
disp_x_to -= _w - ui(16);
cursor_pos_y = c_y0;
cursor_pos = cursor_pos == 0? cursor_pos_to : lerp_float(cursor_pos, cursor_pos_to, 2);
if(cursor_select > -1) { //draw highlight
draw_set_color(COLORS.widget_text_highlight);
var c_x1 = tx + disp_x + string_width(string_copy(txt, 1, cursor_select));
var _rx0 = clamp(min(cursor_pos, c_x1), tx, tx + _w);
var _rx1 = clamp(max(cursor_pos, c_x1), tx, tx + _w);
draw_roundrect_ext(_rx0, c_y0, _rx1, c_y1, THEME_VALUE.highlight_corner_radius, THEME_VALUE.highlight_corner_radius, 0);
}
var _mx = -1;
var _my = -1;
if(hover && hoverRect) {
_mx = _m[0];
_my = _m[1];
}
var _display_text = string_real(txt);
if(_update || _display_text != _disp_text) {
surface_set_shader(text_surface, noone, true, BLEND.add);
display_text(tx - tb_surf_x, _h / 2 - th / 2, _display_text, _w - ui(4), _mx - tb_surf_x);
surface_reset_shader();
}
BLEND_ALPHA
draw_surface(text_surface, tb_surf_x, tb_surf_y);
BLEND_NORMAL
draw_set_color(COLORS._main_text_accent);
draw_set_alpha(typing || current_time % (PREFERENCES.caret_blink * 2000) > PREFERENCES.caret_blink * 1000);
draw_line_width(cursor_pos, c_y0, cursor_pos, c_y1, 2);
draw_set_alpha(1);
if(typing) typing--;
#endregion
disp_x_to = clamp(disp_x_to, disp_x_min, disp_x_max);
if(!hoverRect && mouse_press(mb_left))
deactivate();
} else {
if(hover && hoverRect) {
hovering = true;
draw_sprite_stretched_ext(THEME.textbox, 1, _x, _y, _w, _h, boxColor, 0.5 + (0.5 * interactable));
if(mouse_press(mb_left, active))
activate();
if(input == TEXTBOX_INPUT.number && key_mod_press(SHIFT)) {
var amo = slide_speed;
if(key_mod_press(CTRL)) amo *= 10;
if(key_mod_press(ALT)) amo /= 10;
if(mouse_wheel_down()) modifyValue(toNumber(_text) + amo * SCROLL_SPEED);
if(mouse_wheel_up()) modifyValue(toNumber(_text) - amo * SCROLL_SPEED);
}
if(slidable && mouse_press(mb_left, active)) {
sliding = 1;
slide_delta = 0;
slide_mx = _m[0];
slide_my = _m[1];
}
} else if(!hide)
draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y, _w, _h, boxColor, 0.5 + 0.5 * interactable);
if(drawText) {
draw_set_text(font, fa_left, fa_center);
var _display_text = _raw_text;
if(input == TEXTBOX_INPUT.number) {
var dig = floor(_w / string_width("0")) - 3;
_display_text = string_real(_display_text, dig, precision);
}
var tw = string_width(_display_text);
var th = string_height(_display_text);
switch(align) {
case fa_left : break;
case fa_center : tx -= tw / 2; break;
case fa_right : tx -= tw; break;
}
if(_update || _display_text != _disp_text) {
surface_set_shader(text_surface, noone, true, BLEND.add);
display_text(tx - tb_surf_x, _h / 2 - th / 2, _display_text, _w - ui(4));
surface_reset_shader();
}
BLEND_ALPHA
draw_surface(text_surface, tb_surf_x, tb_surf_y);
BLEND_NORMAL
}
}
if(DRAGGING && (DRAGGING.type == "Text" || DRAGGING.type == "Number") && hover && hoverRect) {
draw_sprite_stretched_ext(THEME.ui_panel_active, 0, _x, _y, _w, _h, COLORS._main_value_positive, 1);
if(mouse_release(mb_left))
onModify(DRAGGING.data);
}
selecting = self == WIDGET_CURRENT;
resetFocus();
sprite_index = -1;
return _h;
} #endregion
}

View file

@ -0,0 +1,749 @@
// 2024-04-18 12:00:32
enum TEXTBOX_INPUT {
text,
number
}
function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
onRelease = noone;
align = _input == TEXTBOX_INPUT.number? fa_center : fa_left;
hide = false;
color = COLORS._main_text;
boxColor = c_white;
format = TEXT_AREA_FORMAT._default;
precision = 5;
suffix = "";
no_empty = true;
auto_update = false;
slidable = false;
sliding = false;
slide_delta = 0;
slide_int = false;
slide_speed = 1 / 10;
slide_snap = 0;
slide_range = noone;
curr_range = [ 0, 1 ];
slider_def_val = 0;
slider_cur_val = 0;
label = "";
starting_char = 1;
_current_text = "";
_input_text = "";
_last_text = "";
current_value = "";
_disp_text = "";
cursor = 0;
cursor_pos = 0;
cursor_pos_y = 0;
cursor_pos_to = 0;
cursor_select = -1;
disp_x = 0;
disp_x_to = 0;
disp_x_min = 0;
disp_x_max = 0;
click_block = 0;
use_range = false;
range_min = 0;
range_max = 0;
disp_text_fx = [];
sprite_index = -1;
text_surface = surface_create(1, 1);
shake_amount = 0;
static setOnRelease = function(release) { onRelease = release; return self; }
static modifyValue = function(value) { #region
if(input == TEXTBOX_INPUT.number) {
if(use_range) value = clamp(value, range_min, range_max);
}
onModify(value);
} #endregion
static setSlidable = function(slideStep = slide_speed, _slide_int = false, _slide_range = noone) { #region
slidable = true;
slide_speed = is_array(slideStep)? slideStep[0] : slideStep;
slide_snap = is_array(slideStep)? slideStep[1] : 0;
slide_int = _slide_int;
slide_range = _slide_range;
return self;
} #endregion
static setRange = function(_rng_min, _rng_max) { #region
use_range = true;
range_min = _rng_min;
range_max = _rng_max;
return self;
} #endregion
static setFont = function(font) { #region
self.font = font;
return self;
} #endregion
static setLabel = function(label) { #region
self.label = label;
return self;
} #endregion
static setPrecision = function(precision) { #region
self.precision = precision;
return self;
} #endregion
static setEmpty = function() { #region
no_empty = false;
return self;
} #endregion
static activate = function() { #region
WIDGET_CURRENT = self;
WIDGET_CURRENT_SCROLL = parent;
parentFocus();
_input_text = _current_text;
_last_text = _current_text;
cursor = string_length(_current_text);
cursor_select = 0;
click_block = 1;
KEYBOARD_STRING = "";
keyboard_lastkey = -1;
if(PEN_USE) keyboard_virtual_show(input == TEXTBOX_INPUT.number? kbv_type_numbers : kbv_type_default, kbv_returnkey_default, kbv_autocapitalize_none, true);
} #endregion
static deactivate = function() { #region
if(WIDGET_CURRENT != self) return;
apply();
if(is_callable(onRelease))
apply(true);
WIDGET_CURRENT = noone;
UNDO_HOLDING = false;
if(PEN_USE) keyboard_virtual_hide();
} #endregion
static onKey = function(key) { #region
if(KEYBOARD_PRESSED == vk_left) {
if(key_mod_press(SHIFT)) {
if(cursor_select == -1)
cursor_select = cursor;
} else if(cursor_select != -1)
cursor_select = -1;
move_cursor(-1);
}
if(KEYBOARD_PRESSED == vk_right) {
if(key_mod_press(SHIFT)) {
if(cursor_select == -1)
cursor_select = cursor;
} else if(cursor_select != -1)
cursor_select = -1;
move_cursor(1);
}
} #endregion
static apply = function(release = false) { #region
var _input_text_current = _input_text;
disp_x_to = 0;
if(input == TEXTBOX_INPUT.number)
_input_text_current = evaluateFunction(_input_text);
if(no_empty && _input_text_current == "")
_input_text_current = _last_text;
current_value = _input_text_current;
if(release) {
if(is_callable(onRelease)) {
var _modi = onRelease(_input_text_current);
if(_modi && IS_PATREON) shake_amount = PREFERENCES.textbox_shake / 4;
return _modi;
}
} else {
if(is_callable(onModify)) {
var _modi = onModify(_input_text_current);
if(_modi && IS_PATREON) shake_amount = PREFERENCES.textbox_shake / 4;
return _modi;
}
}
if(IS_PATREON) shake_amount = PREFERENCES.textbox_shake / 4;
return false;
} #endregion
static move_cursor = function(delta) { #region
var ll = string_length(_input_text) + 1;
cursor = safe_mod(cursor + delta + ll, ll);
} #endregion
static editText = function() { #region
var edited = false;
#region text editor
if(key_mod_press(CTRL) && keyboard_check_pressed(ord("A"))) {
cursor_select = 0;
cursor = string_length(_input_text);
} else if(key_mod_press(CTRL) && (keyboard_check_pressed(ord("C")) || keyboard_check_pressed(ord("X")))) {
if(cursor_select != -1) {
var minc = min(cursor, cursor_select);
var maxc = max(cursor, cursor_select);
clipboard_set_text(string_copy(_input_text, minc + 1, maxc - minc));
}
} else {
if(key_mod_press(CTRL) && keyboard_check_pressed(ord("V"))) {
KEYBOARD_STRING = clipboard_get_text();
edited = true;
}
if(keyboard_check_pressed(vk_escape) || keyboard_check_pressed(vk_enter)) {
} else if(KEYBOARD_PRESSED == vk_backspace) {
if(cursor_select == -1) {
var str_before, str_after;
if(key_mod_press(CTRL)) {
var _c = cursor - 1;
while(_c > 0) {
var ch = string_char_at(_input_text, _c);
if(breakCharacter(ch)) break;
_c--;
}
str_before = string_copy(_input_text, 1, _c);
str_after = string_copy(_input_text, cursor + 1, string_length(_input_text) - cursor);
cursor = _c + 1;
} else {
str_before = string_copy(_input_text, 1, cursor - 1);
str_after = string_copy(_input_text, cursor + 1, string_length(_input_text) - cursor);
}
_input_text = str_before + str_after;
} else {
var minc = min(cursor, cursor_select);
var maxc = max(cursor, cursor_select);
var str_before = string_copy(_input_text, 1, minc);
var str_after = string_copy(_input_text, maxc + 1, string_length(_input_text) - maxc);
cursor = minc + 1;
_input_text = str_before + str_after;
}
edited = true;
cursor_select = -1;
move_cursor(-1);
} else if(KEYBOARD_PRESSED == vk_delete || (keyboard_check_pressed(ord("X")) && key_mod_press(CTRL) && cursor_select != -1)) {
if(cursor_select == -1) {
var str_before = string_copy(_input_text, 1, cursor);
var str_after = string_copy(_input_text, cursor + 2, string_length(_input_text) - cursor - 1);
_input_text = str_before + str_after;
} else {
var minc = min(cursor, cursor_select);
var maxc = max(cursor, cursor_select);
var str_before = string_copy(_input_text, 1, minc);
var str_after = string_copy(_input_text, maxc + 1, string_length(_input_text) - maxc);
cursor = minc;
_input_text = str_before + str_after;
}
edited = true;
cursor_select = -1;
} else if(KEYBOARD_STRING != "") {
var ch = KEYBOARD_STRING;
if(cursor_select == -1) {
var str_before = string_copy(_input_text, 1, cursor);
var str_after = string_copy(_input_text, cursor + 1, string_length(_input_text) - cursor);
_input_text = str_before + ch + str_after;
move_cursor(string_length(ch));
} else {
var minc = min(cursor, cursor_select);
var maxc = max(cursor, cursor_select);
var str_before = string_copy(_input_text, 1, minc);
var str_after = string_copy(_input_text, maxc + 1, string_length(_input_text) - maxc);
_input_text = str_before + ch + str_after;
cursor = minc + string_length(ch);
}
edited = true;
cursor_select = -1;
}
}
KEYBOARD_STRING = "";
keyboard_lastkey = -1;
#endregion
if(keyboard_check_pressed(vk_left)) onKey(vk_left);
if(keyboard_check_pressed(vk_right)) onKey(vk_right);
if(input == TEXTBOX_INPUT.number) {
var _inc = 1;
if(key_mod_press(CTRL)) _inc *= 10;
if(key_mod_press(ALT)) _inc /= 10;
if(KEYBOARD_PRESSED == vk_up || keyboard_check_pressed(vk_up)) { _input_text = string(toNumber(_input_text) + _inc); apply(); }
if(KEYBOARD_PRESSED == vk_down || keyboard_check_pressed(vk_down)) { _input_text = string(toNumber(_input_text) - _inc); apply(); }
}
if(edited) {
typing = 100;
if(IS_PATREON) {
shake_amount = PREFERENCES.textbox_shake;
repeat(PREFERENCES.textbox_particle) spawn_particle(rx + cursor_pos, ry + cursor_pos_y + random(16), 8);
}
}
if(keyboard_check_pressed(vk_home)) {
if(key_mod_press(SHIFT)) {
if(cursor_select == -1)
cursor_select = cursor;
} else
cursor_select = -1;
move_cursor(-cursor);
} else if(keyboard_check_pressed(vk_end)) {
if(key_mod_press(SHIFT)) {
if(cursor_select == -1)
cursor_select = cursor;
} else
cursor_select = -1;
move_cursor(string_length(_input_text) - cursor);
} else if(keyboard_check_pressed(vk_escape)) {
_input_text = _last_text;
deactivate();
} else if(keyboard_check_pressed(vk_enter)) {
deactivate();
} else if(auto_update && (edited || keyboard_check_pressed(vk_anykey))) {
apply();
}
} #endregion
static display_text = function(_x, _y, _text, _w, _m = -1) { #region
draw_set_alpha(0.5 + 0.5 * interactable);
_y += ui(1); //Huh?
var cc = color;
if(sliding == 2) cc = COLORS._main_accent
draw_set_text(font, fa_left, fa_top, cc);
draw_text_add(_x + disp_x, _y, _text + suffix);
draw_set_alpha(1);
_disp_text = _text;
var _xx = _x + disp_x;
var _mm = _m;
var target = -999;
if(!sliding && selecting) {
for( var i = 1; i <= string_length(_text); i++ ) {
var _ch = string_char_at(_text, i);
var _chw = string_width(_ch);
if(_mm < _xx + _chw / 2) {
target = i - 1;
break;
} else if(_mm < _xx + _chw) {
target = i;
break;
}
_xx += _chw;
}
if(target != -999) {
if(!click_block) {
if(mouse_press(mb_left, active)) {
cursor_select = target;
cursor = target;
} else if(mouse_click(mb_left, active) && cursor != target)
cursor = target;
}
}
if(mouse_release(mb_left, active))
click_block = false;
}
} #endregion
static drawParam = function(params) { #region
setParam(params);
return draw(params.x, params.y, params.w, params.h, params.data, params.m, params.halign, params.valign);
} #endregion
static draw = function(_x, _y, _w, _h, _text = "", _m = mouse_ui, halign = fa_left, valign = fa_top) { #region
x = _x;
y = _y;
w = _w;
h = _h;
hovering = false;
if(shake_amount != 0) {
_x += irandom_range(-shake_amount, shake_amount);
_y += irandom_range(-shake_amount, shake_amount);
if(shake_amount) shake_amount--;
}
var drawText = selecting || _h >= line_get_height(font);
switch(halign) {
case fa_left: _x = _x; break;
case fa_center: _x = _x - _w / 2; break;
case fa_right: _x = _x - _w; break;
}
switch(valign) {
case fa_top: _y = _y; break;
case fa_center: _y = _y - _h / 2; break;
case fa_bottom: _y = _y - _h; break;
}
var _bs = min(h, ui(32));
if(_w - _bs > ui(100) && side_button) {
side_button.setFocusHover(active, hover);
side_button.draw(_x + _w - _bs, _y + _h / 2 - _bs / 2, _bs, _bs, _m, THEME.button_hide);
_w -= _bs + ui(4);
}
var _raw_text = _text;
_text = string_real(_text);
_current_text = _text;
var tb_surf_x = _x + ui(8);
var tb_surf_y = _y;
var tx = _x;
switch(align) {
case fa_left : tx = _x + ui(8); break;
case fa_center : tx = _x + _w / 2; break;
case fa_right : tx = _x + _w - ui(8); break;
}
if(drawText) {
var _update = !surface_valid(text_surface, _w - ui(16), _h);
if(_update) text_surface = surface_verify(text_surface, _w - ui(16), _h);
}
if(!hide) {
draw_sprite_stretched_ext(THEME.textbox, 3, _x, _y, _w, _h, boxColor, 1);
if(slide_range != noone) {
var _minn = slide_range[0];
var _maxx = slide_range[1];
var _rang = abs(_maxx - _minn);
var _currVal = toNumber(_current_text);
if(sliding != 2) {
curr_range[0] = (_currVal >= _minn)? _minn : _minn - ceil(abs(_currVal - _minn) / _rang) * _rang;
curr_range[1] = (_currVal <= _maxx)? _maxx : _maxx + ceil(abs(_currVal - _maxx) / _rang) * _rang;
}
var lw = _w * (_currVal - curr_range[0]) / (curr_range[1] - curr_range[0]);
draw_sprite_stretched_ext(THEME.textbox, 4, _x, _y, lw, _h, boxColor, 1);
}
}
if(_w > ui(48)) {
if(sliding == 2) {
var _ax0 = _x + ui(10);
var _ax1 = _x + _w - ui(10);
var _ay = _y + _h / 2;
draw_sprite_ui_uniform(THEME.arrow, 2, _ax0, _ay, 1, COLORS._main_accent, 1);
draw_sprite_ui_uniform(THEME.arrow, 0, _ax1, _ay, 1, COLORS._main_accent, 1);
} else if(label != "") {
draw_set_text(font, fa_left, fa_center, COLORS._main_text_sub);
draw_set_alpha(0.5);
draw_text_add(_x + ui(8), _y + _h / 2, label);
draw_set_alpha(1);
}
}
disp_x = lerp_float(disp_x, disp_x_to, 5);
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
if(sliding > 0) { #region slide
slide_delta += PEN_USE? PEN_X_DELTA : window_mouse_get_delta_x();
slide_delta += PEN_USE? PEN_Y_DELTA : window_mouse_get_delta_y();
if(sliding == 1 && abs(slide_delta) > 8) {
deactivate();
var _defval = toNumber(_current_text);
slider_def_val = _defval;
slider_cur_val = _defval;
CURSOR_LOCK_X = mouse_mx;
CURSOR_LOCK_Y = mouse_my;
sliding = 2;
}
if(sliding == 2) {
MOUSE_BLOCK = true;
CURSOR_LOCK = true;
if(mouse_check_button_pressed(mb_right)) {
_input_text = string_real(slider_def_val);
sliding = 0;
apply();
deactivate();
UNDO_HOLDING = false;
} else {
var _s = slide_speed;
var _mdx = PEN_USE? PEN_X_DELTA : window_mouse_get_delta_x();
var _mdy = PEN_USE? PEN_Y_DELTA : window_mouse_get_delta_y();
var _dx = abs(_mdx) > abs(_mdy)? _mdx : -_mdy;
if(key_mod_press(CTRL) && !slide_snap) _s *= 10;
if(key_mod_press(ALT)) _s /= 10;
slider_cur_val += _dx * _s;
if(slide_range != noone)
slider_cur_val = clamp(slider_cur_val, curr_range[0], curr_range[1]);
var _val = value_snap(slider_cur_val, _s);
if(key_mod_press(CTRL) && slide_snap) _val = value_snap(slider_cur_val, slide_snap);
if(slide_int) _val = round(_val);
if(abs(_val) < _s * 4) _val = 0;
_input_text = string_real(_val);
if(apply()) UNDO_HOLDING = true;
}
if(mouse_release(mb_left)) {
deactivate();
if(onRelease != noone) apply(true);
}
}
if(mouse_release(mb_left)) {
sliding = 0;
_update = true;
UNDO_HOLDING = false;
}
} #endregion
if(selecting) {
if(sprite_index == -1) draw_sprite_stretched_ext(THEME.textbox, 2, _x, _y, _w, _h, COLORS._main_accent, 1);
else draw_sprite_stretched(THEME.textbox, sprite_index, _x, _y, _w, _h);
editText();
#region multiplier
if(_w > ui(80) && input == TEXTBOX_INPUT.number) {
draw_set_alpha(0.5);
if(hover && point_in_rectangle(_m[0], _m[1], _x + _w - ui(32), _y, _x + _w, _y + _h)) {
draw_set_alpha(1);
if(mouse_press(mb_left, active)) {
if(key_mod_press(ALT)) _input_text = string_real(toNumber(_input_text) / 2);
else _input_text = string_real(toNumber(_input_text) * 2);
apply();
if(IS_PATREON) shake_amount = PREFERENCES.textbox_shake;
}
}
draw_set_text(f_p0b, fa_center, fa_center, COLORS._main_text_sub);
if(key_mod_press(ALT)) draw_text_add(_x + _w - ui(16), _y + _h / 2, "/2");
else draw_text_add(_x + _w - ui(16), _y + _h / 2, "x2");
draw_set_alpha(1);
}
#endregion
#region draw
var txt = _input_text;
draw_set_text(font, fa_left, fa_top);
var tw = string_width(txt);
var th = string_height(txt == ""? "l" : txt);
var cs = string_copy(txt, 1, cursor);
var c_w = string_width(cs);
var c_y0 = _y + _h / 2 - th / 2;
var c_y1 = _y + _h / 2 + th / 2;
switch(align) {
case fa_left :
disp_x_min = -max(0, tw - _w + ui(16 + 8));
disp_x_max = 0;
break;
case fa_center :
disp_x_min = -max(0, tw - _w + ui(16 + 8)) / 2;
disp_x_max = max(0, tw - _w + ui(16 + 8)) / 2;
tx -= tw / 2;
break;
case fa_right :
disp_x_min = 0;
disp_x_max = max(0, tw - _w + ui(16 + 8));
tx -= tw;
break;
}
cursor_pos_to = disp_x + tx + c_w;
if(cursor_pos_to < _x)
disp_x_to += _w - ui(16);
if(cursor_pos_to > _x + _w - ui(16))
disp_x_to -= _w - ui(16);
cursor_pos_y = c_y0;
cursor_pos = cursor_pos == 0? cursor_pos_to : lerp_float(cursor_pos, cursor_pos_to, 2);
if(cursor_select > -1) { //draw highlight
draw_set_color(COLORS.widget_text_highlight);
var c_x1 = tx + disp_x + string_width(string_copy(txt, 1, cursor_select));
var _rx0 = clamp(min(cursor_pos, c_x1), tx, tx + _w);
var _rx1 = clamp(max(cursor_pos, c_x1), tx, tx + _w);
draw_roundrect_ext(_rx0, c_y0, _rx1, c_y1, THEME_VALUE.highlight_corner_radius, THEME_VALUE.highlight_corner_radius, 0);
}
var _mx = -1;
var _my = -1;
if(hover && hoverRect) {
_mx = _m[0];
_my = _m[1];
}
var _display_text = string_real(txt);
if(_update || _display_text != _disp_text) {
surface_set_shader(text_surface, noone, true, BLEND.add);
display_text(tx - tb_surf_x, _h / 2 - th / 2, _display_text, _w - ui(4), _mx - tb_surf_x);
surface_reset_shader();
}
BLEND_ALPHA
draw_surface(text_surface, tb_surf_x, tb_surf_y);
BLEND_NORMAL
draw_set_color(COLORS._main_text_accent);
draw_set_alpha(typing || current_time % (PREFERENCES.caret_blink * 2000) > PREFERENCES.caret_blink * 1000);
draw_line_width(cursor_pos, c_y0, cursor_pos, c_y1, 2);
draw_set_alpha(1);
if(typing) typing--;
#endregion
disp_x_to = clamp(disp_x_to, disp_x_min, disp_x_max);
if(!hoverRect && mouse_press(mb_left))
deactivate();
} else {
if(hover && hoverRect) {
hovering = true;
draw_sprite_stretched_ext(THEME.textbox, 1, _x, _y, _w, _h, boxColor, 0.5 + (0.5 * interactable));
if(mouse_press(mb_left, active))
activate();
if(input == TEXTBOX_INPUT.number && key_mod_press(SHIFT)) {
var amo = slide_speed;
if(key_mod_press(CTRL)) amo *= 10;
if(key_mod_press(ALT)) amo /= 10;
if(mouse_wheel_down()) modifyValue(toNumber(_text) + amo * SCROLL_SPEED);
if(mouse_wheel_up()) modifyValue(toNumber(_text) - amo * SCROLL_SPEED);
}
if(slidable && mouse_press(mb_left, active)) {
sliding = 1;
slide_delta = 0;
slide_mx = _m[0];
slide_my = _m[1];
}
} else if(!hide)
draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y, _w, _h, boxColor, 0.5 + 0.5 * interactable);
if(drawText) {
draw_set_text(font, fa_left, fa_center);
var _display_text = _raw_text;
if(input == TEXTBOX_INPUT.number) {
var dig = floor(_w / string_width("0")) - 3;
_display_text = string_real(_display_text, dig, precision);
}
var tw = string_width(_display_text);
var th = string_height(_display_text);
switch(align) {
case fa_left : break;
case fa_center : tx -= tw / 2; break;
case fa_right : tx -= tw; break;
}
if(_update || _display_text != _disp_text) {
surface_set_shader(text_surface, noone, true, BLEND.add);
display_text(tx - tb_surf_x, _h / 2 - th / 2, _display_text, _w - ui(4));
surface_reset_shader();
}
BLEND_ALPHA
draw_surface(text_surface, tb_surf_x, tb_surf_y);
BLEND_NORMAL
}
}
if(DRAGGING && (DRAGGING.type == "Text" || DRAGGING.type == "Number") && hover && hoverRect) {
draw_sprite_stretched_ext(THEME.ui_panel_active, 0, _x, _y, _w, _h, COLORS._main_value_positive, 1);
if(mouse_release(mb_left))
onModify(DRAGGING.data);
}
selecting = self == WIDGET_CURRENT;
resetFocus();
sprite_index = -1;
return _h;
} #endregion
}

View file

@ -0,0 +1,38 @@
// 2024-04-18 08:42:38
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
#define TAU 6.283185307179586
void main() {
vec2 tx = 1. / dimension;
vec4 col = texture2D( gm_BaseTexture, v_vTexcoord );
gl_FragColor = col;
if(col.a == 1.)
return;
for(float i = 1.; i <= 64.; i++) {
float base = 1.;
float top = 0.;
for(float j = 0.; j <= 64.; j++) {
float ang = top / base * TAU;
top += 2.;
if(top >= base) {
top = 1.;
base *= 2.;
}
vec2 pxs = v_vTexcoord + vec2( cos(ang), sin(ang)) * i * tx;
vec4 sam = texture2D( gm_BaseTexture, pxs );
if(sam.a < 1.) continue;
gl_FragColor = sam;
return;
}
}
}

View file

@ -0,0 +1,38 @@
// 2024-04-18 08:42:35
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
#define TAU 6.283185307179586
void main() {
vec2 tx = 1. / dimension;
vec4 col = texture2D( gm_BaseTexture, v_vTexcoord );
gl_FragColor = col;
if(col.a == 1.)
return;
for(float i = 1.; i <= 64.; i++) {
float base = 1.;
float top = 0.;
for(float j = 0.; j <= 64.; j++) {
float ang = top / base * TAU;
top += 2.;
if(top >= base) {
top = 1.;
base *= 2.;
}
vec2 pxs = v_vTexcoord + vec2( cos(ang), sin(ang)) * i * tx;
vec4 sam = texture2D( gm_BaseTexture, pxs );
if(sam.a < 1.) continue;
gl_FragColor = sam;
return;
}
}
}

View file

@ -0,0 +1,49 @@
// 2024-04-18 08:38:57
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
uniform int axis;
uniform float iteration;
void main() {
vec2 tx = 1. / dimension;
vec4 col = texture2D( gm_BaseTexture, v_vTexcoord );
gl_FragColor = col;
if(col.a == 1.)
return;
float _min, _cmp;
vec2 _str, _axs;
if(axis == 0) {
_min = dimension.x;
_cmp = _min * v_vTexcoord.x;
_str = vec2(0., v_vTexcoord.y);
_axs = vec2(tx.x, 0.);
} else {
_min = dimension.y;
_cmp = _min * v_vTexcoord.y;
_str = vec2(v_vTexcoord.x, 0.);
_axs = vec2(0., tx.y);
}
for(float i = 1.; i < 2048.; i++) {
if(i > iteration) break;
vec2 sx = _str + _axs * i;
vec4 ss = texture2D( gm_BaseTexture, sx );
if(ss.a == 1. && abs(i - _cmp) < _min) {
_min = abs(i - _cmp);
col = ss;
}
}
gl_FragColor = col;
}

View file

@ -0,0 +1,49 @@
// 2024-04-18 08:38:57
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
uniform int axis;
uniform float iteration;
void main() {
vec2 tx = 1. / dimension;
vec4 col = texture2D( gm_BaseTexture, v_vTexcoord );
gl_FragColor = col;
if(col.a == 1.)
return;
float _min, _cmp;
vec2 _str, _axs;
if(axis == 0) {
_min = dimension.x;
_cmp = _min * v_vTexcoord.x;
_str = vec2(0., v_vTexcoord.y);
_axs = vec2(tx.x, 0.);
} else {
_min = dimension.y;
_cmp = _min * v_vTexcoord.y;
_str = vec2(v_vTexcoord.x, 0.);
_axs = vec2(0., tx.y);
}
for(float i = 1.; i < 2048.; i++) {
if(i > iteration) break;
vec2 sx = _str + _axs * i;
vec4 ss = texture2D( gm_BaseTexture, sx );
if(ss.a == 1. && abs(i - _cmp) < _min) {
_min = abs(i - _cmp);
col = ss;
}
}
gl_FragColor = col;
}

View file

@ -21,6 +21,9 @@ var pb = e[? "pointer_info_button_change_type"];
var tx = e[? "pointer_info_pen_tilt_x"];
var ty = e[? "pointer_info_pen_tilt_y"];
PEN_X_DELTA = px - PEN_X;
PEN_Y_DELTA = px - PEN_Y;
PEN_X = px;
PEN_Y = py;

View file

@ -1,4 +1,5 @@
globalvar PEN_USE, PEN_CONTACT, PEN_RELEASED, PEN_PRESSURE, PEN_X, PEN_Y;
globalvar PEN_USE, PEN_CONTACT, PEN_RELEASED, PEN_PRESSURE;
globalvar PEN_X, PEN_Y, PEN_X_DELTA, PEN_Y_DELTA;
globalvar PEN_RIGHT_CLICK, PEN_RIGHT_PRESS, PEN_RIGHT_RELEASE;
PEN_USE = false;
@ -6,6 +7,9 @@ PEN_USE = false;
PEN_X = 0;
PEN_Y = 0;
PEN_X_DELTA = 0;
PEN_Y_DELTA = 0;
PEN_CONTACT = false;
PEN_PRESSURE = 0;

View file

@ -7,6 +7,7 @@ function buttonGroup(_data, _onClick) : widget() constructor {
fColor = COLORS._main_text;
current_selecting = 0;
tooltips = [];
for(var i = 0; i < array_length(data); i++)
buttons[i] = button(-1);
@ -18,6 +19,8 @@ function buttonGroup(_data, _onClick) : widget() constructor {
return self;
}
static setTooltips = function(tt) { tooltips = tt; return self; }
static trigger = function() {
if(current_selecting + 1 >= array_length(data))
onClick(0);
@ -75,6 +78,7 @@ function buttonGroup(_data, _onClick) : widget() constructor {
for(var i = 0; i < amo; i++) {
buttons[i].setFocusHover(active, hover);
buttons[i].tooltip = array_safe_get(tooltips, i, "");
var spr = i == 0 ? buttonSpr[0] : (i == amo - 1? buttonSpr[2] : buttonSpr[1]);

View file

@ -135,16 +135,33 @@ function canvas_draw_ellp_size(brush, _x0, _y0, _x1, _y1, _fill) { #region
return;
}
var _min_x = min(_x0, _x1) - 1;
var _max_x = max(_x0, _x1);
var _min_y = min(_y0, _y1) - 1;
var _max_y = max(_y0, _y1);
draw_set_circle_precision(64);
var _min_x = min(_x0, _x1) - 0.5;
var _max_x = max(_x0, _x1) - 0.5;
var _min_y = min(_y0, _y1) - 0.5;
var _max_y = max(_y0, _y1) - 0.5;
if(_fill) {
draw_set_circle_precision(64);
draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
if(brush.brush_surface == noone) {
if(_fill) draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
if(brush.brush_size == 1) {
draw_ellipse(_min_x, _min_y, _max_x, _max_y, 1);
} else if(brush.brush_size < global.FIX_POINTS_AMOUNT) {
var fx = global.FIX_POINTS[brush.brush_size];
for( var i = 0, n = array_length(fx); i < n; i++ )
draw_ellipse(_min_x + fx[i][0], _min_y + fx[i][1], _max_x + fx[i][0], _max_y + fx[i][1], 1);
} else {
draw_ellipse(_min_x, _min_y, _max_x, _max_y, brush.brush_size);
}
return;
}
if(_fill) draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
var samp = 64;
var cx = (_min_x + _max_x) / 2;
var cy = (_min_y + _max_y) / 2;

View file

@ -22,25 +22,34 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
surface_reset_shader();
static destroy = function() {
noti_warning("Selected node has no surface output.");
if(applySelection) canvas.tool_selection.apply();
canvas.nodeTool = noone;
surface_free_safe(maskedSurface);
cleanUp();
}
static cleanUp = function() {
surface_free_safe(targetSurface);
surface_free_safe(maskedSurface);
nodeObject.destroy();
if(is_struct(nodeObject)) {
if(is_instanceof(nodeObject, Node))
nodeObject.destroy();
else {
var keys = struct_get_names(nodeObject);
for (var i = 0, n = array_length(keys); i < n; i++)
if(is_instanceof(nodeObject[$ keys[i]], Node))
nodeObject[$ keys[i]].destroy();
}
}
}
nodeObject = node.build(0, 0);
if(nodeObject == noone || !is_instanceof(nodeObject, Node)) {
noti_warning("Not tools only allows a single node.");
destroy();
return;
}
@ -65,6 +74,7 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
}
if(outputJunction == noone) {
noti_warning("Selected node has no surface output.");
destroy();
return;
}

View file

@ -229,15 +229,18 @@ function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
selection_sy = pos_y;
selection_mx = mouse_cur_x;
selection_my = mouse_cur_y;
}
}
if(key_press(vk_delete)) {
is_selected = false;
surface_free(selection_surface);
}
if(key_press(ord("C"), MOD_KEY.ctrl)) copySelection();
} else if(key_press(vk_escape)) {
apply();
} else if(key_press(ord("C"), MOD_KEY.ctrl)) copySelection();
} #endregion
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region

View file

@ -2,6 +2,8 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
self.tool_attribute = toolAttr;
selecting = false;
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
mouse_cur_x = round((_mx - _x) / _s - 0.5);
@ -13,7 +15,7 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
var _fill_type = tool_attribute.fill8;
if(!selector.is_select_drag && mouse_press(mb_left, active)) {
selecting = true;
canvas_buffer = node.canvas_buffer;
preview_index = node.preview_index;
@ -57,7 +59,8 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
if(node.selection_tool_after != noone)
node.selection_tool_after.toggle();
node.selection_tool_after = noone;
}
} else
selector.apply();
}
}

View file

@ -4,10 +4,10 @@ function checkBoxGroup(sprs, _onClick) : widget() constructor {
onClick = _onClick;
holding = noone;
tooltips = [];
static trigger = function(ind, val) {
onClick(ind, val);
}
static trigger = function(ind, val) { onClick(ind, val); }
static setTooltips = function(tt) { tooltips = tt; return self; }
static drawParam = function(params) {
setParam(params);
@ -44,6 +44,7 @@ function checkBoxGroup(sprs, _onClick) : widget() constructor {
if(hover && point_in_rectangle(_m[0], _m[1], _dx, _dy, _dx + ss, _dy + ss)) {
ind = 1
TOOLTIP = array_safe_get(tooltips, i, "");
if(holding != noone)
trigger(i, holding);

View file

@ -38,7 +38,7 @@
LATEST_VERSION = 11600;
VERSION = 11700;
SAVE_VERSION = 11690;
VERSION_STRING = "1.17.rc1";
VERSION_STRING = "1.17.rc3";
BUILD_NUMBER = 11700;
globalvar HOTKEYS, HOTKEY_CONTEXT;

View file

@ -115,7 +115,7 @@ function LOAD_AT(path, readonly = false, override = false) { #region
s = buffer_read(b, buffer_string);
}
_load_content = json_parse(s);
_load_content = json_try_parse(s);
printIf(log, $" > Load struct : {(get_timer() - t1) / 1000} ms"); t1 = get_timer();

View file

@ -214,10 +214,12 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
tool_attribute.drawLayer = 0;
tool_attribute.pickColor = c_white;
tool_drawLayer_edit = new buttonGroup( [ THEME.canvas_draw_layer, THEME.canvas_draw_layer, THEME.canvas_draw_layer ], function(val) { tool_attribute.drawLayer = val; });
tool_drawLayer_edit = new buttonGroup( [ THEME.canvas_draw_layer, THEME.canvas_draw_layer, THEME.canvas_draw_layer ], function(val) { tool_attribute.drawLayer = val; })
.setTooltips( [ "Draw on top", "Draw behind", "Draw inside" ] );
tool_attribute.mirror = [ false, false, false ];
tool_mirror_edit = new checkBoxGroup( THEME.canvas_mirror, function(ind, val) { tool_attribute.mirror[ind] = val; });
tool_mirror_edit = new checkBoxGroup( THEME.canvas_mirror, function(ind, val) { tool_attribute.mirror[ind] = val; })
.setTooltips( [ "Toggle diagonal", "", "" ] );
tool_settings = [ [ "", tool_channel_edit, "channel", tool_attribute ],
[ "", tool_drawLayer_edit, "drawLayer", tool_attribute ],
@ -512,12 +514,12 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
surface_clear(drawing_surface);
} #endregion
function surface_store_buffers(index = preview_index) { #region
static surface_store_buffers = function(index = preview_index) { #region
for( var i = 0; i < attributes.frames; i++ )
surface_store_buffer(i);
} #endregion
function surface_store_buffer(index = preview_index) { #region
static surface_store_buffer = function(index = preview_index) { #region
if(index >= attributes.frames) return;
buffer_delete(canvas_buffer[index]);
@ -817,6 +819,42 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
draw_surface_ext_safe(preview_draw_mask, 0, 0, 1, 1, 0, c_white, 1);
shader_reset();
draw_set_color(COLORS._main_accent);
if(tool_selection.is_selected) {
var _spx = tool_selection.selection_position[0];
var _spy = tool_selection.selection_position[1];
var _spw = tool_selection.selection_size[0];
var _sph = tool_selection.selection_size[1];
var _x0 = _x + _spx * _s;
var _x1 = _x + (_spx + _spw) * _s;
var _xc = _x + (_spx + _spw / 2) * _s;
var _y0 = _y + _spy * _s;
var _y1 = _y + (_spy + _sph) * _s;
var _yc = _y + (_spy + _sph / 2) * _s;
if(tool_attribute.mirror[1]) draw_line(_xc, _y0, _xc, _y1);
if(tool_attribute.mirror[2]) draw_line(_x0, _yc, _x1, _yc);
} else {
var _x0 = _x;
var _x1 = _x + _dim[0] * _s;
var _xc = _x + _dim[0] / 2 * _s;
var _y0 = _y;
var _y1 = _y + _dim[1] * _s;
var _yc = _y + _dim[1] / 2 * _s;
if(tool_attribute.mirror[0] == false) {
if(tool_attribute.mirror[1]) draw_line(_xc, _y0, _xc, _y1);
if(tool_attribute.mirror[2]) draw_line(_x0, _yc, _x1, _yc);
} else {
if(tool_attribute.mirror[1]) draw_line(_x0, _y1, _x1, _y0);
if(tool_attribute.mirror[2]) draw_line(_x0, _y0, _x1, _y1);
}
}
if(_tool) _tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
#endregion
@ -916,8 +954,6 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
}
} #endregion
static getPreviewValues = function() { return nodeTool == noone || nodeTool.applySelection? output_surface : noone; }
static doSerialize = function(_map) { #region
surface_store_buffers();
var _buff = array_create(attributes.frames);

View file

@ -17,7 +17,7 @@ function Node_Outline(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) c
inputs[| 5] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
.setDisplay(VALUE_DISPLAY.enum_button, ["Inside", "Outside"]);
inputs[| 6] = nodeValue("Anti alising", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, 0);
inputs[| 6] = nodeValue("Anti aliasing", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, 0);
inputs[| 7] = nodeValue("Oversample mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "How to deal with pixel outside the surface.\n - Empty: Use empty pixel\n - Clamp: Repeat edge pixel\n - Repeat: Repeat texture.")
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Empty", "Clamp", "Repeat" ]);

View file

@ -55,7 +55,7 @@ function Node_Shape(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) con
.setDisplay(VALUE_DISPLAY.slider)
.setVisible(false);
inputs[| 6] = nodeValue("Anti alising", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 6] = nodeValue("Anti-aliasing", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 7] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
.setDisplay(VALUE_DISPLAY.rotation);

View file

@ -397,7 +397,6 @@ function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
if(mouse_release(mb_left, active))
click_block = false;
}
} #endregion
@ -502,9 +501,9 @@ function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
if(sliding > 0) { #region
slide_delta += window_mouse_get_delta_x();
slide_delta += window_mouse_get_delta_y();
if(sliding > 0) { #region slide
slide_delta += PEN_USE? PEN_X_DELTA : window_mouse_get_delta_x();
slide_delta += PEN_USE? PEN_Y_DELTA : window_mouse_get_delta_y();
if(sliding == 1 && abs(slide_delta) > 8) {
deactivate();
@ -532,8 +531,10 @@ function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
} else {
var _s = slide_speed;
var _mdx = window_mouse_get_delta_x();
var _mdy = window_mouse_get_delta_y();
var _mdx = PEN_USE? PEN_X_DELTA : window_mouse_get_delta_x();
var _mdy = PEN_USE? PEN_Y_DELTA : window_mouse_get_delta_y();
var _dx = abs(_mdx) > abs(_mdy)? _mdx : -_mdy;
if(key_mod_press(CTRL) && !slide_snap) _s *= 10;