Compare commits
	
		
			304 Commits
		
	
	
		
			1958342a74
			...
			e2002e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 316441b954 | |||
| 9d7613be8f | |||
| c989f3254f | |||
| f8d76929ae | |||
| a51c28b607 | |||
| 9142371f88 | |||
| 35f92341fa | |||
| a8d1eebdaf | |||
| 87922c9389 | |||
| 38287f56b0 | |||
| 42ad5b01c1 | |||
| 2b46d6ebca | |||
| 953ad8391c | |||
| 1458ecd84f | |||
| 288b085d0c | |||
| aa0b2b1b7e | |||
| acede01167 | |||
| 92a2b0305e | |||
| 4886953722 | |||
| 601860b242 | |||
| f00cef2e21 | |||
| e733dca053 | |||
| 387be05826 | |||
| c5b21a9bb3 | |||
| 5b2c7bfc84 | |||
| 47d913ab64 | |||
| 878ce14254 | |||
| 9075931c51 | |||
| 39ab42f2da | |||
| 30cab4d79b | |||
| 8ee2aaa70a | |||
| 2f9694632d | |||
| 7b8d73cd84 | |||
| 3d8bd77c59 | |||
| 290289f413 | |||
| 2732210fc9 | |||
| 68900fb992 | |||
| ef724ae323 | |||
| 6d4c1a680b | |||
| 8aeaa0368e | |||
| 7969286fdc | |||
| cde2bead97 | |||
| c42e4c09a8 | |||
| b8c8ccad9d | |||
| 335f3541f1 | |||
| 808dcef817 | |||
| 6ac06cc504 | |||
| 86de9617f3 | |||
| 29761ec9e6 | |||
| ea7cf849b8 | |||
| 5d559734b9 | |||
| 939346c896 | |||
| f2dcfc0ffa | |||
| e78bd17d93 | |||
| f9a02f03cb | |||
| 21a4ee0af7 | |||
| 9bf83bc49f | |||
| d88e1f0f42 | |||
| 96f4e29778 | |||
| 1d705d2ca2 | |||
| 0979cd976f | |||
| db6d786ee4 | |||
| 06319131fd | |||
| c08e1d3835 | |||
| 27bd360317 | |||
| 82a53a868a | |||
| 94eaba7319 | |||
| 8d1c2c51bd | |||
| 07d98639f2 | |||
| 1944fc97b8 | |||
| d69e3438ff | |||
| 62e52a7316 | |||
| c4b48c2d87 | |||
| 96f69a7cfe | |||
| 90950970f0 | |||
| 106e36e30d | |||
| e71b0849b3 | |||
| e079c94832 | |||
| 5572494f3d | |||
| 8f03927391 | |||
| 6586d90177 | |||
| 952cee36a3 | |||
| 35bfdf3715 | |||
| 135aaa0669 | |||
| c6b776a329 | |||
| 67c7443985 | |||
| 42273470c3 | |||
| 4dfc6be702 | |||
| 92e1abcfdc | |||
| 764eefeb06 | |||
| 979dfc605d | |||
| 55fb300901 | |||
| c59e6a66d4 | |||
| 659802b888 | |||
| 33f6fcaaaf | |||
| d37b41b181 | |||
| 70742b823f | |||
| da8f9d23e4 | |||
| ff886e6d46 | |||
| 70a603cf7a | |||
| bfc4c2644f | |||
| f101124d24 | |||
| c6f672bd61 | |||
| 7f38b15fe7 | |||
| 2bb296028f | |||
| 5628493493 | |||
| f8a08a41b1 | |||
| 2cd91f598c | |||
| a20d6b581c | |||
| e34ed0794f | |||
| bdcf4c980b | |||
| 25d7ba3e72 | |||
| 30e5acf9bf | |||
| c3435b9533 | |||
| 8765e894f5 | |||
| 2c5c8d0e4f | |||
| 4805dd06a7 | |||
| 2bc2ab43a1 | |||
| bf7b4416ec | |||
| a2d03cfe6e | |||
| 95f0ecfc54 | |||
| 07f59224fc | |||
| 02259985be | |||
| 6b8585c81a | |||
| 5d78eabf94 | |||
| 41c1459c4e | |||
| 304a497565 | |||
| 9fa399371a | |||
| 4625fdb6b2 | |||
| 79553927aa | |||
| 86661c1012 | |||
| 03967c7a2b | |||
| 61fd48a12f | |||
| 519039b8b6 | |||
| 5244b1b3e8 | |||
| 7ae3bbe496 | |||
| 001be2f8da | |||
| 6a25b3c5d7 | |||
| 8d4ac7251a | |||
| ae63b252c6 | |||
| ee73823206 | |||
| af2850e20c | |||
| bc4a31d415 | |||
| 5303ad3ac6 | |||
| 5153cff790 | |||
| abe17870ce | |||
| c798f122d0 | |||
| d1edb1464e | |||
| ee8d3314b5 | |||
| c6139282ed | |||
| 559a3b8b39 | |||
| 8d072ae481 | |||
| 293a612e9c | |||
| 8020599513 | |||
| 4fbc1aba7f | |||
| 1380585297 | |||
| beee036a3d | |||
| 76b2ba8f80 | |||
| e7143cc740 | |||
| bd0886b1d7 | |||
| 8eb8c0bd98 | |||
| dd06e490a7 | |||
| 5e4ac6dd0b | |||
| be0a9149ad | |||
| 7ab3398941 | |||
| c10e988d2d | |||
| caafeea2f1 | |||
| 2edee3fe68 | |||
| af147c9c63 | |||
| 8e4c20647b | |||
| 594cbeffbe | |||
| e1d48e4289 | |||
| 7960ca94a6 | |||
| 72f14f59bf | |||
| d994d040ef | |||
| 1e18795d29 | |||
| 9557b82970 | |||
| 88949c63c5 | |||
| 7cab325397 | |||
| 8792ef5cee | |||
| 761b1832ad | |||
| 074a51866f | |||
| c382460355 | |||
| 4a3544b5d8 | |||
| 7cebe8340f | |||
| ecaea8ad9d | |||
| cae7963b21 | |||
| 7a2976ced1 | |||
| aae64aa8f8 | |||
| ef25d15aed | |||
| 01bcf029f9 | |||
| 2b9baef712 | |||
| 489057018e | |||
| 501a064d25 | |||
| 9478e4e957 | |||
| 32c6535f8a | |||
| 21c2abe67c | |||
| 2b1b56bc0a | |||
| 9e47c1db6d | |||
| 6be977da7e | |||
| 693fa36ee1 | |||
| 6ec480930a | |||
| a627a52d46 | |||
| be63323c09 | |||
| 38595db46b | |||
| 48d28f6873 | |||
| eb033149a0 | |||
| db1c3bdf4c | |||
| 2b16b565a8 | |||
| 8c758bf51f | |||
| 1764081740 | |||
| c90bde8719 | |||
| bfb11275df | |||
| 3185f61f39 | |||
| fb00ca88ff | |||
| 78109cfee2 | |||
| fa65c02e8a | |||
| cb93ede7d7 | |||
| 2a3f8db0bc | |||
| 3ab9123000 | |||
| d6b4b6eeea | |||
| 2f1e6783a4 | |||
| 603a976adf | |||
| 1e0d32a88d | |||
| 82a7075308 | |||
| de8f7d08ed | |||
| caf95e2611 | |||
| b639f06aba | |||
| de41800e1c | |||
| d2746fb087 | |||
| 62d3e65796 | |||
| 74473087b5 | |||
| 392da64d1f | |||
| 30748390ca | |||
| f9d463ca1d | |||
| b8771e9d81 | |||
| 1f52eed66c | |||
| e562b626cb | |||
| ccb554ba16 | |||
| 972775b432 | |||
| ee984c332e | |||
| 038e5123c9 | |||
| b5575e5a48 | |||
| 76d79e6e18 | |||
| ca8fd0b357 | |||
| 87fa82e3d3 | |||
| 9fa58d9d7c | |||
| 864568d66b | |||
| f3e96546ae | |||
| fcc114aed3 | |||
| df33848bee | |||
| c17516a4e2 | |||
| 9b9acd5e15 | |||
| 3b0eb0e075 | |||
| f5b3da3a15 | |||
| b71275d0d5 | |||
| 6aeb9b0f22 | |||
| 609477737e | |||
| a747f89438 | |||
| 0bd0c57a00 | |||
| f3ab801928 | |||
| 9b821d4b8e | |||
| f2a0dbe36c | |||
| 12e66d8cf1 | |||
| 4b6424b702 | |||
| e66e082cc7 | |||
| 42eff22cbb | |||
| 448898a634 | |||
| 15ec41b1f0 | |||
| c5a7746c84 | |||
| 51aa8ea1d4 | |||
| ccdfc4246f | |||
| aead4c4903 | |||
| d2f4c0e221 | |||
| 887eeebe27 | |||
| 83077e3f15 | |||
| f5c20c5a13 | |||
| 4bd4995b6e | |||
| 381744e678 | |||
| 34c15c29cd | |||
| 0346e27657 | |||
| 9087b9c98c | |||
| f2cbcc88a7 | |||
| b8d9ea2aff | |||
| 37a09d0a21 | |||
| ed932e3fa4 | |||
| f00edd882f | |||
| f403955fcd | |||
| a562af9b60 | |||
| bdd9b0197f | |||
| f200933375 | |||
| 829ef5f269 | |||
| 0d73133f36 | |||
| 181b860360 | |||
| 20db9cc24d | |||
| c67b38ea1e | |||
| adb95eab1e | |||
| 93addd1200 | |||
| 7f9a7c9b4a | |||
| 7433409cda | |||
| 2a6e05aff1 | |||
| 348d7bf343 | |||
| 4c6df16aa7 | |||
| 8a7f5ee519 | 
| @ -18,7 +18,7 @@ | |||||||
|  * |  * | ||||||
|  *  This file is part of mbed TLS (https://tls.mbed.org) |  *  This file is part of mbed TLS (https://tls.mbed.org) | ||||||
|  */ |  */ | ||||||
|  | #define _GNU_SOURCE | ||||||
| #if !defined(MBEDTLS_CONFIG_FILE) | #if !defined(MBEDTLS_CONFIG_FILE) | ||||||
| #include "mbedtls/config.h" | #include "mbedtls/config.h" | ||||||
| #else | #else | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ if (platform == Platform.OSX) project.addDefine('KORE_DEBUGDIR="osx-hl"'); | |||||||
| if (platform == Platform.iOS) project.addDefine('KORE_DEBUGDIR="ios-hl"'); | if (platform == Platform.iOS) project.addDefine('KORE_DEBUGDIR="ios-hl"'); | ||||||
| if (platform !== Platform.Windows || audio !== AudioApi.DirectSound) { | if (platform !== Platform.Windows || audio !== AudioApi.DirectSound) { | ||||||
| 	project.addDefine('KORE_MULTITHREADED_AUDIO'); | 	project.addDefine('KORE_MULTITHREADED_AUDIO'); | ||||||
|  | 	project.addDefine('KINC_MULTITHREADED_AUDIO'); | ||||||
| } | } | ||||||
|  |  | ||||||
| project.addDefine('KORE'); | project.addDefine('KORE'); | ||||||
|  | |||||||
| @ -1,16 +1,55 @@ | |||||||
| package kha.graphics4; | package kha.graphics4; | ||||||
|  | using StringTools; | ||||||
| import kha.Blob; | import kha.Blob; | ||||||
|  |  | ||||||
| class FragmentShader { | class FragmentShader { | ||||||
| 	public var _shader: Pointer; | 	public var _shader: Pointer; | ||||||
|  |  | ||||||
| 	public function new(sources: Array<Blob>, files: Array<String>) { | 	public function new(sources: Array<Blob>, files: Array<String>) { | ||||||
| 		initShader(sources[0]); | 		//initShader(sources[0]); | ||||||
|  | 		var shaderBlob: Blob = null; | ||||||
|  | 		var shaderFile: String = null; | ||||||
|  |  | ||||||
|  | 		#if kha_opengl | ||||||
|  | 		final expectedExtension = ".glsl"; | ||||||
|  | 		#elseif kha_direct3d11 | ||||||
|  | 		final expectedExtension = ".d3d11"; | ||||||
|  | 		#elseif kha_direct3d12 | ||||||
|  | 		final expectedExtension = ".d3d12"; | ||||||
|  | 		#elseif kha_metal | ||||||
|  | 		final expectedExtension = ".metal"; | ||||||
|  | 		#elseif kha_vulkan | ||||||
|  | 		final expectedExtension = ".spirv"; | ||||||
|  | 		#else | ||||||
|  | 		final expectedExtension = ".glsl"; | ||||||
|  | 		#end | ||||||
|  |  | ||||||
|  | 		if (sources != null && files != null) { | ||||||
|  | 			for (i in 0...files.length) { | ||||||
|  | 				if (files[i].endsWith(expectedExtension)) { | ||||||
|  | 					shaderBlob = sources[i]; | ||||||
|  | 					shaderFile = files[i]; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (shaderBlob == null && sources != null && sources.length > 0) { | ||||||
|  | 			trace('Warning: Could not find shader with extension ${expectedExtension}. Falling back to sources[0]: ${files != null && files.length > 0 ? files[0] : "Unknown"}'); | ||||||
|  | 			shaderBlob = sources[0]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (shaderBlob != null) { | ||||||
|  | 			initShader(shaderBlob); | ||||||
|  | 		} else { | ||||||
|  | 			trace('Error: No suitable fragment shader source found!'); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function initShader(source: Blob): Void { | 	function initShader(source: Blob): Void { | ||||||
| 		_shader = kinc_create_fragmentshader(source.bytes.getData(), source.bytes.getData().length); | 		//_shader = kinc_create_fragmentshader(source.bytes.getData(), source.bytes.getData().length); | ||||||
|  | 		_shader = kinc_create_fragmentshader(source.bytes.getData(), source.length); // Use source.length here | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static function fromSource(source: String): FragmentShader { | 	public static function fromSource(source: String): FragmentShader { | ||||||
|  | |||||||
| @ -1,179 +1,38 @@ | |||||||
| #include <kinc/compute/compute.h> | #include <kinc/graphics4/compute.h> | ||||||
| #include <kinc/graphics4/texture.h> | #include <kinc/graphics4/texture.h> | ||||||
|  |  | ||||||
| #include <hl.h> | #include <hl.h> | ||||||
|  |  | ||||||
| vbyte *hl_kinc_compute_create_shader(vbyte *data, int length) { | vbyte *hl_kinc_compute_create_shader(vbyte *data, int length) { | ||||||
| 	kinc_compute_shader_t *shader = (kinc_compute_shader_t *)malloc(sizeof(kinc_compute_shader_t)); | 	kinc_g4_compute_shader *shader = (kinc_g4_compute_shader *)malloc(sizeof(kinc_g4_compute_shader)); | ||||||
| 	kinc_compute_shader_init(shader, data, length); | 	kinc_g4_compute_shader_init(shader, data, length); | ||||||
| 	return (vbyte *)shader; | 	return (vbyte *)shader; | ||||||
| } | } | ||||||
|  |  | ||||||
| void hl_kinc_compute_delete_shader(vbyte *shader) { | void hl_kinc_compute_delete_shader(vbyte *shader) { | ||||||
| 	kinc_compute_shader_t *sh = (kinc_compute_shader_t *)shader; | 	kinc_g4_compute_shader *sh = (kinc_g4_compute_shader *)shader; | ||||||
| 	kinc_compute_shader_destroy(sh); | 	kinc_g4_compute_shader_destroy(sh); | ||||||
| 	free(sh); | 	free(sh); | ||||||
| } | } | ||||||
|  |  | ||||||
| vbyte *hl_kinc_compute_get_constantlocation(vbyte *shader, vbyte *name) { | vbyte *hl_kinc_compute_get_constantlocation(vbyte *shader, vbyte *name) { | ||||||
| 	kinc_compute_shader_t *sh = (kinc_compute_shader_t *)shader; | 	kinc_g4_compute_shader *sh = (kinc_g4_compute_shader *)shader; | ||||||
| 	kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)malloc(sizeof(kinc_compute_constant_location_t)); | 	kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)malloc(sizeof(kinc_g4_constant_location_t)); | ||||||
| 	*location = kinc_compute_shader_get_constant_location(sh, (char *)name), sizeof(kinc_compute_constant_location_t); | 	*location = kinc_g4_compute_shader_get_constant_location(sh, (char *)name); | ||||||
| 	return (vbyte *)location; | 	return (vbyte *)location; | ||||||
| } | } | ||||||
|  |  | ||||||
| vbyte *hl_kinc_compute_get_textureunit(vbyte *shader, vbyte *name) { | vbyte *hl_kinc_compute_get_textureunit(vbyte *shader, vbyte *name) { | ||||||
| 	kinc_compute_shader_t *sh = (kinc_compute_shader_t *)shader; | 	kinc_g4_compute_shader *sh = (kinc_g4_compute_shader *)shader; | ||||||
| 	kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)malloc(sizeof(kinc_compute_texture_unit_t)); | 	kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)malloc(sizeof(kinc_g4_texture_unit_t)); | ||||||
| 	*unit = kinc_compute_shader_get_texture_unit(sh, (char *)name), sizeof(kinc_compute_texture_unit_t); | 	*unit = kinc_g4_compute_shader_get_texture_unit(sh, (char *)name); | ||||||
| 	return (vbyte *)unit; | 	return (vbyte *)unit; | ||||||
| } | } | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_bool(vbyte *location, bool value) { | void hl_kinc_set_compute_shader(vbyte *shader) { | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; | 	kinc_g4_set_compute_shader((kinc_g4_compute_shader *)shader); | ||||||
| 	kinc_compute_set_bool(*loc, value); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_int(vbyte *location, int value) { | void hl_kinc_compute(int x, int y, int z) { | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; | 	kinc_g4_compute(x, y, z); | ||||||
| 	kinc_compute_set_int(*loc, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_float(vbyte *location, float value) { |  | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; |  | ||||||
| 	kinc_compute_set_float(*loc, value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_float2(vbyte *location, float value1, float value2) { |  | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; |  | ||||||
| 	kinc_compute_set_float2(*loc, value1, value2); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_float3(vbyte *location, float value1, float value2, float value3) { |  | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; |  | ||||||
| 	kinc_compute_set_float3(*loc, value1, value2, value3); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_float4(vbyte *location, float value1, float value2, float value3, float value4) { |  | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; |  | ||||||
| 	kinc_compute_set_float4(*loc, value1, value2, value3, value4); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_floats(vbyte *location, vbyte *values, int count) { |  | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; |  | ||||||
| 	kinc_compute_set_floats(*loc, (float *)values, count); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_matrix(vbyte *location, float _00, float _10, float _20, float _30, float _01, float _11, float _21, float _31, float _02, float _12, |  | ||||||
|                                 float _22, float _32, float _03, float _13, float _23, float _33) { |  | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; |  | ||||||
| 	kinc_matrix4x4_t value; |  | ||||||
| 	kinc_matrix4x4_set(&value, 0, 0, _00); |  | ||||||
| 	kinc_matrix4x4_set(&value, 0, 1, _01); |  | ||||||
| 	kinc_matrix4x4_set(&value, 0, 2, _02); |  | ||||||
| 	kinc_matrix4x4_set(&value, 0, 3, _03); |  | ||||||
| 	kinc_matrix4x4_set(&value, 1, 0, _10); |  | ||||||
| 	kinc_matrix4x4_set(&value, 1, 1, _11); |  | ||||||
| 	kinc_matrix4x4_set(&value, 1, 2, _12); |  | ||||||
| 	kinc_matrix4x4_set(&value, 1, 3, _13); |  | ||||||
| 	kinc_matrix4x4_set(&value, 2, 0, _20); |  | ||||||
| 	kinc_matrix4x4_set(&value, 2, 1, _21); |  | ||||||
| 	kinc_matrix4x4_set(&value, 2, 2, _22); |  | ||||||
| 	kinc_matrix4x4_set(&value, 2, 3, _23); |  | ||||||
| 	kinc_matrix4x4_set(&value, 3, 0, _30); |  | ||||||
| 	kinc_matrix4x4_set(&value, 3, 1, _31); |  | ||||||
| 	kinc_matrix4x4_set(&value, 3, 2, _32); |  | ||||||
| 	kinc_matrix4x4_set(&value, 3, 3, _33); |  | ||||||
| 	kinc_compute_set_matrix4(*loc, &value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_matrix3(vbyte *location, float _00, float _10, float _20, float _01, float _11, float _21, float _02, float _12, float _22) { |  | ||||||
| 	kinc_compute_constant_location_t *loc = (kinc_compute_constant_location_t *)location; |  | ||||||
| 	kinc_matrix3x3_t value; |  | ||||||
| 	kinc_matrix3x3_set(&value, 0, 0, _00); |  | ||||||
| 	kinc_matrix3x3_set(&value, 0, 1, _01); |  | ||||||
| 	kinc_matrix3x3_set(&value, 0, 2, _02); |  | ||||||
| 	kinc_matrix3x3_set(&value, 1, 0, _10); |  | ||||||
| 	kinc_matrix3x3_set(&value, 1, 1, _11); |  | ||||||
| 	kinc_matrix3x3_set(&value, 1, 2, _12); |  | ||||||
| 	kinc_matrix3x3_set(&value, 2, 0, _20); |  | ||||||
| 	kinc_matrix3x3_set(&value, 2, 1, _21); |  | ||||||
| 	kinc_matrix3x3_set(&value, 2, 2, _22); |  | ||||||
| 	kinc_compute_set_matrix3(*loc, &value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_texture(vbyte *unit, vbyte *texture, int access) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_g4_texture_t *tex = (kinc_g4_texture_t *)texture; |  | ||||||
| 	kinc_compute_set_texture(*u, tex, (kinc_compute_access_t)access); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_target(vbyte *unit, vbyte *renderTarget, int access) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget; |  | ||||||
| 	kinc_compute_set_render_target(*u, rt, (kinc_compute_access_t)access); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_sampled_texture(vbyte *unit, vbyte *texture) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_g4_texture_t *tex = (kinc_g4_texture_t *)texture; |  | ||||||
| 	kinc_compute_set_sampled_texture(*u, tex); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_sampled_target(vbyte *unit, vbyte *renderTarget) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget; |  | ||||||
| 	kinc_compute_set_sampled_render_target(*u, rt); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_sampled_depth_target(vbyte *unit, vbyte *renderTarget) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget; |  | ||||||
| 	kinc_compute_set_sampled_depth_from_render_target(*u, rt); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_sampled_cubemap_texture(vbyte *unit, vbyte *texture) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_g4_texture_t *tex = (kinc_g4_texture_t *)texture; |  | ||||||
| 	kinc_compute_set_sampled_texture(*u, tex); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_sampled_cubemap_target(vbyte *unit, vbyte *renderTarget) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget; |  | ||||||
| 	kinc_compute_set_sampled_render_target(*u, rt); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_sampled_cubemap_depth_target(vbyte *unit, vbyte *renderTarget) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)renderTarget; |  | ||||||
| 	kinc_compute_set_sampled_depth_from_render_target(*u, rt); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_texture_parameters(vbyte *unit, int uAddressing, int vAddressing, int minificationFilter, int magnificationFilter, int mipmapFilter) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_compute_set_texture_addressing(*u, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)uAddressing); |  | ||||||
| 	kinc_compute_set_texture_addressing(*u, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)vAddressing); |  | ||||||
| 	kinc_compute_set_texture_minification_filter(*u, (kinc_g4_texture_filter_t)minificationFilter); |  | ||||||
| 	kinc_compute_set_texture_magnification_filter(*u, (kinc_g4_texture_filter_t)magnificationFilter); |  | ||||||
| 	kinc_compute_set_texture_mipmap_filter(*u, (kinc_g4_mipmap_filter_t)mipmapFilter); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_texture3d_parameters(vbyte *unit, int uAddressing, int vAddressing, int wAddressing, int minificationFilter, int magnificationFilter, |  | ||||||
|                                               int mipmapFilter) { |  | ||||||
| 	kinc_compute_texture_unit_t *u = (kinc_compute_texture_unit_t *)unit; |  | ||||||
| 	kinc_compute_set_texture3d_addressing(*u, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)uAddressing); |  | ||||||
| 	kinc_compute_set_texture3d_addressing(*u, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)vAddressing); |  | ||||||
| 	kinc_compute_set_texture3d_addressing(*u, KINC_G4_TEXTURE_DIRECTION_W, (kinc_g4_texture_addressing_t)wAddressing); |  | ||||||
| 	kinc_compute_set_texture3d_minification_filter(*u, (kinc_g4_texture_filter_t)minificationFilter); |  | ||||||
| 	kinc_compute_set_texture3d_magnification_filter(*u, (kinc_g4_texture_filter_t)magnificationFilter); |  | ||||||
| 	kinc_compute_set_texture3d_mipmap_filter(*u, (kinc_g4_mipmap_filter_t)mipmapFilter); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_set_shader(vbyte *shader) { |  | ||||||
| 	kinc_compute_set_shader((kinc_compute_shader_t *)shader); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void hl_kinc_compute_compute(int x, int y, int z) { |  | ||||||
| 	kinc_compute(x, y, z); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -42,8 +42,8 @@ static void update(void *data) { | |||||||
|  |  | ||||||
| static bool mixThreadregistered = false; | static bool mixThreadregistered = false; | ||||||
|  |  | ||||||
| static void mix(kinc_a2_buffer_t *buffer, int samples) { | static void mix(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) { | ||||||
| #ifdef KORE_MULTITHREADED_AUDIO | #ifdef KINC_MULTITHREADED_AUDIO | ||||||
| 	if (!mixThreadregistered) { | 	if (!mixThreadregistered) { | ||||||
| 		vdynamic *ret; | 		vdynamic *ret; | ||||||
| 		hl_register_thread(&ret); | 		hl_register_thread(&ret); | ||||||
| @ -54,16 +54,18 @@ static void mix(kinc_a2_buffer_t *buffer, int samples) { | |||||||
|  |  | ||||||
| 	audioCallCallback(samples); | 	audioCallCallback(samples); | ||||||
|  |  | ||||||
| 	for (int i = 0; i < samples; ++i) { | 	for (uint32_t i = 0; i < samples; i += 2) { | ||||||
| 		float value = audioReadSample(); | 		float left_value = audioReadSample(); | ||||||
| 		*(float *)&buffer->data[buffer->write_location] = value; | 		float right_value = audioReadSample(); | ||||||
| 		buffer->write_location += 4; | 		*(float *)&buffer->channels[0][buffer->write_location] = left_value; | ||||||
|  | 		*(float *)&buffer->channels[1][buffer->write_location] = right_value; | ||||||
|  | 		buffer->write_location += 1; | ||||||
| 		if (buffer->write_location >= buffer->data_size) { | 		if (buffer->write_location >= buffer->data_size) { | ||||||
| 			buffer->write_location = 0; | 			buffer->write_location = 0; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #ifdef KORE_MULTITHREADED_AUDIO | #ifdef KINC_MULTITHREADED_AUDIO | ||||||
| 	hl_blocking(false); | 	hl_blocking(false); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| @ -92,9 +94,9 @@ void hl_init_kore(vbyte *title, int width, int height, int samplesPerPixel, bool | |||||||
| void hl_kinc_init_audio(vclosure *callCallback, vclosure *readSample, int *outSamplesPerSecond) { | void hl_kinc_init_audio(vclosure *callCallback, vclosure *readSample, int *outSamplesPerSecond) { | ||||||
| 	audioCallCallback = *((FN_AUDIO_CALL_CALLBACK *)(&callCallback->fun)); | 	audioCallCallback = *((FN_AUDIO_CALL_CALLBACK *)(&callCallback->fun)); | ||||||
| 	audioReadSample = *((FN_AUDIO_READ_SAMPLE *)(&readSample->fun)); | 	audioReadSample = *((FN_AUDIO_READ_SAMPLE *)(&readSample->fun)); | ||||||
| 	kinc_a2_set_callback(mix); |  | ||||||
| 	kinc_a2_init(); | 	kinc_a2_init(); | ||||||
| 	*outSamplesPerSecond = kinc_a2_samples_per_second; | 	kinc_a2_set_callback(mix, NULL); | ||||||
|  | 	*outSamplesPerSecond = kinc_a2_samples_per_second(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void hl_run_kore(void) { | void hl_run_kore(void) { | ||||||
|  | |||||||
| @ -94,11 +94,11 @@ void hl_kinc_system_load_url(vbyte *url) { | |||||||
| } | } | ||||||
|  |  | ||||||
| vbyte *hl_kinc_get_gamepad_id(int index) { | vbyte *hl_kinc_get_gamepad_id(int index) { | ||||||
| 	return (vbyte*)kinc_gamepad_product_name(index); | 	return (vbyte *)kinc_gamepad_product_name(index); | ||||||
| } | } | ||||||
|  |  | ||||||
| vbyte *hl_kinc_get_gamepad_vendor(int index) { | vbyte *hl_kinc_get_gamepad_vendor(int index) { | ||||||
| 	return (vbyte*)kinc_gamepad_vendor(index); | 	return (vbyte *)kinc_gamepad_vendor(index); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool hl_kinc_gamepad_connected(int index) { | bool hl_kinc_gamepad_connected(int index) { | ||||||
| @ -137,12 +137,12 @@ void hl_kinc_register_pen(vclosure *penDown, vclosure *penUp, vclosure *penMove) | |||||||
| 	kinc_pen_set_move_callback(*((FN_PEN_MOVE *)(&penMove->fun))); | 	kinc_pen_set_move_callback(*((FN_PEN_MOVE *)(&penMove->fun))); | ||||||
| } | } | ||||||
|  |  | ||||||
| typedef void (*FN_GAMEPAD_AXIS)(int, int, float); | typedef void (*FN_GAMEPAD_AXIS)(int, int, float, void *); | ||||||
| typedef void (*FN_GAMEPAD_BUTTON)(int, int, float); | typedef void (*FN_GAMEPAD_BUTTON)(int, int, float, void *); | ||||||
|  |  | ||||||
| void hl_kinc_register_gamepad(vclosure *gamepadAxis, vclosure *gamepadButton) { | void hl_kinc_register_gamepad(vclosure *gamepadAxis, vclosure *gamepadButton) { | ||||||
| 	kinc_gamepad_set_axis_callback(*((FN_GAMEPAD_AXIS *)(&gamepadAxis->fun))); | 	kinc_gamepad_set_axis_callback(*((FN_GAMEPAD_AXIS *)(&gamepadAxis->fun)), NULL); | ||||||
| 	kinc_gamepad_set_button_callback(*((FN_GAMEPAD_BUTTON *)(&gamepadButton->fun))); | 	kinc_gamepad_set_button_callback(*((FN_GAMEPAD_BUTTON *)(&gamepadButton->fun)), NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
| typedef void (*FN_TOUCH_START)(int, int, int); | typedef void (*FN_TOUCH_START)(int, int, int); | ||||||
|  | |||||||
| @ -80,6 +80,7 @@ extern class Krom { | |||||||
| 	static function unloadImage(image: kha.Image): Void; | 	static function unloadImage(image: kha.Image): Void; | ||||||
| 	static function loadSound(file: String): Dynamic; | 	static function loadSound(file: String): Dynamic; | ||||||
| 	static function writeAudioBuffer(buffer: js.lib.ArrayBuffer, samples: Int): Void; | 	static function writeAudioBuffer(buffer: js.lib.ArrayBuffer, samples: Int): Void; | ||||||
|  | 	static function getSamplesPerSecond(): Int; | ||||||
| 	static function loadBlob(file: String): js.lib.ArrayBuffer; | 	static function loadBlob(file: String): js.lib.ArrayBuffer; | ||||||
|  |  | ||||||
| 	static function init(title: String, width: Int, height: Int, samplesPerPixel: Int, vSync: Bool, windowMode: Int, windowFeatures: Int, kromApi: Int): Void; | 	static function init(title: String, width: Int, height: Int, samplesPerPixel: Int, vSync: Bool, windowMode: Int, windowFeatures: Int, kromApi: Int): Void; | ||||||
| @ -115,6 +116,7 @@ extern class Krom { | |||||||
| 	static function screenDpi(): Int; | 	static function screenDpi(): Int; | ||||||
| 	static function systemId(): String; | 	static function systemId(): String; | ||||||
| 	static function requestShutdown(): Void; | 	static function requestShutdown(): Void; | ||||||
|  | 	static function displayFrequency(): Int; | ||||||
| 	static function displayCount(): Int; | 	static function displayCount(): Int; | ||||||
| 	static function displayWidth(index: Int): Int; | 	static function displayWidth(index: Int): Int; | ||||||
| 	static function displayHeight(index: Int): Int; | 	static function displayHeight(index: Int): Int; | ||||||
|  | |||||||
| @ -79,7 +79,7 @@ class Display { | |||||||
| 	public var frequency(get, never): Int; | 	public var frequency(get, never): Int; | ||||||
|  |  | ||||||
| 	function get_frequency(): Int { | 	function get_frequency(): Int { | ||||||
| 		return 60; | 		return Krom.displayFrequency(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public var pixelsPerInch(get, never): Int; | 	public var pixelsPerInch(get, never): Int; | ||||||
|  | |||||||
| @ -171,8 +171,9 @@ class SystemImpl { | |||||||
| 		Krom.setGamepadAxisCallback(gamepadAxisCallback); | 		Krom.setGamepadAxisCallback(gamepadAxisCallback); | ||||||
| 		Krom.setGamepadButtonCallback(gamepadButtonCallback); | 		Krom.setGamepadButtonCallback(gamepadButtonCallback); | ||||||
|  |  | ||||||
| 		kha.audio2.Audio._init(); | 		kha.audio2.Audio.samplesPerSecond = Krom.getSamplesPerSecond(); | ||||||
| 		kha.audio1.Audio._init(); | 		kha.audio1.Audio._init(); | ||||||
|  | 		kha.audio2.Audio._init(); | ||||||
| 		Krom.setAudioCallback(audioCallback); | 		Krom.setAudioCallback(audioCallback); | ||||||
|  |  | ||||||
| 		Scheduler.start(); | 		Scheduler.start(); | ||||||
| @ -207,7 +208,7 @@ class SystemImpl { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static function getRefreshRate(): Int { | 	public static function getRefreshRate(): Int { | ||||||
| 		return 60; | 		return Krom.displayFrequency(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static function getSystemId(): String { | 	public static function getSystemId(): String { | ||||||
|  | |||||||
| @ -10,8 +10,7 @@ class Audio { | |||||||
|  |  | ||||||
| 	public static function _init() { | 	public static function _init() { | ||||||
| 		var bufferSize = 1024 * 2; | 		var bufferSize = 1024 * 2; | ||||||
| 		buffer = new Buffer(bufferSize * 4, 2, 44100); | 		buffer = new Buffer(bufferSize * 4, 2, samplesPerSecond); | ||||||
| 		Audio.samplesPerSecond = 44100; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static function _callCallback(samples: Int): Void { | 	public static function _callCallback(samples: Int): Void { | ||||||
| @ -32,11 +31,11 @@ class Audio { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static function _readSample(): Float { | 	public static function _readSample(): FastFloat { | ||||||
| 		if (buffer == null) | 		if (buffer == null) | ||||||
| 			return 0; | 			return 0; | ||||||
| 		var value = buffer.data.get(buffer.readLocation); | 		var value = buffer.data.get(buffer.readLocation); | ||||||
| 		buffer.readLocation += 1; | 		++buffer.readLocation; | ||||||
| 		if (buffer.readLocation >= buffer.size) { | 		if (buffer.readLocation >= buffer.size) { | ||||||
| 			buffer.readLocation = 0; | 			buffer.readLocation = 0; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -59,7 +59,7 @@ class Graphics implements kha.graphics4.Graphics { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public function refreshRate(): Int { | 	public function refreshRate(): Int { | ||||||
| 		return 60; | 		return Krom.displayFrequency(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public function clear(?color: Color, ?depth: Float, ?stencil: Int): Void { | 	public function clear(?color: Color, ?depth: Float, ?stencil: Int): Void { | ||||||
|  | |||||||
| @ -34,22 +34,46 @@ void copySample(void *buffer) { | |||||||
| } | } | ||||||
|  |  | ||||||
| int playback_callback(snd_pcm_sframes_t nframes) { | int playback_callback(snd_pcm_sframes_t nframes) { | ||||||
| 	int err = 0; |     int err = 0;  | ||||||
| 	if (kinc_a2_internal_callback(&a2_buffer, nframes)) { |     if (kinc_a2_internal_callback(&a2_buffer, nframes)) { | ||||||
| 		int ni = 0; |         int ni = 0; | ||||||
| 		while (ni < nframes) { |         while (ni < nframes) { | ||||||
| 			int i = 0; |             int i = 0; | ||||||
| 			for (; ni < nframes && i < 4096 * 2; ++i, ++ni) { |             for (; ni < nframes && i < 4096; ++i, ++ni) { | ||||||
| 				copySample(&buf[i * 2]); |                 copySample(&buf[i * 2]); | ||||||
| 			} |             } | ||||||
| 			int err2; |             int err2 = snd_pcm_writei(playback_handle, buf, i); | ||||||
| 			if ((err2 = snd_pcm_writei(playback_handle, buf, i)) < 0) { |             if (err2 < 0) { | ||||||
| 				fprintf(stderr, "write failed (%s)\n", snd_strerror(err2)); |                 fprintf(stderr, "ALSA write failed in playback_callback: %s\n", snd_strerror(err2)); | ||||||
| 			} |                 return err2; | ||||||
| 			err += err2; |             } | ||||||
| 		} |             if (err2 < i) { | ||||||
| 	} |                 fprintf(stderr, "ALSA short write in playback_callback: wrote %d of %d frames\n", err2, i); | ||||||
| 	return err; |             } | ||||||
|  |         } | ||||||
|  |         err = nframes; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         // Write silence data to prevent recovery | ||||||
|  |         if (nframes > 4096) { | ||||||
|  |              fprintf(stderr, "Warning: ALSA requested %ld frames for silence, exceeding local buffer size %d. Clamping.\n", nframes, 4096); | ||||||
|  |              nframes = 4096;  | ||||||
|  |         } | ||||||
|  |         memset(buf, 0, nframes * 4); | ||||||
|  |  | ||||||
|  |         int err2 = snd_pcm_writei(playback_handle, buf, nframes); | ||||||
|  |  | ||||||
|  |         if (err2 < 0) { | ||||||
|  |             fprintf(stderr, "ALSA silence write failed in playback_callback: %s\n", snd_strerror(err2)); | ||||||
|  |             err = err2; | ||||||
|  |         } else { | ||||||
|  |             if (err2 < nframes) { | ||||||
|  |                 fprintf(stderr, "ALSA short silence write in playback_callback: wrote %d of %d frames\n", err2, (int)nframes); | ||||||
|  |             } | ||||||
|  |             err = err2; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool tryToRecover(snd_pcm_t *handle, int errorCode) { | bool tryToRecover(snd_pcm_t *handle, int errorCode) { | ||||||
|  | |||||||
| Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB | 
| Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB | 
| Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB | 
| Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB | 
| Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB | 
| Before Width: | Height: | Size: 417 KiB After Width: | Height: | Size: 281 KiB | 
| @ -51,7 +51,7 @@ class Scheduler { | |||||||
| 	static var vsync: Bool; | 	static var vsync: Bool; | ||||||
|  |  | ||||||
| 	// Html5 target can update display frequency after some delay | 	// Html5 target can update display frequency after some delay | ||||||
| 	#if kha_html5 | 	#if (kha_html5 || kha_debug_html5) | ||||||
| 	static var onedifhz(get, never): Float; | 	static var onedifhz(get, never): Float; | ||||||
|  |  | ||||||
| 	static inline function get_onedifhz(): Float { | 	static inline function get_onedifhz(): Float { | ||||||
| @ -97,7 +97,7 @@ class Scheduler { | |||||||
|  |  | ||||||
| 	public static function start(restartTimers: Bool = false): Void { | 	public static function start(restartTimers: Bool = false): Void { | ||||||
| 		vsync = Window.get(0).vSynced; | 		vsync = Window.get(0).vSynced; | ||||||
| 		#if !kha_html5 | 		#if !(kha_html5 || kha_debug_html5) | ||||||
| 		var hz = Display.primary != null ? Display.primary.frequency : 60; | 		var hz = Display.primary != null ? Display.primary.frequency : 60; | ||||||
| 		if (hz >= 57 && hz <= 63) | 		if (hz >= 57 && hz <= 63) | ||||||
| 			hz = 60; | 			hz = 60; | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								Krom/Krom.exe
									
									
									
									
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Krom/Krom_opengl.exe
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -310,9 +310,9 @@ class LeenkxAddonPreferences(AddonPreferences): | |||||||
|         layout.label(text="Welcome to Leenkx!") |         layout.label(text="Welcome to Leenkx!") | ||||||
|  |  | ||||||
|         # Compare version Blender and Leenkx (major, minor) |         # Compare version Blender and Leenkx (major, minor) | ||||||
|         if bpy.app.version[0] != 4 or bpy.app.version[1] != 2: |         if bpy.app.version[:2] not in [(4, 4), (4, 2), (3, 6), (3, 3)]: | ||||||
|             box = layout.box().column() |             box = layout.box().column() | ||||||
|             box.label(text="Warning: For Leenkx to work correctly, use a Blender LTS version such as 4.2 | 3.6 | 3.3") |             box.label(text="Warning: For Leenkx to work correctly, use a Blender LTS version") | ||||||
|  |  | ||||||
|         layout.prop(self, "sdk_path") |         layout.prop(self, "sdk_path") | ||||||
|         sdk_path = get_sdk_path(context) |         sdk_path = get_sdk_path(context) | ||||||
| @ -914,7 +914,10 @@ def restart_leenkx(context): | |||||||
|  |  | ||||||
| @persistent | @persistent | ||||||
| def on_load_post(context): | def on_load_post(context): | ||||||
|     restart_leenkx(bpy.context)  # context is None, use bpy.context instead |     if bpy.context is not None: | ||||||
|  |         restart_leenkx(bpy.context)  # context is None, use bpy.context instead | ||||||
|  |     else: | ||||||
|  |         bpy.app.timers.register(lambda: restart_leenkx(bpy.context), first_interval=0.1) | ||||||
|  |  | ||||||
|  |  | ||||||
| def on_register_post(): | def on_register_post(): | ||||||
|  | |||||||
| @ -475,7 +475,11 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5); | |||||||
| 			} else { | 			} else { | ||||||
| 				fragColor.rgb = mix(midLumColor, maxLumColor, luminance); | 				fragColor.rgb = mix(midLumColor, maxLumColor, luminance); | ||||||
| 			} | 			} | ||||||
|  | 		} else if (PPComp4.x == 9){ | ||||||
|  | 			fragColor.rgb = tonemapAgXSimple(fragColor.rgb); | ||||||
|  | 			fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma | ||||||
|  | 		} else if (PPComp4.x == 10){ | ||||||
|  | 			fragColor.rgb = tonemapAgXFull(fragColor.rgb); | ||||||
| 		} else { | 		} else { | ||||||
| 			fragColor.rgb = vec3(0,1,0); //ERROR | 			fragColor.rgb = vec3(0,1,0); //ERROR | ||||||
| 		} | 		} | ||||||
| @ -498,6 +502,13 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5); | |||||||
| 		fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma | 		fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma | ||||||
| 		fragColor.rgb = clamp(fragColor.rgb, 0.0, 2.2); | 		fragColor.rgb = clamp(fragColor.rgb, 0.0, 2.2); | ||||||
| 	#endif | 	#endif | ||||||
|  | 	#ifdef _CToneAgXSimple | ||||||
|  | 		fragColor.rgb = tonemapAgXSimple(fragColor.rgb); | ||||||
|  | 		fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma | ||||||
|  | 	#endif | ||||||
|  | 	#ifdef _CToneAgXFull | ||||||
|  | 		fragColor.rgb = tonemapAgXFull(fragColor.rgb); | ||||||
|  | 	#endif | ||||||
| 	#ifdef _CToneNone | 	#ifdef _CToneNone | ||||||
| 		fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma | 		fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma | ||||||
| 	#endif | 	#endif | ||||||
| @ -614,4 +625,37 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5); | |||||||
| #ifdef _CLUT | #ifdef _CLUT | ||||||
| 	fragColor = LUTlookup(fragColor, lutTexture); | 	fragColor = LUTlookup(fragColor, lutTexture); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifdef _CDitheringBlueNoise | ||||||
|  | 	const float ditherStrength = ditherStrengthValue / 255.0; | ||||||
|  | 	float noise = ditherBlueNoiseStyle(gl_FragCoord.xy); | ||||||
|  | 	float noiseOffset = (noise - 0.5) * ditherStrength; | ||||||
|  | 	fragColor.rgb += noiseOffset; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _CDitheringWhiteNoise | ||||||
|  | 	const float ditherStrength = ditherStrengthValue / 255.0; | ||||||
|  | 	float noise = ditherWhiteNoise(gl_FragCoord.xy); | ||||||
|  | 	float noiseOffset = (noise - 0.5) * ditherStrength; | ||||||
|  | 	fragColor.rgb += noiseOffset; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _CDitheringOrderedBayer4x4 | ||||||
|  | 	const float ditherStrength = ditherStrengthValue / 255.0; | ||||||
|  | 	float noise = ditherOrderedBayer4x4(ivec2(gl_FragCoord.xy)); | ||||||
|  | 	float noiseOffset = (noise - 0.5) * ditherStrength; | ||||||
|  | 	fragColor.rgb += noiseOffset; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef _CDitheringOrderedBayer8x8 | ||||||
|  | 	const float ditherStrength = ditherStrengthValue / 255.0; | ||||||
|  | 	float noise = ditherOrderedBayer8x8(ivec2(gl_FragCoord.xy)); | ||||||
|  | 	float noiseOffset = (noise - 0.5) * ditherStrength; | ||||||
|  | 	fragColor.rgb += noiseOffset; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	//fragColor.rgb = clamp(fragColor.rgb, 0.0, 1.0); | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ uniform sampler2D gbuffer0; | |||||||
| uniform sampler2D gbuffer1; | uniform sampler2D gbuffer1; | ||||||
|  |  | ||||||
| #ifdef _gbuffer2 | #ifdef _gbuffer2 | ||||||
| 	uniform sampler2D gbuffer2; | 	//!uniform sampler2D gbuffer2; | ||||||
| #endif | #endif | ||||||
| #ifdef _EmissionShaded | #ifdef _EmissionShaded | ||||||
| 	uniform sampler2D gbufferEmission; | 	uniform sampler2D gbufferEmission; | ||||||
| @ -286,7 +286,7 @@ void main() { | |||||||
|  |  | ||||||
| #ifdef _VoxelGI | #ifdef _VoxelGI | ||||||
| 	vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0); | 	vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0); | ||||||
| 	fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff; | 	fragColor.rgb = (indirect_diffuse.rgb + envl.rgb * (1.0 - indirect_diffuse.a)) * albedo * voxelgiDiff; | ||||||
| 	if(roughness < 1.0 && occspec.y > 0.0) | 	if(roughness < 1.0 && occspec.y > 0.0) | ||||||
| 		fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; | 		fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; | ||||||
| #endif | #endif | ||||||
| @ -380,7 +380,7 @@ void main() { | |||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	#ifdef _VoxelShadow | 	#ifdef _VoxelShadow | ||||||
| 	svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; | 	svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad; | ||||||
| 	#endif | 	#endif | ||||||
| 	 | 	 | ||||||
| 	#ifdef _SSRS | 	#ifdef _SSRS | ||||||
|  | |||||||
| @ -92,7 +92,7 @@ void main() { | |||||||
|  |  | ||||||
| 	vec3 viewNormal = V3 * n; | 	vec3 viewNormal = V3 * n; | ||||||
| 	vec3 viewPos = getPosView(viewRay, d, cameraProj); | 	vec3 viewPos = getPosView(viewRay, d, cameraProj); | ||||||
| 	vec3 reflected = reflect(viewPos, viewNormal); | 	vec3 reflected = reflect(normalize(viewPos), viewNormal); | ||||||
| 	hitCoord = viewPos; | 	hitCoord = viewPos; | ||||||
|  |  | ||||||
| 	#ifdef _CPostprocess | 	#ifdef _CPostprocess | ||||||
|  | |||||||
| @ -57,14 +57,17 @@ vec4 binarySearch(vec3 dir) { | |||||||
| } | } | ||||||
|  |  | ||||||
| vec4 rayCast(vec3 dir) { | vec4 rayCast(vec3 dir) { | ||||||
| 	float ddepth; |     float ddepth; | ||||||
| 	dir *= ss_refractionRayStep; |     dir *= ss_refractionRayStep; | ||||||
| 	for (int i = 0; i < maxSteps; i++) { |     for (int i = 0; i < maxSteps; i++) { | ||||||
| 		hitCoord += dir; |         hitCoord += dir; | ||||||
| 		ddepth = getDeltaDepth(hitCoord); |         ddepth = getDeltaDepth(hitCoord); | ||||||
| 		if (ddepth > 0.0) return binarySearch(dir); |         if (ddepth > 0.0) | ||||||
| 	} |             return binarySearch(dir); | ||||||
| 	return vec4(texCoord, 0.0, 1.0); |     } | ||||||
|  |     // No hit — fallback to projecting the ray to UV space | ||||||
|  |     vec2 fallbackUV = getProjectedCoord(hitCoord); | ||||||
|  |     return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback | ||||||
| } | } | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
| @ -74,7 +77,7 @@ void main() { | |||||||
|     float ior = gr.x; |     float ior = gr.x; | ||||||
|     float opac = gr.y; |     float opac = gr.y; | ||||||
|     float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; |     float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; | ||||||
|     if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { |     if (d == 0.0 || opac == 1.0 || ior == 1.0) { | ||||||
|         fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; |         fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @ -86,7 +89,7 @@ void main() { | |||||||
|  |  | ||||||
|     vec3 viewNormal = V3 * n; |     vec3 viewNormal = V3 * n; | ||||||
|     vec3 viewPos = getPosView(viewRay, d, cameraProj); |     vec3 viewPos = getPosView(viewRay, d, cameraProj); | ||||||
|     vec3 refracted = refract(viewPos, viewNormal, 1.0 / ior); |     vec3 refracted = refract(normalize(viewPos), viewNormal, 1.0 / ior); | ||||||
|     hitCoord = viewPos; |     hitCoord = viewPos; | ||||||
|  |  | ||||||
|     vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0; |     vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0; | ||||||
|  | |||||||
| @ -166,7 +166,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, | |||||||
| } | } | ||||||
|  |  | ||||||
| vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { | vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { | ||||||
| 	vec3 specularDir = reflect(-viewDir, normal); | 	vec3 specularDir = reflect(normalize(-viewDir), normal); | ||||||
| 	vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; | 	vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; | ||||||
| 	vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); | 	vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); | ||||||
|  |  | ||||||
| @ -176,9 +176,9 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, | |||||||
| 	return amount * voxelgiOcc; | 	return amount * voxelgiOcc; | ||||||
| } | } | ||||||
|  |  | ||||||
| vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { | vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) { | ||||||
|  	const float transmittance = 1.0; |  	const float transmittance = 1.0 - opacity; | ||||||
|  	vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); |  	vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior); | ||||||
|  	vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; |  	vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; | ||||||
| 	vec4 amount =  transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); | 	vec4 amount =  transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); | ||||||
|  |  | ||||||
| @ -328,8 +328,8 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) { | float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { | ||||||
|  	vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep; |  	vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; | ||||||
| 	float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); | 	float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); | ||||||
| 	amount = clamp(amount, 0.0, 1.0); | 	amount = clamp(amount, 0.0, 1.0); | ||||||
| 	return amount * voxelgiOcc; | 	return amount * voxelgiOcc; | ||||||
|  | |||||||
| @ -9,7 +9,9 @@ | |||||||
| #endif | #endif | ||||||
| #ifdef _VoxelShadow | #ifdef _VoxelShadow | ||||||
| #include "std/conetrace.glsl" | #include "std/conetrace.glsl" | ||||||
| //!uniform sampler2D voxels_shadows; | #endif | ||||||
|  | #ifdef _gbuffer2 | ||||||
|  | uniform sampler2D gbuffer2; | ||||||
| #endif | #endif | ||||||
| #ifdef _LTC | #ifdef _LTC | ||||||
| #include "std/ltc.glsl" | #include "std/ltc.glsl" | ||||||
| @ -146,7 +148,8 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co | |||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	#ifdef _VoxelShadow | 	#ifdef _VoxelShadow | ||||||
| 	direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; | 	vec4 g2 = textureLod(gbuffer2, gl_FragCoord.xy, 0.0); | ||||||
|  | 	direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad; | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	#ifdef _LTC | 	#ifdef _LTC | ||||||
|  | |||||||
| @ -1,4 +1,3 @@ | |||||||
|  |  | ||||||
| vec3 uncharted2Tonemap(const vec3 x) { | vec3 uncharted2Tonemap(const vec3 x) { | ||||||
| 	const float A = 0.15; | 	const float A = 0.15; | ||||||
| 	const float B = 0.50; | 	const float B = 0.50; | ||||||
| @ -36,3 +35,106 @@ vec3 acesFilm(const vec3 x) { | |||||||
| vec3 tonemapReinhard(const vec3 color) { | vec3 tonemapReinhard(const vec3 color) { | ||||||
| 	return color / (color + vec3(1.0)); | 	return color / (color + vec3(1.0)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Blender AgX Implementation  | ||||||
|  | // Troy Sobotka https://github.com/sobotka/AgX | ||||||
|  |  | ||||||
|  | // AGX Simple | ||||||
|  | vec3 tonemapAgXSimple(vec3 x) { | ||||||
|  | 	// TODO CORRECT AND OPTIMIZE | ||||||
|  |     x = max(x, vec3(0.0)); | ||||||
|  |     float exposure = 0.6; | ||||||
|  |     x *= exposure; | ||||||
|  |     const vec3 AgX_A = vec3(0.92, 0.92, 0.72); | ||||||
|  |     const vec3 AgX_B = vec3(0.24, 0.24, 0.36); | ||||||
|  |     const vec3 AgX_C = vec3(0.92, 0.92, 0.72); | ||||||
|  |     const vec3 AgX_D = vec3(0.24, 0.24, 0.36); | ||||||
|  |     const vec3 AgX_E = vec3(0.08, 0.08, 0.12); | ||||||
|  |     const vec3 AgX_F = vec3(0.0); | ||||||
|  |     vec3 result = (x * (AgX_A * x + AgX_B)) / (x * (AgX_C * x + AgX_D) + AgX_E) + AgX_F; | ||||||
|  |     float luma = dot(result, vec3(0.2126, 0.7152, 0.0722)); | ||||||
|  |     result = mix(vec3(luma), result, 0.6); | ||||||
|  |     return clamp(result, vec3(0.0), vec3(1.0)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // AGX Full Contrast Approx | ||||||
|  | vec3 agxDefaultContrastApprox(vec3 x) { | ||||||
|  |     vec3 x2 = x * x; | ||||||
|  |     vec3 x4 = x2 * x2; | ||||||
|  |     return + 15.5     * x4 * x2 | ||||||
|  |            - 40.14    * x4 * x | ||||||
|  |            + 31.96    * x4 | ||||||
|  |            - 6.868    * x2 * x | ||||||
|  |            + 0.4298   * x2 | ||||||
|  |            + 0.1191   * x | ||||||
|  |            - 0.00232; | ||||||
|  | } | ||||||
|  | // AGX Full Look | ||||||
|  | vec3 agxLook(vec3 x, float strength) { | ||||||
|  |     const vec3 slope = vec3(1.0); | ||||||
|  |     const vec3 power = vec3(1.35); | ||||||
|  |     const vec3 sat = vec3(1.4); | ||||||
|  |     vec3 lw = vec3(0.2126, 0.7152, 0.0722); | ||||||
|  |     float luma = dot(x, lw); | ||||||
|  |     return pow(x * slope, power) * sat - (pow(luma * slope, power) * (sat - 1.0)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // AGX Full | ||||||
|  | vec3 tonemapAgXFull(vec3 x) { | ||||||
|  |     // x *= 2.0 * (1.0/0.8); // Brightness scale to match Blender's default | ||||||
|  |     x = clamp(x, 0.0, 65504.0); | ||||||
|  |     x = log2(x + 1.0); | ||||||
|  |     x = agxDefaultContrastApprox(clamp(x * 0.5 - 10.5, -12.0, 12.0));     | ||||||
|  |     x = mix(x, agxLook(x, 0.5), 0.5); | ||||||
|  |     x = clamp(x, 0.0, 1.0); | ||||||
|  |     return pow(x, vec3(1.0/2.2));  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Interleaved Gradient Noise (Pseudo-random, AKA Blue Noise style) | ||||||
|  | // Based on http://momentsingraphics.de/BlueNoise.html | ||||||
|  | float ditherBlueNoiseStyle(vec2 p) { | ||||||
|  |     return fract(sin(dot(p.xy, vec2(12.9898, 78.233))) * 43758.5453123); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // White Noise Dithering | ||||||
|  | float ditherWhiteNoise(vec2 p) { | ||||||
|  |     return fract(sin(dot(p, vec2(12.9898, 4.1414))) * 43758.5453); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Ordered Dithering (4x4 Bayer Matrix) | ||||||
|  | float ditherOrderedBayer4x4(ivec2 p) { | ||||||
|  |     const float bayer[16] = float[16]( | ||||||
|  |          0.0,  8.0,  2.0, 10.0, | ||||||
|  |         12.0,  4.0, 14.0,  6.0, | ||||||
|  |          3.0, 11.0,  1.0,  9.0, | ||||||
|  |         15.0,  7.0, 13.0,  5.0 | ||||||
|  |     ); | ||||||
|  |     int index = (p.x % 4) * 4 + (p.y % 4); | ||||||
|  |     return bayer[index] / 16.0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Ordered Dithering (8x8 Bayer Matrix) | ||||||
|  | float ditherOrderedBayer8x8(ivec2 p) { | ||||||
|  |     const float bayer8x8[64] = float[64]( | ||||||
|  |          0.0, 32.0,  8.0, 40.0,  2.0, 34.0, 10.0, 42.0, | ||||||
|  |         48.0, 16.0, 56.0, 24.0, 50.0, 18.0, 58.0, 26.0, | ||||||
|  |         12.0, 44.0,  4.0, 36.0, 14.0, 46.0,  6.0, 38.0, | ||||||
|  |         60.0, 28.0, 52.0, 20.0, 62.0, 30.0, 54.0, 22.0, | ||||||
|  |          3.0, 35.0, 11.0, 43.0,  1.0, 33.0,  9.0, 41.0, | ||||||
|  |         51.0, 19.0, 59.0, 27.0, 49.0, 17.0, 57.0, 25.0, | ||||||
|  |         15.0, 47.0,  7.0, 39.0, 13.0, 45.0,  5.0, 37.0, | ||||||
|  |         63.0, 31.0, 55.0, 23.0, 61.0, 29.0, 53.0, 21.0 | ||||||
|  |     ); | ||||||
|  |     int index = (p.x % 8) * 8 + (p.y % 8); | ||||||
|  |     return bayer8x8[index] / 64.0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //vec3 applyDither(vec3 color, vec2 screenCoord) { | ||||||
|  | //    float quantizationLevels = 255.0; | ||||||
|  | //    float noise = randomDither(screenCoord); | ||||||
|  | //    float noiseOffset = (noise - 0.5) / quantizationLevels; | ||||||
|  | //    vec3 ditheredColor = color + noiseOffset; | ||||||
|  | //    return clamp(ditheredColor, 0.0, 1.0); | ||||||
|  | //} | ||||||
|  | |||||||
| @ -33,6 +33,7 @@ uniform layout(r32ui) uimage3D voxelsLight; | |||||||
|  |  | ||||||
| #ifdef _ShadowMap | #ifdef _ShadowMap | ||||||
| uniform sampler2DShadow shadowMap; | uniform sampler2DShadow shadowMap; | ||||||
|  | uniform sampler2D shadowMapTransparent; | ||||||
| uniform sampler2DShadow shadowMapSpot; | uniform sampler2DShadow shadowMapSpot; | ||||||
| #ifdef _ShadowMapAtlas | #ifdef _ShadowMapAtlas | ||||||
| uniform sampler2DShadow shadowMapPoint; | uniform sampler2DShadow shadowMapPoint; | ||||||
| @ -86,53 +87,51 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { | |||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
| 	int res = voxelgiResolution.x; | 	int res = voxelgiResolution.x; | ||||||
|  | 	for (int i = 0; i < 6; i++) { | ||||||
|  | 		ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); | ||||||
|  | 		vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; | ||||||
|  | 		P = P * 2.0 - 1.0; | ||||||
|  |  | ||||||
| 	ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); | 		float visibility; | ||||||
| 	dst.y += clipmapLevel * res; | 		vec3 lp = lightPos - P; | ||||||
|  | 		vec3 l; | ||||||
| 	vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; | 		if (lightType == 0) { l = lightDir; visibility = 1.0; } | ||||||
| 	P = P * 2.0 - 1.0; | 		else { l = normalize(lp); visibility = attenuate(distance(P, lightPos)); } | ||||||
| 	P *= clipmaps[int(clipmapLevel * 10)]; |  | ||||||
| 	P *= voxelgiResolution; |  | ||||||
| 	P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]); |  | ||||||
|  |  | ||||||
| 	vec3 visibility; |  | ||||||
| 	vec3 lp = lightPos - P; |  | ||||||
| 	vec3 l; |  | ||||||
| 	if (lightType == 0) { l = lightDir; visibility = vec3(1.0); } |  | ||||||
| 	else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); } |  | ||||||
|  |  | ||||||
| #ifdef _ShadowMap | #ifdef _ShadowMap | ||||||
| 	if (lightShadow == 1) { | 		if (lightShadow == 1) { | ||||||
| 		vec4 lightPosition = LVP * vec4(P, 1.0); | 			vec4 lightPosition = LVP * vec4(P, 1.0); | ||||||
| 		vec3 lPos = lightPosition.xyz / lightPosition.w; | 			vec3 lPos = lightPosition.xyz / lightPosition.w; | ||||||
| 		visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr; | 			visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; | ||||||
| 	} | 		} | ||||||
| 	else if (lightShadow == 2) { | 		else if (lightShadow == 2) { | ||||||
| 		vec4 lightPosition = LVP * vec4(P, 1.0); | 			vec4 lightPosition = LVP * vec4(P, 1.0); | ||||||
| 		vec3 lPos = lightPosition.xyz / lightPosition.w; | 			vec3 lPos = lightPosition.xyz / lightPosition.w; | ||||||
| 		visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; | 			visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; | ||||||
| 	} | 		} | ||||||
| 	else if (lightShadow == 3) { | 		else if (lightShadow == 3) { | ||||||
| 		#ifdef _ShadowMapAtlas | 			#ifdef _ShadowMapAtlas | ||||||
| 		int faceIndex = 0; | 			int faceIndex = 0; | ||||||
| 		const int lightIndex = index * 6; | 			const int lightIndex = index * 6; | ||||||
| 		const vec2 uv = sampleCube(-l, faceIndex); | 			const vec2 uv = sampleCube(-l, faceIndex); | ||||||
| 		vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas | 			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; | 			vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; | ||||||
| 		#ifdef _FlipY | 			#ifdef _FlipY | ||||||
| 		uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system | 			uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system | ||||||
| 		#endif | 			#endif | ||||||
| 		visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; | 			visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; | ||||||
| 		#else | 			#else | ||||||
| 		visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; | 			visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; | ||||||
| 		#endif | 			#endif | ||||||
| 	} | 		} | ||||||
| #endif | 	#endif | ||||||
|  | 		vec3 uvw_light = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution); | ||||||
|  | 		uvw_light = (uvw_light * 0.5 + 0.5); | ||||||
|  | 		if (any(notEqual(uvw_light, clamp(uvw_light, 0.0, 1.0)))) return; | ||||||
|  | 		vec3 writecoords_light = floor(uvw_light * voxelgiResolution); | ||||||
|  |  | ||||||
| 	vec3 light = visibility * lightColor; | 		imageAtomicMax(voxelsLight, ivec3(writecoords_light), uint(visibility * lightColor.r * 255)); | ||||||
|  | 		imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255)); | ||||||
| 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), uint(light.r * 255)); | 		imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255)); | ||||||
| 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(light.g * 255)); | 	} | ||||||
| 	imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(light.b * 255)); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; | |||||||
| uniform sampler3D voxels; | uniform sampler3D voxels; | ||||||
| uniform sampler2D gbufferD; | uniform sampler2D gbufferD; | ||||||
| uniform sampler2D gbuffer0; | uniform sampler2D gbuffer0; | ||||||
| uniform layout(r8) image2D voxels_ao; | uniform layout(r16) image2D voxels_ao; | ||||||
|  |  | ||||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||||
| uniform mat4 InvVP; | uniform mat4 InvVP; | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; | |||||||
| uniform sampler3D voxels; | uniform sampler3D voxels; | ||||||
| uniform sampler2D gbufferD; | uniform sampler2D gbufferD; | ||||||
| uniform sampler2D gbuffer0; | uniform sampler2D gbuffer0; | ||||||
| uniform layout(rgba8) image2D voxels_diffuse; | uniform layout(rgba16) image2D voxels_diffuse; | ||||||
|  |  | ||||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||||
| uniform mat4 InvVP; | uniform mat4 InvVP; | ||||||
| @ -46,7 +46,7 @@ void main() { | |||||||
| 	const vec2 pixel = gl_GlobalInvocationID.xy; | 	const vec2 pixel = gl_GlobalInvocationID.xy; | ||||||
| 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | ||||||
| 	#ifdef _InvY | 	#ifdef _InvY | ||||||
| 	uv.y = 1.0 - uv.y | 	uv.y = 1.0 - uv.y; | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; | 	float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ uniform sampler2D gbufferD; | |||||||
| uniform sampler2D gbuffer0; | uniform sampler2D gbuffer0; | ||||||
| uniform sampler3D voxels; | uniform sampler3D voxels; | ||||||
| uniform sampler3D voxelsSDF; | uniform sampler3D voxelsSDF; | ||||||
| uniform layout(rgba8) image2D voxels_specular; | uniform layout(rgba16) image2D voxels_specular; | ||||||
|  |  | ||||||
| uniform float clipmaps[voxelgiClipmapCount * 10]; | uniform float clipmaps[voxelgiClipmapCount * 10]; | ||||||
| uniform mat4 InvVP; | uniform mat4 InvVP; | ||||||
| @ -48,7 +48,7 @@ void main() { | |||||||
| 	const vec2 pixel = gl_GlobalInvocationID.xy; | 	const vec2 pixel = gl_GlobalInvocationID.xy; | ||||||
| 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | 	vec2 uv = (pixel + 0.5) / postprocess_resolution; | ||||||
| 	#ifdef _InvY | 	#ifdef _InvY | ||||||
| 	uv.y = 1.0 - uv.y | 	uv.y = 1.0 - uv.y; | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; | 	float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; | ||||||
| @ -71,7 +71,7 @@ void main() { | |||||||
|  |  | ||||||
| 	vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; | 	vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; | ||||||
|  |  | ||||||
| 	vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z, clipmaps, pixel, velocity).rgb; | 	vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb; | ||||||
|  |  | ||||||
| 	imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); | 	imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,8 +23,8 @@ THE SOFTWARE. | |||||||
|  |  | ||||||
| #include "compiled.inc" | #include "compiled.inc" | ||||||
|  |  | ||||||
| uniform layout(r16) image3D input_sdf; | uniform layout(r8) image3D input_sdf; | ||||||
| uniform layout(r16) image3D output_sdf; | uniform layout(r8) image3D output_sdf; | ||||||
|  |  | ||||||
| uniform float jump_size; | uniform float jump_size; | ||||||
| uniform int clipmapLevel; | uniform int clipmapLevel; | ||||||
|  | |||||||
| @ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels; | |||||||
| uniform layout(r32ui) uimage3D voxelsLight; | uniform layout(r32ui) uimage3D voxelsLight; | ||||||
| uniform layout(rgba8) image3D voxelsB; | uniform layout(rgba8) image3D voxelsB; | ||||||
| uniform layout(rgba8) image3D voxelsOut; | uniform layout(rgba8) image3D voxelsOut; | ||||||
| uniform layout(r16) image3D SDF; | uniform layout(r8) image3D SDF; | ||||||
| #else | #else | ||||||
| #ifdef _VoxelAOvar | #ifdef _VoxelAOvar | ||||||
| #ifdef _VoxelShadow | #ifdef _VoxelShadow | ||||||
| uniform layout(r16) image3D SDF; | uniform layout(r8) image3D SDF; | ||||||
| #endif | #endif | ||||||
| uniform layout(r32ui) uimage3D voxels; | uniform layout(r32ui) uimage3D voxels; | ||||||
| uniform layout(r16) image3D voxelsB; | uniform layout(r8) image3D voxelsB; | ||||||
| uniform layout(r16) image3D voxelsOut; | uniform layout(r8) image3D voxelsOut; | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @ -80,7 +80,6 @@ void main() { | |||||||
| 	light.r = float(imageLoad(voxelsLight, src)) / 255; | 	light.r = float(imageLoad(voxelsLight, src)) / 255; | ||||||
| 	light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255; | 	light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255; | ||||||
| 	light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; | 	light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; | ||||||
| 	light /= 3; |  | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) | 	for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) | ||||||
| @ -125,7 +124,7 @@ void main() { | |||||||
| 			envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; | 			envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; | ||||||
| 			envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; | 			envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; | ||||||
| 			envl /= 3; | 			envl /= 3; | ||||||
| 			envl *= 100; |  | ||||||
|  |  | ||||||
| 			//clipmap to world | 			//clipmap to world | ||||||
| 			vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; | 			vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; | ||||||
| @ -137,7 +136,7 @@ void main() { | |||||||
| 			radiance = basecol; | 			radiance = basecol; | ||||||
| 			vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); | 			vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); | ||||||
| 			vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); | 			vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); | ||||||
| 			radiance.rgb *= light + indirect; | 			radiance.rgb *= light / PI + indirect; | ||||||
| 			radiance.rgb += emission.rgb; | 			radiance.rgb += emission.rgb; | ||||||
|  |  | ||||||
| 			#else | 			#else | ||||||
|  | |||||||
| @ -75,16 +75,17 @@ vec4 binarySearch(vec3 dir) { | |||||||
| } | } | ||||||
|  |  | ||||||
| vec4 rayCast(vec3 dir) { | vec4 rayCast(vec3 dir) { | ||||||
| 	#ifdef _CPostprocess |     float ddepth; | ||||||
| 		dir *= PPComp9.x; |     dir *= ss_refractionRayStep; | ||||||
| 	#else |     for (int i = 0; i < maxSteps; i++) { | ||||||
| 		dir *= ssrRayStep; |         hitCoord += dir; | ||||||
| 	#endif |         ddepth = getDeltaDepth(hitCoord); | ||||||
| 	for (int i = 0; i < maxSteps; i++) { |         if (ddepth > 0.0) | ||||||
| 		hitCoord += dir; |             return binarySearch(dir); | ||||||
| 		if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir); |     } | ||||||
| 	} |     // No hit — fallback to projecting the ray to UV space | ||||||
| 	return vec4(0.0); |     vec2 fallbackUV = getProjectedCoord(hitCoord); | ||||||
|  |     return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback | ||||||
| } | } | ||||||
| #endif //SSR | #endif //SSR | ||||||
|  |  | ||||||
|  | |||||||
| @ -66,12 +66,32 @@ class Quat { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public inline function fromAxisAngle(axis: Vec4, angle: FastFloat): Quat { | 	public inline function fromAxisAngle(axis: Vec4, angle: FastFloat): Quat { | ||||||
| 		var s: FastFloat = Math.sin(angle * 0.5); | 		//var s: FastFloat = Math.sin(angle * 0.5); | ||||||
| 		x = axis.x * s; | 		//x = axis.x * s; | ||||||
| 		y = axis.y * s; | 		//y = axis.y * s; | ||||||
| 		z = axis.z * s; | 		//z = axis.z * s; | ||||||
| 		w = Math.cos(angle * 0.5); | 		//w = Math.cos(angle * 0.5); | ||||||
| 		return normalize(); | 		//return normalize(); | ||||||
|  | 		// Normalize the axis vector first | ||||||
|  | 		var axisLen = Math.sqrt(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z); | ||||||
|  | 		if (axisLen > 0.00001) { | ||||||
|  | 			var aL = 1.0 / axisLen; | ||||||
|  | 			var nX = axis.x * aL; | ||||||
|  | 			var nY = axis.y * aL; | ||||||
|  | 			var nZ = axis.z * aL; | ||||||
|  | 			var halfAngle = angle * 0.5; | ||||||
|  | 			var s: FastFloat = Math.sin(halfAngle); | ||||||
|  | 			x = nX * s; | ||||||
|  | 			y = nY * s; | ||||||
|  | 			z = nZ * s; | ||||||
|  | 			w = Math.cos(halfAngle); | ||||||
|  | 		} else { | ||||||
|  | 			x = 0.0; | ||||||
|  | 			y = 0.0; | ||||||
|  | 			z = 0.0; | ||||||
|  | 			w = 1.0; | ||||||
|  | 		} | ||||||
|  | 		return this; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public inline function toAxisAngle(axis: Vec4): FastFloat { | 	public inline function toAxisAngle(axis: Vec4): FastFloat { | ||||||
| @ -379,17 +399,33 @@ class Quat { | |||||||
| 		@return	This quaternion. | 		@return	This quaternion. | ||||||
| 	**/ | 	**/ | ||||||
| 	public inline function fromEulerOrdered(e: Vec4, order: String): Quat { | 	public inline function fromEulerOrdered(e: Vec4, order: String): Quat { | ||||||
| 		var c1 = Math.cos(e.x / 2); |  | ||||||
| 		var c2 = Math.cos(e.y / 2); |  | ||||||
| 		var c3 = Math.cos(e.z / 2); |  | ||||||
| 		var s1 = Math.sin(e.x / 2); |  | ||||||
| 		var s2 = Math.sin(e.y / 2); |  | ||||||
| 		var s3 = Math.sin(e.z / 2); |  | ||||||
| 		 | 		 | ||||||
|  | 		var mappedAngles = new Vec4(); | ||||||
|  | 		switch (order) { | ||||||
|  | 			case "XYZ": | ||||||
|  | 				mappedAngles.set(e.x, e.y, e.z); | ||||||
|  | 			case "XZY": | ||||||
|  | 				mappedAngles.set(e.x, e.z, e.y); | ||||||
|  | 			case "YXZ":  | ||||||
|  | 				mappedAngles.set(e.y, e.x, e.z); | ||||||
|  | 			case "YZX":  | ||||||
|  | 				mappedAngles.set(e.y, e.z, e.x); | ||||||
|  | 			case "ZXY":  | ||||||
|  | 				mappedAngles.set(e.z, e.x, e.y); | ||||||
|  | 			case "ZYX":  | ||||||
|  | 				mappedAngles.set(e.z, e.y, e.x); | ||||||
|  | 		} | ||||||
|  | 		var c1 = Math.cos(mappedAngles.x / 2); | ||||||
|  | 		var c2 = Math.cos(mappedAngles.y / 2); | ||||||
|  | 		var c3 = Math.cos(mappedAngles.z / 2); | ||||||
|  | 		var s1 = Math.sin(mappedAngles.x / 2); | ||||||
|  | 		var s2 = Math.sin(mappedAngles.y / 2); | ||||||
|  | 		var s3 = Math.sin(mappedAngles.z / 2); | ||||||
| 		var qx = new Quat(s1, 0, 0, c1); | 		var qx = new Quat(s1, 0, 0, c1); | ||||||
| 		var qy = new Quat(0, s2, 0, c2); | 		var qy = new Quat(0, s2, 0, c2); | ||||||
| 		var qz = new Quat(0, 0, s3, c3); | 		var qz = new Quat(0, 0, s3, c3); | ||||||
|  |  | ||||||
|  | 		// Original multiplication sequence (implements reverse of 'order') | ||||||
| 		if (order.charAt(2) == 'X') | 		if (order.charAt(2) == 'X') | ||||||
| 			this.setFrom(qx); | 			this.setFrom(qx); | ||||||
| 		else if (order.charAt(2) == 'Y') | 		else if (order.charAt(2) == 'Y') | ||||||
| @ -409,6 +445,12 @@ class Quat { | |||||||
| 		else | 		else | ||||||
| 			this.mult(qz); | 			this.mult(qz); | ||||||
|  |  | ||||||
|  | 		// TO DO quick fix somethings wrong.. | ||||||
|  | 		this.x = -this.x; | ||||||
|  | 		this.y = -this.y; | ||||||
|  | 		this.z = -this.z; | ||||||
|  | 		this.w = -this.w; | ||||||
|  | 		 | ||||||
| 		return this; | 		return this; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
| @ -411,12 +411,23 @@ class ActionSampler { | |||||||
| 	 */ | 	 */ | ||||||
| 	public inline function setBoneAction(actionData: Array<TObj>) { | 	public inline function setBoneAction(actionData: Array<TObj>) { | ||||||
| 		this.actionData = actionData; | 		this.actionData = actionData; | ||||||
| 		this.totalFrames = actionData[0].anim.tracks[0].frames.length; | 		if (actionData != null && actionData.length > 0 && actionData[0] != null && actionData[0].anim != null) { | ||||||
| 		if(actionData[0].anim.root_motion_pos) this.rootMotionPos = true; | 			if (actionData[0].anim.tracks != null && actionData[0].anim.tracks.length > 0) { | ||||||
| 		if(actionData[0].anim.root_motion_rot) this.rootMotionRot = true; | 				this.totalFrames = actionData[0].anim.tracks[0].frames.length; | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				this.totalFrames = 0; | ||||||
|  | 			} | ||||||
|  | 			if(actionData[0].anim.root_motion_pos) this.rootMotionPos = true; | ||||||
|  | 			if(actionData[0].anim.root_motion_rot) this.rootMotionRot = true; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			this.totalFrames = 0; | ||||||
|  | 		} | ||||||
| 		actionDataInit = true; | 		actionDataInit = true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Cache raw object data for object animation. | 	 * Cache raw object data for object animation. | ||||||
| 	 * @param actionData Raw object data. | 	 * @param actionData Raw object data. | ||||||
|  | |||||||
| @ -51,6 +51,7 @@ class ParticleSystem { | |||||||
| 		seed = pref.seed; | 		seed = pref.seed; | ||||||
| 		particles = []; | 		particles = []; | ||||||
| 		ready = false; | 		ready = false; | ||||||
|  | 		 | ||||||
| 		Data.getParticle(sceneName, pref.particle, function(b: ParticleData) { | 		Data.getParticle(sceneName, pref.particle, function(b: ParticleData) { | ||||||
| 			data = b; | 			data = b; | ||||||
| 			r = data.raw; | 			r = data.raw; | ||||||
| @ -70,7 +71,13 @@ class ParticleSystem { | |||||||
| 			lifetime = r.lifetime / frameRate; | 			lifetime = r.lifetime / frameRate; | ||||||
| 			animtime = (r.frame_end - r.frame_start) / frameRate; | 			animtime = (r.frame_end - r.frame_start) / frameRate; | ||||||
| 			spawnRate = ((r.frame_end - r.frame_start) / r.count) / frameRate; | 			spawnRate = ((r.frame_end - r.frame_start) / r.count) / frameRate; | ||||||
| 			for (i in 0...r.count) particles.push(new Particle(i)); |  | ||||||
|  | 			for (i in 0...r.count) { | ||||||
|  | 				var particle = new Particle(i); | ||||||
|  | 				particle.sr = 1 - Math.random() * r.size_random; | ||||||
|  | 				particles.push(particle); | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			ready = true; | 			ready = true; | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| @ -108,7 +115,7 @@ class ParticleSystem { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Animate | 		// Animate | ||||||
| 		time += Time.realDelta * speed; | 		time += Time.delta * speed; | ||||||
| 		lap = Std.int(time / animtime); | 		lap = Std.int(time / animtime); | ||||||
| 		lapTime = time - lap * animtime; | 		lapTime = time - lap * animtime; | ||||||
| 		count = Std.int(lapTime / spawnRate); | 		count = Std.int(lapTime / spawnRate); | ||||||
| @ -143,7 +150,7 @@ class ParticleSystem { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function setupGeomGpu(object: MeshObject, owner: MeshObject) { | 	function setupGeomGpu(object: MeshObject, owner: MeshObject) { | ||||||
| 		var instancedData = new Float32Array(particles.length * 3); | 		var instancedData = new Float32Array(particles.length * 6); | ||||||
| 		var i = 0; | 		var i = 0; | ||||||
|  |  | ||||||
| 		var normFactor = 1 / 32767; // pa.values are not normalized | 		var normFactor = 1 / 32767; // pa.values are not normalized | ||||||
| @ -162,6 +169,10 @@ class ParticleSystem { | |||||||
| 					instancedData.set(i, pa.values[j * pa.size    ] * normFactor * scaleFactor.x); i++; | 					instancedData.set(i, pa.values[j * pa.size    ] * normFactor * scaleFactor.x); i++; | ||||||
| 					instancedData.set(i, pa.values[j * pa.size + 1] * normFactor * scaleFactor.y); i++; | 					instancedData.set(i, pa.values[j * pa.size + 1] * normFactor * scaleFactor.y); i++; | ||||||
| 					instancedData.set(i, pa.values[j * pa.size + 2] * normFactor * scaleFactor.z); i++; | 					instancedData.set(i, pa.values[j * pa.size + 2] * normFactor * scaleFactor.z); i++; | ||||||
|  |  | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 			case 1: // Face | 			case 1: // Face | ||||||
| @ -185,6 +196,10 @@ class ParticleSystem { | |||||||
| 					instancedData.set(i, pos.x * normFactor * scaleFactor.x); i++; | 					instancedData.set(i, pos.x * normFactor * scaleFactor.x); i++; | ||||||
| 					instancedData.set(i, pos.y * normFactor * scaleFactor.y); i++; | 					instancedData.set(i, pos.y * normFactor * scaleFactor.y); i++; | ||||||
| 					instancedData.set(i, pos.z * normFactor * scaleFactor.z); i++; | 					instancedData.set(i, pos.z * normFactor * scaleFactor.z); i++; | ||||||
|  |  | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 			case 2: // Volume | 			case 2: // Volume | ||||||
| @ -195,9 +210,13 @@ class ParticleSystem { | |||||||
| 					instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.x); i++; | 					instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.x); i++; | ||||||
| 					instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.y); i++; | 					instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.y); i++; | ||||||
| 					instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.z); i++; | 					instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.z); i++; | ||||||
|  |  | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
|  | 					instancedData.set(i, p.sr); i++; | ||||||
| 				} | 				} | ||||||
| 		} | 		} | ||||||
| 		object.data.geom.setupInstanced(instancedData, 1, Usage.StaticUsage); | 		object.data.geom.setupInstanced(instancedData, 3, Usage.StaticUsage); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function fhash(n: Int): Float { | 	function fhash(n: Int): Float { | ||||||
| @ -236,9 +255,10 @@ class ParticleSystem { | |||||||
|  |  | ||||||
| class Particle { | class Particle { | ||||||
| 	public var i: Int; | 	public var i: Int; | ||||||
| 	public var x = 0.0; | 	public var px = 0.0; | ||||||
| 	public var y = 0.0; | 	public var py = 0.0; | ||||||
| 	public var z = 0.0; | 	public var pz = 0.0; | ||||||
|  | 	public var sr = 1.0; // Size random | ||||||
| 	public var cameraDistance: Float; | 	public var cameraDistance: Float; | ||||||
|  |  | ||||||
| 	public function new(i: Int) { | 	public function new(i: Int) { | ||||||
|  | |||||||
| @ -160,6 +160,7 @@ class LnxPack { | |||||||
| 			case "anim": TAnimation; | 			case "anim": TAnimation; | ||||||
| 			case "tracks": TTrack; | 			case "tracks": TTrack; | ||||||
| 			case "morph_target": TMorphTarget; | 			case "morph_target": TMorphTarget; | ||||||
|  | 			case "vertex_groups": TVertex_groups; | ||||||
| 			case _: TSceneFormat; | 			case _: TSceneFormat; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -2,9 +2,11 @@ package leenkx.logicnode; | |||||||
|  |  | ||||||
| import iron.object.Object; | import iron.object.Object; | ||||||
|  |  | ||||||
| #if lnx_physics | #if lnx_bullet | ||||||
| import leenkx.trait.physics.PhysicsConstraint; | import leenkx.trait.physics.PhysicsConstraint; | ||||||
| import leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintType; | import leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintType; | ||||||
|  | #elseif lnx_oimo | ||||||
|  | // TODO | ||||||
| #end | #end | ||||||
|  |  | ||||||
| class AddPhysicsConstraintNode extends LogicNode { | class AddPhysicsConstraintNode extends LogicNode { | ||||||
| @ -25,7 +27,7 @@ class AddPhysicsConstraintNode extends LogicNode { | |||||||
|  |  | ||||||
| 		if (pivotObject == null || rb1 == null || rb2 == null) return; | 		if (pivotObject == null || rb1 == null || rb2 == null) return; | ||||||
|  |  | ||||||
| #if lnx_physics | #if lnx_bullet | ||||||
|  |  | ||||||
| 		var disableCollisions: Bool = inputs[4].get(); | 		var disableCollisions: Bool = inputs[4].get(); | ||||||
| 		var breakable: Bool = inputs[5].get(); | 		var breakable: Bool = inputs[5].get(); | ||||||
| @ -108,6 +110,8 @@ class AddPhysicsConstraintNode extends LogicNode { | |||||||
| 			} | 			} | ||||||
| 			pivotObject.addTrait(con); | 			pivotObject.addTrait(con); | ||||||
| 		} | 		} | ||||||
|  | #elseif lnx_oimo | ||||||
|  | // TODO | ||||||
| #end | #end | ||||||
| 		runOutput(0); | 		runOutput(0); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ import iron.object.Object; | |||||||
|  |  | ||||||
| #if lnx_physics | #if lnx_physics | ||||||
| import leenkx.trait.physics.RigidBody; | import leenkx.trait.physics.RigidBody; | ||||||
| import leenkx.trait.physics.bullet.RigidBody.Shape; | import leenkx.trait.physics.RigidBody.Shape; | ||||||
| #end | #end | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ class ApplyForceNode extends LogicNode { | |||||||
|  |  | ||||||
| #if lnx_physics | #if lnx_physics | ||||||
| 		var rb: RigidBody = object.getTrait(RigidBody); | 		var rb: RigidBody = object.getTrait(RigidBody); | ||||||
|  | 		if (rb == null) return; | ||||||
| 		!local ? rb.applyForce(force) : rb.applyForce(object.transform.worldVecToOrientation(force)); | 		!local ? rb.applyForce(force) : rb.applyForce(object.transform.worldVecToOrientation(force)); | ||||||
| #end | #end | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								leenkx/Sources/leenkx/logicnode/ArrayIndexListNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,26 @@ | |||||||
|  | package leenkx.logicnode; | ||||||
|  |  | ||||||
|  | class ArrayIndexListNode extends LogicNode { | ||||||
|  |  | ||||||
|  | 	public function new(tree: LogicTree) { | ||||||
|  | 		super(tree); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	override function get(from: Int): Dynamic { | ||||||
|  | 		var array: Array<Dynamic> = inputs[0].get(); | ||||||
|  | 		array = array.map(item -> Std.string(item)); | ||||||
|  | 		var value: Dynamic = inputs[1].get(); | ||||||
|  | 		var from: Int = 0; | ||||||
|  |  | ||||||
|  | 		var arrayList: Array<Int> = []; | ||||||
|  |  | ||||||
|  | 		var index: Int = array.indexOf(Std.string(value), from); | ||||||
|  |  | ||||||
|  | 		while(index != -1){ | ||||||
|  | 			arrayList.push(index); | ||||||
|  | 			index = array.indexOf(Std.string(value), index+1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return arrayList; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -1,7 +1,7 @@ | |||||||
| package leenkx.logicnode; | package leenkx.logicnode; | ||||||
| import aura.Aura; | import aura.Aura; | ||||||
| import aura.Types; | import aura.Types; | ||||||
| import aura.types.HRTFData; | import aura.types.HRTF; | ||||||
| import aura.dsp.panner.HRTFPanner; | import aura.dsp.panner.HRTFPanner; | ||||||
|  |  | ||||||
| class AudioHRTFPannerNode extends LogicNode { | class AudioHRTFPannerNode extends LogicNode { | ||||||
|  | |||||||
| @ -26,9 +26,8 @@ class GetBoneTransformNode extends LogicNode { | |||||||
| 		// Get bone in armature | 		// Get bone in armature | ||||||
| 		var bone = anim.getBone(boneName); | 		var bone = anim.getBone(boneName); | ||||||
|  |  | ||||||
|         //return anim.getAbsWorldMat(bone); | 		return anim.getAbsWorldMat(anim.skeletonMats, bone); | ||||||
| 		return anim.getAbsMat(bone).clone().multmat(object.transform.world); |         //return anim.getAbsMat(bone).clone().multmat(object.transform.world); | ||||||
| 		//return anim.getAbsWorldMat(bone); |  | ||||||
| 		 | 		 | ||||||
|         #else |         #else | ||||||
|         return null; |         return null; | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package leenkx.logicnode; | package leenkx.logicnode; | ||||||
|  |  | ||||||
| #if lnx_physics | #if lnx_physics | ||||||
| import leenkx.trait.physics.bullet.PhysicsWorld; | import leenkx.trait.physics.PhysicsWorld; | ||||||
| #end | #end | ||||||
| import leenkx.trait.navigation.Navigation; | import leenkx.trait.navigation.Navigation; | ||||||
| import iron.object.Object; | import iron.object.Object; | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package leenkx.logicnode; | package leenkx.logicnode; | ||||||
|  | #if lnx_audio | ||||||
| import iron.object.SpeakerObject; | import iron.object.SpeakerObject; | ||||||
|  | #end | ||||||
| class PauseSoundNode extends LogicNode { | class PauseSoundNode extends LogicNode { | ||||||
|  |  | ||||||
| 	public function new(tree: LogicTree) { | 	public function new(tree: LogicTree) { | ||||||
| @ -9,9 +9,11 @@ class PauseSoundNode extends LogicNode { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	override function run(from: Int) { | 	override function run(from: Int) { | ||||||
|  | 		#if lnx_audio | ||||||
| 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | ||||||
| 		if (object == null) return; | 		if (object == null) return; | ||||||
| 		object.pause(); | 		object.pause(); | ||||||
|  | 		#end | ||||||
| 		runOutput(0); | 		runOutput(0); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package leenkx.logicnode; | package leenkx.logicnode; | ||||||
|  |  | ||||||
| #if lnx_physics | #if lnx_physics | ||||||
| import leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintAxis; | import leenkx.trait.physics.PhysicsConstraint.ConstraintAxis; | ||||||
| #end | #end | ||||||
|  |  | ||||||
| class PhysicsConstraintNode extends LogicNode { | class PhysicsConstraintNode extends LogicNode { | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package leenkx.logicnode; | package leenkx.logicnode; | ||||||
|  | #if lnx_audio | ||||||
| import iron.object.SpeakerObject; | import iron.object.SpeakerObject; | ||||||
|  | #end | ||||||
| class PlaySoundNode extends LogicNode { | class PlaySoundNode extends LogicNode { | ||||||
|  |  | ||||||
| 	public function new(tree: LogicTree) { | 	public function new(tree: LogicTree) { | ||||||
| @ -9,9 +9,11 @@ class PlaySoundNode extends LogicNode { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	override function run(from: Int) { | 	override function run(from: Int) { | ||||||
|  | 		#if lnx_audio | ||||||
| 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | ||||||
| 		if (object == null) return; | 		if (object == null) return; | ||||||
| 		object.play(); | 		object.play(); | ||||||
|  | 		#end | ||||||
| 		runOutput(0); | 		runOutput(0); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -16,15 +16,16 @@ class PlaySoundRawNode extends LogicNode { | |||||||
| 	public var property5: Bool; | 	public var property5: Bool; | ||||||
|  |  | ||||||
| 	public var property6: String; | 	public var property6: String; | ||||||
|  | 	#if lnx_audio | ||||||
| 	var sound: kha.Sound = null; | 	var sound: kha.Sound = null; | ||||||
| 	var channel: kha.audio1.AudioChannel = null; | 	var channel: kha.audio1.AudioChannel = null; | ||||||
|  | 	#end | ||||||
| 	public function new(tree: LogicTree) { | 	public function new(tree: LogicTree) { | ||||||
| 		super(tree); | 		super(tree); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	override function run(from: Int) { | 	override function run(from: Int) { | ||||||
|  | 		#if lnx_audio | ||||||
| 		switch (from) { | 		switch (from) { | ||||||
| 			case Play: | 			case Play: | ||||||
| 				if (property6 == 'Sound' ? sound == null : true) { | 				if (property6 == 'Sound' ? sound == null : true) { | ||||||
| @ -63,6 +64,10 @@ class PlaySoundRawNode extends LogicNode { | |||||||
| 			case UpdateVolume: | 			case UpdateVolume: | ||||||
| 				if (channel != null) channel.volume = inputs[4].get(); | 				if (channel != null) channel.volume = inputs[4].get(); | ||||||
| 		} | 		} | ||||||
|  | 		#end | ||||||
|  | 		#if !lnx_audio | ||||||
|  | 			runOutput(0); | ||||||
|  | 		#end | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function onUpdate() { | 	function onUpdate() { | ||||||
|  | |||||||
| @ -37,6 +37,7 @@ class RotationNode extends LogicNode { | |||||||
| 				value.y = vect.y; | 				value.y = vect.y; | ||||||
| 				value.z = vect.z; | 				value.z = vect.z; | ||||||
| 				value.w = inputs[1].get(); | 				value.w = inputs[1].get(); | ||||||
|  | 				value.normalize(); | ||||||
|  |  | ||||||
| 			case "AxisAngle": | 			case "AxisAngle": | ||||||
| 				var vec: Vec4 = inputs[0].get(); | 				var vec: Vec4 = inputs[0].get(); | ||||||
|  | |||||||
							
								
								
									
										37
									
								
								leenkx/Sources/leenkx/logicnode/SetBoneTransformNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,37 @@ | |||||||
|  | package leenkx.logicnode; | ||||||
|  |  | ||||||
|  | import iron.object.Object; | ||||||
|  | #if lnx_skin | ||||||
|  | import iron.object.BoneAnimation; | ||||||
|  | #end | ||||||
|  | import iron.math.Mat4; | ||||||
|  |  | ||||||
|  | class SetBoneTransformNode extends LogicNode { | ||||||
|  |  | ||||||
|  | 	public function new(tree: LogicTree) { | ||||||
|  | 		super(tree); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	override function run(from: Int) { | ||||||
|  | 		#if lnx_skin | ||||||
|  |  | ||||||
|  | 		var object: Object = inputs[1].get(); | ||||||
|  | 		if (object == null) return; | ||||||
|  |                 var transform = inputs[3].get(); | ||||||
|  |                 if (transform == null) return; | ||||||
|  |                 var boneName: String = inputs[2].get(); | ||||||
|  |  | ||||||
|  | 		var anim = object.animation != null ? cast(object.animation, BoneAnimation) : null; | ||||||
|  | 		if (anim == null) anim = object.getBoneAnimation(object.uid); | ||||||
|  |  | ||||||
|  | 		// Get bone in armature | ||||||
|  | 		var bone = anim.getBone(boneName); | ||||||
|  |  | ||||||
|  | 		anim.setBoneMatFromWorldMat(anim.skeletonMats, transform, bone); | ||||||
|  |  | ||||||
|  | 		runOutput(0); | ||||||
|  |  | ||||||
|  |         #end | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -17,7 +17,7 @@ class SetParentBoneNode extends LogicNode { | |||||||
|  |  | ||||||
| 		if (object == null || parent == null) return; | 		if (object == null || parent == null) return; | ||||||
|  |  | ||||||
| 		object.setParent(parent, false, false); | 		object.setParent(parent, inputs[4].get(), inputs[5].get()); | ||||||
|  |  | ||||||
| 		var banim = object.getBoneAnimation(object.parent.uid); | 		var banim = object.getBoneAnimation(object.parent.uid); | ||||||
| 		banim.addBoneChild(bone, object); | 		banim.addBoneChild(bone, object); | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package leenkx.logicnode; | package leenkx.logicnode; | ||||||
|  | #if lnx_audio | ||||||
| import iron.object.SpeakerObject; | import iron.object.SpeakerObject; | ||||||
|  | #end | ||||||
| class SetSoundNode extends LogicNode { | class SetSoundNode extends LogicNode { | ||||||
|  |  | ||||||
| 	public function new(tree: LogicTree) { | 	public function new(tree: LogicTree) { | ||||||
| @ -9,10 +9,12 @@ class SetSoundNode extends LogicNode { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	override function run(from: Int) { | 	override function run(from: Int) { | ||||||
|  | 		#if lnx_audio | ||||||
| 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | ||||||
| 		var sound: String = inputs[2].get();  | 		var sound: String = inputs[2].get();  | ||||||
| 		if (object == null || sound == null) return; | 		if (object == null || sound == null) return; | ||||||
| 		object.setSound(sound); | 		object.setSound(sound); | ||||||
|  | 		#end | ||||||
| 		runOutput(0); | 		runOutput(0); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package leenkx.logicnode; | package leenkx.logicnode; | ||||||
|  | #if lnx_audio | ||||||
| import iron.object.SpeakerObject; | import iron.object.SpeakerObject; | ||||||
|  | #end | ||||||
| class SetVolumeSoundNode extends LogicNode { | class SetVolumeSoundNode extends LogicNode { | ||||||
|  |  | ||||||
| 	public function new(tree: LogicTree) { | 	public function new(tree: LogicTree) { | ||||||
| @ -9,9 +9,11 @@ class SetVolumeSoundNode extends LogicNode { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	override function run(from: Int) { | 	override function run(from: Int) { | ||||||
|  | 		#if lnx_audio | ||||||
| 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | ||||||
| 		if (object == null) return; | 		if (object == null) return; | ||||||
| 		object.setVolume(inputs[2].get()); | 		object.setVolume(inputs[2].get()); | ||||||
|  | 		#end | ||||||
| 		runOutput(0); | 		runOutput(0); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package leenkx.logicnode; | package leenkx.logicnode; | ||||||
|  | #if lnx_audio | ||||||
| import iron.object.SpeakerObject; | import iron.object.SpeakerObject; | ||||||
|  | #end | ||||||
| class StopSoundNode extends LogicNode { | class StopSoundNode extends LogicNode { | ||||||
|  |  | ||||||
| 	public function new(tree: LogicTree) { | 	public function new(tree: LogicTree) { | ||||||
| @ -9,9 +9,11 @@ class StopSoundNode extends LogicNode { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	override function run(from: Int) { | 	override function run(from: Int) { | ||||||
|  | 		#if lnx_audio | ||||||
| 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | 		var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject); | ||||||
| 		if (object == null) return; | 		if (object == null) return; | ||||||
| 		object.stop(); | 		object.stop(); | ||||||
|  | 		#end | ||||||
| 		runOutput(0); | 		runOutput(0); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,7 +18,7 @@ class TransformNode extends LogicNode { | |||||||
| 	override function get(from: Int): Dynamic { | 	override function get(from: Int): Dynamic { | ||||||
| 		var loc: Vec4 = inputs[0].get(); | 		var loc: Vec4 = inputs[0].get(); | ||||||
| 		var rot: Quat = new Quat().setFrom(inputs[1].get()); | 		var rot: Quat = new Quat().setFrom(inputs[1].get()); | ||||||
| 		rot.normalize(); | 		//rot.normalize(); | ||||||
| 		var scale: Vec4 = inputs[2].get(); | 		var scale: Vec4 = inputs[2].get(); | ||||||
| 		if (loc == null && rot == null && scale == null) return this.value; | 		if (loc == null && rot == null && scale == null) return this.value; | ||||||
| 		if (loc == null || rot == null || scale == null) return null; | 		if (loc == null || rot == null || scale == null) return null; | ||||||
|  | |||||||
| @ -77,6 +77,9 @@ class Inc { | |||||||
| 	#if (rp_voxels == "Voxel GI") | 	#if (rp_voxels == "Voxel GI") | ||||||
| 	static var voxel_sh5:kha.compute.Shader = null; | 	static var voxel_sh5:kha.compute.Shader = null; | ||||||
| 	static var voxel_ta5:kha.compute.TextureUnit; | 	static var voxel_ta5:kha.compute.TextureUnit; | ||||||
|  | 	static var voxel_te5:kha.compute.TextureUnit; | ||||||
|  | 	static var voxel_tf5:kha.compute.TextureUnit; | ||||||
|  | 	static var voxel_tg5:kha.compute.TextureUnit; | ||||||
| 	static var voxel_ca5:kha.compute.ConstantLocation; | 	static var voxel_ca5:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_cb5:kha.compute.ConstantLocation; | 	static var voxel_cb5:kha.compute.ConstantLocation; | ||||||
| 	static var voxel_cc5:kha.compute.ConstantLocation; | 	static var voxel_cc5:kha.compute.ConstantLocation; | ||||||
| @ -677,7 +680,7 @@ class Inc { | |||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| 			if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { | 			if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { | ||||||
| 				t.format = "R16"; | 				t.format = "R8"; | ||||||
| 				t.width = res; | 				t.width = res; | ||||||
| 				t.height = res * Main.voxelgiClipmapCount; | 				t.height = res * Main.voxelgiClipmapCount; | ||||||
| 				t.depth = res; | 				t.depth = res; | ||||||
| @ -686,7 +689,7 @@ class Inc { | |||||||
| 				#if (rp_voxels == "Voxel AO") | 				#if (rp_voxels == "Voxel AO") | ||||||
| 				{ | 				{ | ||||||
| 					if (t.name == "voxelsOut" || t.name == "voxelsOutB") { | 					if (t.name == "voxelsOut" || t.name == "voxelsOutB") { | ||||||
| 						t.format = "R16"; | 						t.format = "R8"; | ||||||
| 						t.width = res * (6 + 16); | 						t.width = res * (6 + 16); | ||||||
| 						t.height = res * Main.voxelgiClipmapCount; | 						t.height = res * Main.voxelgiClipmapCount; | ||||||
| 						t.depth = res; | 						t.depth = res; | ||||||
| @ -892,7 +895,9 @@ class Inc { | |||||||
| 		{ | 		{ | ||||||
| 			voxel_sh5 = path.getComputeShader("voxel_light"); | 			voxel_sh5 = path.getComputeShader("voxel_light"); | ||||||
| 			voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight"); | 			voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight"); | ||||||
|  | 			voxel_te5 = voxel_sh5.getTextureUnit("voxels"); | ||||||
|  | 			voxel_tf5 = voxel_sh5.getTextureUnit("voxelsSampler"); | ||||||
|  | 			voxel_tg5 = voxel_sh5.getTextureUnit("voxelsSDFSampler"); | ||||||
| 	 		voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps"); | 	 		voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps"); | ||||||
| 			voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel"); | 			voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel"); | ||||||
|  |  | ||||||
| @ -1288,7 +1293,9 @@ class Inc { | |||||||
| 	 		kha.compute.Compute.setShader(voxel_sh5); | 	 		kha.compute.Compute.setShader(voxel_sh5); | ||||||
|  |  | ||||||
| 			kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write); | 			kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write); | ||||||
|  | 			kha.compute.Compute.setTexture(voxel_te5, rts.get("voxels").image, kha.compute.Access.Read); | ||||||
|  | 			kha.compute.Compute.setSampledTexture(voxel_tf5, rts.get("voxelsOut").image); | ||||||
|  | 			kha.compute.Compute.setSampledTexture(voxel_tg5, rts.get("voxelsSDF").image); | ||||||
| 			var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | 			var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); | ||||||
| 			for (i in 0...Main.voxelgiClipmapCount) { | 			for (i in 0...Main.voxelgiClipmapCount) { | ||||||
| 				fa[i * 10] = clipmaps[i].voxelSize; | 				fa[i * 10] = clipmaps[i].voxelSize; | ||||||
|  | |||||||
| @ -368,7 +368,7 @@ class RenderPathDeferred { | |||||||
| 			t.scale = Inc.getSuperSampling(); | 			t.scale = Inc.getSuperSampling(); | ||||||
| 			path.createRenderTarget(t); | 			path.createRenderTarget(t); | ||||||
|  |  | ||||||
| 			// holds background depth | 			// holds background color | ||||||
| 			var t = new RenderTargetRaw(); | 			var t = new RenderTargetRaw(); | ||||||
| 			t.name = "refr"; | 			t.name = "refr"; | ||||||
| 			t.width = 0; | 			t.width = 0; | ||||||
| @ -473,6 +473,13 @@ class RenderPathDeferred { | |||||||
| 		} | 		} | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
|  | 		#if rp_ssrefr | ||||||
|  | 		{ | ||||||
|  | 			path.setTarget("gbuffer_refraction"); | ||||||
|  | 			path.clearTarget(0xffffff00); | ||||||
|  | 		} | ||||||
|  | 		#end | ||||||
|  |  | ||||||
| 		RenderPathCreator.setTargetMeshes(); | 		RenderPathCreator.setTargetMeshes(); | ||||||
|  |  | ||||||
| 		#if rp_dynres | 		#if rp_dynres | ||||||
| @ -837,7 +844,7 @@ class RenderPathDeferred { | |||||||
| 				{ | 				{ | ||||||
| 					path.bindTarget("voxelsOut", "voxels"); | 					path.bindTarget("voxelsOut", "voxels"); | ||||||
| 					path.bindTarget("voxelsSDF", "voxelsSDF"); | 					path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||||
| 					path.bindTarget("gbuffer2", "sveloc"); | 					path.bindTarget("gbuffer2", "gbuffer2"); | ||||||
| 				} | 				} | ||||||
| 				#end | 				#end | ||||||
|  |  | ||||||
|  | |||||||
| @ -522,6 +522,17 @@ class RenderPathForward { | |||||||
|  |  | ||||||
| 					path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); | 					path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); | ||||||
|  |  | ||||||
|  | 					#if rp_shadowmap | ||||||
|  | 					{ | ||||||
|  | 						#if lnx_shadowmap_atlas | ||||||
|  | 						Inc.bindShadowMapAtlas(); | ||||||
|  | 						#else | ||||||
|  | 						Inc.bindShadowMap(); | ||||||
|  | 						#end | ||||||
|  | 					} | ||||||
|  | 					#end | ||||||
|  |  | ||||||
|  |  | ||||||
| 					#if (rp_voxels != "Off") | 					#if (rp_voxels != "Off") | ||||||
| 					path.bindTarget("voxelsOut", "voxels"); | 					path.bindTarget("voxelsOut", "voxels"); | ||||||
| 					path.bindTarget("voxelsSDF", "voxelsSDF"); | 					path.bindTarget("voxelsSDF", "voxelsSDF"); | ||||||
|  | |||||||
| @ -41,7 +41,11 @@ class Starter { | |||||||
| 			try { | 			try { | ||||||
| 			#end | 			#end | ||||||
|  |  | ||||||
| 			kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { | 			kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: { | ||||||
|  | 			#if lnx_render_viewport | ||||||
|  | 			visible: false, | ||||||
|  | 			#end | ||||||
|  | 			mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { | ||||||
|  |  | ||||||
| 				iron.App.init(function() { | 				iron.App.init(function() { | ||||||
| 					#if lnx_loadscreen | 					#if lnx_loadscreen | ||||||
|  | |||||||
| @ -10,6 +10,10 @@ class KinematicCharacterController extends iron.Trait { public function new() { | |||||||
|  |  | ||||||
| 	typedef KinematicCharacterController = leenkx.trait.physics.bullet.KinematicCharacterController; | 	typedef KinematicCharacterController = leenkx.trait.physics.bullet.KinematicCharacterController; | ||||||
|  |  | ||||||
|  | 	#else | ||||||
|  |  | ||||||
|  | 	typedef KinematicCharacterController = leenkx.trait.physics.oimo.KinematicCharacterController; | ||||||
|  |  | ||||||
| 	#end | 	#end | ||||||
|  |  | ||||||
| #end | #end | ||||||
|  | |||||||
| @ -3,17 +3,16 @@ package leenkx.trait.physics; | |||||||
| #if (!lnx_physics) | #if (!lnx_physics) | ||||||
|  |  | ||||||
| class PhysicsConstraint extends iron.Trait { public function new() { super(); } } | class PhysicsConstraint extends iron.Trait { public function new() { super(); } } | ||||||
|  | @:enum abstract ConstraintAxis(Int) from Int to Int { } | ||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
| 	#if lnx_bullet | 	#if lnx_bullet | ||||||
|  |  | ||||||
| 	typedef PhysicsConstraint = leenkx.trait.physics.bullet.PhysicsConstraint; | 	typedef PhysicsConstraint = leenkx.trait.physics.bullet.PhysicsConstraint; | ||||||
|  | 	typedef ConstraintAxis = leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintAxis; | ||||||
| 	#else | 	#else | ||||||
|  |  | ||||||
| 	typedef PhysicsConstraint = leenkx.trait.physics.oimo.PhysicsConstraint; | 	typedef PhysicsConstraint = leenkx.trait.physics.oimo.PhysicsConstraint; | ||||||
|  | 	typedef ConstraintAxis = leenkx.trait.physics.oimo.PhysicsConstraint.ConstraintAxis; | ||||||
| 	#end | 	#end | ||||||
|  |  | ||||||
| #end | #end | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ package leenkx.trait.physics; | |||||||
|  |  | ||||||
| #if (!lnx_physics) | #if (!lnx_physics) | ||||||
|  |  | ||||||
|  | class Hit { } | ||||||
| class PhysicsWorld extends iron.Trait { public function new() { super(); } } | class PhysicsWorld extends iron.Trait { public function new() { super(); } } | ||||||
|  |  | ||||||
| #else | #else | ||||||
| @ -9,11 +10,11 @@ class PhysicsWorld extends iron.Trait { public function new() { super(); } } | |||||||
| 	#if lnx_bullet | 	#if lnx_bullet | ||||||
|  |  | ||||||
| 	typedef PhysicsWorld = leenkx.trait.physics.bullet.PhysicsWorld; | 	typedef PhysicsWorld = leenkx.trait.physics.bullet.PhysicsWorld; | ||||||
|  | 	typedef Hit = leenkx.trait.physics.bullet.PhysicsWorld.Hit; | ||||||
| 	#else | 	#else | ||||||
|  |  | ||||||
| 	typedef PhysicsWorld = leenkx.trait.physics.oimo.PhysicsWorld; | 	typedef PhysicsWorld = leenkx.trait.physics.oimo.PhysicsWorld; | ||||||
|  | 	typedef Hit = leenkx.trait.physics.oimo.PhysicsWorld.Hit; | ||||||
| 	#end | 	#end | ||||||
|  |  | ||||||
| #end | #end | ||||||
|  | |||||||
| @ -3,16 +3,19 @@ package leenkx.trait.physics; | |||||||
| #if (!lnx_physics) | #if (!lnx_physics) | ||||||
|  |  | ||||||
| class RigidBody extends iron.Trait { public function new() { super(); } } | class RigidBody extends iron.Trait { public function new() { super(); } } | ||||||
|  | @:enum abstract Shape(Int) from Int to Int { } | ||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
| 	#if lnx_bullet | 	#if lnx_bullet | ||||||
|  |  | ||||||
| 	typedef RigidBody = leenkx.trait.physics.bullet.RigidBody; | 	typedef RigidBody = leenkx.trait.physics.bullet.RigidBody; | ||||||
|  | 	typedef Shape = leenkx.trait.physics.bullet.RigidBody.Shape; | ||||||
| 	 | 	 | ||||||
| 	#else | 	#else | ||||||
|  |  | ||||||
| 	typedef RigidBody = leenkx.trait.physics.oimo.RigidBody; | 	typedef RigidBody = leenkx.trait.physics.oimo.RigidBody; | ||||||
|  | 	typedef Shape = leenkx.trait.physics.oimo.RigidBody.Shape; | ||||||
| 	 | 	 | ||||||
| 	#end | 	#end | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,5 +1,8 @@ | |||||||
| package leenkx.trait.physics.bullet; | package leenkx.trait.physics.bullet; | ||||||
|  |  | ||||||
|  | #if lnx_bullet | ||||||
|  | import leenkx.trait.physics.bullet.PhysicsWorld.DebugDrawMode; | ||||||
|  |  | ||||||
| import bullet.Bt.Vector3; | import bullet.Bt.Vector3; | ||||||
|  |  | ||||||
| import kha.FastFloat; | import kha.FastFloat; | ||||||
| @ -18,15 +21,21 @@ class DebugDrawHelper { | |||||||
| 	static inline var contactPointNormalColor = 0xffffffff; | 	static inline var contactPointNormalColor = 0xffffffff; | ||||||
| 	static inline var contactPointDrawLifetime = true; | 	static inline var contactPointDrawLifetime = true; | ||||||
|  |  | ||||||
|  | 	final rayCastColor: Vec4 = new Vec4(0.0, 1.0, 0.0); | ||||||
|  | 	final rayCastHitColor: Vec4 = new Vec4(1.0, 0.0, 0.0); | ||||||
|  | 	final rayCastHitPointColor: Vec4 = new Vec4(1.0, 1.0, 0.0); | ||||||
|  |  | ||||||
| 	final physicsWorld: PhysicsWorld; | 	final physicsWorld: PhysicsWorld; | ||||||
| 	final lines: Array<LineData> = []; | 	final lines: Array<LineData> = []; | ||||||
| 	final texts: Array<TextData> = []; | 	final texts: Array<TextData> = []; | ||||||
| 	var font: kha.Font = null; | 	var font: kha.Font = null; | ||||||
|  |  | ||||||
| 	var debugMode: PhysicsWorld.DebugDrawMode = NoDebug; | 	var rayCasts:Array<TRayCastData> = []; | ||||||
|  | 	var debugDrawMode: DebugDrawMode = NoDebug; | ||||||
|  |  | ||||||
| 	public function new(physicsWorld: PhysicsWorld) { | 	public function new(physicsWorld: PhysicsWorld, debugDrawMode: DebugDrawMode) { | ||||||
| 		this.physicsWorld = physicsWorld; | 		this.physicsWorld = physicsWorld; | ||||||
|  | 		this.debugDrawMode = debugDrawMode; | ||||||
|  |  | ||||||
| 		#if lnx_ui | 		#if lnx_ui | ||||||
| 		iron.data.Data.getFont(Canvas.defaultFontName, function(defaultFont: kha.Font) { | 		iron.data.Data.getFont(Canvas.defaultFontName, function(defaultFont: kha.Font) { | ||||||
| @ -35,6 +44,11 @@ class DebugDrawHelper { | |||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| 		iron.App.notifyOnRender2D(onRender); | 		iron.App.notifyOnRender2D(onRender); | ||||||
|  | 		if (debugDrawMode & DrawRayCast != 0) { | ||||||
|  | 			iron.App.notifyOnUpdate(function () { | ||||||
|  | 				rayCasts.resize(0); | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public function drawLine(from: bullet.Bt.Vector3, to: bullet.Bt.Vector3, color: bullet.Bt.Vector3) { | 	public function drawLine(from: bullet.Bt.Vector3, to: bullet.Bt.Vector3, color: bullet.Bt.Vector3) { | ||||||
| @ -49,9 +63,10 @@ class DebugDrawHelper { | |||||||
| 		final fromScreenSpace = worldToScreenFast(new Vec4(from.x(), from.y(), from.z(), 1.0)); | 		final fromScreenSpace = worldToScreenFast(new Vec4(from.x(), from.y(), from.z(), 1.0)); | ||||||
| 		final toScreenSpace = worldToScreenFast(new Vec4(to.x(), to.y(), to.z(), 1.0)); | 		final toScreenSpace = worldToScreenFast(new Vec4(to.x(), to.y(), to.z(), 1.0)); | ||||||
|  |  | ||||||
| 		// For now don't draw lines if any point is outside of clip space z, |  | ||||||
| 		// investigate how to clamp lines to clip space borders | 		// investigate how to clamp lines to clip space borders | ||||||
| 		if (fromScreenSpace.w == 1 && toScreenSpace.w == 1) { | 		// If at least one point is within the Z clip space (w==1), attempt to draw. | ||||||
|  | 		// Note: This is not full clipping, line may still go off screen sides. | ||||||
|  | 		if (fromScreenSpace.w == 1 || toScreenSpace.w == 1) { | ||||||
| 			lines.push({ | 			lines.push({ | ||||||
| 				fromX: fromScreenSpace.x, | 				fromX: fromScreenSpace.x, | ||||||
| 				fromY: fromScreenSpace.y, | 				fromY: fromScreenSpace.y, | ||||||
| @ -112,6 +127,61 @@ class DebugDrawHelper { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public function rayCast(rayCastData:TRayCastData) { | ||||||
|  | 		rayCasts.push(rayCastData); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function drawRayCast(f: Vec4, t: Vec4, hit: Bool) { | ||||||
|  | 		final from = worldToScreenFast(f.clone()); | ||||||
|  | 		final to = worldToScreenFast(t.clone()); | ||||||
|  | 		var c: kha.Color; | ||||||
|  |  | ||||||
|  | 		if (from.w == 1 && to.w == 1) { | ||||||
|  | 			if (hit) c = kha.Color.fromFloats(rayCastHitColor.x, rayCastHitColor.y, rayCastHitColor.z); | ||||||
|  | 			else c = kha.Color.fromFloats(rayCastColor.x, rayCastColor.y, rayCastColor.z); | ||||||
|  |  | ||||||
|  | 			lines.push({ | ||||||
|  | 				fromX: from.x, | ||||||
|  | 				fromY: from.y, | ||||||
|  | 				toX: to.x, | ||||||
|  | 				toY: to.y, | ||||||
|  | 				color: c | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function drawHitPoint(hp: Vec4) { | ||||||
|  | 		final hitPoint = worldToScreenFast(hp.clone()); | ||||||
|  | 		final c = kha.Color.fromFloats(rayCastHitPointColor.x, rayCastHitPointColor.y, rayCastHitPointColor.z); | ||||||
|  |  | ||||||
|  | 		if (hitPoint.w == 1) { | ||||||
|  | 			lines.push({ | ||||||
|  | 				fromX: hitPoint.x - contactPointSizePx, | ||||||
|  | 				fromY: hitPoint.y - contactPointSizePx, | ||||||
|  | 				toX: hitPoint.x + contactPointSizePx, | ||||||
|  | 				toY: hitPoint.y + contactPointSizePx, | ||||||
|  | 				color: c | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  | 			lines.push({ | ||||||
|  | 				fromX: hitPoint.x - contactPointSizePx, | ||||||
|  | 				fromY: hitPoint.y + contactPointSizePx, | ||||||
|  | 				toX: hitPoint.x + contactPointSizePx, | ||||||
|  | 				toY: hitPoint.y - contactPointSizePx, | ||||||
|  | 				color: c | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  | 			if (font != null) { | ||||||
|  | 				texts.push({ | ||||||
|  | 					x: hitPoint.x, | ||||||
|  | 					y: hitPoint.y, | ||||||
|  | 					color: c, | ||||||
|  | 					text: 'RAYCAST HIT' | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public function reportErrorWarning(warningString: bullet.Bt.BulletString) { | 	public function reportErrorWarning(warningString: bullet.Bt.BulletString) { | ||||||
| 		trace(warningString.toHaxeString().trim()); | 		trace(warningString.toHaxeString().trim()); | ||||||
| 	} | 	} | ||||||
| @ -135,13 +205,13 @@ class DebugDrawHelper { | |||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public function setDebugMode(debugMode: PhysicsWorld.DebugDrawMode) { | 	public function setDebugMode(debugDrawMode: DebugDrawMode) { | ||||||
| 		this.debugMode = debugMode; | 		this.debugDrawMode = debugDrawMode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public function getDebugMode(): PhysicsWorld.DebugDrawMode { | 	public function getDebugMode(): DebugDrawMode { | ||||||
| 		#if js | 		#if js | ||||||
| 			return debugMode; | 			return debugDrawMode; | ||||||
| 		#elseif hl | 		#elseif hl | ||||||
| 			return physicsWorld.getDebugDrawMode(); | 			return physicsWorld.getDebugDrawMode(); | ||||||
| 		#else | 		#else | ||||||
| @ -161,6 +231,7 @@ class DebugDrawHelper { | |||||||
| 		// before some user-specific physics update, which would result in a | 		// before some user-specific physics update, which would result in a | ||||||
| 		// one-frame drawing delay... Ideally we would ensure that debugDrawWorld() | 		// one-frame drawing delay... Ideally we would ensure that debugDrawWorld() | ||||||
| 		// is called when all other (late) update callbacks are already executed... | 		// is called when all other (late) update callbacks are already executed... | ||||||
|  | 		 | ||||||
| 		physicsWorld.world.debugDrawWorld(); | 		physicsWorld.world.debugDrawWorld(); | ||||||
|  |  | ||||||
| 		g.opacity = 1.0; | 		g.opacity = 1.0; | ||||||
| @ -180,6 +251,17 @@ class DebugDrawHelper { | |||||||
| 			} | 			} | ||||||
| 			texts.resize(0); | 			texts.resize(0); | ||||||
| 		} | 		} | ||||||
|  | 		 | ||||||
|  | 		if (debugDrawMode & DrawRayCast != 0) { | ||||||
|  | 			for (rayCastData in rayCasts) { | ||||||
|  | 				if (rayCastData.hasHit) { | ||||||
|  | 					drawRayCast(rayCastData.from, rayCastData.hitPoint, true); | ||||||
|  | 					drawHitPoint(rayCastData.hitPoint); | ||||||
|  | 				} else { | ||||||
|  | 					drawRayCast(rayCastData.from, rayCastData.to, false); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @ -222,3 +304,14 @@ class TextData { | |||||||
| 	public var color: kha.Color; | 	public var color: kha.Color; | ||||||
| 	public var text: String; | 	public var text: String; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @:structInit | ||||||
|  | typedef TRayCastData = { | ||||||
|  | 	var from: Vec4; | ||||||
|  | 	var to: Vec4; | ||||||
|  | 	var hasHit: Bool; | ||||||
|  | 	@:optional var hitPoint: Vec4; | ||||||
|  | 	@:optional var hitNormal: Vec4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #end | ||||||
| @ -85,6 +85,22 @@ class PhysicsWorld extends Trait { | |||||||
| 	public static var physTime = 0.0; | 	public static var physTime = 0.0; | ||||||
| 	#end | 	#end | ||||||
|  |  | ||||||
|  | 	public static function getSolverInfo(world:bullet.Bt.DynamicsWorld):Dynamic { | ||||||
|  | 		return Reflect.callMethod(world, Reflect.field(world, "getSolverInfo"), []); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public static function setSolverIterations(world:bullet.Bt.DynamicsWorld, iterations:Int):Void { | ||||||
|  | 		var solverInfo = getSolverInfo(world); | ||||||
|  | 		if (solverInfo != null) { | ||||||
|  | 			Reflect.setField(solverInfo, "m_numIterations", iterations); | ||||||
|  | 		} else { | ||||||
|  | 			trace("Warning: Could not access solver info. Solver iterations not applied."); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug) { | 	public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug) { | ||||||
| 		super(); | 		super(); | ||||||
|  |  | ||||||
| @ -164,7 +180,8 @@ class PhysicsWorld extends Trait { | |||||||
| #else | #else | ||||||
| 		world = new bullet.Bt.DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); | 		world = new bullet.Bt.DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); | ||||||
| #end | #end | ||||||
|  | 		// TO DO: Set the solver iterations from Blender's rigid body world | ||||||
|  | 		// setSolverIterations(world, solverIterations); | ||||||
| 		setGravity(gravity); | 		setGravity(gravity); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -378,6 +395,7 @@ class PhysicsWorld extends Trait { | |||||||
| 		rayTo.setValue(to.x, to.y, to.z); | 		rayTo.setValue(to.x, to.y, to.z); | ||||||
|  |  | ||||||
| 		var rayCallback = new bullet.Bt.ClosestRayResultCallback(rayFrom, rayTo); | 		var rayCallback = new bullet.Bt.ClosestRayResultCallback(rayFrom, rayTo); | ||||||
|  |  | ||||||
| 		#if js | 		#if js | ||||||
| 		rayCallback.set_m_collisionFilterGroup(group); | 		rayCallback.set_m_collisionFilterGroup(group); | ||||||
| 		rayCallback.set_m_collisionFilterMask(mask); | 		rayCallback.set_m_collisionFilterMask(mask); | ||||||
| @ -387,6 +405,7 @@ class PhysicsWorld extends Trait { | |||||||
| 		#end | 		#end | ||||||
| 		var worldDyn: bullet.Bt.DynamicsWorld = world; | 		var worldDyn: bullet.Bt.DynamicsWorld = world; | ||||||
| 		var worldCol: bullet.Bt.CollisionWorld = worldDyn; | 		var worldCol: bullet.Bt.CollisionWorld = worldDyn; | ||||||
|  |  | ||||||
| 		worldCol.rayTest(rayFrom, rayTo, rayCallback); | 		worldCol.rayTest(rayFrom, rayTo, rayCallback); | ||||||
| 		var rb: RigidBody = null; | 		var rb: RigidBody = null; | ||||||
| 		var hitInfo: Hit = null; | 		var hitInfo: Hit = null; | ||||||
| @ -412,6 +431,16 @@ class PhysicsWorld extends Trait { | |||||||
| 			#end | 			#end | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if (getDebugDrawMode() & DrawRayCast != 0) { | ||||||
|  | 			debugDrawHelper.rayCast({ | ||||||
|  | 				from: from, | ||||||
|  | 				to: to, | ||||||
|  | 				hasHit: rc.hasHit(), | ||||||
|  | 				hitPoint: hitPointWorld, | ||||||
|  | 				hitNormal: hitNormalWorld | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		#if js | 		#if js | ||||||
| 		bullet.Bt.Ammo.destroy(rayCallback); | 		bullet.Bt.Ammo.destroy(rayCallback); | ||||||
| 		#else | 		#else | ||||||
| @ -493,7 +522,7 @@ class PhysicsWorld extends Trait { | |||||||
| 			if (debugDrawMode == NoDebug) { | 			if (debugDrawMode == NoDebug) { | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 			initDebugDrawing(); | 			initDebugDrawing(debugDrawMode); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		#if js | 		#if js | ||||||
| @ -517,8 +546,8 @@ class PhysicsWorld extends Trait { | |||||||
| 		#end | 		#end | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function initDebugDrawing() { | 	function initDebugDrawing(debugDrawMode: DebugDrawMode) { | ||||||
| 		debugDrawHelper = new DebugDrawHelper(this); | 		debugDrawHelper = new DebugDrawHelper(this, debugDrawMode); | ||||||
|  |  | ||||||
| 		#if js | 		#if js | ||||||
| 			final drawer = new bullet.Bt.DebugDrawer(); | 			final drawer = new bullet.Bt.DebugDrawer(); | ||||||
| @ -644,10 +673,7 @@ enum abstract DebugDrawMode(Int) from Int to Int { | |||||||
| 	// We could use it in the future to toggle depth testing for lines, i.e. draw actual 3D lines if not set and Kha's g2 lines if set. | 	// We could use it in the future to toggle depth testing for lines, i.e. draw actual 3D lines if not set and Kha's g2 lines if set. | ||||||
| 	var FastWireframe = 1 << 13; | 	var FastWireframe = 1 << 13; | ||||||
|  |  | ||||||
| 	/** | 	/** Draw the normal vectors of the triangles of the physics collider meshes. **/ | ||||||
| 		Draw the normal vectors of the triangles of the physics collider meshes. |  | ||||||
| 		This only works for `Mesh` collision shapes. |  | ||||||
| 	**/ |  | ||||||
| 	// Outside of Leenkx this works for a few more collision shapes | 	// Outside of Leenkx this works for a few more collision shapes | ||||||
| 	var DrawNormals = 1 << 14; | 	var DrawNormals = 1 << 14; | ||||||
|  |  | ||||||
| @ -657,6 +683,8 @@ enum abstract DebugDrawMode(Int) from Int to Int { | |||||||
| 	 **/ | 	 **/ | ||||||
| 	var DrawFrames = 1 << 15; | 	var DrawFrames = 1 << 15; | ||||||
|  |  | ||||||
|  | 	var DrawRayCast = 1 << 16; | ||||||
|  |  | ||||||
| 	@:op(~A) public inline function bitwiseNegate(): DebugDrawMode { | 	@:op(~A) public inline function bitwiseNegate(): DebugDrawMode { | ||||||
| 		return ~this; | 		return ~this; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -1,8 +1,5 @@ | |||||||
| package zui; | package zui; | ||||||
|  |  | ||||||
| // Immediate Mode UI Library |  | ||||||
| // https://github.com/leenkx3d/zui |  | ||||||
|  |  | ||||||
| import kha.input.Mouse; | import kha.input.Mouse; | ||||||
| import kha.input.Pen; | import kha.input.Pen; | ||||||
| import kha.input.Surface; | import kha.input.Surface; | ||||||
| @ -255,7 +252,7 @@ class Zui { | |||||||
| 		Mouse.get().notifyWindowed(ops.khaWindowId, onMouseDown, onMouseUp, onMouseMove, onMouseWheel); | 		Mouse.get().notifyWindowed(ops.khaWindowId, onMouseDown, onMouseUp, onMouseMove, onMouseWheel); | ||||||
| 		if (Pen.get() != null) Pen.get().notify(onPenDown, onPenUp, onPenMove); | 		if (Pen.get() != null) Pen.get().notify(onPenDown, onPenUp, onPenMove); | ||||||
| 		Keyboard.get().notify(onKeyDown, onKeyUp, onKeyPress); | 		Keyboard.get().notify(onKeyDown, onKeyUp, onKeyPress); | ||||||
| 		#if (kha_android || kha_ios) | 		#if (kha_android || kha_ios || kha_html5 || kha_debug_html5) | ||||||
| 		if (Surface.get() != null) Surface.get().notify(onTouchDown, onTouchUp, onTouchMove); | 		if (Surface.get() != null) Surface.get().notify(onTouchDown, onTouchUp, onTouchMove); | ||||||
| 		#end | 		#end | ||||||
| 		// Reset mouse delta on foreground | 		// Reset mouse delta on foreground | ||||||
| @ -268,7 +265,7 @@ class Zui { | |||||||
| 		Mouse.get().removeWindowed(ops.khaWindowId, onMouseDown, onMouseUp, onMouseMove, onMouseWheel); | 		Mouse.get().removeWindowed(ops.khaWindowId, onMouseDown, onMouseUp, onMouseMove, onMouseWheel); | ||||||
| 		if (Pen.get() != null) Pen.get().remove(onPenDown, onPenUp, onPenMove); | 		if (Pen.get() != null) Pen.get().remove(onPenDown, onPenUp, onPenMove); | ||||||
| 		Keyboard.get().remove(onKeyDown, onKeyUp, onKeyPress); | 		Keyboard.get().remove(onKeyDown, onKeyUp, onKeyPress); | ||||||
| 		#if (kha_android || kha_ios) | 		#if (kha_android || kha_ios || kha_html5 || kha_debug_html5) | ||||||
| 		if (Surface.get() != null) Surface.get().remove(onTouchDown, onTouchUp, onTouchMove); | 		if (Surface.get() != null) Surface.get().remove(onTouchDown, onTouchUp, onTouchMove); | ||||||
| 		#end | 		#end | ||||||
| 		endInput(); | 		endInput(); | ||||||
| @ -1760,7 +1757,7 @@ class Zui { | |||||||
| 		button == 0 ? inputStarted = true : inputStartedR = true; | 		button == 0 ? inputStarted = true : inputStartedR = true; | ||||||
| 		button == 0 ? inputDown = true : inputDownR = true; | 		button == 0 ? inputDown = true : inputDownR = true; | ||||||
| 		inputStartedTime = kha.Scheduler.time(); | 		inputStartedTime = kha.Scheduler.time(); | ||||||
| 		#if (kha_android || kha_ios) | 		#if (kha_android || kha_ios || kha_html5 || kha_debug_html5) | ||||||
| 		setInputPosition(x, y); | 		setInputPosition(x, y); | ||||||
| 		#end | 		#end | ||||||
| 		inputStartedX = x; | 		inputStartedX = x; | ||||||
| @ -1787,7 +1784,7 @@ class Zui { | |||||||
| 			button == 0 ? inputReleased = true : inputReleasedR = true; | 			button == 0 ? inputReleased = true : inputReleasedR = true; | ||||||
| 		} | 		} | ||||||
| 		button == 0 ? inputDown = false : inputDownR = false; | 		button == 0 ? inputDown = false : inputDownR = false; | ||||||
| 		#if (kha_android || kha_ios) | 		#if (kha_android || kha_ios || kha_html5 || kha_debug_html5) | ||||||
| 		setInputPosition(x, y); | 		setInputPosition(x, y); | ||||||
| 		#end | 		#end | ||||||
| 		deselectText(); | 		deselectText(); | ||||||
| @ -1811,7 +1808,7 @@ class Zui { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public function onPenDown(x: Int, y: Int, pressure: Float) { | 	public function onPenDown(x: Int, y: Int, pressure: Float) { | ||||||
| 		#if (kha_android || kha_ios) | 		#if (kha_android || kha_ios || kha_html5 || kha_debug_html5) | ||||||
| 		return; | 		return; | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| @ -1819,7 +1816,7 @@ class Zui { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public function onPenUp(x: Int, y: Int, pressure: Float) { | 	public function onPenUp(x: Int, y: Int, pressure: Float) { | ||||||
| 		#if (kha_android || kha_ios) | 		#if (kha_android || kha_ios || kha_html5 || kha_debug_html5) | ||||||
| 		return; | 		return; | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| @ -1829,7 +1826,7 @@ class Zui { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public function onPenMove(x: Int, y: Int, pressure: Float) { | 	public function onPenMove(x: Int, y: Int, pressure: Float) { | ||||||
| 		#if (kha_android || kha_ios) | 		#if (kha_android || kha_ios || kha_html5 || kha_debug_html5) | ||||||
| 		return; | 		return; | ||||||
| 		#end | 		#end | ||||||
|  |  | ||||||
| @ -1889,7 +1886,7 @@ class Zui { | |||||||
| 		isKeyPressed = true; | 		isKeyPressed = true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	#if (kha_android || kha_ios) | 	#if (kha_android || kha_ios || kha_html5 || kha_debug_html5) | ||||||
| 	public function onTouchDown(index: Int, x: Int, y: Int) { | 	public function onTouchDown(index: Int, x: Int, y: Int) { | ||||||
| 		// Reset movement delta on touch start | 		// Reset movement delta on touch start | ||||||
| 		if (index == 0) { | 		if (index == 0) { | ||||||
|  | |||||||
| @ -324,6 +324,20 @@ class LeenkxExporter: | |||||||
|     def export_object_transform(self, bobject: bpy.types.Object, o): |     def export_object_transform(self, bobject: bpy.types.Object, o): | ||||||
|         wrd = bpy.data.worlds['Lnx'] |         wrd = bpy.data.worlds['Lnx'] | ||||||
|  |  | ||||||
|  |         # HACK: In Blender 4.2.x, each camera must be selected to ensure its matrix is correctly assigned | ||||||
|  |         if bpy.app.version >= (4, 2, 0) and bobject.type == 'CAMERA' and bobject.users_scene: | ||||||
|  |             current_scene = bpy.context.window.scene | ||||||
|  |  | ||||||
|  |             bpy.context.window.scene = bobject.users_scene[0] | ||||||
|  |             bpy.context.view_layer.update() | ||||||
|  |  | ||||||
|  |             bobject.select_set(True) | ||||||
|  |             bpy.context.view_layer.update() | ||||||
|  |             bobject.select_set(False) | ||||||
|  |  | ||||||
|  |             bpy.context.window.scene = current_scene | ||||||
|  |             bpy.context.view_layer.update() | ||||||
|  |  | ||||||
|         # Static transform |         # Static transform | ||||||
|         o['transform'] = {'values': LeenkxExporter.write_matrix(bobject.matrix_local)} |         o['transform'] = {'values': LeenkxExporter.write_matrix(bobject.matrix_local)} | ||||||
|  |  | ||||||
| @ -1001,6 +1015,7 @@ class LeenkxExporter: | |||||||
|                     action = actions.get('leenkxpose') |                     action = actions.get('leenkxpose') | ||||||
|                     if action is None: |                     if action is None: | ||||||
|                         action = actions.new(name='leenkxpose') |                         action = actions.new(name='leenkxpose') | ||||||
|  |                     adata.action = action | ||||||
|                      |                      | ||||||
|                 # Export actions |                 # Export actions | ||||||
|                 export_actions = [action] |                 export_actions = [action] | ||||||
| @ -1551,8 +1566,7 @@ class LeenkxExporter: | |||||||
|                         log.error(e.message) |                         log.error(e.message) | ||||||
|                     else: |                     else: | ||||||
|                         # Assume it was caused because of encountering n-gons |                         # Assume it was caused because of encountering n-gons | ||||||
|                         log.error(f"""object {bobject.name} contains n-gons in its mesh, so it's impossible to compute tanget space for normal mapping. |                         log.error(f"""object {bobject.name} contains n-gons in its mesh, so it's impossible to compute tanget space for normal mapping. Make sure the mesh only has tris/quads.""") | ||||||
| Make sure the mesh only has tris/quads.""") |  | ||||||
|  |  | ||||||
|                 tangdata = np.empty(num_verts * 3, dtype='<f4') |                 tangdata = np.empty(num_verts * 3, dtype='<f4') | ||||||
|         if has_col: |         if has_col: | ||||||
| @ -3025,14 +3039,15 @@ Make sure the mesh only has tris/quads.""") | |||||||
|             if rbw is not None and rbw.enabled: |             if rbw is not None and rbw.enabled: | ||||||
|                 out_trait['parameters'] = [str(rbw.time_scale), str(rbw.substeps_per_frame), str(rbw.solver_iterations)] |                 out_trait['parameters'] = [str(rbw.time_scale), str(rbw.substeps_per_frame), str(rbw.solver_iterations)] | ||||||
|  |  | ||||||
|                 if phys_pkg == 'bullet': |                 if phys_pkg == 'bullet' or phys_pkg == 'oimo': | ||||||
|                     debug_draw_mode = 1 if wrd.lnx_bullet_dbg_draw_wireframe else 0 |                     debug_draw_mode = 1 if wrd.lnx_physics_dbg_draw_wireframe else 0 | ||||||
|                     debug_draw_mode |= 2 if wrd.lnx_bullet_dbg_draw_aabb else 0 |                     debug_draw_mode |= 2 if wrd.lnx_physics_dbg_draw_aabb else 0 | ||||||
|                     debug_draw_mode |= 8 if wrd.lnx_bullet_dbg_draw_contact_points else 0 |                     debug_draw_mode |= 8 if wrd.lnx_physics_dbg_draw_contact_points else 0 | ||||||
|                     debug_draw_mode |= 2048 if wrd.lnx_bullet_dbg_draw_constraints else 0 |                     debug_draw_mode |= 2048 if wrd.lnx_physics_dbg_draw_constraints else 0 | ||||||
|                     debug_draw_mode |= 4096 if wrd.lnx_bullet_dbg_draw_constraint_limits else 0 |                     debug_draw_mode |= 4096 if wrd.lnx_physics_dbg_draw_constraint_limits else 0 | ||||||
|                     debug_draw_mode |= 16384 if wrd.lnx_bullet_dbg_draw_normals else 0 |                     debug_draw_mode |= 16384 if wrd.lnx_physics_dbg_draw_normals else 0 | ||||||
|                     debug_draw_mode |= 32768 if wrd.lnx_bullet_dbg_draw_axis_gizmo else 0 |                     debug_draw_mode |= 32768 if wrd.lnx_physics_dbg_draw_axis_gizmo else 0 | ||||||
|  |                     debug_draw_mode |= 65536 if wrd.lnx_physics_dbg_draw_raycast else 0 | ||||||
|                     out_trait['parameters'].append(str(debug_draw_mode)) |                     out_trait['parameters'].append(str(debug_draw_mode)) | ||||||
|  |  | ||||||
|             self.output['traits'].append(out_trait) |             self.output['traits'].append(out_trait) | ||||||
|  | |||||||
| @ -132,6 +132,7 @@ def always() -> float: | |||||||
|     return 0.5 |     return 0.5 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def poll_threads() -> float: | def poll_threads() -> float: | ||||||
|     """Polls the thread callback queue and if a thread has finished, it |     """Polls the thread callback queue and if a thread has finished, it | ||||||
|     is joined with the main thread and the corresponding callback is |     is joined with the main thread and the corresponding callback is | ||||||
| @ -141,21 +142,27 @@ def poll_threads() -> float: | |||||||
|         thread, callback = make.thread_callback_queue.get(block=False) |         thread, callback = make.thread_callback_queue.get(block=False) | ||||||
|     except queue.Empty: |     except queue.Empty: | ||||||
|         return 0.25 |         return 0.25 | ||||||
|  |     if thread.is_alive(): | ||||||
|     thread.join() |         try: | ||||||
|  |             make.thread_callback_queue.put((thread, callback), block=False) | ||||||
|     try: |         except queue.Full: | ||||||
|         callback() |             return 0.5 | ||||||
|     except Exception as e: |         return 0.1  | ||||||
|         # If there is an exception, we can no longer return the time to |     else: | ||||||
|         # the next call to this polling function, so to keep it running |         try: | ||||||
|         # we re-register it and then raise the original exception. |             thread.join() | ||||||
|         bpy.app.timers.unregister(poll_threads) |             callback() | ||||||
|         bpy.app.timers.register(poll_threads, first_interval=0.01, persistent=True) |         except Exception as e: | ||||||
|         raise e |             # If there is an exception, we can no longer return the time to | ||||||
|  |             # the next call to this polling function, so to keep it running | ||||||
|     # Quickly check if another thread has finished |             # we re-register it and then raise the original exception. | ||||||
|     return 0.01 |             try: | ||||||
|  |                 bpy.app.timers.unregister(poll_threads) | ||||||
|  |             except ValueError: | ||||||
|  |                 pass | ||||||
|  |             bpy.app.timers.register(poll_threads, first_interval=0.01, persistent=True) | ||||||
|  |         # Quickly check if another thread has finished | ||||||
|  |         return 0.01 | ||||||
|  |  | ||||||
|  |  | ||||||
| loaded_py_libraries: dict[str, types.ModuleType] = {} | loaded_py_libraries: dict[str, types.ModuleType] = {} | ||||||
|  | |||||||
| @ -7,48 +7,46 @@ if lnx.is_reload(__name__): | |||||||
| else: | else: | ||||||
|     lnx.enable_reload(__name__) |     lnx.enable_reload(__name__) | ||||||
|  |  | ||||||
| lnx.keymaps = [] | #lnx.keymaps = [] | ||||||
|  |  | ||||||
|  |  | ||||||
| def register(): | def register(): | ||||||
|     wm = bpy.context.window_manager |     wm = bpy.context.window_manager | ||||||
|     addon_keyconfig = wm.keyconfigs.addon |     keyconfig = wm.keyconfigs.user | ||||||
|      |      | ||||||
|     # Keyconfigs are not available in background mode. If the keyconfig |     # Keyconfigs are not available in background mode. If the keyconfig | ||||||
|     # was not found despite running _not_ in background mode, a warning |     # was not found despite running _not_ in background mode, a warning | ||||||
|     # is printed |     # is printed | ||||||
|     if addon_keyconfig is None: |     if keyconfig is None: | ||||||
|         if not bpy.app.background: |         if not bpy.app.background: | ||||||
|             log.warn("No keyconfig path found") |             log.warn("No keyconfig path found") | ||||||
|         return |         return | ||||||
|  |     km = keyconfig.keymaps.get('Window') | ||||||
|     km = addon_keyconfig.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW") |     if km is None: | ||||||
|     km.keymap_items.new(props_ui.LeenkxPlayButton.bl_idname, type='F5', value='PRESS') |         log.warn("Window keymaps not available") | ||||||
|     km.keymap_items.new("tlm.build_lightmaps", type='F6', value='PRESS') |         return | ||||||
|     km.keymap_items.new("tlm.clean_lightmaps", type='F7', value='PRESS') |     lnx_start = any(kmi.idname == props_ui.LeenkxPlayButton.bl_idname for kmi in km.keymap_items) | ||||||
|     lnx.keymaps.append(km) |     if not lnx_start: | ||||||
|  |         kmw = keyconfig.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW") | ||||||
|     km = addon_keyconfig.keymaps.new(name='Node Editor', space_type='NODE_EDITOR') |         kmw.keymap_items.new(props_ui.LeenkxPlayButton.bl_idname, type='F5', value='PRESS') | ||||||
|  |         kmw.keymap_items.new('tlm.build_lightmaps', type='F6', value='PRESS') | ||||||
|     # shift+G: Create a new node call group node |         kmw.keymap_items.new('tlm.clean_lightmaps', type='F7', value='PRESS') | ||||||
|     km.keymap_items.new('lnx.add_call_group_node', 'G', 'PRESS', shift=True) |         kmn = keyconfig.keymaps.new(name='Node Editor', space_type='NODE_EDITOR') | ||||||
|  |         kmn.keymap_items.new('lnx.add_call_group_node', 'G', 'PRESS', shift=True) | ||||||
|     # ctrl+G: make node group from selected |         kmn.keymap_items.new('lnx.add_group_tree_from_selected', 'G', 'PRESS', ctrl=True) | ||||||
|     km.keymap_items.new('lnx.add_group_tree_from_selected', 'G', 'PRESS', ctrl=True) |         kmn.keymap_items.new('lnx.edit_group_tree', 'TAB', 'PRESS') | ||||||
|  |         kmn.keymap_items.new('node.tree_path_parent', 'TAB', 'PRESS', ctrl=True) | ||||||
|     # TAB: enter node groups depending on selection |         kmn.keymap_items.new('lnx.ungroup_group_tree', 'G', 'PRESS', alt=True) | ||||||
|     km.keymap_items.new('lnx.edit_group_tree', 'TAB', 'PRESS') |  | ||||||
|  |  | ||||||
|     # ctrl+TAB: exit node groups depending on selectio |  | ||||||
|     km.keymap_items.new('node.tree_path_parent', 'TAB', 'PRESS', ctrl=True) |  | ||||||
|  |  | ||||||
|     # alt+G: ungroup node tree |  | ||||||
|     km.keymap_items.new('lnx.ungroup_group_tree', 'G', 'PRESS', alt=True) |  | ||||||
|     lnx.keymaps.append(km) |  | ||||||
|          |          | ||||||
|  |  | ||||||
| def unregister(): | def unregister(): | ||||||
|     wm = bpy.context.window_manager |     kmw = bpy.context.window_manager.keyconfigs.user.keymaps.get('Window') | ||||||
|     for km in lnx.keymaps: |     kmw.keymap_items.remove(kmw.keymap_items[props_ui.LeenkxPlayButton.bl_idname]) | ||||||
|         wm.keyconfigs.addon.keymaps.remove(km) |     kmw.keymap_items.remove(kmw.keymap_items['tlm.build_lightmaps']) | ||||||
|     del lnx.keymaps[:] |     kmw.keymap_items.remove(kmw.keymap_items['tlm.clean_lightmaps']) | ||||||
|  |     kmn = bpy.context.window_manager.keyconfigs.user.keymaps.get('Node Editor') | ||||||
|  |     kmn.keymap_items.remove(kmn.keymap_items['lnx.add_call_group_node']) | ||||||
|  |     kmn.keymap_items.remove(kmn.keymap_items['lnx.add_group_tree_from_selected']) | ||||||
|  |     kmn.keymap_items.remove(kmn.keymap_items['lnx.edit_group_tree']) | ||||||
|  |     kmn.keymap_items.remove(kmn.keymap_items['node.tree_path_parent']) | ||||||
|  |     kmn.keymap_items.remove(kmn.keymap_items['lnx.ungroup_group_tree']) | ||||||
|  | |||||||
| @ -5,7 +5,8 @@ class TLM_Logman: | |||||||
|  |  | ||||||
|     _log = [] |     _log = [] | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|  |         super(TLM_Logman, self).__init__(*args, **kwargs) | ||||||
|         print("Logger started Init") |         print("Logger started Init") | ||||||
|         self.append("Logger started.") |         self.append("Logger started.") | ||||||
|  |  | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ class BlendActionNode(LnxLogicTreeNode): | |||||||
|         self.add_input('LnxNodeSocketObject', 'Object') |         self.add_input('LnxNodeSocketObject', 'Object') | ||||||
|         self.add_input('LnxNodeSocketAnimTree', 'Action 1') |         self.add_input('LnxNodeSocketAnimTree', 'Action 1') | ||||||
|         self.add_input('LnxNodeSocketAnimTree', 'Action 2') |         self.add_input('LnxNodeSocketAnimTree', 'Action 2') | ||||||
|         self.add_input('ArmFactorSocket', 'Factor', default_value = 0.5) |         self.add_input('LnxFactorSocket', 'Factor', default_value = 0.5) | ||||||
|         self.add_input('LnxIntSocket', 'Bone Group', default_value = -1) |         self.add_input('LnxIntSocket', 'Bone Group', default_value = -1) | ||||||
|  |  | ||||||
|         self.add_output('LnxNodeSocketAnimTree', 'Result') |         self.add_output('LnxNodeSocketAnimTree', 'Result') | ||||||
|  | |||||||
| @ -90,7 +90,8 @@ class BlendSpaceNode(LnxLogicTreeNode): | |||||||
|     draw_handler_dict = {} |     draw_handler_dict = {} | ||||||
|     modal_handler_dict = {} |     modal_handler_dict = {} | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|  |         super(BlendSpaceNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[str(id(self))] = self |         array_nodes[str(id(self))] = self | ||||||
|         if self.advanced_draw_run: |         if self.advanced_draw_run: | ||||||
|             self.add_advanced_draw() |             self.add_advanced_draw() | ||||||
| @ -112,8 +113,8 @@ class BlendSpaceNode(LnxLogicTreeNode): | |||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|         self.add_input('LnxNodeSocketObject', 'Object') |         self.add_input('LnxNodeSocketObject', 'Object') | ||||||
|         self.add_input('LnxNodeSocketArray', 'Actions') |         self.add_input('LnxNodeSocketArray', 'Actions') | ||||||
|         self.add_input('ArmBlendSpaceSocket', 'Cursor X') |         self.add_input('LnxBlendSpaceSocket', 'Cursor X') | ||||||
|         self.add_input('ArmBlendSpaceSocket', 'Cursor Y') |         self.add_input('LnxBlendSpaceSocket', 'Cursor Y') | ||||||
|         self.add_output('LnxNodeSocketAnimTree', 'Out') |         self.add_output('LnxNodeSocketAnimTree', 'Out') | ||||||
|  |  | ||||||
|     def add_advanced_draw(self): |     def add_advanced_draw(self): | ||||||
|  | |||||||
| @ -45,7 +45,7 @@ class BoneIKNode(LnxLogicTreeNode): | |||||||
|         self.add_input('LnxBoolSocket', 'Enable Pole') |         self.add_input('LnxBoolSocket', 'Enable Pole') | ||||||
|         self.add_input('LnxVectorSocket', 'Pole Position') |         self.add_input('LnxVectorSocket', 'Pole Position') | ||||||
|         self.add_input('LnxFloatSocket', 'Roll Angle') |         self.add_input('LnxFloatSocket', 'Roll Angle') | ||||||
|         self.add_input('ArmFactorSocket', 'Influence', default_value = 1.0) |         self.add_input('LnxFactorSocket', 'Influence', default_value = 1.0) | ||||||
|         self.add_input('LnxIntSocket', 'Bone Group', default_value = 0) |         self.add_input('LnxIntSocket', 'Bone Group', default_value = 0) | ||||||
|  |  | ||||||
|         self.add_output('LnxNodeSocketAnimTree', 'Result') |         self.add_output('LnxNodeSocketAnimTree', 'Result') | ||||||
|  | |||||||
| @ -8,8 +8,8 @@ class OneShotActionMultiNode(LnxLogicTreeNode): | |||||||
|     lnx_version = 1 |     lnx_version = 1 | ||||||
|     min_inputs = 10 |     min_inputs = 10 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(OneShotActionMultiNode, self).__init__() |         super(OneShotActionMultiNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[self.get_id_str()] = self |         array_nodes[self.get_id_str()] = self | ||||||
|  |  | ||||||
|     property0: HaxeStringProperty('property0', name = 'Action ID', default = '') |     property0: HaxeStringProperty('property0', name = 'Action ID', default = '') | ||||||
|  | |||||||
| @ -0,0 +1,16 @@ | |||||||
|  | from lnx.logicnode.lnx_nodes import * | ||||||
|  |  | ||||||
|  | class SetBoneTransformNode(LnxLogicTreeNode): | ||||||
|  |     """Sets the bones transform in world space.""" | ||||||
|  |     bl_idname = 'LNSetBoneTransformNode' | ||||||
|  |     bl_label = 'Set Bone Transform' | ||||||
|  |     lnx_version = 1 | ||||||
|  |     lnx_section = 'armature' | ||||||
|  |  | ||||||
|  |     def lnx_init(self, context): | ||||||
|  |         self.add_input('LnxNodeSocketAction', 'In') | ||||||
|  |         self.add_input('LnxNodeSocketObject', 'Object') | ||||||
|  |         self.add_input('LnxStringSocket', 'Bone') | ||||||
|  |         self.add_input('LnxDynamicSocket', 'Transform') | ||||||
|  |  | ||||||
|  |         self.add_output('LnxNodeSocketAction', 'Out') | ||||||
| @ -12,5 +12,7 @@ class SetParentBoneNode(LnxLogicTreeNode): | |||||||
|         self.add_input('LnxNodeSocketObject', 'Object') |         self.add_input('LnxNodeSocketObject', 'Object') | ||||||
|         self.add_input('LnxNodeSocketObject', 'Parent') |         self.add_input('LnxNodeSocketObject', 'Parent') | ||||||
|         self.add_input('LnxStringSocket', 'Bone', default_value='Bone') |         self.add_input('LnxStringSocket', 'Bone', default_value='Bone') | ||||||
|  |         self.add_input('LnxBoolSocket', 'Set Inverse') | ||||||
|  |         self.add_input('LnxBoolSocket', 'Keep Transform') | ||||||
|                |                | ||||||
|         self.add_output('LnxNodeSocketAction', 'Out') |         self.add_output('LnxNodeSocketAction', 'Out') | ||||||
|  | |||||||
| @ -7,8 +7,8 @@ class SwitchActionMultiNode(LnxLogicTreeNode): | |||||||
|     lnx_version = 1 |     lnx_version = 1 | ||||||
|     min_inputs = 8 |     min_inputs = 8 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(SwitchActionMultiNode, self).__init__() |         super(SwitchActionMultiNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[self.get_id_str()] = self |         array_nodes[self.get_id_str()] = self | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,7 +9,8 @@ class ArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode): | |||||||
|     lnx_section = 'variable' |     lnx_section = 'variable' | ||||||
|     min_inputs = 0 |     min_inputs = 0 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|  |         super(ArrayNode, self).__init__(*args, **kwargs) | ||||||
|         self.register_id() |         self.register_id() | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -12,8 +12,8 @@ class ArrayAddNode(LnxLogicTreeNode): | |||||||
|     lnx_version = 5 |     lnx_version = 5 | ||||||
|     min_inputs = 6 |     min_inputs = 6 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(ArrayAddNode, self).__init__() |         super(ArrayAddNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[self.get_id_str()] = self |         array_nodes[self.get_id_str()] = self | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,8 +9,8 @@ class BooleanArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode): | |||||||
|     lnx_section = 'variable' |     lnx_section = 'variable' | ||||||
|     min_inputs = 0 |     min_inputs = 0 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(BooleanArrayNode, self).__init__() |         super(BooleanArrayNode, self).__init__(*args, **kwargs) | ||||||
|         self.register_id() |         self.register_id() | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,8 +9,8 @@ class ColorArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode): | |||||||
|     lnx_section = 'variable' |     lnx_section = 'variable' | ||||||
|     min_inputs = 0 |     min_inputs = 0 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(ColorArrayNode, self).__init__() |         super(ColorArrayNode, self).__init__(*args, **kwargs) | ||||||
|         self.register_id() |         self.register_id() | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,8 +9,8 @@ class FloatArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode): | |||||||
|     lnx_section = 'variable' |     lnx_section = 'variable' | ||||||
|     min_inputs = 0 |     min_inputs = 0 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(FloatArrayNode, self).__init__() |         super(FloatArrayNode, self).__init__(*args, **kwargs) | ||||||
|         self.register_id() |         self.register_id() | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
							
								
								
									
										13
									
								
								leenkx/blender/lnx/logicnode/array/LN_array_index_list.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,13 @@ | |||||||
|  | from lnx.logicnode.lnx_nodes import * | ||||||
|  |  | ||||||
|  | class ArrayIndexNode(LnxLogicTreeNode): | ||||||
|  |     """Returns the array index list of the given value as an array.""" | ||||||
|  |     bl_idname = 'LNArrayIndexListNode' | ||||||
|  |     bl_label = 'Array Index List' | ||||||
|  |     lnx_version = 1 | ||||||
|  |  | ||||||
|  |     def lnx_init(self, context): | ||||||
|  |         self.add_input('LnxNodeSocketArray', 'Array') | ||||||
|  |         self.add_input('LnxDynamicSocket', 'Value') | ||||||
|  |  | ||||||
|  |         self.add_output('LnxNodeSocketArray', 'Array') | ||||||
| @ -9,8 +9,8 @@ class IntegerArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode): | |||||||
|     lnx_section = 'variable' |     lnx_section = 'variable' | ||||||
|     min_inputs = 0 |     min_inputs = 0 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(IntegerArrayNode, self).__init__() |         super(IntegerArrayNode, self).__init__(*args, **kwargs) | ||||||
|         self.register_id() |         self.register_id() | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,8 +9,8 @@ class ObjectArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode): | |||||||
|     lnx_section = 'variable' |     lnx_section = 'variable' | ||||||
|     min_inputs = 0 |     min_inputs = 0 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(ObjectArrayNode, self).__init__() |         super(ObjectArrayNode, self).__init__(*args, **kwargs) | ||||||
|         self.register_id() |         self.register_id() | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -8,7 +8,8 @@ class ArrayRemoveValueNode(LnxLogicTreeNode): | |||||||
|     bl_label = 'Array Remove by Value' |     bl_label = 'Array Remove by Value' | ||||||
|     lnx_version = 1 |     lnx_version = 1 | ||||||
|  |  | ||||||
|     # def __init__(self): |     # def __init__(self, *args, **kwargs): | ||||||
|  |         # super(ArrayRemoveValueNode, self).__init__(*args, **kwargs) | ||||||
|         # array_nodes[str(id(self))] = self |         # array_nodes[str(id(self))] = self | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,8 +9,8 @@ class StringArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode): | |||||||
|     lnx_section = 'variable' |     lnx_section = 'variable' | ||||||
|     min_inputs = 0 |     min_inputs = 0 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(StringArrayNode, self).__init__() |         super(StringArrayNode, self).__init__(*args, **kwargs) | ||||||
|         self.register_id() |         self.register_id() | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,8 +9,9 @@ class VectorArrayNode(LnxLogicVariableNodeMixin, LnxLogicTreeNode): | |||||||
|     lnx_section = 'variable' |     lnx_section = 'variable' | ||||||
|     min_inputs = 0 |     min_inputs = 0 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(VectorArrayNode, self).__init__() |         super(VectorArrayNode, self).__init__(*args, **kwargs) | ||||||
|  |  | ||||||
|         self.register_id() |         self.register_id() | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,7 +9,8 @@ class AddTorrentNode(LnxLogicTreeNode): | |||||||
|     lnx_category = 'Leenkx' |     lnx_category = 'Leenkx' | ||||||
|     lnx_version = 1 |     lnx_version = 1 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|  |         super(AddTorrentNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[str(id(self))] = self |         array_nodes[str(id(self))] = self | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -17,8 +17,8 @@ class CallWASMNode(LnxLogicTreeNode): | |||||||
|         default=False, |         default=False, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(CallWASMNode, self).__init__() |         super(CallWASMNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[str(id(self))] = self |         array_nodes[str(id(self))] = self | ||||||
|          |          | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -406,8 +406,8 @@ class CreateStyleNode(LnxLogicTreeNode): | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|         super(CreateStyleNode, self).__init__() |         super(CreateStyleNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[str(id(self))] = self |         array_nodes[str(id(self))] = self | ||||||
|  |  | ||||||
|     def lnx_init(self, context): |     def lnx_init(self, context): | ||||||
|  | |||||||
| @ -9,7 +9,8 @@ class CreateTorrentNode(LnxLogicTreeNode): | |||||||
|     lnx_category = 'Leenkx' |     lnx_category = 'Leenkx' | ||||||
|     lnx_version = 1 |     lnx_version = 1 | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|  |         super(CreateTorrentNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[str(id(self))] = self |         array_nodes[str(id(self))] = self | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -88,7 +88,8 @@ class LeenkxEventNode(LnxLogicTreeNode): | |||||||
|         name='',  |         name='',  | ||||||
|         default='onopen') |         default='onopen') | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self, *args, **kwargs): | ||||||
|  |         super(LeenkxEventNode, self).__init__(*args, **kwargs) | ||||||
|         array_nodes[str(id(self))] = self |         array_nodes[str(id(self))] = self | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||