diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index 3e42d44c5..c146af096 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -1006,34 +1006,35 @@ {"name":"node_palette_sort","order":2,"path":"scripts/node_palette_sort/node_palette_sort.yy",}, {"name":"node_palette","order":1,"path":"scripts/node_palette/node_palette.yy",}, {"name":"node_particle","order":10,"path":"scripts/node_particle/node_particle.yy",}, + {"name":"node_path_3d_camera","order":2,"path":"scripts/node_path_3d_camera/node_path_3d_camera.yy",}, {"name":"node_path_3d","order":1,"path":"scripts/node_path_3d/node_path_3d.yy",}, - {"name":"node_path_anchor","order":16,"path":"scripts/node_path_anchor/node_path_anchor.yy",}, - {"name":"node_path_array","order":14,"path":"scripts/node_path_array/node_path_array.yy",}, - {"name":"node_path_bake","order":19,"path":"scripts/node_path_bake/node_path_bake.yy",}, - {"name":"node_path_blend","order":5,"path":"scripts/node_path_blend/node_path_blend.yy",}, - {"name":"node_path_bridge","order":20,"path":"scripts/node_path_bridge/node_path_bridge.yy",}, - {"name":"node_path_builder","order":12,"path":"scripts/node_path_builder/node_path_builder.yy",}, - {"name":"node_path_fill","order":6,"path":"scripts/node_path_fill/node_path_fill.yy",}, - {"name":"node_path_from_mask","order":17,"path":"scripts/node_path_from_mask/node_path_from_mask.yy",}, - {"name":"node_path_l_system","order":13,"path":"scripts/node_path_l_system/node_path_l_system.yy",}, - {"name":"node_path_map_area","order":4,"path":"scripts/node_path_map_area/node_path_map_area.yy",}, - {"name":"node_path_map","order":21,"path":"scripts/node_path_map/node_path_map.yy",}, - {"name":"node_path_morph","order":22,"path":"scripts/node_path_morph/node_path_morph.yy",}, - {"name":"node_path_plot","order":15,"path":"scripts/node_path_plot/node_path_plot.yy",}, + {"name":"node_path_anchor","order":17,"path":"scripts/node_path_anchor/node_path_anchor.yy",}, + {"name":"node_path_array","order":15,"path":"scripts/node_path_array/node_path_array.yy",}, + {"name":"node_path_bake","order":20,"path":"scripts/node_path_bake/node_path_bake.yy",}, + {"name":"node_path_blend","order":6,"path":"scripts/node_path_blend/node_path_blend.yy",}, + {"name":"node_path_bridge","order":21,"path":"scripts/node_path_bridge/node_path_bridge.yy",}, + {"name":"node_path_builder","order":13,"path":"scripts/node_path_builder/node_path_builder.yy",}, + {"name":"node_path_fill","order":7,"path":"scripts/node_path_fill/node_path_fill.yy",}, + {"name":"node_path_from_mask","order":18,"path":"scripts/node_path_from_mask/node_path_from_mask.yy",}, + {"name":"node_path_l_system","order":14,"path":"scripts/node_path_l_system/node_path_l_system.yy",}, + {"name":"node_path_map_area","order":5,"path":"scripts/node_path_map_area/node_path_map_area.yy",}, + {"name":"node_path_map","order":22,"path":"scripts/node_path_map/node_path_map.yy",}, + {"name":"node_path_morph","order":23,"path":"scripts/node_path_morph/node_path_morph.yy",}, + {"name":"node_path_plot","order":16,"path":"scripts/node_path_plot/node_path_plot.yy",}, {"name":"node_path_profile","order":15,"path":"scripts/node_path_profile/node_path_profile.yy",}, - {"name":"node_path_repeat","order":26,"path":"scripts/node_path_repeat/node_path_repeat.yy",}, - {"name":"node_path_reverse","order":11,"path":"scripts/node_path_reverse/node_path_reverse.yy",}, - {"name":"node_path_sample","order":7,"path":"scripts/node_path_sample/node_path_sample.yy",}, - {"name":"node_path_scatter","order":25,"path":"scripts/node_path_scatter/node_path_scatter.yy",}, - {"name":"node_path_sdf","order":27,"path":"scripts/node_path_sdf/node_path_sdf.yy",}, + {"name":"node_path_repeat","order":27,"path":"scripts/node_path_repeat/node_path_repeat.yy",}, + {"name":"node_path_reverse","order":12,"path":"scripts/node_path_reverse/node_path_reverse.yy",}, + {"name":"node_path_sample","order":8,"path":"scripts/node_path_sample/node_path_sample.yy",}, + {"name":"node_path_scatter","order":26,"path":"scripts/node_path_scatter/node_path_scatter.yy",}, + {"name":"node_path_sdf","order":28,"path":"scripts/node_path_sdf/node_path_sdf.yy",}, {"name":"node_path_separate_folder","order":12,"path":"scripts/node_path_separate_folder/node_path_separate_folder.yy",}, - {"name":"node_path_shape","order":2,"path":"scripts/node_path_shape/node_path_shape.yy",}, - {"name":"node_path_shift","order":8,"path":"scripts/node_path_shift/node_path_shift.yy",}, - {"name":"node_path_smooth","order":24,"path":"scripts/node_path_smooth/node_path_smooth.yy",}, - {"name":"node_path_transform","order":3,"path":"scripts/node_path_transform/node_path_transform.yy",}, - {"name":"node_path_trim","order":9,"path":"scripts/node_path_trim/node_path_trim.yy",}, - {"name":"node_path_wave","order":10,"path":"scripts/node_path_wave/node_path_wave.yy",}, - {"name":"node_path_weight_adjust","order":30,"path":"scripts/node_path_weight_adjust/node_path_weight_adjust.yy",}, + {"name":"node_path_shape","order":3,"path":"scripts/node_path_shape/node_path_shape.yy",}, + {"name":"node_path_shift","order":9,"path":"scripts/node_path_shift/node_path_shift.yy",}, + {"name":"node_path_smooth","order":25,"path":"scripts/node_path_smooth/node_path_smooth.yy",}, + {"name":"node_path_transform","order":4,"path":"scripts/node_path_transform/node_path_transform.yy",}, + {"name":"node_path_trim","order":10,"path":"scripts/node_path_trim/node_path_trim.yy",}, + {"name":"node_path_wave","order":11,"path":"scripts/node_path_wave/node_path_wave.yy",}, + {"name":"node_path_weight_adjust","order":31,"path":"scripts/node_path_weight_adjust/node_path_weight_adjust.yy",}, {"name":"node_pb_box_contract","order":8,"path":"scripts/node_pb_box_contract/node_pb_box_contract.yy",}, {"name":"node_pb_box_divide_grid","order":7,"path":"scripts/node_pb_box_divide_grid/node_pb_box_divide_grid.yy",}, {"name":"node_pb_box_divide","order":5,"path":"scripts/node_pb_box_divide/node_pb_box_divide.yy",}, @@ -1123,7 +1124,7 @@ {"name":"node_scale","order":12,"path":"scripts/node_scale/node_scale.yy",}, {"name":"node_scatter_points","order":7,"path":"scripts/node_scatter_points/node_scatter_points.yy",}, {"name":"node_scatter","order":13,"path":"scripts/node_scatter/node_scatter.yy",}, - {"name":"node_segment_filter","order":29,"path":"scripts/node_segment_filter/node_segment_filter.yy",}, + {"name":"node_segment_filter","order":30,"path":"scripts/node_segment_filter/node_segment_filter.yy",}, {"name":"node_separate_color","order":42,"path":"scripts/node_separate_color/node_separate_color.yy",}, {"name":"node_sequence_anim","order":6,"path":"scripts/node_sequence_anim/node_sequence_anim.yy",}, {"name":"node_shadow_cast","order":28,"path":"scripts/node_shadow_cast/node_shadow_cast.yy",}, @@ -1660,7 +1661,7 @@ {"name":"sh_grid","order":3,"path":"shaders/sh_grid/sh_grid.yy",}, {"name":"sh_herringbone_tile","order":15,"path":"shaders/sh_herringbone_tile/sh_herringbone_tile.yy",}, {"name":"sh_high_pass","order":32,"path":"shaders/sh_high_pass/sh_high_pass.yy",}, - {"name":"sh_image_trace","order":18,"path":"shaders/sh_image_trace/sh_image_trace.yy",}, + {"name":"sh_image_trace","order":19,"path":"shaders/sh_image_trace/sh_image_trace.yy",}, {"name":"sh_interlaced","order":51,"path":"shaders/sh_interlaced/sh_interlaced.yy",}, {"name":"sh_interpret_number","order":9,"path":"shaders/sh_interpret_number/sh_interpret_number.yy",}, {"name":"sh_invert","order":17,"path":"shaders/sh_invert/sh_invert.yy",}, @@ -1737,8 +1738,8 @@ {"name":"sh_palette_replace","order":9,"path":"shaders/sh_palette_replace/sh_palette_replace.yy",}, {"name":"sh_palette_shift","order":31,"path":"shaders/sh_palette_shift/sh_palette_shift.yy",}, {"name":"sh_path_fill_profile","order":16,"path":"shaders/sh_path_fill_profile/sh_path_fill_profile.yy",}, - {"name":"sh_path_morph","order":23,"path":"shaders/sh_path_morph/sh_path_morph.yy",}, - {"name":"sh_path_sdf","order":28,"path":"shaders/sh_path_sdf/sh_path_sdf.yy",}, + {"name":"sh_path_morph","order":24,"path":"shaders/sh_path_morph/sh_path_morph.yy",}, + {"name":"sh_path_sdf","order":29,"path":"shaders/sh_path_sdf/sh_path_sdf.yy",}, {"name":"sh_pb_blob","order":1,"path":"shaders/sh_pb_blob/sh_pb_blob.yy",}, {"name":"sh_pb_brick","order":9,"path":"shaders/sh_pb_brick/sh_pb_brick.yy",}, {"name":"sh_pb_draw_mask","order":8,"path":"shaders/sh_pb_draw_mask/sh_pb_draw_mask.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index c4b98a7fa..ccf557c18 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -2202,6 +2202,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_camera","path":"scripts/node_path_3d_camera/node_path_3d_camera.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",},}, diff --git a/datafiles/data/Nodes/Internal.zip b/datafiles/data/Nodes/Internal.zip index 54c00c634..3220fea33 100644 Binary files a/datafiles/data/Nodes/Internal.zip and b/datafiles/data/Nodes/Internal.zip differ diff --git a/datafiles/data/Nodes/Internal/Values/Path/Node_Path_3D_Camera/info.json b/datafiles/data/Nodes/Internal/Values/Path/Node_Path_3D_Camera/info.json new file mode 100644 index 000000000..bb620a5ee --- /dev/null +++ b/datafiles/data/Nodes/Internal/Values/Path/Node_Path_3D_Camera/info.json @@ -0,0 +1,8 @@ +{ + "name":"3D Path Camera", + "tooltip":"Render a 3D path into 2d space", + "baseNode":"Node_Path_3D_Camera", + "spr":"s_node_path_3d", + "pxc_version":118080, + "io":[ "pathnode" ], +} \ No newline at end of file diff --git a/datafiles/data/Nodes/display_data.json b/datafiles/data/Nodes/display_data.json index 5738b090c..2c18c6da5 100644 --- a/datafiles/data/Nodes/display_data.json +++ b/datafiles/data/Nodes/display_data.json @@ -766,6 +766,7 @@ "Node_Path_From_Mask", "Node_Path_Plot", "Node_Path_3D", + "Node_Path_3D_Camera", "Node_Path_Anchor", { "label": "/Modifiers" }, "Node_Path_Transform", diff --git a/scripts/node_line/node_line.gml b/scripts/node_line/node_line.gml index 8fe71c9d6..41d3e97b7 100644 --- a/scripts/node_line/node_line.gml +++ b/scripts/node_line/node_line.gml @@ -398,6 +398,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons // print($"===== {_prog_curr} / {_segLength} : {_segIndex} - {_pathLength} ====="); while(true) { + var _pp = 0; wght = 1; _segIndexPrev = _segIndex; @@ -410,7 +411,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons //print($"{segmentLength}/{_pathLength} = {_prog_next}"); if(_prog_next == segmentLength) _segIndex++; - var _pp = _clamp? clamp(_pathPng, 0, _pathLength) : _pathPng; + _pp = _clamp? clamp(_pathPng, 0, _pathLength) : _pathPng; // print($"_pp = {_pp}, total = {_total}"); p = _pat.getPointDistance(_pp, i, p); @@ -420,7 +421,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons _prog_next = min(_prog_curr + _stepLen, 1); //Move forward _stepLen or _total (if less) stop at 1 _pathPng = _ratInv? 1 - _prog_curr : _prog_curr; - var _pp = _clamp? clamp(_pathPng, 0, 1) : _pathPng + _pp = _clamp? clamp(_pathPng, 0, 1) : _pathPng p = _pat.getPointRatio(_pp, i, p); wght = p[$ "weight"] ?? 1; @@ -428,7 +429,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons _nx = p.x; _ny = p.y; - + if(_total < _pathEnd) { //Do not wiggle the last point. var _d = point_direction(_ox, _oy, _nx, _ny); _nx += lengthdir_x(random1D(_sed + _sedIndex, -_wig, _wig), _d + 90); _sedIndex++; @@ -591,7 +592,6 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons var _ldata = line_data[i]; var _len = _ldata.length; - var _caps = []; var pxs = []; var dat = array_safe_get_fast(_pathData, i, noone); @@ -627,14 +627,20 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons if(_cap) { if(j == 1) { _d = _dir + 180; - _caps[0] = [ _oc, _ox, _oy, _ow / 2, _d - 90, _d ]; - _caps[1] = [ _oc, _ox, _oy, _ow / 2, _d, _d + 90 ]; + + draw_primitive_end(); + drawCaps( _cap, _oc, _ox * _aa, _oy * _aa, _ow / 2 * _aa, _d - 90, _d, _capP ); + drawCaps( _cap, _oc, _ox * _aa, _oy * _aa, _ow / 2 * _aa, _d, _d + 90, _capP ); + if(_useTex) draw_primitive_begin_texture(pr_trianglestrip, tex); else draw_primitive_begin(pr_trianglestrip); } if(j == m - 1) { _d = _dir; - _caps[2] = [ _nc, _nx, _ny, _nw / 2, _d - 90, _d ]; - _caps[3] = [ _nc, _nx, _ny, _nw / 2, _d, _d + 90 ]; + + draw_primitive_end(); + drawCaps( _cap, _nc, _nx * _aa, _ny * _aa, _nw / 2 * _aa, _d - 90, _d, _capP ); + drawCaps( _cap, _nc, _nx * _aa, _ny * _aa, _nw / 2 * _aa, _d, _d + 90, _capP ); + if(_useTex) draw_primitive_begin_texture(pr_trianglestrip, tex); else draw_primitive_begin(pr_trianglestrip); } } @@ -695,38 +701,14 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons _ow = _nw; _oc = _nc; } - if(j % 120 == 0) { draw_primitive_end(); - - if(_useTex) draw_primitive_begin_texture(pr_trianglestrip, tex); - else draw_primitive_begin(pr_trianglestrip); + if(_useTex) draw_primitive_begin_texture(pr_trianglestrip, tex); else draw_primitive_begin(pr_trianglestrip); } } draw_primitive_end(); - - for( var j = 0, m = array_length(_caps); j < m; j++ ) { - var _cps = _caps[j]; - var _cpx = _cps[1] * _aa; - var _cpy = _cps[2] * _aa; - var _cpr = _cps[3] * _aa; - - draw_set_color(_cps[0]); - - switch(_cap) { - case 1 : draw_circle_angle(_cpx, _cpy, _cpr, _cps[4], _cps[5], _capP); break; - case 2 : - var _x0 = _cpx + lengthdir_x(_cpr, _cps[4]); - var _y0 = _cpy + lengthdir_y(_cpr, _cps[4]); - var _x2 = _cpx + lengthdir_x(_cpr, _cps[5]); - var _y2 = _cpy + lengthdir_y(_cpr, _cps[5]); - - draw_triangle(_cpx - 1, _cpy - 1, _x0 - 1, _y0 - 1, _x2 - 1, _y2 - 1, false); - break; - } - } } if(_useTex) shader_reset(); @@ -747,8 +729,6 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons var points = lines[i]; if(array_length(points) < 2) continue; - var _caps = []; - draw_primitive_begin(pr_trianglestrip); random_set_seed(_sed + i); @@ -777,14 +757,20 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons if(_cap) { if(j == 1) { _d = _dir + 180; - _caps[0] = [ c_grey, _ox, _oy, _ow / 2, _d - 90, _d ]; - _caps[1] = [ c_grey, _ox, _oy, _ow / 2, _d, _d + 90 ]; + + draw_primitive_end(); + drawCaps( _cap, c_grey, _ox * _aa, _oy * _aa, _ow / 2 * _aa, _d - 90, _d, _capP ); + drawCaps( _cap, c_grey, _ox * _aa, _oy * _aa, _ow / 2 * _aa, _d, _d + 90, _capP ); + draw_primitive_begin(pr_trianglestrip); } if(j == m - 1) { _d = _dir; - _caps[2] = [ c_grey, _nx, _ny, _nw / 2, _d - 90, _d ]; - _caps[3] = [ c_grey, _nx, _ny, _nw / 2, _d, _d + 90 ]; + + draw_primitive_end(); + drawCaps( _cap, c_grey, _nx * _aa, _ny * _aa, _nw / 2 * _aa, _d - 90, _d, _capP ); + drawCaps( _cap, c_grey, _nx * _aa, _ny * _aa, _nw / 2 * _aa, _d, _d + 90, _capP ); + draw_primitive_begin(pr_trianglestrip); } } @@ -820,27 +806,6 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons } draw_primitive_end(); - - for( var j = 0, m = array_length(_caps); j < m; j++ ) { - var _cps = _caps[j]; - var _cpx = _cps[1]; - var _cpy = _cps[2]; - var _cpr = _cps[3]; - - draw_set_color(_cps[0]); - - switch(_cap) { - case 1 : draw_circle_angle(_cpx, _cpy, _cpr, _cps[4], _cps[5], _capP); break; - case 2 : - var _x0 = _cpx + lengthdir_x(_cpr, _cps[4]); - var _y0 = _cpy + lengthdir_y(_cpr, _cps[4]); - var _x2 = _cpx + lengthdir_x(_cpr, _cps[5]); - var _y2 = _cpy + lengthdir_y(_cpr, _cps[5]); - - draw_triangle(_cpx - 1, _cpy - 1, _x0 - 1, _y0 - 1, _x2 - 1, _y2 - 1, false); - break; - } - } } surface_reset_target(); @@ -849,4 +814,20 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons return [ _colorPass, _widthPass ]; } + + static drawCaps = function(_typ, _cpc, _cpx, _cpy, _cpr, _a0, _a1, _prec = 32) { + draw_set_color(_cpc); + + switch(_typ) { + case 1 : draw_circle_angle(_cpx, _cpy, _cpr, _a0, _a1, _prec); break; + case 2 : + var _x0 = _cpx + lengthdir_x(_cpr, _a0); + var _y0 = _cpy + lengthdir_y(_cpr, _a0); + var _x2 = _cpx + lengthdir_x(_cpr, _a1); + var _y2 = _cpy + lengthdir_y(_cpr, _a1); + + draw_triangle(_cpx - 1, _cpy - 1, _x0 - 1, _y0 - 1, _x2 - 1, _y2 - 1, false); + break; + } + } } \ No newline at end of file diff --git a/scripts/node_path/node_path.gml b/scripts/node_path/node_path.gml index e1f8b0328..88032cfad 100644 --- a/scripts/node_path/node_path.gml +++ b/scripts/node_path/node_path.gml @@ -12,8 +12,8 @@ enum _ANCHOR { function __vec2P(_x = 0, _y = _x, _w = 1) : __vec2(_x, _y) constructor { weight = _w; - static clone = function() /*=>*/ {return new __vec2P(x, y, weight)}; + static toString = function() { return $"[__vec2P] ({x}, {y} | {weight})"; } } function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { diff --git a/scripts/node_path_3d/node_path_3d.gml b/scripts/node_path_3d/node_path_3d.gml index 291458390..741f30252 100644 --- a/scripts/node_path_3d/node_path_3d.gml +++ b/scripts/node_path_3d/node_path_3d.gml @@ -13,6 +13,11 @@ enum _ANCHOR3 { amount } +function __vec3P(_x = 0, _y = _x, _z = _x, _w = 1) : __vec3(_x, _y, _z) constructor { + weight = _w; + static clone = function() /*=>*/ {return new __vec3P(x, y, z, weight)}; +} + function Node_Path_3D(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { name = "3D Path"; is_3D = NODE_3D.polygon; @@ -579,15 +584,14 @@ function Node_Path_3D(_x, _y, _group = noone) : Node(_x, _y, _group) constructor // surface_free(_surf); } - 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 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) { - if(out == undefined) out = new __vec3(); else { out.x = 0; out.y = 0; out.z = 0; } + if(out == undefined) out = new __vec3P(); else { out.x = 0; out.y = 0; out.z = 0; } if(array_empty(lengths)) return out; var _cKey = _dist; @@ -630,7 +634,7 @@ function Node_Path_3D(_x, _y, _group = noone) : Node(_x, _y, _group) constructor } - cached_pos[? _cKey] = new __vec3(out.x, out.y, out.z); + cached_pos[? _cKey] = new __vec3P(out.x, out.y, out.z); return out; } @@ -643,19 +647,19 @@ function Node_Path_3D(_x, _y, _group = noone) : Node(_x, _y, _group) constructor } static getPointSegment = function(_rat) { - if(array_empty(lengths)) return new __vec3(); + if(array_empty(lengths)) return new __vec3P(); var loop = getInputData(1); var ansize = array_length(inputs) - input_fix_len; - if(_rat < 0) return new __vec3(anchors[0][0], anchors[0][1], anchors[0][2]); + if(_rat < 0) return new __vec3P(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]); + if(_i1 >= ansize && !loop) return new __vec3P(anchors[ansize - 1][0], anchors[ansize - 1][1], anchors[ansize - 1][2]); var _a0 = anchors[_i0]; var _a1 = anchors[_i1]; @@ -673,7 +677,7 @@ function Node_Path_3D(_x, _y, _group = noone) : Node(_x, _y, _group) constructor } - return new __vec3(px, py, pz); + return new __vec3P(px, py, pz); } static update = function(frame = CURRENT_FRAME) { diff --git a/scripts/node_path_3d_camera/node_path_3d_camera.gml b/scripts/node_path_3d_camera/node_path_3d_camera.gml new file mode 100644 index 000000000..6693a96fb --- /dev/null +++ b/scripts/node_path_3d_camera/node_path_3d_camera.gml @@ -0,0 +1,289 @@ +function Node_Path_3D_Camera(_x, _y, _group = noone) : Node_3D_Object(_x, _y, _group) constructor { + name = "3D Path Camera"; + batch_output = true; + + object = new __3dCamera_object(); + camera = new __3dCamera(); + lookat = new __3dGizmoSphere(0.5, c_ltgray, 1); + lookLine = noone; + lookRad = new __3dGizmoCircleZ(0.5, c_yellow, 0.5); + + w = 128; + var i = in_d3d; + + setDimension(96, 48); + + newInput(i+0, nodeValue_Int("FOV", self, 60 )) + .setDisplay(VALUE_DISPLAY.slider, { range: [ 10, 90, 0.1 ] }); + + newInput(i+1, nodeValue_Enum_Button("Projection", self, 1 , [ "Perspective", "Orthographic" ])); + + newInput(i+2, nodeValue_PathNode("Path", self, noone )) + .setVisible(true, true); + + newInput(i+3, nodeValue_Float("Orthographic Scale", self, 0.5 )) + .setDisplay(VALUE_DISPLAY.slider, { range: [ 0.01, 4, 0.01 ] }); + + newInput(i+4, nodeValue_Enum_Scroll("Postioning Mode", self, 2, [ "Position + Rotation", "Position + Lookat", "Lookat + Rotation" ] )); + + newInput(i+5, nodeValue_Vec3("Lookat Position", self, [ 0, 0, 0 ] )); + + newInput(i+6, nodeValue_Rotation("Roll", self, 0)); + + newInput(i+7, nodeValue_Rotation("Horizontal Angle", self, 45 )); + + newInput(i+8, nodeValue_Float("Vertical Angle", self, 30 )) + .setDisplay(VALUE_DISPLAY.slider, { range: [0, 90, 0.1] }); + + newInput(i+9, nodeValue_Float("Distance", self, 4 )); + + newInput(i+10, nodeValue_Dimension(self)); + + newInput(i+11, nodeValue_Bool("Apply depth to weight", self, false)); + + newInput(i+12, nodeValue_Vec2("Depth range", self, [ 0.1, 100 ])); + + in_cam = array_length(inputs); + + newOutput(0, nodeValue_Output("Rendered", self, VALUE_TYPE.pathnode, self )); + + input_display_list = [ i+2, i+10, + ["Transform", false], i+4, 0, 1, i+5, i+6, i+7, i+8, i+9, + ["Camera", false], i+1, i+0, i+3, + ["Output", false], i+11, i+12, + ]; + + tool_lookat = new NodeTool( "Move Target", THEME.tools_3d_transform_object ); + + #region current data + cached_pos = ds_map_create(); + + is_path = false; + + curr_pos = noone; + curr_rot = noone; + + curr_fov = noone; + curr_proj = noone; + curr_path = noone; + curr_orts = noone; + + curr_posm = noone; + curr_look = noone; + curr_roll = noone; + curr_hAng = noone; + curr_vAng = noone; + curr_dist = noone; + curr_scal = [ 1, 1 ]; + curr_weig = false; + curr_dept = [ 1, 1 ]; + + curr_qi1 = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(0, 1, 0), 90); + curr_qi2 = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), -90); + curr_qi3 = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90); + #endregion + + ////- Preview + + static getToolSettings = function() { return curr_posm == 0? tool_settings : []; } + + static drawOverlay3D = function(active, params, _mx, _my, _snx, _sny, _panel) { + var preObj = getPreviewObjects(); + if(array_empty(preObj)) return; + preObj = preObj[0]; + + var _pos = inputs[0].getValue(,,, true); + var _vpos = new __vec3( _pos[0], _pos[1], _pos[2] ); + + if(isUsingTool("Transform")) drawGizmoPosition(0, preObj, _vpos, active, params, _mx, _my, _snx, _sny, _panel); + else if(isUsingTool("Rotate")) drawGizmoRotation(1, preObj, _vpos, active, params, _mx, _my, _snx, _sny, _panel); + else if(isUsingTool("Move Target")) { + var _lkpos = inputs[in_d3d + 5].getValue(,,, true); + var _lkvpos = new __vec3( _lkpos[0], _lkpos[1], _lkpos[2] ); + + drawGizmoPosition(in_d3d + 5, noone, _lkvpos, active, params, _mx, _my, _snx, _sny, _panel); + } + + if(drag_axis != noone && mouse_release(mb_left)) { + drag_axis = noone; + UNDO_HOLDING = false; + } + } + + ////- Path + + static getLineCount = function( ) /*=>*/ {return is_path? curr_path.getLineCount() : 1}; + static getSegmentCount = function(i=0) /*=>*/ {return is_path? curr_path.getSegmentCount(i) : 0}; + static getLength = function(i=0) /*=>*/ {return is_path? curr_path.getLength(i) : 0}; + static getAccuLength = function(i=0) /*=>*/ {return is_path? curr_path.getAccuLength(i) : []}; + static getBoundary = function(i=0) /*=>*/ {return is_path? curr_path.getBoundary(i) : new BoundingBox( 0, 0, 1, 1 )}; + + static getPointRatio = function(_rat, ind = 0, out = undefined) { + if(out == undefined) out = new __vec2P(); else { out.x = 0; out.y = 0; } + + var _cKey = $"{string_format(_rat, 0, 6)},{ind}"; + if(ds_map_exists(cached_pos, _cKey)) { + var _p = cached_pos[? _cKey]; + out.x = _p.x; + out.y = _p.y; + out.weight = _p.weight; + return out; + } + + if(!is_path) return out; + + var _p = curr_path.getPointRatio(_rat, ind); + var _w = _p.weight; + var _v = camera.worldPointToViewPoint(_p); + + out.x = _v.x * curr_scal[0] / 2; + out.y = _v.y * curr_scal[1] / 2; + out.weight = curr_weig? _v.z : _p.weight; + + cached_pos[? _cKey] = new __vec2P(out.x, out.y, out.weight); + + return out; + } + + static getPointDistance = function(_dist, ind = 0, out = undefined) { return getPointRatio(_dist / getLength(), ind, out); } + + ////- Update + + static onValueUpdate = function(index) { if(index == in_d3d + 4) PANEL_PREVIEW.tool_current = noone; } + + static step = function() { + inputs[in_d3d + 0].setVisible(curr_proj == 0); + inputs[in_d3d + 3].setVisible(curr_proj == 1); + + inputs[0].setVisible(curr_posm == 0 || curr_posm == 1); + inputs[1].setVisible(curr_posm == 0); + inputs[in_d3d + 5].setVisible(curr_posm == 1 || curr_posm == 2); + inputs[in_d3d + 6].setVisible(curr_posm == 1); + inputs[in_d3d + 7].setVisible(curr_posm == 2); + inputs[in_d3d + 8].setVisible(curr_posm == 2); + inputs[in_d3d + 9].setVisible(curr_posm == 2); + + switch(curr_posm) { + case 0 : + tools = [ tool_pos, tool_rot ]; + break; + + case 1 : + tools = [ tool_pos, tool_lookat ]; + tool_attribute.context = 1; + break; + + case 2 : + tools = [ tool_lookat ]; + tool_attribute.context = 1; + break; + } + } + + static preProcessData = function(_data) /*=>*/ {} + static submitShadow = function() /*=>*/ {} + static submitShader = function() /*=>*/ {} + + static processData = function(_outData, _data, _output_index, _array_index = 0) { + #region data + curr_pos = _data[0]; + curr_rot = _data[1]; + + curr_fov = _data[in_d3d + 0]; + curr_proj = _data[in_d3d + 1]; + curr_path = _data[in_d3d + 2]; + curr_orts = _data[in_d3d + 3]; + + curr_posm = _data[in_d3d + 4]; + curr_look = _data[in_d3d + 5]; + curr_roll = _data[in_d3d + 6]; + curr_hAng = _data[in_d3d + 7]; + curr_vAng = _data[in_d3d + 8]; + curr_dist = _data[in_d3d + 9]; + curr_scal = _data[in_d3d +10]; + curr_weig = _data[in_d3d +11]; + curr_dept = _data[in_d3d +12]; + #endregion + + switch(curr_posm) { // ++++ camera positioning ++++ + case 0 : + camera.useFocus = false; + camera.position.set(curr_pos); + camera.rotation.set(curr_rot[0], curr_rot[1], curr_rot[2], curr_rot[3]); + break; + + case 1 : + camera.useFocus = true; + camera.position.set(curr_pos); + camera.focus.set(curr_look); + camera.up.set(0, 0, -1); + + var _for = camera.focus.subtract(camera.position); + if(!_for.isZero()) camera.rotation = new BBMOD_Quaternion().FromLookRotation(_for, camera.up).Mul(curr_qi1).Mul(curr_qi2); + + lookat.transform.position.set(curr_look); + lookLine = new __3dGizmoLineDashed(camera.position, camera.focus, 0.25, c_gray, 1); + break; + + case 2 : + camera.useFocus = true; + camera.focus.set(curr_look); + camera.setFocusAngle(curr_hAng, curr_vAng, curr_dist); + camera.setCameraLookRotate(); + camera.up = camera.getUp()._multiply(-1); + + var _for = camera.focus.subtract(camera.position); + if(!_for.isZero()) camera.rotation = new BBMOD_Quaternion().FromLookRotation(_for, camera.up.multiply(-1)).Mul(curr_qi1).Mul(curr_qi3); + + lookat.transform.position.set(curr_look); + lookLine = new __3dGizmoLineDashed(camera.position, camera.focus, 0.25, c_gray, 1); + + var _camRad = camera.position.subtract(camera.focus); + var _rad = point_distance(0, 0, _camRad.x, _camRad.y) * 2; + lookRad.transform.scale.set(_rad, _rad, 1); + lookRad.transform.position.set(new __vec3(camera.focus.x, camera.focus.y, camera.position.z)); + break; + } + + #region camera view project + object.transform.position.set(camera.position); + object.transform.rotation = camera.rotation.Clone(); + + camera.projection = curr_proj; + camera.setViewFov(curr_fov, curr_dept[0], curr_dept[1]); + + if(curr_proj == 0) camera.setViewSize(curr_scal[0], curr_scal[1]); + else if(curr_proj == 1) camera.setViewSize(1 / curr_orts, curr_scal[0] / curr_scal[1] / curr_orts); + + camera.setMatrix(); + #endregion + + is_path = curr_path != noone && struct_has(curr_path, "getPointRatio"); + ds_map_clear(cached_pos); + return self; + } + + ////- Draw + + static getGraphPreviewSurface = function() { return noone; } + + static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { + var bbox = drawGetBbox(xx, yy, _s); + draw_sprite_bbox_uniform(s_node_path_3d, 0, bbox); + } + + static getPreviewObject = function() { return noone; } + + static getPreviewObjects = function() { + switch(curr_posm) { + case 0 : return [ object ]; + case 1 : return [ object, lookat, lookLine ]; + case 2 : return [ object, lookat, lookLine, lookRad ]; + } + + return [ object ]; + } + + static getPreviewObjectOutline = function() { return isUsingTool("Move Target")? [ lookat ] : [ object ]; } + +} \ No newline at end of file diff --git a/scripts/node_path_3d_camera/node_path_3d_camera.yy b/scripts/node_path_3d_camera/node_path_3d_camera.yy new file mode 100644 index 000000000..fd62eb3e1 --- /dev/null +++ b/scripts/node_path_3d_camera/node_path_3d_camera.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"v1", + "%Name":"node_path_3d_camera", + "isCompatibility":false, + "isDnD":false, + "name":"node_path_3d_camera", + "parent":{ + "name":"path", + "path":"folders/nodes/data/value/path.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file