expression if, for

This commit is contained in:
Tanasart 2023-07-12 21:00:05 +02:00
parent 26b230431a
commit bc74de404d
9 changed files with 439 additions and 107 deletions

Binary file not shown.

View file

@ -76,7 +76,7 @@
VERSION = 1147;
SAVE_VERSION = 1447;
VERSION_STRING = "1.14.6n4";
VERSION_STRING = "1.14.6n5";
BUILD_NUMBER = 114600;
globalvar APPEND_MAP;
@ -214,4 +214,6 @@
#region debug
global.FLAG = {};
global.FLAG.expression_debug = false;
#endregion

View file

@ -14,7 +14,7 @@ function variable_editor(nodeVal) constructor {
/*Text*/ [ "Default", ],
]
tb_name = new textArea(TEXTBOX_INPUT.text, function(str) {
tb_name = new textBox(TEXTBOX_INPUT.text, function(str) {
value_name = str;
value.name = str;

View file

@ -169,7 +169,7 @@ function valueAnimator(_val, _prop, _sep_axis = false) constructor {
if(!prop.is_anim)
return processType(values[| 0].value);
var _time_first = values[| 0].time;
var _time_first = prop.loop_range == -1? values[| 0].time : values[| ds_list_size(values) - 1 - prop.loop_range].time;
var _time_last = values[| ds_list_size(values) - 1].time;
var _time_dura = _time_last - _time_first;

View file

@ -399,6 +399,8 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
def_val = _value;
on_end = KEYFRAME_END.hold;
loop_range = -1;
unit = new nodeValueUnit(self);
extra_data = [];
dyna_depo = ds_list_create();
@ -441,6 +443,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
});
express_edit.autocomplete_server = pxl_autocomplete_server;
express_edit.function_guide_server = pxl_function_guide_server;
express_edit.parser_server = pxl_document_parser;
express_edit.format = TEXT_AREA_FORMAT.code;
express_edit.font = f_code;
express_edit.boxColor = COLORS._main_value_positive;
@ -874,7 +877,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
resetDisplay();
static expressionUpdate = function() {
expTree = evaluateFunctionTree(expression);
expTree = evaluateFunctionList(expression);
node.triggerRender();
}
@ -1114,8 +1117,9 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
val = value_from.getValueRecursive(_time);
if(expUse && is_struct(expTree) && expTree.validate()) {
//print("========== Expression eval ==========")
val[0] = expTree.eval({ value: val[0] });
printIf(global.FLAG.expression_debug, "==================== EVAL BEGIN ====================");
var params = { value: val[0] };
val[0] = expTree.eval(variable_clone(params));
}
return val;
@ -1647,6 +1651,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
return _map;
_map.on_end = on_end;
_map.loop_range = loop_range;
_map.unit = unit.mode;
_map.sep_axis = sep_axis;
_map.shift_x = draw_line_shift_x;
@ -1682,10 +1687,11 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
//printIf(TESTING, " |- Applying deserialize to junction " + name + " of node " + node.name);
on_end = struct_try_get(_map, "on_end");
loop_range = struct_try_get(_map, "loop_range", -1);
unit.mode = struct_try_get(_map, "unit");
expUse = struct_try_get(_map, "global_use");
expression = struct_try_get(_map, "global_key");
expTree = evaluateFunctionTree(expression);
expTree = evaluateFunctionList(expression);
sep_axis = struct_try_get(_map, "sep_axis");
is_anim = struct_try_get(_map, "anim");

View file

@ -90,6 +90,8 @@ function Panel_Animation() : PanelContent() constructor {
tool_width_start = 0;
tool_width_mx = 0;
on_end_dragging_anim = noone;
onion_dragging = noone;
prev_cache = array_create(PROJECT.animator.frames_total);
@ -798,7 +800,7 @@ function Panel_Animation() : PanelContent() constructor {
var key_list = animator.values;
if((animator.prop.on_end == KEYFRAME_END.loop || animator.prop.on_end == KEYFRAME_END.ping) && ds_list_size(key_list) > 1) {
var keyframe_s = key_list[| 0].time;
var keyframe_s = animator.prop.loop_range == -1? key_list[| 0].time : key_list[| ds_list_size(key_list) - 1 - animator.prop.loop_range].time;
var keyframe_e = key_list[| ds_list_size(key_list) - 1].time;
var ks_x = (keyframe_s + 1) * ui(timeline_scale) + timeline_shift;
@ -854,6 +856,7 @@ function Panel_Animation() : PanelContent() constructor {
var prop_y = animator.dopesheet_y;
var key_hover = noone;
var node_y = _node.dopesheet_y + dope_sheet_node_padding;
var anim_set = true;
for(var k = 0; k < ds_list_size(animator.values); k++) {
var keyframe = animator.values[| k];
@ -863,6 +866,14 @@ function Panel_Animation() : PanelContent() constructor {
if(!_node.anim_show) continue;
var cc = COLORS.panel_animation_keyframe_unselected;
if(on_end_dragging_anim == animator.prop && msx < t && anim_set) {
if(k == 0)
animator.prop.loop_range = -1;
else
animator.prop.loop_range = ds_list_size(animator.values) - k;
anim_set = false;
}
if(pHOVER && point_in_circle(msx, msy, t, prop_y, ui(8))) {
cc = COLORS.panel_animation_keyframe_selected;
key_hover = keyframe;
@ -981,10 +992,12 @@ function Panel_Animation() : PanelContent() constructor {
draw_sprite_ui_uniform(THEME.prop_on_end, animator.prop.on_end, tx, ty, 1, COLORS._main_icon_on_inner, 1);
TOOLTIP = __txtx("panel_animation_looping_mode", "Looping mode") + ": " + ON_END_NAME[animator.prop.on_end];
if(mouse_press(mb_left, pFOCUS))
if(mouse_release(mb_left, pFOCUS))
animator.prop.on_end = safe_mod(animator.prop.on_end + 1, sprite_get_number(THEME.prop_on_end));
if(mouse_press(mb_left, pFOCUS))
on_end_dragging_anim = animator.prop;
} else
draw_sprite_ui_uniform(THEME.prop_on_end, animator.prop.on_end, tx, ty, 1, COLORS._main_icon);
draw_sprite_ui_uniform(THEME.prop_on_end, animator.prop.on_end, tx, ty, 1, on_end_dragging_anim == animator.prop? COLORS._main_accent : COLORS._main_icon);
if(pHOVER && point_in_circle(msx, msy, ui(22), ty - 1, ui(10))) {
draw_sprite_ui_uniform(THEME.timeline_clock, 1, ui(22), ty - 1, 1, COLORS._main_icon_on_inner, 1);
@ -1421,6 +1434,13 @@ function Panel_Animation() : PanelContent() constructor {
//}
#endregion
#region on end dragging
if(on_end_dragging_anim != noone) {
if(mouse_release(mb_left))
on_end_dragging_anim = false;
}
#endregion
#region draw graph, easing line
var key_hover = noone;

View file

@ -1,13 +1,48 @@
global.GLOBAL_VAR = [ "project" ];
global.NODE_SUB_CATAG = [ "input", "output" ];
function pxl_autocomplete_server(prompt) {
function pxl_document_parser(prompt) {
var params = [];
var lines = string_split(prompt, "\n");
for( var i = 0; i < array_length(lines); i++ ) {
var line = lines[i];
line = functionStringClean(line);
var eq = string_split(line, "=");
if(array_length(eq) > 1) {
for( var j = 0; j < array_length(eq) - 1; j++ )
array_push(params, string_trim(eq[j]));
}
}
return params;
}
function pxl_autocomplete_server(prompt, params = []) {
var res = [];
var pr_list = ds_priority_create();
//////////////////////////////////
ds_priority_clear(pr_list);
for( var i = 0; i < array_length(params); i++ ) {
var gl = params[i];
var match = string_partial_match(string_lower(gl), string_lower(prompt));
if(match == -9999) continue;
ds_priority_add(pr_list, [[THEME.ac_constant, 2], gl, "local", gl], match);
}
repeat(ds_priority_size(pr_list))
array_push(res, ds_priority_delete_max(pr_list));
//////////////////////////////////
ds_priority_clear(pr_list);
for( var i = 0; i < array_length(global.GLOBAL_VAR); i++ ) {
var gl = global.GLOBAL_VAR[i];
@ -23,6 +58,27 @@ function pxl_autocomplete_server(prompt) {
//////////////////////////////////
ds_priority_clear(pr_list);
var F = PROJECT.globalNode.value;
var k = ds_map_find_first(F);
var a = ds_map_size(F);
repeat(a) {
var match = string_partial_match(string_lower(k), string_lower(prompt));
if(match == -9999) {
k = ds_map_find_next(F, k);
continue;
}
var fn = F[? prompt];
ds_priority_add(pr_list, [[THEME.ac_constant, 0], k, "global", k], match);
k = ds_map_find_next(F, k);
}
repeat(ds_priority_size(pr_list))
array_push(res, ds_priority_delete_max(pr_list));
//////////////////////////////////
ds_priority_clear(pr_list);
var sp = string_splice(prompt, ".");
if(array_length(sp) > 1) {
@ -102,7 +158,7 @@ function pxl_autocomplete_server(prompt) {
}
var fn = F[? prompt];
ds_priority_add(pr_list, [[THEME.ac_constant, 0], k, "node", k], match);
ds_priority_add(pr_list, [[THEME.ac_constant, 1], k, "node", k], match);
k = ds_map_find_next(F, k);
}

View file

@ -5,6 +5,7 @@
global.EQUATION_PRES[? "∸"] = 9; //unary negative
global.EQUATION_PRES[? "*"] = 2;
global.EQUATION_PRES[? "/"] = 2;
global.EQUATION_PRES[? "%"] = 2;
global.EQUATION_PRES[? "$"] = 3;
global.EQUATION_PRES[? "&"] = 5;
@ -15,7 +16,8 @@
global.EQUATION_PRES[? "«"] = 6;
global.EQUATION_PRES[? "~"] = 9;
global.EQUATION_PRES[? "="] = -1; //==
global.EQUATION_PRES[? "="] = -99;
global.EQUATION_PRES[? "⩵"] = -1; //==
global.EQUATION_PRES[? "≠"] = -1; //!=
global.EQUATION_PRES[? "<"] = 0;
global.EQUATION_PRES[? ">"] = 0;
@ -33,6 +35,8 @@
global.FUNCTIONS[? "ceil"] = [ ["number"], function(val) { return ceil(val[0]); } ];
global.FUNCTIONS[? "floor"] = [ ["number"], function(val) { return floor(val[0]); } ];
global.FUNCTIONS[? "lerp"] = [ ["number_0", "number_1", "amount"], function(val) { return lerp(array_safe_get(val, 0), array_safe_get(val, 1), array_safe_get(val, 2)); } ];
global.FUNCTIONS[? "wiggle"] = [ ["time", "frequency", "octave", "seed"], function(val) {
return wiggle(0, 1, array_safe_get(val, 1),
array_safe_get(val, 0),
@ -65,13 +69,14 @@ function functionStringClean(fx) {
fx = string_replace_all(fx, "<<", "«");
fx = string_replace_all(fx, ">>", "»");
fx = string_replace_all(fx, "==", "=");
fx = string_replace_all(fx, "==", "");
fx = string_replace_all(fx, "!=", "≠");
fx = string_replace_all(fx, "<>", "≠");
fx = string_replace_all(fx, ">=", "≥");
fx = string_replace_all(fx, "<=", "≤");
fx = string_replace_all(fx, "[", "@["); //add array accessor symbol arr[i] = arr@[i] = arr @ (i)
fx = string_trim(fx);
return fx;
}
@ -83,6 +88,131 @@ function functionStringClean(fx) {
animated
}
function __funcList() constructor {
funcTrees = [];
static addFunction = function(fn) {
array_push(funcTrees, fn);
}
static validate = function() {
for( var i = 0; i < array_length(funcTrees); i++ )
if(!funcTrees[i].validate())
return false;
return true;
}
static isAnimated = function() {
for( var i = 0; i < array_length(funcTrees); i++ )
if(!funcTrees[i].isAnimated())
return false;
return true;
}
static eval = function(params = {}) {
//var _params = variable_clone(params);
var val = 0;
for( var i = 0; i < array_length(funcTrees); i++ )
val = funcTrees[i].eval(params);
return val;
}
}
function __funcIf() constructor {
condition = noone;
if_true = new __funcList();
if_false = new __funcList();
static validate = function() {
if(condition != noone && !condition.validate()) return false;
if(if_true != noone && !if_true.validate()) return false;
if(if_false != noone && !if_false.validate()) return false;
return true;
}
static isAnimated = function() {
if(condition != noone && !condition.isAnimated()) return false;
if(if_true != noone && !if_true.isAnimated()) return false;
if(if_false != noone && !if_false.isAnimated()) return false;
return true;
}
static eval = function(params = {}) {
if(condition == noone) return 0;
var res = condition.eval(params);
printIf(global.FLAG.expression_debug, $"<<<<<< IF {res} >>>>>>");
if(res) return if_true == noone? 0 : if_true.eval(params);
else return if_false == noone? 0 : if_false.eval(params);
}
}
function __funcFor() constructor {
itr_array = false;
cond_init = noone;
cond_iter = noone;
cond_term = noone;
cond_arr = noone;
cond_step = 1;
action = new __funcList();
static validate = function() {
if(itr_array) {
if(cond_arr == noone || !cond_arr.validate()) return false;
} else {
if(cond_init == noone || !cond_init.validate()) return false;
if(cond_term == noone || !cond_term.validate()) return false;
}
if(action != noone && !action.validate()) return false;
return true;
}
static isAnimated = function() {
if(itr_array) {
if(cond_arr == noone || !cond_arr.isAnimated()) return false;
} else {
if(cond_init == noone || !cond_init.isAnimated()) return false;
if(cond_term == noone || !cond_term.isAnimated()) return false;
}
if(action != noone && !action.isAnimated()) return false;
return true;
}
static eval = function(params = {}) {
if(itr_array) {
var _arr = cond_arr.eval(params);
printIf(global.FLAG.expression_debug, $"<<<<<< FOR EACH {_arr} >>>>>>");
for( var i = 0; i < array_length(_arr); i++ ) {
var val = _arr[i];
params[$ cond_iter] = val;
printIf(global.FLAG.expression_debug, $"<< ITER {i}: {cond_iter} = {val} >>");
action.eval(params);
}
} else {
printIf(global.FLAG.expression_debug, "<< FOR >>");
cond_init.eval(params);
while(cond_term.eval(params)) {
action.eval(params);
cond_iter.eval(params);
}
}
}
}
function __funcTree(symbol, l = noone, r = noone) constructor {
self.symbol = symbol;
self.l = l;
@ -101,13 +231,15 @@ function functionStringClean(fx) {
static getVal = function(val, params = {}, getRaw = false) {
if(is_struct(val)) return val.eval(params);
if(is_real(val)) return val;
if(getRaw) return val;
if(is_string(val)) val = string_trim(val);
//printIf(global.FLAG.expression_debug, $" [ get struct {params}[{val}] ]");
if(struct_has(params, val))
return struct_try_get(params, val);
if(getRaw) return val;
if(_string(string_trim(val)))
return string_trim(val);
@ -188,13 +320,13 @@ function functionStringClean(fx) {
_l[i] = getVal(l[i], params);
var res = _ev(_l);
//print($"Function {symbol}{_l} = {res}");
//print("====================");
printIf(global.FLAG.expression_debug, $"Function {symbol}{_l} = {res}");
printIf(global.FLAG.expression_debug, "====================");
return res;
}
var v1 = getVal(l, params, symbol == "【");
var v1 = getVal(l, params, symbol == "=" || symbol == "【");
var v2 = getVal(r, params);
var res = 0;
@ -207,6 +339,9 @@ function functionStringClean(fx) {
res[i] = getVal(v1[i], params);
} else if(symbol == "@") {
res = is_real(v2)? array_safe_get(v1, v2) : 0;
} else if(symbol == "=") {
params[$ v1] = v2;
res = v2;
} else if(is_array(v1) && !is_array(v2)) {
res = array_create(array_length(v1));
for( var i = 0; i < array_length(res); i++ )
@ -222,11 +357,11 @@ function functionStringClean(fx) {
} else
res = eval_real(v1, v2);
//print($"|{v1}|{symbol}|{v2}| = {res}");
//print($"symbol : {symbol}");
//print($"l : | {typeof(l)} |{l}|");
//print($"r : | {typeof(r)} |{r}|");
//print("====================");
printIf(global.FLAG.expression_debug, $"|{v1}|{symbol}|{v2}| = {res}");
printIf(global.FLAG.expression_debug, $"symbol : {symbol}");
printIf(global.FLAG.expression_debug, $"l : | {typeof(l)} |{l}|");
printIf(global.FLAG.expression_debug, $"r : | {typeof(r)} |{r}|");
printIf(global.FLAG.expression_debug, "====================");
return res;
}
@ -244,6 +379,7 @@ function functionStringClean(fx) {
case "*": return (is_real(v1) && is_real(v2))? v1 * v2 : 0;
case "$": return (is_real(v1) && is_real(v2))? power(v1, v2) : 0;
case "/": return (is_real(v1) && is_real(v2) && v2 != 0)? v1 / v2 : 0;
case "%": return (is_real(v1) && is_real(v2) && v2 != 0)? v1 % v2 : 0;
case "&": return (is_real(v1) && is_real(v2))? v1 & v2 : 0;
case "|": return (is_real(v1) && is_real(v2))? v1 | v2 : 0;
@ -252,7 +388,7 @@ function functionStringClean(fx) {
case "»": return (is_real(v1) && is_real(v2))? v1 >> v2 : 0;
case "~": return is_real(v1)? ~v1 : 0;
case "=": return (is_real(v1) && is_real(v2))? v1 == v2 : 0;
case "": return (is_real(v1) && is_real(v2))? v1 == v2 : 0;
case "≠": return (is_real(v1) && is_real(v2))? v1 != v2 : 0;
case "≤": return (is_real(v1) && is_real(v2))? v1 <= v2 : 0;
case "≥": return (is_real(v1) && is_real(v2))? v1 >= v2 : 0;
@ -272,6 +408,93 @@ function functionStringClean(fx) {
}
}
function functionStrip(fx) {
var el_st = 1;
var el_ed = 1;
for( var i = 1; i <= string_length(fx); i++ ) {
var cch = string_char_at(fx, i);
if(cch == "(") {
el_st = i + 1;
break;
}
}
for( var i = string_length(fx); i >= 1; i-- ) {
var cch = string_char_at(fx, i);
if(cch == ")") {
el_ed = i;
break;
}
}
return string_copy(fx, el_st, el_ed - el_st)
}
function evaluateFunctionList(fx) {
var fxs = string_split(fx, "\n");
var flist = new __funcList();
var call_st = ds_stack_create();
ds_stack_push(call_st, flist);
for( var i = 0; i < array_length(fxs); i++ ) {
var _fx = functionStringClean(fxs[i]);
if(_fx == "") continue;
var _fx_sp = string_split(_fx, "(");
if(string_char_at(_fx, 1) == "}") {
ds_stack_pop(call_st);
_fx = string_replace(_fx, "}", "");
}
if(array_length(_fx_sp) > 1) {
var _cond = functionStrip(_fx);
switch(_fx_sp[0]) {
case "if":
var con_if = new __funcIf();
con_if.condition = evaluateFunctionTree(_cond);
ds_stack_top(call_st).addFunction(con_if);
ds_stack_push(call_st, con_if.if_true);
continue;
case "else if":
var con_if = new __funcIf();
con_if.condition = evaluateFunctionTree(_cond);
ds_stack_top(call_st).addFunction(con_if);
ds_stack_push(call_st, con_if.if_true);
continue;
case "else":
ds_stack_push(call_st, con_if.if_false);
continue;
case "for":
var con_for = new __funcFor();
var cond = string_splice(_cond, ":");
if(array_length(cond) == 2) {
con_for.itr_array = true;
con_for.cond_iter = cond[0];
con_for.cond_arr = evaluateFunctionTree(cond[1]);
} else if(array_length(cond) == 3) {
con_for.itr_array = false;
con_for.cond_init = evaluateFunctionTree(cond[0]);
con_for.cond_iter = evaluateFunctionTree(cond[1]);
con_for.cond_term = evaluateFunctionTree(cond[2]);
}
ds_stack_top(call_st).addFunction(con_for);
ds_stack_push(call_st, con_for.action);
continue;
}
}
ds_stack_top(call_st).addFunction(evaluateFunctionTree(_fx));
}
var val = ds_stack_pop(call_st);
ds_stack_destroy(call_st);
return val;
}
function evaluateFunctionTree(fx) {
static __BRACKETS = [ "(", ")", "[", "]" ];
@ -280,8 +503,6 @@ function functionStringClean(fx) {
var op = ds_stack_create();
var last_push = "";
fx = functionStringClean(fx);
var len = string_length(fx);
var l = 1;
var ch = "";
@ -294,6 +515,8 @@ function functionStringClean(fx) {
while(l <= len) {
ch = string_char_at(fx, l);
//print($"Analyzing {ch}");
if(ds_map_exists(pres, ch)) { //symbol is operator
if(ds_stack_empty(op)) ds_stack_push(op, ch);
else {
@ -348,10 +571,12 @@ function functionStringClean(fx) {
var arr = [];
while(ds_stack_size(vl) > _top[1])
array_insert(arr, 0, ds_stack_pop(vl));
ds_stack_push(vl, arr);
ds_stack_pop(op);
ds_stack_push(vl, new __funcTree("【", arr));
break;
}
print($"Build tree {_top}");
ds_stack_push(vl, buildFuncTree(_top, vl));
}
@ -399,14 +624,17 @@ function functionStringClean(fx) {
}
}
//print($"op: {ds_stack_size(op)}; vl: {ds_stack_size(vl)}");
_ch = ch;
}
while(!ds_stack_empty(op))
ds_stack_push(vl, buildFuncTree(ds_stack_pop(op), vl));
ds_stack_destroy(op);
var tree = ds_stack_empty(vl)? noone : ds_stack_pop(vl)
var tree = ds_stack_empty(vl)? noone : ds_stack_pop(vl);
ds_stack_destroy(op);
ds_stack_destroy(vl);
if(!is_struct(tree))
@ -440,17 +668,14 @@ function functionStringClean(fx) {
case "@":
var _v1 = ds_stack_pop(vl);
if(is_array(_v1))
return new __funcTree("【", _v1);
else {
var _v2 = ds_stack_pop(vl);
return new __funcTree(operator, _v2, _v1);
}
case "+": //binary operators
case "*":
case "$":
case "/":
case "%":
case "|":
case "&":
@ -459,6 +684,7 @@ function functionStringClean(fx) {
case "«":
case "=":
case "⩵":
case "≠":
case "≤":
case "≥":
@ -479,6 +705,6 @@ function functionStringClean(fx) {
function evaluateFunction(fx, params = {}) {
if(isNumber(fx)) return toNumber(fx);
return evaluateFunctionTree(fx).eval(params);
return evaluateFunctionList(fx).eval(params);
}
#endregion

View file

@ -39,6 +39,8 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
code_line_width = 48;
parser_server = noone;
autocomplete_box = instance_create(0, 0, o_dialog_textbox_autocomplete);
autocomplete_box.textbox = self;
autocomplete_server = noone;
@ -73,6 +75,67 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
UNDO_HOLDING = false;
}
static onModified = function() {
if(format == TEXT_AREA_FORMAT.code && autocomplete_server != noone) {
var crop = string_copy(_input_text, 1, cursor);
var slp = string_splice(crop, [" ", "(", ",", "\n"]);
var pmt = array_safe_get(slp, -1,, ARRAY_OVERFLOW.loop);
var params = [];
if(parser_server != noone)
params = parser_server(crop);
var data = autocomplete_server(pmt, params);
if(array_length(data)) {
autocomplete_box.data = data;
autocomplete_box.active = true;
autocomplete_box.dialog_x = rx + cursor_pos_x + 1;
autocomplete_box.dialog_y = ry + cursor_pos_y + line_get_height() + 1;
autocomplete_box.prompt = pmt;
autocomplete_box.selecting= 0;
} else
autocomplete_box.active = false;
var _c = cursor;
var _v = false;
var _fn = "";
var _el = 0;
var amo = 0;
while(_c > 1) {
var cch0 = string_char_at(_input_text, _c - 1);
var cch1 = string_char_at(_input_text, _c);
if(_el == 0 && cch1 == ",") amo++;
if(_el == 0 && cch1 == "(" && string_variable_valid(cch0))
_v = true;
else if(cch1 == ")") _el++;
else if(cch1 == "(") _el--;
if(_v) {
if(!string_variable_valid(cch0))
break;
_fn = cch0 + _fn;
}
_c--;
}
var guide = function_guide_server(_fn);
if(guide != "") {
function_guide_box.active = true;
function_guide_box.dialog_x = rx + cursor_pos_x + 1;
function_guide_box.dialog_y = ry + cursor_pos_y - 12;
function_guide_box.prompt = guide;
function_guide_box.index = amo;
} else
function_guide_box.active = false;
}
}
static onKey = function(key) {
if(key == vk_left) {
if(key_mod_press(SHIFT)) {
@ -140,6 +203,7 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
cursor_select = -1;
cursor = _target;
onModified();
}
if(format != TEXT_AREA_FORMAT.code || !autocomplete_box.active)
@ -174,6 +238,7 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
cursor_select = -1;
cursor = _target;
onModified();
}
}
@ -185,6 +250,8 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
static move_cursor = function(delta) {
var ll = string_length(_input_text);
cursor = clamp(cursor + delta, 0, ll);
onModified();
}
static cut_line = function() {
@ -238,6 +305,10 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
}
static editText = function() {
//print("==========");
//print(_input_text);
//print($"cursor: {cursor}");
var modified = false;
#region text editor
@ -256,7 +327,7 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
if(keyboard_check_pressed(vk_escape)) {
} else if(keyboard_check_pressed(vk_tab)) {
} else if(keyboard_check_pressed(vk_enter) && !key_mod_press(SHIFT)) {
} else if(keyboard_check_pressed(vk_enter) && key_mod_press(SHIFT)) {
var ch = "\n";
if(cursor_select == -1) {
var str_before = string_copy(_input_text, 1, cursor);
@ -350,64 +421,7 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
keyboard_lastkey = -1;
#endregion
if(modified) {
#region autocomplete
if(format == TEXT_AREA_FORMAT.code && autocomplete_server != noone) {
var crop = string_copy(_input_text, 1, cursor);
var slp = string_splice(crop, [" ", "(", ","]);
var pmt = array_safe_get(slp, -1,, ARRAY_OVERFLOW.loop);
var data = autocomplete_server(pmt);
if(array_length(data)) {
autocomplete_box.data = data;
autocomplete_box.active = true;
autocomplete_box.dialog_x = rx + cursor_pos_x + 1;
autocomplete_box.dialog_y = ry + cursor_pos_y + line_get_height() + 1;
autocomplete_box.prompt = pmt;
autocomplete_box.selecting= 0;
} else
autocomplete_box.active = false;
var _c = cursor;
var _v = false;
var _fn = "";
var _el = 0;
var amo = 0;
while(_c > 1) {
var cch0 = string_char_at(_input_text, _c - 1);
var cch1 = string_char_at(_input_text, _c);
if(_el == 0 && cch1 == ",") amo++;
if(_el == 0 && cch1 == "(" && string_variable_valid(cch0))
_v = true;
else if(cch1 == ")") _el++;
else if(cch1 == "(") _el--;
if(_v) {
if(!string_variable_valid(cch0))
break;
_fn = cch0 + _fn;
}
_c--;
}
var guide = function_guide_server(_fn);
if(guide != "") {
function_guide_box.active = true;
function_guide_box.dialog_x = rx + cursor_pos_x + 1;
function_guide_box.dialog_y = ry + cursor_pos_y - 12;
function_guide_box.prompt = guide;
function_guide_box.index = amo;
} else
function_guide_box.active = false;
}
#endregion
}
if(modified) onModified();
if(auto_update && keyboard_check_pressed(vk_anykey))
apply();
@ -440,11 +454,11 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
while(string_char_at(_input_text, cursor + 1) != "\n" && cursor < string_length(_input_text)) {
cursor++;
}
} else if(keyboard_check_pressed(vk_escape)) {
} else if(keyboard_check_pressed(vk_escape) && !autocomplete_box.active) {
_input_text = _last_value;
cut_line();
deactivate();
} else if(keyboard_check_pressed(vk_enter) && key_mod_press(SHIFT)) {
} else if(keyboard_check_pressed(vk_enter) && !key_mod_press(SHIFT)) {
deactivate();
}
}
@ -466,6 +480,14 @@ function textArea(_input, _onModify, _extras = noone) : textInput(_input, _onMod
var ch_y = _y;
var _str;
//print("==========");
//print(_text);
//print(">>>>");
//print(_input_text);
//print("----");
//print(_input_text_line);
//print($"cursor: {cursor}");
if(_input_text != _text) {
_input_text = _text;
cut_line();