Compare commits

...

665 commits

Author SHA1 Message Date
Lubos Lenco 9220e6b57e
Merge pull request #2381 from Skehmatics/fix/abc_deprication
Correct depricated (and now removed) import
2021-11-08 10:14:09 +01:00
Lubos Lenco 15ec53830f
Merge pull request #2379 from MoritzBrueckner/fix-cpu-count
Fix cpu_count() for incomplete PATH var on Windows and improve error handling
2021-11-08 10:13:36 +01:00
Lubos Lenco 946610c793
Merge pull request #2382 from Skehmatics/fix/morph_targets_linux
Fix morph target exporting on Unix-based systems
2021-11-08 09:07:13 +01:00
Moritz Brückner 1430e22a90 Make utils.cpu_count() even more failsafe on Windows 2021-11-07 16:50:20 +01:00
Derek Schmidt 07f4bea206 Fix morph target exporting on Unix-based systems
Also fixes some extra space issues since my editor auto-fixed them
2021-11-06 17:18:36 -07:00
Derek Schmidt 8581a75f9c Correct depricated (and now removed) import 2021-11-06 14:52:05 -07:00
Moritz Brückner 6bb2513001 Fix cpu_count() for incomplete PATH var on Windows and improve error handling 2021-11-06 22:36:04 +01:00
Lubos Lenco f581e91ba9 Move in morph target texture links 2021-11-06 12:34:03 +01:00
Lubos Lenco 263d5853a5
Merge pull request #2375 from QuantumCoderQC/shape-keys
Implementing Shape keys
2021-11-06 12:31:23 +01:00
QuantumCoderQC 1cec287891 Conditional compilation for shape key node 2021-11-02 15:59:40 +01:00
QuantumCoderQC 83a60e7462 Implement shape key conditions 2021-11-02 15:59:15 +01:00
QuantumCoderQC 603d23fbfd Add shape key export option 2021-11-02 15:58:38 +01:00
QuantumCoderQC 03090cafa2 remove shape key textures on clean 2021-11-02 15:56:46 +01:00
QuantumCoderQC a1951bb66e clean up export 2021-11-02 15:56:24 +01:00
QuantumCoderQC 3c0f580f69 fix morph weights lookup 2021-11-02 13:42:09 +01:00
QuantumCoderQC 8116729822 fix pixel count for images, fix max shape keys 2021-11-02 13:42:09 +01:00
QuantumCoderQC 6c0d4bdead fix error when all shape keys muted 2021-11-02 13:42:09 +01:00
QuantumCoderQC 8f733222a9 fix shape keys and multiple uv 2021-11-02 13:42:09 +01:00
QuantumCoderQC 4b65d8d68c do not export muted shape keys 2021-11-02 13:42:09 +01:00
QuantumCoderQC 13a2f4538a move shape key textures to dedicated directory 2021-11-02 13:42:09 +01:00
QuantumCoderQC b7cafbb4e3 add node to set shape key value 2021-11-02 13:42:08 +01:00
QuantumCoderQC d4f9982768 documentation 1 2021-11-02 13:42:08 +01:00
QuantumCoderQC 8e69bea14e appy position scale 2021-11-02 13:42:08 +01:00
QuantumCoderQC 669898fae1 fix normals with shape key and skin 2021-11-02 13:42:08 +01:00
QuantumCoderQC 8df6fc9176 fix shape key with skinning 2021-11-02 13:42:08 +01:00
QuantumCoderQC edeaf488b9 remove debug prints 2021-11-02 13:42:08 +01:00
QuantumCoderQC cb2cf0c9b4 keep both vert colors and shape keys 2021-11-02 13:42:07 +01:00
QuantumCoderQC 4522055fac use vec4 uniform array instead of float array 2021-11-02 13:42:07 +01:00
QuantumCoderQC 1d0eaf9371 debug prints 2021-11-02 13:42:07 +01:00
QuantumCoderQC e562d2515e export with optimized texture size 2021-11-02 13:42:07 +01:00
QuantumCoderQC 8e7d8a4f56 additional uniforms 2021-11-02 13:42:06 +01:00
QuantumCoderQC 6e153569dc make attrib skin fix 2021-11-02 13:42:06 +01:00
QuantumCoderQC d01c55fcd4 mordify to export shape keys 2021-11-02 13:42:06 +01:00
QuantumCoderQC 3814cd9da7 methods to get if vertex colors and if shapekey present 2021-11-02 13:42:06 +01:00
QuantumCoderQC 0636eb85c6 add morph attribute to shaders 2021-11-02 13:42:06 +01:00
QuantumCoderQC 2f77c5b060 modify normals calculation in skinning for morphing 2021-11-02 13:42:06 +01:00
QuantumCoderQC 26a0fb8c5a add morph target to make_shader.py 2021-11-02 13:42:05 +01:00
QuantumCoderQC 8c034655be implement morph_target.glsl 2021-11-02 13:42:05 +01:00
QuantumCoderQC 6f9b51a57a move make_morph_target 2021-11-02 13:42:05 +01:00
QuantumCoderQC 34243ed74c implement make_morph_target 2021-11-02 13:42:05 +01:00
QuantumCoderQC fb004f5dcc make attributes for shadow maps and depth 2021-11-02 13:42:05 +01:00
QuantumCoderQC 867100d151 make shader attribute for morph targets 2021-11-02 13:42:05 +01:00
QuantumCoderQC 09433f2a19 init morph target glsl 2021-11-02 13:42:05 +01:00
QuantumCoderQC 10d41e5eca init make morph target 2021-11-02 13:42:05 +01:00
QuantumCoderQC b7941d2fa8 export shape keys as texture 2021-11-02 13:42:04 +01:00
Lubos Lenco 93563dbba5 Bump version 2021-11-02 10:29:01 +01:00
Lubos Lenco 9094154440
Merge pull request #2367 from MoritzBrueckner/fix-library-textures
Fix exporting textures from linked libraries
2021-11-01 21:51:20 +01:00
Lubos Lenco 6ad9941d43
Merge pull request #2374 from tong/fix-uniformsmanager-register
Fix switch expression
2021-11-01 20:53:23 +01:00
Lubos Lenco 326d3bbf0d
Merge pull request #2373 from QuantumCoderQC/pick-rb-imp
add normal output for pick rb node
2021-11-01 20:52:23 +01:00
Lubos Lenco b2566a8249
Merge pull request #2372 from QuantumCoderQC/decal-fix
Decal fix
2021-11-01 20:51:37 +01:00
tong 18c5636d03 Fix switch expression 2021-11-01 02:44:56 +01:00
QuantumCoderQC 07cfa40727 add normal output for pick rb node 2021-10-31 23:06:11 +01:00
QuantumCoderQC e06ca4b9e7 get material from decal object too 2021-10-31 23:03:25 +01:00
QuantumCoderQC ec1f25cfec add support for decal object uniforms 2021-10-31 23:02:45 +01:00
QuantumCoderQC 1dc733ca88 dont cast decal objects to mesh objects 2021-10-31 20:58:27 +01:00
Lubos Lenco f22542a0b4
Merge pull request #2369 from t3du/master
add Between and Not Equal to Compare Logic
2021-10-28 11:40:37 +02:00
t3du c97c738870
add Between and Not Equal to Compare Logic 2021-10-27 10:35:58 -03:00
t3du 130e470290
add Between and Not Equal to Compare Logic 2021-10-27 10:32:58 -03:00
Lubos Lenco fabb4c0c3c
Merge pull request #2368 from t3du/master
add Not Equal to Gate Node
2021-10-26 16:50:04 +02:00
t3du ca03897811
Update LN_gate.py 2021-10-26 10:08:46 -03:00
t3du 6e255bcb05
add Not Equal to Gate node logic 2021-10-26 10:05:11 -03:00
t3du f6dfc43dde
add Not Equal to Gate Node 2021-10-26 10:04:31 -03:00
Moritz Brückner 36e42ad736 Fix exporting textures from linked libraries 2021-10-25 19:43:13 +02:00
Lubos Lenco 3df2916f5b
Merge pull request #2366 from MoritzBrueckner/fix-collection-export
Fix exporting collections with parent object in another collection
2021-10-25 10:00:41 +02:00
Moritz Brückner 59aca7ea41 Fix exporting collections with parent object in another collection 2021-10-23 17:12:22 +02:00
Lubos Lenco 297f7cdfca
Merge pull request #2363 from t3du/master
add get object uid nodes / agg args to call haxe static function / add Between to gate node
2021-10-22 09:18:51 +02:00
t3du 176ab43fd0
fix return with correct screen cords
solution from:

https://forums.armory3d.org/t/worldtoscreencoord-draw-debug-lines-with-2d-api/3467/9
2021-10-20 16:51:11 -03:00
t3du 6b1333902c
change version and add NodeReplacement 2021-10-20 11:15:06 -03:00
t3du 89ff1c29fc
change node version and add NodeReplacement 2021-10-20 11:12:01 -03:00
t3du 086c05eba2
change node version and add NodeReplacement 2021-10-20 11:11:44 -03:00
t3du 3e6e1e4bd1
change info 2021-10-20 09:49:00 -03:00
t3du 977b2db376
change info 2021-10-20 09:48:17 -03:00
t3du ebb3076431
add between logic condition 2021-10-19 21:19:16 -03:00
t3du 826dbd786d
add property0 between 2021-10-19 21:18:02 -03:00
t3du 4fe8f683dc
add args to the call of haxe static function 2021-10-19 19:11:10 -03:00
t3du b9b5c65141
add args to the haxe static function 2021-10-19 19:07:49 -03:00
t3du ec3054cdeb
add uid nodes 2021-10-18 17:55:44 -03:00
t3du d3b006c873
add nodes for uid 2021-10-18 17:53:09 -03:00
Lubos Lenco 9c931aff56
Merge pull request #2362 from tong/fix-doc-generation
Fix dox when using special characters
2021-10-15 16:02:15 +02:00
tong 622b8a275f Fix dox when using special characters 2021-10-14 17:35:23 +02:00
Lubos Lenco ea9b01e733
Merge pull request #2361 from SaxonGao-SZ/master
Use project name for web title
2021-10-14 12:35:03 +02:00
SaxonGao-SZ 34897c9747
feature: Use project name for web title
feature: Use project name for web title
2021-10-13 20:52:36 +08:00
Lubos Lenco c1f98dc668
Merge pull request #2359 from t3du/master
add logic nodes: set/get canvas font size and set progress bar color
2021-10-12 16:20:55 +02:00
t3du 67d511568f
add new nodes 2021-10-11 17:41:03 -03:00
t3du b8319fe28b
add new nodes 2021-10-11 17:38:18 -03:00
t3du d5e0208fd6
add getCanvasFontSize and fix setCanvasFontSize 2021-10-11 17:35:56 -03:00
Lubos Lenco 0fadefab69
Merge pull request #2357 from QuantumCoderQC/fix-random-color
random color node fix
2021-10-08 10:27:07 +02:00
QuantumCoderQC 50a1994867 random color node fix 2021-10-07 19:18:43 +02:00
Lubos Lenco b9a220fbcb
Merge pull request #2356 from MoritzBrueckner/fix-world-geometry
Fix Geometry and Texture Coordinate nodes for world shaders
2021-10-06 10:17:43 +02:00
Moritz Brückner 5e1105f51d Fix some Texture Coordinate node outputs for world shaders 2021-10-05 19:03:08 +02:00
Moritz Brückner b060953a7e Further fixes for the geometry node on world shaders 2021-10-05 18:41:45 +02:00
Moritz Brückner a4d09936d6 Fix world normals and position (adjust to Blender) 2021-10-05 18:40:39 +02:00
Lubos Lenco 786e68e475
Merge pull request #2355 from MoritzBrueckner/fix-deprecated-nodes
Fix deprecated nodes and improve deprecation handling
2021-10-05 11:02:00 +02:00
Lubos Lenco c7cba9d792
Merge pull request #2353 from MoritzBrueckner/debug-renderpath
Allow to set default renderpath for debugging
2021-10-05 11:01:00 +02:00
Lubos Lenco d9ddb5f4a3
Merge pull request #2352 from MoritzBrueckner/fix-cmft-cpu-count
Fix CPU count parameter for cmft
2021-10-05 09:39:18 +02:00
Moritz Brückner 8e8e8f586d Assert correct category for deprecated nodes 2021-10-05 00:03:48 +02:00
Moritz Brückner e8fa3b1b9a Whitespace cleanup 2021-10-04 23:57:15 +02:00
Moritz Brückner 7289b95a48 Don't show empty "Deprecated" node category menu 2021-10-04 23:56:35 +02:00
Moritz Brückner 7f5d382131 Allow to set default renderpath for debugging 2021-10-03 22:40:29 +02:00
Lubos Lenco ea02600d14 Bump version 2021-10-03 20:15:36 +02:00
Lubos Lenco a2c33b2f6a
Merge pull request #2351 from MoritzBrueckner/debug-console-trace
Debug console: make log output more readable
2021-09-28 13:00:51 +02:00
Moritz Brückner c40fd26c20 Fix CPU count parameter for cmft 2021-09-27 23:13:30 +02:00
Moritz Brückner 308ab2d77b Add some tooltips to the debug console 2021-09-27 16:02:29 +02:00
Moritz Brückner d979e4fde9 Debug console: make spacing between log lines smaller 2021-09-27 15:53:08 +02:00
Moritz Brückner 1c237dd6c3 Make printing with PosInfos configurable in the debug console UI 2021-09-27 15:46:35 +02:00
Moritz Brückner 152959699a Debug console: optionally omit PosInfos when printing 2021-09-27 15:43:03 +02:00
Moritz Brückner 259c375fda Whitespace cleanup 2021-09-27 15:41:53 +02:00
Lubos Lenco b579c8a15d
Merge pull request #2350 from MoritzBrueckner/fix-nodes-reload
Fix add-on reloading when there are new unimported node files
2021-09-27 11:03:02 +02:00
Lubos Lenco 73a352b76e
Merge pull request #2349 from MoritzBrueckner/global-canvas-scale-nodes
Add nodes to get/set global canvas scale
2021-09-27 11:02:16 +02:00
Moritz Brückner 957c5371c8 Fix add-on reloading when there are new unimported node files 2021-09-26 22:34:09 +02:00
Moritz Brückner 962f8a79a5 Add nodes to get/set global canvas scale 2021-09-26 22:31:56 +02:00
Lubos Lenco 8604e670c3
Merge pull request #2342 from tong/log-message-improvements
Improve log messages
2021-09-26 09:51:06 +02:00
tong d1d266a0f0 Improve log messages 2021-09-23 11:30:46 +02:00
Lubos Lenco 62d399e01a
Merge pull request #2338 from tong/no-haxe-times-param
Remove haxe --times param per default
2021-09-22 19:21:52 +02:00
tong 128efcc0ef Use haxe_times prefs field 2021-09-21 14:56:12 +02:00
tong 3920c475be No haxe times param 2021-09-21 14:43:47 +02:00
Lubos Lenco e3a55db813
Merge pull request #2339 from tong/fix-local-sdk-path
Fix invalid fp when using local sdk
2021-09-21 11:42:22 +02:00
Lubos Lenco 597c291da7
Merge pull request #2336 from QuantumCoderQC/tweenNodes
Introducing Tween nodes
2021-09-19 10:25:45 +02:00
Lubos Lenco 16976cdc5b
Merge pull request #2335 from MoritzBrueckner/fix-trait-fakeuser
Fix fake user export for traits
2021-09-18 11:05:19 +02:00
tong d1fe4d6686 Fix invalid fp when using local sdk 2021-09-17 13:21:36 +02:00
QuantumCoderQC ca966588ff add documentation 2021-09-13 23:10:31 +02:00
QuantumCoderQC 0ce0c5c115 change socket order 2021-09-13 22:48:32 +02:00
QuantumCoderQC 05465bcea1 minor clean-up 2021-09-13 22:30:39 +02:00
Moritz Brückner 77815d95ed Fix fake user export for traits 2021-09-13 21:29:21 +02:00
Lubos Lenco 156f1f433a
Merge pull request #2334 from tong/fix-throw-assert-error
Fix assert throw error
2021-09-13 10:03:11 +02:00
Lubos Lenco 5b4d24f067
Merge pull request #2332 from MoritzBrueckner/fix-realtime-postprocess
Fix realtime postprocess & cleanup arm.lib.make_datas
2021-09-12 08:05:29 +02:00
tong c24389813f Fix assert throw error 2021-09-12 00:03:57 +02:00
Lubos Lenco c398c1181e
Merge pull request #2331 from tong/fix-background-mode-open-build-dir
Do not open build directory in background mode
2021-09-11 13:49:20 +02:00
Lubos Lenco 7d9d5ac50f
Merge pull request #2329 from MoritzBrueckner/fix-ArmNodeAddInputOutputButton
Fix ArmNodeAddInputOutputButton
2021-09-10 09:12:59 +02:00
QuantumCoderQC eb5ef99309 create tween vector node 2021-09-10 01:08:31 +02:00
QuantumCoderQC 62294c8bb4 create tween rotation node 2021-09-10 01:08:12 +02:00
QuantumCoderQC ed6aa96fb0 create tween float node 2021-09-10 01:07:52 +02:00
Lubos Lenco f3fcb2846e
Merge pull request #2326 from onelsonic/patch-2
Update props_ui.py
2021-09-08 08:51:07 +02:00
Lubos Lenco afeecd4df1
Merge pull request #2325 from onelsonic/patch-1
Update props.py
2021-09-08 08:49:39 +02:00
Moritz Brückner de72bbf3a4 Cleanup arm.lib.make_datas 2021-09-07 23:40:52 +02:00
Moritz Brückner ecc4317919 Fix realtime postprocess: use compositor defines also for non-compositor pass shaders 2021-09-07 22:19:12 +02:00
tong 667e73c867 Do not open build directory in background mode 2021-09-07 10:15:11 +02:00
Moritz Brückner 56d84b08f4 Cleanup 2021-09-06 18:23:21 +02:00
Moritz Brückner adb2468245 Fix ArmNodeAddInputOutputButton 2021-09-06 18:22:38 +02:00
onelsonic abc52627a3
Update props_ui.py
change the UI to reflect common order to setup Android SDK values
https://developer.android.com/guide/topics/manifest/uses-sdk-element.html
android:minSdkVersion="integer"
then
android:targetSdkVersion="integer"
then
android:maxSdkVersion="integer"
2021-09-06 15:33:16 +02:00
onelsonic 68ef00b668
Update props.py
proposed UI descriptions changes to reflect current Android SDK
https://developer.android.com/guide/topics/manifest/uses-sdk-element.html
and updating default SDK values to Android Oreo
2021-09-06 15:26:13 +02:00
Lubos Lenco 55cfead084 Bump version 2021-09-06 09:22:25 +02:00
Lubos Lenco fe6d1fa372
Merge pull request #2320 from QuantumCoderQC/AddTraitFix
Add trait fix
2021-09-06 09:02:22 +02:00
Lubos Lenco 974181e75e
Merge pull request #2319 from MoritzBrueckner/assert-string-expr
Allow to use more complex string expressions as assert() messages
2021-09-05 11:55:28 +02:00
Lubos Lenco a4ab1dcc98
Merge pull request #2318 from QuantumCoderQC/navMeshImprove
Small improvement to Navigation nodes
2021-09-04 15:15:44 +02:00
QuantumCoderQC ccbc946bf1 Add warning if trait is already applied on the object 2021-09-03 23:42:43 +02:00
QuantumCoderQC fddef0983c Modify Add Trait Node To Accept String Trait 2021-09-03 23:37:13 +02:00
Moritz Brückner e715bf0108 Allow to use more complex string expressions as assert() messages 2021-09-03 22:21:57 +02:00
QuantumCoderQC 214b84fcf7 Modify NavAgent Trait 2021-09-03 21:00:58 +02:00
QuantumCoderQC 32b745f829 Modify Navigation Go To Location Node 2021-09-03 21:00:33 +02:00
QuantumCoderQC 8caf859db9 Create and implement Get Nav Agent Data Node 2021-09-03 20:59:49 +02:00
Lubos Lenco d6692efbdc
Merge pull request #2316 from onelsonic/patch-1
correcting Haxe Warnings : Std.is is deprecated. Use Std.isOfType ins…
2021-09-03 12:37:23 +02:00
onelsonic c77eea93fa
correcting Haxe Warnings : Std.is is deprecated. Use Std.isOfType instead.
correcting Warning : Std.is is deprecated. Use Std.isOfType instead.
2021-09-03 08:36:13 +02:00
Lubos Lenco e0cbf1b332
Merge pull request #2315 from MoritzBrueckner/fix-ppcomp-warnings
Fix "Uniform PPCompXX not found" warnings
2021-09-02 20:05:11 +02:00
Moritz Brückner b7024a5854 Whitespace cleanup 2021-09-02 17:18:59 +02:00
Moritz Brückner 44d8325001 Fix "Uniform PPCompXX not found" warnings 2021-09-02 17:14:18 +02:00
Lubos Lenco 052c7b00c5
Merge pull request #2309 from MoritzBrueckner/assert
Add assert() macro
2021-09-01 09:16:46 +02:00
Lubos Lenco 675618e529
Merge pull request #2308 from tong/html5-server-settings
HTML5 webserver log, port prefs
2021-08-30 09:10:26 +02:00
Moritz Brückner a6b67e4e00 Improve assert() docstring 2021-08-27 14:34:59 +02:00
Moritz Brückner 4b75a896d6 Auto-import assert() macro 2021-08-27 01:32:38 +02:00
Moritz Brückner ecddc0af92 Add assert() macro 2021-08-27 01:26:00 +02:00
tong e05d556552 Webserver log, port prefs 2021-08-26 10:01:35 +02:00
Lubos Lenco 85edde6d24
Merge pull request #2305 from niacdoial/newrotation
Added a rotation node-socket
2021-08-26 09:53:25 +02:00
niacdoial 703c618c7d
Misc. patches before merge [watch for amends]
- fixed type/import bugs in RotationNode.hx and SeparateRotationNode.hx
2021-08-21 16:07:34 +02:00
Lubos Lenco df715db381
Merge pull request #2307 from MoritzBrueckner/krom-es6
Switch to ES6 on krom target and fix 'armory' define
2021-08-20 10:35:19 +02:00
Lubos Lenco a8a44df249
Merge pull request #2306 from MoritzBrueckner/various-node-fixes
Various node fixes
2021-08-20 10:34:22 +02:00
Moritz Brückner 1eb087125f Fix 'armory' define 2021-08-19 22:27:09 +02:00
Moritz Brückner 2347348504 Switch to ES6 on krom target
See https://github.com/armory3d/armorcore/issues/32
2021-08-19 22:26:30 +02:00
Moritz Brückner 3e22cb3375 Update ArmOpenNodeWikiEntry to new wiki page structure 2021-08-19 22:02:01 +02:00
Moritz Brückner 4e526a6dd3 Various smaller node fixes 2021-08-19 21:59:52 +02:00
Moritz Brückner 2630c159d8 Align new custom sockets to Blender UI 2021-08-19 21:58:43 +02:00
niacdoial a67452802d
React to commit 14d33ee0530e5db640e0fafb8604662333c1b066 in iron. 2021-08-19 11:31:12 +02:00
niacdoial f892fdfd8a
Merge months of changes into 'newrotation' branch
(and homogeneised the contents of said branch in the process)
(plus a couple bugfixes, because what else)
2021-08-18 17:04:00 +02:00
Lubos Lenco 29785172f4
Merge pull request #2304 from tong/just-run
Shift click play just run
2021-08-18 11:03:21 +02:00
niacdoial 1d0a6d7955
Did the haxe part of the ongoing update.
Also fixed a ton of bugs in the python part.
NOTE: this requires a yet-to-be-done commit to Iron to work.
2021-08-17 19:29:35 +02:00
tong 7b6d3536e3 Shift click play just run 2021-08-17 17:47:04 +02:00
Lubos Lenco f017d68ed7
Merge pull request #2303 from MoritzBrueckner/fix-nishita-LUT
Fix nishita artifacts and improve LUT value range
2021-08-17 09:30:22 +02:00
Moritz Brückner 1de97e1898 Minor cleanup 2021-08-15 00:30:41 +02:00
Moritz Brückner ca96174b6b Fix nishita sky artifacts on some GPUs
It could happen that values returned by dot() were slightly larger than 1 or less than -1 due to precision errors, but acos() is undefined outside of [-1, 1]. This would lead to NaN values on some GPUs, causing visible artifacts.
2021-08-14 23:45:33 +02:00
niacdoial bd67667a6e Added node replacement routines for previous commits
(and fixed a couple bugs along the way)
2021-08-12 20:58:35 +02:00
Lubos Lenco 2910fcf1a8
Merge pull request #2302 from MoritzBrueckner/fix-addon-reload
Fix accidental module reloading caused by name conflicts of global vars
2021-08-11 18:25:44 +02:00
Moritz Brückner c56a0c3a72 Fix accidental module reloading caused by name conflicts of global vars 2021-08-11 14:32:21 +02:00
Moritz Brückner d610cc6a2f Fix value range in Nishita LUT 2021-08-09 16:51:26 +02:00
Lubos Lenco 34f6e0fc7c Kha update 2021-08-08 13:02:19 +02:00
Lubos Lenco 45e3c1c138
Merge pull request #2298 from MoritzBrueckner/reload-addon
Implement basic addon reloading
2021-08-07 19:06:44 +02:00
Lubos Lenco c49bece460
Merge pull request #2299 from MoritzBrueckner/fix-armsdk-ci
Fix armsdk CI
2021-08-07 19:03:57 +02:00
Lubos Lenco 2ef4f19eb7
Merge pull request #2300 from N8n5h/volumetric-light
fix volumetric lights not working when shadow map atlas is enabled
2021-08-07 16:54:08 +02:00
N8n5h 5509096158 fix volumetric lights not working with shadow map atlas enabled
Added missing code so the shader refers to the correct variable when
using shadow map atlasing.
2021-08-06 18:34:39 -03:00
Moritz Brückner 2d3e15064a Fix armsdk CI
Updated Logic.hx with changes made in make_logic.py. Is this file even used somewhere?
2021-08-06 22:33:20 +02:00
Lubos Lenco 386d2a3bf4 Bump version 2021-08-06 11:10:28 +02:00
Lubos Lenco 7607cc8ccd
Merge pull request #2296 from tong/physics-drag-limit-props
PhysicsDrag trait limit props
2021-08-05 22:13:58 +02:00
Lubos Lenco 52a594c910
Merge pull request #2297 from MoritzBrueckner/ui-font-fix
Canvas: fix using non-default fonts
2021-08-05 22:13:30 +02:00
Moritz Brückner 4c4bebcf4f Canvas: fix using non-default fonts 2021-08-04 23:35:54 +02:00
Moritz Brückner ea8c13686c Implement basic addon reloading 2021-08-04 22:56:11 +02:00
tong 4c34c2a5ce PhysicsDrag trait limit props 2021-08-04 22:09:54 +02:00
Lubos Lenco b664e3a010
Merge pull request #2287 from MoritzBrueckner/fix-thread-polling
Continue thread polling after an exception in the done callback
2021-08-02 08:23:37 +02:00
Lubos Lenco 60d0f443f8
Merge pull request #2286 from MoritzBrueckner/fix-getfp-drive-root
Windows: fix arm.utils.get_fp() if the project path is a drive root
2021-08-01 16:50:22 +02:00
Lubos Lenco aeffd76b75
Merge pull request #2285 from tong/arcball-improvements
ArcBall axis trait prop
2021-07-31 20:07:16 +02:00
Lubos Lenco 1532a332ff
Merge pull request #2284 from QuantumCoderQC/TerrainTextureFix
Fix terrain export for Krom
2021-07-30 08:25:01 +02:00
Moritz Brückner 4fc1f38b3b Continue thread polling after an exception in the done callback 2021-07-27 00:21:27 +02:00
Moritz Brückner 5f2dce140e Windows: fix arm.utils.get_fp() if the project path is a drive root 2021-07-26 23:40:47 +02:00
tong 13cf22ecc2 ArcBall axis trait prop 2021-07-26 19:26:17 +02:00
QuantumCoderQC 9f7af6a1cd Change terrain material bump output to normal 2021-07-26 18:02:23 +02:00
QuantumCoderQC 9ec425f6ae get file name only if specifiedin node 2021-07-26 13:50:52 +02:00
QuantumCoderQC 3bad878650 Add exception for null data 2021-07-26 13:48:44 +02:00
Lubos Lenco ce75516c59
Merge pull request #2283 from MoritzBrueckner/live-patch
Live patch: refactor and logic nodes support
2021-07-26 09:00:31 +02:00
Moritz Brückner bce14549ac Fix LN live patch when using multiple instances of the same logic tree 2021-07-26 00:02:54 +02:00
Moritz Brückner ee208ece18 Live patch: ignore two more operators 2021-07-25 20:20:43 +02:00
Moritz Brückner 549040fc09 Fix publishing with live patch enabled 2021-07-25 20:13:47 +02:00
Moritz Brückner 62ff11747b Update nodes for live patch support (merge conflict cleanup) 2021-07-25 19:50:51 +02:00
Moritz Brückner 6a3045477f Fix physics node if arm_physics is false + cleanup 2021-07-25 18:36:36 +02:00
Moritz Brückner 8a758bbe26 Only stop live patch session if live patch was active 2021-07-25 17:07:51 +02:00
Moritz Brückner ffee6dc521 Fix error caused by resolving merge conflict 2021-07-25 17:02:29 +02:00
Moritz Brückner cca82a69bf
Merge branch 'master' into live-patch 2021-07-25 16:47:32 +02:00
Moritz Brückner c52d25e471 arm_props.py: cleanup and fix docstrings 2021-07-25 00:15:32 +02:00
Moritz Brückner cf1dd0ac71 Live patch: fix creation of node outputs 2021-07-24 23:07:22 +02:00
Moritz Brückner 8e1aa2fb0d Live patch: fix creation of nodes without properties 2021-07-24 23:06:53 +02:00
Moritz Brückner 6d2b825dd5 Fix LN replacement and take arm_watch and arm_logic_id properties into account 2021-07-24 20:24:04 +02:00
Moritz Brückner 6050bceaf1 Fix nodes with "..._get" property names 2021-07-24 20:17:29 +02:00
Moritz Brückner dbb0764ca7 Fix typo 2021-07-24 20:16:54 +02:00
Moritz Brückner 568f4f3a6d Remove unnecessary privateAccess metadata 2021-07-24 19:51:01 +02:00
Moritz Brückner 0a58279756 Live patch: add more ignored operators 2021-07-24 19:49:35 +02:00
Moritz Brückner ff5fd9c7ed Fix generator usage 2021-07-24 19:49:19 +02:00
Moritz Brückner 0456d5f080 Remove legacy code stub 2021-07-24 18:21:06 +02:00
Moritz Brückner af520b518e Fix compatibility for frames and reroutes 2021-07-24 13:54:48 +02:00
Moritz Brückner 82c7302dd9 Live patch: simplify node deletion code 2021-07-24 13:54:31 +02:00
Moritz Brückner 2b6a7a4f78 Live patch: add another ignored operator 2021-07-24 13:37:13 +02:00
Moritz Brückner 7eced3b4f5 Live patch: don't try to re-export if live patch is not active 2021-07-24 13:36:55 +02:00
Moritz Brückner aa21402221 Live patch: handle deletion of node links 2021-07-24 13:36:16 +02:00
Lubos Lenco 97cc737aff
Merge pull request #2280 from MoritzBrueckner/fix-multi-uv
Fix usage of multiple UV maps on mobile render path
2021-07-22 09:28:00 +02:00
Moritz Brückner 256d27e289 Fix vector/color handling for logic node live patching 2021-07-21 22:58:21 +02:00
Moritz Brückner 9ff726bac1 Fix usage of multiple UV maps on mobile render path 2021-07-21 00:01:27 +02:00
Moritz Brückner 5276711094 Live patch: add more ignored operators 2021-07-20 23:34:06 +02:00
Moritz Brückner 4f13ebc439 Live patch: fix updates of object sockets 2021-07-20 23:33:47 +02:00
Moritz Brückner 1edc7a9469 Live patch: support for adding nodes 2021-07-20 20:53:37 +02:00
Moritz Brückner 3ed915b654 Cleanup LivePatch.hx 2021-07-20 14:28:42 +02:00
Moritz Brückner e930da7388 Live patch: support for node deletion 2021-07-20 14:25:35 +02:00
Moritz Brückner c65764be99 Cleanup LivePatch.hx 2021-07-20 14:24:00 +02:00
Moritz Brückner bdee03873b Live patch: support for node duplication 2021-07-18 22:29:18 +02:00
Lubos Lenco 1b758ec32c
Merge pull request #2276 from tong/fix-fetch-prop-type
Fix fetch trait prop type
2021-07-18 09:12:44 +02:00
tong cfa941eab4 Fix fetch trait prop type 2021-07-17 18:49:37 +02:00
niacdoial 9b1393ea41
Make rotation its own socket in logic nodes, add rotation-specific math node
(part 1: conversion code not developed)
2021-07-11 11:28:00 +02:00
Lubos Lenco bfde181da6
Merge pull request #2268 from MoritzBrueckner/fix-gbuffer2-overlay
Fix visual artifacts caused by invalid gbuffer2 on OpenGL
2021-07-11 10:48:00 +02:00
Lubos Lenco a59c789528
Merge pull request #2266 from QuantumCoderQC/staticTargetFix
Static target fix
2021-07-11 10:46:52 +02:00
Lubos Lenco caa03b59c5
Merge pull request #2263 from knowledgenude/master
Fix nullability
2021-07-11 10:42:12 +02:00
Lubos Lenco ff93e5f824
Merge pull request #2262 from tong/replace-deprecated-std-is
Replace deprecated Std.is with Std.isOfType
2021-07-11 10:41:53 +02:00
Moritz Brückner b3162d8f6e Fix visual artifacts caused by invalid gbuffer2 on OpenGL 2021-07-10 22:41:19 +02:00
Moritz Brückner 823cc379b6 Live patch: ignore more operators & fix code style 2021-07-10 22:08:19 +02:00
Moritz Brückner ee194a1806 Live patch: support for socket default values 2021-07-10 21:50:30 +02:00
Moritz Brückner 96aa0ee890 Use custom sockets for default data types
This allows to listen for socket updates for the live patch system
2021-07-10 21:46:44 +02:00
QuantumCoderQC c0333db44f Fix typos. Fix fast float 2021-07-10 19:22:26 +02:00
QuantumCoderQC e0ff256f40 make boolean objects nullable for static targets 2021-07-10 19:20:56 +02:00
Henrique 28d21bf35f Fix nullability 2021-07-09 21:42:12 -03:00
tong b452acaebb Replace deprecated Std.is with Std.isOfType 2021-07-09 22:04:50 +02:00
Lubos Lenco 3c88ddcb23
Merge pull request #2260 from knowledgenude/master
Improved Input Map and added nodes to it
2021-07-09 07:52:24 +02:00
Henrique db5aed465e Add static method to remove keys 2021-07-08 16:10:45 -03:00
Henrique 55cf2896a2 Cleanup 2021-07-07 17:11:56 -03:00
Henrique daee309ad8 Add Remove Input Map Key node 2021-07-07 17:08:01 -03:00
Henrique 43a574eb15 Remove unnecessary read access 2021-07-07 16:51:07 -03:00
Henrique 919512fad0 Improve InputMap and add nodes to it 2021-07-07 16:33:20 -03:00
Lubos Lenco 14b18408aa
Merge pull request #2254 from N8n5h/fix-atlas-ui
Fix compiling error with shadow map atlas shadow size option
2021-07-06 23:35:35 +02:00
N8n5h 801668a0c2 Fix compiling error with shadow map atlas shadow size option
Added 512 option to Inc so it doesn't fails compilation because of
missing option as explained here
https://github.com/armory3d/armory/issues/2252#issue-937328497
2021-07-06 10:39:07 -03:00
Lubos Lenco dc6753c2ca Bump version 2021-07-06 10:46:44 +02:00
Lubos Lenco 6dd27bfeed
Merge pull request #2251 from MoritzBrueckner/ui-canvas-font
UI Canvas: use font from asset for all element types
2021-07-06 09:20:43 +02:00
Moritz Brückner e7da337530 UI Canvas: use font from asset for all element types 2021-07-05 19:25:47 +02:00
Lubos Lenco 50c8ceec1e
Merge pull request #2247 from QuantumCoderQC/LogicNodeFix
Add check to LogicNode run
2021-07-04 23:19:57 +02:00
Moritz Brückner a6ec652d5f Fix identity node replacement for Blender 2.93 2021-07-03 22:49:19 +02:00
QuantumCoderQC cb800729d2 Add check
Add a check to see if input socket is linked to correct output socket
2021-07-03 20:12:10 +02:00
Moritz Brückner 4e19ddfeb0 Do not send live patch events if live patch isn't running 2021-07-03 19:47:09 +02:00
Moritz Brückner b2153dbcd2 Cleanup 2021-07-03 19:45:35 +02:00
Moritz Brückner 4387d774cc Live patch: add support for node property updates 2021-07-03 19:45:05 +02:00
Lubos Lenco 738a217001
Merge pull request #2245 from QuantumCoderQC/NavMeshNodeFix
A few small fixes to UniformsManager calss and go to location node
2021-07-02 19:24:34 +02:00
QuantumCoderQC 9e493f6e79 do not remove trait at init 2021-07-01 15:33:28 +02:00
QuantumCoderQC 7504d5d92b Change input type from shader to vector 2021-07-01 15:32:53 +02:00
Lubos Lenco e308d9058b
Merge pull request #2242 from knowledgenude/master
Add "Parent Relative" option to location nodes
2021-06-29 08:44:17 +02:00
Henrique c7e1f5d0a9 Fix nodes 2021-06-28 16:12:05 -03:00
Moritz Brückner 202138304a Live patch: add support for creating connections between nodes 2021-06-28 12:17:13 +02:00
Lubos Lenco 8c0b6ba13e
Merge pull request #2240 from QuantumCoderQC/RelativePhysConstraint
Add option for relative physics constraint
2021-06-28 11:44:39 +02:00
Henrique 7515a20d93 Keep compatibility 2021-06-27 20:47:55 -03:00
Henrique 3d49edee71 Add Subtract option to World Vector to Local Space node 2021-06-27 19:13:00 -03:00
Henrique 34b816b4d9 Remove default value 2021-06-27 18:27:16 -03:00
Henrique 13c1e0508d Fix for null parent 2021-06-27 18:26:13 -03:00
Henrique f940e8566e Remove unused quat 2021-06-27 18:21:59 -03:00
Henrique dfad6902af Add Relative Parent option to location nodes 2021-06-27 18:18:04 -03:00
Moritz Brückner 441f42383e Correctly stop live patching after player terminates 2021-06-27 22:35:37 +02:00
Lubos Lenco 616a0e230d
Merge pull request #2239 from QuantumCoderQC/MatParamPerObject
Set material parameter on per object basis
2021-06-26 12:17:40 +02:00
Lubos Lenco 20540ccb11
Merge pull request #2238 from MoritzBrueckner/background-mode
Fix threading and publishing in background mode
2021-06-25 08:57:16 +02:00
QuantumCoderQC 31a2c9c4d3 Modify export of physics constraint 2021-06-24 23:13:29 +02:00
QuantumCoderQC ac48fd0bc9 Implement adding of relative physics constraint 2021-06-24 23:12:51 +02:00
QuantumCoderQC f2cf3bdeda Add new property to set if constraint is relative 2021-06-24 23:12:15 +02:00
QuantumCoderQC 112c00a649 Modify unifroms manager 2021-06-24 21:33:53 +02:00
QuantumCoderQC ee43724b97 Change imports 2021-06-24 21:33:21 +02:00
QuantumCoderQC 5a2f952f89 Add uniforms manager to mesh objects 2021-06-24 21:32:48 +02:00
QuantumCoderQC 936f11ed8e Move uniforms manager back to armory 2021-06-24 18:19:33 +02:00
QuantumCoderQC eab7fcbbe6 update node implementations 2021-06-24 18:13:13 +02:00
QuantumCoderQC 5a591fa15a set default vector and float parameter 2021-06-24 18:13:13 +02:00
QuantumCoderQC 975ec76f38 Set default image file 2021-06-24 18:13:13 +02:00
QuantumCoderQC 340f7e8af4 Pass default image file name when adding uniform 2021-06-24 18:13:13 +02:00
QuantumCoderQC fa44147ee6 Pass default float value when adding uniform 2021-06-24 18:13:13 +02:00
QuantumCoderQC c44e2cf555 Pass default vector value when adding uniform 2021-06-24 18:13:13 +02:00
QuantumCoderQC 15da6ccf58 Upgrade nodes to include object. Add documnetation 2021-06-24 18:13:12 +02:00
QuantumCoderQC 39922bc0f3 move uniforms manager to iron 2021-06-24 18:13:12 +02:00
QuantumCoderQC ea4f88aca8 remove debug trace 2021-06-24 18:13:12 +02:00
QuantumCoderQC 39bd32f9d3 get image from node 2021-06-24 18:13:12 +02:00
QuantumCoderQC e744fd901c create and implement uniforms manager
remove node mapping

Revert "remove node mapping"

This reverts commit e70aa60e120e71236cba885bd7e0e5f1b6acf39d.
2021-06-24 18:13:12 +02:00
QuantumCoderQC dbd348ad5d update node scripts 2021-06-24 18:13:12 +02:00
QuantumCoderQC f542dc00ca update similar nodes 2021-06-24 18:13:12 +02:00
QuantumCoderQC aaa21bc019 implement per object option 2021-06-24 18:13:12 +02:00
QuantumCoderQC a9f430c374 Add per object option 2021-06-24 18:13:12 +02:00
QuantumCoderQC 6cf3299ffe Implement and upgrade set material value parameter node 2021-06-24 18:13:12 +02:00
QuantumCoderQC a588396dea Update set material value param node 2021-06-24 18:13:12 +02:00
Moritz Brückner dc34e48c52 Unregister timers on exit/disabling addon 2021-06-24 17:26:21 +02:00
Moritz Brückner fce97a5ddf Cleanup 2021-06-24 15:03:30 +02:00
Moritz Brückner d18aede964 run_proc: no thread in background mode and call done in main thread 2021-06-24 14:59:32 +02:00
Moritz Brückner 66856e7ecc Build/publish: add poll() function to prevent exception when executing from outside of UI
If there was no exporter, calling `bpy.ops.arm.publish_project()` would result in an exception before. Now the call is simply ignored and a "poll failed" message is emitted instead.
2021-06-23 20:19:08 +02:00
Lubos Lenco ebfbb68bb4
Merge pull request #2235 from knowledgenude/master
Cleanup in ui Ext
2021-06-20 20:53:48 +02:00
Henrique 3c1264378b Cleanup in ui Ext 2021-06-19 13:39:18 -03:00
Lubos Lenco cbcc3e4e04
Merge pull request #2233 from MoritzBrueckner/fix-compilation
Fix compilation of some nodes
2021-06-16 08:10:03 +02:00
Moritz Brückner f45304ea10 Fix compilation of some nodes 2021-06-15 15:24:58 +02:00
Lubos Lenco dd13cc31b7
Merge pull request #2231 from knowledgenude/master
Fix GetBoneFkIkOnly node & add new input nodes
2021-06-14 10:41:51 +02:00
Henrique a5fa3445d9 Add new input nodes 2021-06-13 22:43:13 -03:00
Henrique 1ece052aee Fix GetBoneFkIkOnly node 2021-06-13 21:38:15 -03:00
Lubos Lenco 24d917ae6a
Merge pull request #2228 from MoritzBrueckner/fix-movie-texture
Fix rendering multiple movie textures
2021-06-10 21:12:32 +02:00
Moritz Brückner 3288c3dcf5 MovieTexture: add documentation 2021-06-10 20:28:30 +02:00
Moritz Brückner 251ad8e47e Cache and reuse movietexture render targets with same size 2021-06-10 20:27:23 +02:00
Moritz Brückner b2619828eb Fix rendering multiple movie textures
Fixes https://github.com/armory3d/armory/issues/1562
2021-06-09 23:11:22 +02:00
Lubos Lenco 6c6d7c1419
Merge pull request #2221 from QuantumCoderQC/ExtraLogicNodes
Extra logic nodes
2021-06-09 07:38:28 +02:00
QuantumCoderQC 0e6ba5b0b0 reverse call order 2021-06-07 13:49:12 +02:00
QuantumCoderQC 107dc730f4 Create and implement once per frame node 2021-06-07 13:41:24 +02:00
Lubos Lenco b72e85894a
Merge pull request #2220 from MoritzBrueckner/select-node
Add Select node
2021-06-07 11:03:42 +02:00
Moritz Brückner 20f9f8a5f4 Add Select node
Implements feature requests #2200 and #2201
2021-06-05 20:35:21 +02:00
Lubos Lenco 5eb8fc781f Bump version 2021-06-02 21:18:47 +02:00
Lubos Lenco 70cb5ea421
Merge pull request #2216 from MoritzBrueckner/shader-fixes
Fix Layer Weight node and multiple cycles shaders in one material
2021-05-28 12:06:04 +02:00
Moritz Brückner ccc427c04a Cleanup 2021-05-27 22:57:53 +02:00
Moritz Brückner 6d37095014 Fix usage of layer weight node in shadowmap shaders 2021-05-27 22:56:07 +02:00
Moritz Brückner 7057ec4ba6 Fix mixing multiple cycles shaders in one material 2021-05-27 22:41:27 +02:00
Lubos Lenco 138386f02a
Merge pull request #2213 from MoritzBrueckner/fix-instancing-mobile
Fix instancing on mobile and solid renderpaths
2021-05-26 12:46:52 +02:00
Moritz Brückner bdc2d91c1e Fix instancing on mobile and solid renderpaths
`gl_Position` was set before the instancing code in the vertex shader, this was the same issue as already fixed for desktop renderpaths in https://github.com/armory3d/armory/pull/2141
2021-05-26 12:42:11 +02:00
Lubos Lenco 7b5294121d is_IK_FK_only -> is_ik_fk_only 2021-05-23 22:19:48 +02:00
Lubos Lenco 9330090179
Merge pull request #2206 from QuantumCoderQC/IKfix29_FK
Improve bone IK. Add new nodes for better animation control
2021-05-23 22:15:26 +02:00
Lubos Lenco 88f522c27b
Merge pull request #2210 from MoritzBrueckner/merge-node
Merge node: add execution mode and output for input index
2021-05-23 16:32:27 +02:00
Moritz Brückner 11da953407 Merge node: add update routine 2021-05-22 12:30:38 +02:00
Moritz Brückner 494e2336ac Node replacement: write original traceback to file also in case of update failures 2021-05-22 12:28:57 +02:00
Moritz Brückner 20c6c52ae6 Merge node: add execution mode and output for input index 2021-05-22 00:36:58 +02:00
Moritz Brückner 088bc0f666 Exporter: remove no longer used Blender version checks 2021-05-20 20:38:43 +02:00
QuantumCoderQC a35cab5482 Implement node to set bone animated by FK or IK only 2021-05-20 18:24:32 +02:00
QuantumCoderQC 03baa49ecd Implement node to get bone transform in world space 2021-05-20 18:24:32 +02:00
QuantumCoderQC c53d04374d Implement node to get if controlled by FK or IK 2021-05-20 18:24:32 +02:00
QuantumCoderQC 43e145c3da Add comments to bone IK node 2021-05-20 18:24:32 +02:00
QuantumCoderQC 6ded7e61f4 Improve bone FK node to accept transform in world space 2021-05-20 18:24:32 +02:00
QuantumCoderQC e7c1855b81 Create new node to set if bones are FK IK only 2021-05-20 18:24:32 +02:00
QuantumCoderQC 86316a10bd Create new node to get world transforms of bones 2021-05-20 18:24:32 +02:00
QuantumCoderQC 646d3a74cf Create new node to get if bones are FK IK 2021-05-20 18:24:32 +02:00
QuantumCoderQC 5ed5b8d6a7 Nodes for IK and FK fix
Edit logic node code

fkcommit30_04

Upgrade bone IK node. Add comments
2021-05-20 18:24:31 +02:00
Moritz Brückner 9fbc3d6cd4 Small cleanup 2021-05-19 21:17:57 +02:00
Moritz Brückner 7b2961459c Live patch support for light strength and color 2021-05-19 21:17:38 +02:00
Moritz Brückner 3d46910530 Live patch: don't re-export on trackball rotation (double 'r' key) 2021-05-18 21:34:46 +02:00
Moritz Brückner 68825516c9 Live patch: more robust shader paths 2021-05-18 21:31:02 +02:00
Moritz Brückner 07ffe06c1d Live patch: move to dedicated module and use msgbus 2021-05-18 21:24:45 +02:00
Lubos Lenco 3b72fff76d
Merge pull request #2196 from N8n5h/light-fix-2
Small improvements for the Shadow Map Atlas Blender UI
2021-05-16 12:29:31 +02:00
N8n5h 1945439cd1 Small improvements for the Shadow Map Atlas Blender UI
* Made shadow map atlas sizes enum's values dynamic:
This allows reducing issues related to picking a "wrong" size for the atlases.
* Added a legend below shadow map sizes to have an idea of how much lights can an option fit.
* Separated listing of subdivisions to include point lights.
* Disable cubemap size if single map is enabled to show that cascade size option is only used.
2021-05-14 11:22:11 -03:00
Lubos Lenco 98eeccd71d
Merge pull request #2082 from armory3d/blender2.9
Blender 2.9 LTS support
2021-05-10 11:14:39 +02:00
Lubos Lenco d31303391f
Merge pull request #2185 from MoritzBrueckner/fix-linked-objects-export
Fix double-export of linked objects (#2175)
2021-05-09 15:50:57 +02:00
Moritz Brückner 590afcc573 Fix double-export of linked objects (#2175) 2021-05-08 23:09:45 +02:00
Lubos Lenco 30b2093b94 Move game theme to armory.ui 2021-05-07 17:02:31 +02:00
Lubos Lenco 2f1fe4ef0b Move Canvas and game ui to armory.ui package 2021-05-07 15:24:03 +02:00
Lubos Lenco 57093c34cd
Merge pull request #2184 from MoritzBrueckner/debug-console-panel
[Blender 2.9] Slightly improve debug console panel UI
2021-05-07 10:29:09 +02:00
Moritz Brückner 2c761b2ff6 Slightly improve debug console panel UI 2021-05-06 21:29:59 +02:00
Lubos Lenco 4db37ea1c1
Merge pull request #2177 from QuantumCoderQC/get-object-node-fix
Get object by name node fix
2021-05-02 11:16:12 +02:00
QuantumCoderQC df372e9523 Spelling correction 2021-05-02 01:37:00 +02:00
QuantumCoderQC 5b6875947c New logic node to spawn objects not in current active scene 2021-05-02 01:33:38 +02:00
QuantumCoderQC badc8853b4 Make description more accurate 2021-05-02 01:31:44 +02:00
QuantumCoderQC 1ebe528417 Remove scene port from logic node 2021-05-02 01:30:34 +02:00
QuantumCoderQC c185882db8 Revert commit that creates an object if not in scene.
Returns object only if present in active scene
2021-05-01 22:19:29 +02:00
Lubos Lenco 0085f6fbd7 Bump version 2021-05-01 11:30:23 +02:00
Lubos Lenco 04909603ec
Merge pull request #2176 from MoritzBrueckner/2.9-version-info
Update Blender version information to 2.93 LTS
2021-05-01 11:15:54 +02:00
Moritz Brückner 22a557162f Update Blender version information to 2.93 LTS 2021-05-01 00:04:25 +02:00
Lubos Lenco ad9c7bfa6b
Merge pull request #2170 from N8n5h/debug-console-atlas
Fix artifact with point light soft shadow in shadow map atlas
2021-04-29 09:01:21 +02:00
Lubos Lenco 6d52238db3
Merge pull request #2174 from N8n5h/light-fix-2
Make tileSizes and TileSizesFactor non-static
2021-04-29 09:00:38 +02:00
N8n5h 939649f492 Make tileSizes and TileSizesFactor non-static
This solves an oversight that basically made all atlases share the
their tileSizesFactor, a variable used to quickly lookup tile tile sizes
depending on the shadowMapScale. So if cascade size was higher than cube
map size, then point light atlases would use incorrect values and break.
2021-04-28 19:12:45 -03:00
N8n5h ddc3da7799 Fix artifact with point light soft shadow in sm atlas 2021-04-26 16:45:20 -03:00
Lubos Lenco a4e9ad945b
Merge pull request #2168 from N8n5h/debug-console-atlas
Add profiling of shadow map atlas logic to debug console
2021-04-25 09:35:52 +02:00
N8n5h 41c6924231 Separate shadow map atlas logic and rendering time 2021-04-24 21:48:24 -03:00
N8n5h 9247b09c88 Add profiling of shadow map atlas logic 2021-04-24 20:31:03 -03:00
Lubos Lenco bb5ff191b7
Merge pull request #2163 from MoritzBrueckner/fix-attribute-node
Fix export of attribute node if no UV map exists
2021-04-20 09:36:37 +02:00
Lubos Lenco df50ba397e
Merge pull request #2162 from MoritzBrueckner/fix-overlay-mats
Fix creation of overlay materials
2021-04-20 09:35:38 +02:00
Moritz Brückner 97b578d0ed Fix export of attribute node if no UV map exists 2021-04-19 22:21:23 +02:00
Moritz Brückner 8a364259db Fix creation of overlay materials 2021-04-19 21:42:09 +02:00
Lubos Lenco 6d4952624a
Merge pull request #2161 from N8n5h/light-fix
Remove redundant 0 check when computing tile offset
2021-04-18 16:58:59 +02:00
Lubos Lenco 1955edf01c
Merge pull request #2160 from N8n5h/debug-console-atlas
Add visual representation of shadow map atlases to the debug console
2021-04-18 16:58:10 +02:00
N8n5h eb01b4652a remove redundant 0 check when computing tile offset 2021-04-18 10:32:36 -03:00
N8n5h c21d17d04e Add visual representation of shadow map atlases to the debug console
This is done to make it easier to understand what is going on with
atlases to help users and also the maintenance of the feature.

Max atlas size and max tile size where moved to the graph to make it
more understandable.
2021-04-18 10:25:27 -03:00
Lubos Lenco 069a9288ea
Merge pull request #2159 from N8n5h/debug-console-atlas
Fix compile error with debug and shadow map atlas LOD
2021-04-16 17:59:11 +02:00
N8n5h da41d1fb17 Fix compile error with debug and shadow map atlas LOD 2021-04-16 11:43:19 -03:00
Lubos Lenco 00af258b14
Merge pull request #2157 from N8n5h/debug-console-atlas
Add shadow map atlases info to the debug console
2021-04-14 11:14:18 +02:00
N8n5h c01b079cf1 Add custom highlighting for debug console
And use it to highlight "not enough lights" with a different color to
bring attention to it.
2021-04-14 01:06:14 -03:00
N8n5h e1cfa2f1da Add shadow map atlases info to the debug console
Display information like tile size, current size, max size, free tiles,
etc. to help debug atlases.
2021-04-14 00:32:54 -03:00
Lubos Lenco 6fbee167ab
Merge pull request #2155 from MoritzBrueckner/fcurve-datapath-warnings
Improve warning message for unsupported/unknown fcurve data paths
2021-04-10 08:32:02 +02:00
Moritz Brückner 78e266f77b Improve warning message for unsupported/unknown fcurve data paths 2021-04-09 20:55:17 +02:00
Lubos Lenco 1df882cad1
Merge pull request #2154 from MoritzBrueckner/fix-system-name-node
Fix GetSystemName node
2021-04-08 19:02:45 +02:00
Moritz Brückner cf56c4f1d8 Fix GetSystemName node 2021-04-08 15:44:18 +02:00
Lubos Lenco a3ca487183
Merge pull request #2152 from N8n5h/light-fix
Fix detection of removed lights by shadow map atlas
2021-04-07 20:47:10 +02:00
N8n5h 63716eea17 Modifications around addLight from Inc
* Removed redundant checks at the start of the function.
* changed the return value to void because the "return false" were
redundant, and simply made it so the lightInAtlas is set at the end of
the function.
* Removed unused variable
2021-04-07 12:44:54 -03:00
N8n5h 614385ea7b Setup callbacks so tiles are notified when a light is removed
A secondary callback is setup so the tile it's also removed from the
activeTiles, because it's freed in a "non standard" way.
2021-04-07 12:44:54 -03:00
Lubos Lenco 69207a6289
Merge pull request #2151 from N8n5h/coll-mask
Expose collision filter mask as integer to the UI
2021-04-04 10:49:13 +02:00
N8n5h 766e26a7df Expose collision filter mask as integer to the UI 2021-04-03 20:49:33 -03:00
Lubos Lenco 316eafd286
Merge pull request #2150 from MoritzBrueckner/blender2.9
[Blender 2.9] Resolve merge conflicts
2021-04-03 14:21:41 +02:00
Moritz Brückner f64419dd06 Merge branch 'master' into blender2.9
# Conflicts:
#	blender/arm/material/shader.py
#	blender/arm/props_collision_filter_mask.py
#	blender/arm/props_ui.py
2021-04-03 14:12:54 +02:00
Lubos Lenco c9182cc152
Merge pull request #2149 from MoritzBrueckner/2.9-NishitaSky
[Blender 2.9] Nishita sky model & (ir)radiance support for all world shaders
2021-04-03 10:07:25 +02:00
Moritz Brückner 899411dea4 Cleanup write_probes.py 2021-04-02 14:57:11 +02:00
Lubos Lenco b930b87bc9 Bump version 2021-04-02 13:34:08 +02:00
Moritz Brückner 34f08e6922 Fix irradiance brightness
See write_sky_irradiance() for reference
2021-04-02 01:59:55 +02:00
Moritz Brückner 656b018e5f Render (ir)radiance probes if no other probes are set 2021-04-02 01:59:28 +02:00
Moritz Brückner c5be90d0b0 Cleanup 2021-03-31 20:33:52 +02:00
Moritz Brückner ffcc5fcceb Make clouds work with Nishita sky model 2021-03-31 20:31:31 +02:00
Lubos Lenco 67110c15a9
Merge pull request #2147 from N8n5h/light-fix
Fix case where sun shadows are not working if there are other type of lights present
2021-03-30 09:08:25 +02:00
N8n5h ead7dc9d32 Moved biasLWVP matrix uniform reference to a new one for sun
This was done because the original "_biasLightWorldViewProjectionMatrix"
relies on renderpath.light, which is problematic when rendering the
deferred light pass and there is a sun and other lights of different
type on the scene. Which would result on the wrong light being picked up
for the calculation of the uniform value.
2021-03-29 10:55:58 -03:00
Lubos Lenco 4a784c70a8
Merge pull request #2144 from MoritzBrueckner/fix-matnames
Replace ' and " characters in asset names
2021-03-27 09:04:25 +01:00
Lubos Lenco 44f08a16ae
Merge pull request #2141 from MoritzBrueckner/instancing-fix
Fix writing to gl_Position before instancing code
2021-03-27 09:03:08 +01:00
Moritz Brückner de8073732a Replace ' and " characters in asset names 2021-03-27 00:30:05 +01:00
Moritz Brückner 420033c86d Add API to set Nishita density parameters 2021-03-26 20:59:26 +01:00
Moritz Brückner 845d2aff93 Use switch/case for uniform links 2021-03-26 15:39:18 +01:00
Lubos Lenco 8118733474
Merge pull request #2139 from Naxela/master
Add map range node, vector rotate node, missing math operations and blackbody node
2021-03-26 08:24:41 +01:00
Moritz Brückner 8d812548c4 Use 2D LUT for Nishita skies 2021-03-25 23:29:34 +01:00
Moritz Brückner 05c14238f2 shader.py: add API to set texture params 2021-03-25 23:03:08 +01:00
Moritz Brückner 24093d15df Fix writing to gl_Position before instancing code 2021-03-25 22:02:59 +01:00
Alexander Kleemann 930b2968fa
Include cycles glsl functions for vector rotation 2021-03-24 10:20:05 +01:00
Alexander Kleemann 6e0bfa272c
Remove float parsing 2021-03-24 10:13:46 +01:00
Alexander Kleemann dfe1a49f85 Implement the remaining 16 math node operations
Math node is now fully supported
2021-03-23 22:02:25 +01:00
Alexander Kleemann 0cc2ea4491 Add map range and vector rotate to node parser dictionary 2021-03-23 21:58:46 +01:00
Alexander Kleemann 5c1f8fe128 Implement vector rotate node
Should now be fully supported
2021-03-23 21:56:14 +01:00
Alexander Kleemann 07741abc55 Implement map range node
Map range node should now be fully supported
2021-03-23 21:53:24 +01:00
Alexander Kleemann 362fffa408 Reimplement blackbody node from python to GLSL
Should now work with changing values
2021-03-23 21:51:28 +01:00
Lubos Lenco fb56d85d02
Merge pull request #2138 from Naxela/blender2.9
[Blender 2.9] Fix material translucency in Blender 2.9+
2021-03-23 12:30:34 +01:00
Alexander Kleemann eb6d23fab3 Fix material translucency in Blender 2.9+
The extra input node in the principled is now taken into consideration
2021-03-22 20:26:01 +01:00
Lubos Lenco dc81aca823
Merge pull request #2137 from N8n5h/tangent-error
Show error in the UI for tangent calculation error instead of just crashing to blender UI
2021-03-22 08:39:12 +01:00
Lubos Lenco d88d2320ed
Merge pull request #2135 from N8n5h/physics-2
Expose the exported rigid body type to the UI to make rb less confusing
2021-03-21 13:03:34 +01:00
N8n5h 7851abc491 Clear error count after building again 2021-03-20 21:26:05 -03:00
Lubos Lenco 54fcd49c27
Merge pull request #2134 from QuantumCoderQC/patch-1
Make description of logic node more precise
2021-03-20 09:58:36 +01:00
Lubos Lenco 451e3484f0
Merge pull request #2133 from Naxela/blender2.9
[Blender 2.9] Ready lightmapper for the transition to the next Blender LTS
2021-03-20 09:58:04 +01:00
Lubos Lenco 8df7f66872
Merge pull request #2131 from N8n5h/physics
Modified UI for collision filter props_collision_filter_mask
2021-03-19 19:07:33 +01:00
N8n5h 57660631b5 Log errors and show them in the blender UI 2021-03-19 11:39:06 -03:00
N8n5h d4463a3611 Catch tangent n-gon error to properly show it to the user
Instead of just letting it crash whenever the users hits play.
2021-03-19 10:22:01 -03:00
N8n5h a778460d28 Expose the exported rigid body type to the UI to make rb less confusing 2021-03-18 22:52:08 -03:00
QuantumCoderQC 255921b9ee
Make description of logic node more precise
The OnVolumeTrigger node does not required a RigidBody.
2021-03-18 21:34:59 +01:00
Alexander Kleemann 5fe816d16a Add in-menu option for OpenCV installation 2021-03-18 19:25:02 +01:00
Alexander Kleemann ef8fb21536 Update lightmapper to Blender 2.9+
Finalized update to support Blender 2.9+ as well as new features, fixes and more stability
2021-03-18 18:49:30 +01:00
Lubos Lenco 4b593af4ee
Merge pull request #2129 from knowledgenude/master
Fix clamp node
2021-03-18 11:49:15 +01:00
N8n5h ca2c3e151a Modified UI for collision filter props_collision_filter_mask
* Moved to collision filter mask panel under armory props to keep UI
more tidy.
* Moved the `arm_rb_collision_filter_mask` property out of the
props_collision_filter_mask to be with the rest of the properties.
* Changed name and description of collision filter mask to be more
consistent with the existing rigid body UI.
2021-03-17 20:28:26 -03:00
knowledgenude 1ad1d564bd
Fix clamp node 2021-03-16 18:27:42 -03:00
Lubos Lenco 7d78e01bb4
Merge pull request #2128 from N8n5h/light-fix-2
Fix shadows not working when there are lights present with cast_shadow=false
2021-03-16 08:28:19 +01:00
Lubos Lenco 95af8f2f77
Merge pull request #2127 from N8n5h/light-fix-mobile
Fix shadow rendering for point and spot lights for deferred and forward mobile
2021-03-16 08:24:49 +01:00
Lubos Lenco 71a5ac6f6e
Merge pull request #2126 from MoritzBrueckner/trait-props
Make `@prop` recognition more robust
2021-03-15 13:45:02 +01:00
N8n5h c7211542b4 Make pointLightData work with lights with cast_shadow=false 2021-03-14 23:21:02 -03:00
N8n5h 7463de6140 Add cast_shadow to lightArray data
This was done to undo the hardcoded nature of "receiveShadows", which
doesn't play nice when you have multiple lights of the same type and
one or several have cast_shadow set to false.

By simply "passing" the cast_shadow parameter within the lightArray it
was possible to detect lights that don't cast shadows before actually
wasting gpu cycles to render shadows with garbage data.

Support for deferred desktop and mobile, and forward was added.
2021-03-14 23:20:57 -03:00
N8n5h efcef7dd25 Fix shadow rendering for deferred and forward mobile 2021-03-14 22:04:47 -03:00
Lubos Lenco 26c29fe15e
Merge pull request #2125 from N8n5h/light-fix-2
Fix light visual artifact when close to the camera
2021-03-14 16:44:43 +01:00
Moritz Brückner b7fef30b70 Further improve handling of final trait props 2021-03-14 15:50:27 +01:00
Moritz Brückner 4ad68304e5 Improve @prop warning messages 2021-03-13 21:22:42 +01:00
Moritz Brückner 7d9c6ce7c7 Make @prop recognition much more robust 2021-03-13 21:12:12 +01:00
N8n5h 404a1248a1 Make clusterNear be the same as in LightObject 2021-03-13 13:30:25 -03:00
N8n5h 8e972f75fd Fix light visual artifact when close to the camera
This fixes a current problem with lights that occurs when getting too
close to the camera. The issue is related to the clustering algorithm
and cluster near.

Cluster near explanation:

Because of the logarithmic nature of how the Z slice is calculated,
clusters slices get "burned" too quickly at the start of the frustum,
which is not ideal. To aid this, and offset is applied to the start of
the cluster frustum, and that is clusterNear.

Cluster near solves that problem but creates another one: There is a gap
between the near plane and the cluster near offset that gets completely
ignored when calculating. And this results in the visual artifact of
slices not being affected by light whatsoever.

The proposed solution is make the gap resolve to the first slice of Z
clusters.
2021-03-13 13:30:19 -03:00
Moritz Brückner 5f55b00710 Begin with Nishita LUT implementation for better performance 2021-03-11 23:16:44 +01:00
Lubos Lenco b1a412cfc7
Merge pull request #2124 from Naxela/master
Fix for material NoneType and fix for Blender exit error
2021-03-11 14:03:49 +01:00
Alexander Kleemann e5d6c47e3e Fix Blender exit error (Keymap winman hangs) 2021-03-10 20:49:51 +01:00
Alexander Kleemann 4009d9d3fe Fix for an error with NoneType materials
Solves an error where an unallocated material slot caused a bug
2021-03-10 20:48:46 +01:00
Lubos Lenco 7c56ee9304
Merge pull request #2122 from N8n5h/light-fix
Fix forward+single atlas failing to compile with just 1 light
2021-03-03 08:26:38 +01:00
Lubos Lenco 70c46407c3
Merge pull request #2120 from N8n5h/light-fix-2
Fix shadow artifacts for HTML5 with shadow map atlas
2021-03-03 08:24:04 +01:00
N8n5h 72dde10fb0 Fix forward+single atlas failing to compile with just 1 light
This should fix an issue where the uniform for shadowMapAtlas used with the single atlas option was not added when having just 1 light.
2021-03-02 20:20:31 -03:00
N8n5h cf99e5a382 Fixed point lights breaking for Krom Windows with shadow map atlas
https://github.com/armory3d/armory/issues/2110#issuecomment-787913813
2021-03-01 18:39:32 -03:00
N8n5h 5f8b92f9c3 Applied flip workaround for point light too for html5 and atlas
The same concept for spot lights was applied for point lights;
the difference is that because point lights require to do the projection in the shader, the first inversion was applied in sampleCube() when returning the uv coordinates.
"_FlipY" was added to replace "_InvY" in "PCFFakeCube()" because the inversion is only necessary for shaders and not anything else, otherwise it would break rendering of other parts.
2021-03-01 18:39:32 -03:00
N8n5h c07de1cc25 Remove the inversion in shader of spot light uv for atlas
With the change in iron, there is no longer a need to do this in the shader.
2021-03-01 18:39:32 -03:00
luboslenco 4dbf8a3b2a Bump version 2021-03-01 09:07:33 +01:00
Lubos Lenco 4ea5156f1e
Merge pull request #2116 from tong/debug-param
Write debug param by default
2021-02-27 09:31:08 +01:00
tong 3e15ed9b5c Write debug param by default 2021-02-25 14:06:31 +01:00
Lubos Lenco 91a10bea5c
Merge pull request #2115 from tong/update-custom-icons
Update custom trait icons
2021-02-25 08:11:45 +01:00
Lubos Lenco 31f1b58c07
Merge pull request #2114 from Naxela/master
Blending fix + ignore irradiance per material
2021-02-23 11:14:11 +01:00
Moritz Brückner 742b9ce1e1 Nishita sky: add support for ozone density 2021-02-22 18:52:56 +01:00
tong dbee605e3f Downscale icons to 32px 2021-02-22 18:05:28 +01:00
tong d20656339b Update custom icons 2021-02-22 15:50:19 +01:00
Lubos Lenco e7ca541b51
Merge pull request #2113 from MoritzBrueckner/fix-1689
Fix drawing of bool properties in UI (#1689)
2021-02-22 09:47:51 +01:00
Lubos Lenco f99ff0576d
Merge pull request #2111 from tong/console-improvements
Console improvements
2021-02-21 10:24:41 +01:00
Moritz Brückner 92554876f1 Fix nishita sky altitude
The scale was changed in recent Blender builds
2021-02-21 01:12:15 +01:00
Alexander Kleemann aec10274f4 Add option to ignore irradiance for baked environments 2021-02-20 15:30:18 +01:00
Alexander Kleemann f1858550d0 Blending fix
Fix for https://github.com/armory3d/armory/issues/1615
2021-02-20 13:51:25 +01:00
tong 352f37db0c More f string 2021-02-20 09:53:48 +01:00
tong a1fce84f59 Use f string to format console messages 2021-02-20 09:36:42 +01:00
Lubos Lenco a25c5a744b
Merge pull request #2112 from SunDaw/pick-rb-node-mask
Add mask option to pick RB node and physicsworld
2021-02-20 09:05:03 +01:00
Moritz Brückner 98481929df Fix drawing of bool properties in UI (#1689) 2021-02-19 20:59:54 +01:00
SunDaw c5855ad96f Add mask option to pick RB node and physicsworld 2021-02-19 19:42:18 +01:00
tong 0abb43f249 Revert terminal color change 2021-02-19 17:25:42 +01:00
tong d93de12252 Print human readable time 2021-02-19 17:04:18 +01:00
tong 325f7471c0 Fix printing build flags 2021-02-19 17:01:09 +01:00
tong b7c4a8bb3f Improve console build messages 2021-02-19 16:57:12 +01:00
tong d4ee144577 Improve console warning 2021-02-19 16:53:01 +01:00
tong 8bc831d7e2 Show scene name in missing camera warning 2021-02-19 16:50:29 +01:00
Lubos Lenco 84663bc981
Merge pull request #2106 from SunDaw/optimize-sendevent-nodes
Remove array allocation from SendEventNode
2021-02-16 15:48:57 +01:00
Lubos Lenco 6beb9efb88
Merge pull request #2108 from knowledgenude/master
Improved FSM
2021-02-15 08:11:48 +01:00
Lubos Lenco 02e9ff7c5c
Merge pull request #2109 from N8n5h/light-fix-2
Make sure compiled.inc is always first when parsing shaders for clusters
2021-02-15 08:10:29 +01:00
N8n5h 3ef380978e Make sure compiled.inc is always first when parsing shaders for clusters 2021-02-14 20:21:51 -03:00
knowledgenude 0ee35adc81 Improved FSM 2021-02-14 19:21:26 -03:00
Lubos Lenco 49a599dc66
Merge pull request #2102 from N8n5h/light-fix-2
Add support for shadow map atlasing
2021-02-14 16:32:59 +01:00
Lubos Lenco 6d8012b45c
Merge pull request #2107 from SunDaw/optimize-physics
Reuse contacts array instead of creating new
2021-02-14 09:44:53 +01:00
Moritz Brückner 702436e2a1 Add artistic option for darkening clouds at night 2021-02-13 19:01:14 +01:00
Moritz Brückner 28011bcc00 Nishita sky: add sun disk drawing 2021-02-13 18:23:37 +01:00
Lubos Lenco 726e2fec6d
Merge pull request #2105 from MoritzBrueckner/custom-mat-operator
Add button to create a new custom material
2021-02-13 17:30:54 +01:00
SunDaw 6cbe539098 Reuse contacts array instead of creating new
Remove unused import from PhysicsWorld
2021-02-13 17:23:16 +01:00
SunDaw a2e4850b12 Remove array allocation from SendEventNode
Remove entires member variable from SendEvent nodes
2021-02-13 16:56:21 +01:00
Moritz Brückner b4d5afd561 Remove unused fragment shader input 2021-02-12 20:54:02 +01:00
Moritz Brückner b70a60078b Fix and improve comments 2021-02-12 20:24:42 +01:00
Moritz Brückner 52e4aaa21c Add button to create a new custom material 2021-02-12 20:12:55 +01:00
Moritz Brückner 3260e627ce Fix custom material export when scene is exported in arm format
See af247f1876 for reference
2021-02-12 00:31:19 +01:00
N8n5h c64b47548e Added support for direct3d-like texture coords uv for shadow atlases
See http://thedev-log.blogspot.com/2012/07/texture-coordinates-tutorial-opengl-and.html,
the "opengl coordinates" where inverted for proper support of direct3d texture coordinate system.
2021-02-10 21:03:10 -03:00
N8n5h 1c3e24a8fd Add support for shadow map atlasing
With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by
grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was
done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that
access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply
using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this
limitation was solved.

The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map
can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic
to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available
space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a
modified version of drawShadowMap().

Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice
that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the
tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial
4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth
levels is added or not when compiling.

the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner
subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a
linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make
some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that
utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-02-04 17:53:59 -03:00
Lubos Lenco f0d7effb7c
Merge pull request #2101 from MoritzBrueckner/fix-skinning-normals
Fix normals export of skinned materials
2021-02-03 18:28:53 +01:00
Moritz Brückner afe133381c Fix normals export of skinned materials 2021-02-03 18:23:22 +01:00
luboslenco 6ffa58fb6b Bump version 2021-02-01 10:00:43 +01:00
Lubos Lenco cbb8ee4bae
Merge pull request #2099 from MoritzBrueckner/2.9-LodOperators
Fix lod operator polling and add some bl_options
2021-02-01 09:55:22 +01:00
Moritz Brückner f2c16097d4 Fix lod operator polling and add some bl_options 2021-01-30 20:21:31 +01:00
Lubos Lenco d0e92b927b
Merge pull request #2097 from armory3d/2.9-AttributeNode
[Blender 2.9] Update attribute node
2021-01-30 19:57:17 +01:00
Moritz Brückner 121d449c35 Blender 2.9: Cycles attribute node - support object/custom properties 2021-01-30 14:19:46 +01:00
Moritz Brückner 75bb88831c Blender 2.9: Cycles attribute node - support alpha output and new attribute_type prop 2021-01-30 14:19:46 +01:00
Lubos Lenco 129d59ab54
Merge pull request #2096 from kevinresol/patch-4
[PickLocation] Actually return null when input invalid
2021-01-30 11:37:39 +01:00
Kevin Leung 4ee1131f6e
[PickLocation] Actually return null when input invalid 2021-01-29 20:54:34 +08:00
Lubos Lenco 4273aff1fb
Merge pull request #2094 from knowledgenude/master
Update inputmap and added finite state machine
2021-01-26 18:27:49 +01:00
Lubos Lenco 74b99411df
Merge pull request #2095 from tong/sdk-path-normalize
Normalize sdk path
2021-01-26 18:27:39 +01:00
tong 725520081a Normalize sdk path 2021-01-26 16:38:49 +01:00
knowledgenude 6ef1195816 Update inputmap and add FSM 2021-01-25 20:19:24 -03:00
Lubos Lenco 0fdb516083
Merge pull request #2093 from MoritzBrueckner/2.9-UI
[Blender 2.9] Various UI improvements & redesigns
2021-01-25 17:24:19 +01:00
Moritz Brückner a1bbd76de7 Fix: Remove unused/non-existing armory icon 2021-01-25 16:51:28 +01:00
Moritz Brückner e3f992b1f3 Whitespace cleanup 2021-01-25 16:48:03 +01:00
Moritz Brückner 05307817ee Fix grammar in warnings report 2021-01-25 16:47:51 +01:00
Moritz Brückner d55f889a84 Another small compositor panel UI improvement 2021-01-25 16:45:30 +01:00
Moritz Brückner 1d79708b22 Fix trait type backward compatibility with pre-Blender2.9 files 2021-01-25 16:23:03 +01:00
Moritz Brückner ba62ba0285 Blender 2.9: Fix/Improve collision filter mask UI 2021-01-25 14:01:53 +01:00
Moritz Brückner d7e70c4c0a Blender 2.9: Improve project flags panel UI 2021-01-25 13:58:47 +01:00
Moritz Brückner 6ae76bfdf6 Blender 2.9: Improve exporter panel UI 2021-01-25 13:53:28 +01:00
Moritz Brückner 6b6dc6264f Blender 2.9: Improve exporter settings UI 2021-01-24 20:42:18 +01:00
Lubos Lenco 888fb5c376
Merge pull request #2092 from tong/print-human-build-time
Print rounded build time to console
2021-01-24 18:56:47 +01:00
tong 8619006757 Print rounded build time to console 2021-01-24 18:36:58 +01:00
Moritz Brückner 288ead64dc Nishita sky: implement air and dust density 2021-01-21 21:14:05 +01:00
Moritz Brückner 396e60574a Optimize Nishita sky shader 2021-01-21 20:36:03 +01:00
Moritz Brückner 22d3530863 Blender 2.9: Add Nishita sky model implementation 2021-01-21 16:12:32 +01:00
Moritz Brückner 562d39c203 Blender 2.9: Improve Armory player panel UI 2021-01-17 20:24:43 +01:00
Moritz Brückner ffd3d6e824 Show is_object property when Add Trait is not invoked from the UI 2021-01-17 16:54:08 +01:00
Moritz Brückner 7b55f3d8f5 Blender 2.9: Improve Add Trait operator UI 2021-01-17 16:53:17 +01:00
Lubos Lenco f2e2a3d7dd
Merge pull request #2091 from MoritzBrueckner/fix-reroutes
Fix Reroute nodes
2021-01-17 09:15:59 +01:00
Moritz Brückner 41657adb64 Cleanup 2021-01-17 00:23:19 +01:00
Moritz Brückner fb8a056394 Fix reroute socket indices 2021-01-17 00:23:02 +01:00
Moritz Brückner ee1b55184c Move icon code into module
This, combined with lazy loading, has the advantage of using icons in property definitions before the actual registration code runs
2021-01-15 19:26:31 +01:00
Moritz Brückner fa7f58e4dd Ensure that only logic node trees show up as node traits 2021-01-14 22:46:22 +01:00
Moritz Brückner 04fdcc5500 Cleanup 2021-01-14 22:28:58 +01:00
Moritz Brückner 820de42e83 Blender 2.9: Fix lod list layout 2021-01-14 22:17:42 +01:00
Moritz Brückner fb88361c5b Blender 2.9: Simplify and improve trait panel UI 2021-01-14 22:14:50 +01:00
Moritz Brückner b7903dbef1 Change canvas icon according to the canvas node category 2021-01-14 22:14:10 +01:00
Moritz Brückner 40efd58214 Blender 2.9: Improve trait list UI and fix checkbox position 2021-01-14 21:24:42 +01:00
Moritz Brückner b4f0df6367 Blender 2.9: Redesign renderpath compositor panel UI 2021-01-14 21:21:01 +01:00
Moritz Brückner 133777f7e5 Blender 2.9: Improve renderpath postprocess panel UI 2021-01-14 21:18:46 +01:00
Moritz Brückner 406d48eb7c Blender 2.9: Improve renderpath world panel UI 2021-01-14 21:13:02 +01:00
Moritz Brückner 4c0f0f4161 Blender 2.9: slightly improve renderpath "Renderer" panel UI 2021-01-14 21:06:37 +01:00
Moritz Brückner a98559ea7f Blender 2.9: Improve material blending panel UI 2021-01-14 20:57:44 +01:00
Moritz Brückner 1b9f010c57 Blender 2.9: Improve project window panel UI 2021-01-14 20:56:04 +01:00
Lubos Lenco 0a5c209dd9
Merge pull request #2087 from knowledgenude/master
Update input mapper
2021-01-13 12:58:32 +01:00
knowledgenude 081fcb2870 update-inputmap 2021-01-11 18:14:21 -03:00
Lubos Lenco 9bab721f5f
Merge pull request #2086 from MoritzBrueckner/2.9-Search-Fixes
[Blender 2.9] Search menu fixes
2021-01-11 21:57:11 +01:00
Moritz Brückner 4920098831 Blender 2.9: Fix another exception when using the search menu 2021-01-11 19:57:29 +01:00
Moritz Brückner 4f25af45ba Cleanup 2021-01-11 19:56:40 +01:00
Moritz Brückner c69774402c Blender 2.9: Fix tilesheet operator exceptions when using the search menu 2021-01-11 19:51:15 +01:00
Lubos Lenco 70041fe2a5
Merge pull request #2085 from MoritzBrueckner/fix-bundled-edit
Fix editing bundled traits if the project was never compiled
2021-01-09 12:46:46 +01:00
Moritz Brückner e742ca76c0 Fix editing bundled traits if the project was never compiled 2021-01-08 22:40:14 +01:00
Lubos Lenco 833b513969
Merge pull request #2084 from QuantumCoderQC/29RBFix
Blender 2.9 Fix Exporter and conversions for Physics World
2021-01-07 11:49:58 +01:00
Lubos Lenco ad12af6933
Merge pull request #2083 from MoritzBrueckner/2.9-Operators
Blender 2.9: Update operator options
2021-01-07 11:49:15 +01:00
QuantumCoderQC 80ea09671c Fix Exporter and conversions for Physics World in Blender 2.9.X 2021-01-06 20:26:43 +01:00
Moritz Brückner c5e9522442 Blender 2.9: Update operator options 2021-01-06 17:23:21 +01:00
Lubos Lenco bf7592ae32
Merge pull request #2081 from MoritzBrueckner/2.9-PrincipledBSDF
[Blender 2.9] Principled BSDF: update input socket indices
2021-01-05 13:12:30 +01:00
Lubos Lenco b7dc297d04
Merge pull request #2080 from knowledgenude/master
Fix mouse wheel key verification
2021-01-05 13:11:54 +01:00
Moritz Brückner cab20d0a64 Principled BSDF: update input socket indices to Blender 2.9 2021-01-04 19:34:42 +01:00
knowledgenude ae057508ca
Fix mouse wheel key verification 2021-01-04 12:09:30 -03:00
Lubos Lenco bc36bf571e
Merge pull request #2079 from knowledgenude/master
Added input mapper
2021-01-04 15:41:22 +01:00
knowledgenude 24f62623ad add-inputmapper 2021-01-04 11:28:59 -03:00
luboslenco 27521265df Bump version 2021-01-03 12:11:59 +01:00
Lubos Lenco 5838401cd9
Merge pull request #2077 from MoritzBrueckner/2.9-UI-ObjectPanel
[Blender 2.9] Object panel UI
2021-01-01 12:58:31 +01:00
Lubos Lenco 97582968bd
Merge pull request #2076 from MoritzBrueckner/instancing
Show warnings for invalid instancing configurations + cleanup
2021-01-01 12:56:52 +01:00
Lubos Lenco c2bf021770
Merge pull request #2075 from MoritzBrueckner/world-warning
Show warning when scene is missing a world and rp background is set to world
2020-12-31 16:29:50 +01:00
Moritz Brückner 14bca0ec80 Shorten too long node trait operator labels 2020-12-30 17:57:23 +01:00
Moritz Brückner 4862054bcf Reorder trait type selection 2020-12-30 17:56:58 +01:00
Moritz Brückner 52cee7f0ce Update "Armory Traits" object panel to Blender 2.9 layouts 2020-12-30 17:56:34 +01:00
Moritz Brückner 257f295b27 Update "Armory Lod" object panel to Blender 2.9 layouts 2020-12-30 17:54:44 +01:00
Moritz Brückner a647263d1a Update "Armory Proxy" object panel to Blender 2.9 layouts 2020-12-30 17:53:35 +01:00
Moritz Brückner 6a6d383970 Update "Armory Props" object panel to Blender 2.9 layouts 2020-12-30 17:52:27 +01:00
Moritz Brückner 11591c79a4 Cleanup 2020-12-30 01:06:54 +01:00
Moritz Brückner 96dfc06295 Show warnings for invalid instancing configurations 2020-12-30 00:43:46 +01:00
Moritz Brückner 93dc0d248b Show warning when scene is missing a world and rp background is set to world 2020-12-29 17:39:18 +01:00
Lubos Lenco 18070621db
Merge pull request #2073 from N8n5h/cluster-fix
Solve artifact with clustering of lights
2020-12-29 10:56:19 +01:00
N8n5h b05f719392 Solve artifact for deferred mobile too 2020-12-27 16:45:27 -03:00
N8n5h 893b313643 Solve artifact with clustering of lights
Changed how a spot light is detected when sampling light, which caused false positives and produced
that visual artifact when a cluster/pixel was detected incorrectly as being lit with a spot light when maybe none were there.
This issue seems somewhat related to that issue that prevents rendering spotlights and point lights shadow at the same time.
2020-12-27 16:02:35 -03:00
Lubos Lenco 3e819d7e99
Merge pull request #2071 from QuantumCoderQC/animLoopFix
Add speed and looping options in Play Action From Node
2020-12-27 16:05:05 +01:00
QuantumCoderQC 174ce72349 Correct Spacing 2020-12-27 00:35:24 +01:00
QuantumCoderQC 4ee36afc0c Add Speed and Loop options for Play Action From Node 2020-12-27 00:29:03 +01:00
Lubos Lenco 2dcd1a951b
Merge pull request #2066 from knowledgenude/master
Fix inverted margin for Kinematic Character
2020-12-26 10:22:31 +01:00
Lubos Lenco 268a59a4c7
Merge pull request #2068 from QuantumCoderQC/conFix
Improve physics constraint handling
2020-12-25 19:01:42 +01:00
QuantumCoderQC a0422d49f2 Improve physics constraint handling 2020-12-23 16:03:45 +01:00
Lubos Lenco 569b2daecc
Merge pull request #2065 from MoritzBrueckner/node-side-panel
Improve node side panel + context menu (more operators, icons)
2020-12-23 13:08:38 +01:00
knowledgenude f836e597d1 fix-inverted-margin 2020-12-22 20:49:03 -03:00
Moritz Brückner 372419c9ff arm.open_node_documentation: add icon and fix docstring 2020-12-22 17:25:26 +01:00
Lubos Lenco 70b989e25f
Merge pull request #2064 from MoritzBrueckner/pose-markers
Fix bone markers export
2020-12-20 11:50:45 +01:00
Lubos Lenco 3d69855935
Merge pull request #2063 from MoritzBrueckner/relative-paths
Use relative paths only when path/reference are on the same drive
2020-12-20 11:50:29 +01:00
Lubos Lenco 6ee5af2518
Merge pull request #2062 from QuantumCoderQC/conFix
Fix adding physics constraint at game start
2020-12-19 11:20:39 +01:00
Lubos Lenco 61986dfafd
Merge pull request #2061 from knowledgenude/master
Added World Vector to Local Space node
2020-12-19 11:19:02 +01:00
Moritz Brückner 15d832c66c Show node operator icons in dropdown menu 2020-12-19 01:11:55 +01:00
Moritz Brückner df522516f2 Rename Armory nodes panel: 'Node' -> 'Armory' 2020-12-19 01:09:55 +01:00
Moritz Brückner 76b2380ec4 Improve node side panel (more operators, icons) 2020-12-19 01:08:52 +01:00
Lubos Lenco fa6d1903c7
Merge pull request #2060 from onelsonic/patch-1
Update math.glsl
2020-12-18 10:35:29 +01:00
Moritz Brückner 563c04f456 Whitespace cleanup 2020-12-17 23:44:59 +01:00
Moritz Brückner f68debf39a Fix bone markers export 2020-12-17 23:44:51 +01:00
Moritz Brückner 3f1200417c Cleanup imports 2020-12-17 23:34:38 +01:00
Moritz Brückner 0bda1abfb7 Optimize on_same_drive() calls 2020-12-17 23:19:56 +01:00
Moritz Brückner 397d860a5a Cleanup write_data.py 2020-12-17 22:57:09 +01:00
Moritz Brückner d7e5d07e52 Only use relative paths when path/reference are on the same drive 2020-12-17 22:25:00 +01:00
QuantumCoderQC 2f911c756e Remove physics constraint helper trait 2020-12-17 15:05:46 +01:00
QuantumCoderQC bf22d7add6 Fix physics constraints at start-up 2020-12-17 15:01:21 +01:00
knowledgenude 570de6f699 fix-cap 2020-12-16 17:27:25 -03:00
knowledgenude 8c1baa2e9a add-world-vector-to-local-space-node 2020-12-16 17:24:43 -03:00
onelsonic a89e3923e7
Update math.glsl
fixing the float
2020-12-16 18:57:25 +01:00
Lubos Lenco 882dea8d6c
Merge pull request #2058 from MoritzBrueckner/dynamic-node-labels
Add dynamic node labels
2020-12-16 10:50:25 +01:00
Lubos Lenco e2231c7f16
Merge pull request #2055 from MoritzBrueckner/shader-uniform-node
Add SetShaderUniform node
2020-12-16 10:48:10 +01:00
Lubos Lenco 1b6d321eaa
Merge pull request #2056 from MoritzBrueckner/sound-node-stream
Add 'stream' option to Play Sound nodes
2020-12-16 10:47:40 +01:00
Moritz Brückner 76389c8652 Add dynamic node labels 2020-12-15 23:47:38 +01:00
Moritz Brückner b03e15edba Add 'stream' option to Play Sound nodes 2020-12-13 22:53:36 +01:00
Moritz Brückner 62dbc5f34a Add SetShaderUniform node 2020-12-13 22:41:05 +01:00
Lubos Lenco f69185a765
Merge pull request #2053 from QuantumCoderQC/ParticleFix
Fix normals and wposition in custom particle node
2020-12-12 18:24:05 +01:00
QuantumCoderQC c0bde50306 Fix normals and wposition in custom particle node 2020-12-12 14:10:03 +01:00
Lubos Lenco 9f35d55bd3
Merge pull request #2047 from QuantumCoderQC/bcon_nodes
New Physics Constraint nodes. Improve Bullet Physics constraint trait
2020-12-06 09:19:14 +01:00
Lubos Lenco fdcdf86c24
Merge pull request #2046 from MoritzBrueckner/node-replacement
Fix and further improve node replacement system
2020-12-06 09:17:38 +01:00
Lubos Lenco bcfbdae925
Merge pull request #2045 from knowledgenude/master
Fix volume trigger
2020-12-06 09:16:12 +01:00
Moritz Brückner 16700de7f0 Node replacement: write error message after file has been written 2020-12-05 12:50:05 +01:00
Moritz Brückner 10587900d4 Node replacement: give credit to @niacdoial (code moved to other module) 2020-12-05 12:48:49 +01:00
QuantumCoderQC 71763f9e47 Custom constraint node implemetation 2020-12-05 01:12:59 +01:00
QuantumCoderQC 8a1b59ef8b Haxe implementation of AddPhysicsTrait. 2020-12-05 01:12:59 +01:00
QuantumCoderQC c845301f7c New logic node to add custom physics constraints. Add documentation. 2020-12-05 01:12:59 +01:00
QuantumCoderQC c250be4735 Improvise logic node implementation. 2020-12-05 01:12:59 +01:00
QuantumCoderQC 300f5e37ea Add documentation. Cleanup. 2020-12-05 01:12:59 +01:00
QuantumCoderQC aab7a027c6 Add support functions to set limits. Add documentation. 2020-12-05 01:12:59 +01:00
QuantumCoderQC d87be744b2 Change SetDecativationParams in node to setUpDeactivation to prevent runtime errors. 2020-12-05 01:12:59 +01:00
QuantumCoderQC e2511fd460 Trying new designs 2020-12-05 01:12:59 +01:00
QuantumCoderQC 02e52341a5 New node to add physics constraints 2020-12-05 01:12:59 +01:00
QuantumCoderQC ca9be33152 Added addPhysicsConstraint and removePhysicsConstraint methods. Added internal Map to keep track of PhysicsConstraints 2020-12-05 01:12:59 +01:00
QuantumCoderQC 951f8298b8 Modify to use iron.object.Object instead of String for objects to be linked by PhysicsConstraint 2020-12-05 01:12:59 +01:00
QuantumCoderQC 174a7f66dd Modify exporter to use PhysicsConstraintExportHelper class 2020-12-05 01:12:59 +01:00
QuantumCoderQC 49e06b4b63 New helper class to add physics constraints via Blender Armory exporter 2020-12-05 01:12:59 +01:00
Moritz Brückner 01874e2287 Replacement error dialog: add button to open report folder 2020-12-04 22:57:47 +01:00
Moritz Brückner bd5953c39f Improve module docstring 2020-12-04 22:53:06 +01:00
Moritz Brückner 1b210d0f00 Node replacement: report original traceback for unknown exceptions 2020-12-04 22:50:25 +01:00
Moritz Brückner 332d60547b Node replacement: improve console output 2020-12-04 22:36:38 +01:00
Moritz Brückner 16376dafe2 Simplify replacement error handling 2020-12-04 22:32:44 +01:00
Moritz Brückner 0bddfea5e3 Move node replacement system into its own module 2020-12-04 22:29:31 +01:00
Moritz Brückner b5e33062b3 Improve replacement error message 2020-12-04 21:55:02 +01:00
Moritz Brückner 1fb1196979 Remove replacement node on error during replacement 2020-12-04 21:25:51 +01:00
Moritz Brückner e53d9446e7 Cleanup 2020-12-04 21:17:50 +01:00
knowledgenude 90daf7e077 rename-labels 2020-12-04 09:49:50 -03:00
knowledgenude d726e8fc83 fix-volume-trigger 2020-12-04 07:20:42 -03:00
Lubos Lenco 9ce721103e
Merge pull request #2042 from E1e5en/html5-settings-more
Added option for HTML5 Settings
2020-12-03 10:56:52 +01:00
E1e5en 59c31950c8 Added option for HTML5 Settings
- Disable browser context menu - disable the browser context menu for the canvas element on the page (index.html).
2020-12-02 20:54:14 +03:00
Lubos Lenco bd6078e303
Merge pull request #2037 from E1e5en/fix-on-swipe
Fix OnSwipe
2020-12-02 10:21:12 +01:00
E1e5en 1867975099 Fix OnSwipe
Correction of determining the direction of UP-LEFT.
Wrong 9 degrees =)
2020-12-01 21:18:12 +03:00
610 changed files with 19529 additions and 5558 deletions

View file

@ -4,7 +4,9 @@
uniform sampler2D tex;
#ifdef _CPostprocess
uniform vec3 PPComp10;
#endif
in vec2 texCoord;
out vec4 fragColor;

View file

@ -8,7 +8,8 @@
"links": [
{
"name": "PPComp10",
"link": "_PPComp10"
"link": "_PPComp10",
"ifdef": ["_CPostprocess"]
}
],
"texture_params": [],

View file

@ -7,7 +7,9 @@ uniform sampler2D tex;
uniform vec2 dir;
uniform vec2 screenSize;
#ifdef _CPostprocess
uniform vec3 PPComp11;
#endif
in vec2 texCoord;
out vec4 fragColor;
@ -26,7 +28,7 @@ void main() {
fragColor.rgb += textureLod(tex, texCoord + s, 0.0).rgb * weight[i];
fragColor.rgb += textureLod(tex, texCoord - s, 0.0).rgb * weight[i];
}
#ifdef _CPostprocess
fragColor.rgb *= PPComp11.x / 5;
#else

View file

@ -16,7 +16,8 @@
},
{
"name": "PPComp11",
"link": "_PPComp11"
"link": "_PPComp11",
"ifdef": ["_CPostprocess"]
}
],
"texture_params": [],
@ -39,7 +40,8 @@
},
{
"name": "PPComp11",
"link": "_PPComp11"
"link": "_PPComp11",
"ifdef": ["_CPostprocess"]
}
],
"texture_params": [],
@ -65,7 +67,8 @@
},
{
"name": "PPComp11",
"link": "_PPComp11"
"link": "_PPComp11",
"ifdef": ["_CPostprocess"]
}
],
"texture_params": [],

View file

@ -3,7 +3,10 @@
#include "compiled.inc"
uniform sampler2D tex;
#ifdef _CPostprocess
uniform vec3 PPComp13;
#endif
in vec2 texCoord;
out vec4 fragColor;

View file

@ -9,7 +9,8 @@
"links": [
{
"name": "PPComp13",
"link": "_PPComp13"
"link": "_PPComp13",
"ifdef": ["_CPostprocess"]
}
],
"texture_params": [],

View file

@ -0,0 +1,31 @@
#version 450
// Include functions for gbuffer operations (packFloat2() etc.)
#include "../std/gbuffer.glsl"
// World-space normal from the vertex shader stage
in vec3 wnormal;
// Gbuffer output. Deferred rendering uses the following layout:
// [0]: normal x normal y roughness metallic/matID
// [1]: base color r base color g base color b occlusion/specular
out vec4 fragColor[2];
void main() {
// Pack normals into 2 components to fit into the gbuffer
vec3 n = normalize(wnormal);
n /= (abs(n.x) + abs(n.y) + abs(n.z));
n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);
// Define PBR material values
vec3 basecol = vec3(1.0);
float roughness = 0.0;
float metallic = 0.0;
float occlusion = 1.0;
float specular = 1.0;
uint materialId = 0;
// Store in gbuffer (see layout table above)
fragColor[0] = vec4(n.xy, roughness, packFloatInt16(metallic, materialId));
fragColor[1] = vec4(basecol.rgb, packFloat2(occlusion, specular));
}

View file

@ -0,0 +1,20 @@
#version 450
// World to view projection matrix to correctly position the vertex on screen
uniform mat4 WVP;
// Matrix to transform normals from local into world space
uniform mat3 N;
// Position and normal vectors of the current vertex in local space
// Armory packs the vertex data to preserve memory, so nor.z values are
// saved in pos.w
in vec4 pos; // pos.xyz, nor.w
in vec2 nor; // nor.xy
// Normal vector in world space
out vec3 wnormal;
void main() {
wnormal = normalize(N * vec3(nor.xy, pos.w));
gl_Position = WVP * vec4(pos.xyz, 1.0);
}

View file

@ -0,0 +1,9 @@
#version 450
// Color of each fragment on the screen
out vec4 fragColor;
void main() {
// Shadeless white color
fragColor = vec4(1.0);
}

View file

@ -0,0 +1,11 @@
#version 450
// World to view projection matrix to correctly position the vertex on screen
uniform mat4 WVP;
// Position vector of the current vertex in local space
in vec3 pos;
void main() {
gl_Position = WVP * vec4(pos, 1.0);
}

View file

@ -2,7 +2,6 @@
#include "compiled.inc"
#include "std/gbuffer.glsl"
#include "std/light.glsl"
#ifdef _Clusters
#include "std/clusters.glsl"
#endif
@ -22,6 +21,9 @@
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1;
#ifdef _gbuffer2
uniform sampler2D gbuffer2;
#endif
#ifdef _VoxelAOvar
uniform sampler3D voxels;
@ -80,14 +82,11 @@ uniform mat4 invVP;
#ifdef _ShadowMap
#ifdef _SinglePoint
//!uniform sampler2DShadow shadowMapSpot[1];
//!uniform mat4 LWVPSpot0;
//!uniform mat4 LWVPSpot[1];
#endif
#ifdef _Clusters
//!uniform sampler2DShadow shadowMapSpot[4];
//!uniform mat4 LWVPSpot0;
//!uniform mat4 LWVPSpot1;
//!uniform mat4 LWVPSpot2;
//!uniform mat4 LWVPSpot3;
//!uniform mat4 LWVPSpotArray[4];
#endif
#endif
#endif
@ -97,7 +96,7 @@ uniform vec3 eye;
uniform vec3 eyeLook;
#ifdef _Clusters
uniform vec4 lightsArray[maxLights * 2];
uniform vec4 lightsArray[maxLights * 3];
#ifdef _Spot
uniform vec4 lightsArraySpot[maxLights];
#endif
@ -109,21 +108,36 @@ uniform vec2 cameraPlane;
#ifdef _SinglePoint
#ifdef _Spot
//!uniform sampler2DShadow shadowMapSpot[1];
//!uniform mat4 LWVPSpot0;
//!uniform mat4 LWVPSpot[1];
#else
//!uniform samplerCubeShadow shadowMapPoint[1];
//!uniform vec2 lightProj;
#endif
#endif
#ifdef _Clusters
//!uniform samplerCubeShadow shadowMapPoint[4];
#ifdef _ShadowMapAtlas
#ifdef _SingleAtlas
uniform sampler2DShadow shadowMapAtlas;
#endif
#endif
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlasPoint;
#endif
//!uniform vec4 pointLightDataArray[4];
#else
//!uniform samplerCubeShadow shadowMapPoint[4];
#endif
//!uniform vec2 lightProj;
#ifdef _Spot
//!uniform sampler2DShadow shadowMapSpot[4];
//!uniform mat4 LWVPSpot0;
//!uniform mat4 LWVPSpot1;
//!uniform mat4 LWVPSpot2;
//!uniform mat4 LWVPSpot3;
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlasSpot;
#endif
#else
//!uniform sampler2DShadow shadowMapSpot[4];
#endif
//!uniform mat4 LWVPSpotArray[4];
#endif
#endif
#endif
@ -132,7 +146,13 @@ uniform vec2 cameraPlane;
uniform vec3 sunDir;
uniform vec3 sunCol;
#ifdef _ShadowMap
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSun;
#endif
#else
uniform sampler2DShadow shadowMap;
#endif
uniform float shadowsBias;
#ifdef _CSM
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
@ -159,6 +179,8 @@ uniform sampler2D texClouds;
uniform float time;
#endif
#include "std/light.glsl"
in vec2 texCoord;
in vec3 viewRay;
out vec4 fragColor;
@ -186,6 +208,10 @@ void main() {
vec3 v = normalize(eye - p);
float dotNV = max(dot(n, v), 0.0);
#ifdef _gbuffer2
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
#endif
#ifdef _MicroShadowing
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
#endif
@ -196,9 +222,19 @@ void main() {
// Envmap
#ifdef _Irr
vec3 envl = shIrradiance(n, shirr);
#ifdef _gbuffer2
if (g2.b < 0.5) {
envl = envl;
} else {
envl = vec3(1.0);
}
#endif
#ifdef _EnvTex
envl /= PI;
envl /= PI;
#endif
#else
vec3 envl = vec3(1.0);
@ -289,10 +325,32 @@ void main() {
#ifdef _ShadowMap
#ifdef _CSM
svisibility = shadowTestCascade(shadowMap, eye, p + n * shadowsBias * 10, shadowsBias);
svisibility = shadowTestCascade(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
, eye, p + n * shadowsBias * 10, shadowsBias
);
#else
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
if (lPos.w > 0.0) svisibility = shadowTest(shadowMap, lPos.xyz / lPos.w, shadowsBias);
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
if (lPos.w > 0.0) svisibility = shadowTest(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
, lPos.xyz / lPos.w, shadowsBias
);
#endif
#endif
@ -335,7 +393,18 @@ void main() {
int casi, casindex;
mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex);
#endif
fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVP, p, n, sunDir, lightPlane.y, shadowMap);
fragColor.rgb += fragColor.rgb * SSSSTransmittance(
LWVP, p, n, sunDir, lightPlane.y,
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
);
}
#endif
@ -393,18 +462,19 @@ void main() {
n,
v,
dotNV,
lightsArray[li * 2].xyz, // lp
lightsArray[li * 2 + 1].xyz, // lightCol
lightsArray[li * 3].xyz, // lp
lightsArray[li * 3 + 1].xyz, // lightCol
albedo,
roughness,
occspec.y,
f0
#ifdef _ShadowMap
, li, lightsArray[li * 2].w, true // bias
// light index, shadow bias, cast_shadows
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0
#endif
#ifdef _Spot
, li > numPoints - 1
, lightsArray[li * 2 + 1].w // cutoff
, lightsArray[li * 3 + 2].y != 0.0
, lightsArray[li * 3 + 2].y // cutoff
, lightsArraySpot[li].w // cutoff - exponent
, lightsArraySpot[li].xyz // spotDir
#endif

View file

@ -99,7 +99,7 @@
},
{
"name": "LWVP",
"link": "_biasLightWorldViewProjectionMatrix",
"link": "_biasLightWorldViewProjectionMatrixSun",
"ifndef": ["_CSM"],
"ifdef": ["_Sun", "_ShadowMap"]
},
@ -199,43 +199,37 @@
"ifdef": ["_SinglePoint", "_Spot"]
},
{
"name": "LWVPSpot0",
"name": "LWVPSpotArray",
"link": "_biasLightWorldViewProjectionMatrixSpotArray",
"ifdef": ["_Clusters", "_ShadowMap", "_Spot"]
},
{
"name": "pointLightDataArray",
"link": "_pointLightsAtlasArray",
"ifdef": ["_Clusters", "_ShadowMap", "_ShadowMapAtlas"]
},
{
"name": "LWVPSpot[0]",
"link": "_biasLightWorldViewProjectionMatrixSpot0",
"ifdef": ["_Spot", "_ShadowMap"]
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot1",
"name": "LWVPSpot[1]",
"link": "_biasLightWorldViewProjectionMatrixSpot1",
"ifdef": ["_Spot", "_ShadowMap"]
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot2",
"name": "LWVPSpot[2]",
"link": "_biasLightWorldViewProjectionMatrixSpot2",
"ifdef": ["_Spot", "_ShadowMap"]
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot3",
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifdef": ["_Spot", "_ShadowMap"]
},
{
"name": "LWVPSpot0",
"link": "_biasLightWorldViewProjectionMatrixSpot0",
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot1",
"link": "_biasLightWorldViewProjectionMatrixSpot1",
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot2",
"link": "_biasLightWorldViewProjectionMatrixSpot2",
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot3",
"name": "LWVPSpot[3]",
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
}
],

View file

@ -3,7 +3,6 @@
#include "compiled.inc"
#include "std/gbuffer.glsl"
#include "std/math.glsl"
#include "std/light_mobile.glsl"
#ifdef _Clusters
#include "std/clusters.glsl"
#endif
@ -30,12 +29,15 @@ uniform int envmapNumMipmaps;
uniform vec3 backgroundCol;
#endif
#ifdef _SMSizeUniform
//!uniform vec2 smSizeUniform;
#endif
uniform vec2 cameraProj;
uniform vec3 eye;
uniform vec3 eyeLook;
#ifdef _Clusters
uniform vec4 lightsArray[maxLights * 2];
uniform vec4 lightsArray[maxLights * 3];
#ifdef _Spot
uniform vec4 lightsArraySpot[maxLights];
#endif
@ -47,21 +49,36 @@ uniform vec2 cameraPlane;
#ifdef _SinglePoint
#ifdef _Spot
//!uniform sampler2DShadow shadowMapSpot[1];
//!uniform mat4 LWVPSpot0;
//!uniform mat4 LWVPSpot[1];
#else
//!uniform samplerCubeShadow shadowMapPoint[1];
//!uniform vec2 lightProj;
#endif
#endif
#ifdef _Clusters
//!uniform samplerCubeShadow shadowMapPoint[4];
#ifdef _ShadowMapAtlas
#ifdef _SingleAtlas
uniform sampler2DShadow shadowMapAtlas;
#endif
#endif
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlasPoint;
#endif
//!uniform vec4 pointLightDataArray[4];
#else
//!uniform samplerCubeShadow shadowMapPoint[4];
#endif
//!uniform vec2 lightProj;
#ifdef _Spot
//!uniform sampler2DShadow shadowMapSpot[4];
//!uniform mat4 LWVPSpot0;
//!uniform mat4 LWVPSpot1;
//!uniform mat4 LWVPSpot2;
//!uniform mat4 LWVPSpot3;
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlasSpot;
#endif
#else
//!uniform sampler2DShadow shadowMapSpot[4];
#endif
//!uniform mat4 LWVPSpotArray[4];
#endif
#endif
#endif
@ -70,7 +87,13 @@ uniform vec2 cameraPlane;
uniform vec3 sunDir;
uniform vec3 sunCol;
#ifdef _ShadowMap
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSun;
#endif
#else
uniform sampler2DShadow shadowMap;
#endif
uniform float shadowsBias;
#ifdef _CSM
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
@ -90,6 +113,8 @@ uniform float pointBias;
#endif
#endif
#include "std/light_mobile.glsl"
in vec2 texCoord;
in vec3 viewRay;
out vec4 fragColor;
@ -168,10 +193,32 @@ void main() {
#ifdef _ShadowMap
#ifdef _CSM
svisibility = shadowTestCascade(shadowMap, eye, p + n * shadowsBias * 10, shadowsBias, shadowmapSize * vec2(shadowmapCascades, 1.0));
svisibility = shadowTestCascade(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
, eye, p + n * shadowsBias * 10, shadowsBias
);
#else
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
if (lPos.w > 0.0) svisibility = shadowTest(shadowMap, lPos.xyz / lPos.w, shadowsBias, shadowmapSize);
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
if (lPos.w > 0.0) svisibility = shadowTest(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
, lPos.xyz / lPos.w, shadowsBias
);
#endif
#endif
@ -211,18 +258,19 @@ void main() {
n,
v,
dotNV,
lightsArray[li * 2].xyz, // lp
lightsArray[li * 2 + 1].xyz, // lightCol
lightsArray[li * 3].xyz, // lp
lightsArray[li * 3 + 1].xyz, // lightCol
albedo,
roughness,
occspec.y,
f0
#ifdef _ShadowMap
, li, lightsArray[li * 2].w, true // bias
// light index, shadow bias, cast_shadows
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0
#endif
#ifdef _Spot
, li > numPoints - 1
, lightsArray[li * 2 + 1].w // cutoff
, lightsArray[li * 3 + 2].y != 0.0
, lightsArray[li * 3 + 2].y // cutoff
, lightsArraySpot[li].w // cutoff - exponent
, lightsArraySpot[li].xyz // spotDir
#endif

View file

@ -88,7 +88,7 @@
},
{
"name": "LWVP",
"link": "_biasLightWorldViewProjectionMatrix",
"link": "_biasLightWorldViewProjectionMatrixSun",
"ifndef": ["_CSM"],
"ifdef": ["_Sun", "_ShadowMap"]
},
@ -107,6 +107,11 @@
"link": "_viewProjectionMatrix",
"ifdef": ["_SSRS"]
},
{
"name": "smSizeUniform",
"link": "_shadowMapSize",
"ifdef": ["_SMSizeUniform"]
},
{
"name": "lightProj",
"link": "_lightPlaneProj",
@ -138,24 +143,38 @@
"ifdef": ["_SinglePoint", "_Spot"]
},
{
"name": "LWVPSpot0",
"name": "LWVPSpotArray",
"link": "_biasLightWorldViewProjectionMatrixSpotArray",
"ifdef": ["_Clusters", "_ShadowMap", "_Spot"]
},
{
"name": "pointLightDataArray",
"link": "_pointLightsAtlasArray",
"ifdef": ["_Clusters", "_ShadowMap", "_ShadowMapAtlas"]
},
{
"name": "LWVPSpot[0]",
"link": "_biasLightWorldViewProjectionMatrixSpot0",
"ifdef": ["_Spot", "_ShadowMap"]
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot1",
"name": "LWVPSpot[1]",
"link": "_biasLightWorldViewProjectionMatrixSpot1",
"ifdef": ["_Spot", "_ShadowMap"]
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot2",
"name": "LWVPSpot[2]",
"link": "_biasLightWorldViewProjectionMatrixSpot2",
"ifdef": ["_Spot", "_ShadowMap"]
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot3",
"name": "LWVPSpot[3]",
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifdef": ["_Spot", "_ShadowMap"]
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
}
],
"vertex_shader": "../include/pass_viewray.vert.glsl",

View file

@ -12,8 +12,10 @@ uniform vec3 eyeLook;
uniform vec2 screenSize;
uniform mat4 invVP;
#ifdef _CPostprocess
uniform vec3 PPComp11;
uniform vec3 PPComp12;
#endif
in vec2 texCoord;
in vec3 viewRay;
@ -23,12 +25,12 @@ void main() {
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
if (depth == 1.0) { fragColor = 1.0; return; }
vec2 enc = textureLod(gbuffer0, texCoord, 0.0).rg;
vec2 enc = textureLod(gbuffer0, texCoord, 0.0).rg;
vec3 n;
n.z = 1.0 - abs(enc.x) - abs(enc.y);
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
n = normalize(n);
vec3 vray = normalize(viewRay);
vec3 currentPos = getPosNoEye(eyeLook, vray, depth, cameraProj);
// vec3 currentPos = getPos2NoEye(eye, invVP, depth, texCoord);
@ -53,7 +55,7 @@ void main() {
vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos;
fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015);
}
#ifdef _CPostprocess
fragColor *= (PPComp12.x * 0.3) / samples;
#else

View file

@ -28,11 +28,13 @@
},
{
"name": "PPComp11",
"link": "_PPComp11"
"link": "_PPComp11",
"ifdef": ["_CPostprocess"]
},
{
"name": "PPComp12",
"link": "_PPComp12"
"link": "_PPComp12",
"ifdef": ["_CPostprocess"]
}
],
"texture_params": [],

View file

@ -12,8 +12,10 @@ uniform mat4 P;
uniform mat3 V3;
uniform vec2 cameraProj;
#ifdef _CPostprocess
uniform vec3 PPComp9;
uniform vec3 PPComp10;
#endif
in vec3 viewRay;
in vec2 texCoord;

View file

@ -24,11 +24,13 @@
},
{
"name": "PPComp9",
"link": "_PPComp9"
"link": "_PPComp9",
"ifdef": ["_CPostprocess"]
},
{
"name": "PPComp10",
"link": "_PPComp10"
"link": "_PPComp10",
"ifdef": ["_CPostprocess"]
}
],
"texture_params": [],

View file

@ -1,7 +1,4 @@
const int maxLights = 16;
const int maxLightsCluster = 4; // Ensure fast loop unroll before going higher
const float clusterNear = 3.0;
const vec3 clusterSlices = vec3(16, 16, 16);
int getClusterI(vec2 tc, float viewz, vec2 cameraPlane) {
@ -11,6 +8,10 @@ int getClusterI(vec2 tc, float viewz, vec2 cameraPlane) {
float z = log(viewz - cnear + 1.0) / log(cameraPlane.y - cnear + 1.0);
sliceZ = int(z * (clusterSlices.z - 1)) + 1;
}
// address gap between near plane and cluster near offset
else if (viewz >= cameraPlane.x) {
sliceZ = 1;
}
return int(tc.x * clusterSlices.x) +
int(int(tc.y * clusterSlices.y) * clusterSlices.x) +
int(sliceZ * clusterSlices.x * clusterSlices.y);

View file

@ -21,27 +21,41 @@
#endif
#ifdef _ShadowMap
#ifdef _SinglePoint
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot0;
#else
uniform samplerCubeShadow shadowMapPoint[1];
uniform vec2 lightProj;
#ifdef _SinglePoint
#ifdef _Spot
#ifndef _LTC
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot[1];
#endif
#else
uniform samplerCubeShadow shadowMapPoint[1];
uniform vec2 lightProj;
#endif
#endif
#endif
#ifdef _Clusters
uniform samplerCubeShadow shadowMapPoint[4];
uniform vec2 lightProj;
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[4];
uniform mat4 LWVPSpot0;
uniform mat4 LWVPSpot1;
uniform mat4 LWVPSpot2;
uniform mat4 LWVPSpot3;
#ifdef _Clusters
#ifdef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlas;
#endif
uniform vec2 lightProj;
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasPoint;
#endif
#else
uniform samplerCubeShadow shadowMapPoint[4];
#endif
#ifdef _Spot
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSpot;
#endif
#else
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
#endif
uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif
#endif
#endif
#endif
#ifdef _LTC
uniform vec3 lightArea0;
@ -51,17 +65,14 @@ uniform vec3 lightArea3;
uniform sampler2D sltcMat;
uniform sampler2D sltcMag;
#ifdef _ShadowMap
#ifndef _Spot
#ifndef _Spot
#ifdef _SinglePoint
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot0;
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot[1];
#endif
#ifdef _Clusters
uniform sampler2DShadow shadowMapSpot[4];
uniform mat4 LWVPSpot0;
uniform mat4 LWVPSpot1;
uniform mat4 LWVPSpot2;
uniform mat4 LWVPSpot3;
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif
#endif
#endif
@ -132,24 +143,24 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#endif
#ifdef _Clusters
if (index == 0) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
}
else if (index == 1) {
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpot[1] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
}
else if (index == 2) {
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpot[2] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
}
else if (index == 3) {
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpot[3] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
}
#endif
@ -168,26 +179,26 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#endif
#ifdef _Clusters
if (index == 0) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
}
else if (index == 1) {
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
}
else if (index == 2) {
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
}
else if (index == 3) {
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
}
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas
direct *= shadowTest(
#ifndef _SingleAtlas
shadowMapAtlasSpot
#else
shadowMapAtlas
#endif
, lPos.xyz / lPos.w, bias
);
#else
if (index == 0) direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
#endif
#endif
}
#endif
@ -207,10 +218,21 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#endif
#endif
#ifdef _Clusters
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#ifdef _ShadowMapAtlas
direct *= PCFFakeCube(
#ifndef _SingleAtlas
shadowMapAtlasPoint
#else
shadowMapAtlas
#endif
, ld, -l, bias, lightProj, n, index
);
#else
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#endif
#endif
}
#endif

View file

@ -8,27 +8,39 @@
#endif
#ifdef _ShadowMap
#ifdef _SinglePoint
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot0;
#else
uniform samplerCubeShadow shadowMapPoint[1];
uniform vec2 lightProj;
#ifdef _SinglePoint
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot[1];
#else
uniform samplerCubeShadow shadowMapPoint[1];
uniform vec2 lightProj;
#endif
#endif
#endif
#ifdef _Clusters
uniform samplerCubeShadow shadowMapPoint[4];
uniform vec2 lightProj;
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[4];
uniform mat4 LWVPSpot0;
uniform mat4 LWVPSpot1;
uniform mat4 LWVPSpot2;
uniform mat4 LWVPSpot3;
#ifdef _Clusters
#ifdef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlas;
#endif
uniform vec2 lightProj;
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasPoint;
#endif
#else
uniform samplerCubeShadow shadowMapPoint[4];
#endif
#ifdef _Spot
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSpot;
#endif
#else
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
#endif
uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif
#endif
#endif
#endif
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
@ -62,26 +74,26 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#endif
#ifdef _Clusters
if (index == 0) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
}
else if (index == 1) {
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
}
else if (index == 2) {
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
}
else if (index == 3) {
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
}
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas
direct *= shadowTest(
#ifndef _SingleAtlas
shadowMapAtlasSpot
#else
shadowMapAtlas
#endif
, lPos.xyz / lPos.w, bias
);
#else
if (index == 0) direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
#endif
#endif
}
#endif
@ -90,20 +102,32 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#endif
#ifdef _ShadowMap
#ifndef _Spot
if (receiveShadow) {
#ifdef _SinglePoint
#ifndef _Spot
direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
#endif
#endif
#ifdef _Clusters
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#ifdef _ShadowMapAtlas
direct *= PCFFakeCube(
#ifndef _SingleAtlas
shadowMapAtlasPoint
#else
shadowMapAtlas
#endif
, ld, -l, bias, lightProj, n, index
);
#else
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#endif
#endif
}
#endif
#endif
return direct;
}

View file

@ -20,10 +20,10 @@ float rand(const vec2 co) { // Unreliable
}
vec2 rand2(const vec2 coord) {
const float width = 1100;
const float height = 500;
const float width = 1100.0;
const float height = 500.0;
float noiseX = ((fract(1.0 - coord.s * (width / 2.0)) * 0.25) + (fract(coord.t * (height / 2.0)) * 0.75)) * 2.0 - 1.0;
float noiseY = ((fract(1.0 - coord.s * (width / 2.0)) * 0.75) + (fract(coord.t * (height / 2.0)) * 0.25)) * 2.0 - 1.0;
float noiseY = ((fract(1.0 - coord.s * (width / 2.0)) * 0.75) + (fract(coord.t * (height / 2.0)) * 0.25)) * 2.0 - 1.0;
return vec2(noiseX, noiseY);
}
@ -40,4 +40,9 @@ float attenuate(const float dist) {
// 1.0 / (quadratic * dist * dist);
}
float safe_acos(const float x) {
// acos is undefined if |x| > 1
return acos(clamp(x, -1.0, 1.0));
}
#endif

View file

@ -0,0 +1,53 @@
uniform sampler2D morphDataPos;
uniform sampler2D morphDataNor;
uniform vec2 morphScaleOffset;
uniform vec2 morphDataDim;
uniform vec4 morphWeights[8];
void getMorphedVertex(vec2 uvCoord, inout vec3 A){
for(int i = 0; i<8; i++ )
{
vec4 tempCoordY = vec4( uvCoord.y - (i * 4) * morphDataDim.y,
uvCoord.y - (i * 4 + 1) * morphDataDim.y,
uvCoord.y - (i * 4 + 2) * morphDataDim.y,
uvCoord.y - (i * 4 + 3) * morphDataDim.y);
vec3 morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.x)).rgb * morphScaleOffset.x + morphScaleOffset.y;
A += morphWeights[i].x * morph;
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.y)).rgb * morphScaleOffset.x + morphScaleOffset.y;
A += morphWeights[i].y * morph;
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.z)).rgb * morphScaleOffset.x + morphScaleOffset.y;
A += morphWeights[i].z * morph;
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.w)).rgb * morphScaleOffset.x + morphScaleOffset.y;
A += morphWeights[i].w * morph;
}
}
void getMorphedNormal(vec2 uvCoord, vec3 oldNor, inout vec3 morphNor){
for(int i = 0; i<8; i++ )
{
vec4 tempCoordY = vec4( uvCoord.y - (i * 4) * morphDataDim.y,
uvCoord.y - (i * 4 + 1) * morphDataDim.y,
uvCoord.y - (i * 4 + 2) * morphDataDim.y,
uvCoord.y - (i * 4 + 3) * morphDataDim.y);
vec3 norm = oldNor + morphWeights[i].x * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.x)).rgb * 2.0 - 1.0);
morphNor += norm;
norm = oldNor + morphWeights[i].y * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.y)).rgb * 2.0 - 1.0);
morphNor += norm;
norm = oldNor + morphWeights[i].z * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.z)).rgb * 2.0 - 1.0);
morphNor += norm;
norm = oldNor + morphWeights[i].w * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.w)).rgb * 2.0 - 1.0);
morphNor += norm;
}
morphNor = normalize(morphNor);
}

View file

@ -11,6 +11,50 @@ uniform vec4 casData[shadowmapCascades * 4 + 4];
uniform vec2 smSizeUniform;
#endif
#ifdef _ShadowMap
#ifdef _Clusters
#ifdef _ShadowMapAtlas
uniform vec4 pointLightDataArray[maxLightsCluster * 6];
#endif
#endif
#endif
#ifdef _ShadowMapAtlas
// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168
// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/
vec2 sampleCube(vec3 dir, out int faceIndex) {
vec3 dirAbs = abs(dir);
float ma;
vec2 uv;
if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) {
faceIndex = dir.z < 0.0 ? 5 : 4;
ma = 0.5 / dirAbs.z;
uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y);
}
else if(dirAbs.y >= dirAbs.x) {
faceIndex = dir.y < 0.0 ? 3 : 2;
ma = 0.5 / dirAbs.y;
uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z);
}
else {
faceIndex = dir.x < 0.0 ? 1 : 0;
ma = 0.5 / dirAbs.x;
uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y);
}
// downscale uv a little to hide seams
// transform coordinates from clip space to texture space
#ifndef _FlipY
return uv * 0.9976 * ma + 0.5;
#else
#ifdef HLSL
return uv * 0.9976 * ma + 0.5;
#else
return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5;
#endif
#endif
}
#endif
float PCF(sampler2DShadow shadowMap, const vec2 uv, const float compare, const vec2 smSize) {
float result = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare));
result += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare));
@ -50,6 +94,186 @@ float PCFCube(samplerCubeShadow shadowMapCube, const vec3 lp, vec3 ml, const flo
return result / 9.0;
}
#ifdef _ShadowMapAtlas
// transform "out-of-bounds" coordinates to the correct face/coordinate system
// https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png
vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) {
if (uv.x < 0.0) {
if (faceIndex == 0) { // X+
newFaceIndex = 4; // Z+
}
else if (faceIndex == 1) { // X-
newFaceIndex = 5; // Z-
}
else if (faceIndex == 2) { // Y+
newFaceIndex = 1; // X-
}
else if (faceIndex == 3) { // Y-
newFaceIndex = 1; // X-
}
else if (faceIndex == 4) { // Z+
newFaceIndex = 1; // X-
}
else { // Z-
newFaceIndex = 0; // X+
}
uv = vec2(1.0 + uv.x, uv.y);
}
else if (uv.x > 1.0) {
if (faceIndex == 0) { // X+
newFaceIndex = 5; // Z-
}
else if (faceIndex == 1) { // X-
newFaceIndex = 4; // Z+
}
else if (faceIndex == 2) { // Y+
newFaceIndex = 0; // X+
}
else if (faceIndex == 3) { // Y-
newFaceIndex = 0; // X+
}
else if (faceIndex == 4) { // Z+
newFaceIndex = 0; // X+
}
else { // Z-
newFaceIndex = 1; // X-
}
uv = vec2(1.0 - uv.x, uv.y);
}
else if (uv.y < 0.0) {
if (faceIndex == 0) { // X+
newFaceIndex = 2; // Y+
}
else if (faceIndex == 1) { // X-
newFaceIndex = 2; // Y+
}
else if (faceIndex == 2) { // Y+
newFaceIndex = 5; // Z-
}
else if (faceIndex == 3) { // Y-
newFaceIndex = 4; // Z+
}
else if (faceIndex == 4) { // Z+
newFaceIndex = 2; // Y+
}
else { // Z-
newFaceIndex = 2; // Y+
}
uv = vec2(uv.x, 1.0 + uv.y);
}
else if (uv.y > 1.0) {
if (faceIndex == 0) { // X+
newFaceIndex = 3; // Y-
}
else if (faceIndex == 1) { // X-
newFaceIndex = 3; // Y-
}
else if (faceIndex == 2) { // Y+
newFaceIndex = 4; // Z+
}
else if (faceIndex == 3) { // Y-
newFaceIndex = 5; // Z-
}
else if (faceIndex == 4) { // Z+
newFaceIndex = 3; // Y-
}
else { // Z-
newFaceIndex = 3; // Y-
}
uv = vec2(uv.x, 1.0 - uv.y);
} else {
newFaceIndex = faceIndex;
}
// cover corner cases too
return uv;
}
float PCFFakeCube(sampler2DShadow shadowMap, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index) {
const vec2 smSize = smSizeUniform; // TODO: incorrect...
const float compare = lpToDepth(lp, lightProj) - bias * 1.5;
ml = ml + n * bias * 20;
int faceIndex = 0;
const int lightIndex = index * 6;
const vec2 uv = sampleCube(ml, faceIndex);
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
float result = texture(shadowMap, vec3(uvtiled, compare));
// soft shadowing
int newFaceIndex = 0;
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 0.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, -1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, 1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, -1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 0.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result += texture(shadowMap, vec3(uvtiled, compare));
return result / 9.0;
}
#endif
float shadowTest(sampler2DShadow shadowMap, const vec3 lPos, const float shadowsBias) {
#ifdef _SMSizeUniform
vec2 smSize = smSizeUniform;
@ -95,7 +319,7 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
float shadowTestCascade(sampler2DShadow shadowMap, const vec3 eye, const vec3 p, const float shadowsBias) {
#ifdef _SMSizeUniform
vec2 smSize = smSizeUniform * vec2(shadowmapCascades, 1.0);
vec2 smSize = smSizeUniform;
#else
const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0);
#endif

155
Shaders/std/sky.glsl Normal file
View file

@ -0,0 +1,155 @@
/* Various sky functions
* =====================
*
* Nishita model is based on https://github.com/wwwtyro/glsl-atmosphere (Unlicense License)
*
* Changes to the original implementation:
* - r and pSun parameters of nishita_atmosphere() are already normalized
* - Some original parameters of nishita_atmosphere() are replaced with pre-defined values
* - Implemented air, dust and ozone density node parameters (see Blender source)
* - Replaced the inner integral calculation with a LUT lookup
*
* Reference for the sun's limb darkening and ozone calculations:
* [Hill] Sebastien Hillaire. Physically Based Sky, Atmosphere and Cloud Rendering in Frostbite
* (https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/s2016-pbs-frostbite-sky-clouds-new.pdf)
*
* Cycles code used for reference: blender/intern/sky/source/sky_nishita.cpp
* (https://github.com/blender/blender/blob/4429b4b77ef6754739a3c2b4fabd0537999e9bdc/intern/sky/source/sky_nishita.cpp)
*/
#ifndef _SKY_GLSL_
#define _SKY_GLSL_
#include "std/math.glsl"
uniform sampler2D nishitaLUT;
uniform vec2 nishitaDensity;
#ifndef PI
#define PI 3.141592
#endif
#ifndef HALF_PI
#define HALF_PI 1.570796
#endif
#define nishita_iSteps 16
// These values are taken from Cycles code if they
// exist there, otherwise they are taken from the example
// in the glsl-atmosphere repo
#define nishita_sun_intensity 22.0
#define nishita_atmo_radius 6420e3
#define nishita_rayleigh_scale 8e3
#define nishita_rayleigh_coeff vec3(5.5e-6, 13.0e-6, 22.4e-6)
#define nishita_mie_scale 1.2e3
#define nishita_mie_coeff 2e-5
#define nishita_mie_dir 0.76 // Aerosols anisotropy ("direction")
#define nishita_mie_dir_sq 0.5776 // Squared aerosols anisotropy
// Values from [Hill: 60]
#define sun_limb_darkening_col vec3(0.397, 0.503, 0.652)
vec3 nishita_lookupLUT(const float height, const float sunTheta) {
vec2 coords = vec2(
sqrt(height * (1 / nishita_atmo_radius)),
0.5 + 0.5 * sign(sunTheta - HALF_PI) * sqrt(abs(sunTheta * (1 / HALF_PI) - 1))
);
return textureLod(nishitaLUT, coords, 0.0).rgb;
}
/* See raySphereIntersection() in armory/Sources/renderpath/Nishita.hx */
vec2 nishita_rsi(const vec3 r0, const vec3 rd, const float sr) {
float a = dot(rd, rd);
float b = 2.0 * dot(rd, r0);
float c = dot(r0, r0) - (sr * sr);
float d = (b*b) - 4.0*a*c;
// If d < 0.0 the ray does not intersect the sphere
return (d < 0.0) ? vec2(1e5,-1e5) : vec2((-b - sqrt(d))/(2.0*a), (-b + sqrt(d))/(2.0*a));
}
/*
* r: normalized ray direction
* r0: ray origin
* pSun: normalized sun direction
* rPlanet: planet radius
*/
vec3 nishita_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const float rPlanet) {
// Calculate the step size of the primary ray
vec2 p = nishita_rsi(r0, r, nishita_atmo_radius);
if (p.x > p.y) return vec3(0.0);
p.y = min(p.y, nishita_rsi(r0, r, rPlanet).x);
float iStepSize = (p.y - p.x) / float(nishita_iSteps);
// Primary ray time
float iTime = 0.0;
// Accumulators for Rayleigh and Mie scattering.
vec3 totalRlh = vec3(0,0,0);
vec3 totalMie = vec3(0,0,0);
// Optical depth accumulators for the primary ray
float iOdRlh = 0.0;
float iOdMie = 0.0;
// Calculate the Rayleigh and Mie phases
float mu = dot(r, pSun);
float mumu = mu * mu;
float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu);
float pMie = 3.0 / (8.0 * PI) * ((1.0 - nishita_mie_dir_sq) * (mumu + 1.0)) / (pow(1.0 + nishita_mie_dir_sq - 2.0 * mu * nishita_mie_dir, 1.5) * (2.0 + nishita_mie_dir_sq));
// Sample the primary ray
for (int i = 0; i < nishita_iSteps; i++) {
// Calculate the primary ray sample position and height
vec3 iPos = r0 + r * (iTime + iStepSize * 0.5);
float iHeight = length(iPos) - rPlanet;
// Calculate the optical depth of the Rayleigh and Mie scattering for this step
float odStepRlh = exp(-iHeight / nishita_rayleigh_scale) * nishitaDensity.x * iStepSize;
float odStepMie = exp(-iHeight / nishita_mie_scale) * nishitaDensity.y * iStepSize;
// Accumulate optical depth
iOdRlh += odStepRlh;
iOdMie += odStepMie;
// Idea behind this: "Rotate" everything by iPos (-> iPos is the new zenith) and then all calculations for the
// inner integral only depend on the sample height (iHeight) and sunTheta (angle between sun and new zenith).
float sunTheta = safe_acos(dot(normalize(iPos), normalize(pSun)));
vec3 jAttn = nishita_lookupLUT(iHeight, sunTheta);
// Calculate attenuation
vec3 iAttn = exp(-(
nishita_mie_coeff * iOdMie
+ nishita_rayleigh_coeff * iOdRlh
// + 0 for ozone
));
vec3 attn = iAttn * jAttn;
// Apply dithering to reduce visible banding
attn *= 0.98 + rand(r.xy) * 0.04;
// Accumulate scattering
totalRlh += odStepRlh * attn;
totalMie += odStepMie * attn;
iTime += iStepSize;
}
return nishita_sun_intensity * (pRlh * nishita_rayleigh_coeff * totalRlh + pMie * nishita_mie_coeff * totalMie);
}
vec3 sun_disk(const vec3 n, const vec3 light_dir, const float disk_size, const float intensity) {
// Normalized SDF
float dist = distance(n, light_dir) / disk_size;
// Darken the edges of the sun
// [Hill: 28, 60] (according to [Nec96])
float invDist = 1.0 - dist;
float mu = sqrt(invDist * invDist);
vec3 limb_darkening = 1.0 - (1.0 - pow(vec3(mu), sun_limb_darkening_col));
return 1 + (1.0 - step(1.0, dist)) * nishita_sun_intensity * intensity * limb_darkening;
}
#endif

View file

@ -12,7 +12,7 @@ uniform sampler2D gbufferD;
uniform sampler2D snoise;
#ifdef _Clusters
uniform vec4 lightsArray[maxLights * 2];
uniform vec4 lightsArray[maxLights * 3];
#ifdef _Spot
uniform vec4 lightsArraySpot[maxLights];
#endif
@ -24,7 +24,7 @@ uniform vec2 cameraPlane;
#ifdef _SinglePoint
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot0;
uniform mat4 LWVPSpot[1];
#else
uniform samplerCubeShadow shadowMapPoint[1];
uniform vec2 lightProj;
@ -35,10 +35,7 @@ uniform vec2 cameraPlane;
uniform vec2 lightProj;
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[4];
uniform mat4 LWVPSpot0;
uniform mat4 LWVPSpot1;
uniform mat4 LWVPSpot2;
uniform mat4 LWVPSpot3;
uniform mat4 LWVPSpot[maxLightsCluster];
#endif
#endif
#endif
@ -47,7 +44,15 @@ uniform vec2 cameraPlane;
uniform vec3 sunDir;
uniform vec3 sunCol;
#ifdef _ShadowMap
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSun;
#else
uniform sampler2DShadow shadowMapAtlas;
#endif
#else
uniform sampler2DShadow shadowMap;
#endif
uniform float shadowsBias;
#ifdef _CSM
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
@ -98,12 +103,22 @@ void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatter
#endif
vec4 lPos = LWVP * vec4(curPos, 1.0);
lPos.xyz /= lPos.w;
visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias));
visibility = texture(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#else
shadowMap
#endif
, vec3(lPos.xy, lPos.z - shadowsBias));
#endif
#ifdef _SinglePoint
#ifdef _Spot
vec4 lPos = LWVPSpot0 * vec4(curPos, 1.0);
vec4 lPos = LWVPSpot[0] * vec4(curPos, 1.0);
visibility = shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, pointBias);
float spotEffect = dot(spotDir, normalize(pointPos - curPos)); // lightDir
if (spotEffect < spotData.x) { // x - cutoff, y - cutoff - exponent

View file

@ -63,7 +63,7 @@
},
{
"name": "LWVP",
"link": "_biasLightWorldViewProjectionMatrix",
"link": "_biasLightWorldViewProjectionMatrixSun",
"ifndef": ["_CSM"],
"ifdef": ["_Sun", "_ShadowMap"]
},
@ -108,23 +108,32 @@
"ifdef": ["_SinglePoint", "_Spot"]
},
{
"name": "LWVPSpot0",
"name": "LWVPSpotArray",
"link": "_biasLightWorldViewProjectionMatrixSpotArray",
"ifdef": ["_Clusters", "_ShadowMap", "_Spot"]
},
{
"name": "LWVPSpot[0]",
"link": "_biasLightWorldViewProjectionMatrixSpot0",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_Spot", "_ShadowMap"]
},
{
"name": "LWVPSpot1",
"name": "LWVPSpot[1]",
"link": "_biasLightWorldViewProjectionMatrixSpot1",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_Spot", "_ShadowMap"]
},
{
"name": "LWVPSpot2",
"name": "LWVPSpot[2]",
"link": "_biasLightWorldViewProjectionMatrixSpot2",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_Spot", "_ShadowMap"]
},
{
"name": "LWVPSpot3",
"name": "LWVPSpot[3]",
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_Spot", "_ShadowMap"]
}
],

1
Sources/armory/import.hx Normal file
View file

@ -0,0 +1 @@
import armory.system.Assert.*;

View file

@ -0,0 +1,114 @@
package armory.logicnode;
import iron.object.Object;
#if arm_physics
import armory.trait.physics.PhysicsConstraint;
import armory.trait.physics.bullet.PhysicsConstraint.ConstraintType;
#end
class AddPhysicsConstraintNode extends LogicNode {
public var property0: String;//Type
public var object: Object;
public var rb1: Object;
public var rb2: Object;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var pivotObject: Object = inputs[1].get();
rb1 = inputs[2].get();
rb2 = inputs[3].get();
if (pivotObject == null || rb1 == null || rb2 == null) return;
#if arm_physics
var disableCollisions: Bool = inputs[4].get();
var breakable: Bool = inputs[5].get();
var breakingThreshold: Float = inputs[6].get();
var type: ConstraintType = 0;
var con: PhysicsConstraint = pivotObject.getTrait(PhysicsConstraint);
if (con == null) {
switch (property0) {
case "Fixed": type = Fixed;
case "Point": type = Point;
case "Hinge": type = Hinge;
case "Slider": type = Slider;
case "Piston": type = Piston;
case "Generic Spring": type = Generic;
}
if (!breakable) breakingThreshold = 0.0;
if (type != Generic) {
con = new PhysicsConstraint(rb1, rb2, type, disableCollisions, breakingThreshold);
switch (type) {
case Hinge:
var setLimit: Bool = inputs[7].get();
var low: Float = inputs[8].get();
var up: Float = inputs[9].get();
con.setHingeConstraintLimits(setLimit, low, up);
case Slider:
var setLimit: Bool = inputs[7].get();
var low: Float = inputs[8].get();
var up: Float = inputs[9].get();
con.setSliderConstraintLimits(setLimit, low, up);
case Piston:
var setLinLimit: Bool = inputs[7].get();
var linLow: Float = inputs[8].get();
var linUp: Float = inputs[9].get();
var setAngLimit: Bool = inputs[10].get();
var angLow: Float = inputs[11].get();
var angUp: Float = inputs[12].get();
con.setPistonConstraintLimits(setLinLimit, linLow, linUp, setAngLimit, angLow, angUp);
default:
}
}
else {
var spring: Bool = false;
var prop: PhysicsConstraintNode;
for (inp in 7...inputs.length) {
prop = inputs[inp].get();
if (prop == null) continue;
if (prop.isSpring) {
spring = true;
break;
}
}
if (spring) {
con = new PhysicsConstraint(rb1, rb2, GenericSpring, disableCollisions, breakingThreshold);
}
else {
con = new PhysicsConstraint(rb1, rb2, Generic, disableCollisions, breakingThreshold);
}
for (inp in 7...inputs.length) {
prop = inputs[inp].get();
if (prop == null) continue;
if (prop.isSpring) {
con.setSpringParams(prop.isSpring, prop.value1, prop.value2, prop.axis, prop.isAngular);
}
else {
con.setGenericConstraintLimits(true, prop.value1, prop.value2, prop.axis, prop.isAngular);
}
}
}
pivotObject.addTrait(con);
}
#end
runOutput(0);
}
}

View file

@ -1,15 +1,17 @@
package armory.logicnode;
import iron.object.Object;
#if arm_physics
import armory.trait.physics.RigidBody;
import armory.trait.physics.bullet.RigidBody.Shape;
#end
import iron.object.Object;
import armory.trait.physics.RigidBody;
class AddRigidBodyNode extends LogicNode {
public var property0: String;//Shape
public var property1: String;//Advanced
public var property0: String; //Shape
public var property1: Bool; //Advanced
public var object: Object;
public function new(tree: LogicTree) {
@ -18,6 +20,10 @@ class AddRigidBodyNode extends LogicNode {
override function run(from: Int) {
object = inputs[1].get();
if (object == null) return;
#if arm_physics
var mass: Float = inputs[2].get();
var active: Bool = inputs[3].get();
var animated: Bool = inputs[4].get();
@ -38,8 +44,7 @@ class AddRigidBodyNode extends LogicNode {
var shape: Shape = 1;
if(property1 == 'true')
{
if (property1) {
margin = inputs[9].get();
marginLen = inputs[10].get();
linDamp = inputs[11].get();
@ -49,51 +54,34 @@ class AddRigidBodyNode extends LogicNode {
angVelThreshold = inputs[15].get();
group = inputs[16].get();
mask = inputs[17].get();
}
if (object == null) return;
#if arm_physics
var rb: RigidBody = object.getTrait(RigidBody);
if((group < 0) || (group > 32)) group = 1; //Limiting max groups to 32
if((mask < 0) || (mask > 32)) mask = 1; //Limiting max masks to 32
if(rb == null)
{
switch (property0){
case 'Box':
shape = Box;
case 'Sphere':
shape = Sphere;
case 'Capsule':
shape = Capsule;
case 'Cone':
shape = Cone;
case 'Cylinder':
shape = Cylinder;
case 'Convex Hull':
shape = ConvexHull;
case 'Mesh':
shape = Mesh;
if ((group < 0) || (group > 32)) group = 1; //Limiting max groups to 32
if ((mask < 0) || (mask > 32)) mask = 1; //Limiting max masks to 32
if (rb == null) {
switch (property0) {
case "Box": shape = Box;
case "Sphere": shape = Sphere;
case "Capsule": shape = Capsule;
case "Cone": shape = Cone;
case "Cylinder": shape = Cylinder;
case "Convex Hull": shape = ConvexHull;
case "Mesh": shape = Mesh;
}
rb = new RigidBody(shape, mass, friction, bounciness, group, mask);
rb.animated = animated;
rb.staticObj = ! active;
rb.staticObj = !active;
rb.isTriggerObject(trigger);
if(property1 == 'true')
{
if (property1) {
rb.linearDamping = linDamp;
rb.angularDamping = angDamp;
if(margin) rb.collisionMargin = marginLen;
if(useDeactiv) {
rb.setDeactivation(true);
rb.setDeactivationParams(linearVelThreshold, angVelThreshold, 0.0);
if (margin) rb.collisionMargin = marginLen;
if (useDeactiv) {
rb.setUpDeactivation(true, linearVelThreshold, angVelThreshold, 0.0);
}
}
object.addTrait(rb);

View file

@ -10,10 +10,17 @@ class AddTraitNode extends LogicNode {
override function run(from: Int) {
var object: Object = inputs[1].get();
var trait: Dynamic = inputs[2].get();
var traitName: String = inputs[2].get();
if (object == null || trait == null) return;
assert(Error, object != null, "Object should not be null");
assert(Error, traitName != null, "Trait name should not be null");
var cname = Type.resolveClass(Main.projectPackage + "." + traitName);
if (cname == null) cname = Type.resolveClass(Main.projectPackage + ".node." + traitName);
assert(Error, cname != null, 'No trait with the name "$traitName" found, make sure that the trait is exported!');
assert(Warning, object.getTrait(cname) == null, 'Object already has the trait "$traitName" applied');
var trait = Type.createInstance(cname, []);
object.addTrait(trait);
runOutput(0);

View file

@ -1,5 +1,7 @@
package armory.logicnode;
import iron.math.Quat;
import iron.math.Vec4;
import iron.object.Object;
import iron.object.BoneAnimation;
import iron.math.Mat4;
@ -26,19 +28,28 @@ class BoneFKNode extends LogicNode {
var anim = object.animation != null ? cast(object.animation, BoneAnimation) : null;
if (anim == null) anim = object.getParentArmature(object.name);
// Manipulating bone in world space
// Get bone in armature
var bone = anim.getBone(boneName);
m = anim.getBoneMat(bone);
w = anim.getAbsMat(bone);
function moveBone() {
m.setFrom(w);
m.multmat(transform);
iw.getInverse(w);
m.multmat(iw);
var t2 = Mat4.identity();
var loc= new Vec4();
var rot = new Quat();
var scl = new Vec4();
// anim.removeUpdate(moveBone);
// notified = false;
//Set scale to Armature scale. Bone scaling not yet implemented
t2.setFrom(transform);
t2.decompose(loc, rot, scl);
scl = object.transform.world.getScale();
t2.compose(loc, rot, scl);
//Set the bone local transform from world transform
anim.setBoneMatFromWorldMat(t2, bone);
//Remove this method from animation loop after FK
anim.removeUpdate(moveBone);
notified = false;
}
if (!notified) {

View file

@ -7,6 +7,13 @@ import iron.math.Vec4;
class BoneIKNode extends LogicNode {
var goal: Vec4;
var pole: Vec4;
var poleEnabled: Bool;
var chainLength: Int;
var maxIterartions: Int;
var precision: Float;
var rollAngle: Float;
var notified = false;
public function new(tree: LogicTree) {
@ -19,6 +26,12 @@ class BoneIKNode extends LogicNode {
var object: Object = inputs[1].get();
var boneName: String = inputs[2].get();
goal = inputs[3].get();
poleEnabled = inputs[4].get();
pole = inputs[5].get();
chainLength = inputs[6].get();
maxIterartions = inputs[7].get();
precision = inputs[8].get();
rollAngle = inputs[9].get();
if (object == null || goal == null) return;
var anim = object.animation != null ? cast(object.animation, BoneAnimation) : null;
@ -26,11 +39,15 @@ class BoneIKNode extends LogicNode {
var bone = anim.getBone(boneName);
function solveBone() {
anim.solveIK(bone, goal);
if(! poleEnabled) pole = null;
// anim.removeUpdate(solveBone);
// notified = false;
function solveBone() {
//Solve IK
anim.solveIK(bone, goal, precision, maxIterartions, chainLength, pole, rollAngle);
//Remove this method from animation loop after IK
anim.removeUpdate(solveBone);
notified = false;
}
if (!notified) {

View file

@ -12,11 +12,17 @@ class CallHaxeStaticNode extends LogicNode {
var path: String = inputs[1].get();
if (path != "") {
var args: Array<Dynamic> = [];
for (i in 2...inputs.length) {
args.push(inputs[i].get());
}
var dotIndex = path.lastIndexOf(".");
var classPath = path.substr(0, dotIndex);
var classType = Type.resolveClass(classPath);
var funName = path.substr(dotIndex + 1);
result = Reflect.callMethod(classType, Reflect.field(classType, funName), [tree]);
result = Reflect.callMethod(classType, Reflect.field(classType, funName), args);
}
runOutput(0);

View file

@ -0,0 +1,39 @@
package armory.logicnode;
import iron.Scene;
import armory.trait.internal.CanvasScript;
import kha.Color;
import iron.math.Vec4;
class CanvasSetProgressBarColorNode extends LogicNode {
var canvas: CanvasScript;
var element: String;
var color = new Vec4();
public function new(tree: LogicTree) {
super(tree);
}
#if arm_ui
function update() {
if (!canvas.ready) return;
tree.removeUpdate(update);
var e = canvas.getElement(element);
if (e != null) e.color_progress = Color.fromFloats(color.x, color.y, color.z, color.w);
runOutput(0);
}
override function run(from: Int) {
element = inputs[1].get();
color = inputs[2].get();
canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
// Ensure canvas is ready
tree.notifyOnUpdate(update);
update();
}
#end
}

View file

@ -1,18 +1,18 @@
package armory.logicnode;
import kha.FastFloat;
class ClampNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var value: kha.FastFloat = inputs[0].get();
var min: kha.FastFloat = inputs[1].get();
var max: kha.FastFloat = inputs[2].get();
override function get(from: Int): FastFloat {
var value = inputs[0].get();
var min = inputs[1].get();
var max = inputs[2].get();
if (value == null || min == null || max == null) return null;
value <= min ? return min : value >= max ? return max : return value;
return value < min ? min : value > max ? max : value;
}
}

View file

@ -19,9 +19,11 @@ class CompareNode extends LogicNode {
switch (property0) {
case "Equal":
cond = Std.is(v1, Vec4) ? v1.equals(v2) : v1 == v2;
cond = Std.isOfType(v1, Vec4) ? v1.equals(v2) : v1 == v2;
case "Not Equal":
cond = Std.isOfType(v1, Vec4) ? !v1.equals(v2) : v1 != v2;
case "Almost Equal":
cond = Std.is(v1, Vec4) ? v1.almostEquals(v2, property1) : Math.abs(v1 - v2) < property1;
cond = Std.isOfType(v1, Vec4) ? v1.almostEquals(v2, property1) : Math.abs(v1 - v2) < property1;
case "Greater":
cond = v1 > v2;
case "Greater Equal":
@ -30,6 +32,9 @@ class CompareNode extends LogicNode {
cond = v1 < v2;
case "Less Equal":
cond = v1 <= v2;
case "Between":
var v3: Dynamic = inputs[2].get();
cond = v2 <= v1 && v1 <= v3;
case "Or":
for (input in inputs) {
if (input.get()) {

View file

@ -18,9 +18,11 @@ class GateNode extends LogicNode {
switch (property0) {
case "Equal":
cond = Std.is(v1, Vec4) ? v1.equals(v2) : v1 == v2;
cond = Std.isOfType(v1, Vec4) ? v1.equals(v2) : v1 == v2;
case "Not Equal":
cond = Std.isOfType(v1, Vec4) ? !v1.equals(v2) : v1 != v2;
case "Almost Equal":
cond = Std.is(v1, Vec4) ? v1.almostEquals(v2, property1) : Math.abs(v1 - v2) < property1;
cond = Std.isOfType(v1, Vec4) ? v1.almostEquals(v2, property1) : Math.abs(v1 - v2) < property1;
case "Greater":
cond = v1 > v2;
case "Greater Equal":
@ -29,6 +31,9 @@ class GateNode extends LogicNode {
cond = v1 < v2;
case "Less Equal":
cond = v1 <= v2;
case "Between":
var v3: Dynamic = inputs[3].get();
cond = v2 <= v1 && v1 <= v3;
case "Or":
for (i in 1...inputs.length) {
if (inputs[i].get()) {

View file

@ -0,0 +1,25 @@
package armory.logicnode;
import iron.object.Object;
class GetAgentDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Float {
var object: Object = inputs[0].get();
assert(Error, object != null, "The object to naviagte should not be null");
#if arm_navigation
var agent: armory.trait.NavAgent = object.getTrait(armory.trait.NavAgent);
assert(Error, agent != null, "The object does not have NavAgent Trait");
if(from == 0) return agent.speed;
else return agent.turnDuration;
#else
return null;
#end
}
}

View file

@ -0,0 +1,31 @@
package armory.logicnode;
import iron.object.Object;
import iron.object.BoneAnimation;
class GetBoneFkIkOnlyNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Bool {
#if arm_skin
var object: Object = inputs[0].get();
var boneName: String = inputs[1].get();
if (object == null) return null;
var anim = object.animation != null ? cast(object.animation, BoneAnimation) : null;
if (anim == null) anim = object.getParentArmature(object.name);
// Get bone in armature
var bone = anim.getBone(boneName);
//Get bone transform in world coordinates
return bone.is_ik_fk_only;
#end
}
}

View file

@ -0,0 +1,30 @@
package armory.logicnode;
import iron.object.Object;
import iron.object.BoneAnimation;
import iron.math.Mat4;
class GetBoneTransformNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Mat4 {
#if arm_skin
var object: Object = inputs[0].get();
var boneName: String = inputs[1].get();
if (object == null) return null;
var anim = object.animation != null ? cast(object.animation, BoneAnimation) : null;
if (anim == null) anim = object.getParentArmature(object.name);
// Get bone in armature
var bone = anim.getBone(boneName);
return anim.getAbsWorldMat(bone);
#end
}
}

View file

@ -0,0 +1,33 @@
package armory.logicnode;
import iron.system.Input;
class GetGamepadStartedNode extends LogicNode {
var buttonStarted: Null<String>;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var g = Input.getGamepad(inputs[0].get());
buttonStarted = null;
for (b in Gamepad.buttons) {
if (g.started(b)) {
buttonStarted = b;
break;
}
}
if (buttonStarted != null) {
runOutput(0);
}
}
override function get(from: Int) {
return buttonStarted;
}
}

View file

@ -0,0 +1,22 @@
package armory.logicnode;
import iron.Scene;
import armory.trait.internal.CanvasScript;
class GetGlobalCanvasFontSizeNode extends LogicNode {
var canvas: CanvasScript;
public function new(tree: LogicTree) {
super(tree);
}
#if arm_ui
override function get(from: Int): Dynamic {
canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
return canvas.getCanvasFontSize();
}
#end
}

View file

@ -0,0 +1,22 @@
package armory.logicnode;
import iron.Scene;
import armory.trait.internal.CanvasScript;
class GetGlobalCanvasScaleNode extends LogicNode {
var canvas: CanvasScript;
public function new(tree: LogicTree) {
super(tree);
}
#if arm_ui
override function get(from: Int): Dynamic {
canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
return canvas.getUiScale();
}
#end
}

View file

@ -0,0 +1,24 @@
package armory.logicnode;
import armory.system.InputMap;
class GetInputMapKeyNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var inputMap = inputs[0].get();
var key = inputs[1].get();
var k = InputMap.getInputMapKey(inputMap, key);
if (k != null) {
if (from == 0) return k.scale;
else if (from == 1) return k.deadzone;
}
return null;
}
}

View file

@ -0,0 +1,32 @@
package armory.logicnode;
import iron.system.Input;
class GetKeyboardStartedNode extends LogicNode {
var kb = Input.getKeyboard();
var keyStarted: Null<String>;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
keyStarted = null;
for (k in Keyboard.keys) {
if (kb.started(k)) {
keyStarted = k;
break;
}
}
if (keyStarted != null) {
runOutput(0);
}
}
override function get(from: Int) {
return keyStarted;
}
}

View file

@ -10,9 +10,22 @@ class GetLocationNode extends LogicNode {
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
var relative: Bool = inputs[1].get();
if (object == null) return null;
return object.transform.world.getLoc();
var loc = object.transform.world.getLoc();
if (relative && object.parent != null) {
loc.sub(object.parent.transform.world.getLoc()); // Add parent location influence
// Convert loc to parent local space
var dotX = loc.dot(object.parent.transform.right());
var dotY = loc.dot(object.parent.transform.look());
var dotZ = loc.dot(object.parent.transform.up());
loc.set(dotX, dotY, dotZ);
}
return loc;
}
}

View file

@ -1,6 +1,7 @@
package armory.logicnode;
import iron.object.MeshObject;
import iron.object.DecalObject;
class GetMaterialNode extends LogicNode {
@ -9,11 +10,27 @@ class GetMaterialNode extends LogicNode {
}
override function get(from: Int): Dynamic {
var object: MeshObject = inputs[0].get();
var slot: Int = inputs[1].get();
if (object == null) return null;
var object = inputs[0].get();
return object.materials[slot];
assert(Error, object != null, "The object input must not be null");
#if rp_decals
if (Std.isOfType(object, DecalObject)) {
var decal = cast(object, DecalObject);
return decal.material;
}
#end
if (Std.isOfType(object, MeshObject)) {
var mesh = cast(object, MeshObject);
var slot: Int = inputs[1].get();
if (mesh == null) return null;
return mesh.materials[slot];
}
return null;
}
}

View file

@ -0,0 +1,32 @@
package armory.logicnode;
import iron.system.Input;
class GetMouseStartedNode extends LogicNode {
var m = Input.getMouse();
var buttonStarted: Null<String>;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
buttonStarted = null;
for (b in Mouse.buttons) {
if (m.started(b)) {
buttonStarted = b;
break;
}
}
if (buttonStarted != null) {
runOutput(0);
}
}
override function get(from: Int) {
return buttonStarted;
}
}

View file

@ -0,0 +1,22 @@
package armory.logicnode;
import iron.data.SceneFormat;
import iron.object.Object;
class GetObjectByUidNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var objectUid: Int = inputs[0].get();
var obj = iron.Scene.active.getChildren(true);
for (obji in obj) if (obji.uid == objectUid) return obji;
return null;
}
}

View file

@ -14,36 +14,7 @@ class GetObjectNode extends LogicNode {
override function get(from: Int): Dynamic {
var objectName: String = inputs[0].get();
if (property0 == null || property0 == iron.Scene.active.raw.name) {
return iron.Scene.active.getChild(objectName);
}
#if arm_json
property0 += ".json";
#elseif arm_compress
property0 += ".lz4";
#end
var outObj: Null<Object> = null;
// Create the object in the active scene if it is from an inactive scene
iron.data.Data.getSceneRaw(property0, (rawScene: TSceneFormat) -> {
var objData: Null<TObj> = null;
for (o in rawScene.objects) {
if (o.name == objectName) {
objData = o;
break;
}
}
if (objData == null) return;
iron.Scene.active.createObject(objData, rawScene, null, null, (newObj: Object) -> {
outObj = newObj;
});
});
return outObj;
return iron.Scene.active.getChild(objectName);
}
}

View file

@ -1,10 +1,13 @@
package armory.logicnode;
import iron.object.Object;
import iron.math.Vec3;
import iron.math.Quat;
import iron.math.Vec4;
class GetRotationNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
}
@ -16,34 +19,16 @@ class GetRotationNode extends LogicNode {
return null;
}
var rot = object.transform.rot;
switch (from) {
case 0:
// euler angles
return object.transform.rot.getEuler();
case 1:
// vector
var sqrtW = Math.sqrt(1 - (rot.w * rot.w));
if (sqrtW == 0) {
return new Vec3(0, 0, 1);
}
return new Vec3(rot.x / sqrtW, rot.y / sqrtW, rot.z / sqrtW);
case 2:
// angle radians
var angle = 2 * Math.acos(rot.w);
return angle;
case 3:
// angle degrees
var angle = 2 * Math.acos(rot.w);
return angle * (180 / Math.PI);
case 4:
//quaternion xyz
return new Vec3(rot.x, rot.y, rot.z);
case 5:
//quaternion w
return rot.w;
}
switch(property0){
case "Local":
return object.transform.rot;
case "Global":{
var useless1 = new Vec4();
var ret = new Quat();
object.transform.world.decompose(useless1, ret, useless1);
return ret;
}}
return null;
}
}

View file

@ -3,22 +3,24 @@ package armory.logicnode;
class GetSystemName extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
super(tree);
}
public static function equalsCI(a : String, b : String) return a.toLowerCase() == b.toLowerCase();
override function get(from: Int): Dynamic {
var systemName: String = kha.System.systemId;
return switch (from) {
case 0: systemName;
case 1: equalsCI(kha.System.systemId, 'Windows');
case 2: equalsCI(kha.System.systemId, 'Linux');
case 3: equalsCI(kha.System.systemId, 'Mac');
case 4: equalsCI(kha.System.systemId, 'HTML5');
case 5: equalsCI(kha.System.systemId, 'Android');
case 1: equalsCI(systemName, 'Windows');
case 2: equalsCI(systemName, 'Linux');
case 3: equalsCI(systemName, 'Mac');
case 4: equalsCI(systemName, 'HTML5');
case 5: equalsCI(systemName, 'Android');
default: null;
}
}
static inline function equalsCI(a: String, b: String): Bool {
return a.toLowerCase() == b.toLowerCase();
}
}

View file

@ -16,12 +16,12 @@ class GetTraitNameNode extends LogicNode {
case 0: {
// Check CanvasScript
var cname = cast Type.resolveClass("armory.trait.internal.CanvasScript");
if (Std.is(trait, cname)) {
if (Std.isOfType(trait, cname)) {
return trait.cnvName;
}
// Check WasmScript
var cname = cast Type.resolveClass("armory.trait.internal.WasmScript");
if (Std.is(trait, cname)) {
if (Std.isOfType(trait, cname)) {
return trait.wasmName;
}
// Other

View file

@ -0,0 +1,18 @@
package armory.logicnode;
import iron.object.Object;
class GetUidNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
if (object == null) return null;
return object.uid;
}
}

View file

@ -13,15 +13,26 @@ class GoToLocationNode extends LogicNode {
override function run(from: Int) {
var object: Object = inputs[1].get();
var location: Vec4 = inputs[2].get();
var speed: Float = inputs[3].get();
var turnDuration: Float = inputs[4].get();
if (object == null || location == null) return;
assert(Error, object != null, "The object input not be null");
assert(Error, location != null, "The location to navigate to must not be null");
assert(Error, speed != null, "Speed of Nav Agent should not be null");
assert(Warning, speed >= 0, "Speed of Nav Agent should be positive");
assert(Error, turnDuration != null, "Turn Duration of Nav Agent should not be null");
assert(Warning, turnDuration >= 0, "Turn Duration of Nav Agent should be positive");
#if arm_navigation
// Assume navmesh exists..
var from = object.transform.world.getLoc();
var to = location;
assert(Error, Navigation.active.navMeshes.length > 0, "No Navigation Mesh Present");
Navigation.active.navMeshes[0].findPath(from, to, function(path: Array<iron.math.Vec4>) {
var agent: armory.trait.NavAgent = object.getTrait(armory.trait.NavAgent);
assert(Error, agent != null, "Object does not have a NavAgent trait");
agent.speed = speed;
agent.turnDuration = turnDuration;
agent.setPath(path);
});
#end

View file

@ -1,31 +1,136 @@
package armory.logicnode;
#if arm_patch @:keep @:keepSub #end
class LogicNode {
var tree: LogicTree;
var inputs: Array<LogicNodeInput> = [];
var outputs: Array<Array<LogicNode>> = [];
var inputs: Array<LogicNodeLink> = [];
var outputs: Array<Array<LogicNodeLink>> = [];
#if arm_debug
#if (arm_debug || arm_patch)
public var name = "";
public function watch(b: Bool) { // Watch in debug console
var nodes = armory.trait.internal.DebugConsole.watchNodes;
b ? nodes.push(this) : nodes.remove(this);
}
#if (arm_debug)
public function watch(b: Bool) { // Watch in debug console
var nodes = armory.trait.internal.DebugConsole.watchNodes;
b ? nodes.push(this) : nodes.remove(this);
}
#end
#end
public function new(tree: LogicTree) {
this.tree = tree;
}
public function addInput(node: LogicNode, from: Int) {
inputs.push(new LogicNodeInput(node, from));
/**
Resize the inputs array to a given size to minimize dynamic
reallocation and over-allocation later.
**/
inline function preallocInputs(amount: Int) {
this.inputs.resize(amount);
}
public function addOutputs(nodes: Array<LogicNode>) {
outputs.push(nodes);
/**
Resize the outputs array to a given size to minimize dynamic
reallocation and over-allocation later.
**/
inline function preallocOutputs(amount: Int) {
this.outputs.resize(amount);
for (i in 0...outputs.length) {
outputs[i] = [];
}
}
/**
Add a link between to nodes to the tree.
**/
public static function addLink(fromNode: LogicNode, toNode: LogicNode, fromIndex: Int, toIndex: Int): LogicNodeLink {
var link = new LogicNodeLink(fromNode, toNode, fromIndex, toIndex);
if (toNode.inputs.length <= toIndex) {
toNode.inputs.resize(toIndex + 1);
}
toNode.inputs[toIndex] = link;
var fromNodeOuts = fromNode.outputs;
var outLen = fromNodeOuts.length;
if (outLen <= fromIndex) {
fromNodeOuts.resize(fromIndex + 1);
// Initialize with empty arrays
for (i in outLen...fromIndex + 1) {
fromNodeOuts[i] = [];
}
}
fromNodeOuts[fromIndex].push(link);
return link;
}
#if arm_patch
/**
Removes a link from the tree.
**/
static function removeLink(link: LogicNodeLink) {
link.fromNode.outputs[link.fromIndex].remove(link);
// Reuse the same link and connect a default input node to it.
// That's why this function is only available in arm_patch mode, we need
// access to the link's type and value.
link.fromNode = LogicNode.createSocketDefaultNode(link.toNode.tree, link.toType, link.toValue);
link.fromIndex = 0;
}
/**
Removes all inputs and their links from this node.
Warning: this function changes the amount of node inputs to 0!
**/
function clearInputs() {
for (link in inputs) {
link.fromNode.outputs[link.fromIndex].remove(link);
}
inputs.resize(0);
}
/**
Removes all outputs and their links from this node.
Warning: this function changes the amount of node inputs to 0!
**/
function clearOutputs() {
for (links in outputs) {
for (link in links) {
var defaultNode = LogicNode.createSocketDefaultNode(tree, link.toType, link.toValue);
link.fromNode = defaultNode;
link.fromIndex = 0;
defaultNode.outputs[0] = [link];
}
}
outputs.resize(0);
}
/**
Creates a default node for a socket so that get() and set() can be
used without null checks.
Loosely equivalent to `make_logic.build_default_node()` in Python.
**/
static inline function createSocketDefaultNode(tree: LogicTree, socketType: String, value: Dynamic): LogicNode {
// Make sure to not add these nodes to the LogicTree.nodes array as they
// won't be garbage collected then if unlinked later.
return switch (socketType) {
case "VECTOR": new armory.logicnode.VectorNode(tree, value[0], value[1], value[2]);
case "RGBA": new armory.logicnode.ColorNode(tree, value[0], value[1], value[2], value[3]);
case "RGB": new armory.logicnode.ColorNode(tree, value[0], value[1], value[2]);
case "VALUE": new armory.logicnode.FloatNode(tree, value);
case "INT": new armory.logicnode.IntegerNode(tree, value);
case "BOOLEAN": new armory.logicnode.BooleanNode(tree, value);
case "STRING": new armory.logicnode.StringNode(tree, value);
case "NONE": new armory.logicnode.NullNode(tree);
case "OBJECT": new armory.logicnode.ObjectNode(tree, value);
default: new armory.logicnode.DynamicNode(tree, value);
}
}
#end
/**
Called when this node is activated.
@param from impulse index
@ -38,42 +143,45 @@ class LogicNode {
**/
function runOutput(i: Int) {
if (i >= outputs.length) return;
for (o in outputs[i]) {
// Check which input activated the node
for (j in 0...o.inputs.length) {
if (o.inputs[j].node == this) {
o.run(j);
break;
}
}
for (outLink in outputs[i]) {
outLink.toNode.run(outLink.toIndex);
}
}
@:allow(armory.logicnode.LogicNodeInput)
@:allow(armory.logicnode.LogicNodeLink)
function get(from: Int): Dynamic { return this; }
@:allow(armory.logicnode.LogicNodeInput)
@:allow(armory.logicnode.LogicNodeLink)
function set(value: Dynamic) {}
}
class LogicNodeInput {
@:allow(armory.logicnode.LogicNode)
@:allow(armory.logicnode.LogicTree)
class LogicNodeLink {
@:allow(armory.logicnode.LogicNode)
var node: LogicNode;
var from: Int; // Socket index
var fromNode: LogicNode;
var toNode: LogicNode;
var fromIndex: Int;
var toIndex: Int;
public function new(node: LogicNode, from: Int) {
this.node = node;
this.from = from;
#if arm_patch
var fromType: String;
var toType: String;
var toValue: Dynamic;
#end
inline function new(fromNode: LogicNode, toNode: LogicNode, fromIndex: Int, toIndex: Int) {
this.fromNode = fromNode;
this.toNode = toNode;
this.fromIndex = fromIndex;
this.toIndex = toIndex;
}
@:allow(armory.logicnode.LogicNode)
function get(): Dynamic {
return node.get(from);
inline function get(): Dynamic {
return fromNode.get(fromIndex);
}
@:allow(armory.logicnode.LogicNode)
function set(value: Dynamic) {
node.set(value);
inline function set(value: Dynamic) {
fromNode.set(value);
}
}

View file

@ -2,10 +2,26 @@ package armory.logicnode;
class LogicTree extends iron.Trait {
#if arm_patch
/**
Stores all trait instances of the tree via its name.
**/
public static var nodeTrees = new Map<String, Array<LogicTree>>();
/**
[node name => logic node] for later node replacement for live patching.
**/
public var nodes: Map<String, LogicNode>;
#end
public var loopBreak = false; // Trigger break from loop nodes
public function new() {
super();
#if arm_patch
nodes = new Map<String, LogicNode>();
#end
}
public function add() {}

View file

@ -37,6 +37,6 @@ class LookAtNode extends LogicNode {
v2.setFrom(vto).sub(vfrom).normalize();
q.fromTo(v1, v2);
return q.getEuler();
return q;
}
}

View file

@ -3,7 +3,7 @@ package armory.logicnode;
class MathNode extends LogicNode {
public var property0: String; // Operation
public var property1: String; // Clamp
public var property1: Bool; // Clamp
public function new(tree: LogicTree) {
super(tree);
@ -80,8 +80,8 @@ class MathNode extends LogicNode {
}
}
// Clamp
if (property1 == "true") r = r < 0.0 ? 0.0 : (r > 1.0 ? 1.0 : r);
if (property1) r = r < 0.0 ? 0.0 : (r > 1.0 ? 1.0 : r);
return r;
}
}
}

View file

@ -2,11 +2,31 @@ package armory.logicnode;
class MergeNode extends LogicNode {
/** Execution mode. **/
public var property0: String;
var lastInputIndex = -1;
public function new(tree: LogicTree) {
super(tree);
tree.notifyOnLateUpdate(lateUpdate);
}
override function run(from: Int) {
// Check if there already were executions on the same frame
if (lastInputIndex != -1 && property0 == "once_per_frame") {
return;
}
lastInputIndex = from;
runOutput(0);
}
override function get(from: Int): Dynamic {
return lastInputIndex;
}
function lateUpdate() {
lastInputIndex = -1;
}
}

View file

@ -6,7 +6,7 @@ class MixNode extends LogicNode {
public var property0: String; // Type
public var property1: String; // Ease
public var property2: String; // Clamp
public var property2: Bool; // Clamp
var ease: Float->Float = null;
@ -50,7 +50,9 @@ class MixNode extends LogicNode {
var v2: Float = inputs[2].get();
var f = v1 + (v2 - v1) * ease(k);
if (property2 == "true") f = f < 0 ? 0 : f > 1 ? 1 : f;
// Clamp
if (property2) f = f < 0 ? 0 : f > 1 ? 1 : f;
return f;
}
}

View file

@ -21,7 +21,7 @@ class ObjectNode extends LogicNode {
override function set(value: Dynamic) {
if (inputs.length > 0) inputs[0].set(value);
else {
objectName = value.name;
objectName = value != null ? value.name : "";
this.value = value;
}
}

View file

@ -4,7 +4,7 @@ import armory.trait.internal.CanvasScript;
import iron.Scene;
#if arm_ui
import zui.Canvas.Anchor;
import armory.ui.Canvas.Anchor;
#end
class OnCanvasElementNode extends LogicNode {

View file

@ -0,0 +1,35 @@
package armory.logicnode;
import armory.system.InputMap;
class OnInputMapNode extends LogicNode {
var inputMap: Null<InputMap>;
public function new(tree: LogicTree) {
super(tree);
tree.notifyOnUpdate(update);
}
function update() {
var i = inputs[0].get();
inputMap = InputMap.getInputMap(i);
if (inputMap != null) {
if (inputMap.started()) {
runOutput(0);
}
if (inputMap.released()) {
runOutput(1);
}
}
}
override function get(from: Int): Dynamic {
if (from == 2) return inputMap.value();
else return inputMap.lastKeyPressed;
}
}

View file

@ -120,8 +120,8 @@ class OnSwipeNode extends LogicNode {
switch (from) {
// UP
case 1: {
// 68 - 121
if ((angle >= 68) && (angle < 121)) return true;
// 68 - 112
if ((angle >= 68) && (angle < 112)) return true;
return false;
}
// DOWN
@ -144,8 +144,8 @@ class OnSwipeNode extends LogicNode {
}
// UP-LEFT
case 5: {
// 121 - 158
if ((angle >= 121) && (angle < 158)) return true;
// 112 - 158
if ((angle >= 112) && (angle < 158)) return true;
return false;
}
// UP-RIGHT

View file

@ -37,11 +37,11 @@ class OnVolumeTriggerNode extends LogicNode {
var b = false;
switch (property0) {
case "enter":
case "begin":
b = overlap && !lastOverlap;
case "overlap":
b = overlap;
case "leave":
case "end":
b = !overlap && lastOverlap;
}

View file

@ -0,0 +1,22 @@
package armory.logicnode;
class OncePerFrameNode extends LogicNode {
var c = false;
public function new(tree: LogicTree) {
super(tree);
tree.notifyOnUpdate(update);
}
override function run(from: Int) {
if(c) {
c = false;
runOutput(0);
}
}
function update() {
c = true;
}
}

View file

@ -8,7 +8,7 @@ class PauseTraitNode extends LogicNode {
override function run(from: Int) {
var trait: Dynamic = inputs[1].get();
if (trait == null || !Std.is(trait, LogicTree)) return;
if (trait == null || !Std.isOfType(trait, LogicTree)) return;
cast(trait, LogicTree).pause();

View file

@ -0,0 +1,41 @@
package armory.logicnode;
#if arm_physics
import armory.trait.physics.bullet.PhysicsConstraint.ConstraintAxis;
#end
class PhysicsConstraintNode extends LogicNode {
public var property0: String; //Linear or Angular
public var property1: String; //Axis
public var property2: Bool; //Is a spring
#if arm_physics
public var value1: Float; //Lower limit or Spring Stiffness
public var value2: Float; //Upper limit or Spring Damping
public var isAngular: Bool;
public var axis: ConstraintAxis;
public var isSpring: Bool;
#end
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): PhysicsConstraintNode {
#if arm_physics
value1 = inputs[0].get();
value2 = inputs[1].get();
isAngular = property0 != "Linear";
isSpring = property2;
switch (property1) {
case "X": axis = X;
case "Y": axis = Y;
case "Z": axis = Z;
}
#end
return this;
}
}

View file

@ -15,7 +15,7 @@ class PickLocationNode extends LogicNode {
var object: Object = inputs[0].get();
var coords: Vec4 = inputs[1].get();
if (object == null || coords == null) null;
if (object == null || coords == null) return null;
#if arm_physics
var physics = armory.trait.physics.PhysicsWorld.active;

View file

@ -4,28 +4,32 @@ import iron.math.Vec4;
class PickObjectNode extends LogicNode {
var v = new Vec4();
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var coords: Vec4 = inputs[0].get();
var mask: Int = inputs[1].get();
if (coords == null) return null;
#if arm_physics
var physics = armory.trait.physics.PhysicsWorld.active;
var rb = physics.pickClosest(coords.x, coords.y);
var rb = physics.pickClosest(coords.x, coords.y, mask);
if (rb == null) return null;
if (from == 0) { // Object
return rb.object;
}
else { // Hit
else if(from == 1){ // Hit
var v = new Vec4();
return v.set(physics.hitPointWorld.x, physics.hitPointWorld.y, physics.hitPointWorld.z);
}
else { // Normal
var v = new Vec4();
return v.set(physics.hitNormalWorld.x, physics.hitNormalWorld.y, physics.hitNormalWorld.z, 0);
}
#end
return null;
}

View file

@ -14,6 +14,8 @@ class PlayActionFromNode extends LogicNode {
var action: String = inputs[2].get();
var startFrame:Int = inputs[3].get();
var blendTime: Float = inputs[4].get();
var speed: Float = inputs[5].get();
var loop: Bool = inputs[6].get();
if (object == null) return;
@ -22,7 +24,7 @@ class PlayActionFromNode extends LogicNode {
animation.play(action, function() {
runOutput(1);
},blendTime);
}, blendTime, speed, loop);
animation.update(startFrame*Scene.active.raw.frame_time);
runOutput(0);

View file

@ -12,6 +12,8 @@ class PlaySoundRawNode extends LogicNode {
public var property3: Bool;
/** Playback sample rate */
public var property4: Int;
/** Whether to stream the sound from disk **/
public var property5: Bool;
var sound: kha.Sound = null;
var channel: kha.audio1.AudioChannel = null;
@ -37,7 +39,7 @@ class PlaySoundRawNode extends LogicNode {
// Start
else if (sound != null) {
if (property3) sound.sampleRate = property4;
channel = iron.system.Audio.play(sound, property1);
channel = iron.system.Audio.play(sound, property1, property5);
}
tree.notifyOnUpdate(this.onUpdate);

View file

@ -19,7 +19,7 @@ class QuaternionMathNode extends LogicNode {
override function get(from: Int): Dynamic {
switch (property0) {
// 1 argument: Module, Normalize, GetEuler
// 1 argument: Module, Normalize
case "Module": {
var q: Quat = inputs[0].get();
if (q == null) return null;
@ -32,159 +32,106 @@ class QuaternionMathNode extends LogicNode {
res_q.setFrom(q);
res_q = res_q.normalize();
}
case "GetEuler": {
var q: Quat = inputs[0].get();
if (q == null) return null;
res_q.setFrom(q);
res_v = res_q.getEuler();
}
// 2 arguments: FromTo, FromMat, FromRotationMat, ToAxisAngle
case "FromTo": {
var v1: Vec4 = inputs[0].get();
var v2: Vec4 = inputs[1].get();
if ((v1 == null) || (v2 == null)) return null;
res_q.fromTo(v1, v2);
}
case "FromMat": {
var q: Quat = inputs[0].get();
var m: Mat4 = inputs[1].get();
if ((q == null) || (m == null)) return null;
res_q.setFrom(q);
res_q = res_q.fromMat(m);
}
case "FromRotationMat": {
var q: Quat = inputs[0].get();
var m: Mat4 = inputs[1].get();
if ((q == null) || (m == null)) return null;
res_q.setFrom(q);
res_q = res_q.fromRotationMat(m);
}
case "ToAxisAngle": {
var q: Quat = inputs[0].get();
var v: Vec4 = inputs[1].get();
if ((q == null) || (v == null)) return null;
res_q.setFrom(q);
res_f = res_q.toAxisAngle(v);
}
// # 3 arguments: Lerp, Slerp, FromAxisAngle, FromEuler
case "Lerp": {
var from: Quat = inputs[0].get();
var to: Quat = inputs[1].get();
var f: Float = inputs[2].get();
if ((from == null) || (to == null)) return null;
res_q = res_q.lerp(from, to, f);
}
case "Slerp": {
var from: Quat = inputs[0].get();
var to: Quat = inputs[1].get();
var f: Float = inputs[2].get();
if ((from == null) || (to == null)) return null;
res_q = res_q.slerp(from, to, f);
}
case "FromAxisAngle": {
var q: Quat = inputs[0].get();
var axis: Vec4 = inputs[1].get();
var angle: Float = inputs[2].get();
if ((q == null) || (axis == null)) return null;
res_q.setFrom(q);
res_q = res_q.fromAxisAngle(axis, angle);
}
case "FromEuler": {
var x: Float = inputs[0].get();
var y: Float = inputs[1].get();
var z: Float = inputs[2].get();
res_q = res_q.fromEuler(x, y, z);
}
// Many arguments: Add, Subtract, DotProduct, Multiply
case "Add": {
var q: Quat = inputs[0].get();
if (q == null) return null;
res_q.setFrom(q);
var q2 = new Quat();
res_v = inputs[0].get();
res_f = inputs[1].get();
if (res_v == null || res_f == null) return null;
res_q.set(res_v.x, res_v.y, res_v.z, res_f);
var i = 1;
while (i < inputs.length) {
q2 = inputs[i].get();
if (q2 == null) return null;
res_q.add(q2);
while (2*i+1 < inputs.length) {
res_v = inputs[2*i].get();
res_f = inputs[2*i+1].get();
if (res_v == null || res_f == null) return null;
res_q.x += res_v.x;
res_q.y += res_v.y;
res_q.z += res_v.z;
res_q.w += res_f;
i++;
}
}
case "Subtract": {
var q: Quat = inputs[0].get();
if (q == null) return null;
res_q.setFrom(q);
var q2 = new Quat();
res_v = inputs[0].get();
res_f = inputs[1].get();
if (res_v == null || res_f == null) return null;
res_q.set(res_v.x, res_v.y, res_v.z, res_f);
var i = 1;
while (i < inputs.length) {
q2 = inputs[i].get();
if (q2 == null) return null;
res_q.sub(q2);
while (2*i+1 < inputs.length) {
res_v = inputs[2*i].get();
res_f = inputs[2*i+1].get();
if (res_v == null || res_f == null) return null;
res_q.x -= res_v.x;
res_q.y -= res_v.y;
res_q.z -= res_v.z;
res_q.w -= res_f;
i++;
}
}
case "Multiply": {
var q: Quat = inputs[0].get();
if (q == null) return null;
res_q.setFrom(q);
var q2 = new Quat();
res_v = inputs[0].get();
res_f = inputs[1].get();
if (res_v == null || res_f == null) return null;
res_q.set(res_v.x, res_v.y, res_v.z, res_f);
var i = 1;
while (i < inputs.length) {
q2 = inputs[i].get();
if (q2 == null) return null;
res_q.mult(q2);
while (2*i+1 < inputs.length) {
res_v = inputs[2*i].get();
res_f = inputs[2*i+1].get();
if (res_v == null || res_f == null) return null;
var temp_q = new Quat(res_v.x, res_v.y, res_v.z, res_f);
res_q.mult(temp_q);
i++;
}
}
case "MultiplyFloats": {
var q: Quat = inputs[0].get();
if (q == null) return null;
res_q.setFrom(q);
res_v = inputs[0].get();
res_f = inputs[1].get();
if (res_v == null || res_f == null) return null;
res_q.set(res_v.x, res_v.y, res_v.z, res_f);
var f: Float = 1.0;
var i = 1;
var i = 2;
while (i < inputs.length) {
f = inputs[i].get();
res_q.scale(f);
f *= inputs[i].get();
if (f == null) return null;
i++;
}
res_q.scale(f);
}
case "DotProduct": {
var q: Quat = inputs[0].get();
if (q == null) return null;
res_q.setFrom(q);
var q2 = new Quat();
case "DotProduct": { // what this does with more than 2 terms is not *remotely* intuitive. Heck, you could consider it a footgun!
res_v = inputs[0].get();
var temp_f = inputs[1].get();
if (res_v == null || temp_f == null) return null;
res_q.set(res_v.x, res_v.y, res_v.z, temp_f);
var i = 1;
while (i < inputs.length) {
q2 = inputs[i].get();
if (q2 == null) return null;
res_f = res_q.dot(q2);
while (2*i+1 < inputs.length) {
res_v = inputs[2*i].get();
temp_f = inputs[2*i+1].get();
if (res_v == null || temp_f == null) return null;
var temp_q = new Quat(res_v.x, res_v.y, res_v.z, temp_f);
res_f = res_q.dot(temp_q);
res_q.set(res_f, res_f, res_f, res_f);
i++;
}
}
}
// Return and check separator
switch (from) {
case 0: {
if (property0 == 'GetEuler')
return res_v;
else
return res_q;
return res_q;
}
case 1:
if (property1) {
return res_q.x;
} else {
if (property0 == "DotProduct" || property0 == "Module") {
return res_f;
} else {
return null;
}
case 2:
if (property1) return res_q.y;
case 3:
if (property1) return res_q.z;
case 4:
if (property1) return res_q.w;
case 5:
if (property1) return res_f;
default: {
return null;
}
}
return null;
}
}

View file

@ -11,10 +11,10 @@ class QuaternionNode extends LogicNode {
super(tree);
if (x != null) {
addInput(new FloatNode(tree, x), 0);
addInput(new FloatNode(tree, y), 0);
addInput(new FloatNode(tree, z), 0);
addInput(new FloatNode(tree, w), 0);
LogicNode.addLink(new FloatNode(tree, x), this, 0, 0);
LogicNode.addLink(new FloatNode(tree, y), this, 0, 1);
LogicNode.addLink(new FloatNode(tree, z), this, 0, 2);
LogicNode.addLink(new FloatNode(tree, w), this, 0, 3);
}
}
@ -27,15 +27,15 @@ class QuaternionNode extends LogicNode {
switch (from){
case 0:
return value;
case 1:
var value1 = new Vec4();
case 1:
var value1 = new Vec4();
value1.x = value.x;
value1.y = value.y;
value1.z = value.z;
value1.w = 0; // use 0 to avoid this vector being translated.
return value1;
case 2:
return value.w;
return value.w;
default:
return null;
}

View file

@ -4,18 +4,17 @@ import iron.math.Vec4;
class RandomColorNode extends LogicNode {
var v = new Vec4();
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var r = Math.random();
var g = Math.random();
var b = Math.random();
// var a = Math.random();
v.set(r, g, b);
var v = new Vec4(r, g, b);
return v;
}
}

View file

@ -0,0 +1,19 @@
package armory.logicnode;
import armory.system.InputMap;
class RemoveInputMapKeyNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var inputMap = inputs[1].get();
var key = inputs[2].get();
if (InputMap.removeInputMapKey(inputMap, key)) {
runOutput(0);
}
}
}

View file

@ -8,7 +8,7 @@ class ResumeTraitNode extends LogicNode {
override function run(from: Int) {
var trait: Dynamic = inputs[1].get();
if (trait == null || !Std.is(trait, LogicTree)) return;
if (trait == null || !Std.isOfType(trait, LogicTree)) return;
cast(trait, LogicTree).resume();

View file

@ -2,13 +2,11 @@ package armory.logicnode;
import iron.object.Object;
import iron.math.Quat;
import iron.math.Vec4;
import armory.trait.physics.RigidBody;
class RotateObjectNode extends LogicNode {
public var property0 = "Euler Angles";
var q = new Quat();
public var property0 = "Local";
public function new(tree: LogicTree) {
super(tree);
@ -16,32 +14,19 @@ class RotateObjectNode extends LogicNode {
override function run(from: Int) {
var object: Object = inputs[1].get();
var vec: Vec4 = inputs[2].get();
var q: Quat = inputs[2].get();
// note: here, the next line is disabled because old versions of the node don't have a third input.
// when those old versions will be considered remove, feel free to uncomment that, and replace the other `inputs[3].get()` by `w` in this file.
//var w: Float = inputs[3].get();
if (object == null || q == null) return;
if (object == null || vec == null) return;
switch (property0) {
case "Euler Angles":
q.fromEuler(vec.x, vec.y, vec.z);
case "Angle Axies (Degrees)" | "Angle Axies (Radians)":
var angle: Float = inputs[3].get();
if (property0 == "Angle Axies (Degrees)") {
angle = angle * (Math.PI / 180);
}
var angleSin = Math.sin(angle / 2);
vec = vec.normalize();
var angleCos = Math.cos(angle / 2);
q = new Quat(vec.x * angleSin, vec.y * angleSin, vec.z * angleSin, angleCos);
case "Quaternion":
q = new Quat(vec.x, vec.y, vec.z, inputs[3].get());
q.normalize();
q.normalize();
switch (property0){
case "Local":
object.transform.rot.mult(q);
case "Global":
object.transform.rot.multquats(q, object.transform.rot);
// that function call (Quat.multquats) is weird: it both modifies the object, and returns `this`
}
object.transform.rot.mult(q);
object.transform.buildMatrix();
#if arm_physics

View file

@ -0,0 +1,96 @@
package armory.logicnode;
import iron.math.Quat;
import iron.math.Vec4;
import iron.math.Mat4;
import kha.FastFloat;
class RotationMathNode extends LogicNode {
public var property0: String; // Operation
var res_q = new Quat();
var res_v = new Vec4();
var res_f: FastFloat = 0.0;
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
//var q: Quat = inputs[0].get();
//if (q==null) return null;
//var res_q: Quat = new Quat();
switch (property0) {
// 1 argument: Normalize, Inverse
case "Normalize": {
var q: Quat = inputs[0].get();
if (q==null) return null;
res_q.setFrom(q);
res_q = res_q.normalize();
}
case "Inverse": {
var q: Quat = inputs[0].get();
if (q==null) return null;
var modl = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
modl = -1/modl;
res_q.w = -q.w*modl;
res_q.x = q.x*modl;
res_q.y = q.y*modl;
res_q.z = q.z*modl;
}
// 2 arguments: Compose, Amplify, FromTo, FromRotationMat,
case "FromTo": {
var v1: Vec4 = inputs[0].get();
var v2: Vec4 = inputs[1].get();
if ((v1 == null) || (v2 == null)) return null;
res_q.fromTo(v1, v2);
}
case "Compose": {
var v1: Quat = inputs[0].get();
var v2: Quat = inputs[1].get();
if ((v1 == null) || (v2 == null)) return null;
res_q.multquats(v1,v2);
}
case "Amplify": {
var v1: Quat = inputs[0].get();
var v2: Float = inputs[1].get();
if ((v1 == null) || (v2 == null)) return null;
res_q.setFrom(v1);
var fac2 = Math.sqrt(1- res_q.w*res_q.w);
if (fac2 > 0.001) {
var fac1 = v2*Math.acos(res_q.w);
res_q.w = Math.cos(fac1);
fac1 = Math.sin(fac1)/fac2;
res_q.x *= fac1;
res_q.y *= fac1;
res_q.z *= fac1;
}
}
//case "FromRotationMat": {
// var m: Mat4 = inputs[1].get();
// if (m == null) return null;
// res_q = res_q.fromMat(m);
//}
// # 3 arguments: Lerp, Slerp, FromAxisAngle, FromEuler
case "Lerp": {
//var from = q;
var from: Quat = inputs[0].get();
var to: Quat = inputs[1].get();
var f: Float = inputs[2].get();
if ((from == null) || (f == null) || (to == null)) return null;
res_q = res_q.lerp(from, to, f);
}
case "Slerp": {
//var from = q;
var from:Quat = inputs[0].get();
var to: Quat = inputs[1].get();
var f: Float = inputs[2].get();
if ((from == null) || (f == null) || (to == null)) return null;
res_q = res_q.slerp(from, to, f);
}
}
return res_q;
}
}

View file

@ -0,0 +1,120 @@
package armory.logicnode;
import iron.math.Vec4;
import iron.math.Quat;
import kha.FastFloat;
class RotationNode extends LogicNode {
static inline var toRAD: FastFloat = 0.017453292519943295; // 180/pi
public var property0: String; // type of input (EulerAngles, AxisAngle, Quaternion)
public var property1: String; // angle unit (Deg, Rad)
public var property2: String; // euler order (XYZ, XZY, etc…)
public var value: Quat;
//var input0_cache: Vec4 = new Vec4();
//var input1_cache: Float = 0;
var input_length: Int = 0;
public function new(tree: LogicTree, x: Null<Float> = null,
y: Null<Float> = null,
z: Null<Float> = null,
w: Null<Float> = null
) {
super(tree);
this.value = new Quat();
if (x!=null) this.value.set(x,y,z,w);
for (input in inputs) {
if (input !=null)
this.input_length +=1;
else
break;
}
}
override function get(from: Int): Dynamic {
//var inp0 = inputs[0].get();
//var inp
//if (inputs[0].get())
if (inputs.length == 0){
return this.value;
}
switch (property0){
case "Quaternion": {
if (inputs[0]!=null && inputs[1]!=null) {
var vect: Vec4 = inputs[0].get();
value.x = vect.x;
value.y = vect.y;
value.z = vect.z;
value.w = inputs[1].get();
}
}
case "AxisAngle": {
if (inputs[0]!=null && inputs[1]!=null){
var vec: Vec4 = inputs[0].get();
var angle: FastFloat = inputs[1].get();
if (property1=="Deg")
angle *= toRAD;
value.fromAxisAngle(vec, angle);
}
}
case "EulerAngles": {
if (inputs[0] != null){
var vec: Vec4 = new Vec4().setFrom(inputs[0].get());
if (property1=="Deg"){
vec.x *= toRAD;
vec.y *= toRAD;
vec.z *= toRAD;
}
this.value.fromEulerOrdered(vec, property2);
}
}
default: {
return property0;
}
}
return this.value;
}
override function set(value: Dynamic) {
switch (property0){
case "Quaternion": {
if (input_length>1) {
var vect = new Vec4();
vect.x = value.x;
vect.y = value.y;
vect.z = value.z;
inputs[0].set(vect);
inputs[1].set(value.w);
}
}
case "AxisAngle": {
if (input_length>1){
var vec = new Vec4();
var angle = this.value.toAxisAngle(vec);
if (property1=="Deg")
angle /= toRAD;
inputs[0].set(vec);
inputs[1].set(angle);
}
}
case "EulerAngles": {
if (input_length>0){
var vec:Vec4 = value.toEulerOrdered(property2);
if (property1=="Deg"){
vec.x /= toRAD;
vec.y /= toRAD;
vec.z /= toRAD;
}
inputs[0].set(vec);
}
}
}
if (input_length > 0){
// NYI
}else this.value=value;
}
}

View file

@ -0,0 +1,37 @@
package armory.logicnode;
class SelectNode extends LogicNode {
/** Execution mode. **/
public var property0: String;
var value: Dynamic = null;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
// Get value according to the activated input (run() can only be called
// if the execution mode is from_input).
value = inputs[from + Std.int(inputs.length / 2)].get();
runOutput(0);
}
override function get(from: Int): Dynamic {
if (property0 == "from_index") {
var index = inputs[0].get() + 2;
// Return default value for invalid index
if (index < 2 || index >= inputs.length) {
return inputs[1].get();
}
return inputs[index].get();
}
// from_input
return value;
}
}

View file

@ -5,8 +5,6 @@ import armory.system.Event;
class SendEventNode extends LogicNode {
var entries: Array<TEvent> = null;
public function new(tree: LogicTree) {
super(tree);
}
@ -17,13 +15,9 @@ class SendEventNode extends LogicNode {
if (object == null) return;
var all = Event.get(name);
if (all != null) {
entries = [];
for (e in all) if (e.mask == object.uid) entries.push(e);
}
var entries = Event.get(name);
if (entries == null) return;
for (e in entries) e.onEvent();
for (e in entries) if (e.mask == object.uid) e.onEvent();
runOutput(0);
}

View file

@ -4,8 +4,6 @@ import armory.system.Event;
class SendGlobalEventNode extends LogicNode {
var entries: Array<TEvent> = null;
public function new(tree: LogicTree) {
super(tree);
}
@ -13,7 +11,7 @@ class SendGlobalEventNode extends LogicNode {
override function run(from: Int) {
var name: String = inputs[1].get();
entries = Event.get(name);
var entries = Event.get(name);
if (entries == null) return; // Event does not exist
for (e in entries) e.onEvent();

View file

@ -0,0 +1,60 @@
package armory.logicnode;
import kha.FastFloat;
import iron.math.Quat;
import iron.math.Vec4;
class SeparateRotationNode extends LogicNode {
public var property0 = "EulerAngles"; // EulerAngles, AxisAngle, or Quat
public var property1 = "Rad"; // Rad or Deg
public var property2 = "XYZ";
static inline var toDEG:FastFloat = 57.29577951308232; // 180/pi
var input_cache = new Quat();
var euler_cache = new Vec4();
var aa_axis_cache = new Vec4();
var aa_angle_cache: Float = 0;
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var q: Quat = inputs[0].get();
if (q == null) return null;
q.normalize();
switch (property0) {
case "EulerAngles":
if (q!=this.input_cache)
euler_cache = q.toEulerOrdered(property2);
if (from>0)
return null;
switch (property1){
case "Rad": return euler_cache;
case "Deg": return new Vec4(euler_cache.x*toDEG, euler_cache.y*toDEG, euler_cache.z*toDEG);
}
case "AxisAngle":
if (q!=this.input_cache)
aa_angle_cache = q.toAxisAngle(aa_axis_cache);
switch (from){
case 0: return aa_axis_cache;
case 1: switch(property1){
case "Rad": return aa_angle_cache;
case "Deg": return toDEG*aa_angle_cache;
}
}
case "Quaternion":
switch(from){
case 0: return new Vec4(q.x,q.y,q.z);
case 1: return q.w;
}
}
return null;
}
}

View file

@ -20,7 +20,7 @@ class SeparateTransformNode extends LogicNode {
matrix.decompose(loc, rot, scale);
if (from == 0) return loc;
else if (from == 1) return rot.getEuler();
else if (from == 1) return rot;
else return scale;
}
}

View file

@ -0,0 +1,35 @@
package armory.logicnode;
import iron.math.Quat;
import iron.math.Vec4;
import iron.object.Object;
import iron.object.BoneAnimation;
class SetBoneFkIkOnlyNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
#if arm_skin
var object: Object = inputs[1].get();
var boneName: String = inputs[2].get();
var fk_ik_only: Bool = inputs[3].get();
if (object == null) return;
var anim = object.animation != null ? cast(object.animation, BoneAnimation) : null;
if (anim == null) anim = object.getParentArmature(object.name);
// Get bone in armature
var bone = anim.getBone(boneName);
//Set bone animated by FK or IK only
bone.is_ik_fk_only = fk_ik_only;
runOutput(0);
#end
}
}

View file

@ -0,0 +1,25 @@
package armory.logicnode;
import iron.Scene;
import armory.trait.internal.CanvasScript;
class SetGlobalCanvasFontSizeNode extends LogicNode {
var canvas: CanvasScript;
var factor: Int;
public function new(tree: LogicTree) {
super(tree);
}
#if arm_ui
override function run(from: Int) {
factor = inputs[1].get();
canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
canvas.setCanvasFontSize(factor);
runOutput(0);
}
#end
}

View file

@ -0,0 +1,25 @@
package armory.logicnode;
import iron.Scene;
import armory.trait.internal.CanvasScript;
class SetGlobalCanvasScaleNode extends LogicNode {
var canvas: CanvasScript;
var factor: Float;
public function new(tree: LogicTree) {
super(tree);
}
#if arm_ui
override function run(from: Int) {
factor = inputs[1].get();
canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
canvas.setUiScale(factor);
runOutput(0);
}
#end
}

View file

@ -0,0 +1,46 @@
package armory.logicnode;
import armory.system.InputMap;
class SetInputMapKeyNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var inputMap = inputs[1].get();
var key = inputs[2].get();
var scale = inputs[3].get();
var deadzone = inputs[4].get();
var index = inputs[5].get();
var i = InputMap.getInputMap(inputMap);
if (i == null) {
i = InputMap.addInputMap(inputMap);
}
var k = InputMap.getInputMapKey(inputMap, key);
if (k == null) {
switch(property0) {
case "keyboard": k = i.addKeyboard(key, scale);
case "mouse": k = i.addMouse(key, scale, deadzone);
case "gamepad": {
k = i.addGamepad(key, scale, deadzone);
k.setIndex(index);
}
}
} else {
k.scale = scale;
k.deadzone = deadzone;
k.setIndex(index);
}
runOutput(0);
}
}

View file

@ -13,9 +13,21 @@ class SetLocationNode extends LogicNode {
override function run(from: Int) {
var object: Object = inputs[1].get();
var vec: Vec4 = inputs[2].get();
var relative: Bool = inputs[3].get();
if (object == null || vec == null) return;
if (!relative && object.parent != null) {
var loc = vec.clone();
loc.sub(object.parent.transform.world.getLoc()); // Remove parent location influence
// Convert vec to parent local space
var dotX = loc.dot(object.parent.transform.right());
var dotY = loc.dot(object.parent.transform.look());
var dotZ = loc.dot(object.parent.transform.up());
vec.set(dotX, dotY, dotZ);
}
object.transform.loc.setFrom(vec);
object.transform.buildMatrix();
@ -26,4 +38,4 @@ class SetLocationNode extends LogicNode {
runOutput(0);
}
}
}

View file

@ -1,40 +1,40 @@
package armory.logicnode;
import iron.Scene;
import iron.data.MaterialData;
import iron.object.Object;
import armory.trait.internal.UniformsManager;
class SetMaterialImageParamNode extends LogicNode {
static var registered = false;
static var map = new Map<MaterialData, Map<String, kha.Image>>();
public function new(tree: LogicTree) {
super(tree);
if (!registered) {
registered = true;
iron.object.Uniforms.externalTextureLinks.push(textureLink);
}
}
override function run(from: Int) {
var mat = inputs[1].get();
if (mat == null) return;
var entry = map.get(mat);
if (entry == null) {
entry = new Map();
map.set(mat, entry);
var perObject: Null<Bool>;
var object = inputs[1].get();
if(object == null) return;
perObject = inputs[2].get();
if(perObject == null) perObject = false;
var mat = inputs[3].get();
if(mat == null) return;
if(! perObject){
UniformsManager.removeObjectFromMap(object, Texture);
object = Scene.active.root;
}
iron.data.Data.getImage(inputs[3].get(), function(image: kha.Image) {
entry.set(inputs[2].get(), image); // Node name, value
var img = inputs[5].get();
if(img == null) return;
iron.data.Data.getImage(img, function(image: kha.Image) {
UniformsManager.setTextureValue(mat, object, inputs[4].get(), image);
});
runOutput(0);
}
static function textureLink(object: Object, mat: MaterialData, link: String): kha.Image {
if (mat == null) return null;
var entry = map.get(mat);
if (entry == null) return null;
return entry.get(link);
}
}

View file

@ -1,38 +1,35 @@
package armory.logicnode;
import iron.Scene;
import iron.math.Vec4;
import iron.data.MaterialData;
import iron.object.Object;
import armory.trait.internal.UniformsManager;
class SetMaterialRgbParamNode extends LogicNode {
static var registered = false;
static var map = new Map<MaterialData, Map<String, Vec4>>();
public function new(tree: LogicTree) {
super(tree);
if (!registered) {
registered = true;
iron.object.Uniforms.externalVec3Links.push(vec3Link);
}
}
override function run(from: Int) {
var mat = inputs[1].get();
if (mat == null) return;
var entry = map.get(mat);
if (entry == null) {
entry = new Map();
map.set(mat, entry);
var perObject: Null<Bool>;
var object = inputs[1].get();
if(object == null) return;
perObject = inputs[2].get();
if(perObject == null) perObject = false;
var mat = inputs[3].get();
if(mat == null) return;
if(! perObject){
UniformsManager.removeObjectFromMap(object, Vector);
object = Scene.active.root;
}
entry.set(inputs[2].get(), inputs[3].get()); // Node name, value
UniformsManager.setVec3Value(mat, object, inputs[4].get(), inputs[5].get());
runOutput(0);
}
static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
if (mat == null) return null;
var entry = map.get(mat);
if (entry == null) return null;
return entry.get(link);
}
}

View file

@ -1,37 +1,35 @@
package armory.logicnode;
import iron.Scene;
import iron.data.MaterialData;
import iron.object.Object;
import armory.trait.internal.UniformsManager;
class SetMaterialValueParamNode extends LogicNode {
static var registered = false;
static var map = new Map<MaterialData, Map<String, Null<kha.FastFloat>>>();
public function new(tree: LogicTree) {
super(tree);
if (!registered) {
registered = true;
iron.object.Uniforms.externalFloatLinks.push(floatLink);
}
}
override function run(from: Int) {
var mat = inputs[1].get();
if (mat == null) return;
var entry = map.get(mat);
if (entry == null) {
entry = new Map();
map.set(mat, entry);
var perObject: Null<Bool>;
var object = inputs[1].get();
if(object == null) return;
perObject = inputs[2].get();
if(perObject == null) perObject = false;
var mat = inputs[3].get();
if(mat == null) return;
if(! perObject){
UniformsManager.removeObjectFromMap(object, Float);
object = Scene.active.root;
}
entry.set(inputs[2].get(), inputs[3].get()); // Node name, value
UniformsManager.setFloatValue(mat, object, inputs[4].get(), inputs[5].get());
runOutput(0);
}
static function floatLink(object: Object, mat: MaterialData, link: String): Null<kha.FastFloat> {
if (mat == null) return null;
var entry = map.get(mat);
if (entry == null) return null;
return entry.get(link);
}
}

View file

@ -0,0 +1,25 @@
package armory.logicnode;
import iron.object.MeshObject;
class SetObjectShapeKeyNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
#if arm_morph_target
var object: Dynamic = inputs[1].get();
var shapeKey: String = inputs[2].get();
var value: Dynamic = inputs[3].get();
assert(Error, object != null, "Object should not be null");
var morph = cast(object, MeshObject).morphTarget;
assert(Error, morph != null, "Object does not have shape keys");
morph.setMorphValue(shapeKey, value);
#end
runOutput(0);
}
}

View file

@ -14,8 +14,9 @@ class SetParentNode extends LogicNode {
var parent: Object;
var isUnparent = false;
if (Std.is(inputs[2].node, ObjectNode)) {
var parentNode = cast(inputs[2].node, ObjectNode);
if (Std.isOfType(inputs[2].fromNode, ObjectNode)) {
var parentNode = cast(inputs[2].fromNode, ObjectNode);
isUnparent = parentNode.objectName == "";
}
if (isUnparent) parent = iron.Scene.active.root;
@ -24,7 +25,7 @@ class SetParentNode extends LogicNode {
if (object == null || parent == null || object.parent == parent) return;
object.parent.removeChild(object, isUnparent); // keepTransform
#if arm_physics
var rigidBody = object.getTrait(RigidBody);
if (rigidBody != null) rigidBody.setActivationState(0);

View file

@ -1,13 +1,13 @@
package armory.logicnode;
import iron.object.Object;
import iron.math.Quat;
import iron.math.Vec4;
import armory.trait.physics.RigidBody;
class SetRotationNode extends LogicNode {
public var property0: String;
public var property0: String; // UNUSED
public function new(tree: LogicTree) {
super(tree);
@ -16,27 +16,13 @@ class SetRotationNode extends LogicNode {
override function run(from: Int) {
var object: Object = inputs[1].get();
if (object == null) return;
var vec: Vec4 = inputs[2].get();
if (vec == null) return;
var w: Float = inputs[3].get();
var q: Quat = inputs[2].get();
if (q == null) return;
switch (property0) {
case "Euler Angles":
object.transform.rot.fromEuler(vec.x, vec.y, vec.z);
case "Angle Axies (Degrees)" | "Angle Axies (Radians)":
var angle: Float = w;
if (property0 == "Angle Axies (Degrees)") {
angle = angle * (Math.PI / 180);
}
var angleSin = Math.sin(angle / 2);
vec = vec.normalize();
var angleCos = Math.cos(angle / 2);
object.transform.rot = new Quat(vec.x * angleSin, vec.y * angleSin, vec.z * angleSin, angleCos);
case "Quaternion":
object.transform.rot = new Quat(vec.x, vec.y, vec.z, w);
object.transform.rot.normalize();
}
q.normalize();
object.transform.rot = q;
object.transform.buildMatrix();
#if arm_physics
var rigidBody = object.getTrait(RigidBody);
if (rigidBody != null) {

View file

@ -0,0 +1,65 @@
package armory.logicnode;
import iron.data.MaterialData;
import iron.object.Object;
class SetShaderUniformNode extends LogicNode {
static var registered = false;
static var intMap = new Map<String, Null<Int>>();
static var floatMap = new Map<String, Null<kha.FastFloat>>();
static var vec2Map = new Map<String, iron.math.Vec4>();
static var vec3Map = new Map<String, iron.math.Vec4>();
static var vec4Map = new Map<String, iron.math.Vec4>();
/** Uniform type **/
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
if (!registered) {
registered = true;
iron.object.Uniforms.externalIntLinks.push(intLink);
iron.object.Uniforms.externalFloatLinks.push(floatLink);
iron.object.Uniforms.externalVec2Links.push(vec2Link);
iron.object.Uniforms.externalVec3Links.push(vec3Link);
iron.object.Uniforms.externalVec4Links.push(vec4Link);
}
}
override function run(from: Int) {
var uniformName: String = inputs[1].get();
if (uniformName == null) return;
switch (property0) {
case "int": intMap.set(uniformName, inputs[2].get());
case "float": floatMap.set(uniformName, inputs[2].get());
case "vec2": vec2Map.set(uniformName, inputs[2].get());
case "vec3": vec3Map.set(uniformName, inputs[2].get());
case "vec4": vec4Map.set(uniformName, inputs[2].get());
default:
}
runOutput(0);
}
static function intLink(object: Object, mat: MaterialData, link: String): Null<Int> {
return intMap.get(link);
}
static function floatLink(object: Object, mat: MaterialData, link: String): Null<kha.FastFloat> {
return floatMap.get(link);
}
static function vec2Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
return vec2Map.get(link);
}
static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
return vec3Map.get(link);
}
static function vec4Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
return vec4Map.get(link);
}
}

View file

@ -10,7 +10,7 @@ class SetTraitPausedNode extends LogicNode {
var trait: Dynamic = inputs[1].get();
var paused: Bool = inputs[2].get();
if (trait == null || !Std.is(trait, LogicTree)) return;
if (trait == null || !Std.isOfType(trait, LogicTree)) return;
paused ? cast(trait, LogicTree).pause() : cast(trait, LogicTree).resume();

Some files were not shown because too many files have changed in this diff Show more