Reflection-driven target dropdowns (SelectNode3D, HasCondition), Brain activeNode generalization with auto-restart, TweenMaterial slot-ownership fix, Behavior/ file reorg into Core/Movements/Receptors, LockOn/CameraLocker updates
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
e2a1171e5e
commit
ba487e326c
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="BehaviorBranch.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
showgrid="false"
|
||||
inkscape:zoom="10.363534"
|
||||
inkscape:cx="4.728117"
|
||||
inkscape:cy="5.789531"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
id="rect401"
|
||||
style="color:#000000;fill:#1de3ab;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none;paint-order:markers stroke fill"
|
||||
d="m 1.319336,0.0888674 c -0.674094,0 -1.248047,0.571999 -1.248047,1.246093 v 2.511719 h 2 V 2.0888674 H 3.81543 v -2 z m 10.84375,0 v 2 h 1.765625 v 1.757812 h 2 v -2.511719 c 0,-0.674094 -0.573952,-1.246093 -1.248047,-1.246093 z M 0.071289,12.194336 v 2.46875 c 0,0.674094 0.573953,1.248047 1.248047,1.248047 H 3.81543 v -2 H 2.071289 v -1.716797 z m 13.857422,0 v 1.716797 h -1.765625 v 2 h 2.517578 c 0.674095,0 1.248047,-0.573953 1.248047,-1.248047 v -2.46875 z" />
|
||||
<path
|
||||
id="path1539"
|
||||
style="font-weight:bold;font-size:15.624px;line-height:1;font-family:'MS Outlook';-inkscape-font-specification:'MS Outlook Bold';fill:#1de3ab;fill-opacity:1;stroke-width:0.29295;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill"
|
||||
d="m 51.913678,-11.337595 c -0.708287,0 -1.359413,0.08855 -1.953125,0.265625 -0.593711,0.177072 -1.145866,0.406268 -1.65625,0.6875 l 0.828125,1.671875 c 0.447888,-0.229152 0.885445,-0.411467 1.3125,-0.546875 0.427056,-0.135408 0.859404,-0.203125 1.296875,-0.203125 0.437472,0 0.776058,0.088553 1.015625,0.265625 0.249984,0.177072 0.373047,0.427104 0.373047,0.75 0,0.333312 -0.10418,0.625016 -0.3125,0.875 -0.197904,0.239568 -0.529327,0.526063 -0.998047,0.859375 -0.531215,0.385392 -0.906264,0.76044 -1.125,1.125 -0.218735,0.354144 -0.328125,0.786492 -0.328125,1.296875 v 0.5625002 h 2.015625 V -4.181345 c 0,-0.20832 0.02605,-0.385426 0.07813,-0.53125 0.0625,-0.15624 0.171885,-0.307301 0.328125,-0.453125 0.166656,-0.15624 0.404318,-0.348973 0.716797,-0.578125 0.406224,-0.291648 0.744809,-0.572934 1.015625,-0.84375 0.270816,-0.270816 0.473967,-0.56252 0.609375,-0.875 0.135408,-0.31248 0.203125,-0.682319 0.203125,-1.109375 0,-0.802031 -0.302122,-1.463576 -0.90625,-1.984375 -0.593711,-0.520799 -1.430409,-0.78125 -2.513672,-0.78125 z m -0.453125,8.9218752 c -0.374975,0 -0.692725,0.09897 -0.953125,0.296875 -0.260399,0.187488 -0.390625,0.520864 -0.390625,1 0,0.45830298 0.130226,0.79167998 0.390625,0.99999998 0.2604,0.197904 0.57815,0.296875 0.953125,0.296875 0.36456,0 0.677101,-0.09897 0.9375,-0.296875 0.2604,-0.20832 0.390625,-0.541697 0.390625,-0.99999998 0,-0.479136 -0.130225,-0.812512 -0.390625,-1 -0.260399,-0.197904 -0.57294,-0.296875 -0.9375,-0.296875 z" />
|
||||
<g
|
||||
id="g96554"
|
||||
transform="matrix(0.75262015,0,0,0.75262015,1.9507002,2.0121453)">
|
||||
<ellipse
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:none;stroke-width:7.27012;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="path92548"
|
||||
cx="5.1813359"
|
||||
cy="8.1338291"
|
||||
rx="4.3999071"
|
||||
ry="5.1538987" />
|
||||
<ellipse
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:none;stroke-width:7.27012;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="circle92550"
|
||||
cx="10.589555"
|
||||
cy="8.1338291"
|
||||
rx="4.3999071"
|
||||
ry="5.1538987" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
|
|
@ -0,0 +1,43 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://whc152vj4786"
|
||||
path="res://.godot/imported/BehaviorBranch.svg-2479d9ece5118d365ff6adf5a4a78745.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/rokojori_action_library/Icons/BehaviorBranch.svg"
|
||||
dest_files=["res://.godot/imported/BehaviorBranch.svg-2479d9ece5118d365ff6adf5a4a78745.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="BehaviorSequence.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
showgrid="false"
|
||||
inkscape:zoom="20.727068"
|
||||
inkscape:cx="-0.38596872"
|
||||
inkscape:cy="6.0307613"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
id="path1539"
|
||||
style="font-weight:bold;font-size:15.624px;line-height:1;font-family:'MS Outlook';-inkscape-font-specification:'MS Outlook Bold';fill:#1de3ab;fill-opacity:1;stroke-width:0.29295;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill"
|
||||
d="m 51.913678,-11.337595 c -0.708287,0 -1.359413,0.08855 -1.953125,0.265625 -0.593711,0.177072 -1.145866,0.406268 -1.65625,0.6875 l 0.828125,1.671875 c 0.447888,-0.229152 0.885445,-0.411467 1.3125,-0.546875 0.427056,-0.135408 0.859404,-0.203125 1.296875,-0.203125 0.437472,0 0.776058,0.088553 1.015625,0.265625 0.249984,0.177072 0.373047,0.427104 0.373047,0.75 0,0.333312 -0.10418,0.625016 -0.3125,0.875 -0.197904,0.239568 -0.529327,0.526063 -0.998047,0.859375 -0.531215,0.385392 -0.906264,0.76044 -1.125,1.125 -0.218735,0.354144 -0.328125,0.786492 -0.328125,1.296875 v 0.5625002 h 2.015625 V -4.181345 c 0,-0.20832 0.02605,-0.385426 0.07813,-0.53125 0.0625,-0.15624 0.171885,-0.307301 0.328125,-0.453125 0.166656,-0.15624 0.404318,-0.348973 0.716797,-0.578125 0.406224,-0.291648 0.744809,-0.572934 1.015625,-0.84375 0.270816,-0.270816 0.473967,-0.56252 0.609375,-0.875 0.135408,-0.31248 0.203125,-0.682319 0.203125,-1.109375 0,-0.802031 -0.302122,-1.463576 -0.90625,-1.984375 -0.593711,-0.520799 -1.430409,-0.78125 -2.513672,-0.78125 z m -0.453125,8.9218752 c -0.374975,0 -0.692725,0.09897 -0.953125,0.296875 -0.260399,0.187488 -0.390625,0.520864 -0.390625,1 0,0.45830298 0.130226,0.79167998 0.390625,0.99999998 0.2604,0.197904 0.57815,0.296875 0.953125,0.296875 0.36456,0 0.677101,-0.09897 0.9375,-0.296875 0.2604,-0.20832 0.390625,-0.541697 0.390625,-0.99999998 0,-0.479136 -0.130225,-0.812512 -0.390625,-1 -0.260399,-0.197904 -0.57294,-0.296875 -0.9375,-0.296875 z" />
|
||||
<g
|
||||
id="g102401"
|
||||
transform="translate(0.15792213,0.18000243)">
|
||||
<g
|
||||
id="g96554"
|
||||
transform="matrix(0.59356973,0,0,0.59356973,6.7183722,-1.2770906)">
|
||||
<ellipse
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:none;stroke-width:7.27012;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="path92548"
|
||||
cx="5.1813359"
|
||||
cy="8.1338291"
|
||||
rx="4.3999071"
|
||||
ry="5.1538987" />
|
||||
<ellipse
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:none;stroke-width:7.27012;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="circle92550"
|
||||
cx="10.589555"
|
||||
cy="8.1338291"
|
||||
rx="4.3999071"
|
||||
ry="5.1538987" />
|
||||
</g>
|
||||
<g
|
||||
id="g102393"
|
||||
transform="matrix(1.0857792,0,0,1.0857792,-5.1777633,-1.0374856)">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:none;fill-opacity:1;stroke:#f7b200;stroke-width:1.93888;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||
id="path120048"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="-8.2018356"
|
||||
sodipodi:cy="-2.1710742"
|
||||
sodipodi:r1="7.9176526"
|
||||
sodipodi:r2="4.7268386"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.9424778"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m -8.2018354,-10.088727 2.7783658,4.0935601 4.75176914,1.3774037 -3.03464454,3.90736248 0.1583886,4.94484222 -4.6538792,-1.6786771 -4.6538794,1.6786768 0.158389,-4.94484188 -3.034645,-3.90736292 4.751769,-1.3774033 z"
|
||||
inkscape:transform-center-y="-0.91462472"
|
||||
transform="matrix(0.61233589,0,0,0.61233589,15.058621,11.720562)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#f7b200;fill-opacity:1;stroke:none;stroke-width:2.56963;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill"
|
||||
id="path855"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="-8.2018356"
|
||||
sodipodi:cy="-2.1710742"
|
||||
sodipodi:r1="7.9176526"
|
||||
sodipodi:r2="4.5684857"
|
||||
sodipodi:arg1="-1.5707963"
|
||||
sodipodi:arg2="-0.94247777"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m -8.2018354,-10.088727 2.6852884,4.2216703 4.84484654,1.2492935 -3.18524704,3.85842889 0.3089911,4.99377581 -4.6538794,-1.8370299 -4.6538792,1.8370296 0.308991,-4.99377573 -3.185247,-3.85842907 4.844847,-1.2492932 z"
|
||||
inkscape:transform-center-y="-0.30053938"
|
||||
transform="matrix(0.2012094,0,0,0.2012094,11.471952,11.056661)" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
|
|
@ -0,0 +1,43 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c0bg8q1qhta8d"
|
||||
path="res://.godot/imported/BehaviorSequence.svg-e83c81b196d7953a5989711a8e3762a9.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/rokojori_action_library/Icons/BehaviorSequence.svg"
|
||||
dest_files=["res://.godot/imported/BehaviorSequence.svg-e83c81b196d7953a5989711a8e3762a9.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="Brain.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8">
|
||||
<linearGradient
|
||||
inkscape:collect="never"
|
||||
id="linearGradient114405">
|
||||
<stop
|
||||
style="stop-color:#c7169f;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop114401" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop114403" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="never"
|
||||
xlink:href="#linearGradient114405"
|
||||
id="radialGradient114407"
|
||||
cx="8"
|
||||
cy="8"
|
||||
fx="8"
|
||||
fy="8"
|
||||
r="8"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.6640625"
|
||||
inkscape:cx="-1.9104478"
|
||||
inkscape:cy="2.45629"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
id="path115146"
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:#000000;stroke-width:3.4861;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
d="M 5.8309076,3.8548992 C 5.538504,3.8549729 5.1211737,3.9611482 5.1194631,4.2639761 4.9425069,3.9804441 4.4185358,4.1843523 4.1624382,4.3457257 3.055579,5.043185 2.3031667,6.4126815 2.3031341,7.9880008 c 2.7e-5,1.3064477 0.7226271,3.2917552 1.5534037,3.0616162 -0.1864958,0.459405 1.1412645,1.071276 1.9743698,1.071486 0.7865919,-0.0031 1.5497544,0.176332 2.1682659,-0.392928 0.6189579,0.569668 1.3827609,0.390289 2.1699195,0.392928 1.088731,-2.75e-4 2.642337,-0.900404 2.472966,-1.776222 0.564685,0.163911 1.054786,-1.3498657 1.054807,-2.3568802 C 13.696842,6.8660251 13.315168,5.8484548 12.695608,5.1037242 12.488198,4.8544121 11.969439,4.4423021 11.708732,4.6418417 11.782246,4.2189562 10.839029,3.8550683 10.169093,3.8548992 9.3845365,3.8583179 8.6233284,3.8184841 8.005789,4.385337 7.3851242,3.815628 6.6194341,3.8552965 5.8309076,3.8548992 Z"
|
||||
sodipodi:nodetypes="ccscccccccscccc" />
|
||||
<path
|
||||
id="rect401"
|
||||
style="color:#000000;fill:#1de3ab;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none;paint-order:markers stroke fill"
|
||||
d="m 44.929225,-13.918847 c -0.674094,0 -1.248047,0.571999 -1.248047,1.246093 v 2.511719 h 2 v -1.757812 h 1.744141 v -2 z m 10.84375,0 v 2 H 57.5386 v 1.757812 h 2 v -2.511719 c 0,-0.674094 -0.573952,-1.246093 -1.248047,-1.246093 z M 43.681178,-1.8133788 v 2.46874998 c 0,0.67409402 0.573953,1.24804702 1.248047,1.24804702 h 2.496094 V -0.09658182 H 45.681178 V -1.8133788 Z m 13.857422,0 v 1.71679698 H 55.772975 V 1.9034182 h 2.517578 c 0.674095,0 1.248047,-0.573953 1.248047,-1.24804702 V -1.8133788 Z" />
|
||||
<path
|
||||
id="path1539"
|
||||
style="font-weight:bold;font-size:15.624px;line-height:1;font-family:'MS Outlook';-inkscape-font-specification:'MS Outlook Bold';fill:#1de3ab;fill-opacity:1;stroke-width:0.29295;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill"
|
||||
d="m 51.913678,-11.337595 c -0.708287,0 -1.359413,0.08855 -1.953125,0.265625 -0.593711,0.177072 -1.145866,0.406268 -1.65625,0.6875 l 0.828125,1.671875 c 0.447888,-0.229152 0.885445,-0.411467 1.3125,-0.546875 0.427056,-0.135408 0.859404,-0.203125 1.296875,-0.203125 0.437472,0 0.776058,0.088553 1.015625,0.265625 0.249984,0.177072 0.373047,0.427104 0.373047,0.75 0,0.333312 -0.10418,0.625016 -0.3125,0.875 -0.197904,0.239568 -0.529327,0.526063 -0.998047,0.859375 -0.531215,0.385392 -0.906264,0.76044 -1.125,1.125 -0.218735,0.354144 -0.328125,0.786492 -0.328125,1.296875 v 0.5625002 h 2.015625 V -4.181345 c 0,-0.20832 0.02605,-0.385426 0.07813,-0.53125 0.0625,-0.15624 0.171885,-0.307301 0.328125,-0.453125 0.166656,-0.15624 0.404318,-0.348973 0.716797,-0.578125 0.406224,-0.291648 0.744809,-0.572934 1.015625,-0.84375 0.270816,-0.270816 0.473967,-0.56252 0.609375,-0.875 0.135408,-0.31248 0.203125,-0.682319 0.203125,-1.109375 0,-0.802031 -0.302122,-1.463576 -0.90625,-1.984375 -0.593711,-0.520799 -1.430409,-0.78125 -2.513672,-0.78125 z m -0.453125,8.9218752 c -0.374975,0 -0.692725,0.09897 -0.953125,0.296875 -0.260399,0.187488 -0.390625,0.520864 -0.390625,1 0,0.45830298 0.130226,0.79167998 0.390625,0.99999998 0.2604,0.197904 0.57815,0.296875 0.953125,0.296875 0.36456,0 0.677101,-0.09897 0.9375,-0.296875 0.2604,-0.20832 0.390625,-0.541697 0.390625,-0.99999998 0,-0.479136 -0.130225,-0.812512 -0.390625,-1 -0.260399,-0.197904 -0.57294,-0.296875 -0.9375,-0.296875 z" />
|
||||
<path
|
||||
id="path92548"
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:#fbfbfb;stroke-width:1.74305;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
d="M 5.8309076,3.8548992 C 5.538504,3.8549729 5.0729276,4.0817634 5.4330627,5.1324058 4.9666299,4.1010593 4.4185358,4.1843523 4.1624382,4.3457257 3.055579,5.043185 2.3031667,6.4126815 2.3031341,7.9880008 c 2.7e-5,1.3064477 0.8432423,3.1952632 2.1564798,2.3379252 -0.8619411,1.158973 0.5381884,1.794967 1.3712937,1.795177 0.7865919,-0.0031 1.863354,0.176332 2.1923889,-1.116619 0.2329892,1.269236 1.3586379,1.11398 2.1457965,1.116619 1.088731,-2.75e-4 2.618214,-1.141634 1.894013,-2.2345599 0.974777,0.6704949 1.633739,-0.8915278 1.63376,-1.8985423 C 13.696842,6.8660251 13.315168,5.8484548 12.695608,5.1037242 12.488198,4.8544121 12.1383,4.2493177 11.346886,4.8830722 11.951107,3.8571105 10.736684,3.7015502 10.066748,3.7013811 8.7534064,3.7047998 8.2763238,4.3033695 8.1022812,5.1090284 7.6692497,3.8740742 7.1482187,3.6164905 5.8309076,3.8548992 Z"
|
||||
sodipodi:nodetypes="ccscccccccscccc" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
|
|
@ -0,0 +1,43 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ddywe4nqkppim"
|
||||
path="res://.godot/imported/Brain.svg-22061c8f9edbd3ff520fcf62d8a1f665.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/rokojori_action_library/Icons/Brain.svg"
|
||||
dest_files=["res://.godot/imported/Brain.svg-22061c8f9edbd3ff520fcf62d8a1f665.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="BrainControl.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
showgrid="false"
|
||||
inkscape:zoom="20.727068"
|
||||
inkscape:cx="1.8333515"
|
||||
inkscape:cy="4.7763631"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
id="rect401"
|
||||
style="color:#000000;fill:#1de3ab;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none;paint-order:markers stroke fill"
|
||||
d="m 44.929225,-13.918847 c -0.674094,0 -1.248047,0.571999 -1.248047,1.246093 v 2.511719 h 2 v -1.757812 h 1.744141 v -2 z m 10.84375,0 v 2 H 57.5386 v 1.757812 h 2 v -2.511719 c 0,-0.674094 -0.573952,-1.246093 -1.248047,-1.246093 z M 43.681178,-1.8133788 v 2.46874998 c 0,0.67409402 0.573953,1.24804702 1.248047,1.24804702 h 2.496094 V -0.09658182 H 45.681178 V -1.8133788 Z m 13.857422,0 v 1.71679698 H 55.772975 V 1.9034182 h 2.517578 c 0.674095,0 1.248047,-0.573953 1.248047,-1.24804702 V -1.8133788 Z" />
|
||||
<path
|
||||
id="path1539"
|
||||
style="font-weight:bold;font-size:15.624px;line-height:1;font-family:'MS Outlook';-inkscape-font-specification:'MS Outlook Bold';fill:#1de3ab;fill-opacity:1;stroke-width:0.29295;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill"
|
||||
d="m 51.913678,-11.337595 c -0.708287,0 -1.359413,0.08855 -1.953125,0.265625 -0.593711,0.177072 -1.145866,0.406268 -1.65625,0.6875 l 0.828125,1.671875 c 0.447888,-0.229152 0.885445,-0.411467 1.3125,-0.546875 0.427056,-0.135408 0.859404,-0.203125 1.296875,-0.203125 0.437472,0 0.776058,0.088553 1.015625,0.265625 0.249984,0.177072 0.373047,0.427104 0.373047,0.75 0,0.333312 -0.10418,0.625016 -0.3125,0.875 -0.197904,0.239568 -0.529327,0.526063 -0.998047,0.859375 -0.531215,0.385392 -0.906264,0.76044 -1.125,1.125 -0.218735,0.354144 -0.328125,0.786492 -0.328125,1.296875 v 0.5625002 h 2.015625 V -4.181345 c 0,-0.20832 0.02605,-0.385426 0.07813,-0.53125 0.0625,-0.15624 0.171885,-0.307301 0.328125,-0.453125 0.166656,-0.15624 0.404318,-0.348973 0.716797,-0.578125 0.406224,-0.291648 0.744809,-0.572934 1.015625,-0.84375 0.270816,-0.270816 0.473967,-0.56252 0.609375,-0.875 0.135408,-0.31248 0.203125,-0.682319 0.203125,-1.109375 0,-0.802031 -0.302122,-1.463576 -0.90625,-1.984375 -0.593711,-0.520799 -1.430409,-0.78125 -2.513672,-0.78125 z m -0.453125,8.9218752 c -0.374975,0 -0.692725,0.09897 -0.953125,0.296875 -0.260399,0.187488 -0.390625,0.520864 -0.390625,1 0,0.45830298 0.130226,0.79167998 0.390625,0.99999998 0.2604,0.197904 0.57815,0.296875 0.953125,0.296875 0.36456,0 0.677101,-0.09897 0.9375,-0.296875 0.2604,-0.20832 0.390625,-0.541697 0.390625,-0.99999998 0,-0.479136 -0.130225,-0.812512 -0.390625,-1 -0.260399,-0.197904 -0.57294,-0.296875 -0.9375,-0.296875 z" />
|
||||
<path
|
||||
id="path92548"
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:none;stroke-width:1.55798;stroke-linecap:square;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
d="M 6.0887647,4.3576783 A 3.1098158,3.6427305 0 0 0 2.9786072,8.0006902 3.1098158,3.6427305 0 0 0 6.0887647,11.642322 3.1098158,3.6427305 0 0 0 8.0006904,10.862367 3.1098158,3.6427305 0 0 0 9.9112359,11.642322 3.1098158,3.6427305 0 0 0 13.021393,8.0006902 3.1098158,3.6427305 0 0 0 9.9112359,4.3576783 3.1098158,3.6427305 0 0 0 8.0062121,5.1321117 3.1098158,3.6427305 0 0 0 6.0887647,4.3576783 Z" />
|
||||
<path
|
||||
id="path103023"
|
||||
style="color:#000000;fill:#ffb801;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none;paint-order:markers stroke fill"
|
||||
d="m 1.319336,0.088867 c -0.674094,0 -1.248047,0.571999 -1.248047,1.246093 v 2.511719 h 2 V 2.088867 H 3.81543 v -2 z m 10.84375,0 v 2 h 1.765625 v 1.757812 h 2 V 1.33496 c 0,-0.674094 -0.573952,-1.246093 -1.248047,-1.246093 z M 0.071289,12.194336 v 2.468749 c 0,0.674095 0.573953,1.248048 1.248047,1.248048 H 3.81543 V 13.911132 H 2.071289 v -1.716796 z m 13.857422,0 v 1.716796 h -1.765625 v 2.000001 h 2.517578 c 0.674095,0 1.248047,-0.573953 1.248047,-1.248048 v -2.468749 z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
|
|
@ -0,0 +1,43 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c37yfx3ryvoxu"
|
||||
path="res://.godot/imported/BrainControl.svg-0da1cfbf5e1e82c6dfa220b6df44195a.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/rokojori_action_library/Icons/BrainControl.svg"
|
||||
dest_files=["res://.godot/imported/BrainControl.svg-0da1cfbf5e1e82c6dfa220b6df44195a.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="Receptor.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
showgrid="false"
|
||||
inkscape:zoom="29.3125"
|
||||
inkscape:cx="9.108742"
|
||||
inkscape:cy="11.633262"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
id="path1539"
|
||||
style="font-weight:bold;font-size:15.624px;line-height:1;font-family:'MS Outlook';-inkscape-font-specification:'MS Outlook Bold';fill:#1de3ab;fill-opacity:1;stroke-width:0.29295;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill"
|
||||
d="m 51.913678,-11.337595 c -0.708287,0 -1.359413,0.08855 -1.953125,0.265625 -0.593711,0.177072 -1.145866,0.406268 -1.65625,0.6875 l 0.828125,1.671875 c 0.447888,-0.229152 0.885445,-0.411467 1.3125,-0.546875 0.427056,-0.135408 0.859404,-0.203125 1.296875,-0.203125 0.437472,0 0.776058,0.088553 1.015625,0.265625 0.249984,0.177072 0.373047,0.427104 0.373047,0.75 0,0.333312 -0.10418,0.625016 -0.3125,0.875 -0.197904,0.239568 -0.529327,0.526063 -0.998047,0.859375 -0.531215,0.385392 -0.906264,0.76044 -1.125,1.125 -0.218735,0.354144 -0.328125,0.786492 -0.328125,1.296875 v 0.5625002 h 2.015625 V -4.181345 c 0,-0.20832 0.02605,-0.385426 0.07813,-0.53125 0.0625,-0.15624 0.171885,-0.307301 0.328125,-0.453125 0.166656,-0.15624 0.404318,-0.348973 0.716797,-0.578125 0.406224,-0.291648 0.744809,-0.572934 1.015625,-0.84375 0.270816,-0.270816 0.473967,-0.56252 0.609375,-0.875 0.135408,-0.31248 0.203125,-0.682319 0.203125,-1.109375 0,-0.802031 -0.302122,-1.463576 -0.90625,-1.984375 -0.593711,-0.520799 -1.430409,-0.78125 -2.513672,-0.78125 z m -0.453125,8.9218752 c -0.374975,0 -0.692725,0.09897 -0.953125,0.296875 -0.260399,0.187488 -0.390625,0.520864 -0.390625,1 0,0.45830298 0.130226,0.79167998 0.390625,0.99999998 0.2604,0.197904 0.57815,0.296875 0.953125,0.296875 0.36456,0 0.677101,-0.09897 0.9375,-0.296875 0.2604,-0.20832 0.390625,-0.541697 0.390625,-0.99999998 0,-0.479136 -0.130225,-0.812512 -0.390625,-1 -0.260399,-0.197904 -0.57294,-0.296875 -0.9375,-0.296875 z" />
|
||||
<ellipse
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:none;stroke-width:9.94378;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="path92548"
|
||||
cx="7.8807526"
|
||||
cy="8.2403135"
|
||||
rx="6.6163163"
|
||||
ry="6.4118476" />
|
||||
<g
|
||||
id="g100943"
|
||||
transform="matrix(0.84582226,0,0,0.84582226,1.0549805,0.17352877)">
|
||||
<ellipse
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:7.54947;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="ellipse100204"
|
||||
cx="7.9489827"
|
||||
cy="8.2061987"
|
||||
rx="5.0232086"
|
||||
ry="4.8679729" />
|
||||
<ellipse
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.70623;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="ellipse100206"
|
||||
cx="7.7077522"
|
||||
cy="7.3860149"
|
||||
rx="3.131393"
|
||||
ry="3.0346215" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
|
|
@ -0,0 +1,43 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://jusswlaofkgc"
|
||||
path="res://.godot/imported/Receptor.svg-3c1cccf5229247e268d12db0af1e1abb.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/rokojori_action_library/Icons/Receptor.svg"
|
||||
dest_files=["res://.godot/imported/Receptor.svg-3c1cccf5229247e268d12db0af1e1abb.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="ReceptorBranch.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
showgrid="false"
|
||||
inkscape:zoom="20.727068"
|
||||
inkscape:cx="12.785214"
|
||||
inkscape:cy="15.583488"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
id="path1539"
|
||||
style="font-weight:bold;font-size:15.624px;line-height:1;font-family:'MS Outlook';-inkscape-font-specification:'MS Outlook Bold';fill:#1de3ab;fill-opacity:1;stroke-width:0.29295;stroke-linecap:round;stroke-linejoin:round;paint-order:markers stroke fill"
|
||||
d="m 51.913678,-11.337595 c -0.708287,0 -1.359413,0.08855 -1.953125,0.265625 -0.593711,0.177072 -1.145866,0.406268 -1.65625,0.6875 l 0.828125,1.671875 c 0.447888,-0.229152 0.885445,-0.411467 1.3125,-0.546875 0.427056,-0.135408 0.859404,-0.203125 1.296875,-0.203125 0.437472,0 0.776058,0.088553 1.015625,0.265625 0.249984,0.177072 0.373047,0.427104 0.373047,0.75 0,0.333312 -0.10418,0.625016 -0.3125,0.875 -0.197904,0.239568 -0.529327,0.526063 -0.998047,0.859375 -0.531215,0.385392 -0.906264,0.76044 -1.125,1.125 -0.218735,0.354144 -0.328125,0.786492 -0.328125,1.296875 v 0.5625002 h 2.015625 V -4.181345 c 0,-0.20832 0.02605,-0.385426 0.07813,-0.53125 0.0625,-0.15624 0.171885,-0.307301 0.328125,-0.453125 0.166656,-0.15624 0.404318,-0.348973 0.716797,-0.578125 0.406224,-0.291648 0.744809,-0.572934 1.015625,-0.84375 0.270816,-0.270816 0.473967,-0.56252 0.609375,-0.875 0.135408,-0.31248 0.203125,-0.682319 0.203125,-1.109375 0,-0.802031 -0.302122,-1.463576 -0.90625,-1.984375 -0.593711,-0.520799 -1.430409,-0.78125 -2.513672,-0.78125 z m -0.453125,8.9218752 c -0.374975,0 -0.692725,0.09897 -0.953125,0.296875 -0.260399,0.187488 -0.390625,0.520864 -0.390625,1 0,0.45830298 0.130226,0.79167998 0.390625,0.99999998 0.2604,0.197904 0.57815,0.296875 0.953125,0.296875 0.36456,0 0.677101,-0.09897 0.9375,-0.296875 0.2604,-0.20832 0.390625,-0.541697 0.390625,-0.99999998 0,-0.479136 -0.130225,-0.812512 -0.390625,-1 -0.260399,-0.197904 -0.57294,-0.296875 -0.9375,-0.296875 z" />
|
||||
<g
|
||||
id="g108125"
|
||||
transform="matrix(0.79163872,0,0,0.79163872,1.7612911,1.4766487)">
|
||||
<ellipse
|
||||
style="fill:#ff82db;fill-opacity:1;stroke:none;stroke-width:9.94378;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="path92548"
|
||||
cx="7.8807526"
|
||||
cy="8.2403135"
|
||||
rx="6.6163163"
|
||||
ry="6.4118476" />
|
||||
<g
|
||||
id="g100943"
|
||||
transform="matrix(0.84582226,0,0,0.84582226,1.0549805,0.17352877)">
|
||||
<ellipse
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:7.54947;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="ellipse100204"
|
||||
cx="7.9489827"
|
||||
cy="8.2061987"
|
||||
rx="5.0232086"
|
||||
ry="4.8679729" />
|
||||
<ellipse
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.70623;stroke-linecap:square;stroke-linejoin:round;paint-order:stroke fill markers"
|
||||
id="ellipse100206"
|
||||
cx="7.7077522"
|
||||
cy="7.3860149"
|
||||
rx="3.131393"
|
||||
ry="3.0346215" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="path103023"
|
||||
style="color:#000000;fill:#1de3ab;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none;paint-order:markers stroke fill"
|
||||
d="m 1.319336,0.088867 c -0.674094,0 -1.248047,0.571999 -1.248047,1.246093 v 2.511719 h 2 V 2.088867 H 3.81543 v -2 z m 10.84375,0 v 2 h 1.765625 v 1.757812 h 2 V 1.33496 c 0,-0.674094 -0.573952,-1.246093 -1.248047,-1.246093 z M 0.071289,12.194336 v 2.468749 c 0,0.674095 0.573953,1.248048 1.248047,1.248048 H 3.81543 V 13.911132 H 2.071289 v -1.716796 z m 13.857422,0 v 1.716796 h -1.765625 v 2.000001 h 2.517578 c 0.674095,0 1.248047,-0.573953 1.248047,-1.248048 v -2.468749 z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
|
|
@ -0,0 +1,43 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c6wwqj7hdrmpa"
|
||||
path="res://.godot/imported/ReceptorBranch.svg-bb59728d991a1a6154c3682d9e33cce7.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/rokojori_action_library/Icons/ReceptorBranch.svg"
|
||||
dest_files=["res://.godot/imported/ReceptorBranch.svg-bb59728d991a1a6154c3682d9e33cce7.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
|
|
@ -18,7 +18,9 @@ namespace Rokojori
|
|||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( lookFrom == null || lookTarget == null )
|
||||
if ( lookFrom == null || lookTarget == null ||
|
||||
! IsInstanceValid( lookFrom ) || ! IsInstanceValid( lookTarget )
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori
|
||||
{
|
||||
[GlobalClass, Tool ]
|
||||
public partial class SelectNode3D : Action
|
||||
{
|
||||
[Export]
|
||||
public Selector selector;
|
||||
|
||||
bool _enteredTree = false;
|
||||
|
||||
public override void _EnterTree()
|
||||
{
|
||||
base._EnterTree();
|
||||
_enteredTree = true;
|
||||
}
|
||||
|
||||
Node _target;
|
||||
|
||||
[Export]
|
||||
public Node target
|
||||
{
|
||||
get => _target;
|
||||
set
|
||||
{
|
||||
if ( _target == value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_target = value;
|
||||
|
||||
// Deserialization sets exported properties before _EnterTree fires, so this
|
||||
// only triggers for genuine interactive edits in the editor, never for a scene
|
||||
// being loaded (regardless of property order) or for runtime reassignment.
|
||||
if ( _enteredTree && Engine.IsEditorHint() )
|
||||
{
|
||||
targetMember = "";
|
||||
|
||||
#if TOOLS
|
||||
NotifyPropertyListChanged();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Export]
|
||||
public string targetMember;
|
||||
|
||||
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( target == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Node3D node3D = null;
|
||||
|
||||
if ( selector == null )
|
||||
{
|
||||
ReflectionHelper.SetValue<Node3D>( target, targetMember, node3D );
|
||||
this.LogInfo( "Set Null:", HierarchyName.Of( target ), targetMember );
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedNode = Unique<SelectManager>.Get().Select( selector );
|
||||
|
||||
|
||||
if ( selectedNode is Selectable )
|
||||
{
|
||||
var go = selectedNode.GetParent<GameObject3D>();
|
||||
|
||||
if ( go != null )
|
||||
{
|
||||
node3D = go.body;
|
||||
}
|
||||
}
|
||||
|
||||
ReflectionHelper.SetValue<Node3D>( target, targetMember, node3D );
|
||||
|
||||
}
|
||||
|
||||
#if TOOLS
|
||||
|
||||
public override void _ValidateProperty( Godot.Collections.Dictionary property )
|
||||
{
|
||||
if ( property[ "name" ].AsString() != nameof( targetMember ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var members = GetTargetNode3DMemberNames();
|
||||
|
||||
property[ "hint" ] = (long) PropertyHint.Enum;
|
||||
property[ "hint_string" ] = members.Count == 0
|
||||
? "(Invalid Target)"
|
||||
: "None," + string.Join( ",", members );
|
||||
}
|
||||
|
||||
List<string> GetTargetNode3DMemberNames()
|
||||
{
|
||||
var names = new List<string>();
|
||||
|
||||
if ( target == null )
|
||||
{
|
||||
return names;
|
||||
}
|
||||
|
||||
var infos = ReflectionHelper.GetDataMemberInfos( target, BindingFlags.Public | BindingFlags.Instance );
|
||||
|
||||
foreach ( var info in infos )
|
||||
{
|
||||
if ( ! info.IsDefined( typeof( ExportAttribute ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var memberType = info.GetMemberType();
|
||||
|
||||
if ( memberType == null || ! memberType.IsAssignableFrom( typeof( Node3D ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
names.Add( info.Name );
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://76pepn06ofq5
|
||||
|
|
@ -30,10 +30,13 @@ namespace Rokojori
|
|||
return;
|
||||
}
|
||||
|
||||
var value = ReflectionHelper.GetValue<Node3D>( source, sourceMember );
|
||||
var value = sourceMember == null || sourceMember == "" ? (Node3D) source :
|
||||
ReflectionHelper.GetValue<Node3D>( source, sourceMember );
|
||||
|
||||
ReflectionHelper.SetValue<Node3D>( target, targetMember, value );
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ public partial class NumberValue : Node
|
|||
return GetType().Name + " { value = " + _value._DDD() + ", frozen = " + _frozen + " }";
|
||||
}
|
||||
|
||||
void _OnValueChange( double v )
|
||||
protected virtual void _OnValueChange( double v )
|
||||
{
|
||||
if ( _frozen )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ namespace Rokojori
|
|||
[Export]
|
||||
public Material material;
|
||||
|
||||
[Export]
|
||||
public GeometryInstance3D instanceTarget;
|
||||
|
||||
[Export]
|
||||
public FloatPropertyName propertyName;
|
||||
|
||||
|
|
@ -59,11 +62,46 @@ namespace Rokojori
|
|||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( ! interruptCurrent && _actionID != -1 )
|
||||
if ( material != null && ! IsInstanceValid( material ) )
|
||||
{
|
||||
material = null;
|
||||
}
|
||||
|
||||
if ( instanceTarget != null && ! IsInstanceValid( instanceTarget ) )
|
||||
{
|
||||
instanceTarget = null;
|
||||
}
|
||||
|
||||
if ( propertyName == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this.LogInfo( "TRIGGERED" );
|
||||
|
||||
if ( instanceTarget != null )
|
||||
{
|
||||
// this.LogInfo( "INSTANCE" );
|
||||
TweenInstanceUniform();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( material != null )
|
||||
{
|
||||
// this.LogInfo( "MATERIAL" );
|
||||
TweenMaterial();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void TweenMaterial()
|
||||
{
|
||||
if ( ! interruptCurrent && _actionID != -1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( _actionID != -1 )
|
||||
{
|
||||
|
|
@ -156,5 +194,105 @@ namespace Rokojori
|
|||
).id;
|
||||
}
|
||||
|
||||
void TweenInstanceUniform()
|
||||
{
|
||||
if ( ! interruptCurrent && _actionID != -1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( _actionID != -1 )
|
||||
{
|
||||
CancelAction( _actionID );
|
||||
}
|
||||
|
||||
if ( stopAnimation )
|
||||
{
|
||||
|
||||
AnimationManager.StartAnimation( this, instanceTarget, propertyName.propertyName );
|
||||
|
||||
if ( setStopValue )
|
||||
{
|
||||
propertyName.SetInstance( instanceTarget, endValue );
|
||||
}
|
||||
|
||||
AnimationManager.EndAnimation( this, instanceTarget, propertyName.propertyName );
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_actionID = DispatchStart();
|
||||
|
||||
var startValue = propertyName.GetInstance( instanceTarget );
|
||||
|
||||
|
||||
|
||||
|
||||
if ( forceStartValue && Engine.IsEditorHint() )
|
||||
{
|
||||
startValue = forcedStartValue;
|
||||
}
|
||||
|
||||
if ( animateStartValue )
|
||||
{
|
||||
startValue = animationStartValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimationManager.StartAnimation( this, instanceTarget, propertyName.propertyName );
|
||||
|
||||
// this.LogInfo( "Get Float Tween", startValue );
|
||||
|
||||
_timeID = TimelineManager.ScheduleSpanWith( duration,
|
||||
( span, type )=>
|
||||
{
|
||||
|
||||
// this.LogInfo( "Update Float Tween", startValue );
|
||||
if ( span.id != _timeID )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! AnimationManager.IsAnimating( this, instanceTarget, propertyName.propertyName ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var phase = span.phase;
|
||||
|
||||
if ( curve != null )
|
||||
{
|
||||
phase = curve.Sample( phase );
|
||||
}
|
||||
|
||||
var value = Mathf.Lerp( startValue, endValue, phase );
|
||||
|
||||
|
||||
|
||||
// this.LogInfo( "Updating Float Tween", "phase:", phase, "value:", value, instanceTarget );
|
||||
|
||||
propertyName.SetInstance( instanceTarget, value );
|
||||
// ReflectionHelper.SetValue( material, propertyName , value );
|
||||
|
||||
if ( type == TimelineSpanUpdateType.End )
|
||||
{
|
||||
// this.LogInfo( "End Float Tween", endValue );
|
||||
|
||||
// target._Set( targetMember, endValue );
|
||||
|
||||
propertyName.SetInstance( instanceTarget, endValue );
|
||||
AnimationManager.EndAnimation( this, instanceTarget, propertyName.propertyName );
|
||||
DispatchEnd( _actionID );
|
||||
_actionID = -1;
|
||||
_timeID = -1;
|
||||
}
|
||||
},
|
||||
this
|
||||
).id;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -89,6 +89,11 @@ namespace Rokojori
|
|||
|
||||
var fromMaterial = MaterialSurfaceContainer.From( target, this.index ).GetMaterialInSlot<Material>( slot );
|
||||
|
||||
// Registers ownership of the *slot assignment itself* (as opposed to the color/float
|
||||
// properties on the material), so a second TweenMaterial targeting the same slot takes
|
||||
// over cleanly instead of both tweens fighting to set the end material.
|
||||
AnimationManager.StartAnimation( this, target, GetSlotKey() );
|
||||
|
||||
SetAssignedMaterial( fromMaterial );
|
||||
|
||||
var tl = TimelineManager.Ensure( timeLine );
|
||||
|
|
@ -180,6 +185,10 @@ namespace Rokojori
|
|||
AnimationManager.EndAnimation( this, _assignedMaterial, f.propertyName );
|
||||
}
|
||||
|
||||
// Only write the end material (and release ownership) if no later TweenMaterial
|
||||
// has since taken over this slot - otherwise this would stomp on it after the fact.
|
||||
if ( AnimationManager.IsAnimating( this, target, GetSlotKey() ) )
|
||||
{
|
||||
if ( MaterialAssignmentMode.Temporary_Duplicate_For_Each_Tween == assignmentMode )
|
||||
{
|
||||
_assignedMaterial = null;
|
||||
|
|
@ -199,6 +208,9 @@ namespace Rokojori
|
|||
// this.LogInfo( "Setting:", slot, toMaterial, info, prop.Get( toMaterial ) );
|
||||
}
|
||||
|
||||
AnimationManager.EndAnimation( this, target, GetSlotKey() );
|
||||
}
|
||||
|
||||
DispatchEnd( sequenceID );
|
||||
}
|
||||
},
|
||||
|
|
@ -208,6 +220,11 @@ namespace Rokojori
|
|||
|
||||
}
|
||||
|
||||
string GetSlotKey()
|
||||
{
|
||||
return $"MaterialSlot:{index}:{slot}";
|
||||
}
|
||||
|
||||
void SetAssignedMaterial( Material material )
|
||||
{
|
||||
if ( MaterialAssignmentMode.Temporary_Duplicate_For_Each_Tween == assignmentMode )
|
||||
|
|
|
|||
|
|
@ -118,6 +118,11 @@ namespace Rokojori
|
|||
|
||||
for ( int i = 0; i < targets.Length; i++ )
|
||||
{
|
||||
if ( ! IsInstanceValid( targets[ i ] ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var o = _targetValues[ i ];
|
||||
|
||||
o.Set( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
|
||||
|
|
@ -146,6 +151,11 @@ namespace Rokojori
|
|||
|
||||
for ( int i = 0; i < targets.Length; i++ )
|
||||
{
|
||||
if ( ! IsInstanceValid( targets[ i ] ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var combined = offsetData.Clone();
|
||||
|
||||
var o = _targetValues[ i ];
|
||||
|
|
|
|||
|
|
@ -1,109 +0,0 @@
|
|||
using Godot;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
public partial class Brain:Action
|
||||
{
|
||||
[Export]
|
||||
public Receptor[] receptors;
|
||||
|
||||
[Export]
|
||||
public Node behaviorRoot;
|
||||
|
||||
[Export]
|
||||
public BehaviorSequence activeSequence;
|
||||
|
||||
bool _paused = false;
|
||||
|
||||
public bool paused => _paused;
|
||||
|
||||
public void SetPaused( bool value )
|
||||
{
|
||||
_paused = value;
|
||||
}
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( _paused )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( activeSequence != null && activeSequence.isExclusive && activeSequence.isRunning )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var resolved = Resolve();
|
||||
|
||||
if ( resolved == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( resolved == activeSequence )
|
||||
{
|
||||
if ( activeSequence.reinitialize )
|
||||
{
|
||||
activeSequence.CancelAllRunning();
|
||||
activeSequence.Trigger();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var previous = activeSequence;
|
||||
activeSequence = resolved;
|
||||
|
||||
if ( previous != null )
|
||||
{
|
||||
previous.CancelAllRunning();
|
||||
}
|
||||
|
||||
activeSequence.Trigger();
|
||||
}
|
||||
|
||||
BehaviorSequence Resolve()
|
||||
{
|
||||
if ( behaviorRoot == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return ResolveIn( behaviorRoot );
|
||||
}
|
||||
|
||||
BehaviorSequence ResolveIn( Node parent )
|
||||
{
|
||||
var walker = NodesWalker.Get();
|
||||
var numChildren = walker.NumChildren( parent );
|
||||
|
||||
for ( int i = 0; i < numChildren; i++ )
|
||||
{
|
||||
var child = walker.ChildAt( parent, i );
|
||||
|
||||
if ( child is BehaviorSequence sequence )
|
||||
{
|
||||
return sequence;
|
||||
}
|
||||
|
||||
if ( child is BehaviorBranch branch )
|
||||
{
|
||||
if ( branch.IsBranchActive( this ) )
|
||||
{
|
||||
var found = ResolveIn( branch );
|
||||
|
||||
if ( found != null )
|
||||
{
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ using Rokojori.Extensions;
|
|||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/BehaviorBranch.svg")]
|
||||
public abstract partial class BehaviorBranch:Node
|
||||
{
|
||||
[Export]
|
||||
|
|
@ -4,7 +4,7 @@ using Rokojori.Extensions;
|
|||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/BehaviorSequence.svg")]
|
||||
public partial class BehaviorSequence:Sequence
|
||||
{
|
||||
[Export]
|
||||
|
|
@ -29,7 +29,9 @@ public partial class BehaviorSequence:Sequence
|
|||
|
||||
void OnDone( SequenceActionFinishedEvent ev )
|
||||
{
|
||||
if ( _brain == null || _brain.activeSequence != this )
|
||||
this.LogInfo( "On Done BS" );
|
||||
|
||||
if ( _brain == null || _brain.activeNode != this )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
using Godot;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
using System.Linq;
|
||||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Brain.svg")]
|
||||
public partial class Brain:Action
|
||||
{
|
||||
[Export]
|
||||
public Receptor[] receptors;
|
||||
|
||||
[Export]
|
||||
public Node[] receporContainers;
|
||||
|
||||
[Export]
|
||||
public Node behaviorRoot;
|
||||
|
||||
|
||||
[ExportGroup( "Debugging")]
|
||||
[Export]
|
||||
public Node activeNode;
|
||||
|
||||
|
||||
[Export]
|
||||
public bool printActiveNodeSelection = false;
|
||||
|
||||
[Export]
|
||||
public bool printBranchResult = false;
|
||||
|
||||
// Non-BehaviorSequence nodes (plain Actions) don't carry this state themselves,
|
||||
// so these stand in for it. Kept as protected statics in case that needs tuning later.
|
||||
protected static bool defaultIsExclusive = false;
|
||||
protected static bool defaultIsRunning = false;
|
||||
protected static bool defaultReinitialize = true;
|
||||
|
||||
bool _paused = false;
|
||||
|
||||
public bool paused => _paused;
|
||||
|
||||
public void SetPaused( bool value )
|
||||
{
|
||||
_paused = value;
|
||||
}
|
||||
|
||||
static bool IsExclusive( Node node )
|
||||
{
|
||||
return node is BehaviorSequence sequence ? sequence.isExclusive : defaultIsExclusive;
|
||||
}
|
||||
|
||||
static bool IsRunning( Node node )
|
||||
{
|
||||
return node is BehaviorSequence sequence ? sequence.isRunning : defaultIsRunning;
|
||||
}
|
||||
|
||||
static bool ShouldReinitialize( Node node )
|
||||
{
|
||||
return node is BehaviorSequence sequence ? sequence.reinitialize : defaultReinitialize;
|
||||
}
|
||||
|
||||
static void CancelIfRunning( Node node )
|
||||
{
|
||||
if ( node is BehaviorSequence sequence )
|
||||
{
|
||||
sequence.CancelAllRunning();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartBrain()
|
||||
{
|
||||
SetPaused( false );
|
||||
|
||||
receptors?.ForEachNonNull( r => r.Start() );
|
||||
|
||||
receporContainers?.ForEachNonNull( c => c.ForEach<Receptor>( r => r.Start() ) );
|
||||
|
||||
Trigger();
|
||||
}
|
||||
|
||||
// The node most recently armed with a one-shot onSequenceDone listener, so a late
|
||||
// event from a node the Brain has since moved away from doesn't retrigger it.
|
||||
SequenceAction _listenedSequenceAction;
|
||||
|
||||
// The node a next-frame restart is currently scheduled for, so a plain Action
|
||||
// doesn't accumulate more than one pending restart chain at a time.
|
||||
Node _pendingRestartNode;
|
||||
|
||||
void ActivateNode( Node node )
|
||||
{
|
||||
if ( node is Action action )
|
||||
{
|
||||
action.Trigger();
|
||||
}
|
||||
|
||||
if ( node is BehaviorSequence )
|
||||
{
|
||||
// Manages its own re-trigger/loop via onSequenceDone already (see BehaviorSequence._Ready).
|
||||
return;
|
||||
}
|
||||
|
||||
if ( node is SequenceAction sequenceAction )
|
||||
{
|
||||
_listenedSequenceAction = sequenceAction;
|
||||
|
||||
if ( ! sequenceAction.onSequenceDone.HasAction( OnListenedSequenceActionDone ) )
|
||||
{
|
||||
sequenceAction.onSequenceDone.Once( OnListenedSequenceActionDone );
|
||||
}
|
||||
}
|
||||
else if ( node is Action )
|
||||
{
|
||||
ScheduleRestartNextFrame( node );
|
||||
}
|
||||
}
|
||||
|
||||
void OnListenedSequenceActionDone( SequenceActionFinishedEvent ev )
|
||||
{
|
||||
if ( activeNode != _listenedSequenceAction )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Trigger();
|
||||
}
|
||||
|
||||
async void ScheduleRestartNextFrame( Node node )
|
||||
{
|
||||
if ( _pendingRestartNode == node )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_pendingRestartNode = node;
|
||||
|
||||
await this.RequestNextFrame();
|
||||
|
||||
if ( _pendingRestartNode == node )
|
||||
{
|
||||
_pendingRestartNode = null;
|
||||
}
|
||||
|
||||
if ( activeNode != node )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Trigger();
|
||||
}
|
||||
|
||||
// Dedup flag for the no-match-resolved restart below, mirroring _pendingRestartNode.
|
||||
bool _pendingNullResolveRestart = false;
|
||||
|
||||
async void ScheduleRestartNextFrameOnNullResolve()
|
||||
{
|
||||
if ( _pendingNullResolveRestart )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_pendingNullResolveRestart = true;
|
||||
|
||||
await this.RequestNextFrame();
|
||||
|
||||
_pendingNullResolveRestart = false;
|
||||
|
||||
Trigger();
|
||||
}
|
||||
|
||||
List<string> _branchInfo = new List<string>();
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( _paused )
|
||||
{
|
||||
if ( printActiveNodeSelection )
|
||||
{
|
||||
this.LogInfo( "Skipped. Paused" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( activeNode != null && IsExclusive( activeNode ) && IsRunning( activeNode ) )
|
||||
{
|
||||
if ( printActiveNodeSelection )
|
||||
{
|
||||
this.LogInfo( "Skipped. Running already exclusively" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( printBranchResult && _branchInfo.Count > 0 )
|
||||
{
|
||||
_branchInfo.Clear();
|
||||
}
|
||||
|
||||
var resolved = Resolve();
|
||||
|
||||
if ( printBranchResult && _branchInfo.Count > 0 )
|
||||
{
|
||||
this.LogInfo( _branchInfo.Join( "\n" ) );
|
||||
}
|
||||
|
||||
if ( printActiveNodeSelection )
|
||||
{
|
||||
this.LogInfo( "Active Node:", resolved == null ? "Null" : ( HierarchyName.Of( resolved ) ) );
|
||||
}
|
||||
|
||||
if ( resolved == null )
|
||||
{
|
||||
ScheduleRestartNextFrameOnNullResolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( resolved == activeNode )
|
||||
{
|
||||
if ( ShouldReinitialize( activeNode ) )
|
||||
{
|
||||
CancelIfRunning( activeNode );
|
||||
ActivateNode( activeNode );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var previous = activeNode;
|
||||
activeNode = resolved;
|
||||
|
||||
if ( previous != null )
|
||||
{
|
||||
CancelIfRunning( previous );
|
||||
}
|
||||
|
||||
ActivateNode( activeNode );
|
||||
}
|
||||
|
||||
Node Resolve()
|
||||
{
|
||||
if ( behaviorRoot == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return ResolveIn( behaviorRoot );
|
||||
}
|
||||
|
||||
Node ResolveIn( Node parent )
|
||||
{
|
||||
var walker = NodesWalker.Get();
|
||||
var numChildren = walker.NumChildren( parent );
|
||||
|
||||
for ( int i = 0; i < numChildren; i++ )
|
||||
{
|
||||
var child = walker.ChildAt( parent, i );
|
||||
|
||||
if ( child is BehaviorBranch branch && branch.IsBranchActive( this ) )
|
||||
{
|
||||
if ( printBranchResult )
|
||||
{
|
||||
_branchInfo.Add( HierarchyName.Of( child ) );
|
||||
}
|
||||
|
||||
var found = ResolveIn( branch );
|
||||
|
||||
if ( found != null )
|
||||
{
|
||||
return found;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( child is SceneCondition condition && condition.Evaluate() )
|
||||
{
|
||||
if ( printBranchResult )
|
||||
{
|
||||
_branchInfo.Add( HierarchyName.Of( child ) );
|
||||
}
|
||||
|
||||
var found = ResolveIn( condition );
|
||||
|
||||
if ( found != null )
|
||||
{
|
||||
return found;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( child is Receptor receptor && receptor.active )
|
||||
{
|
||||
if ( printBranchResult )
|
||||
{
|
||||
_branchInfo.Add( HierarchyName.Of( child ) );
|
||||
}
|
||||
|
||||
var found = ResolveIn( receptor );
|
||||
|
||||
if ( found != null )
|
||||
{
|
||||
return found;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( child is BehaviorSequence sequence )
|
||||
{
|
||||
return sequence;
|
||||
}
|
||||
|
||||
if ( child is Action action )
|
||||
{
|
||||
return action;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ using Rokojori.Extensions;
|
|||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/BrainControl.svg")]
|
||||
public partial class BrainControl:Action
|
||||
{
|
||||
public enum Mode
|
||||
|
|
@ -31,7 +31,7 @@ public partial class BrainControl:Action
|
|||
switch ( mode )
|
||||
{
|
||||
case Mode.Start:
|
||||
StartBrain();
|
||||
brain.StartBrain();
|
||||
break;
|
||||
|
||||
case Mode.Pause:
|
||||
|
|
@ -48,21 +48,5 @@ public partial class BrainControl:Action
|
|||
}
|
||||
}
|
||||
|
||||
void StartBrain()
|
||||
{
|
||||
brain.SetPaused( false );
|
||||
|
||||
if ( brain.receptors != null )
|
||||
{
|
||||
foreach ( var receptor in brain.receptors )
|
||||
{
|
||||
if ( receptor != null )
|
||||
{
|
||||
receptor.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
brain.Trigger();
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ using Rokojori.Extensions;
|
|||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
[GlobalClass]
|
||||
public partial class ConditionBranch:BehaviorBranch
|
||||
{
|
||||
[Export]
|
||||
|
|
@ -4,7 +4,7 @@ using Rokojori.Extensions;
|
|||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/ReceptorBranch.svg")]
|
||||
public partial class ReceptorBranch:BehaviorBranch
|
||||
{
|
||||
[Export]
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
using Godot;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
public partial class FollowBehavior:BehaviorSequence
|
||||
{
|
||||
[Export]
|
||||
public BehaviorMovement movement;
|
||||
|
||||
[Export]
|
||||
public Node3D target;
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( movement != null )
|
||||
{
|
||||
movement.Follow( target );
|
||||
}
|
||||
|
||||
base._OnTrigger();
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ using Rokojori.Extensions;
|
|||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
[GlobalClass]
|
||||
public abstract partial class BehaviorMovement:Node
|
||||
{
|
||||
public abstract void GoToPosition( Vector3 worldPosition );
|
||||
|
|
@ -4,7 +4,7 @@ using Rokojori.Extensions;
|
|||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
[GlobalClass]
|
||||
public partial class CharacterBodyBehaviorMovement:BehaviorMovement
|
||||
{
|
||||
[Export]
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using Godot;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class FollowBehavior:Action
|
||||
{
|
||||
[Export]
|
||||
public BehaviorMovement movement;
|
||||
|
||||
[Export]
|
||||
public Node3D target;
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( movement == null || target == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// var id = DispatchStart();
|
||||
|
||||
movement.Follow( target );
|
||||
|
||||
// await this.RequestNextFrame();
|
||||
|
||||
// this.LogInfo( "Done" );
|
||||
|
||||
// DispatchEnd( id );
|
||||
}
|
||||
}
|
||||
|
|
@ -4,17 +4,17 @@ using Rokojori.Extensions;
|
|||
namespace Rokojori;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Receptor.svg")]
|
||||
public partial class Receptor:Action
|
||||
{
|
||||
[Export]
|
||||
public SceneCondition sceneCondition;
|
||||
|
||||
[Export( PropertyHint.Range, "0.1,100")]
|
||||
public float receiptionTriggerCoverage = 75f;
|
||||
public float receptionTriggerCoverage = 75f;
|
||||
|
||||
[Export( PropertyHint.Range, "10,2000")]
|
||||
public float receiptionWindowDurationMS = 500f;
|
||||
public float receptionWindowDurationMS = 500f;
|
||||
|
||||
[Export( PropertyHint.Range, "10,1000")]
|
||||
public float tickRateMS = 100f;
|
||||
|
|
@ -22,7 +22,11 @@ public partial class Receptor:Action
|
|||
[Export]
|
||||
public Timeline timeline;
|
||||
|
||||
int resultSize => Mathf.CeilToInt( receiptionWindowDurationMS / tickRateMS );
|
||||
[ExportGroup("Debugging")]
|
||||
[Export]
|
||||
public float fillState = 0;
|
||||
|
||||
int resultSize => Mathf.CeilToInt( receptionWindowDurationMS / tickRateMS );
|
||||
|
||||
RingBuffer<bool> _resultsBuffer;
|
||||
|
||||
|
|
@ -70,8 +74,11 @@ public partial class Receptor:Action
|
|||
|
||||
void Sample()
|
||||
{
|
||||
// this.LogInfo( "Receptor Update" );
|
||||
|
||||
if ( sceneCondition == null )
|
||||
{
|
||||
// this.LogInfo( "No condition" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -84,12 +91,15 @@ public partial class Receptor:Action
|
|||
|
||||
if ( _resultsBuffer.count != resultSize )
|
||||
{
|
||||
// this.LogInfo( "No activation" );
|
||||
_activated = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var numActive = _resultsBuffer.CountItems( b => b );
|
||||
_activated = numActive / (float) resultSize >= receiptionTriggerCoverage / 100f;
|
||||
fillState = numActive / (float) resultSize;
|
||||
|
||||
_activated = fillState >= receptionTriggerCoverage / 100f;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
using Godot;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori
|
||||
{
|
||||
public enum ThirdPersonCameraLockMode
|
||||
{
|
||||
Lock,
|
||||
Release
|
||||
}
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class SetThirdPersonCameraLockTarget : Action
|
||||
{
|
||||
[Export]
|
||||
public ThirdPersonCamera camera;
|
||||
|
||||
[Export]
|
||||
public Pointer source;
|
||||
|
||||
[Export]
|
||||
public ThirdPersonCameraLockMode mode = ThirdPersonCameraLockMode.Lock;
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( camera == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mode == ThirdPersonCameraLockMode.Release )
|
||||
{
|
||||
camera.lockTarget = null;
|
||||
return;
|
||||
}
|
||||
|
||||
camera.lockTarget = source != null && source.pointable != null ? source.pointable.pointerPosition : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://pesdcfjnpi30
|
||||
|
|
@ -17,7 +17,7 @@ namespace Rokojori
|
|||
public Node3D target;
|
||||
|
||||
[Export]
|
||||
public Node3D lockTarget;
|
||||
public CameraLocker cameraLocker;
|
||||
|
||||
[Export]
|
||||
public float yaw;
|
||||
|
|
@ -68,12 +68,6 @@ namespace Rokojori
|
|||
return;
|
||||
}
|
||||
|
||||
if ( lockTarget != null && ! IsInstanceValid( lockTarget ) )
|
||||
{
|
||||
lockTarget = null;
|
||||
}
|
||||
|
||||
|
||||
// var tl = TimeLineManager.Ensure( timeLine );
|
||||
// var delta = tl.delta;
|
||||
var delta = (float) gameDelta;
|
||||
|
|
@ -81,19 +75,14 @@ namespace Rokojori
|
|||
|
||||
var targetPosition = Smoothing.Apply( settings.targetFollowSmoothing, target.GlobalPosition, delta );
|
||||
|
||||
var hasLockTarget = lockTarget != null;
|
||||
var lockTargetNode = cameraLocker != null && cameraLocker.isLocked && IsInstanceValid( cameraLocker.lockTarget ) ? cameraLocker.lockTarget.pointerPosition : null;
|
||||
var hasLockTarget = lockTargetNode != null;
|
||||
var lockTargetPosition = _lastLockTargetPosition;
|
||||
|
||||
if ( hasLockTarget )
|
||||
{
|
||||
lockTargetPosition = Smoothing.Apply( settings.lockTargetFollowSmoothing, lockTarget.GlobalPosition, delta );
|
||||
lockTargetPosition = Smoothing.Apply( settings.lockTargetFollowSmoothing, lockTargetNode.GlobalPosition, delta );
|
||||
_lastLockTargetPosition = lockTargetPosition;
|
||||
|
||||
if ( settings.lockReleaseDistance > 0f && ( lockTargetPosition - targetPosition ).Length() > settings.lockReleaseDistance )
|
||||
{
|
||||
lockTarget = null;
|
||||
hasLockTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
// lockBlend fades 0->1 on engage and 1->0 on release instead of snapping, so the focus
|
||||
|
|
|
|||
|
|
@ -81,9 +81,6 @@ namespace Rokojori
|
|||
[Export]
|
||||
public Smoothing lockBlendSmoothing = new FrameSmoothing();
|
||||
|
||||
[Export]
|
||||
public float lockReleaseDistance = 0f;
|
||||
|
||||
[Export]
|
||||
public float lockMinPitch = -10;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,205 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Godot;
|
||||
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Condition.svg")]
|
||||
public partial class HasCondition: SceneCondition
|
||||
{
|
||||
bool _enteredTree = false;
|
||||
|
||||
public override void _EnterTree()
|
||||
{
|
||||
base._EnterTree();
|
||||
_enteredTree = true;
|
||||
}
|
||||
|
||||
void OnTargetAssignmentChanged()
|
||||
{
|
||||
// Deserialization sets exported properties before _EnterTree fires, so this
|
||||
// only triggers for genuine interactive edits in the editor, never for a scene
|
||||
// being loaded (regardless of property order) or for runtime reassignment.
|
||||
if ( ! _enteredTree || ! Engine.IsEditorHint() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
targetName = "";
|
||||
|
||||
#if TOOLS
|
||||
NotifyPropertyListChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
GodotObject _target;
|
||||
|
||||
[Export]
|
||||
public GodotObject target
|
||||
{
|
||||
get => _target;
|
||||
set
|
||||
{
|
||||
if ( _target == value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_target = value;
|
||||
OnTargetAssignmentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Node _targetNode;
|
||||
|
||||
[Export]
|
||||
public Node targetNode
|
||||
{
|
||||
get => _targetNode;
|
||||
set
|
||||
{
|
||||
if ( _targetNode == value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_targetNode = value;
|
||||
OnTargetAssignmentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[Export]
|
||||
public string targetName;
|
||||
|
||||
GodotObject GetEffectiveTarget()
|
||||
{
|
||||
return target != null ? target : (GodotObject) targetNode;
|
||||
}
|
||||
|
||||
public override bool Evaluate()
|
||||
{
|
||||
var effectiveTarget = GetEffectiveTarget();
|
||||
|
||||
if ( effectiveTarget == null || string.IsNullOrEmpty( targetName ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var value = ReflectionHelper.GetDataMemberValue<object>( effectiveTarget, targetName );
|
||||
|
||||
return EvaluateValue( value );
|
||||
}
|
||||
|
||||
static bool EvaluateValue( object value )
|
||||
{
|
||||
switch ( value )
|
||||
{
|
||||
case null:
|
||||
return false;
|
||||
|
||||
case GodotObject go:
|
||||
return GodotObject.IsInstanceValid( go );
|
||||
|
||||
case bool b:
|
||||
return b;
|
||||
|
||||
case string s:
|
||||
return ! string.IsNullOrEmpty( s );
|
||||
|
||||
case int i:
|
||||
return i > 0;
|
||||
|
||||
case long l:
|
||||
return l > 0;
|
||||
|
||||
case float f:
|
||||
return f > 0;
|
||||
|
||||
case double d:
|
||||
return d > 0;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if TOOLS
|
||||
|
||||
static bool IsSupportedMemberType( System.Type type )
|
||||
{
|
||||
if ( type == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( type == typeof( bool ) || type == typeof( string ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( type == typeof( int ) || type == typeof( long ) || type == typeof( float ) || type == typeof( double ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( typeof( Node ).IsAssignableFrom( type ) || typeof( Resource ).IsAssignableFrom( type ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
List<string> GetTargetMemberNames()
|
||||
{
|
||||
var names = new List<string>();
|
||||
var effectiveTarget = GetEffectiveTarget();
|
||||
|
||||
if ( effectiveTarget == null )
|
||||
{
|
||||
return names;
|
||||
}
|
||||
|
||||
var infos = ReflectionHelper.GetDataMemberInfos( effectiveTarget, BindingFlags.Public | BindingFlags.Instance );
|
||||
|
||||
foreach ( var info in infos )
|
||||
{
|
||||
if ( ! info.IsDefined( typeof( ExportAttribute ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! IsSupportedMemberType( info.GetMemberType() ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
names.Add( info.Name );
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
public override void _ValidateProperty( Godot.Collections.Dictionary property )
|
||||
{
|
||||
if ( property[ "name" ].AsString() != nameof( targetName ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var members = GetTargetMemberNames();
|
||||
|
||||
property[ "hint" ] = (long) PropertyHint.Enum;
|
||||
property[ "hint_string" ] = members.Count == 0
|
||||
? "(Invalid Target)"
|
||||
: "None," + string.Join( ",", members );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://de0vq8n1ylgjn
|
||||
|
|
@ -14,6 +14,7 @@ namespace Rokojori
|
|||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/GameObject3D.svg") ]
|
||||
public partial class GameObject3D:Node3D, INetworkNode
|
||||
{
|
||||
|
||||
[ExportToolButton("Center On Children")]
|
||||
public Callable centerOnChildrenButton => Callable.From( ()=> { this.CenterOnChildren(); } );
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori;
|
||||
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class GameObject3DFlag:SelectorFlag
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://exkchmx40u0h
|
||||
|
|
@ -16,6 +16,40 @@ namespace Rokojori
|
|||
}
|
||||
}
|
||||
|
||||
public static void ForEach<[MustBeVariant] T>( this T[] array, System.Action<T> action )
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
action( array[i] );
|
||||
}
|
||||
}
|
||||
|
||||
public static void ForEachNonNull<[MustBeVariant] T>( this Godot.Collections.Array<T> array, System.Action<T> action ) where T:class
|
||||
{
|
||||
for (int i = 0; i < array.Count; i++)
|
||||
{
|
||||
if ( array[ i ] == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
action( array[i] );
|
||||
}
|
||||
}
|
||||
|
||||
public static void ForEachNonNull<T>( this T[] array, System.Action<T> action ) where T:class
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if ( array[ i ] == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
action( array[i] );
|
||||
}
|
||||
}
|
||||
|
||||
public static T Find<[MustBeVariant] T>( this Godot.Collections.Array<T> array, System.Func<T,bool> evaluater, int offset = 0 )
|
||||
{
|
||||
for ( int i = offset; i < array.Count; i++ )
|
||||
|
|
|
|||
|
|
@ -435,6 +435,50 @@ namespace Rokojori
|
|||
return list;
|
||||
}
|
||||
|
||||
public static Node Select( this Node root, Selector selector )
|
||||
{
|
||||
var walker = nodesWalker;
|
||||
|
||||
var end = walker.IterationEndOf( root );
|
||||
|
||||
var it = root;
|
||||
|
||||
while ( it != end )
|
||||
{
|
||||
if ( selector.Selects( it ) )
|
||||
{
|
||||
return it;
|
||||
}
|
||||
|
||||
it = walker.NextNode( it );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Node> SelectAll( this Node root, Selector selector )
|
||||
{
|
||||
var walker = nodesWalker;
|
||||
|
||||
var end = walker.IterationEndOf( root );
|
||||
|
||||
var it = root;
|
||||
|
||||
var list = new List<Node>();
|
||||
|
||||
while ( it != end )
|
||||
{
|
||||
if ( selector.Selects( it ) )
|
||||
{
|
||||
list.Add( it );
|
||||
}
|
||||
|
||||
it = walker.NextNode( it );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void ForEach<T>( this Node root, Action<T> callback ) where T:class
|
||||
{
|
||||
var walker = nodesWalker;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,293 @@
|
|||
using Godot;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori
|
||||
{
|
||||
// Single owner of lock state. LockOnPointer only tracks candidates and the current selection;
|
||||
// ThirdPersonCamera (or anything else) only reads isLocked/lockTarget from here.
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class CameraLocker : Action
|
||||
{
|
||||
[Export]
|
||||
public LockOnPointer source;
|
||||
|
||||
[Export]
|
||||
public Sensor engageSensor;
|
||||
|
||||
[ExportGroup( "Release" )]
|
||||
[Export]
|
||||
public float releaseDistance = 0f;
|
||||
|
||||
[Export]
|
||||
public Node3D releaseDistanceOrigin;
|
||||
|
||||
[ExportGroup( "Cycling" )]
|
||||
[Export]
|
||||
public LockOnCyclingSetup cyclingSetup;
|
||||
|
||||
[Export]
|
||||
public LockOnCyclingSetup lockedCyclingSetup;
|
||||
|
||||
[ExportGroup( "Visualizer" )]
|
||||
[Export]
|
||||
public Node3D visualizerMarker;
|
||||
|
||||
[ExportGroup( "Candidate Events" )]
|
||||
[Export]
|
||||
public Action onCandidateSpotted;
|
||||
|
||||
[Export]
|
||||
public Action onCandidateUnlocked;
|
||||
|
||||
[Export]
|
||||
public Action onCandidateVanished;
|
||||
|
||||
[Export]
|
||||
public Action onCandidateChanged;
|
||||
|
||||
[Export]
|
||||
public bool triggerCanidatesWhenLocked = false;
|
||||
|
||||
|
||||
[ExportGroup( "Lock Events" )]
|
||||
[Export]
|
||||
public Action onLock;
|
||||
|
||||
[Export]
|
||||
public Action onReleasedLock;
|
||||
|
||||
[Export]
|
||||
public Action onChangeLocked;
|
||||
|
||||
[ExportGroup( "Read Only" )]
|
||||
[Export]
|
||||
public Pointable lockTarget;
|
||||
|
||||
public bool isLocked => lockTarget != null;
|
||||
|
||||
Pointable _previousCandidate;
|
||||
bool _wasEngaged = false;
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
if ( source == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
source.Trigger();
|
||||
|
||||
UpdateCandidateEvents();
|
||||
|
||||
var previousTarget = lockTarget;
|
||||
var wasLocked = previousTarget != null;
|
||||
|
||||
// Order matters: cycling may move an existing lock, engagement may start/end one,
|
||||
// auto-release may end one - each only touches lockTarget for its own reason, nothing
|
||||
// here resyncs it every frame just because source.pointable drifted on its own.
|
||||
UpdateCycling();
|
||||
UpdateEngagement();
|
||||
UpdateAutoRelease();
|
||||
|
||||
FireLockEvents( wasLocked, previousTarget );
|
||||
|
||||
UpdateVisualizer();
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
if ( lockTarget == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var previousTarget = lockTarget;
|
||||
lockTarget = null;
|
||||
|
||||
FireLockEvents( true, previousTarget );
|
||||
}
|
||||
|
||||
void UpdateCandidateEvents()
|
||||
{
|
||||
if ( lockTarget != null && ! triggerCanidatesWhenLocked )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var candidate = source.pointable;
|
||||
|
||||
if ( candidate == _previousCandidate )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_previousCandidate = candidate;
|
||||
|
||||
onCandidateChanged?.Trigger();
|
||||
|
||||
Action.TriggerSafe( candidate == null ? onCandidateVanished : onCandidateSpotted );
|
||||
}
|
||||
|
||||
void UpdateCycling()
|
||||
{
|
||||
var setup = isLocked ? ( lockedCyclingSetup ?? cyclingSetup ) : ( cyclingSetup ?? lockedCyclingSetup );
|
||||
|
||||
if ( setup == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var cycled = false;
|
||||
|
||||
if ( setup.cycleMode == LockOnCycleMode.ClosestCycle )
|
||||
{
|
||||
if ( setup.cycleSensor != null && setup.cycleSensor.isDown )
|
||||
{
|
||||
source.CycleNext();
|
||||
cycled = true;
|
||||
}
|
||||
}
|
||||
else if ( setup.cycleMode == LockOnCycleMode.Directional && setup.directionalCycleInputs != null )
|
||||
{
|
||||
for ( int i = 0; i < setup.directionalCycleInputs.Length; i++ )
|
||||
{
|
||||
var input = setup.directionalCycleInputs[ i ];
|
||||
|
||||
if ( input == null || input.sensor == null || ! input.sensor.isDown )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
source.CycleInScreenSpaceDirection( input.direction );
|
||||
cycled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cycling is the only thing that is allowed to move an already-established lock onto a
|
||||
// different candidate - a deliberate, one-time assignment here, not a per-frame resync.
|
||||
if ( cycled && isLocked )
|
||||
{
|
||||
lockTarget = source.pointable;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateEngagement()
|
||||
{
|
||||
var engaged = engageSensor != null && engageSensor.isActive;
|
||||
var risingEdge = engaged && ! _wasEngaged;
|
||||
_wasEngaged = engaged;
|
||||
|
||||
if ( ! engaged )
|
||||
{
|
||||
lockTarget = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only a fresh press/toggle-on acquires a target. Once locked, the lock is held
|
||||
// regardless of what source.pointable does on its own (e.g. losing/regaining the raycast
|
||||
// hit) - it only changes via cycling, auto-release, or an explicit Release() call.
|
||||
if ( lockTarget == null && risingEdge )
|
||||
{
|
||||
lockTarget = source.pointable;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAutoRelease()
|
||||
{
|
||||
if ( lockTarget == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( IsGone( lockTarget ) )
|
||||
{
|
||||
lockTarget = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( IsTooFar( lockTarget ) )
|
||||
{
|
||||
lockTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Covers both an actually freed node and one that was removed from the tree without being
|
||||
// freed (e.g. pooled/recycled enemies) - either way it is no longer something the lock
|
||||
// should keep pointing at.
|
||||
static bool IsGone( Pointable target )
|
||||
{
|
||||
return target == null || ! IsInstanceValid( target ) || ! target.IsInsideTree();
|
||||
}
|
||||
|
||||
bool IsTooFar( Pointable target )
|
||||
{
|
||||
if ( releaseDistance <= 0f )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var origin = releaseDistanceOrigin ?? source.caster;
|
||||
|
||||
if ( origin == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return origin.GlobalPosition.DistanceTo( target.GlobalPosition ) > releaseDistance;
|
||||
}
|
||||
|
||||
void ReleaseEngageSensorIfToggled()
|
||||
{
|
||||
if ( engageSensor is ActivationModeSensor ams && ams.isActive )
|
||||
{
|
||||
ams.Release();
|
||||
}
|
||||
}
|
||||
|
||||
void FireLockEvents( bool wasLocked, Pointable previousTarget )
|
||||
{
|
||||
var isLockedNow = lockTarget != null;
|
||||
|
||||
if ( isLockedNow && ! wasLocked )
|
||||
{
|
||||
Action.TriggerSafe( onLock );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! isLockedNow && wasLocked )
|
||||
{
|
||||
ReleaseEngageSensorIfToggled();
|
||||
Action.TriggerSafe( onReleasedLock );
|
||||
|
||||
if ( source.IsCandidate( previousTarget ) )
|
||||
{
|
||||
Action.TriggerSafe( onCandidateUnlocked );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isLockedNow && wasLocked && lockTarget != previousTarget )
|
||||
{
|
||||
Action.TriggerSafe( onChangeLocked );
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateVisualizer()
|
||||
{
|
||||
if ( visualizerMarker == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var current = lockTarget ?? source.pointable;
|
||||
|
||||
if ( ! IsGone( current ) )
|
||||
{
|
||||
visualizerMarker.CopyGlobalPoseFrom( current.pointerPosition );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://dskrrdkp3hcu6
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using Godot;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class LockOnCyclingSetup : Resource
|
||||
{
|
||||
[Export]
|
||||
public LockOnCycleMode cycleMode = LockOnCycleMode.None;
|
||||
|
||||
[Export]
|
||||
public Sensor cycleSensor;
|
||||
|
||||
[Export]
|
||||
public DirectionalCycleInput[] directionalCycleInputs = [];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://bt07jjknw0aty
|
||||
|
|
@ -11,52 +11,28 @@ namespace Rokojori
|
|||
Directional
|
||||
}
|
||||
|
||||
// Only tracks the current candidate list and the single selected pointable (sticky - stays on
|
||||
// the selection until it is cycled away from or stops being a valid candidate). Owns no concept
|
||||
// of "locked" - that is CameraLocker's job, reading/driving this pointer's pointable.
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class LockOnPointer : Pointer
|
||||
{
|
||||
[Export]
|
||||
public Sensor engageSensor;
|
||||
public int test = 0;
|
||||
|
||||
[Export]
|
||||
public bool releaseWhenTargetInvalid = true;
|
||||
List<Pointable> _candidates = new List<Pointable>();
|
||||
|
||||
[Export]
|
||||
public Action onLockEngaged;
|
||||
public int numCandidates => _candidates.Count;
|
||||
|
||||
[Export]
|
||||
public Action onLockReleased;
|
||||
public Pointable GetCandidate( int index )
|
||||
{
|
||||
return _candidates[ index ];
|
||||
}
|
||||
|
||||
[ExportGroup( "Cycling" )]
|
||||
[Export]
|
||||
public LockOnCycleMode cycleMode = LockOnCycleMode.None;
|
||||
|
||||
[Export]
|
||||
public Sensor cycleSensor;
|
||||
|
||||
[Export]
|
||||
public DirectionalCycleInput[] directionalCycleInputs = [];
|
||||
|
||||
[Export]
|
||||
public Node3D closestVisualizer;
|
||||
|
||||
[Export]
|
||||
public Action onClosestFound;
|
||||
|
||||
[Export]
|
||||
public Action onClosestLost;
|
||||
|
||||
[Export]
|
||||
public Action onClosestChanged;
|
||||
|
||||
[ExportGroup("Read Only")]
|
||||
[Export]
|
||||
public Pointable closestCandidate;
|
||||
|
||||
|
||||
bool _engaged = false;
|
||||
|
||||
public bool isEngaged => _engaged;
|
||||
public bool IsCandidate( Pointable p )
|
||||
{
|
||||
return p != null && _candidates.Contains( p );
|
||||
}
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
|
|
@ -68,185 +44,68 @@ namespace Rokojori
|
|||
if ( pointable != null && ! IsInstanceValid( pointable ) )
|
||||
{
|
||||
pointable = null;
|
||||
}
|
||||
|
||||
if ( engageSensor.isActive && engageSensor is ActivationModeSensor ams )
|
||||
RefreshCandidates();
|
||||
|
||||
if ( pointable == null || ! _candidates.Contains( pointable ) )
|
||||
{
|
||||
ams.Release();
|
||||
SetPointable( ClosestCandidate() );
|
||||
}
|
||||
}
|
||||
|
||||
onLockReleased?.Trigger();
|
||||
}
|
||||
|
||||
UpdateClosestCandidate();
|
||||
|
||||
var wasLocked = pointable != null;
|
||||
|
||||
if ( visualizer != null && pointable != null )
|
||||
void RefreshCandidates()
|
||||
{
|
||||
visualizer.CopyGlobalPoseFrom( pointable.pointerPosition );
|
||||
}
|
||||
_candidates.Clear();
|
||||
|
||||
if ( engageSensor != null )
|
||||
{
|
||||
_engaged = engageSensor.isActive;
|
||||
|
||||
if ( ! _engaged )
|
||||
{
|
||||
if ( pointable != null )
|
||||
{
|
||||
SetPointable( null );
|
||||
}
|
||||
}
|
||||
else if ( pointable == null )
|
||||
{
|
||||
SetPointable( closestCandidate );
|
||||
}
|
||||
else if ( releaseWhenTargetInvalid && ! IsStillValidTarget( pointable ) )
|
||||
{
|
||||
SetPointable( null );
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleCycling();
|
||||
}
|
||||
}
|
||||
|
||||
// Fires off the pointable transition (not the raw engage-sensor edge) so it also covers the
|
||||
// releaseWhenTargetInvalid auto-release path above, and so pointable already holds its new
|
||||
// value (or null) by the time a listener - e.g. SetThirdPersonCameraLockTarget - reads it.
|
||||
var isNowLocked = pointable != null;
|
||||
|
||||
if ( isNowLocked != wasLocked )
|
||||
{
|
||||
Action.TriggerSafe( isNowLocked ? onLockEngaged : onLockReleased );
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateClosestCandidate()
|
||||
{
|
||||
var next = FindClosestCandidate();
|
||||
|
||||
if ( next == closestCandidate )
|
||||
{
|
||||
if ( closestVisualizer != null && closestCandidate != null )
|
||||
{
|
||||
closestVisualizer.CopyGlobalPoseFrom( closestCandidate.pointerPosition );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
closestCandidate = next;
|
||||
|
||||
onClosestChanged?.Trigger();
|
||||
|
||||
if ( closestCandidate == null )
|
||||
{
|
||||
onClosestLost?.Trigger();
|
||||
}
|
||||
else
|
||||
{
|
||||
onClosestFound?.Trigger();
|
||||
}
|
||||
|
||||
if ( closestVisualizer != null && closestCandidate != null )
|
||||
{
|
||||
closestVisualizer.CopyGlobalPoseFrom( closestCandidate.pointerPosition );
|
||||
}
|
||||
}
|
||||
|
||||
void HandleCycling()
|
||||
{
|
||||
if ( cycleMode == LockOnCycleMode.ClosestCycle )
|
||||
{
|
||||
if ( cycleSensor != null && cycleSensor.isDown )
|
||||
{
|
||||
SetPointable( FindNextClosestCandidate() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( cycleMode != LockOnCycleMode.Directional || directionalCycleInputs == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < directionalCycleInputs.Length; i++ )
|
||||
{
|
||||
var input = directionalCycleInputs[ i ];
|
||||
|
||||
if ( input == null || input.sensor == null || ! input.sensor.isDown )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var next = FindDirectionalCandidate( input.direction );
|
||||
|
||||
if ( next != null )
|
||||
{
|
||||
SetPointable( next );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Pointable FindClosestCandidate()
|
||||
{
|
||||
for ( int i = 0; i < caster.NumColliders(); i++ )
|
||||
{
|
||||
var p = Nodes.Find<Pointable>( caster.GetCollider( i ) );
|
||||
|
||||
if ( p != null && p.enabled )
|
||||
{
|
||||
return p;
|
||||
_candidates.Add( p );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Pointable FindNextClosestCandidate()
|
||||
Pointable ClosestCandidate()
|
||||
{
|
||||
var currentIndex = -1;
|
||||
var candidates = new List<Pointable>();
|
||||
return _candidates.Count == 0 ? null : _candidates[ 0 ];
|
||||
}
|
||||
|
||||
for ( int i = 0; i < caster.NumColliders(); i++ )
|
||||
public void CycleNext()
|
||||
{
|
||||
var p = Nodes.Find<Pointable>( caster.GetCollider( i ) );
|
||||
|
||||
if ( p == null || ! p.enabled )
|
||||
if ( _candidates.Count == 0 )
|
||||
{
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( p == pointable )
|
||||
var currentIndex = _candidates.IndexOf( pointable );
|
||||
var nextIndex = currentIndex == -1 ? 0 : ( currentIndex + 1 ) % _candidates.Count;
|
||||
|
||||
SetPointable( _candidates[ nextIndex ] );
|
||||
}
|
||||
|
||||
public void CyclePrevious()
|
||||
{
|
||||
currentIndex = candidates.Count;
|
||||
}
|
||||
|
||||
candidates.Add( p );
|
||||
}
|
||||
|
||||
if ( candidates.Count == 0 )
|
||||
if ( _candidates.Count == 0 )
|
||||
{
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( currentIndex == -1 )
|
||||
{
|
||||
return candidates[ 0 ];
|
||||
var currentIndex = _candidates.IndexOf( pointable );
|
||||
var previousIndex = currentIndex == -1 ? 0 : ( currentIndex - 1 + _candidates.Count ) % _candidates.Count;
|
||||
|
||||
SetPointable( _candidates[ previousIndex ] );
|
||||
}
|
||||
|
||||
return candidates[ ( currentIndex + 1 ) % candidates.Count ];
|
||||
}
|
||||
|
||||
Pointable FindDirectionalCandidate( Vector2 direction )
|
||||
public void CycleInScreenSpaceDirection( Vector2 screenSpaceDirection )
|
||||
{
|
||||
if ( pointable == null )
|
||||
{
|
||||
return FindClosestCandidate();
|
||||
SetPointable( ClosestCandidate() );
|
||||
return;
|
||||
}
|
||||
|
||||
var right = caster.GlobalTransform.Basis.X;
|
||||
|
|
@ -256,11 +115,11 @@ namespace Rokojori
|
|||
Pointable best = null;
|
||||
var bestScore = float.NegativeInfinity;
|
||||
|
||||
for ( int i = 0; i < caster.NumColliders(); i++ )
|
||||
for ( int i = 0; i < _candidates.Count; i++ )
|
||||
{
|
||||
var candidate = Nodes.Find<Pointable>( caster.GetCollider( i ) );
|
||||
var candidate = _candidates[ i ];
|
||||
|
||||
if ( candidate == null || candidate == pointable || ! candidate.enabled )
|
||||
if ( candidate == pointable )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -273,7 +132,7 @@ namespace Rokojori
|
|||
continue;
|
||||
}
|
||||
|
||||
var score = projected.Normalized().Dot( direction );
|
||||
var score = projected.Normalized().Dot( screenSpaceDirection );
|
||||
|
||||
if ( score > bestScore )
|
||||
{
|
||||
|
|
@ -282,20 +141,10 @@ namespace Rokojori
|
|||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
bool IsStillValidTarget( Pointable p )
|
||||
if ( best != null )
|
||||
{
|
||||
for ( int i = 0; i < caster.NumColliders(); i++ )
|
||||
{
|
||||
if ( Nodes.Find<Pointable>( caster.GetCollider( i ) ) == p )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
SetPointable( best );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
using Godot;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class ReleaseCameraLock : Action
|
||||
{
|
||||
[Export]
|
||||
public CameraLocker cameraLocker;
|
||||
|
||||
protected override void _OnTrigger()
|
||||
{
|
||||
cameraLocker?.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://b6ipiialv2te8
|
||||
|
|
@ -24,7 +24,18 @@ namespace Rokojori
|
|||
}
|
||||
|
||||
[Export]
|
||||
public FlagMode mode = FlagMode.Needs_One_Flag;
|
||||
public FlagMode flagMode = FlagMode.Needs_One_Flag;
|
||||
|
||||
public enum IterationMode
|
||||
{
|
||||
Only_Node,
|
||||
Only_Iterator,
|
||||
Node_And_Iterator
|
||||
}
|
||||
|
||||
[Export]
|
||||
public IterationMode iterationMode= IterationMode.Node_And_Iterator;
|
||||
|
||||
|
||||
[Export]
|
||||
public TreeIteratorType iteratorType = TreeIteratorType.DirectChildren;
|
||||
|
|
@ -41,7 +52,12 @@ namespace Rokojori
|
|||
}
|
||||
}
|
||||
|
||||
if ( numPresent == flag.Length || mode == FlagMode.Needs_One_Flag && numPresent > 0 )
|
||||
if ( numPresent == flag.Length )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( flagMode == FlagMode.Needs_One_Flag && numPresent > 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -51,6 +67,21 @@ namespace Rokojori
|
|||
|
||||
public override bool Selects( Node node )
|
||||
{
|
||||
|
||||
if ( IterationMode.Only_Node == iterationMode )
|
||||
{
|
||||
return node is Selectable s && SelectsSelectable( s );
|
||||
}
|
||||
|
||||
if ( IterationMode.Only_Iterator != iterationMode )
|
||||
{
|
||||
if ( node is Selectable s && SelectsSelectable( s ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var iterator = TreeIterator<Node>.GetIterator( iteratorType, node, NodesWalker.Get() );
|
||||
|
||||
while ( iterator.HasNext() )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Godot;
|
||||
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Selector.svg")]
|
||||
public partial class SelectManager:Node
|
||||
{
|
||||
[Export]
|
||||
public Node root;
|
||||
|
||||
Dictionary<Selector,Node> _singleSelections = new Dictionary<Selector, Node>();
|
||||
Dictionary<Selector,List<Node>> _listSelections = new Dictionary<Selector, List<Node>>();
|
||||
|
||||
public Node GetSelectionRoot()
|
||||
{
|
||||
return root == null ? GetTree().Root : root;
|
||||
}
|
||||
|
||||
public Node Select( Selector selector )
|
||||
{
|
||||
if ( selector == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( ! _singleSelections.ContainsKey( selector ) )
|
||||
{
|
||||
_singleSelections[ selector ] = GetSelectionRoot().Select( selector );
|
||||
}
|
||||
|
||||
return _singleSelections[ selector ];
|
||||
}
|
||||
|
||||
public List<Node> SelectAll( Selector selector )
|
||||
{
|
||||
if ( selector == null )
|
||||
{
|
||||
return new List<Node>();
|
||||
}
|
||||
|
||||
if ( ! _singleSelections.ContainsKey( selector ) )
|
||||
{
|
||||
_listSelections[ selector ] = GetSelectionRoot().SelectAll( selector );
|
||||
}
|
||||
|
||||
return _listSelections[ selector ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://7ogqhvo3x5og
|
||||
|
|
@ -36,6 +36,8 @@ namespace Rokojori
|
|||
{
|
||||
var variant = Variant.From<T>( value );
|
||||
mi.SetInstanceShaderParameter( propertyName, variant );
|
||||
|
||||
// RJLog.Log( "Set", propertyName, variant );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,6 +155,20 @@ public static class ListExtensions
|
|||
);
|
||||
}
|
||||
|
||||
public static void ForEachNonNull<T>( this List<T> elements, Action<T> callback ) where T:class
|
||||
{
|
||||
foreach ( var e in elements )
|
||||
{
|
||||
if ( e == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
callback( e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static List<T> Sub<T>( this List<T> elements, int start, int length = 0 )
|
||||
{
|
||||
var end = length == 0 ? elements.Count : ( start + length );
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Rokojori.Extensions;
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")]
|
||||
public partial class CustomUIImageType:UIImageType
|
||||
{
|
||||
[Export]
|
||||
public Material material;
|
||||
|
||||
|
||||
protected override void _Assign( UIImage image )
|
||||
{
|
||||
image.Material = material;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://dd3mbku3iiltt
|
||||
|
|
@ -613,7 +613,10 @@ namespace Rokojori
|
|||
}
|
||||
else
|
||||
{
|
||||
return control.GetWindow().Size.X;
|
||||
// return control.GetWindow().Size.X;
|
||||
return control.GetViewport().GetVisibleRect().Size.X;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -625,7 +628,8 @@ namespace Rokojori
|
|||
}
|
||||
else
|
||||
{
|
||||
return control.GetWindow().Size.Y;
|
||||
// return control.GetWindow().Size.Y;
|
||||
return control.GetViewport().GetVisibleRect().Size.Y;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ public abstract partial class ParticleVFXData:Resource
|
|||
return;
|
||||
}
|
||||
|
||||
if ( ! IsInstanceValid( particles ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( particles.Amount != preset.maxParticles )
|
||||
{
|
||||
particles.Amount = preset.maxParticles;
|
||||
|
|
|
|||
Loading…
Reference in New Issue