Pixel-Composer/scripts/node_rigid_object/node_rigid_object.gml

764 lines
20 KiB
Text
Raw Normal View History

2024-03-22 11:15:22 +01:00
enum RIGID_SHAPE {
box,
circle,
mesh
}
2023-02-28 09:43:01 +01:00
function Node_Rigid_Object(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Object";
2023-02-14 05:32:32 +01:00
color = COLORS.node_blend_simulation;
icon = THEME.rigidSim;
2024-03-28 14:18:02 +01:00
setDimension(96, 96);
2023-01-25 06:49:00 +01:00
manual_ungroupable = false;
object = [];
2023-06-13 14:42:06 +02:00
attributes.mesh = [];
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 0] = nodeValue("Affect by force", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true)
2023-10-09 07:36:20 +02:00
.rejectArray()
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 1] = nodeValue("Weight", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5)
2023-10-09 07:36:20 +02:00
.rejectArray()
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 2] = nodeValue("Contact friction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.2)
2023-10-09 07:36:20 +02:00
.rejectArray()
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 3] = nodeValue("Air resistance", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.2)
2023-10-09 07:36:20 +02:00
.rejectArray()
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 4] = nodeValue("Rotation resistance", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.2)
2023-10-09 07:36:20 +02:00
.rejectArray()
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 5] = nodeValue("Shape", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
2024-01-28 09:53:41 +01:00
.setDisplay(VALUE_DISPLAY.enum_scroll, [ new scrollItem("Box", s_node_shape_type, 0), new scrollItem("Circle", s_node_shape_type, 1), new scrollItem("Custom", s_node_shape_misc, 1) ])
2023-10-09 07:36:20 +02:00
.rejectArray()
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2023-10-09 07:36:20 +02:00
inputs[| 6] = nodeValue("Texture", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone)
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
inputs[| 7] = nodeValue("Start position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 16, 16 ])
2023-10-09 07:36:20 +02:00
.setDisplay(VALUE_DISPLAY.vector)
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 8] = nodeValue("Spawn", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true, "Make object spawn when start.")
2023-10-09 07:36:20 +02:00
.rejectArray()
.setAnimable(false);
2023-01-25 06:49:00 +01:00
2024-04-08 07:13:46 +02:00
inputs[| 9] = nodeValue("Generate mesh", self, JUNCTION_CONNECT.input, VALUE_TYPE.trigger, false )
.setDisplay(VALUE_DISPLAY.button, { name: "Generate", UI : true, onClick: function() { generateAllMesh(); } });
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 10] = nodeValue("Mesh expansion", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
2023-10-06 11:51:11 +02:00
.setDisplay(VALUE_DISPLAY.slider, { range: [ -2, 2, 0.1 ] })
2023-10-09 07:36:20 +02:00
.rejectArray()
.setAnimable(false);
2023-10-06 11:51:11 +02:00
2023-10-09 07:36:20 +02:00
inputs[| 11] = nodeValue("Add pixel collider", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true)
.rejectArray()
.setAnimable(false);
2024-03-22 11:15:22 +01:00
inputs[| 12] = nodeValue("Collision group", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
2023-12-18 13:54:33 +01:00
.rejectArray()
2024-03-22 11:15:22 +01:00
outputs[| 0] = nodeValue("Object", self, JUNCTION_CONNECT.output, VALUE_TYPE.rigid, object);
2023-01-25 06:49:00 +01:00
2023-12-18 13:54:33 +01:00
input_display_list = [ 8, 12,
2024-03-23 07:26:11 +01:00
["Texture", false], 6,
["Physics", false], 0, 1, 2, 3, 4,
["Shape", false], 7, 5, 9, 10, 11,
2023-01-25 06:49:00 +01:00
];
static newMesh = function(index) {
2023-06-13 14:42:06 +02:00
var mesh = struct_try_get(attributes, "mesh", []);
2023-04-10 20:02:59 +02:00
mesh[index] = [ [ 0, 0],
[32, 0],
[32, 32],
[ 0, 32] ];
2023-06-13 14:42:06 +02:00
attributes.mesh = mesh;
2023-01-25 06:49:00 +01:00
}
newMesh(0);
2023-12-19 14:30:34 +01:00
tools = [];
mesh_tools = [
2023-03-11 01:40:17 +01:00
new NodeTool( "Mesh edit", THEME.mesh_tool_edit ),
new NodeTool( "Anchor remove", THEME.mesh_tool_delete ),
2023-01-25 06:49:00 +01:00
];
2023-10-07 09:09:18 +02:00
is_convex = true;
2023-12-19 14:30:34 +01:00
hover = -1;
2023-10-07 09:09:18 +02:00
anchor_dragging = -1;
anchor_drag_sx = -1;
anchor_drag_sy = -1;
anchor_drag_mx = -1;
anchor_drag_my = -1;
2023-01-25 06:49:00 +01:00
2023-10-07 09:09:18 +02:00
static getPreviewValues = function() { #region
return getInputData(6);
} #endregion
2023-10-06 11:51:11 +02:00
2023-10-07 09:09:18 +02:00
static generateAllMesh = function() { #region
var _tex = getInputData(6);
2023-10-06 11:51:11 +02:00
if(is_array(_tex)) {
for( var i = 0, n = array_length(_tex); i < n; i++ )
generateMesh(i);
} else
generateMesh();
doUpdate();
2023-10-07 09:09:18 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-07 09:09:18 +02:00
static drawOverlayPreviewSingle = function(_i, _x, _y, _s, _pr_x, _pr_y, _tex_s) { #region
2023-10-06 11:51:11 +02:00
var meshes = attributes.mesh;
var _shp = getInputData(5);
2023-01-25 06:49:00 +01:00
2023-10-07 09:09:18 +02:00
var ww = surface_get_width_safe(_tex_s);
var hh = surface_get_height_safe(_tex_s);
var _tex = _tex_s;
2023-01-25 06:49:00 +01:00
2023-10-07 09:09:18 +02:00
if(is_instanceof(_tex_s, SurfaceAtlas)) {
_tex = _tex_s.getSurface();
_pr_x += _tex_s.x * _s;
_pr_y += _tex_s.y * _s;
} else {
2023-10-06 11:51:11 +02:00
_pr_x -= ww * _s / 2;
_pr_y -= hh * _s / 2;
}
if(_shp == 2 && array_length(meshes) > _i) {
draw_set_color(is_convex? COLORS._main_accent : COLORS._main_value_negative);
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
var _m = meshes[_i];
var _l = array_length(_m);
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
for( var i = 0; i < _l; i++ ) {
var _px0 = _m[i][0];
var _py0 = _m[i][1];
var _px1 = _m[safe_mod(i + 1, _l)][0];
var _py1 = _m[safe_mod(i + 1, _l)][1];
2023-04-10 20:02:59 +02:00
2023-10-06 11:51:11 +02:00
_px0 = _pr_x + _px0 * _s;
_py0 = _pr_y + _py0 * _s;
_px1 = _pr_x + _px1 * _s;
_py1 = _pr_y + _py1 * _s;
draw_line_width(_px0, _py0, _px1, _py1, 1);
2023-01-25 06:49:00 +01:00
}
2023-10-07 09:09:18 +02:00
}
2023-01-25 06:49:00 +01:00
2023-10-07 09:09:18 +02:00
draw_surface_ext_safe(_tex, _pr_x, _pr_y, _s, _s, 0, c_white, 0.5);
2023-10-06 11:51:11 +02:00
} #endregion
2024-03-22 11:15:22 +01:00
static drawOverlayPreview = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
2023-10-06 11:51:11 +02:00
var _pos = getInputData(7);
var _tex = getInputData(6);
2023-10-07 09:09:18 +02:00
var _pr_x = _x + _pos[0] * _s;
var _pr_y = _y + _pos[1] * _s;
if(is_array(_tex)) {
for( var i = 0, n = array_length(_tex); i < n; i++ )
drawOverlayPreviewSingle(i, _x, _y, _s, _pr_x, _pr_y, _tex[i]);
} else
drawOverlayPreviewSingle(0, _x, _y, _s, _pr_x, _pr_y, _tex);
2023-12-19 14:30:34 +01:00
2024-03-14 14:35:19 +01:00
return inputs[| 7].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
2023-10-07 09:09:18 +02:00
} #endregion
2024-03-14 14:35:19 +01:00
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
2023-12-19 14:30:34 +01:00
var gr = is_instanceof(group, Node_Rigid_Group)? group : noone;
if(inline_context != noone) gr = inline_context;
2023-12-19 14:30:34 +01:00
if(gr == noone) return;
if(previewing == 0) {
for( var i = 0, n = ds_list_size(gr.nodes); i < n; i++ ) {
var _node = gr.nodes[| i];
2023-10-07 09:09:18 +02:00
if(!is_instanceof(_node, Node_Rigid_Object)) continue;
2023-10-09 07:36:20 +02:00
var _hov = _node.drawOverlayPreview(active, _x, _y, _s, _mx, _my, _snx, _sny);
active &= _hov;
2023-10-06 11:51:11 +02:00
}
2023-10-09 07:36:20 +02:00
return active;
2023-01-25 06:49:00 +01:00
}
2023-10-07 09:09:18 +02:00
var _shp = getInputData(5);
2023-10-09 07:36:20 +02:00
if(_shp != 2) return active;
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
var meshes = attributes.mesh;
2023-01-25 06:49:00 +01:00
var _hover = -1, _side = 0;
draw_set_color(is_convex? COLORS._main_accent : COLORS._main_value_negative);
2023-04-10 20:02:59 +02:00
var mesh = meshes[preview_index];
var len = array_length(mesh);
2023-01-25 06:49:00 +01:00
is_convex = true;
for( var i = 0; i < len; i++ ) {
2023-04-10 20:02:59 +02:00
var _px0 = mesh[safe_mod(i + 0, len)][0];
var _py0 = mesh[safe_mod(i + 0, len)][1];
var _px1 = mesh[safe_mod(i + 1, len)][0];
var _py1 = mesh[safe_mod(i + 1, len)][1];
var _px2 = mesh[safe_mod(i + 2, len)][0];
var _py2 = mesh[safe_mod(i + 2, len)][1];
2023-01-25 06:49:00 +01:00
var side = cross_product(_px0, _py0, _px1, _py1, _px2, _py2);
if(_side != 0 && sign(_side) != sign(side))
is_convex = false;
_side = side;
var _dx0 = _x + _px0 * _s;
var _dy0 = _y + _py0 * _s;
var _dx1 = _x + _px1 * _s;
var _dy1 = _y + _py1 * _s;
draw_line_width(_dx0, _dy0, _dx1, _dy1, hover == i + 0.5? 4 : 2);
2023-03-11 01:40:17 +01:00
if(isUsingTool(0) && distance_to_line(_mx, _my, _dx0, _dy0, _dx1, _dy1) < 6)
2023-01-25 06:49:00 +01:00
_hover = i + 0.5;
}
draw_set_color(COLORS._main_accent);
draw_set_text(f_p1, fa_center, fa_bottom);
for( var i = 0; i < len; i++ ) {
2023-04-10 20:02:59 +02:00
var _px = mesh[i][0];
var _py = mesh[i][1];
2023-01-25 06:49:00 +01:00
var _dx = _x + _px * _s;
var _dy = _y + _py * _s;
//draw_text(_dx, _dy - 8, i);
2023-03-11 01:40:17 +01:00
if(isNotUsingTool())
2023-06-17 14:30:49 +02:00
draw_circle_prec(_dx, _dy, 4, false)
2023-03-11 01:40:17 +01:00
else {
2023-04-08 20:06:27 +02:00
draw_sprite_colored(THEME.anchor_selector, hover == i, _dx, _dy);
2023-03-11 01:40:17 +01:00
if(point_distance(_mx, _my, _dx, _dy) < 8)
_hover = i;
}
2023-01-25 06:49:00 +01:00
}
hover = _hover;
if(anchor_dragging > -1) {
var dx = anchor_drag_sx + (_mx - anchor_drag_mx) / _s;
var dy = anchor_drag_sy + (_my - anchor_drag_my) / _s;
dx = value_snap(dx, _snx);
dy = value_snap(dy, _sny);
2023-04-10 20:02:59 +02:00
mesh[anchor_dragging][0] = dx;
mesh[anchor_dragging][1] = dy;
2023-01-25 06:49:00 +01:00
if(mouse_release(mb_left))
anchor_dragging = -1;
2023-10-09 07:36:20 +02:00
return active;
2023-01-25 06:49:00 +01:00
}
2023-10-09 07:36:20 +02:00
if(hover == -1) return active;
2023-01-25 06:49:00 +01:00
if(frac(hover) == 0) {
if(mouse_click(mb_left, active)) {
2023-03-11 01:40:17 +01:00
if(isUsingTool(0)) {
2023-01-25 06:49:00 +01:00
anchor_dragging = hover;
2023-04-10 20:02:59 +02:00
anchor_drag_sx = mesh[hover][0];
anchor_drag_sy = mesh[hover][1];
2023-01-25 06:49:00 +01:00
anchor_drag_mx = _mx;
anchor_drag_my = _my;
2023-03-11 01:40:17 +01:00
} else if(isUsingTool(1)) {
2023-04-10 20:02:59 +02:00
if(array_length(mesh) > 3)
array_delete(mesh, hover, 1);
2023-01-25 06:49:00 +01:00
}
}
} else {
if(mouse_click(mb_left, active)) {
var ind = ceil(hover);
ds_list_insert(lx, ind, (_mx - _x) / _s);
ds_list_insert(ly, ind, (_my - _y) / _s);
anchor_dragging = ind;
2023-04-10 20:02:59 +02:00
anchor_drag_sx = mesh[ind][0];
anchor_drag_sy = mesh[ind][1];
2023-01-25 06:49:00 +01:00
anchor_drag_mx = _mx;
anchor_drag_my = _my;
}
}
2023-10-09 07:36:20 +02:00
2024-03-23 07:26:11 +01:00
var a = inputs[| 7].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active &= !a;
2023-10-09 07:36:20 +02:00
return active;
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static generateMesh = function(index = 0) { #region
var _tex = getInputData(6);
var _exp = getInputData(10);
2023-10-09 07:36:20 +02:00
var _pix = getInputData(11);
2023-10-07 09:09:18 +02:00
2024-03-31 05:36:11 +02:00
if(is_array(_tex)) _tex = array_safe_get_fast(_tex, index);
2023-10-07 09:09:18 +02:00
if(is_instanceof(_tex, SurfaceAtlas))
_tex = _tex.getSurface();
2023-01-25 06:49:00 +01:00
if(!is_surface(_tex)) return;
2023-06-13 14:42:06 +02:00
var meshes = attributes.mesh;
2023-04-10 20:02:59 +02:00
var mesh = [];
2023-01-25 06:49:00 +01:00
2023-09-08 21:37:36 +02:00
var ww = surface_get_width_safe(_tex);
var hh = surface_get_height_safe(_tex);
2023-01-25 06:49:00 +01:00
var surface_buffer = buffer_create(ww * hh * 4, buffer_fixed, 2);
buffer_get_surface(surface_buffer, _tex, 0);
buffer_seek(surface_buffer, buffer_seek_start, 0);
var cmX = 0;
var cmY = 0;
var cmA = 0;
for( var j = 0; j < hh; j++ )
for( var i = 0; i < ww; i++ ) {
var cc = buffer_read(surface_buffer, buffer_u32);
var _a = (cc & (0b11111111 << 24)) >> 24;
if(_a > 0) {
cmX += i;
cmY += j;
cmA++;
}
}
2023-10-07 09:09:18 +02:00
if(cmA == 0) return;
2023-01-25 06:49:00 +01:00
cmX /= cmA;
cmY /= cmA;
var uni_com = shader_get_uniform(sh_mesh_generation, "com");
var uni_dim = shader_get_uniform(sh_mesh_generation, "dimension");
2023-02-14 05:32:32 +01:00
var temp = surface_create_valid(ww, hh);
2023-01-25 06:49:00 +01:00
surface_set_target(temp);
2023-03-19 09:17:39 +01:00
DRAW_CLEAR
2023-01-25 06:49:00 +01:00
shader_set(sh_mesh_generation);
shader_set_uniform_f(uni_dim, ww, hh);
shader_set_uniform_f(uni_com, cmX, cmY);
2023-03-19 09:17:39 +01:00
draw_surface_safe(_tex, 0, 0);
2023-01-25 06:49:00 +01:00
shader_reset();
surface_reset_target();
buffer_get_surface(surface_buffer, temp, 0);
buffer_seek(surface_buffer, buffer_seek_start, 0);
var _pm = ds_map_create();
for( var j = 0; j < hh; j++ )
for( var i = 0; i < ww; i++ ) {
var cc = buffer_read(surface_buffer, buffer_u32);
var _a = (cc & (0b11111111 << 24)) >> 24;
2023-10-09 07:36:20 +02:00
if(_a > 0) _pm[? point_direction_positive(cmX, cmY, i, j)] = [ i, j ];
2023-01-25 06:49:00 +01:00
}
if(ds_map_size(_pm)) {
var keys = ds_map_keys_to_array(_pm);
array_sort(keys, false);
2023-10-07 09:09:18 +02:00
2023-10-09 07:36:20 +02:00
var _minx = ww, _maxx = 0;
var _miny = hh, _maxy = 0;
2023-10-07 09:09:18 +02:00
2023-10-09 07:36:20 +02:00
for( var i = 0, n = array_length(keys); i < n; i++ ) {
2023-01-25 06:49:00 +01:00
var px = _pm[? keys[i]][0];
var py = _pm[? keys[i]][1];
2023-10-09 07:36:20 +02:00
_minx = min(_minx, px + 0.5);
_maxx = max(_maxx, px + 0.5);
_miny = min(_miny, py + 0.5);
_maxy = max(_maxy, py + 0.5);
2023-01-25 06:49:00 +01:00
if(px > cmX) px++;
if(py > cmY) py++;
if(_exp != 0) {
2023-10-09 07:36:20 +02:00
var dist = max(0.5, point_distance(cmX, cmY, px, py) + _exp);
2023-01-25 06:49:00 +01:00
var dirr = point_direction(cmX, cmY, px, py);
px = cmX + lengthdir_x(dist, dirr);
py = cmY + lengthdir_y(dist, dirr);
}
2023-04-10 20:02:59 +02:00
array_push(mesh, [ px, py ]);
2023-01-25 06:49:00 +01:00
}
2023-04-10 20:02:59 +02:00
mesh = removeColinear(mesh);
mesh = removeConcave(mesh);
2023-10-09 07:36:20 +02:00
2023-01-25 06:49:00 +01:00
var _sm = ds_map_create();
2023-10-09 07:36:20 +02:00
if(array_length(mesh)) {
for( var i = 0, n = array_length(mesh); i < n; i++ )
_sm[? point_direction_positive(cmX, cmY, mesh[i][0], mesh[i][1])] = [ mesh[i][0], mesh[i][1] ];
}
2023-01-25 06:49:00 +01:00
var keys = ds_map_keys_to_array(_sm);
2023-04-10 20:02:59 +02:00
mesh = [];
2023-01-25 06:49:00 +01:00
if(array_length(keys)) {
array_sort(keys, false);
2023-07-25 20:12:40 +02:00
for( var i = 0, n = array_length(keys); i < n; i++ ) {
2023-04-10 20:02:59 +02:00
var k = keys[i];
array_push( mesh, [_sm[? k][0], _sm[? k][1]] );
2023-01-25 06:49:00 +01:00
}
}
2023-10-09 07:36:20 +02:00
2023-01-25 06:49:00 +01:00
ds_map_destroy(_sm);
}
2023-10-09 07:36:20 +02:00
if(_pix && array_empty(mesh)) {
mesh = [
[ _minx - 0.5, _minx - 0.5 ],
[ _maxx + 0.5, _minx - 0.5 ],
[ _maxx + 0.5, _maxy + 0.5 ],
[ _minx - 0.5, _maxy + 0.5 ],
];
}
2023-01-25 06:49:00 +01:00
ds_map_destroy(_pm);
surface_free(temp);
buffer_delete(surface_buffer);
2023-04-10 20:02:59 +02:00
meshes[index] = mesh;
2023-06-13 14:42:06 +02:00
attributes.mesh = meshes;
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static removeColinear = function(mesh) { #region
2023-04-10 20:02:59 +02:00
var len = array_length(mesh), _side = 0;
2023-01-25 06:49:00 +01:00
var remSt = [];
var tolerance = 5;
for( var i = 0; i < len; i++ ) {
2023-04-10 20:02:59 +02:00
var _px0 = mesh[safe_mod(i + 0, len)][0];
var _py0 = mesh[safe_mod(i + 0, len)][1];
var _px1 = mesh[safe_mod(i + 1, len)][0];
var _py1 = mesh[safe_mod(i + 1, len)][1];
var _px2 = mesh[safe_mod(i + 2, len)][0];
var _py2 = mesh[safe_mod(i + 2, len)][1];
2023-01-25 06:49:00 +01:00
var dir0 = point_direction(_px0, _py0, _px1, _py1);
var dir1 = point_direction(_px1, _py1, _px2, _py2);
if(abs(dir0 - dir1) <= tolerance)
array_push(remSt, safe_mod(i + 1, len));
}
array_sort(remSt, false);
2023-07-25 20:12:40 +02:00
for( var i = 0, n = array_length(remSt); i < n; i++ ) {
2023-01-25 06:49:00 +01:00
var ind = remSt[i];
2023-04-10 20:02:59 +02:00
array_delete(mesh, ind, 1);
2023-01-25 06:49:00 +01:00
}
2023-04-10 20:02:59 +02:00
return mesh;
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static removeConcave = function(mesh) { #region
2023-04-10 20:02:59 +02:00
var len = array_length(mesh);
2023-01-25 06:49:00 +01:00
if(len <= 3) return;
var startIndex = 0;
var maxx = 0;
for( var i = 0; i < len; i++ ) {
2023-04-10 20:02:59 +02:00
var _px0 = mesh[i][0];
2023-01-25 06:49:00 +01:00
if(_px0 > maxx) {
maxx = _px0;
startIndex = i;
}
}
var remSt = [];
var chkSt = ds_stack_create();
ds_stack_push(chkSt, startIndex);
ds_stack_push(chkSt, safe_mod(startIndex + 1, len));
var anchorTest = safe_mod(startIndex + 2, len)
var log = false;
var _side = 1;
printIf(log, "Start " + string(startIndex))
while(true) {
var potentialPoint = ds_stack_pop(chkSt);
var anchorPoint = ds_stack_top(chkSt);
printIf(log, "Checking " + string(potentialPoint) + " Against " + string(anchorPoint) + " Test " + string(anchorTest))
if(potentialPoint == startIndex) break;
2023-04-10 20:02:59 +02:00
var _px0 = mesh[anchorPoint][0];
var _py0 = mesh[anchorPoint][1];
var _px1 = mesh[potentialPoint][0];
var _py1 = mesh[potentialPoint][1];
var _px2 = mesh[anchorTest][0];
var _py2 = mesh[anchorTest][1];
2023-01-25 06:49:00 +01:00
var side = sign(cross_product(_px0, _py0, _px1, _py1, _px2, _py2));
if(_side == 0 || _side == side) {
ds_stack_push(chkSt, potentialPoint);
ds_stack_push(chkSt, anchorTest);
anchorTest = safe_mod(anchorTest + 1, len);
_side = side;
} else {
if(ds_stack_size(chkSt) == 1) {
ds_stack_push(chkSt, anchorTest);
anchorTest = safe_mod(anchorTest + 1, len);
}
array_push(remSt, potentialPoint);
printIf(log, " > Remove " + string(potentialPoint));
}
}
array_sort(remSt, false);
2023-07-25 20:12:40 +02:00
for( var i = 0, n = array_length(remSt); i < n; i++ ) {
2023-01-25 06:49:00 +01:00
var ind = remSt[i];
2023-04-10 20:02:59 +02:00
array_delete(mesh, ind, 1);
2023-01-25 06:49:00 +01:00
}
2023-04-10 20:02:59 +02:00
return mesh;
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static fixtureCreate = function(fixture, object, dx = 0, dy = 0) { #region
2023-12-18 13:54:33 +01:00
var _mov = getInputData(0);
var _den = getInputData(1);
var _cnt_frc = getInputData(2);
var _air_frc = getInputData(3);
var _rot_frc = getInputData(4);
var collIndex = getInputData(12);
2023-01-25 06:49:00 +01:00
if(!_mov) {
physics_fixture_set_kinematic(fixture);
_den = 0;
}
physics_fixture_set_density(fixture, _den);
physics_fixture_set_friction(fixture, _cnt_frc);
physics_fixture_set_linear_damping(fixture, _air_frc);
physics_fixture_set_angular_damping(fixture, _rot_frc);
physics_fixture_set_awake(fixture, true);
2023-12-18 13:54:33 +01:00
physics_fixture_set_collision_group(fixture, collIndex);
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
array_push(object.fixture, physics_fixture_bind_ext(fixture, object, dx, dy));
2023-01-25 06:49:00 +01:00
physics_fixture_delete(fixture);
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static spawn = function(index = 0, object = noone) { #region
2023-10-07 09:09:18 +02:00
var _shp = getInputData(5);
var _tex = getInputData(6);
var _spos = getInputData(7);
2023-01-25 06:49:00 +01:00
2023-10-07 09:09:18 +02:00
if(is_array(_tex)) {
index = safe_mod(index, array_length(_tex));
2024-03-31 05:36:11 +02:00
_tex = array_safe_get_fast(_tex, index);
2023-10-07 09:09:18 +02:00
}
2023-01-25 06:49:00 +01:00
2023-10-07 09:09:18 +02:00
var ww = surface_get_width_safe(_tex);
var hh = surface_get_height_safe(_tex);
2023-10-06 11:51:11 +02:00
var sw = ww, sh = hh;
var ox = _spos[0];
var oy = _spos[1];
2023-01-25 06:49:00 +01:00
2023-10-07 09:09:18 +02:00
if(is_instanceof(_tex, SurfaceAtlas)) {
ox += _tex.x;
oy += _tex.y;
2023-10-06 11:51:11 +02:00
sw = 0;
sh = 0;
2023-10-07 09:09:18 +02:00
_tex = _tex.getSurface();
2023-10-06 11:51:11 +02:00
}
2023-01-25 06:49:00 +01:00
if(object == noone) {
2023-10-06 11:51:11 +02:00
object = instance_create_depth(ox - sw / 2, oy - sh / 2, 0, oRigidbody);
2023-01-25 06:49:00 +01:00
object.surface = _tex;
2024-03-22 11:15:22 +01:00
2023-01-25 06:49:00 +01:00
} else if(instance_exists(object)) {
2023-07-25 20:12:40 +02:00
for( var i = 0, n = array_length(object.fixture); i < n; i++ )
2023-01-25 06:49:00 +01:00
physics_remove_fixture(object, object.fixture[i]);
object.fixture = [];
2024-03-22 11:15:22 +01:00
2023-01-25 06:49:00 +01:00
} else
2023-04-14 12:23:25 +02:00
return noone;
2023-01-25 06:49:00 +01:00
if(_shp == 0) {
var fixture = physics_fixture_create();
2023-10-06 11:51:11 +02:00
physics_fixture_set_box_shape(fixture, ww / 2, hh / 2);
fixtureCreate(fixture, object, ww / 2, hh / 2);
2024-03-22 11:15:22 +01:00
object.type = RIGID_SHAPE.box;
object.width = ww;
object.height = hh;
2023-01-25 06:49:00 +01:00
} else if(_shp == 1) {
var fixture = physics_fixture_create();
2023-10-06 11:51:11 +02:00
var rr = min(ww, hh) / 2;
physics_fixture_set_circle_shape(fixture, rr);
fixtureCreate(fixture, object, rr, rr);
2024-03-22 11:15:22 +01:00
object.type = RIGID_SHAPE.circle;
object.radius = rr;
2023-01-25 06:49:00 +01:00
} else if(_shp == 2) {
2023-06-13 14:42:06 +02:00
var meshes = attributes.mesh;
2024-03-31 05:36:11 +02:00
if(array_safe_get_fast(meshes, index, noone) == noone)
2023-04-14 12:23:25 +02:00
return noone;
var mesh = meshes[index];
2023-04-10 20:02:59 +02:00
var cx = 0, cy = 0;
var cmx = 0, cmy = 0;
2023-01-25 06:49:00 +01:00
2023-04-10 20:02:59 +02:00
var len = array_length(mesh), _side = 0;
2023-01-25 06:49:00 +01:00
is_convex = true;
for( var i = 0; i < len; i++ ) {
2023-04-10 20:02:59 +02:00
var _px0 = mesh[safe_mod(i + 0, len)][0];
var _py0 = mesh[safe_mod(i + 0, len)][1];
var _px1 = mesh[safe_mod(i + 1, len)][0];
var _py1 = mesh[safe_mod(i + 1, len)][1];
var _px2 = mesh[safe_mod(i + 2, len)][0];
var _py2 = mesh[safe_mod(i + 2, len)][1];
2023-01-25 06:49:00 +01:00
var side = cross_product(_px0, _py0, _px1, _py1, _px2, _py2);
if(_side != 0 && sign(_side) != sign(side))
is_convex = false;
_side = side;
cx += _px0;
cy += _py0;
}
cx /= len;
cy /= len;
if(!is_convex) return object;
2023-10-06 11:51:11 +02:00
if(len < 3) return object;
2023-01-25 06:49:00 +01:00
if(len <= 8) {
var fixture = physics_fixture_create();
physics_fixture_set_polygon_shape(fixture);
for( var i = 0; i < len; i++ ) {
2023-04-10 20:02:59 +02:00
var _px0 = mesh[i][0];
var _py0 = mesh[i][1];
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
physics_fixture_add_point(fixture, _px0, _py0);
2023-01-25 06:49:00 +01:00
}
2023-10-06 11:51:11 +02:00
fixtureCreate(fixture, object, -1, -1);
2023-01-25 06:49:00 +01:00
} else {
for( var i = 0; i < len; i++ ) {
var fixture = physics_fixture_create();
physics_fixture_set_polygon_shape(fixture);
2023-04-10 20:02:59 +02:00
var _px0 = mesh[safe_mod(i + 0, len)][0];
var _py0 = mesh[safe_mod(i + 0, len)][1];
var _px1 = mesh[safe_mod(i + 1, len)][0];
var _py1 = mesh[safe_mod(i + 1, len)][1];
2023-01-25 06:49:00 +01:00
physics_fixture_add_point(fixture, cx, cy);
physics_fixture_add_point(fixture, _px0, _py0);
physics_fixture_add_point(fixture, _px1, _py1);
2023-10-06 11:51:11 +02:00
fixtureCreate(fixture, object, -1, -1);
2023-01-25 06:49:00 +01:00
}
}
2024-03-22 11:15:22 +01:00
object.type = RIGID_SHAPE.mesh;
2023-01-25 06:49:00 +01:00
}
return object;
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-09 16:07:33 +02:00
static update = function(frame = CURRENT_FRAME) { #region
2024-01-19 09:33:37 +01:00
if(IS_FIRST_FRAME) reset();
2024-03-22 11:15:22 +01:00
outputs[| 0].setValue(object);
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static step = function() { #region
var _shp = getInputData(5);
2023-10-06 11:51:11 +02:00
2023-10-08 04:14:35 +02:00
inputs[| 9].setVisible(_shp == 2);
inputs[| 10].setVisible(_shp == 2);
2023-10-09 07:36:20 +02:00
inputs[| 11].setVisible(_shp == 2);
2023-01-25 06:49:00 +01:00
2023-12-19 14:30:34 +01:00
tools = _shp == 2? mesh_tools : -1;
var _tex = getInputData(6);
2023-01-25 06:49:00 +01:00
if(is_array(_tex)) {
2023-06-13 14:42:06 +02:00
var meshes = attributes.mesh;
2023-04-10 20:02:59 +02:00
for( var i = array_length(meshes); i < array_length(_tex); i++ )
newMesh(i);
2023-01-25 06:49:00 +01:00
}
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static reset = function() { #region
2023-10-07 09:09:18 +02:00
var _tex = getInputData(6);
2023-10-06 11:51:11 +02:00
2023-07-25 20:12:40 +02:00
for( var i = 0, n = array_length(object); i < n; i++ ) {
2023-01-25 06:49:00 +01:00
if(instance_exists(object[i]))
instance_destroy(object[i]);
}
object = [];
var _spwn = getInputData(8);
2023-04-04 09:49:33 +02:00
if(!_spwn) return;
2023-01-25 06:49:00 +01:00
if(is_array(_tex)) {
2023-07-25 20:12:40 +02:00
for( var i = 0, n = array_length(_tex); i < n; i++ )
2023-10-06 11:51:11 +02:00
object[i] = spawn(i);
2023-01-25 06:49:00 +01:00
} else
object = [ spawn() ];
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
2023-11-27 11:40:28 +01:00
if(!previewable) return;
2023-01-25 06:49:00 +01:00
var bbox = drawGetBbox(xx, yy, _s);
2023-10-07 09:09:18 +02:00
var _tex = getInputData(6);
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
if(is_array(_tex)) {
if(array_empty(_tex)) return;
_tex = _tex[0];
}
2023-11-27 11:40:28 +01:00
var aa = 0.5 + 0.5 * renderActive;
if(!isHighlightingInGraph()) aa *= 0.25;
draw_surface_bbox(_tex, bbox,, aa);
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static attributeSerialize = function() { #region
2023-06-13 14:42:06 +02:00
var att = {};
2023-04-10 20:02:59 +02:00
2023-06-13 14:42:06 +02:00
var mesh = struct_try_get(attributes, "mesh", []);
att.mesh = json_stringify(mesh);
2023-01-25 06:49:00 +01:00
return att;
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
static attributeDeserialize = function(attr) { #region
struct_append(attributes, attr);
2023-06-13 14:42:06 +02:00
if(struct_has(attr, "mesh"))
attributes.mesh = json_parse(attr.mesh);
2023-10-06 11:51:11 +02:00
} #endregion
2023-01-25 06:49:00 +01:00
}