mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2024-12-25 06:26:42 +01:00
expression if, for
This commit is contained in:
parent
26b230431a
commit
bc74de404d
9 changed files with 439 additions and 107 deletions
Binary file not shown.
|
@ -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
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
@ -439,8 +441,9 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
|||
expression = str;
|
||||
expressionUpdate();
|
||||
});
|
||||
express_edit.autocomplete_server = pxl_autocomplete_server;
|
||||
express_edit.function_guide_server = pxl_function_guide_server;
|
||||
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");
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#region data
|
||||
global.EQUATION_PRES = ds_map_create();
|
||||
global.EQUATION_PRES = ds_map_create();
|
||||
global.EQUATION_PRES[? "+"] = 1;
|
||||
global.EQUATION_PRES[? "-"] = 1;
|
||||
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,12 +16,13 @@
|
|||
global.EQUATION_PRES[? "«"] = 6;
|
||||
global.EQUATION_PRES[? "~"] = 9;
|
||||
|
||||
global.EQUATION_PRES[? "="] = -1; //==
|
||||
global.EQUATION_PRES[? "≠"] = -1; //!=
|
||||
global.EQUATION_PRES[? "<"] = 0;
|
||||
global.EQUATION_PRES[? ">"] = 0;
|
||||
global.EQUATION_PRES[? "≤"] = 0;
|
||||
global.EQUATION_PRES[? "≥"] = 0;
|
||||
global.EQUATION_PRES[? "="] = -99;
|
||||
global.EQUATION_PRES[? "⩵"] = -1; //==
|
||||
global.EQUATION_PRES[? "≠"] = -1; //!=
|
||||
global.EQUATION_PRES[? "<"] = 0;
|
||||
global.EQUATION_PRES[? ">"] = 0;
|
||||
global.EQUATION_PRES[? "≤"] = 0;
|
||||
global.EQUATION_PRES[? "≥"] = 0;
|
||||
|
||||
global.EQUATION_PRES[? "@"] = 5; //array accerssor symbol
|
||||
|
||||
|
@ -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;
|
||||
|
@ -271,7 +407,94 @@ function functionStringClean(fx) {
|
|||
return v1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
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
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue