diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index 5c2008e05..a7005d815 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -198,6 +198,7 @@ {"name":"discordBridge","order":11,"path":"extensions/discordBridge/discordBridge.yy",}, {"name":"display_measure","order":1,"path":"extensions/display_measure/display_measure.yy",}, {"name":"display_screenshot","order":4,"path":"extensions/display_screenshot/display_screenshot.yy",}, + {"name":"dllTest","order":19,"path":"extensions/dllTest/dllTest.yy",}, {"name":"file_dropper","order":6,"path":"extensions/file_dropper/file_dropper.yy",}, {"name":"FLIP","order":17,"path":"extensions/FLIP/FLIP.yy",}, {"name":"gameframe_native","order":2,"path":"extensions/gameframe_native/gameframe_native.yy",}, @@ -446,6 +447,7 @@ {"name":"d3d_material","order":4,"path":"scripts/d3d_material/d3d_material.yy",}, {"name":"d3d_object_instancer","order":5,"path":"scripts/d3d_object_instancer/d3d_object_instancer.yy",}, {"name":"d3d_object","order":1,"path":"scripts/d3d_object/d3d_object.yy",}, + {"name":"d3d_path_extrude","order":10,"path":"scripts/d3d_path_extrude/d3d_path_extrude.yy",}, {"name":"d3d_plane_mesh","order":6,"path":"scripts/d3d_plane_mesh/d3d_plane_mesh.yy",}, {"name":"d3d_plane","order":2,"path":"scripts/d3d_plane/d3d_plane.yy",}, {"name":"d3d_ray","order":9,"path":"scripts/d3d_ray/d3d_ray.yy",}, @@ -641,6 +643,7 @@ {"name":"node_3d_mesh_export","order":14,"path":"scripts/node_3d_mesh_export/node_3d_mesh_export.yy",}, {"name":"node_3d_mesh_extrude","order":8,"path":"scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.yy",}, {"name":"node_3d_mesh_obj","order":2,"path":"scripts/node_3d_mesh_obj/node_3d_mesh_obj.yy",}, + {"name":"node_3d_mesh_path_extrude","order":10,"path":"scripts/node_3d_mesh_path_extrude/node_3d_mesh_path_extrude.yy",}, {"name":"node_3d_mesh_plane","order":7,"path":"scripts/node_3d_mesh_plane/node_3d_mesh_plane.yy",}, {"name":"node_3d_mesh_sphere_ico","order":5,"path":"scripts/node_3d_mesh_sphere_ico/node_3d_mesh_sphere_ico.yy",}, {"name":"node_3d_mesh_sphere_uv","order":4,"path":"scripts/node_3d_mesh_sphere_uv/node_3d_mesh_sphere_uv.yy",}, @@ -759,6 +762,7 @@ {"name":"node_display_image","order":4,"path":"scripts/node_display_image/node_display_image.yy",}, {"name":"node_display_text","order":3,"path":"scripts/node_display_text/node_display_text.yy",}, {"name":"node_dither","order":6,"path":"scripts/node_dither/node_dither.yy",}, + {"name":"node_dll","order":28,"path":"scripts/node_dll/node_dll.yy",}, {"name":"node_dust","order":3,"path":"scripts/node_dust/node_dust.yy",}, {"name":"node_dynasurf_in","order":4,"path":"scripts/node_dynasurf_in/node_dynasurf_in.yy",}, {"name":"node_dynasurf_out_height","order":3,"path":"scripts/node_dynasurf_out_height/node_dynasurf_out_height.yy",}, @@ -912,6 +916,7 @@ {"name":"node_palette_sort","order":9,"path":"scripts/node_palette_sort/node_palette_sort.yy",}, {"name":"node_palette","order":4,"path":"scripts/node_palette/node_palette.yy",}, {"name":"node_particle","order":11,"path":"scripts/node_particle/node_particle.yy",}, + {"name":"node_path_3d","order":20,"path":"scripts/node_path_3d/node_path_3d.yy",}, {"name":"node_path_anchor","order":13,"path":"scripts/node_path_anchor/node_path_anchor.yy",}, {"name":"node_path_array","order":11,"path":"scripts/node_path_array/node_path_array.yy",}, {"name":"node_path_bake","order":15,"path":"scripts/node_path_bake/node_path_bake.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index 94c3af5fd..37ce83fde 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -388,6 +388,7 @@ "CopyToMask":"0", }, },"CopyToMask":0,"filePath":"datafiles","name":"dllcredits.txt","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"dlltest1.dll","CopyToMask":-1,"filePath":"datafiles","name":"dlltest1.dll","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"ffmpeg.exe","CopyToMask":-1,"filePath":"datafiles/ffmpeg/bin","name":"ffmpeg.exe","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"LICENSE","CopyToMask":-1,"filePath":"datafiles/ffmpeg","name":"LICENSE","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"README.txt","CopyToMask":-1,"filePath":"datafiles/ffmpeg","name":"README.txt","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, @@ -496,6 +497,7 @@ {"id":{"name":"discordBridge","path":"extensions/discordBridge/discordBridge.yy",},}, {"id":{"name":"display_measure","path":"extensions/display_measure/display_measure.yy",},}, {"id":{"name":"display_screenshot","path":"extensions/display_screenshot/display_screenshot.yy",},}, + {"id":{"name":"dllTest","path":"extensions/dllTest/dllTest.yy",},}, {"id":{"name":"file_dropper","path":"extensions/file_dropper/file_dropper.yy",},}, {"id":{"name":"FileDropper","path":"extensions/FileDropper/FileDropper.yy",},}, {"id":{"name":"FirebaseSetup","path":"extensions/FirebaseSetup/FirebaseSetup.yy",},}, @@ -795,6 +797,7 @@ {"id":{"name":"d3d_material","path":"scripts/d3d_material/d3d_material.yy",},}, {"id":{"name":"d3d_object_instancer","path":"scripts/d3d_object_instancer/d3d_object_instancer.yy",},}, {"id":{"name":"d3d_object","path":"scripts/d3d_object/d3d_object.yy",},}, + {"id":{"name":"d3d_path_extrude","path":"scripts/d3d_path_extrude/d3d_path_extrude.yy",},}, {"id":{"name":"d3d_plane_mesh","path":"scripts/d3d_plane_mesh/d3d_plane_mesh.yy",},}, {"id":{"name":"d3d_plane","path":"scripts/d3d_plane/d3d_plane.yy",},}, {"id":{"name":"d3d_ray","path":"scripts/d3d_ray/d3d_ray.yy",},}, @@ -1021,6 +1024,7 @@ {"id":{"name":"node_3d_mesh_export","path":"scripts/node_3d_mesh_export/node_3d_mesh_export.yy",},}, {"id":{"name":"node_3d_mesh_extrude","path":"scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.yy",},}, {"id":{"name":"node_3d_mesh_obj","path":"scripts/node_3d_mesh_obj/node_3d_mesh_obj.yy",},}, + {"id":{"name":"node_3d_mesh_path_extrude","path":"scripts/node_3d_mesh_path_extrude/node_3d_mesh_path_extrude.yy",},}, {"id":{"name":"node_3d_mesh_plane","path":"scripts/node_3d_mesh_plane/node_3d_mesh_plane.yy",},}, {"id":{"name":"node_3d_mesh_sphere_ico","path":"scripts/node_3d_mesh_sphere_ico/node_3d_mesh_sphere_ico.yy",},}, {"id":{"name":"node_3d_mesh_sphere_uv","path":"scripts/node_3d_mesh_sphere_uv/node_3d_mesh_sphere_uv.yy",},}, @@ -1159,6 +1163,7 @@ {"id":{"name":"node_display_image","path":"scripts/node_display_image/node_display_image.yy",},}, {"id":{"name":"node_display_text","path":"scripts/node_display_text/node_display_text.yy",},}, {"id":{"name":"node_dither","path":"scripts/node_dither/node_dither.yy",},}, + {"id":{"name":"node_dll","path":"scripts/node_dll/node_dll.yy",},}, {"id":{"name":"node_dust","path":"scripts/node_dust/node_dust.yy",},}, {"id":{"name":"node_dynasurf_in","path":"scripts/node_dynasurf_in/node_dynasurf_in.yy",},}, {"id":{"name":"node_dynasurf_out_height","path":"scripts/node_dynasurf_out_height/node_dynasurf_out_height.yy",},}, @@ -1331,6 +1336,7 @@ {"id":{"name":"node_palette_sort","path":"scripts/node_palette_sort/node_palette_sort.yy",},}, {"id":{"name":"node_palette","path":"scripts/node_palette/node_palette.yy",},}, {"id":{"name":"node_particle","path":"scripts/node_particle/node_particle.yy",},}, + {"id":{"name":"node_path_3d","path":"scripts/node_path_3d/node_path_3d.yy",},}, {"id":{"name":"node_path_anchor","path":"scripts/node_path_anchor/node_path_anchor.yy",},}, {"id":{"name":"node_path_array","path":"scripts/node_path_array/node_path_array.yy",},}, {"id":{"name":"node_path_bake","path":"scripts/node_path_bake/node_path_bake.yy",},}, diff --git a/datafiles/dlltest1.dll b/datafiles/dlltest1.dll new file mode 100644 index 000000000..cb5c42e20 Binary files /dev/null and b/datafiles/dlltest1.dll differ diff --git a/scripts/__bbox/__bbox.gml b/scripts/__bbox/__bbox.gml index ec55c2124..e05f414bd 100644 --- a/scripts/__bbox/__bbox.gml +++ b/scripts/__bbox/__bbox.gml @@ -30,6 +30,42 @@ function BoundingBox(minx = noone, miny = noone, maxx = noone, maxy = noone) con static clone = function() { return new BoundingBox(minx, miny, maxx, maxy); } } +function BoundingBox3D(minx = noone, miny = noone, minz = noone, maxx = noone, maxy = noone, maxz = noone) : BoundingBox(minx, miny, maxx, maxy) constructor { + self.minz = minz; + self.maxz = maxz; + + depth = maxz - minz; + + static addPoint = function(px, py, pz) { + minx = minx == noone? px : min(minx, px); + miny = miny == noone? py : min(miny, py); + minz = minz == noone? pz : min(minz, pz); + + maxx = maxx == noone? px : max(maxx, px); + maxy = maxy == noone? py : max(maxy, py); + maxz = maxz == noone? pz : max(maxz, pz); + + width = maxx - minx; + height = maxy - miny; + depth = maxz - minz; + } + + static lerpTo = function(bbox, rat) { + var b = new BoundingBox3D( + lerp( minx, bbox.minx, rat ), + lerp( miny, bbox.miny, rat ), + lerp( minz, bbox.minz, rat ), + + lerp( maxx, bbox.maxx, rat ), + lerp( maxy, bbox.maxy, rat ), + lerp( maxz, bbox.maxz, rat ), + ); + return b; + } + + static clone = function() { return new BoundingBox3D(minx, miny, minz, maxx, maxy, maxz); } +} + function BBOX() { return new __BBOX(); } function __BBOX() constructor { x0 = 0; x1 = 0; diff --git a/scripts/__node_3d_object/__node_3d_object.gml b/scripts/__node_3d_object/__node_3d_object.gml index 1916260d3..9e5113238 100644 --- a/scripts/__node_3d_object/__node_3d_object.gml +++ b/scripts/__node_3d_object/__node_3d_object.gml @@ -80,13 +80,13 @@ function Node_3D_Object(_x, _y, _group = noone) : Node_3D(_x, _y, _group) constr var _camera = params.camera; var _qview = new BBMOD_Quaternion().FromEuler(_camera.focus_angle_y, -_camera.focus_angle_x, 0); - + var _axis = tool_attribute.context; var _hover = noone; var _hoverDist = 10; var th; - + var _posView = _camera.worldPointToViewPoint(_vpos); var cx = _posView.x; @@ -244,8 +244,7 @@ function Node_3D_Object(_x, _y, _group = noone) : Node_3D(_x, _y, _group) constr case 5 : nor = new __vec3(0, 1, 0); break; } - if(_axis == 0) - nor = _qrot.Rotate(nor); + if(_axis == 0) nor = _qrot.Rotate(nor); var pln = new __plane(drag_original, nor); mAdj = d3d_intersect_ray_plane(ray, pln); diff --git a/scripts/buffer_functions/buffer_functions.gml b/scripts/buffer_functions/buffer_functions.gml index c1314523b..c13939bb8 100644 --- a/scripts/buffer_functions/buffer_functions.gml +++ b/scripts/buffer_functions/buffer_functions.gml @@ -23,6 +23,21 @@ function buffer_get_string(buffer, text = true, limit = 400) { #region return ss; } #endregion +function buffer_to_string(buffer) { #region + if(!buffer_exists(buffer)) return ""; + + buffer_seek(buffer, buffer_seek_start, 0); + var len = buffer_get_size(buffer); + var ss = ""; + + repeat(len) { + var _r = buffer_read(buffer, buffer_u8); + ss += chr(_r); + } + + return ss; +} #endregion + function buffer_from_string(str) { #region var _b = buffer_create(string_length(str) * 1, buffer_fast, 1); for( var i = 1; i <= string_length(str); i++ ) diff --git a/scripts/control_function/control_function.gml b/scripts/control_function/control_function.gml index a55068da6..072f2354e 100644 --- a/scripts/control_function/control_function.gml +++ b/scripts/control_function/control_function.gml @@ -40,6 +40,8 @@ return CTRL == KEYBOARD_STATUS.pressing || ALT == KEYBOARD_STATUS.pressing || SHIFT == KEYBOARD_STATUS.pressing; } + function key_mod_down(key) { INLINE return key == KEYBOARD_STATUS.down; } + function key_mod_press(key) { INLINE return key == KEYBOARD_STATUS.pressing; } function key_mod_presses(keys) { INLINE diff --git a/scripts/d3d_path_extrude/d3d_path_extrude.gml b/scripts/d3d_path_extrude/d3d_path_extrude.gml new file mode 100644 index 000000000..37e42fb05 --- /dev/null +++ b/scripts/d3d_path_extrude/d3d_path_extrude.gml @@ -0,0 +1,219 @@ +function __3dPathExtrude(radius = 0.5, sides = 8, smooth = false) : __3dObject() constructor { + VF = global.VF_POS_NORM_TEX_COL; + render_type = pr_trianglelist; + object_counts = 3; + + self.radius = radius; + self.sides = sides; + self.smooth = smooth; + + endCap = true; + points = []; + uvProg = []; + radiusOverPath = []; + uvScale = [ 1, 1 ]; + + static initModel = function() { + var vs = []; + var v0 = []; + var v1 = []; + var o = new __vec3(); + var n = new __vec3(); + var v = new __vec3(); + var u = new __vec3(); + var w = new __vec3(); + var len; + + var prevp = array_create((sides + 1) * 3); + var prevn = array_create((sides + 1) * 3); + var _subd = array_length(points) / 3; + var _ind = 0; + var _in0 = 0; + var _in1 = 0; + + var _u0 = new __vec3(0, 1, 0); + var _u1 = new __vec3(0, 0, 1); + + if(_subd < 2) return; + + o.x = points[0]; + o.y = points[1]; + o.z = points[2]; + + var _us = uvScale[0]; + var _vs = uvScale[1]; + + for(var i = 1; i < _subd; i++) { + n.x = points[i * 3 + 0]; + n.y = points[i * 3 + 1]; + n.z = points[i * 3 + 2]; + + if(i == 1) { + v.x = n.x - o.x; + v.y = n.y - o.y; + v.z = n.z - o.z; + v._normalize(); + + if(v.z == v.z) u = v.cross(_u0); + else u = v.cross(_u1); + + u._normalize(); + w = v.cross(u); + + var _rr = radius * radiusOverPath[0]; + + for(var j = 0; j <= sides; j++) { + var a0 = j / sides * 360; + + var _u = u.multiply(dcos(a0)); + var _w = w.multiply(dsin(a0)); + var _pp = _u.add(_w); + + prevp[j * 3 + 0] = o.x + _pp.x * _rr; + prevp[j * 3 + 1] = o.y + _pp.y * _rr; + prevp[j * 3 + 2] = o.z + _pp.z * _rr; + } + + for(var j = 0; j < sides; j++) { + var cx0 = prevp[j * 3 + 0]; + var cy0 = prevp[j * 3 + 1]; + var cz0 = prevp[j * 3 + 2]; + + var cx1 = prevp[j * 3 + 0 + 3]; + var cy1 = prevp[j * 3 + 1 + 3]; + var cz1 = prevp[j * 3 + 2 + 3]; + + var a0 = (j + 0) / sides * 360; + var a1 = (j + 1) / sides * 360; + + var __u0 = 0.5 + lengthdir_x(0.5, a0); + var __v0 = 0.5 + lengthdir_y(0.5, a0); + var __u1 = 0.5 + lengthdir_x(0.5, a1); + var __v1 = 0.5 + lengthdir_y(0.5, a1); + + v0[_in0++] = new __vertex(o.x, o.y, o.z).setNormal(-v.x, -v.y, -v.z).setUV(0.5, 0.5); + v0[_in0++] = new __vertex(cx0, cy0, cz0).setNormal(-v.x, -v.y, -v.z).setUV(__u0, __v0); + v0[_in0++] = new __vertex(cx1, cy1, cz1).setNormal(-v.x, -v.y, -v.z).setUV(__u1, __v1); + } + } + + if(i) { + if(i < _subd - 1) { + v.x = points[(i + 1) * 3 + 0] - o.x; + v.y = points[(i + 1) * 3 + 1] - o.y; + v.z = points[(i + 1) * 3 + 2] - o.z; + } else { + v.x = n.x - o.x; + v.y = n.y - o.y; + v.z = n.z - o.z; + } + + v._normalize(); + + if(v.z == v.z) u = v.cross(_u0); + else u = v.cross(_u1); + + u._normalize(); + w = v.cross(u); + + var _rr = radius * radiusOverPath[i]; + var __v0 = 1. - uvProg[i-1]; + var __v1 = 1. - uvProg[i ]; + // print($"{i}: {__v0} - {__v1}") + + for(var j = 0; j <= sides; j++) { + var a0 = j / sides * 360; + + var _u = u.multiply(dcos(a0)); + var _w = w.multiply(dsin(a0)); + var _pp = _u.add(_w); + + prevn[j * 3 + 0] = n.x + _pp.x * _rr; + prevn[j * 3 + 1] = n.y + _pp.y * _rr; + prevn[j * 3 + 2] = n.z + _pp.z * _rr; + + if(j) { + var x0 = prevp[(j - 1) * 3 + 0]; + var y0 = prevp[(j - 1) * 3 + 1]; + var z0 = prevp[(j - 1) * 3 + 2]; + + var x1 = prevp[j * 3 + 0]; + var y1 = prevp[j * 3 + 1]; + var z1 = prevp[j * 3 + 2]; + + var x2 = prevn[(j - 1) * 3 + 0]; + var y2 = prevn[(j - 1) * 3 + 1]; + var z2 = prevn[(j - 1) * 3 + 2]; + + var x3 = prevn[j * 3 + 0]; + var y3 = prevn[j * 3 + 1]; + var z3 = prevn[j * 3 + 2]; + + var _n0, _n1, _n2, _n3; + + if(smooth) { + _n0 = new __vec3(x0 - o.x, y0 - o.y, z0 - o.z).normalize(); + _n1 = new __vec3(x1 - o.x, y1 - o.y, z1 - o.z).normalize(); + _n2 = new __vec3(x2 - n.x, y2 - n.y, z2 - n.z).normalize(); + _n3 = new __vec3(x3 - n.x, y3 - n.y, z3 - n.z).normalize(); + + } else { + _n0 = _pp.normalize(); + _n1 = _n0; + _n2 = _n0; + _n3 = _n0; + } + + var __u0 = (j-1) / sides; + var __u1 = (j ) / sides; + + vs[_ind++] = new __vertex(x0, y0, z0).setNormal(_n0.x, _n0.y, _n0.z).setUV(__u0 * _us, __v0 * _vs); + vs[_ind++] = new __vertex(x2, y2, z2).setNormal(_n2.x, _n2.y, _n2.z).setUV(__u0 * _us, __v1 * _vs); + vs[_ind++] = new __vertex(x1, y1, z1).setNormal(_n1.x, _n1.y, _n1.z).setUV(__u1 * _us, __v0 * _vs); + + vs[_ind++] = new __vertex(x1, y1, z1).setNormal(_n1.x, _n1.y, _n1.z).setUV(__u1 * _us, __v0 * _vs); + vs[_ind++] = new __vertex(x2, y2, z2).setNormal(_n2.x, _n2.y, _n2.z).setUV(__u0 * _us, __v1 * _vs); + vs[_ind++] = new __vertex(x3, y3, z3).setNormal(_n3.x, _n3.y, _n3.z).setUV(__u1 * _us, __v1 * _vs); + } + } + + for (var j = 0, m = array_length(prevn); j < m; j++) + prevp[j] = prevn[j]; + } + + if(i == _subd - 1) { + for(var j = 0; j < sides; j++) { + var cx0 = prevp[j * 3 + 0]; + var cy0 = prevp[j * 3 + 1]; + var cz0 = prevp[j * 3 + 2]; + + var cx1 = prevp[j * 3 + 0 + 3]; + var cy1 = prevp[j * 3 + 1 + 3]; + var cz1 = prevp[j * 3 + 2 + 3]; + + var a0 = (j + 0) / sides * 360; + var a1 = (j + 1) / sides * 360; + + var __u0 = 0.5 + lengthdir_x(0.5, a0); + var __v0 = 0.5 + lengthdir_y(0.5, a0); + var __u1 = 0.5 + lengthdir_x(0.5, a1); + var __v1 = 0.5 + lengthdir_y(0.5, a1); + + v1[_in1++] = new __vertex(n.x, n.y, n.z).setNormal(-v.x, -v.y, -v.z).setUV(0.5, 0.5); + v1[_in1++] = new __vertex(cx0, cy0, cz0).setNormal(-v.x, -v.y, -v.z).setUV(__u0, __v0); + v1[_in1++] = new __vertex(cx1, cy1, cz1).setNormal(-v.x, -v.y, -v.z).setUV(__u1, __v1); + } + } + + o.x = n.x; + o.y = n.y; + o.z = n.z; + } + + vertex = endCap? [ vs, v0, v1 ] : [ vs ]; + object_counts = array_length(vertex); + VB = build(); + } initModel(); + + static onParameterUpdate = initModel; +} \ No newline at end of file diff --git a/scripts/d3d_path_extrude/d3d_path_extrude.yy b/scripts/d3d_path_extrude/d3d_path_extrude.yy new file mode 100644 index 000000000..01713dada --- /dev/null +++ b/scripts/d3d_path_extrude/d3d_path_extrude.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"d3d_path_extrude", + "isCompatibility":false, + "isDnD":false, + "name":"d3d_path_extrude", + "parent":{ + "name":"mesh", + "path":"folders/functions/3d/mesh.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/ds_list/ds_list.gml b/scripts/ds_list/ds_list.gml index d81d55ff5..089f6d1a3 100644 --- a/scripts/ds_list/ds_list.gml +++ b/scripts/ds_list/ds_list.gml @@ -65,9 +65,15 @@ function ds_list_remove(list, item) { function ds_list_append(list, _append) { INLINE - for( var i = 0; i < ds_list_size(_append); i++ ) { + for( var i = 0; i < ds_list_size(_append); i++ ) ds_list_add(list, _append[| i]); - } +} + +function ds_list_append_array(list, _append) { + INLINE + + for( var i = 0; i < array_length(_append); i++ ) + ds_list_add(list, _append[i]); } function ds_list_exist(list, item) { diff --git a/scripts/globals/globals.gml b/scripts/globals/globals.gml index 546affd1f..b462d4895 100644 --- a/scripts/globals/globals.gml +++ b/scripts/globals/globals.gml @@ -36,10 +36,10 @@ globalvar VERSION, SAVE_VERSION, VERSION_STRING, BUILD_NUMBER, LATEST_VERSION; LATEST_VERSION = 11700; - VERSION = 11742; + VERSION = 11750; SAVE_VERSION = 11700; - VERSION_STRING = "1.17.5.001"; - BUILD_NUMBER = 11742; + VERSION_STRING = "1.17.5.002"; + BUILD_NUMBER = 11750; globalvar HOTKEYS, HOTKEY_CONTEXT; HOTKEYS = ds_map_create(); diff --git a/scripts/node_3d_mesh_path_extrude/node_3d_mesh_path_extrude.gml b/scripts/node_3d_mesh_path_extrude/node_3d_mesh_path_extrude.gml new file mode 100644 index 000000000..e04f98f61 --- /dev/null +++ b/scripts/node_3d_mesh_path_extrude/node_3d_mesh_path_extrude.gml @@ -0,0 +1,110 @@ +function Node_3D_Mesh_Path_Extrude(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group) constructor { + name = "Path Extrude"; + + object_class = __3dPathExtrude; + + inputs[| in_mesh + 0] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone ) + .setVisible(true, true); + + inputs[| in_mesh + 1] = nodeValue("Side", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 8 ) + .setValidator(VV_min(2)); + + inputs[| in_mesh + 2] = nodeValue("Material Side", self, JUNCTION_CONNECT.input, VALUE_TYPE.d3Material, new __d3dMaterial() ) + .setVisible(true, true); + + inputs[| in_mesh + 3] = nodeValue("Material Cap", self, JUNCTION_CONNECT.input, VALUE_TYPE.d3Material, new __d3dMaterial() ) + .setVisible(true, true); + + inputs[| in_mesh + 4] = nodeValue("Smooth", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ); + + inputs[| in_mesh + 5] = nodeValue("End caps", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true ); + + inputs[| in_mesh + 6] = nodeValue("Subdivision", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 8 ) + .setValidator(VV_min(2)); + + inputs[| in_mesh + 7] = nodeValue("Radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.25 ) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| in_mesh + 8] = nodeValue("Radius Over Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11 ); + + inputs[| in_mesh + 9] = nodeValue("Texture Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ] ) + .setDisplay(VALUE_DISPLAY.vector); + + input_display_list = [ + __d3d_input_list_mesh, in_mesh + 0, in_mesh + 6, in_mesh + 1, in_mesh + 7, in_mesh + 8, in_mesh + 5, + __d3d_input_list_transform, + ["Material", false], in_mesh + 4, in_mesh + 2, in_mesh + 3, in_mesh + 9, + ] + + static step = function() { #region + var _caps = getInputData(in_mesh + 5); + + inputs[| in_mesh + 3].setVisible(_caps, _caps); + } #endregion + + static processData = function(_output, _data, _output_index, _array_index = 0) { #region + var _path = _data[in_mesh + 0]; + var _sides = _data[in_mesh + 1]; + var _mat_sid = _data[in_mesh + 2]; + var _mat_cap = _data[in_mesh + 3]; + var _smt = _data[in_mesh + 4]; + var _caps = _data[in_mesh + 5]; + var _samp = _data[in_mesh + 6]; + var _rad = _data[in_mesh + 7]; + var _radOv = _data[in_mesh + 8]; + var _uvScale = _data[in_mesh + 9]; + + if(_path == noone) return noone; + + var _points = array_create(_samp * 3); + var _radPath = array_create(_samp); + var _uvProg = array_create(_samp); + + var _stp = 1 / (_samp - 1); + var _p = new __vec3(); + var _distTotal = 0; + + for(var i = 0; i < _samp; i++) { + var _prg = _stp * i; + _p = _path.getPointRatio(_prg, 0, _p); + + _points[i * 3 + 0] = _p.x; + _points[i * 3 + 1] = _p.y; + _points[i * 3 + 2] = _p.z; + + _radPath[i] = eval_curve_x(_radOv, _prg); + + if(i) { + var _d = point_distance_3d(_points[i * 3 - 3 + 0], _points[i * 3 - 3 + 1], _points[i * 3 - 3 + 2], + _points[i * 3 + 0], _points[i * 3 + 1], _points[i * 3 + 2]); + _distTotal += _d; + _uvProg[i] = _distTotal; + } + } + + for (var i = 0; i < _samp; i++) + _uvProg[i] /= _distTotal; + _uvProg[_samp] = 1; + + var object = getObject(_array_index); + object.checkParameter({ + sides : _sides, + endCap : _caps, + smooth : _smt, + points : _points, + radius : _rad, + radiusOverPath: _radPath, + + uvProg : _uvProg, + uvScale : _uvScale, + }); + + object.materials = _caps? [ _mat_sid, _mat_cap, _mat_cap ] : [ _mat_sid ]; + + setTransform(object, _data); + + return object; + } #endregion + + static getPreviewValues = function() { return array_safe_get_fast(all_inputs, in_mesh + 2, noone); } +} \ No newline at end of file diff --git a/scripts/node_3d_mesh_path_extrude/node_3d_mesh_path_extrude.yy b/scripts/node_3d_mesh_path_extrude/node_3d_mesh_path_extrude.yy new file mode 100644 index 000000000..7f6792562 --- /dev/null +++ b/scripts/node_3d_mesh_path_extrude/node_3d_mesh_path_extrude.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"node_3d_mesh_path_extrude", + "isCompatibility":false, + "isDnD":false, + "name":"node_3d_mesh_path_extrude", + "parent":{ + "name":"d3d_mesh", + "path":"folders/nodes/data/3D/d3d_mesh.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/node_3d_mesh_path_extrude/node_counter.yy b/scripts/node_3d_mesh_path_extrude/node_counter.yy new file mode 100644 index 000000000..10832a0b0 --- /dev/null +++ b/scripts/node_3d_mesh_path_extrude/node_counter.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "variable", + "path": "folders/nodes/data/variable.yy", + }, + "resourceVersion": "1.0", + "name": "node_counter", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_dll/node_dll.gml b/scripts/node_dll/node_dll.gml new file mode 100644 index 000000000..783bc9ab0 --- /dev/null +++ b/scripts/node_dll/node_dll.gml @@ -0,0 +1,183 @@ +function Node_DLL(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { + name = "DLL"; + setDimension(96, 32 + 24 * 1); + + inputs[| 0] = nodeValue("DLL File", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "") + .setDisplay(VALUE_DISPLAY.path_load, { filter: "Dynamic-link library (.dll)|*.dll" }) + .setVisible(true, false); + + inputs[| 1] = nodeValue("Function name", self, JUNCTION_CONNECT.input, VALUE_TYPE.text, ""); + + inputs[| 2] = nodeValue("Return type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) + .setDisplay(VALUE_DISPLAY.enum_button, [ "Number", "Buffer" ]); + + outputs[| 0] = nodeValue("Return Value", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, 0); + + ext_cache = ""; + ext_function = -1; + attributes.size = 0; + + array_adjust_tool = new Inspector_Custom_Renderer(function(_x, _y, _w, _m, _hover, _focus) { #region + var _h = ui(48); + + var bw = _w / 2 - ui(4); + var bh = ui(36); + if(buttonTextIconInstant(true, THEME.button_hide, _x, _y + ui(8), bw, bh, _m, _focus, _hover, "", THEME.add, __txt("Add"), COLORS._main_value_positive) == 2) { + attributes.size++; + refreshDynamicInput(); + triggerRender(); + } + + var amo = attributes.size; + if(buttonTextIconInstant(attributes.size > 0, THEME.button_hide, _x + _w - bw, _y + ui(8), bw, bh, _m, _focus, _hover, "", THEME.minus, __txt("Remove"), COLORS._main_value_negative) == 2) { + attributes.size--; + refreshDynamicInput(); + triggerRender(); + } + + return _h; + }); #endregion + + input_display_list = [ + ["Function", false], 0, 1, 2, + ["Parameters", false], array_adjust_tool, + ] + + static createNewInput = function() { + var index = ds_list_size(inputs); + + inputs[| index + 0] = nodeValue("Parameter type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) + .setDisplay(VALUE_DISPLAY.enum_button, [ "Number", "Buffer" ]); + + inputs[| index + 1] = nodeValue("Parameter value", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0 ) + .setVisible(true, true); + + array_push(input_display_list, index + 0, index + 1); + + return [ inputs[| index + 0], inputs[| index + 1] ]; + } + + setDynamicInput(2, false); + + static refreshDynamicInput = function() { + var _l = ds_list_create(); + var amo = attributes.size; + var _ind = input_fix_len + amo * data_length; + + for( var i = 0; i < min(_ind, ds_list_size(inputs)); i++ ) + ds_list_add(_l, inputs[| i]); + + var _add = amo - getInputAmount(); + repeat(_add) ds_list_append_array(_l, createNewInput()); + + input_display_list = array_clone(input_display_list_raw); + + for( var i = input_fix_len; i < ds_list_size(_l); i++ ) { + _l[| i].index = i; + array_push(input_display_list, i); + } + + ds_list_destroy(inputs); + inputs = _l; + + getJunctionList(); + setHeight(); + + } + + val_types = [ VALUE_TYPE.float, VALUE_TYPE.buffer ]; + val_typeo = [ VALUE_TYPE.float, VALUE_TYPE.text ]; + + static update = function() { + var amo = getInputAmount(); + amo = clamp(round(amo), 0, 16); + var ts = array_create(amo); + var tv = array_create(amo); + var _rdy = true; + + for(var i = 0; i < amo; i++) { + var _ind = input_fix_len + i * data_length; + var _typ = getInputData(_ind + 0); + + inputs[| _ind + 1].setType(val_types[_typ]); + ts[i] = _typ? ty_string : ty_real; + + var _val = getInputData(_ind + 1); + if(_typ == 1) _val = buffer_to_string(_val); + + tv[i] = _val; + } + + var _fnS = { + path : getInputData(0), + func : getInputData(1), + type : getInputData(2)? ty_string : ty_real, + params : ts + } + + var _str = json_stringify(_fnS); + if(ext_cache != _str) { + + switch(amo) { + case 0 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 0); break; + case 1 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 1, ts[0]); break; + case 2 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 2, ts[0],ts[1]); break; + case 3 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 3, ts[0],ts[1],ts[2]); break; + case 4 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 4, ts[0],ts[1],ts[2],ts[3]); break; + case 5 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 5, ts[0],ts[1],ts[2],ts[3],ts[4]); break; + case 6 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 6, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5]); break; + case 7 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 7, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6]); break; + case 8 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 8, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7]); break; + case 9 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 9, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7],ts[8]); break; + case 10 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 10, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7],ts[8],ts[9]); break; + case 11 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 11, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7],ts[8],ts[9],ts[10]); break; + case 12 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 12, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7],ts[8],ts[9],ts[10],ts[11]); break; + case 13 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 13, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7],ts[8],ts[9],ts[10],ts[11],ts[12]); break; + case 14 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 14, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7],ts[8],ts[9],ts[10],ts[11],ts[12],ts[13]); break; + case 15 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 15, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7],ts[8],ts[9],ts[10],ts[11],ts[12],ts[13],ts[14]); break; + case 16 : ext_function = external_define(_fnS.path, _fnS.func, dll_cdecl, _fnS.type, 16, ts[0],ts[1],ts[2],ts[3],ts[4],ts[5],ts[6],ts[7],ts[8],ts[9],ts[10],ts[11],ts[12],ts[13],ts[14],ts[15]); break; + } + + ext_cache = _str; + } + + var _res = 0; + + if(_rdy) { + switch(amo) { + case 0 : _res = external_call(ext_function); break; + case 1 : _res = external_call(ext_function, tv[0]); break; + case 2 : _res = external_call(ext_function, tv[0],tv[1]); break; + case 3 : _res = external_call(ext_function, tv[0],tv[1],tv[2]); break; + case 4 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3]); break; + case 5 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4]); break; + case 6 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5]); break; + case 7 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6]); break; + case 8 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7]); break; + case 9 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7],tv[8]); break; + case 10 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7],tv[8],tv[9]); break; + case 11 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7],tv[8],tv[9],tv[10]); break; + case 12 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7],tv[8],tv[9],tv[10],tv[11]); break; + case 13 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7],tv[8],tv[9],tv[10],tv[11],tv[12]); break; + case 14 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7],tv[8],tv[9],tv[10],tv[11],tv[12],tv[13]); break; + case 15 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7],tv[8],tv[9],tv[10],tv[11],tv[12],tv[13],tv[14]); break; + case 16 : _res = external_call(ext_function, tv[0],tv[1],tv[2],tv[3],tv[4],tv[5],tv[6],tv[7],tv[8],tv[9],tv[10],tv[11],tv[12],tv[13],tv[14],tv[15]); break; + } + } + + outputs[| 0].setType(val_types[_fnS.type]); + + if(_fnS.type) _res = buffer_from_string(_res); + + outputs[| 0].setValue(_res); + + } + + static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { + var bbox = drawGetBbox(xx, yy, _s); + var _fn = getInputData(1); + + draw_set_text(f_sdf, fa_center, fa_center, COLORS._main_text); + draw_text_bbox(bbox, _fn); + } +} \ No newline at end of file diff --git a/scripts/node_dll/node_dll.yy b/scripts/node_dll/node_dll.yy new file mode 100644 index 000000000..474e0d1fc --- /dev/null +++ b/scripts/node_dll/node_dll.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"node_dll", + "isCompatibility":false, + "isDnD":false, + "name":"node_dll", + "parent":{ + "name":"misc", + "path":"folders/nodes/data/misc.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/node_dll/node_outline.yy b/scripts/node_dll/node_outline.yy new file mode 100644 index 000000000..86468bc09 --- /dev/null +++ b/scripts/node_dll/node_outline.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "process", + "path": "folders/nodes/data/process.yy", + }, + "resourceVersion": "1.0", + "name": "node_outline", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_path/node_path.gml b/scripts/node_path/node_path.gml index 2c4558dca..895cf7f41 100644 --- a/scripts/node_path/node_path.gml +++ b/scripts/node_path/node_path.gml @@ -37,8 +37,9 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { .setArrayDepth(1); input_display_list = [ - ["Path", false], 0, 2, 1, 3, - ["Anchors", false], + ["Path", false], 1, 3, + ["Sampling", false], 0, 2, + ["Anchors", false], ]; output_display_list = [ 1, 0, 2 ]; @@ -130,16 +131,16 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { } #endregion static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region - var sample = PREFERENCES.path_resolution; - var loop = getInputData(1); - var ansize = ds_list_size(inputs) - input_fix_len; - var _edited = false; + var ansize = ds_list_size(inputs) - input_fix_len; + var edited = false; var pos = outputs[| 0].getValue(); draw_set_color(COLORS._main_accent); draw_circle(_x + pos[0] * _s, _y + pos[1] * _s, 4, false); + /////////////////////////////////////////////////////// EDIT /////////////////////////////////////////////////////// + if(transform_type > 0) { var _transform_minx = transform_minx; var _transform_miny = transform_miny; @@ -166,7 +167,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { p[1] += dy / _s; if(inputs[| i].setValue(p)) - _edited = true; + edited = true; } transform_mx = mx; @@ -278,12 +279,12 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { p[_ANCHOR.c2y] = _p5 - p[_ANCHOR.y]; if(inputs[| i].setValue(p)) - _edited = true; + edited = true; } #endregion } - if(_edited) + if(edited) UNDO_HOLDING = true; if(mouse_release(mb_left)) { @@ -299,7 +300,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { var inp = inputs[| input_fix_len + drag_point]; var anc = array_clone(inp.getValue()); - if(drag_type != 0 && SHIFT == KEYBOARD_STATUS.down) + if(drag_type != 0 && key_mod_press(SHIFT)) anc[_ANCHOR.ind] = !anc[_ANCHOR.ind]; if(drag_type == 0) { //drag anchor point @@ -348,7 +349,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { } if(inp.setValue(anc)) - _edited = true; + edited = true; #endregion } else if(drag_type == 2) { #region pen tools var ox, oy, nx, ny; @@ -485,7 +486,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { for( var i = 0; i < 4; i++ ) { if(inputs[| input_fix_len + i].setValue(a[i])) - _edited = true; + edited = true; } #endregion } else if(drag_type == 4) { #region draw circle @@ -539,12 +540,12 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { for( var i = 0; i < 4; i++ ) { if(inputs[| input_fix_len + i].setValue(a[i])) - _edited = true; + edited = true; } #endregion } - if(_edited) UNDO_HOLDING = true; + if(edited) UNDO_HOLDING = true; if(mouse_release(mb_left)) { drag_point = -1; @@ -553,6 +554,8 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { } } + /////////////////////////////////////////////////////// DRAW PATH /////////////////////////////////////////////////////// + var _line_hover = -1; var anchor_hover = -1; var hover_type = 0; @@ -564,7 +567,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { var maxx = -99999, maxy = -99999; if(!array_empty(anchors)) { - draw_set_color(isUsingTool(0)? c_white : COLORS._main_accent); + draw_set_color(isUsingTool(0)? COLORS._main_icon : COLORS._main_accent); for( var i = 0, n = array_length(segments); i < n; i++ ) { #region draw path var _seg = segments[i]; @@ -640,6 +643,8 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { line_hover = _line_hover; + /////////////////////////////////////////////////////// TOOLS /////////////////////////////////////////////////////// + if(isUsingTool(0)) { #region transform tools var hov = 0; if(point_in_circle(_mx, _my, minx, miny, 8)) hov = 1; diff --git a/scripts/node_path_3d/node_path_3d.gml b/scripts/node_path_3d/node_path_3d.gml new file mode 100644 index 000000000..2611a9d4b --- /dev/null +++ b/scripts/node_path_3d/node_path_3d.gml @@ -0,0 +1,747 @@ +enum _ANCHOR3 { + x, + y, + z, + c1x, + c1y, + c1z, + c2x, + c2y, + c2z, + + ind, +} + +function Node_Path_3D(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { + name = "3D Path"; + is_3D = NODE_3D.polygon; + + setDimension(96, 48); + + inputs[| 0] = nodeValue("Path progress", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0, "Sample position from path.") + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 1] = nodeValue("Loop", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false) + .rejectArray(); + + inputs[| 2] = nodeValue("Progress mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) + .setDisplay(VALUE_DISPLAY.enum_scroll, ["Entire line", "Segment"]) + .rejectArray(); + + inputs[| 3] = nodeValue("Round anchor", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false) + .rejectArray(); + + outputs[| 0] = nodeValue("Position out", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [ 0, 0 ]) + .setDisplay(VALUE_DISPLAY.vector); + + outputs[| 1] = nodeValue("Path data", self, JUNCTION_CONNECT.output, VALUE_TYPE.pathnode, self); + + outputs[| 2] = nodeValue("Anchors", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, []) + .setVisible(false) + .setArrayDepth(1); + + input_display_list = [ + ["Path", false], 1, 3, + ["Sampling", false], 0, 2, + ["Anchors", false], + ]; + + output_display_list = [ 1, 0, 2 ]; + path_preview_surface = noone; + + setDynamicInput(1, false); + + tools = [ + new NodeTool( "Transform", THEME.path_tools_transform ), + new NodeTool( "Anchor add / remove", THEME.path_tools_add ), + new NodeTool( "Edit Control point", THEME.path_tools_anchor ), + ]; + + #region ---- path ---- + path_loop = false; + anchors = []; + segments = []; + lengths = []; + lengthAccs = []; + lengthTotal = 0; + boundary = new BoundingBox3D(); + + cached_pos = ds_map_create(); + #endregion + + #region ---- editor ---- + line_hover = -1; + + drag_point = -1; + drag_points = []; + drag_type = 0; + drag_point_mx = 0; + drag_point_my = 0; + drag_point_mz = 0; + + drag_point_sx = 0; + drag_point_sy = 0; + drag_point_sz = 0; + + drag_plane = noone; + drag_plane_origin = __vec3(); + drag_plane_normal = __vec3(); + + transform_type = 0; + + transform_minx = 0; transform_miny = 0; transform_minz = 0; + transform_maxx = 0; transform_maxy = 0; transform_maxz = 0; + + transform_cx = 0; transform_cy = 0; transform_cz = 0; + transform_sx = 0; transform_sy = 0; transform_sz = 0; + transform_mx = 0; transform_my = 0; transform_mz = 0; + #endregion + + static resetDisplayList = function() { #region + recordAction(ACTION_TYPE.var_modify, self, [ array_clone(input_display_list), "input_display_list" ]); + + input_display_list = array_clone(input_display_list_raw); + + for( var i = input_fix_len, n = ds_list_size(inputs); i < n; i++ ) { + array_push(input_display_list, i); + inputs[| i].name = $"Anchor {i - input_fix_len}"; + } + } #endregion + + static createNewInput = function( _x = 0, _y = 0, _z = 0, + _dxx = 0, _dxy = 0, _dxz = 0, + _dyx = 0, _dyy = 0, _dyz = 0, rec = true) { + + var index = ds_list_size(inputs); + + inputs[| index] = nodeValue("Anchor", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ _x, _y, _z, _dxx, _dxy, _dxz, _dyx, _dyy, _dyz, false ]) + .setDisplay(VALUE_DISPLAY.path_anchor); + + if(!rec) return inputs[| index]; + + recordAction(ACTION_TYPE.list_insert, inputs, [ inputs[| index], index, $"add path anchor point {index}" ]); + resetDisplayList(); + + return inputs[| index]; + } + + static onValueUpdate = function(index = 0) { #region + if(index == 2) { + var type = getInputData(2); + + if(type == 0) inputs[| 0].setDisplay(VALUE_DISPLAY.slider); + else if(type == 1) inputs[| 0].setDisplay(VALUE_DISPLAY._default); + } + } #endregion + + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { + + } + + static drawOverlay3D = function(active, params, _mx, _my, _snx, _sny, _panel) { + var ansize = ds_list_size(inputs) - input_fix_len; + var edited = false; + + var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90); + + var _camera = params.camera; + var _qview = new BBMOD_Quaternion().FromEuler(_camera.focus_angle_y, -_camera.focus_angle_x, 0); + var ray = _camera.viewPointToWorldRay(_mx, _my); + + /////////////////////////////////////////////////////// EDIT /////////////////////////////////////////////////////// + + if(drag_point > -1) { + var mAdj = d3d_intersect_ray_plane(ray, drag_plane); + + var dx = drag_point_sx + mAdj.x - drag_point_mx; + var dy = drag_point_sy + mAdj.y - drag_point_my; + var dz = drag_point_sz + mAdj.z - drag_point_mz; + + if(drag_type < 2) { // move points + var inp = inputs[| input_fix_len + drag_point]; + var anc = array_clone(inp.getValue()); + + if(drag_type != 0 && key_mod_down(SHIFT)) + anc[_ANCHOR3.ind] = !anc[_ANCHOR3.ind]; + + if(drag_type == 0) { //drag anchor point + anc[_ANCHOR3.x] = dx; + anc[_ANCHOR3.y] = dy; + anc[_ANCHOR3.z] = dz; + + if(key_mod_press(CTRL)) { + anc[_ANCHOR3.x] = round(anc[_ANCHOR3.x]); + anc[_ANCHOR3.y] = round(anc[_ANCHOR3.y]); + anc[_ANCHOR3.z] = round(anc[_ANCHOR3.z]); + } + + } else if(drag_type == 1) { //drag control 1 + anc[_ANCHOR3.c1x] = dx - anc[_ANCHOR3.x]; + anc[_ANCHOR3.c1y] = dy - anc[_ANCHOR3.y]; + anc[_ANCHOR3.c1z] = dz - anc[_ANCHOR3.z]; + + if(!anc[_ANCHOR3.ind]) { + anc[_ANCHOR3.c2x] = -anc[_ANCHOR3.c1x]; + anc[_ANCHOR3.c2y] = -anc[_ANCHOR3.c1y]; + anc[_ANCHOR3.c2z] = -anc[_ANCHOR3.c1z]; + } + + if(key_mod_press(CTRL)) { + anc[_ANCHOR3.c1x] = round(anc[_ANCHOR3.c1x]); + anc[_ANCHOR3.c1y] = round(anc[_ANCHOR3.c1y]); + anc[_ANCHOR3.c1z] = round(anc[_ANCHOR3.c1z]); + + if(!anc[_ANCHOR3.ind]) { + anc[_ANCHOR3.c2x] = round(anc[_ANCHOR3.c2x]); + anc[_ANCHOR3.c2y] = round(anc[_ANCHOR3.c2y]); + anc[_ANCHOR3.c2z] = round(anc[_ANCHOR3.c2z]); + } + } + + } else if(drag_type == -1) { //drag control 2 + anc[_ANCHOR3.c2x] = dx - anc[_ANCHOR3.x]; + anc[_ANCHOR3.c2y] = dy - anc[_ANCHOR3.y]; + anc[_ANCHOR3.c2z] = dz - anc[_ANCHOR3.z]; + + if(!anc[_ANCHOR3.ind]) { + anc[_ANCHOR3.c1x] = -anc[_ANCHOR3.c2x]; + anc[_ANCHOR3.c1y] = -anc[_ANCHOR3.c2y]; + anc[_ANCHOR3.c1z] = -anc[_ANCHOR3.c2z]; + } + + if(key_mod_press(CTRL)) { + anc[_ANCHOR3.c2x] = round(anc[_ANCHOR3.c2x]); + anc[_ANCHOR3.c2y] = round(anc[_ANCHOR3.c2y]); + anc[_ANCHOR3.c2z] = round(anc[_ANCHOR3.c2z]); + + if(!anc[_ANCHOR3.ind]) { + anc[_ANCHOR3.c1x] = round(anc[_ANCHOR3.c1x]); + anc[_ANCHOR3.c1y] = round(anc[_ANCHOR3.c1y]); + anc[_ANCHOR3.c1z] = round(anc[_ANCHOR3.c1z]); + } + } + } + + if(inp.setValue(anc)) + edited = true; + } + + if(edited) UNDO_HOLDING = true; + + if(mouse_release(mb_left)) { + drag_point = -1; + RENDER_ALL + UNDO_HOLDING = false; + } + } + + /////////////////////////////////////////////////////// DRAW PATH /////////////////////////////////////////////////////// + + var _line_hover = -1; + var anchor_hover = -1; + var hover_type = 0; + + var minx = 99999, miny = 99999, minz = 99999; + var maxx = -99999, maxy = -99999, maxz = -99999; + + if(!array_empty(anchors)) { + draw_set_color(isUsingTool(0)? COLORS._main_icon : COLORS._main_accent); + + var _v3 = new __vec3(); + + for( var i = 0, n = array_length(segments); i < n; i++ ) { + var _seg = segments[i]; + + var _px = 0, _py = 0, _pz = 0; + var _ox = 0, _oy = 0; + var _nx = 0, _ny = 0; + var p = 0; + + for( var j = 0, m = array_length(_seg); j < m; j += 3 ) { + _v3.x = _seg[j + 0]; + _v3.y = _seg[j + 1]; + _v3.z = _seg[j + 2]; + + var _posView = _camera.worldPointToViewPoint(_v3); + _nx = _posView.x; + _ny = _posView.y; + + minx = min(minx, _nx); miny = min(miny, _ny); + maxx = max(maxx, _nx); maxy = max(maxy, _ny); + + if(j) { + if((key_mod_press(CTRL) || isUsingTool(1)) && distance_to_line(_mx, _my, _ox, _oy, _nx, _ny) < 4) + _line_hover = i; + draw_line_width(_ox, _oy, _nx, _ny, 1 + 2 * (line_hover == i)); + } + + _ox = _nx; + _oy = _ny; + } + } + + if(!isUsingTool(0)) + for(var i = 0; i < ansize; i++) { + var _a = anchors[i]; + _v3.x = _a[0]; + _v3.y = _a[1]; + _v3.z = _a[2]; + + _posView = _camera.worldPointToViewPoint(_v3); + var xx = _posView.x; + var yy = _posView.y; + var cont = false; + var _ax0 = 0, _ay0 = 0; + var _ax1 = 0, _ay1 = 0; + + if(array_length(_a) < 6) continue; + + if(_a[2] != 0 || _a[3] != 0 || _a[4] != 0 || _a[5] != 0) { + _v3.x = _a[0] + _a[3]; + _v3.y = _a[1] + _a[4]; + _v3.z = _a[2] + _a[5]; + + _posView = _camera.worldPointToViewPoint(_v3); + _ax0 = _posView.x; + _ay0 = _posView.y; + + _v3.x = _a[0] + _a[6]; + _v3.y = _a[1] + _a[7]; + _v3.z = _a[2] + _a[8]; + + _posView = _camera.worldPointToViewPoint(_v3); + _ax1 = _posView.x; + _ay1 = _posView.y; + + cont = true; + + draw_set_color(COLORS.node_path_overlay_control_line); + draw_line(_ax0, _ay0, xx, yy); + draw_line(_ax1, _ay1, xx, yy); + + draw_sprite_colored(THEME.anchor_selector, 2, _ax0, _ay0); + draw_sprite_colored(THEME.anchor_selector, 2, _ax1, _ay1); + } + + draw_sprite_colored(THEME.anchor_selector, 0, xx, yy); + draw_set_text(f_p1, fa_left, fa_bottom, COLORS._main_accent); + draw_text(xx + ui(4), yy - ui(4), inputs[| input_fix_len + i].name); + + if(drag_point == i) { + draw_sprite_colored(THEME.anchor_selector, 1, xx, yy); + + } else if(point_in_circle(_mx, _my, xx, yy, 8)) { + draw_sprite_colored(THEME.anchor_selector, 1, xx, yy); + anchor_hover = i; + hover_type = 0; + + } else if(cont && point_in_circle(_mx, _my, _ax0, _ay0, 8)) { + draw_sprite_colored(THEME.anchor_selector, 0, _ax0, _ay0); + anchor_hover = i; + hover_type = 1; + + } else if(cont && point_in_circle(_mx, _my, _ax1, _ay1, 8)) { + draw_sprite_colored(THEME.anchor_selector, 0, _ax1, _ay1); + anchor_hover = i; + hover_type = -1; + } + } + } + + line_hover = _line_hover; + + /////////////////////////////////////////////////////// TOOLS /////////////////////////////////////////////////////// + + if(anchor_hover != -1) { // no tool, dragging existing point + var _a = array_clone(getInputData(input_fix_len + anchor_hover)); + if(isUsingTool(2) && hover_type == 0) { + draw_sprite_ui_uniform(THEME.cursor_path_anchor, 0, _mx + 16, _my + 16); + + if(mouse_press(mb_left, active)) { + + if(_a[3] != 0 || _a[4] != 0 || _a[5] != 0 || _a[6] != 0 || _a[7] != 0 || _a[8] != 0) { + _a[3] = 0; _a[4] = 0; _a[5] = 0; + _a[6] = 0; _a[7] = 0; _a[8] = 0; + _a[9] = false; + + inputs[| input_fix_len + anchor_hover].setValue(_a); + + } else { + _a[3] = -8; _a[4] = 0; _a[5] = 0; + _a[6] = 8; _a[7] = 0; _a[8] = 0; + _a[9] = false; + + drag_point = anchor_hover; + drag_type = 1; + + drag_plane_origin = new __vec3(_a[0], _a[1], _a[2]); + drag_plane_normal = ray.direction.multiply(-1)._normalize(); + drag_plane = new __plane(drag_plane_origin, drag_plane_normal); + + var mAdj = d3d_intersect_ray_plane(ray, drag_plane); + drag_point_mx = mAdj.x; + drag_point_my = mAdj.y; + drag_point_mz = mAdj.z; + + drag_point_sx = _a[0]; + drag_point_sy = _a[1]; + drag_point_sz = _a[2]; + } + } + } else if(hover_type == 0 && key_mod_press(SHIFT)) { //remove + draw_sprite_ui_uniform(THEME.cursor_path_remove, 0, _mx + 16, _my + 16); + + if(mouse_press(mb_left, active)) { + var _indx = input_fix_len + anchor_hover; + recordAction(ACTION_TYPE.list_delete, inputs, [ inputs[| _indx], _indx, "remove path anchor point" ]); + + ds_list_delete(inputs, _indx); + resetDisplayList(); + doUpdate(); + } + } else { + draw_sprite_ui_uniform(THEME.cursor_path_move, 0, _mx + 16, _my + 16); + + if(mouse_press(mb_left, active)) { + if(isUsingTool(2)) { + _a[_ANCHOR3.ind] = true; + inputs[| input_fix_len + anchor_hover].setValue(_a); + } + + drag_point = anchor_hover; + drag_type = hover_type; + + drag_plane_origin = new __vec3(_a[0], _a[1], _a[2]); + drag_plane_normal = ray.direction.multiply(-1)._normalize(); + drag_plane = new __plane(drag_plane_origin, drag_plane_normal); + + var mAdj = d3d_intersect_ray_plane(ray, drag_plane); + drag_point_mx = mAdj.x; + drag_point_my = mAdj.y; + drag_point_mz = mAdj.z; + + drag_point_sx = _a[0]; + drag_point_sy = _a[1]; + drag_point_sz = _a[2]; + + if(hover_type == 1) { + drag_point_sx = _a[0] + _a[3]; + drag_point_sy = _a[1] + _a[4]; + drag_point_sz = _a[2] + _a[5]; + + } else if(hover_type == -1) { + drag_point_sx = _a[0] + _a[6]; + drag_point_sy = _a[1] + _a[7]; + drag_point_sz = _a[2] + _a[8]; + } + } + } + + } else if(key_mod_press(CTRL) || isUsingTool(1)) { // anchor edit + draw_sprite_ui_uniform(THEME.cursor_path_add, 0, _mx + 16, _my + 16); + + if(mouse_press(mb_left, active)) { + + drag_plane_origin = new __vec3(); + drag_plane_normal = ray.direction.multiply(-1)._normalize(); + drag_plane = new __plane(drag_plane_origin, drag_plane_normal); + var mAdj = d3d_intersect_ray_plane(ray, drag_plane); + + var ind = ds_list_size(inputs); + var anc = createNewInput(mAdj.x, mAdj.y, mAdj.z, 0, 0, 0, 0, 0, 0, false); + + if(_line_hover == -1) { + drag_point = ds_list_size(inputs) - input_fix_len - 1; + } else { + ds_list_remove(inputs, anc); + ds_list_insert(inputs, input_fix_len + _line_hover + 1, anc); + drag_point = _line_hover + 1; + ind = input_fix_len + _line_hover + 1; + } + + recordAction(ACTION_TYPE.list_insert, inputs, [ inputs[| ind], ind, $"add path anchor point {ind}" ]); + resetDisplayList(); + UNDO_HOLDING = true; + + drag_type = -1; + + drag_point_mx = mAdj.x; + drag_point_my = mAdj.y; + drag_point_mz = mAdj.z; + + drag_point_sx = mAdj.x; + drag_point_sy = mAdj.y; + drag_point_sz = mAdj.z; + + RENDER_ALL + } + } + + } + + static updateLength = function() { #region + boundary = new BoundingBox(); + segments = []; + lengths = []; + lengthAccs = []; + lengthTotal = 0; + + var _index = 0; + var sample = PREFERENCES.path_resolution; + var ansize = ds_list_size(inputs) - input_fix_len; + if(ansize < 2) return; + + var con = path_loop? ansize : ansize - 1; + + for(var i = 0; i < con; i++) { + var _a0 = anchors[(i + 0) % ansize]; + var _a1 = anchors[(i + 1) % ansize]; + + var l = 0; + var _ox = 0, _oy = 0, _oz = 0; + var _nx = 0, _ny = 0, _nz = 0; + var p = 0; + + var sg = array_create((sample + 1) * 3); + + for(var j = 0; j <= sample; j++) { + var _t = j / sample; + + if(_a0[6] == 0 && _a0[7] == 0 && _a0[8] == 0 && _a1[3] == 0 && _a1[4] == 0 && _a1[5] == 0) { + _nx = lerp(_a0[0], _a1[0], _t); + _ny = lerp(_a0[1], _a1[1], _t); + _nz = lerp(_a0[2], _a1[2], _t); + + } else { + _nx = eval_bezier_n(_t, _a0[0], _a1[0], _a0[0] + _a0[6], _a1[0] + _a1[3]); + _ny = eval_bezier_n(_t, _a0[1], _a1[1], _a0[1] + _a0[7], _a1[1] + _a1[4]); + _nz = eval_bezier_n(_t, _a0[2], _a1[2], _a0[2] + _a0[8], _a1[2] + _a1[5]); + + } + + sg[j * 3 + 0] = _nx; + sg[j * 3 + 1] = _ny; + sg[j * 3 + 2] = _nz; + + boundary.addPoint(_nx, _ny, _nz); + if(j) l += point_distance_3d(_nx, _ny, _nz, _ox, _oy, _oz); + + _ox = _nx; + _oy = _ny; + } + + segments[i] = sg; + lengths[i] = l; + lengthTotal += l; + lengthAccs[i] = lengthTotal; + } + + // var minx = boundary.minx - 8, miny = boundary.miny - 8; + // var maxx = boundary.maxx + 8, maxy = boundary.maxy + 8; + // var rngx = maxx - minx, rngy = maxy - miny; + // var prev_s = 128; + // var _surf = surface_create(prev_s, prev_s); + + // _surf = surface_verify(_surf, prev_s, prev_s); + // surface_set_target(_surf); + // DRAW_CLEAR + + // var ox, oy, nx, ny; + // draw_set_color(c_white); + // for (var i = 0, n = array_length(segments); i < n; i++) { + // var segment = segments[i]; + + // for (var j = 0, m = array_length(segment); j < m; j += 2) { + // nx = (segment[j + 0] - minx) / rngx * prev_s; + // ny = (segment[j + 1] - miny) / rngy * prev_s; + + // if(j) draw_line_round(ox, oy, nx, ny, 4); + + // ox = nx; + // oy = ny; + // } + // } + + // draw_set_color(COLORS._main_accent); + // for (var i = 0, n = array_length(anchors); i < n; i++) { + // var _a0 = anchors[i]; + // draw_circle((_a0[0] - minx) / rngx * prev_s, (_a0[1] - miny) / rngy * prev_s, 8, false); + // } + // surface_reset_target(); + + // path_preview_surface = surface_verify(path_preview_surface, prev_s, prev_s); + // surface_set_shader(path_preview_surface, sh_FXAA); + // shader_set_f("dimension", prev_s, prev_s); + // shader_set_f("cornerDis", 0.5); + // shader_set_f("mixAmo", 1); + + // draw_surface(_surf, 0, 0); + // surface_reset_shader(); + + // surface_free(_surf); + } #endregion + + static getLineCount = function() { return 1; } + static getSegmentCount = function() { return array_length(lengths); } + static getBoundary = function() { return boundary; } + + static getLength = function() { return lengthTotal; } + static getAccuLength = function() { return lengthAccs; } + + static getPointDistance = function(_dist, _ind = 0, out = undefined) { #region + if(out == undefined) out = new __vec3(); else { out.x = 0; out.y = 0; out.z = 0; } + if(array_empty(lengths)) return out; + + var _cKey = _dist; + if(ds_map_exists(cached_pos, _cKey)) { + var _p = cached_pos[? _cKey]; + out.x = _p.x; + out.y = _p.y; + out.z = _p.z; + return out; + } + + var loop = getInputData(1); + if(loop) _dist = safe_mod(_dist, lengthTotal, MOD_NEG.wrap); + + var ansize = ds_list_size(inputs) - input_fix_len; + if(ansize == 0) return out; + + var _a0, _a1; + + for(var i = 0; i < ansize; i++) { + _a0 = anchors[(i + 0) % ansize]; + _a1 = anchors[(i + 1) % ansize]; + + if(_dist > lengths[i]) { + _dist -= lengths[i]; + continue; + } + + var _t = _dist / lengths[i]; + + if(_a0[6] == 0 && _a0[7] == 0 && _a0[8] == 0 && _a1[3] == 0 && _a1[4] == 0 && _a1[5] == 0) { + out.x = lerp(_a0[0], _a1[0], _t); + out.y = lerp(_a0[1], _a1[1], _t); + out.z = lerp(_a0[2], _a1[2], _t); + + } else { + out.x = eval_bezier_n(_t, _a0[0], _a1[0], _a0[0] + _a0[6], _a1[0] + _a1[3]); + out.y = eval_bezier_n(_t, _a0[1], _a1[1], _a0[1] + _a0[7], _a1[1] + _a1[4]); + out.z = eval_bezier_n(_t, _a0[2], _a1[2], _a0[2] + _a0[8], _a1[2] + _a1[5]); + + } + + cached_pos[? _cKey] = new __vec3(out.x, out.y, out.z); + return out; + } + + return out; + } #endregion + + static getPointRatio = function(_rat, _ind = 0, out = undefined) { #region + var pix = (path_loop? frac(_rat) : clamp(_rat, 0, 0.99)) * lengthTotal; + return getPointDistance(pix, _ind, out); + } #endregion + + static getPointSegment = function(_rat) { #region + if(array_empty(lengths)) return new __vec3(); + + var loop = getInputData(1); + var ansize = ds_list_size(inputs) - input_fix_len; + + if(_rat < 0) return new __vec3(anchors[0][0], anchors[0][1], anchors[0][2]); + + _rat = safe_mod(_rat, ansize); + var _i0 = clamp(floor(_rat), 0, ansize - 1); + var _i1 = (_i0 + 1) % ansize; + var _t = frac(_rat); + + if(_i1 >= ansize && !loop) return new __vec3(anchors[ansize - 1][0], anchors[ansize - 1][1], anchors[ansize - 1][2]); + + var _a0 = anchors[_i0]; + var _a1 = anchors[_i1]; + var px, py, pz; + + if(_a0[6] == 0 && _a0[7] == 0 && _a0[8] == 0 && _a1[3] == 0 && _a1[4] == 0 && _a1[5] == 0) { + px = lerp(_a0[0], _a1[0], _t); + py = lerp(_a0[1], _a1[1], _t); + pz = lerp(_a0[2], _a1[2], _t); + + } else { + px = eval_bezier_n(_t, _a0[0], _a1[0], _a0[0] + _a0[6], _a1[0] + _a1[3]); + py = eval_bezier_n(_t, _a0[1], _a1[1], _a0[1] + _a0[7], _a1[1] + _a1[4]); + pz = eval_bezier_n(_t, _a0[2], _a1[2], _a0[2] + _a0[8], _a1[2] + _a1[5]); + + } + + return new __vec3(px, py, pz); + } #endregion + + static update = function(frame = CURRENT_FRAME) { #region + ds_map_clear(cached_pos); + + var _rat = getInputData(0); + path_loop = getInputData(1); + var _typ = getInputData(2); + var _rnd = getInputData(3); + + var _a = []; + for(var i = input_fix_len; i < ds_list_size(inputs); i++) { + var _val = getInputData(i); + var _anc = array_create(10, 0); + + for(var j = 0; j < 10; j++) + _anc[j] = array_safe_get(_val, j); + + if(_rnd) { + _anc[0] = round(_val[0]); + _anc[1] = round(_val[1]); + _anc[2] = round(_val[2]); + } + + array_push(_a, _anc); + } + + anchors = _a; + outputs[| 2].setValue(_a); + + updateLength(); + + if(is_array(_rat)) { + var _out = array_create(array_length(_rat)); + + for( var i = 0, n = array_length(_rat); i < n; i++ ) { + if(_typ == 0) _out[i] = getPointRatio(_rat[i]); + else if(_typ == 1) _out[i] = getPointSegment(_rat[i]); + } + + outputs[| 0].setValue(_out); + } else { + var _out = [0, 0]; + + if(_typ == 0) _out = getPointRatio(_rat); + else if(_typ == 1) _out = getPointSegment(_rat); + + outputs[| 0].setValue(_out.toArray()); + } + } #endregion + + static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region + var bbox = drawGetBbox(xx, yy, _s); + + // if(array_empty(segments)) { + draw_sprite_fit(s_node_path, 0, bbox.xc, bbox.yc, bbox.w, bbox.h); + + // } else { + // gpu_set_tex_filter(true); + // draw_surface_bbox(path_preview_surface, bbox); + // gpu_set_tex_filter(false); + // } + } #endregion + + static getPreviewObject = function() { return noone; } + static getPreviewObjects = function() { return []; } + static getPreviewObjectOutline = function() { return []; } + +} \ No newline at end of file diff --git a/scripts/node_path_3d/node_path_3d.yy b/scripts/node_path_3d/node_path_3d.yy new file mode 100644 index 000000000..d15b519b6 --- /dev/null +++ b/scripts/node_path_3d/node_path_3d.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"node_path_3d", + "isCompatibility":false, + "isDnD":false, + "name":"node_path_3d", + "parent":{ + "name":"path", + "path":"folders/nodes/data/value/path.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/node_registry/node_registry.gml b/scripts/node_registry/node_registry.gml index 21d67606c..82775283b 100644 --- a/scripts/node_registry/node_registry.gml +++ b/scripts/node_registry/node_registry.gml @@ -674,6 +674,7 @@ function __initNodes() { addNodeObject(d3d, "3D Cone", s_node_3d_cone, "Node_3D_Mesh_Cone", [1, Node_3D_Mesh_Cone]).setVersion(11510); addNodeObject(d3d, "3D Terrain", s_node_3d_displace, "Node_3D_Mesh_Terrain", [1, Node_3D_Mesh_Terrain],, "Create 3D terrain from height map.").setVersion(11560); addNodeObject(d3d, "Surface Extrude", s_node_3d_extrude, "Node_3D_Mesh_Extrude", [1, Node_3D_Mesh_Extrude],, "Extrude 2D image into 3D object.").setVersion(11510); + addNodeObject(d3d, "Path Extrude", s_node_3d_path_extrude, "Node_3D_Mesh_Path_Extrude",[1, Node_3D_Mesh_Path_Extrude],, "Extrude path into 3D object.").setVersion(11750); ds_list_add(d3d, "Light"); addNodeObject(d3d, "Directional Light", s_node_3d_light_directi, "Node_3D_Light_Directional", [1, Node_3D_Light_Directional],, "Create directional light directed at the origin point.").setVersion(11510); @@ -902,6 +903,7 @@ function __initNodes() { addNodeObject(values, "Bake Path", s_node_path_bake, "Node_Path_Bake", [1, Node_Path_Bake]).setVersion(11640); addNodeObject(values, "Map Path", s_node_path_mapp, "Node_Path_Map", [1, Node_Path_Map]).setVersion(11640); addNodeObject(values, "Scatter Path", s_node_path_scatter, "Node_Path_Scatter", [1, Node_Path_Scatter]).setVersion(11740); + addNodeObject(values, "3D Path", s_node_path_3d, "Node_Path_3D", [1, Node_Path_3D], [ "path 3d" ]).setVersion(11750); ds_list_add(values, "Boolean"); addNodeObject(values, "Boolean", s_node_boolean, "Node_Boolean", [1, Node_Boolean]); @@ -1039,6 +1041,7 @@ function __initNodes() { addNodeObject(node, "Monitor Capture", s_node_monitor_capture, "Node_Monitor_Capture", [1, Node_Monitor_Capture]); addNodeObject(node, "GUI In", s_node_gui_in, "Node_Application_In", [1, Node_Application_In]); addNodeObject(node, "GUI Out", s_node_gui_out, "Node_Application_Out", [1, Node_Application_Out]); + // addNodeObject(node, "DLL", s_node_gui_out, "Node_DLL", [1, Node_DLL]).setVersion(11750); #endregion var actions = ds_list_create(); diff --git a/scripts/node_transform/node_transform.gml b/scripts/node_transform/node_transform.gml index 61778e2a8..fc3932fa7 100644 --- a/scripts/node_transform/node_transform.gml +++ b/scripts/node_transform/node_transform.gml @@ -212,6 +212,11 @@ function Node_Transform(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) var _ww = ww; var _hh = hh; + if(!is_surface(ins)) { + surface_free(_outSurf); + _outSurf = noone; + } + _outRes[0] = _outSurf; _outRes[1] = [ ww, hh ]; diff --git a/scripts/panel_addon/panel_addon.gml b/scripts/panel_addon/panel_addon.gml index 4d2faba8f..922f4886a 100644 --- a/scripts/panel_addon/panel_addon.gml +++ b/scripts/panel_addon/panel_addon.gml @@ -67,9 +67,9 @@ function Panel_Addon() : PanelContent() constructor { var hover = pHOVER && point_in_rectangle(_m[0], _m[1], 0, by, ww, by + hh); if(_addon.open) draw_sprite_stretched_ext(THEME.ui_panel_bg, 3, 0, by, ww, hh, COLORS._main_icon_light, 1); - - var cc = hover? c_white : COLORS._main_icon_light; - draw_sprite_stretched_ext(THEME.ui_panel_bg, 3, 0, by, ww, hg, cc, 1); + + if(hover) draw_sprite_stretched_ext(THEME.group_label, 0, 0, by, ww, hg, COLORS.panel_inspector_group_hover, 1); + else draw_sprite_stretched_ext(THEME.group_label, 0, 0, by, ww, hg, COLORS.panel_inspector_group_bg, 1); draw_set_text(f_p0, fa_left, fa_center, COLORS._main_text); draw_text_add(ui(44), by + hg / 2, _addon.name); diff --git a/scripts/path_function/path_function.gml b/scripts/path_function/path_function.gml index e50007a13..095354ce8 100644 --- a/scripts/path_function/path_function.gml +++ b/scripts/path_function/path_function.gml @@ -1,6 +1,8 @@ function eval_bezier_x(t, x0, y0, x1, y1, cx0, cy0, cx1, cy1) { INLINE return power(1 - t, 3) * x0 + 3 * power(1 - t, 2) * (t) * cx0 + 3 * power(t, 2) * (1 - t) * cx1 + power(t, 3) * x1; } function eval_bezier_y(t, x0, y0, x1, y1, cx0, cy0, cx1, cy1) { INLINE return power(1 - t, 3) * y0 + 3 * power(1 - t, 2) * (t) * cy0 + 3 * power(t, 2) * (1 - t) * cy1 + power(t, 3) * y1; } +function eval_bezier_n(t, x0, x1, cx0, cx1) { INLINE return power(1 - t, 3) * x0 + 3 * power(1 - t, 2) * (t) * cx0 + 3 * power(t, 2) * (1 - t) * cx1 + power(t, 3) * x1; } + function eval_bezier(t, x0, y0, x1, y1, cx0, cy0, cx1, cy1) { var xx = power(1 - t, 3) * x0 + 3 * power(1 - t, 2) * (t) * cx0 + 3 * power(t, 2) * (1 - t) * cx1 + power(t, 3) * x1; var yy = power(1 - t, 3) * y0 + 3 * power(1 - t, 2) * (t) * cy0 + 3 * power(t, 2) * (1 - t) * cy1 + power(t, 3) * y1;