function curveBox(_onModify) : widget() constructor { onModify = _onModify; curve_surface = surface_create(1, 1); node_dragging = -1; node_drag_typ = -1; miny = 0; maxy = 1; static get_x = function(val, _x, _w) { return _x + _w * val; } static get_y = function(val, _y, _h) { return _y + _h * (1 - (val - miny) / (maxy - miny)); } static register = function() {} static drawParam = function(params) { return draw(params.x, params.y, params.w, params.h, params.data, params.m); } static draw = function(_x, _y, _w, _h, _data, _m) { x = _x; y = _y; w = _w; h = _h; if(!is_array(_data) || array_length(_data) == 0) return 0; if(is_array(_data[0])) return 0; var points = array_length(_data) / 6; curve_surface = surface_verify(curve_surface, _w, _h); if(node_dragging != -1) { #region editing if(node_drag_typ == 0) { var node_point = (node_dragging - 2) / 6; if(node_point > 0 && node_point < points - 1) { var _mx = (_m[0] - _x) / _w; _mx = clamp(_mx, 0, 1); var bfx = _data[node_dragging - 6]; var afx = _data[node_dragging + 6]; if(_mx == bfx) node_dragging -= 6; else if(_mx == afx) node_dragging += 6; else _data[node_dragging + 0] = _mx; } var _my = 1 - (_m[1] - _y) / _h; _my = clamp(_my * (maxy - miny) + miny, 0, 1); _data[node_dragging + 1] = _my; //sort by x var _xindex = []; var _pindex = []; for( var i = 0; i < points; i++ ) { var ind = i * 6; var _x0 = _data[ind + 2]; array_push(_xindex, _x0); array_push(_pindex, _x0); } array_sort(_xindex, true); if(node_point > 0 && node_point < points - 1) { var sorted = []; for( var i = 0; i < points; i++ ) { var prog = _xindex[i]; var ind = array_find(_pindex, prog); array_push(sorted, _data[ind * 6 + 0]); array_push(sorted, _data[ind * 6 + 1]); array_push(sorted, _data[ind * 6 + 2]); array_push(sorted, _data[ind * 6 + 3]); array_push(sorted, _data[ind * 6 + 4]); array_push(sorted, _data[ind * 6 + 5]); } if(onModify(sorted)) UNDO_HOLDING = true; } else if(onModify(_data)) UNDO_HOLDING = true; } else { var _px = _data[node_dragging + 0]; var _py = _data[node_dragging + 1]; var _mx = (_m[0] - _x) / _w; _mx = clamp(_mx, 0, 1); _data[node_dragging - 2] = (_px - _mx) * node_drag_typ; _data[node_dragging + 2] = (_mx - _px) * node_drag_typ; var _my = 1 - (_m[1] - _y) / _h; _my = _my * (maxy - miny) + miny; _data[node_dragging - 1] = clamp(_py - _my, -1, 1) * node_drag_typ; _data[node_dragging + 3] = clamp(_my - _py, -1, 1) * node_drag_typ; if(onModify(_data)) UNDO_HOLDING = true; } if(mouse_release(mb_left)) { node_dragging = -1; node_drag_typ = -1; UNDO_HOLDING = false; } } #endregion var node_hovering = -1; var node_hover_typ = -1; var point_insert = 1; var _x1 = 0; var msx = _m[0] - _x; var msy = _m[1] - _y; #region ==== draw ==== surface_set_target(curve_surface); DRAW_CLEAR draw_set_color(COLORS.widget_curve_line); draw_set_alpha(0.75); var y0 = _h - _h * (0 - miny) / (maxy - miny); draw_line(0, y0, _w, y0); var y1 = _h - _h * (1 - miny) / (maxy - miny); draw_line(0, y1, _w, y1); draw_set_alpha(1); for( var i = 0; i < points; i++ ) { var ind = i * 6; var _x0 = _data[ind + 2]; var _y0 = _data[ind + 3]; var bx0 = _x0 + _data[ind + 0]; var by0 = _y0 + _data[ind + 1]; var ax0 = _x0 + _data[ind + 4]; var ay0 = _y0 + _data[ind + 5]; bx0 = get_x(bx0, 0, _w); by0 = get_y(by0, 0, _h); _x0 = get_x(_x0, 0, _w); _y0 = get_y(_y0, 0, _h); ax0 = get_x(ax0, 0, _w); ay0 = get_y(ay0, 0, _h); draw_set_color(COLORS.widget_curve_line); if(i > 0) { //draw pre line draw_line(bx0, by0, _x0, _y0); draw_circle_prec(bx0, by0, 3, false); if(hover && point_in_circle(msx, msy, bx0, by0, 10)) { draw_circle_prec(bx0, by0, 5, false); node_hovering = ind + 2; node_hover_typ = -1; } } if(i < points - 1) { //draw post line draw_line(ax0, ay0, _x0, _y0); draw_circle_prec(ax0, ay0, 3, false); if(hover && point_in_circle(msx, msy, ax0, ay0, 10)) { draw_circle_prec(ax0, ay0, 5, false); node_hovering = ind + 2; node_hover_typ = 1; } } draw_set_color(COLORS._main_accent); draw_circle_prec(_x0, _y0, 3, false); if(hover && point_in_circle(msx, msy, _x0, _y0, 10)) { draw_circle_prec(_x0, _y0, 5, false); node_hovering = ind + 2; node_hover_typ = 0; } if(msx >= _x1 && msy <= _x0) point_insert = i; _x1 = _x0; } draw_set_color(COLORS._main_accent); draw_curve(0, 0, _w, -_h, _data, miny, maxy); surface_reset_target(); #endregion #region ==== buttons ==== var bx = _x + _w - ui(6 + 24); var by = _y + _h - ui(6 + 24); if(buttonInstant(THEME.button_hide, bx, by, ui(24), ui(24), _m, active, hover,, THEME.add) == 2) { miny = 0; maxy = 1; } bx -= ui(24 + 4); if(buttonInstant(THEME.button_hide, bx, by, ui(24), ui(24), _m, active, hover,, THEME.minus) == 2) { miny = -1; maxy = 2; } #endregion if(hover) { #region if(point_in_rectangle(_m[0], _m[1], _x + _w - ui(6 + 24 * 2 + 4), _y + _h - ui(6 + 24), _x + _w + ui(5), _y + _h + ui(5))) { } else if(point_in_rectangle(msx, msy, -ui(5), -ui(5), _w + ui(5), _h + ui(5))) { if(mouse_press(mb_left, active)) { if(node_hovering == -1) { var _ind = point_insert * 6; var _px = (_m[0] - _x) / _w; var _py = 1 - (_m[1] - _y) / _h; array_insert(_data, _ind + 0, -0.1); array_insert(_data, _ind + 1, 0); array_insert(_data, _ind + 2, _px); array_insert(_data, _ind + 3, _py); array_insert(_data, _ind + 4, 0.1); array_insert(_data, _ind + 5, 0); if(onModify(_data)) UNDO_HOLDING = true; node_dragging = _ind + 2; node_drag_typ = 0; } else { node_dragging = node_hovering; node_drag_typ = node_hover_typ; } } else if(mouse_press(mb_right, active)) { var node_point = (node_hovering - 2) / 6; if(node_hover_typ == 0 && node_point > 0 && node_point < points - 1) { array_delete(_data, node_point * 6, 6); if(onModify(_data)) UNDO_HOLDING = true; } } } } #endregion draw_surface(curve_surface, _x, _y); draw_set_color(COLORS.widget_curve_outline); draw_rectangle(_x, _y, _x + _w, _y + _h, true); resetFocus(); return h; } }