Pixel-Composer/scripts/textBox/textBox.gml
2023-07-30 19:56:53 +02:00

578 lines
16 KiB
Plaintext

enum TEXTBOX_INPUT {
text,
number
}
function textBox(_input, _onModify, _extras = noone) : textInput(_input, _onModify, _extras) constructor {
align = _input == TEXTBOX_INPUT.number? fa_right : fa_left;
hide = false;
font = noone;
color = COLORS._main_text;
boxColor = c_white;
no_empty = true;
auto_update = false;
slidable = false;
sliding = false;
slide_mx = 0;
slide_my = 0;
slide_speed = 1 / 10;
starting_char = 1;
_current_text = "";
_input_text = "";
_last_text = "";
current_value = "";
cursor = 0;
cursor_pos = 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;
sprite_index = -1;
text_surface = surface_create(1, 1);
static setFont = function(font) {
self.font = font;
return self;
}
static setEmpty = function() {
no_empty = false;
return self;
}
static activate = function() {
WIDGET_CURRENT = self;
WIDGET_CURRENT_SCROLL = parent;
parentFocus();
_input_text = _current_text;
_last_text = _current_text;
cursor_select = 0;
cursor = string_length(_current_text);
click_block = 1;
KEYBOARD_STRING = "";
keyboard_lastkey = -1;
}
static deactivate = function() {
apply();
WIDGET_CURRENT = noone;
UNDO_HOLDING = false;
}
static onKey = function(key) {
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;
else
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;
else
move_cursor(1);
}
}
static apply = function() {
var _input_text_current = _input_text;
disp_x_to = 0;
switch(input) {
case TEXTBOX_INPUT.number :
_input_text_current = evaluateFunction(_input_text);
break;
}
if(no_empty && _input_text_current == "")
_input_text_current = _last_text;
current_value = _input_text_current;
if(is_callable(onModify))
return onModify(_input_text_current);
return false;
}
static move_cursor = function(delta) {
var ll = string_length(_input_text) + 1;
cursor = safe_mod(cursor + delta + ll, ll);
}
static editText = function() {
#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, maxc - minc));
}
} else {
if(key_mod_press(CTRL) && keyboard_check_pressed(ord("V")))
KEYBOARD_STRING = clipboard_get_text();
if(keyboard_check_pressed(vk_escape) || keyboard_check_pressed(vk_enter)) {
} else if(KEYBOARD_PRESSED == vk_backspace) {
if(cursor_select == -1) {
var str_before = string_copy(_input_text, 1, cursor - 1);
var 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;
}
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;
}
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);
}
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(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 && keyboard_check_pressed(vk_anykey))
apply();
}
static display_text = function(_x, _y, _text, _w, _format, _m = -1) {
_text = string_real(_text);
BLEND_OVERRIDE;
if(!interactable) draw_set_alpha(0.5);
switch(_format) {
case VALUE_DISPLAY._default :
draw_set_text(font == noone? f_p0 : font, fa_left, fa_top, color);
draw_text(_x + disp_x, _y, _text);
break;
case VALUE_DISPLAY.export_format :
draw_set_text(font == noone? f_p0 : font, fa_left, fa_top, color);
var _x0 = _x + disp_x, ch = "", len = string_length(_text), i = 1;
var cc = draw_get_color();
var str = "", _comm = false;
while(i <= len) {
ch = string_char_at(_text, i);
if(ch == "%")
_comm = true;
if(!_comm) {
draw_text(_x0, 0, ch);
_x0 += string_width(ch);
} else {
str += ch;
switch(ch) {
case "d" : draw_set_color(COLORS.widget_text_dec_d); break;
case "n" : draw_set_color(COLORS.widget_text_dec_n); break;
case "e" : draw_set_color(COLORS.widget_text_dec_e); break;
case "f" : draw_set_color(COLORS.widget_text_dec_f); break;
case "i" : draw_set_color(COLORS.widget_text_dec_i); break;
}
switch(ch) {
case "d" : case "n" : case "e" : case "f" : case "i" :
draw_text(_x0, 0, str);
_x0 += string_width(str);
_comm = false;
str = "";
draw_set_color(cc);
break;
}
}
i++;
}
draw_text(_x0, _y, str);
break;
case VALUE_DISPLAY.node_title :
draw_set_text(font == noone? f_p0 : font, fa_left, fa_top, color);
draw_text(_x + disp_x, _y, _text);
break;
}
draw_set_alpha(1);
BLEND_NORMAL;
var _xx = _x, _ch, _chw;
var target = -999;
if(!sliding && _m != -1) {
for( var i = 1; i <= string_length(_text); i++ ) {
_ch = string_char_at(_text, i);
_chw = string_width(_ch);
if(_m < _xx + _chw / 2) {
target = i - 1;
break;
} else if(_m < _xx + _chw) {
target = i;
break;
}
_xx += _chw;
}
}
if(target != -999) {
if(mouse_press(mb_left, active) || click_block == 1) {
cursor_select = -1;
cursor = target;
click_block = 0;
} else if(mouse_click(mb_left, active) && cursor != target) {
cursor_select = target;
}
}
}
static drawParam = function(params) {
return draw(params.x, params.y, params.w, params.h, params.data, params.m,, params.halign, params.valign);
}
static draw = function(_x, _y, _w, _h, _text = "", _m = mouse_ui, _format = VALUE_DISPLAY._default, halign = fa_left, valign = fa_top) {
x = _x;
y = _y;
w = _w;
h = _h;
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;
}
if(extras && instanceof(extras) == "buttonClass") {
extras.setFocusHover(active, hover);
extras.draw(_x + _w - ui(32), _y + _h / 2 - ui(32 / 2), ui(32), ui(32), _m, THEME.button_hide);
_w -= ui(40);
}
draw_set_font(font == noone? f_p0 : font);
var _raw_text = _text;
_text = string_real(_text);
_current_text = _text;
if(sliding > 0) {
var dx = _m[0] - slide_mx;
var dy = -(_m[1] - slide_my);
if(sliding == 1 && (abs(dx) > 16 || abs(dy) > 16)) {
sliding = 2;
slide_mx = _m[0];
slide_my = _m[1];
dx = 0;
dy = 0;
}
if(sliding == 2) {
var _ip = _input_text;
if(!MOUSE_WRAPPING) {
var spd = (abs(dx) > abs(dy)? dx : dy) * slide_speed;
if(key_mod_press(ALT))
spd /= 10;
if(key_mod_press(CTRL))
spd *= 10;
_input_text = string_real(toNumber(_input_text) + spd);
if(apply())
UNDO_HOLDING = true;
}
if(MOUSE_WRAPPING || _input_text != _ip) {
slide_mx = _m[0];
slide_my = _m[1];
}
setMouseWrap();
if(mouse_release(mb_left))
deactivate();
}
if(mouse_release(mb_left)) {
sliding = 0;
UNDO_HOLDING = false;
}
}
var tb_surf_x = _x + ui(8);
var tb_surf_y = _y;
draw_set_text(font == noone? f_p0 : font, fa_left, fa_top);
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;
}
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);
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(self == WIDGET_CURRENT) {
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_text(f_p0b, fa_left, fa_center, COLORS._main_text_sub);
draw_set_alpha(0.5);
if(hover && point_in_rectangle(_m[0], _m[1], _x, _y, _x + ui(32), _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(key_mod_press(ALT))
draw_text(_x + ui(8), _y + _h / 2, "/2");
else
draw_text(_x + ui(8), _y + _h / 2, "x2");
draw_set_alpha(1);
}
#endregion
#region draw
var txt = _input_text;
draw_set_text(font == noone? f_p0 : font, fa_left, fa_top);
var tw = string_width(txt);
var th = string_height(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 = 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 x1 = tx + string_width(string_copy(txt, 1, cursor_select));
draw_roundrect_ext(cursor_pos, c_y0, x1, c_y1, THEME_VALUE.highlight_corner_radius, THEME_VALUE.highlight_corner_radius, 0);
}
var _mx = -1;
var _my = -1;
if(mouse_press(mb_any, active) && hover && hoverRect) {
_mx = _m[0];
_my = _m[1];
}
surface_set_target(text_surface);
DRAW_CLEAR
display_text(tx - tb_surf_x, _h / 2 - th / 2, txt, _w - ui(4), _format, _mx);
surface_reset_target();
draw_surface(text_surface, tb_surf_x, tb_surf_y);
draw_set_color(COLORS._main_text_accent);
draw_line_width(cursor_pos, c_y0, cursor_pos, c_y1, 2);
#endregion
disp_x_to = clamp(disp_x_to, disp_x_min, disp_x_max);
if(!point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h) && mouse_press(mb_left))
deactivate();
} else {
draw_set_text(font == noone? f_p0 : 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);
}
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(hover && hoverRect) {
if(hide)
draw_sprite_stretched_ext(THEME.textbox, 1, _x, _y, _w, _h, boxColor, 0.5);
else
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()) onModify(toNumber(_text) + amo * SCROLL_SPEED);
if(mouse_wheel_up()) onModify(toNumber(_text) - amo * SCROLL_SPEED);
}
} else if(!hide)
draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y, _w, _h, boxColor, 0.5 + 0.5 * interactable);
if(slidable) {
if(_w > ui(64))
draw_sprite_ui_uniform(THEME.text_slider, 0, _x + ui(20), _y + _h / 2, 1, COLORS._main_icon, 0.5);
if(hover && point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h) && mouse_press(mb_left, active)) {
sliding = 1;
slide_mx = _m[0];
slide_my = _m[1];
}
}
surface_set_target(text_surface);
DRAW_CLEAR
//draw_set_color(c_black);
//draw_line(0, _h / 2 - th / 2, 9999, _h / 2 - th / 2);
display_text(tx - tb_surf_x, _h / 2 - th / 2, _display_text, _w - ui(4), _format);
surface_reset_target();
draw_surface(text_surface, tb_surf_x, tb_surf_y);
}
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);
}
resetFocus();
sprite_index = -1;
return _h;
}
}