merge upstream
This commit is contained in:
		@ -3,6 +3,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "compiled.inc"
 | 
					#include "compiled.inc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _CPostprocess
 | 
				
			||||||
 | 
					uniform vec4 PPComp17;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uniform sampler2D tex;
 | 
					uniform sampler2D tex;
 | 
				
			||||||
uniform vec2 dir;
 | 
					uniform vec2 dir;
 | 
				
			||||||
uniform vec2 screenSize;
 | 
					uniform vec2 screenSize;
 | 
				
			||||||
@ -45,6 +49,12 @@ void main() {
 | 
				
			|||||||
		res += factor * col;
 | 
							res += factor * col;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#ifdef _CPostprocess
 | 
				
			||||||
 | 
							vec3 AirColor = vec3(PPComp17.x, PPComp17.y, PPComp17.z);
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
 | 
							vec3 AirColor = volumAirColor;
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	res /= sumfactor;
 | 
						res /= sumfactor;
 | 
				
			||||||
	fragColor = vec4(volumAirColor * res, 1.0);
 | 
						fragColor = vec4(AirColor * res, 1.0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,11 @@
 | 
				
			|||||||
				{
 | 
									{
 | 
				
			||||||
					"name": "screenSize",
 | 
										"name": "screenSize",
 | 
				
			||||||
					"link": "_screenSize"
 | 
										"link": "_screenSize"
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										"name": "PPComp17",
 | 
				
			||||||
 | 
										"link": "_PPComp17",
 | 
				
			||||||
 | 
										"ifdef": ["_CPostprocess"]
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			],
 | 
								],
 | 
				
			||||||
			"texture_params": [],
 | 
								"texture_params": [],
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@
 | 
				
			|||||||
uniform sampler2D tex;
 | 
					uniform sampler2D tex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _CPostprocess
 | 
					#ifdef _CPostprocess
 | 
				
			||||||
uniform vec3 PPComp13;
 | 
					uniform vec4 PPComp13;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
in vec2 texCoord;
 | 
					in vec2 texCoord;
 | 
				
			||||||
@ -43,13 +43,17 @@ void main() {
 | 
				
			|||||||
	#ifdef _CPostprocess
 | 
						#ifdef _CPostprocess
 | 
				
			||||||
		float max_distort = PPComp13.x;
 | 
							float max_distort = PPComp13.x;
 | 
				
			||||||
		int num_iter = int(PPComp13.y);
 | 
							int num_iter = int(PPComp13.y);
 | 
				
			||||||
 | 
							int CAType = int(PPComp13.z);
 | 
				
			||||||
 | 
							int on = int(PPComp13.w);
 | 
				
			||||||
	#else
 | 
						#else
 | 
				
			||||||
		float max_distort = compoChromaticStrength;
 | 
							float max_distort = compoChromaticStrength;
 | 
				
			||||||
		int num_iter = compoChromaticSamples;
 | 
							int num_iter = compoChromaticSamples;
 | 
				
			||||||
 | 
							int CAType = compoChromaticType;
 | 
				
			||||||
 | 
							int on = 1;
 | 
				
			||||||
	#endif
 | 
						#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Spectral
 | 
						// Spectral
 | 
				
			||||||
	if (compoChromaticType == 1) {
 | 
						if (CAType == 1) {
 | 
				
			||||||
		float reci_num_iter_f = 1.0 / float(num_iter);
 | 
							float reci_num_iter_f = 1.0 / float(num_iter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		vec2 resolution = vec2(1,1);
 | 
							vec2 resolution = vec2(1,1);
 | 
				
			||||||
@ -64,7 +68,7 @@ void main() {
 | 
				
			|||||||
			sumcol += w * texture(tex, barrelDistortion(uv, 0.6 * max_distort * t));
 | 
								sumcol += w * texture(tex, barrelDistortion(uv, 0.6 * max_distort * t));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fragColor = sumcol / sumw;
 | 
							if (on == 1) fragColor = sumcol / sumw; else fragColor = texture(tex, texCoord);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Simple
 | 
						// Simple
 | 
				
			||||||
@ -73,6 +77,7 @@ void main() {
 | 
				
			|||||||
		col.x = texture(tex, texCoord + ((vec2(0.0, 1.0) * max_distort) / vec2(1000.0))).x;
 | 
							col.x = texture(tex, texCoord + ((vec2(0.0, 1.0) * max_distort) / vec2(1000.0))).x;
 | 
				
			||||||
		col.y = texture(tex, texCoord + ((vec2(-0.85, -0.5) * max_distort) / vec2(1000.0))).y;
 | 
							col.y = texture(tex, texCoord + ((vec2(-0.85, -0.5) * max_distort) / vec2(1000.0))).y;
 | 
				
			||||||
		col.z = texture(tex, texCoord + ((vec2(0.85, -0.5) * max_distort) / vec2(1000.0))).z;
 | 
							col.z = texture(tex, texCoord + ((vec2(0.85, -0.5) * max_distort) / vec2(1000.0))).z;
 | 
				
			||||||
		fragColor = vec4(col.x, col.y, col.z, fragColor.w);
 | 
							if (on == 1) fragColor = vec4(col.x, col.y, col.z, fragColor.w); 
 | 
				
			||||||
 | 
							else fragColor = texture(tex, texCoord);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -62,8 +62,11 @@ uniform vec3 PPComp5;
 | 
				
			|||||||
uniform vec3 PPComp6;
 | 
					uniform vec3 PPComp6;
 | 
				
			||||||
uniform vec3 PPComp7;
 | 
					uniform vec3 PPComp7;
 | 
				
			||||||
uniform vec3 PPComp8;
 | 
					uniform vec3 PPComp8;
 | 
				
			||||||
 | 
					uniform vec3 PPComp11;
 | 
				
			||||||
uniform vec3 PPComp14;
 | 
					uniform vec3 PPComp14;
 | 
				
			||||||
uniform vec4 PPComp15;
 | 
					uniform vec4 PPComp15;
 | 
				
			||||||
 | 
					uniform vec4 PPComp16;
 | 
				
			||||||
 | 
					uniform vec4 PPComp18;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// #ifdef _CPos
 | 
					// #ifdef _CPos
 | 
				
			||||||
@ -106,6 +109,16 @@ in vec2 texCoord;
 | 
				
			|||||||
out vec4 fragColor;
 | 
					out vec4 fragColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _CFog
 | 
					#ifdef _CFog
 | 
				
			||||||
 | 
						#ifdef _CPostprocess
 | 
				
			||||||
 | 
							vec3 FogColor = vec3(PPComp18.x, PPComp18.y, PPComp18.z);
 | 
				
			||||||
 | 
							float FogAmountA = PPComp18.w;
 | 
				
			||||||
 | 
							float FogAmountB = PPComp11.z;
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
 | 
							vec3 FogColor = compoFogColor;
 | 
				
			||||||
 | 
							float FogAmountA = compoFogAmountA;
 | 
				
			||||||
 | 
							float FogAmountB = compoFogAmountB;
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
						
 | 
				
			||||||
// const vec3 compoFogColor = vec3(0.5, 0.6, 0.7);
 | 
					// const vec3 compoFogColor = vec3(0.5, 0.6, 0.7);
 | 
				
			||||||
// const float compoFogAmountA = 1.0; // b = 0.01
 | 
					// const float compoFogAmountA = 1.0; // b = 0.01
 | 
				
			||||||
// const float compoFogAmountB = 1.0; // c = 0.1
 | 
					// const float compoFogAmountB = 1.0; // c = 0.1
 | 
				
			||||||
@ -118,8 +131,8 @@ out vec4 fragColor;
 | 
				
			|||||||
// }
 | 
					// }
 | 
				
			||||||
vec3 applyFog(vec3 rgb, float distance) {
 | 
					vec3 applyFog(vec3 rgb, float distance) {
 | 
				
			||||||
	// float fogAmount = 1.0 - exp(-distance * compoFogAmountA);
 | 
						// float fogAmount = 1.0 - exp(-distance * compoFogAmountA);
 | 
				
			||||||
	float fogAmount = 1.0 - exp(-distance * (compoFogAmountA / 100));
 | 
						float fogAmount = 1.0 - exp(-distance * (FogAmountA / 100));
 | 
				
			||||||
	return mix(rgb, compoFogColor, fogAmount);
 | 
						return mix(rgb, FogColor, fogAmount);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -350,15 +363,21 @@ void main() {
 | 
				
			|||||||
#ifdef _CSharpen
 | 
					#ifdef _CSharpen
 | 
				
			||||||
	#ifdef _CPostprocess
 | 
						#ifdef _CPostprocess
 | 
				
			||||||
		float strengthSharpen = PPComp14.y;	
 | 
							float strengthSharpen = PPComp14.y;	
 | 
				
			||||||
 | 
							vec3 SharpenColor = vec3(PPComp16.x, PPComp16.y, PPComp16.z); 
 | 
				
			||||||
 | 
							float SharpenSize = PPComp16.w;
 | 
				
			||||||
	#else
 | 
						#else
 | 
				
			||||||
		float strengthSharpen = compoSharpenStrength;
 | 
							float strengthSharpen = compoSharpenStrength;
 | 
				
			||||||
 | 
							vec3 SharpenColor = compoSharpenColor;
 | 
				
			||||||
 | 
							float SharpenSize = compoSharpenSize;
 | 
				
			||||||
	#endif
 | 
						#endif
 | 
				
			||||||
	vec3 col1 = textureLod(tex, texCo + vec2(-texStep.x, -texStep.y) * 1.5, 0.0).rgb;
 | 
						vec3 col1 = textureLod(tex, texCo + vec2(-texStep.x, -texStep.y) * SharpenSize, 0.0).rgb;
 | 
				
			||||||
	vec3 col2 = textureLod(tex, texCo + vec2(texStep.x, -texStep.y) * 1.5, 0.0).rgb;
 | 
						vec3 col2 = textureLod(tex, texCo + vec2(texStep.x, -texStep.y) * SharpenSize, 0.0).rgb;
 | 
				
			||||||
	vec3 col3 = textureLod(tex, texCo + vec2(-texStep.x, texStep.y) * 1.5, 0.0).rgb;
 | 
						vec3 col3 = textureLod(tex, texCo + vec2(-texStep.x, texStep.y) * SharpenSize, 0.0).rgb;
 | 
				
			||||||
	vec3 col4 = textureLod(tex, texCo + vec2(texStep.x, texStep.y) * 1.5, 0.0).rgb;
 | 
						vec3 col4 = textureLod(tex, texCo + vec2(texStep.x, texStep.y) * SharpenSize, 0.0).rgb;
 | 
				
			||||||
	vec3 colavg = (col1 + col2 + col3 + col4) * 0.25;
 | 
						vec3 colavg = (col1 + col2 + col3 + col4) * 0.25;
 | 
				
			||||||
	fragColor.rgb += (fragColor.rgb - colavg) * strengthSharpen;
 | 
						
 | 
				
			||||||
 | 
						float edgeMagnitude = length(fragColor.rgb - colavg); 
 | 
				
			||||||
 | 
						fragColor.rgb = mix(fragColor.rgb, SharpenColor, min(edgeMagnitude * strengthSharpen * 2.0, 1.0));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _CFog
 | 
					#ifdef _CFog
 | 
				
			||||||
@ -407,16 +426,25 @@ void main() {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _CExposure
 | 
					#ifdef _CExposure
 | 
				
			||||||
 | 
						#ifdef _CPostprocess
 | 
				
			||||||
 | 
							fragColor.rgb+=fragColor.rgb*PPComp8.x;
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
		fragColor.rgb+= fragColor.rgb*compoExposureStrength;
 | 
							fragColor.rgb+= fragColor.rgb*compoExposureStrength;
 | 
				
			||||||
	#endif
 | 
						#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _CPostprocess
 | 
					#ifdef _CPostprocess
 | 
				
			||||||
	fragColor.rgb *= ComputeEV(0.0);
 | 
						fragColor.rgb *= ComputeEV(0.0);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _AutoExposure
 | 
					#ifdef _AutoExposure
 | 
				
			||||||
 | 
						#ifdef _CPostprocess
 | 
				
			||||||
 | 
							float AEStrength = PPComp8.y;
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
 | 
							float AEStrength = autoExposureStrength;
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
	float expo = 2.0 - clamp(length(textureLod(histogram, vec2(0.5, 0.5), 0).rgb), 0.0, 1.0);
 | 
						float expo = 2.0 - clamp(length(textureLod(histogram, vec2(0.5, 0.5), 0).rgb), 0.0, 1.0);
 | 
				
			||||||
	fragColor.rgb *= pow(expo, autoExposureStrength * 2.0);
 | 
						fragColor.rgb *= pow(expo, AEStrength * 2.0);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Clamp color to get rid of INF values that don't work for the tone mapping below
 | 
					// Clamp color to get rid of INF values that don't work for the tone mapping below
 | 
				
			||||||
 | 
				
			|||||||
@ -235,6 +235,16 @@
 | 
				
			|||||||
					"name": "PPComp15",
 | 
										"name": "PPComp15",
 | 
				
			||||||
					"link": "_PPComp15",
 | 
										"link": "_PPComp15",
 | 
				
			||||||
					"ifdef": ["_CPostprocess"]
 | 
										"ifdef": ["_CPostprocess"]
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										"name": "PPComp16",
 | 
				
			||||||
 | 
										"link": "_PPComp16",
 | 
				
			||||||
 | 
										"ifdef": ["_CPostprocess"]
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										"name": "PPComp18",
 | 
				
			||||||
 | 
										"link": "_PPComp18",
 | 
				
			||||||
 | 
										"ifdef": ["_CPostprocess"]
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			],
 | 
								],
 | 
				
			||||||
			"texture_params": [],
 | 
								"texture_params": [],
 | 
				
			||||||
 | 
				
			|||||||
@ -2,13 +2,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "compiled.inc"
 | 
					#include "compiled.inc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _CPostprocess
 | 
				
			||||||
 | 
					uniform vec3 PPComp8;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uniform sampler2D tex;
 | 
					uniform sampler2D tex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
in vec2 texCoord;
 | 
					in vec2 texCoord;
 | 
				
			||||||
out vec4 fragColor;
 | 
					out vec4 fragColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void main() {
 | 
					void main() {
 | 
				
			||||||
 | 
						#ifdef _CPostprocess
 | 
				
			||||||
 | 
							fragColor.a = 0.01 * PPComp8.z;
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
		fragColor.a = 0.01 * autoExposureSpeed;
 | 
							fragColor.a = 0.01 * autoExposureSpeed;
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fragColor.rgb = textureLod(tex, vec2(0.5, 0.5), 0.0).rgb +
 | 
						fragColor.rgb = textureLod(tex, vec2(0.5, 0.5), 0.0).rgb +
 | 
				
			||||||
					textureLod(tex, vec2(0.2, 0.2), 0.0).rgb +
 | 
										textureLod(tex, vec2(0.2, 0.2), 0.0).rgb +
 | 
				
			||||||
					textureLod(tex, vec2(0.8, 0.2), 0.0).rgb +
 | 
										textureLod(tex, vec2(0.8, 0.2), 0.0).rgb +
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,13 @@
 | 
				
			|||||||
			"blend_source": "source_alpha",
 | 
								"blend_source": "source_alpha",
 | 
				
			||||||
			"blend_destination": "inverse_source_alpha",
 | 
								"blend_destination": "inverse_source_alpha",
 | 
				
			||||||
			"blend_operation": "add",
 | 
								"blend_operation": "add",
 | 
				
			||||||
			"links": [],
 | 
								"links": [
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										"name": "PPComp8",
 | 
				
			||||||
 | 
										"link": "_PPComp8",
 | 
				
			||||||
 | 
										"ifdef": ["_CPostprocess"]
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
			"texture_params": [],
 | 
								"texture_params": [],
 | 
				
			||||||
			"vertex_shader": "../include/pass.vert.glsl",
 | 
								"vertex_shader": "../include/pass.vert.glsl",
 | 
				
			||||||
			"fragment_shader": "histogram_pass.frag.glsl"
 | 
								"fragment_shader": "histogram_pass.frag.glsl"
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,11 @@
 | 
				
			|||||||
#include "std/light_common.glsl"
 | 
					#include "std/light_common.glsl"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _CPostprocess
 | 
				
			||||||
 | 
					uniform vec3 PPComp11;
 | 
				
			||||||
 | 
					uniform vec4 PPComp17;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uniform sampler2D gbufferD;
 | 
					uniform sampler2D gbufferD;
 | 
				
			||||||
uniform sampler2D snoise;
 | 
					uniform sampler2D snoise;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -87,7 +92,13 @@ out float fragColor;
 | 
				
			|||||||
const float tScat = 0.08;
 | 
					const float tScat = 0.08;
 | 
				
			||||||
const float tAbs = 0.0;
 | 
					const float tAbs = 0.0;
 | 
				
			||||||
const float tExt = tScat + tAbs;
 | 
					const float tExt = tScat + tAbs;
 | 
				
			||||||
 | 
					#ifdef _CPostprocess
 | 
				
			||||||
 | 
						float stepLen = 1.0 / int(PPComp11.y);
 | 
				
			||||||
 | 
						float AirTurbidity = PPComp17.w;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
	const float stepLen = 1.0 / volumSteps;
 | 
						const float stepLen = 1.0 / volumSteps;
 | 
				
			||||||
 | 
						float AirTurbidity = volumAirTurbidity;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
const float lighting = 0.4;
 | 
					const float lighting = 0.4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatteredLightAmount, float stepLenWorld, vec3 viewVecNorm) {
 | 
					void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatteredLightAmount, float stepLenWorld, vec3 viewVecNorm) {
 | 
				
			||||||
@ -162,5 +173,5 @@ void main() {
 | 
				
			|||||||
		rayStep(curPos, curOpticalDepth, scatteredLightAmount, stepLenWorld, viewVecNorm);
 | 
							rayStep(curPos, curOpticalDepth, scatteredLightAmount, stepLenWorld, viewVecNorm);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fragColor = scatteredLightAmount * volumAirTurbidity;
 | 
						fragColor = scatteredLightAmount * AirTurbidity;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -140,6 +140,16 @@
 | 
				
			|||||||
					"link": "_biasLightWorldViewProjectionMatrixSpot3",
 | 
										"link": "_biasLightWorldViewProjectionMatrixSpot3",
 | 
				
			||||||
					"ifndef": ["_ShadowMapAtlas"],
 | 
										"ifndef": ["_ShadowMapAtlas"],
 | 
				
			||||||
					"ifdef": ["_Spot", "_ShadowMap"]
 | 
										"ifdef": ["_Spot", "_ShadowMap"]
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										"name": "PPComp11",
 | 
				
			||||||
 | 
										"link": "_PPComp11",
 | 
				
			||||||
 | 
										"ifdef": ["_CPostprocess"]
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										"name": "PPComp17",
 | 
				
			||||||
 | 
										"link": "_PPComp17",
 | 
				
			||||||
 | 
										"ifdef": ["_CPostprocess"]
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			],
 | 
								],
 | 
				
			||||||
			"texture_params": [],
 | 
								"texture_params": [],
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@ class App {
 | 
				
			|||||||
	static var traitInits: Array<Void->Void> = [];
 | 
						static var traitInits: Array<Void->Void> = [];
 | 
				
			||||||
	static var traitUpdates: Array<Void->Void> = [];
 | 
						static var traitUpdates: Array<Void->Void> = [];
 | 
				
			||||||
	static var traitLateUpdates: Array<Void->Void> = [];
 | 
						static var traitLateUpdates: Array<Void->Void> = [];
 | 
				
			||||||
 | 
						static var traitFixedUpdates: Array<Void->Void> = [];
 | 
				
			||||||
	static var traitRenders: Array<kha.graphics4.Graphics->Void> = [];
 | 
						static var traitRenders: Array<kha.graphics4.Graphics->Void> = [];
 | 
				
			||||||
	static var traitRenders2D: Array<kha.graphics2.Graphics->Void> = [];
 | 
						static var traitRenders2D: Array<kha.graphics2.Graphics->Void> = [];
 | 
				
			||||||
	public static var framebuffer: kha.Framebuffer;
 | 
						public static var framebuffer: kha.Framebuffer;
 | 
				
			||||||
@ -23,6 +24,8 @@ class App {
 | 
				
			|||||||
	public static var renderPathTime: Float;
 | 
						public static var renderPathTime: Float;
 | 
				
			||||||
	public static var endFrameCallbacks: Array<Void->Void> = [];
 | 
						public static var endFrameCallbacks: Array<Void->Void> = [];
 | 
				
			||||||
	#end
 | 
						#end
 | 
				
			||||||
 | 
						static var last = 0.0;
 | 
				
			||||||
 | 
						static var time = 0.0;
 | 
				
			||||||
	static var lastw = -1;
 | 
						static var lastw = -1;
 | 
				
			||||||
	static var lasth = -1;
 | 
						static var lasth = -1;
 | 
				
			||||||
	public static var onResize: Void->Void = null;
 | 
						public static var onResize: Void->Void = null;
 | 
				
			||||||
@ -34,13 +37,14 @@ class App {
 | 
				
			|||||||
	function new(done: Void->Void) {
 | 
						function new(done: Void->Void) {
 | 
				
			||||||
		done();
 | 
							done();
 | 
				
			||||||
		kha.System.notifyOnFrames(render);
 | 
							kha.System.notifyOnFrames(render);
 | 
				
			||||||
		kha.Scheduler.addTimeTask(update, 0, iron.system.Time.delta);
 | 
							kha.Scheduler.addTimeTask(update, 0, iron.system.Time.step);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static function reset() {
 | 
						public static function reset() {
 | 
				
			||||||
		traitInits = [];
 | 
							traitInits = [];
 | 
				
			||||||
		traitUpdates = [];
 | 
							traitUpdates = [];
 | 
				
			||||||
		traitLateUpdates = [];
 | 
							traitLateUpdates = [];
 | 
				
			||||||
 | 
							traitFixedUpdates = [];
 | 
				
			||||||
		traitRenders = [];
 | 
							traitRenders = [];
 | 
				
			||||||
		traitRenders2D = [];
 | 
							traitRenders2D = [];
 | 
				
			||||||
		if (onResets != null) for (f in onResets) f();
 | 
							if (onResets != null) for (f in onResets) f();
 | 
				
			||||||
@ -48,6 +52,8 @@ class App {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	static function update() {
 | 
						static function update() {
 | 
				
			||||||
		if (Scene.active == null || !Scene.active.ready) return;
 | 
							if (Scene.active == null || !Scene.active.ready) return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							iron.system.Time.update();
 | 
				
			||||||
		if (pauseUpdates) return;
 | 
							if (pauseUpdates) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		#if lnx_debug
 | 
							#if lnx_debug
 | 
				
			||||||
@ -56,6 +62,14 @@ class App {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		Scene.active.updateFrame();
 | 
							Scene.active.updateFrame();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							time += iron.system.Time.delta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while (time >= iron.system.Time.fixedStep) {
 | 
				
			||||||
 | 
								for (f in traitFixedUpdates) f();
 | 
				
			||||||
 | 
								time -= iron.system.Time.fixedStep;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var i = 0;
 | 
							var i = 0;
 | 
				
			||||||
		var l = traitUpdates.length;
 | 
							var l = traitUpdates.length;
 | 
				
			||||||
		while (i < l) {
 | 
							while (i < l) {
 | 
				
			||||||
@ -106,7 +120,7 @@ class App {
 | 
				
			|||||||
		var frame = frames[0];
 | 
							var frame = frames[0];
 | 
				
			||||||
		framebuffer = frame;
 | 
							framebuffer = frame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		iron.system.Time.update();
 | 
							iron.system.Time.render();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (Scene.active == null || !Scene.active.ready) {
 | 
							if (Scene.active == null || !Scene.active.ready) {
 | 
				
			||||||
			render2D(frame);
 | 
								render2D(frame);
 | 
				
			||||||
@ -172,6 +186,14 @@ class App {
 | 
				
			|||||||
		traitLateUpdates.remove(f);
 | 
							traitLateUpdates.remove(f);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static function notifyOnFixedUpdate(f: Void->Void) {
 | 
				
			||||||
 | 
							traitFixedUpdates.push(f);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static function removeFixedUpdate(f: Void->Void) {
 | 
				
			||||||
 | 
							traitFixedUpdates.remove(f);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static function notifyOnRender(f: kha.graphics4.Graphics->Void) {
 | 
						public static function notifyOnRender(f: kha.graphics4.Graphics->Void) {
 | 
				
			||||||
		traitRenders.push(f);
 | 
							traitRenders.push(f);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ class Trait {
 | 
				
			|||||||
	var _remove: Array<Void->Void> = null;
 | 
						var _remove: Array<Void->Void> = null;
 | 
				
			||||||
	var _update: Array<Void->Void> = null;
 | 
						var _update: Array<Void->Void> = null;
 | 
				
			||||||
	var _lateUpdate: Array<Void->Void> = null;
 | 
						var _lateUpdate: Array<Void->Void> = null;
 | 
				
			||||||
 | 
						var _fixedUpdate: Array<Void->Void> = null;
 | 
				
			||||||
	var _render: Array<kha.graphics4.Graphics->Void> = null;
 | 
						var _render: Array<kha.graphics4.Graphics->Void> = null;
 | 
				
			||||||
	var _render2D: Array<kha.graphics2.Graphics->Void> = null;
 | 
						var _render2D: Array<kha.graphics2.Graphics->Void> = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -87,6 +88,23 @@ class Trait {
 | 
				
			|||||||
		App.removeLateUpdate(f);
 | 
							App.removeLateUpdate(f);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					      Add fixed game logic handler.
 | 
				
			||||||
 | 
					    **/
 | 
				
			||||||
 | 
						public function notifyOnFixedUpdate(f: Void->Void) {
 | 
				
			||||||
 | 
							if (_fixedUpdate == null) _fixedUpdate = [];
 | 
				
			||||||
 | 
							_fixedUpdate.push(f);
 | 
				
			||||||
 | 
							App.notifyOnFixedUpdate(f);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					      Remove fixed game logic handler.
 | 
				
			||||||
 | 
					    **/
 | 
				
			||||||
 | 
						public function removeFixedUpdate(f: Void->Void) {
 | 
				
			||||||
 | 
							_fixedUpdate.remove(f);
 | 
				
			||||||
 | 
							App.removeFixedUpdate(f);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
      Add render handler.
 | 
					      Add render handler.
 | 
				
			||||||
    **/
 | 
					    **/
 | 
				
			||||||
 | 
				
			|||||||
@ -392,6 +392,8 @@ typedef TParticleData = {
 | 
				
			|||||||
#end
 | 
					#end
 | 
				
			||||||
	public var name: String;
 | 
						public var name: String;
 | 
				
			||||||
	public var type: Int; // 0 - Emitter, Hair
 | 
						public var type: Int; // 0 - Emitter, Hair
 | 
				
			||||||
 | 
						public var auto_start: Bool;
 | 
				
			||||||
 | 
						public var is_unique: Bool;
 | 
				
			||||||
	public var loop: Bool;
 | 
						public var loop: Bool;
 | 
				
			||||||
	public var count: Int;
 | 
						public var count: Int;
 | 
				
			||||||
	public var frame_start: FastFloat;
 | 
						public var frame_start: FastFloat;
 | 
				
			||||||
 | 
				
			|||||||
@ -159,9 +159,17 @@ class Animation {
 | 
				
			|||||||
			if(markerEvents.get(sampler) != null){
 | 
								if(markerEvents.get(sampler) != null){
 | 
				
			||||||
				for (i in 0...anim.marker_frames.length) {
 | 
									for (i in 0...anim.marker_frames.length) {
 | 
				
			||||||
					if (frameIndex == anim.marker_frames[i]) {
 | 
										if (frameIndex == anim.marker_frames[i]) {
 | 
				
			||||||
						var marketAct = markerEvents.get(sampler);
 | 
											var markerAct = markerEvents.get(sampler);
 | 
				
			||||||
						var ar = marketAct.get(anim.marker_names[i]);
 | 
											var ar = markerAct.get(anim.marker_names[i]);
 | 
				
			||||||
						if (ar != null) for (f in ar) f();
 | 
											if (ar != null) for (f in ar) f();
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											for (j in 0...(frameIndex - lastFrameIndex)) {
 | 
				
			||||||
 | 
												if (lastFrameIndex + j + 1 == anim.marker_frames[i]) {
 | 
				
			||||||
 | 
													var markerAct = markerEvents.get(sampler);
 | 
				
			||||||
 | 
													var ar = markerAct.get(anim.marker_names[i]);
 | 
				
			||||||
 | 
													if (ar != null) for (f in ar) f();
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				lastFrameIndex = frameIndex;
 | 
									lastFrameIndex = frameIndex;
 | 
				
			||||||
 | 
				
			|||||||
@ -172,6 +172,10 @@ class Object {
 | 
				
			|||||||
			for (f in t._init) App.removeInit(f);
 | 
								for (f in t._init) App.removeInit(f);
 | 
				
			||||||
			t._init = null;
 | 
								t._init = null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (t._fixedUpdate != null) {
 | 
				
			||||||
 | 
								for (f in t._fixedUpdate) App.removeFixedUpdate(f);
 | 
				
			||||||
 | 
								t._fixedUpdate = null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (t._update != null) {
 | 
							if (t._update != null) {
 | 
				
			||||||
			for (f in t._update) App.removeUpdate(f);
 | 
								for (f in t._update) App.removeUpdate(f);
 | 
				
			||||||
			t._update = null;
 | 
								t._update = null;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ package iron.object;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if lnx_particles
 | 
					#if lnx_particles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import kha.FastFloat;
 | 
				
			||||||
import kha.graphics4.Usage;
 | 
					import kha.graphics4.Usage;
 | 
				
			||||||
import kha.arrays.Float32Array;
 | 
					import kha.arrays.Float32Array;
 | 
				
			||||||
import iron.data.Data;
 | 
					import iron.data.Data;
 | 
				
			||||||
@ -16,39 +17,45 @@ import iron.math.Vec4;
 | 
				
			|||||||
class ParticleSystem {
 | 
					class ParticleSystem {
 | 
				
			||||||
	public var data: ParticleData;
 | 
						public var data: ParticleData;
 | 
				
			||||||
	public var speed = 1.0;
 | 
						public var speed = 1.0;
 | 
				
			||||||
 | 
						var currentSpeed = 0.0;
 | 
				
			||||||
	var particles: Array<Particle>;
 | 
						var particles: Array<Particle>;
 | 
				
			||||||
	var ready: Bool;
 | 
						var ready: Bool;
 | 
				
			||||||
	public var frameRate = 24;
 | 
						var frameRate = 24;
 | 
				
			||||||
	public var lifetime = 0.0;
 | 
						var lifetime = 0.0;
 | 
				
			||||||
	public var animtime = 0.0;
 | 
						var looptime = 0.0;
 | 
				
			||||||
	public var time = 0.0;
 | 
						var animtime = 0.0;
 | 
				
			||||||
	public var spawnRate = 0.0;
 | 
						var time = 0.0;
 | 
				
			||||||
 | 
						var spawnRate = 0.0;
 | 
				
			||||||
	var seed = 0;
 | 
						var seed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public var r: TParticleData;
 | 
						var r: TParticleData;
 | 
				
			||||||
	public var gx: Float;
 | 
						var gx: Float;
 | 
				
			||||||
	public var gy: Float;
 | 
						var gy: Float;
 | 
				
			||||||
	public var gz: Float;
 | 
						var gz: Float;
 | 
				
			||||||
	public var alignx: Float;
 | 
						var alignx: Float;
 | 
				
			||||||
	public var aligny: Float;
 | 
						var aligny: Float;
 | 
				
			||||||
	public var alignz: Float;
 | 
						var alignz: Float;
 | 
				
			||||||
	var dimx: Float;
 | 
						var dimx: Float;
 | 
				
			||||||
	var dimy: Float;
 | 
						var dimy: Float;
 | 
				
			||||||
	var tilesx: Int;
 | 
						var tilesx: Int;
 | 
				
			||||||
	var tilesy: Int;
 | 
						var tilesy: Int;
 | 
				
			||||||
	var tilesFramerate: Int;
 | 
						var tilesFramerate: Int;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public var count = 0;
 | 
						var count = 0;
 | 
				
			||||||
	public var lap = 0;
 | 
						var lap = 0;
 | 
				
			||||||
	public var lapTime = 0.0;
 | 
						var lapTime = 0.0;
 | 
				
			||||||
	var m = Mat4.identity();
 | 
						var m = Mat4.identity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var ownerLoc = new Vec4();
 | 
						var ownerLoc = new Vec4();
 | 
				
			||||||
	var ownerRot = new Quat();
 | 
						var ownerRot = new Quat();
 | 
				
			||||||
	var ownerScl = new Vec4();
 | 
						var ownerScl = new Vec4();
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						var random = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function new(sceneName: String, pref: TParticleReference) {
 | 
						public function new(sceneName: String, pref: TParticleReference) {
 | 
				
			||||||
		seed = pref.seed;
 | 
							seed = pref.seed;
 | 
				
			||||||
 | 
							currentSpeed = speed;
 | 
				
			||||||
 | 
							speed = 0;
 | 
				
			||||||
		particles = [];
 | 
							particles = [];
 | 
				
			||||||
		ready = false;
 | 
							ready = false;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
@ -65,33 +72,61 @@ class ParticleSystem {
 | 
				
			|||||||
				gy = 0;
 | 
									gy = 0;
 | 
				
			||||||
				gz = -9.81 * r.weight_gravity;
 | 
									gz = -9.81 * r.weight_gravity;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			alignx = r.object_align_factor[0] / 2;
 | 
								alignx = r.object_align_factor[0];
 | 
				
			||||||
			aligny = r.object_align_factor[1] / 2;
 | 
								aligny = r.object_align_factor[1];
 | 
				
			||||||
			alignz = r.object_align_factor[2] / 2;
 | 
								alignz = r.object_align_factor[2];
 | 
				
			||||||
 | 
								looptime = (r.frame_end - r.frame_start) / frameRate;
 | 
				
			||||||
			lifetime = r.lifetime / frameRate;
 | 
								lifetime = r.lifetime / frameRate;
 | 
				
			||||||
			animtime = (r.frame_end - r.frame_start) / frameRate;
 | 
								animtime = r.loop ? looptime : looptime + lifetime;
 | 
				
			||||||
			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) {
 | 
								for (i in 0...r.count) {
 | 
				
			||||||
				var particle = new Particle(i);
 | 
									particles.push(new Particle(i));
 | 
				
			||||||
				particle.sr = 1 - Math.random() * r.size_random;
 | 
					 | 
				
			||||||
				particles.push(particle);
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ready = true;
 | 
								ready = true;
 | 
				
			||||||
 | 
								if (r.auto_start){
 | 
				
			||||||
 | 
									start();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function start() {
 | 
				
			||||||
 | 
							if (r.is_unique) random = Math.random();
 | 
				
			||||||
 | 
							lifetime = r.lifetime / frameRate;
 | 
				
			||||||
 | 
							time = 0;
 | 
				
			||||||
 | 
							lap = 0;
 | 
				
			||||||
 | 
							lapTime = 0;
 | 
				
			||||||
 | 
							speed = currentSpeed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function pause() {
 | 
						public function pause() {
 | 
				
			||||||
		lifetime = 0;
 | 
							speed = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function resume() {
 | 
						public function resume() {
 | 
				
			||||||
		lifetime = r.lifetime / frameRate;
 | 
							lifetime = r.lifetime / frameRate;
 | 
				
			||||||
 | 
							speed = currentSpeed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: interrupt smoothly
 | 
				
			||||||
 | 
						public function stop() {
 | 
				
			||||||
 | 
							end();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function end() {
 | 
				
			||||||
 | 
							lifetime = 0;
 | 
				
			||||||
 | 
							speed = 0;
 | 
				
			||||||
 | 
							lap = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	public function update(object: MeshObject, owner: MeshObject) {
 | 
						public function update(object: MeshObject, owner: MeshObject) {
 | 
				
			||||||
		if (!ready || object == null || speed == 0.0) return;
 | 
							if (!ready || object == null || speed == 0.0) return;
 | 
				
			||||||
 | 
							if (iron.App.pauseUpdates) return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							var prevLap = lap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Copy owner world transform but discard scale
 | 
							// Copy owner world transform but discard scale
 | 
				
			||||||
		owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl);
 | 
							owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl);
 | 
				
			||||||
@ -115,17 +150,21 @@ class ParticleSystem {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Animate
 | 
							// Animate
 | 
				
			||||||
		time += Time.delta * speed;
 | 
							time += Time.renderDelta * speed; // realDelta to renderDelta
 | 
				
			||||||
		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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (lap > prevLap && !r.loop) {
 | 
				
			||||||
 | 
								end();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		updateGpu(object, owner);
 | 
							updateGpu(object, owner);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function getData(): Mat4 {
 | 
						public function getData(): Mat4 {
 | 
				
			||||||
		var hair = r.type == 1;
 | 
							var hair = r.type == 1;
 | 
				
			||||||
		m._00 = r.loop ? animtime : -animtime;
 | 
							m._00 = animtime;
 | 
				
			||||||
		m._01 = hair ? 1 / particles.length : spawnRate;
 | 
							m._01 = hair ? 1 / particles.length : spawnRate;
 | 
				
			||||||
		m._02 = hair ? 1 : lifetime;
 | 
							m._02 = hair ? 1 : lifetime;
 | 
				
			||||||
		m._03 = particles.length;
 | 
							m._03 = particles.length;
 | 
				
			||||||
@ -133,9 +172,9 @@ class ParticleSystem {
 | 
				
			|||||||
		m._11 = hair ? 0 : aligny;
 | 
							m._11 = hair ? 0 : aligny;
 | 
				
			||||||
		m._12 = hair ? 0 : alignz;
 | 
							m._12 = hair ? 0 : alignz;
 | 
				
			||||||
		m._13 = hair ? 0 : r.factor_random;
 | 
							m._13 = hair ? 0 : r.factor_random;
 | 
				
			||||||
		m._20 = hair ? 0 : gx * r.mass;
 | 
							m._20 = hair ? 0 : gx;
 | 
				
			||||||
		m._21 = hair ? 0 : gy * r.mass;
 | 
							m._21 = hair ? 0 : gy;
 | 
				
			||||||
		m._22 = hair ? 0 : gz * r.mass;
 | 
							m._22 = hair ? 0 : gz;
 | 
				
			||||||
		m._23 = hair ? 0 : r.lifetime_random;
 | 
							m._23 = hair ? 0 : r.lifetime_random;
 | 
				
			||||||
		m._30 = tilesx;
 | 
							m._30 = tilesx;
 | 
				
			||||||
		m._31 = tilesy;
 | 
							m._31 = tilesy;
 | 
				
			||||||
@ -144,13 +183,25 @@ class ParticleSystem {
 | 
				
			|||||||
		return m;
 | 
							return m;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function getSizeRandom(): FastFloat {
 | 
				
			||||||
 | 
							return r.size_random;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function getRandom(): FastFloat {
 | 
				
			||||||
 | 
							return random;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function getSize(): FastFloat {
 | 
				
			||||||
 | 
							return r.particle_size;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function updateGpu(object: MeshObject, owner: MeshObject) {
 | 
						function updateGpu(object: MeshObject, owner: MeshObject) {
 | 
				
			||||||
		if (!object.data.geom.instanced) setupGeomGpu(object, owner);
 | 
							if (!object.data.geom.instanced) setupGeomGpu(object, owner);
 | 
				
			||||||
		// GPU particles transform is attached to owner object
 | 
							// GPU particles transform is attached to owner object
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function setupGeomGpu(object: MeshObject, owner: MeshObject) {
 | 
						function setupGeomGpu(object: MeshObject, owner: MeshObject) {
 | 
				
			||||||
		var instancedData = new Float32Array(particles.length * 6);
 | 
							var instancedData = new Float32Array(particles.length * 3);
 | 
				
			||||||
		var i = 0;
 | 
							var i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var normFactor = 1 / 32767; // pa.values are not normalized
 | 
							var normFactor = 1 / 32767; // pa.values are not normalized
 | 
				
			||||||
@ -169,10 +220,6 @@ 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
 | 
				
			||||||
@ -196,10 +243,6 @@ 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
 | 
				
			||||||
@ -210,13 +253,9 @@ 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, 3, Usage.StaticUsage);
 | 
							object.data.geom.setupInstanced(instancedData, 1, Usage.StaticUsage);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function fhash(n: Int): Float {
 | 
						function fhash(n: Int): Float {
 | 
				
			||||||
@ -255,10 +294,11 @@ class ParticleSystem {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Particle {
 | 
					class Particle {
 | 
				
			||||||
	public var i: Int;
 | 
						public var i: Int;
 | 
				
			||||||
	public var px = 0.0;
 | 
						
 | 
				
			||||||
	public var py = 0.0;
 | 
						public var x = 0.0;
 | 
				
			||||||
	public var pz = 0.0;
 | 
						public var y = 0.0;
 | 
				
			||||||
	public var sr = 1.0; // Size random
 | 
						public var z = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public var cameraDistance: Float;
 | 
						public var cameraDistance: Float;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function new(i: Int) {
 | 
						public function new(i: Int) {
 | 
				
			||||||
 | 
				
			|||||||
@ -80,7 +80,7 @@ class Tilesheet {
 | 
				
			|||||||
	function update() {
 | 
						function update() {
 | 
				
			||||||
		if (!ready || paused || action.start >= action.end) return;
 | 
							if (!ready || paused || action.start >= action.end) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		time += Time.realDelta;
 | 
							time += Time.renderDelta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var frameTime = 1 / raw.framerate;
 | 
							var frameTime = 1 / raw.framerate;
 | 
				
			||||||
		var framesToAdvance = 0;
 | 
							var framesToAdvance = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -1113,6 +1113,26 @@ class Uniforms {
 | 
				
			|||||||
				case "_texUnpack": {
 | 
									case "_texUnpack": {
 | 
				
			||||||
					f = texUnpack != null ? texUnpack : 1.0;
 | 
										f = texUnpack != null ? texUnpack : 1.0;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									#if lnx_particles
 | 
				
			||||||
 | 
									case "_particleSizeRandom": {
 | 
				
			||||||
 | 
										var mo = cast(object, MeshObject);
 | 
				
			||||||
 | 
										if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
 | 
				
			||||||
 | 
											f = mo.particleOwner.particleSystems[mo.particleIndex].getSizeRandom();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									case "_particleRandom": {
 | 
				
			||||||
 | 
										var mo = cast(object, MeshObject);
 | 
				
			||||||
 | 
										if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
 | 
				
			||||||
 | 
											f = mo.particleOwner.particleSystems[mo.particleIndex].getRandom();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									case "_particleSize": {
 | 
				
			||||||
 | 
										var mo = cast(object, MeshObject);
 | 
				
			||||||
 | 
										if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
 | 
				
			||||||
 | 
											f = mo.particleOwner.particleSystems[mo.particleIndex].getSize();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									#end
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (f == null && externalFloatLinks != null) {
 | 
								if (f == null && externalFloatLinks != null) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,12 @@
 | 
				
			|||||||
package iron.system;
 | 
					package iron.system;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Time {
 | 
					class Time {
 | 
				
			||||||
 | 
						public static var scale = 1.0;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						static var frequency: Null<Int> = null;
 | 
				
			||||||
 | 
						static function initFrequency() {
 | 
				
			||||||
 | 
							frequency = kha.Display.primary != null ? kha.Display.primary.frequency : 60;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	public static var step(get, never): Float;
 | 
						public static var step(get, never): Float;
 | 
				
			||||||
	static function get_step(): Float {
 | 
						static function get_step(): Float {
 | 
				
			||||||
@ -8,30 +14,45 @@ class Time {
 | 
				
			|||||||
		return 1 / frequency;
 | 
							return 1 / frequency;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	public static var scale = 1.0;
 | 
						static var _fixedStep: Null<Float>;
 | 
				
			||||||
	public static var delta(get, never): Float;
 | 
						public static var fixedStep(get, never): Float;
 | 
				
			||||||
	static function get_delta(): Float {
 | 
						static function get_fixedStep(): Float {
 | 
				
			||||||
		if (frequency == null) initFrequency();
 | 
							return _fixedStep;
 | 
				
			||||||
		return (1 / frequency) * scale;
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public static function initFixedStep(value: Float = 1 / 60) {
 | 
				
			||||||
 | 
							_fixedStep = value;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static var lastTime = 0.0;
 | 
				
			||||||
 | 
						static var _delta = 0.0;
 | 
				
			||||||
 | 
						public static var delta(get, never): Float;
 | 
				
			||||||
 | 
						static function get_delta(): Float {
 | 
				
			||||||
 | 
							return _delta;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						static var lastRenderTime = 0.0;
 | 
				
			||||||
 | 
						static var _renderDelta = 0.0;
 | 
				
			||||||
 | 
						public static var renderDelta(get, never): Float;
 | 
				
			||||||
 | 
						static function get_renderDelta(): Float {
 | 
				
			||||||
 | 
							return _renderDelta;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	static var last = 0.0;
 | 
					 | 
				
			||||||
	public static var realDelta = 0.0;
 | 
					 | 
				
			||||||
	public static inline function time(): Float {
 | 
						public static inline function time(): Float {
 | 
				
			||||||
		return kha.Scheduler.time();
 | 
							return kha.Scheduler.time();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	public static inline function realTime(): Float {
 | 
						public static inline function realTime(): Float {
 | 
				
			||||||
		return kha.Scheduler.realTime();
 | 
							return kha.Scheduler.realTime();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static var frequency: Null<Int> = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	static function initFrequency() {
 | 
					 | 
				
			||||||
		frequency = kha.Display.primary != null ? kha.Display.primary.frequency : 60;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public static function update() {
 | 
						public static function update() {
 | 
				
			||||||
		realDelta = realTime() - last;
 | 
							_delta = realTime() - lastTime;
 | 
				
			||||||
		last = realTime();
 | 
							lastTime = realTime();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static function render() {
 | 
				
			||||||
 | 
							_renderDelta = realTime() - lastRenderTime;
 | 
				
			||||||
 | 
							lastRenderTime = realTime();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ class Config {
 | 
				
			|||||||
		var path = iron.data.Data.dataPath + "config.lnx";
 | 
							var path = iron.data.Data.dataPath + "config.lnx";
 | 
				
			||||||
		var bytes = haxe.io.Bytes.ofString(haxe.Json.stringify(raw));
 | 
							var bytes = haxe.io.Bytes.ofString(haxe.Json.stringify(raw));
 | 
				
			||||||
		#if kha_krom
 | 
							#if kha_krom
 | 
				
			||||||
 | 
							if (iron.data.Data.dataPath == '') path = Krom.getFilesLocation() + "/config.lnx";
 | 
				
			||||||
		Krom.fileSaveBytes(path, bytes.getData());
 | 
							Krom.fileSaveBytes(path, bytes.getData());
 | 
				
			||||||
		#elseif kha_kore
 | 
							#elseif kha_kore
 | 
				
			||||||
		sys.io.File.saveBytes(path, bytes);
 | 
							sys.io.File.saveBytes(path, bytes);
 | 
				
			||||||
@ -47,6 +48,7 @@ typedef TConfig = {
 | 
				
			|||||||
	@:optional var rp_ssr: Null<Bool>;
 | 
						@:optional var rp_ssr: Null<Bool>;
 | 
				
			||||||
	@:optional var rp_ssrefr: Null<Bool>;
 | 
						@:optional var rp_ssrefr: Null<Bool>;
 | 
				
			||||||
	@:optional var rp_bloom: Null<Bool>;
 | 
						@:optional var rp_bloom: Null<Bool>;
 | 
				
			||||||
 | 
						@:optional var rp_chromatic_aberration: Null<Bool>;
 | 
				
			||||||
	@:optional var rp_motionblur: Null<Bool>;
 | 
						@:optional var rp_motionblur: Null<Bool>;
 | 
				
			||||||
	@:optional var rp_gi: Null<Bool>; // voxelao
 | 
						@:optional var rp_gi: Null<Bool>; // voxelao
 | 
				
			||||||
	@:optional var rp_dynres: Null<Bool>; // dynamic resolution scaling
 | 
						@:optional var rp_dynres: Null<Bool>; // dynamic resolution scaling
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ class AddParticleToObjectNode extends LogicNode {
 | 
				
			|||||||
	
 | 
						
 | 
				
			||||||
			var mobjTo = cast(objTo, iron.object.MeshObject);
 | 
								var mobjTo = cast(objTo, iron.object.MeshObject);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
			mobjTo.setupParticleSystem(iron.Scene.active.raw.name, {name: 'LnxPS', seed: 0, particle: psys.r.name});
 | 
								mobjTo.setupParticleSystem(iron.Scene.active.raw.name, {name: 'LnxPS', seed: 0, particle: @:privateAccess psys.r.name});
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			mobjTo.render_emitter = inputs[4].get();
 | 
								mobjTo.render_emitter = inputs[4].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -47,7 +47,7 @@ class AddParticleToObjectNode extends LogicNode {
 | 
				
			|||||||
	
 | 
						
 | 
				
			||||||
			var oslot: Int = mobjTo.particleSystems.length-1;
 | 
								var oslot: Int = mobjTo.particleSystems.length-1;
 | 
				
			||||||
			var opsys = mobjTo.particleSystems[oslot];
 | 
								var opsys = mobjTo.particleSystems[oslot];
 | 
				
			||||||
			opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
 | 
								@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			var sceneName: String = inputs[1].get();
 | 
								var sceneName: String = inputs[1].get();
 | 
				
			||||||
@ -82,7 +82,7 @@ class AddParticleToObjectNode extends LogicNode {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					var oslot: Int = mobjTo.particleSystems.length-1;
 | 
										var oslot: Int = mobjTo.particleSystems.length-1;
 | 
				
			||||||
					var opsys = mobjTo.particleSystems[oslot];
 | 
										var opsys = mobjTo.particleSystems[oslot];
 | 
				
			||||||
					opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
 | 
										@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								leenkx/Sources/leenkx/logicnode/AutoExposureGetNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								leenkx/Sources/leenkx/logicnode/AutoExposureGetNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AutoExposureGetNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function get(from:Int):Dynamic {
 | 
				
			||||||
 | 
							return switch (from) {
 | 
				
			||||||
 | 
								case 0: leenkx.renderpath.Postprocess.auto_exposure_uniforms[0];
 | 
				
			||||||
 | 
								case 1: leenkx.renderpath.Postprocess.auto_exposure_uniforms[1];
 | 
				
			||||||
 | 
								default: 0.0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								leenkx/Sources/leenkx/logicnode/AutoExposureSetNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								leenkx/Sources/leenkx/logicnode/AutoExposureSetNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AutoExposureSetNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function run(from:Int) {
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.auto_exposure_uniforms[0] = inputs[1].get();
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.auto_exposure_uniforms[1] = inputs[2].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							runOutput(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2,25 +2,48 @@ package leenkx.logicnode;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class CameraSetNode extends LogicNode {
 | 
					class CameraSetNode extends LogicNode {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						public var property0: String;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	public function new(tree:LogicTree) {
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
		super(tree);
 | 
							super(tree);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	override function run(from:Int) {
 | 
						override function run(from:Int) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (property0) {
 | 
				
			||||||
 | 
								case 'F-stop':
 | 
				
			||||||
				leenkx.renderpath.Postprocess.camera_uniforms[0] = inputs[1].get();//Camera: F-Number
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[0] = inputs[1].get();//Camera: F-Number
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[1] = inputs[2].get();//Camera: Shutter time
 | 
								case 'Shutter Time':	
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[2] = inputs[3].get();//Camera: ISO
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[1] = inputs[1].get();//Camera: Shutter time
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[3] = inputs[4].get();//Camera: Exposure Compensation
 | 
								case 'ISO':
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[4] = inputs[5].get();//Fisheye Distortion
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[2] = inputs[1].get();//Camera: ISO
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[5] = inputs[6].get();//DoF AutoFocus §§ If true, it ignores the DoF Distance setting
 | 
								case 'Exposure Compensation':
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[6] = inputs[7].get();//DoF Distance
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[3] = inputs[1].get();//Camera: Exposure Compensation
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[7] = inputs[8].get();//DoF Focal Length mm
 | 
								case 'Fisheye Distortion':
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[8] = inputs[9].get();//DoF F-Stop
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[4] = inputs[1].get();//Fisheye Distortion
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[9] = inputs[10].get();//Tonemapping Method
 | 
								case 'Auto Focus':
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[10] = inputs[11].get();//Distort
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[5] = inputs[1].get();//DoF AutoFocus §§ If true, it ignores the DoF Distance setting
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[11] = inputs[12].get();//Film Grain
 | 
								case 'DoF Distance':
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[12] = inputs[13].get();//Sharpen
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[6] = inputs[1].get();//DoF Distance
 | 
				
			||||||
		leenkx.renderpath.Postprocess.camera_uniforms[13] = inputs[14].get();//Vignette
 | 
								case 'DoF Length':
 | 
				
			||||||
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[7] = inputs[1].get();//DoF Focal Length mm
 | 
				
			||||||
 | 
								case 'DoF F-Stop':
 | 
				
			||||||
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[8] = inputs[1].get();//DoF F-Stop
 | 
				
			||||||
 | 
								case 'Tonemapping':
 | 
				
			||||||
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[9] = inputs[1].get();//Tonemapping Method
 | 
				
			||||||
 | 
								case 'Distort':
 | 
				
			||||||
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[10] = inputs[1].get();//Distort
 | 
				
			||||||
 | 
								case 'Film Grain':
 | 
				
			||||||
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[11] = inputs[1].get();//Film Grain
 | 
				
			||||||
 | 
								case 'Sharpen':
 | 
				
			||||||
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[12] = inputs[1].get();//Sharpen
 | 
				
			||||||
 | 
								case 'Vignette':
 | 
				
			||||||
 | 
									leenkx.renderpath.Postprocess.camera_uniforms[13] = inputs[1].get();//Vignette
 | 
				
			||||||
 | 
								case 'Exposure':
 | 
				
			||||||
 | 
									leenkx.renderpath.Postprocess.exposure_uniforms[0] = inputs[1].get();//Exposure
 | 
				
			||||||
 | 
								default: 
 | 
				
			||||||
 | 
									null;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		runOutput(0);
 | 
							runOutput(0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ class ChromaticAberrationGetNode extends LogicNode {
 | 
				
			|||||||
		return switch (from) {
 | 
							return switch (from) {
 | 
				
			||||||
			case 0: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[0];
 | 
								case 0: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[0];
 | 
				
			||||||
			case 1: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[1];
 | 
								case 1: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[1];
 | 
				
			||||||
 | 
								case 2: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[2];
 | 
				
			||||||
			default: 0.0;
 | 
								default: 0.0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ class ChromaticAberrationSetNode extends LogicNode {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[0] = inputs[1].get();
 | 
					        leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[0] = inputs[1].get();
 | 
				
			||||||
        leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[1] = inputs[2].get();
 | 
					        leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[1] = inputs[2].get();
 | 
				
			||||||
 | 
							leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[2] = inputs[3].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		runOutput(0);
 | 
							runOutput(0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ class GetFPSNode extends LogicNode {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    override function get(from: Int): Dynamic {
 | 
					    override function get(from: Int): Dynamic {
 | 
				
			||||||
        if (from == 0) {
 | 
					        if (from == 0) {
 | 
				
			||||||
            var fps = Math.round(1 / iron.system.Time.realDelta);
 | 
					            var fps = Math.round(1 / iron.system.Time.renderDelta);
 | 
				
			||||||
            if ((fps == Math.POSITIVE_INFINITY) || (fps == Math.NEGATIVE_INFINITY) || (Math.isNaN(fps))) {
 | 
					            if ((fps == Math.POSITIVE_INFINITY) || (fps == Math.NEGATIVE_INFINITY) || (Math.isNaN(fps))) {
 | 
				
			||||||
                return 0;
 | 
					                return 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -25,37 +25,43 @@ class GetParticleDataNode extends LogicNode {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		return switch (from) {
 | 
							return switch (from) {
 | 
				
			||||||
			case 0:
 | 
								case 0:
 | 
				
			||||||
				psys.r.name;
 | 
									@:privateAccess psys.r.name;
 | 
				
			||||||
			case 1:
 | 
								case 1:
 | 
				
			||||||
				psys.r.particle_size;
 | 
									@:privateAccess psys.r.particle_size;
 | 
				
			||||||
			case 2:
 | 
								case 2:
 | 
				
			||||||
				psys.r.frame_start;
 | 
									@:privateAccess psys.r.frame_start;
 | 
				
			||||||
			case 3:
 | 
								case 3:
 | 
				
			||||||
				psys.r.frame_end;
 | 
									@:privateAccess psys.r.frame_end;
 | 
				
			||||||
			case 4:
 | 
								case 4:
 | 
				
			||||||
				psys.lifetime;
 | 
									@:privateAccess psys.lifetime;
 | 
				
			||||||
			case 5:
 | 
								case 5:
 | 
				
			||||||
				psys.r.lifetime;
 | 
									@:privateAccess psys.r.lifetime;
 | 
				
			||||||
			case 6:
 | 
								case 6:
 | 
				
			||||||
				psys.r.emit_from;
 | 
									@:privateAccess psys.r.emit_from;
 | 
				
			||||||
			case 7:
 | 
								case 7:
 | 
				
			||||||
				new iron.math.Vec3(psys.alignx*2, psys.aligny*2, psys.alignz*2);
 | 
									@:privateAccess psys.r.auto_start;
 | 
				
			||||||
			case 8:
 | 
								case 8:
 | 
				
			||||||
				psys.r.factor_random;
 | 
									@:privateAccess psys.r.is_unique;
 | 
				
			||||||
			case 9:
 | 
								case 9:
 | 
				
			||||||
				new iron.math.Vec3(psys.gx, psys.gy, psys.gz);
 | 
									@:privateAccess psys.r.loop;
 | 
				
			||||||
			case 10:
 | 
								case 10:
 | 
				
			||||||
				psys.r.weight_gravity;
 | 
									new iron.math.Vec3(@:privateAccess psys.alignx, @:privateAccess psys.aligny, @:privateAccess psys.alignz);
 | 
				
			||||||
			case 11:
 | 
								case 11:
 | 
				
			||||||
				psys.speed;
 | 
									@:privateAccess psys.r.factor_random;
 | 
				
			||||||
			case 12:
 | 
								case 12:
 | 
				
			||||||
				psys.time;
 | 
									new iron.math.Vec3(@:privateAccess psys.gx, @:privateAccess psys.gy, @:privateAccess psys.gz);
 | 
				
			||||||
			case 13:
 | 
								case 13:
 | 
				
			||||||
				psys.lap;
 | 
									@:privateAccess psys.r.weight_gravity;
 | 
				
			||||||
			case 14:
 | 
								case 14:
 | 
				
			||||||
				psys.lapTime;
 | 
									psys.speed;
 | 
				
			||||||
			case 15:
 | 
								case 15:
 | 
				
			||||||
				psys.count;
 | 
									@:privateAccess psys.time;
 | 
				
			||||||
 | 
								case 16:
 | 
				
			||||||
 | 
									@:privateAccess psys.lap;
 | 
				
			||||||
 | 
								case 17:
 | 
				
			||||||
 | 
									@:privateAccess psys.lapTime;
 | 
				
			||||||
 | 
								case 18:
 | 
				
			||||||
 | 
									@:privateAccess psys.count;
 | 
				
			||||||
			default: 
 | 
								default: 
 | 
				
			||||||
				null;
 | 
									null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ class GetParticleNode extends LogicNode {
 | 
				
			|||||||
				var names: Array<String> = [];
 | 
									var names: Array<String> = [];
 | 
				
			||||||
				if (mo.particleSystems != null)
 | 
									if (mo.particleSystems != null)
 | 
				
			||||||
					for (psys in mo.particleSystems)
 | 
										for (psys in mo.particleSystems)
 | 
				
			||||||
						names.push(psys.r.name);
 | 
											names.push(@:privateAccess psys.r.name);
 | 
				
			||||||
				return names;
 | 
									return names;
 | 
				
			||||||
			case 1:
 | 
								case 1:
 | 
				
			||||||
				return mo.particleSystems != null ? mo.particleSystems.length : 0;
 | 
									return mo.particleSystems != null ? mo.particleSystems.length : 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -33,7 +33,7 @@ class RemoveParticleFromObjectNode extends LogicNode {
 | 
				
			|||||||
			if (property0 == 'Name'){
 | 
								if (property0 == 'Name'){
 | 
				
			||||||
				var name: String = inputs[2].get();
 | 
									var name: String = inputs[2].get();
 | 
				
			||||||
				for (i => psys in mo.particleSystems){
 | 
									for (i => psys in mo.particleSystems){
 | 
				
			||||||
					if (psys.r.name == name){ slot = i; break; }
 | 
										if (@:privateAccess psys.r.name == name){ slot = i; break; }
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} 
 | 
								} 
 | 
				
			||||||
			else slot = inputs[2].get();
 | 
								else slot = inputs[2].get();
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,8 @@ class RpConfigNode extends LogicNode {
 | 
				
			|||||||
			on ? leenkx.data.Config.raw.rp_ssrefr = true : leenkx.data.Config.raw.rp_ssrefr = false;
 | 
								on ? leenkx.data.Config.raw.rp_ssrefr = true : leenkx.data.Config.raw.rp_ssrefr = false;
 | 
				
			||||||
        case "Bloom":
 | 
					        case "Bloom":
 | 
				
			||||||
			on ? leenkx.data.Config.raw.rp_bloom = true : leenkx.data.Config.raw.rp_bloom = false;
 | 
								on ? leenkx.data.Config.raw.rp_bloom = true : leenkx.data.Config.raw.rp_bloom = false;
 | 
				
			||||||
 | 
							case "CA":
 | 
				
			||||||
 | 
								on ? leenkx.data.Config.raw.rp_chromatic_aberration = true : leenkx.data.Config.raw.rp_chromatic_aberration = false;
 | 
				
			||||||
        case "GI":
 | 
					        case "GI":
 | 
				
			||||||
			on ? leenkx.data.Config.raw.rp_gi = true : leenkx.data.Config.raw.rp_gi = false;
 | 
								on ? leenkx.data.Config.raw.rp_gi = true : leenkx.data.Config.raw.rp_gi = false;
 | 
				
			||||||
		case "Motion Blur":
 | 
							case "Motion Blur":
 | 
				
			||||||
 | 
				
			|||||||
@ -24,43 +24,49 @@ class SetParticleDataNode extends LogicNode {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		switch (property0) {
 | 
							switch (property0) {
 | 
				
			||||||
			case 'Particle Size':
 | 
								case 'Particle Size':
 | 
				
			||||||
				psys.r.particle_size = inputs[3].get();
 | 
									@:privateAccess psys.r.particle_size = inputs[3].get();
 | 
				
			||||||
			case 'Frame Start':
 | 
								case 'Frame Start':
 | 
				
			||||||
				psys.r.frame_start = inputs[3].get();
 | 
									@:privateAccess psys.r.frame_start = inputs[3].get();
 | 
				
			||||||
				psys.animtime = (psys.r.frame_end - psys.r.frame_start) / psys.frameRate;
 | 
									@:privateAccess psys.animtime = (@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.frameRate;
 | 
				
			||||||
				psys.spawnRate = ((psys.r.frame_end - psys.r.frame_start) / psys.count) / psys.frameRate;
 | 
									@:privateAccess psys.spawnRate = ((@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.count) / @:privateAccess psys.frameRate;
 | 
				
			||||||
			case 'Frame End':
 | 
								case 'Frame End':
 | 
				
			||||||
				psys.r.frame_end = inputs[3].get();
 | 
									@:privateAccess psys.r.frame_end = inputs[3].get();
 | 
				
			||||||
				psys.animtime = (psys.r.frame_end - psys.r.frame_start) / psys.frameRate;
 | 
									@:privateAccess psys.animtime = (@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.frameRate;
 | 
				
			||||||
				psys.spawnRate = ((psys.r.frame_end - psys.r.frame_start) / psys.count) / psys.frameRate;
 | 
									@:privateAccess psys.spawnRate = ((@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.count) / @:privateAccess psys.frameRate;
 | 
				
			||||||
			case 'Lifetime':
 | 
								case 'Lifetime':
 | 
				
			||||||
				psys.lifetime = inputs[3].get() / psys.frameRate;
 | 
									@:privateAccess psys.lifetime = inputs[3].get() / @:privateAccess psys.frameRate;
 | 
				
			||||||
			case 'Lifetime Random':
 | 
								case 'Lifetime Random':
 | 
				
			||||||
				psys.r.lifetime_random = inputs[3].get();
 | 
									@:privateAccess psys.r.lifetime_random = inputs[3].get();
 | 
				
			||||||
			case 'Emit From':
 | 
								case 'Emit From':
 | 
				
			||||||
				var emit_from: Int = inputs[3].get();
 | 
									var emit_from: Int = inputs[3].get();
 | 
				
			||||||
				if (emit_from == 0 || emit_from == 1 || emit_from == 2) {
 | 
									if (emit_from == 0 || emit_from == 1 || emit_from == 2) {
 | 
				
			||||||
					psys.r.emit_from = emit_from;
 | 
										@:privateAccess psys.r.emit_from = emit_from;
 | 
				
			||||||
					psys.setupGeomGpu(mo.particleChildren != null ? mo.particleChildren[slot] : cast(iron.Scene.active.getChild(psys.data.raw.instance_object), iron.object.MeshObject), mo);
 | 
										@:privateAccess psys.setupGeomGpu(mo.particleChildren != null ? mo.particleChildren[slot] : cast(iron.Scene.active.getChild(@:privateAccess psys.data.raw.instance_object), iron.object.MeshObject), mo);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								case 'Auto Start':
 | 
				
			||||||
 | 
									@:privateAccess psys.r.auto_start = inputs[3].get(); 
 | 
				
			||||||
 | 
								case 'Is Unique':
 | 
				
			||||||
 | 
									@:privateAccess psys.r.is_unique = inputs[3].get();
 | 
				
			||||||
 | 
								case 'Loop':
 | 
				
			||||||
 | 
									@:privateAccess psys.r.loop = inputs[3].get();
 | 
				
			||||||
			case 'Velocity':
 | 
								case 'Velocity':
 | 
				
			||||||
				var vel: iron.math.Vec3 = inputs[3].get();
 | 
									var vel: iron.math.Vec3 = inputs[3].get();
 | 
				
			||||||
				psys.alignx = vel.x / 2;
 | 
									@:privateAccess psys.alignx = vel.x;
 | 
				
			||||||
				psys.aligny = vel.y / 2;
 | 
									@:privateAccess psys.aligny = vel.y;
 | 
				
			||||||
				psys.alignz = vel.z / 2;
 | 
									@:privateAccess psys.alignz = vel.z;
 | 
				
			||||||
			case 'Velocity Random':
 | 
								case 'Velocity Random':
 | 
				
			||||||
				psys.r.factor_random = inputs[3].get();
 | 
									psys.r.factor_random = inputs[3].get();
 | 
				
			||||||
			case 'Weight Gravity':
 | 
								case 'Weight Gravity':
 | 
				
			||||||
				psys.r.weight_gravity = inputs[3].get();
 | 
									psys.r.weight_gravity = inputs[3].get();
 | 
				
			||||||
				if (iron.Scene.active.raw.gravity != null) {
 | 
									if (iron.Scene.active.raw.gravity != null) {
 | 
				
			||||||
					psys.gx = iron.Scene.active.raw.gravity[0] * psys.r.weight_gravity;
 | 
										@:privateAccess psys.gx = iron.Scene.active.raw.gravity[0] * @:privateAccess psys.r.weight_gravity;
 | 
				
			||||||
					psys.gy = iron.Scene.active.raw.gravity[1] * psys.r.weight_gravity;
 | 
										@:privateAccess psys.gy = iron.Scene.active.raw.gravity[1] * @:privateAccess psys.r.weight_gravity;
 | 
				
			||||||
					psys.gz = iron.Scene.active.raw.gravity[2] * psys.r.weight_gravity;
 | 
										@:privateAccess psys.gz = iron.Scene.active.raw.gravity[2] * @:privateAccess psys.r.weight_gravity;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else {
 | 
									else {
 | 
				
			||||||
					psys.gx = 0;
 | 
										@:privateAccess psys.gx = 0;
 | 
				
			||||||
					psys.gy = 0;
 | 
										@:privateAccess psys.gy = 0;
 | 
				
			||||||
					psys.gz = -9.81 * psys.r.weight_gravity;
 | 
										@:privateAccess psys.gz = -9.81 * @:privateAccess psys.r.weight_gravity;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			case 'Speed':
 | 
								case 'Speed':
 | 
				
			||||||
				psys.speed = inputs[3].get();
 | 
									psys.speed = inputs[3].get();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								leenkx/Sources/leenkx/logicnode/SharpenGetNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								leenkx/Sources/leenkx/logicnode/SharpenGetNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SharpenGetNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function get(from:Int):Dynamic {
 | 
				
			||||||
 | 
							return switch (from) {
 | 
				
			||||||
 | 
								case 0: leenkx.renderpath.Postprocess.sharpen_uniforms[0];
 | 
				
			||||||
 | 
								case 1: leenkx.renderpath.Postprocess.sharpen_uniforms[1][0];
 | 
				
			||||||
 | 
								case 2: leenkx.renderpath.Postprocess.camera_uniforms[12];
 | 
				
			||||||
 | 
								default: 0.0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								leenkx/Sources/leenkx/logicnode/SharpenSetNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								leenkx/Sources/leenkx/logicnode/SharpenSetNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SharpenSetNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function run(from:Int) {
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.sharpen_uniforms[0][0] = inputs[1].get().x;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.sharpen_uniforms[0][1] = inputs[1].get().y;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.sharpen_uniforms[0][2] = inputs[1].get().z;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.sharpen_uniforms[1][0] = inputs[2].get();
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.camera_uniforms[12] = inputs[3].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							runOutput(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								leenkx/Sources/leenkx/logicnode/VolumetricFogGetNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								leenkx/Sources/leenkx/logicnode/VolumetricFogGetNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumetricFogGetNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function get(from:Int):Dynamic {
 | 
				
			||||||
 | 
							return switch (from) {
 | 
				
			||||||
 | 
								case 0: leenkx.renderpath.Postprocess.volumetric_fog_uniforms[0];
 | 
				
			||||||
 | 
								case 1: leenkx.renderpath.Postprocess.volumetric_fog_uniforms[1][0];
 | 
				
			||||||
 | 
								case 2: leenkx.renderpath.Postprocess.volumetric_fog_uniforms[2][0];
 | 
				
			||||||
 | 
								default: 0.0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								leenkx/Sources/leenkx/logicnode/VolumetricFogSetNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								leenkx/Sources/leenkx/logicnode/VolumetricFogSetNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumetricFogSetNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function run(from:Int) {
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_fog_uniforms[0][0] = inputs[1].get().x;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_fog_uniforms[0][1] = inputs[1].get().y;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_fog_uniforms[0][2] = inputs[1].get().z;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_fog_uniforms[1][0] = inputs[2].get();
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_fog_uniforms[2][0] = inputs[3].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							runOutput(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								leenkx/Sources/leenkx/logicnode/VolumetricLightGetNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								leenkx/Sources/leenkx/logicnode/VolumetricLightGetNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumetricLightGetNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function get(from:Int):Dynamic {
 | 
				
			||||||
 | 
							return switch (from) {
 | 
				
			||||||
 | 
								case 0: leenkx.renderpath.Postprocess.volumetric_light_uniforms[0];
 | 
				
			||||||
 | 
								case 1: leenkx.renderpath.Postprocess.volumetric_light_uniforms[1][0];
 | 
				
			||||||
 | 
								case 2: leenkx.renderpath.Postprocess.volumetric_light_uniforms[2][0];
 | 
				
			||||||
 | 
								default: 0.0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								leenkx/Sources/leenkx/logicnode/VolumetricLightSetNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								leenkx/Sources/leenkx/logicnode/VolumetricLightSetNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package leenkx.logicnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumetricLightSetNode extends LogicNode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function new(tree:LogicTree) {
 | 
				
			||||||
 | 
							super(tree);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						override function run(from:Int) {
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_light_uniforms[0][0] = inputs[1].get().x;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_light_uniforms[0][1] = inputs[1].get().y;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_light_uniforms[0][2] = inputs[1].get().z;
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_light_uniforms[1][0] = inputs[2].get();
 | 
				
			||||||
 | 
					        leenkx.renderpath.Postprocess.volumetric_light_uniforms[2][0] = inputs[3].get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							runOutput(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -527,8 +527,14 @@ class Inc {
 | 
				
			|||||||
	public static function applyConfig() {
 | 
						public static function applyConfig() {
 | 
				
			||||||
		#if lnx_config
 | 
							#if lnx_config
 | 
				
			||||||
		var config = leenkx.data.Config.raw;
 | 
							var config = leenkx.data.Config.raw;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							#if rp_chromatic_aberration
 | 
				
			||||||
 | 
							Postprocess.chromatic_aberration_uniforms[3] = config.rp_chromatic_aberration == true ? 1 : 0;
 | 
				
			||||||
 | 
							#end
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		// Resize shadow map
 | 
							// Resize shadow map
 | 
				
			||||||
		var l = path.light;
 | 
							var l = path.light;
 | 
				
			||||||
 | 
							if (l != null){
 | 
				
			||||||
			if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) {
 | 
								if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) {
 | 
				
			||||||
				l.data.raw.shadowmap_size = config.rp_shadowmap_cascade;
 | 
									l.data.raw.shadowmap_size = config.rp_shadowmap_cascade;
 | 
				
			||||||
				var rt = path.renderTargets.get("shadowMap");
 | 
									var rt = path.renderTargets.get("shadowMap");
 | 
				
			||||||
@ -545,6 +551,7 @@ class Inc {
 | 
				
			|||||||
					path.renderTargets.remove("shadowMapCube");
 | 
										path.renderTargets.remove("shadowMapCube");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (superSample != config.rp_supersample) {
 | 
							if (superSample != config.rp_supersample) {
 | 
				
			||||||
			superSample = config.rp_supersample;
 | 
								superSample = config.rp_supersample;
 | 
				
			||||||
			for (rt in path.renderTargets) {
 | 
								for (rt in path.renderTargets) {
 | 
				
			||||||
 | 
				
			|||||||
@ -54,10 +54,15 @@ class Postprocess {
 | 
				
			|||||||
		0,					//9: Tonemapping Method
 | 
							0,					//9: Tonemapping Method
 | 
				
			||||||
		2.0,				//10: Distort
 | 
							2.0,				//10: Distort
 | 
				
			||||||
		2.0,				//11: Film Grain
 | 
							2.0,				//11: Film Grain
 | 
				
			||||||
		0.25,				//12: Sharpen
 | 
							0.25,				//12: Sharpen Strength
 | 
				
			||||||
		0.7					//13: Vignette
 | 
							0.7					//13: Vignette
 | 
				
			||||||
	];
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static var sharpen_uniforms = [
 | 
				
			||||||
 | 
							[0.0, 0.0, 0.0],	//0: Sharpen Color
 | 
				
			||||||
 | 
							[2.5]				//1: Sharpen Size
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static var tonemapper_uniforms = [
 | 
						public static var tonemapper_uniforms = [
 | 
				
			||||||
		1.0, 				//0: Slope
 | 
							1.0, 				//0: Slope
 | 
				
			||||||
		1.0, 				//1: Toe
 | 
							1.0, 				//1: Toe
 | 
				
			||||||
@ -102,7 +107,30 @@ class Postprocess {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	public static var chromatic_aberration_uniforms = [
 | 
						public static var chromatic_aberration_uniforms = [
 | 
				
			||||||
		2.0,				//0: Strength
 | 
							2.0,				//0: Strength
 | 
				
			||||||
		32					//1: Samples
 | 
							32,					//1: Samples
 | 
				
			||||||
 | 
							0,					//2: Type				
 | 
				
			||||||
 | 
							1					//3: On/Off
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static var exposure_uniforms = [
 | 
				
			||||||
 | 
							1 					//0: Exposure
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static var auto_exposure_uniforms = [
 | 
				
			||||||
 | 
							1, 					//0: Auto Exposure Strength
 | 
				
			||||||
 | 
							1 					//1: Auto Exposure Speed
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static var volumetric_light_uniforms = [
 | 
				
			||||||
 | 
							[1.0, 1.0, 1.0], 	//0: Volumetric Light Air Color
 | 
				
			||||||
 | 
							[1.0], 				//1: Volumetric Light Air Turbidity
 | 
				
			||||||
 | 
							[20.0]				//2: Volumetric Light Steps
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static var volumetric_fog_uniforms = [
 | 
				
			||||||
 | 
							[0.5, 0.6, 0.7], 	//0: Volumetric Fog Color
 | 
				
			||||||
 | 
							[0.25], 			//1: Volumetric Fog Amount A
 | 
				
			||||||
 | 
							[50.0]				//2: Volumetric Fog Amount B
 | 
				
			||||||
	];
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
 | 
						public static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
 | 
				
			||||||
@ -284,6 +312,11 @@ class Postprocess {
 | 
				
			|||||||
			v.x = lenstexture_uniforms[2]; //Lum min
 | 
								v.x = lenstexture_uniforms[2]; //Lum min
 | 
				
			||||||
			v.y = lenstexture_uniforms[3]; //Lum max
 | 
								v.y = lenstexture_uniforms[3]; //Lum max
 | 
				
			||||||
			v.z = lenstexture_uniforms[4]; //Expo
 | 
								v.z = lenstexture_uniforms[4]; //Expo
 | 
				
			||||||
 | 
							case "_PPComp8":
 | 
				
			||||||
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
 | 
								v.x = exposure_uniforms[0];	   //Exposure
 | 
				
			||||||
 | 
								v.y = auto_exposure_uniforms[0]; //Auto Exposure Strength
 | 
				
			||||||
 | 
								v.z = auto_exposure_uniforms[1]; //Auto Exposure Speed
 | 
				
			||||||
		case "_PPComp9":
 | 
							case "_PPComp9":
 | 
				
			||||||
			v = iron.object.Uniforms.helpVec;
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
			v.x = ssr_uniforms[0]; //Step
 | 
								v.x = ssr_uniforms[0]; //Step
 | 
				
			||||||
@ -297,8 +330,8 @@ class Postprocess {
 | 
				
			|||||||
		case "_PPComp11":
 | 
							case "_PPComp11":
 | 
				
			||||||
			v = iron.object.Uniforms.helpVec;
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
			v.x = bloom_uniforms[2]; // Bloom Strength
 | 
								v.x = bloom_uniforms[2]; // Bloom Strength
 | 
				
			||||||
			v.y = 0; // Unused
 | 
								v.y = volumetric_light_uniforms[2][0]; //Volumetric Light Steps
 | 
				
			||||||
			v.z = 0; // Unused
 | 
								v.z = volumetric_fog_uniforms[2][0]; //Volumetric Fog Amount B
 | 
				
			||||||
		case "_PPComp12":
 | 
							case "_PPComp12":
 | 
				
			||||||
			v = iron.object.Uniforms.helpVec;
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
			v.x = ssao_uniforms[0]; //SSAO Strength
 | 
								v.x = ssao_uniforms[0]; //SSAO Strength
 | 
				
			||||||
@ -308,7 +341,8 @@ class Postprocess {
 | 
				
			|||||||
			v = iron.object.Uniforms.helpVec;
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
			v.x = chromatic_aberration_uniforms[0]; //CA Strength
 | 
								v.x = chromatic_aberration_uniforms[0]; //CA Strength
 | 
				
			||||||
			v.y = chromatic_aberration_uniforms[1]; //CA Samples
 | 
								v.y = chromatic_aberration_uniforms[1]; //CA Samples
 | 
				
			||||||
			v.z = 0;
 | 
								v.z = chromatic_aberration_uniforms[2]; //CA Type
 | 
				
			||||||
 | 
								v.w = chromatic_aberration_uniforms[3]; //On/Off
 | 
				
			||||||
		case "_PPComp14":
 | 
							case "_PPComp14":
 | 
				
			||||||
			v = iron.object.Uniforms.helpVec;
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
			v.x = camera_uniforms[10]; //Distort
 | 
								v.x = camera_uniforms[10]; //Distort
 | 
				
			||||||
@ -338,6 +372,24 @@ class Postprocess {
 | 
				
			|||||||
			v.y = letterbox_uniforms[0][1];
 | 
								v.y = letterbox_uniforms[0][1];
 | 
				
			||||||
			v.z = letterbox_uniforms[0][2];
 | 
								v.z = letterbox_uniforms[0][2];
 | 
				
			||||||
			v.w = letterbox_uniforms[1][0]; //Size
 | 
								v.w = letterbox_uniforms[1][0]; //Size
 | 
				
			||||||
 | 
							case "_PPComp16":
 | 
				
			||||||
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
 | 
								v.x = sharpen_uniforms[0][0]; //Color
 | 
				
			||||||
 | 
								v.y = sharpen_uniforms[0][1];
 | 
				
			||||||
 | 
								v.z = sharpen_uniforms[0][2];
 | 
				
			||||||
 | 
								v.w = sharpen_uniforms[1][0]; //Size
 | 
				
			||||||
 | 
							case "_PPComp17":
 | 
				
			||||||
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
 | 
								v.x = volumetric_light_uniforms[0][0]; //Air Color
 | 
				
			||||||
 | 
								v.y = volumetric_light_uniforms[0][1];
 | 
				
			||||||
 | 
								v.z = volumetric_light_uniforms[0][2];
 | 
				
			||||||
 | 
								v.w = volumetric_light_uniforms[1][0]; //Air Turbidity
 | 
				
			||||||
 | 
							case "_PPComp18":
 | 
				
			||||||
 | 
								v = iron.object.Uniforms.helpVec;
 | 
				
			||||||
 | 
								v.x = volumetric_fog_uniforms[0][0]; //Color
 | 
				
			||||||
 | 
								v.y = volumetric_fog_uniforms[0][1];
 | 
				
			||||||
 | 
								v.z = volumetric_fog_uniforms[0][2];
 | 
				
			||||||
 | 
								v.w = volumetric_fog_uniforms[1][0]; //Amount A
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return v;
 | 
							return v;
 | 
				
			||||||
 | 
				
			|||||||
@ -101,7 +101,7 @@ class PhysicsWorld extends Trait {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug) {
 | 
						public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, fixedStep = 1 / 60, debugDrawMode: DebugDrawMode = NoDebug) {
 | 
				
			||||||
		super();
 | 
							super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (nullvec) {
 | 
							if (nullvec) {
 | 
				
			||||||
@ -120,6 +120,7 @@ class PhysicsWorld extends Trait {
 | 
				
			|||||||
		this.timeScale = timeScale;
 | 
							this.timeScale = timeScale;
 | 
				
			||||||
		this.maxSteps = maxSteps;
 | 
							this.maxSteps = maxSteps;
 | 
				
			||||||
		this.solverIterations = solverIterations;
 | 
							this.solverIterations = solverIterations;
 | 
				
			||||||
 | 
							Time.initFixedStep(fixedStep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// First scene
 | 
							// First scene
 | 
				
			||||||
		if (active == null) {
 | 
							if (active == null) {
 | 
				
			||||||
@ -136,9 +137,9 @@ class PhysicsWorld extends Trait {
 | 
				
			|||||||
		conMap = new Map();
 | 
							conMap = new Map();
 | 
				
			||||||
		active = this;
 | 
							active = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Ensure physics are updated first in the lateUpdate list
 | 
							// Ensure physics are updated first in the fixedUpdate list
 | 
				
			||||||
		_lateUpdate = [lateUpdate];
 | 
							_fixedUpdate = [fixedUpdate];
 | 
				
			||||||
		@:privateAccess iron.App.traitLateUpdates.insert(0, lateUpdate);
 | 
							@:privateAccess iron.App.traitFixedUpdates.insert(0, fixedUpdate);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		setDebugDrawMode(debugDrawMode);
 | 
							setDebugDrawMode(debugDrawMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -298,8 +299,8 @@ class PhysicsWorld extends Trait {
 | 
				
			|||||||
		return rb;
 | 
							return rb;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function lateUpdate() {
 | 
						function fixedUpdate() {
 | 
				
			||||||
		var t = Time.delta * timeScale;
 | 
							var t = Time.fixedStep * timeScale * Time.scale;
 | 
				
			||||||
		if (t == 0.0) return; // Simulation paused
 | 
							if (t == 0.0) return; // Simulation paused
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		#if lnx_debug
 | 
							#if lnx_debug
 | 
				
			||||||
@ -308,13 +309,10 @@ class PhysicsWorld extends Trait {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if (preUpdates != null) for (f in preUpdates) f();
 | 
							if (preUpdates != null) for (f in preUpdates) f();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//Bullet physics fixed timescale
 | 
					 | 
				
			||||||
		var fixedTime = 1.0 / 60;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		//This condition must be satisfied to not loose time
 | 
							//This condition must be satisfied to not loose time
 | 
				
			||||||
		var currMaxSteps = t < (fixedTime * maxSteps) ? maxSteps : 1;
 | 
							var currMaxSteps = t < (Time.fixedStep * maxSteps) ? maxSteps : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		world.stepSimulation(t, currMaxSteps, fixedTime);
 | 
							world.stepSimulation(t, currMaxSteps, Time.fixedStep);
 | 
				
			||||||
		updateContacts();
 | 
							updateContacts();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (rb in rbMap) @:privateAccess rb.physicsUpdate();
 | 
							for (rb in rbMap) @:privateAccess rb.physicsUpdate();
 | 
				
			||||||
 | 
				
			|||||||
@ -2,11 +2,13 @@ package leenkx.trait.physics.bullet;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if lnx_bullet
 | 
					#if lnx_bullet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import leenkx.math.Helper;
 | 
				
			||||||
 | 
					import iron.data.MeshData;
 | 
				
			||||||
import iron.math.Vec4;
 | 
					import iron.math.Vec4;
 | 
				
			||||||
import iron.math.Quat;
 | 
					import iron.math.Quat;
 | 
				
			||||||
import iron.object.Transform;
 | 
					import iron.object.Transform;
 | 
				
			||||||
import iron.object.MeshObject;
 | 
					import iron.object.MeshObject;
 | 
				
			||||||
import iron.data.MeshData;
 | 
					import iron.system.Time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
   RigidBody is used to allow objects to interact with Physics in your game including collisions and gravity.
 | 
					   RigidBody is used to allow objects to interact with Physics in your game including collisions and gravity.
 | 
				
			||||||
@ -76,6 +78,14 @@ class RigidBody extends iron.Trait {
 | 
				
			|||||||
	static var triangleMeshCache = new Map<MeshData, bullet.Bt.TriangleMesh>();
 | 
						static var triangleMeshCache = new Map<MeshData, bullet.Bt.TriangleMesh>();
 | 
				
			||||||
	static var usersCache = new Map<MeshData, Int>();
 | 
						static var usersCache = new Map<MeshData, Int>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Interpolation
 | 
				
			||||||
 | 
						var interpolate: Bool = false;
 | 
				
			||||||
 | 
						var time: Float = 0.0;
 | 
				
			||||||
 | 
						var currentPos: bullet.Bt.Vector3 = new bullet.Bt.Vector3(0, 0, 0);
 | 
				
			||||||
 | 
						var prevPos: bullet.Bt.Vector3 = new bullet.Bt.Vector3(0, 0, 0);
 | 
				
			||||||
 | 
						var currentRot: bullet.Bt.Quaternion = new bullet.Bt.Quaternion(0, 0, 0, 1);
 | 
				
			||||||
 | 
						var prevRot: bullet.Bt.Quaternion = new bullet.Bt.Quaternion(0, 0, 0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function new(shape = Shape.Box, mass = 1.0, friction = 0.5, restitution = 0.0, group = 1, mask = 1,
 | 
						public function new(shape = Shape.Box, mass = 1.0, friction = 0.5, restitution = 0.0, group = 1, mask = 1,
 | 
				
			||||||
						params: RigidBodyParams = null, flags: RigidBodyFlags = null) {
 | 
											params: RigidBodyParams = null, flags: RigidBodyFlags = null) {
 | 
				
			||||||
		super();
 | 
							super();
 | 
				
			||||||
@ -85,7 +95,7 @@ class RigidBody extends iron.Trait {
 | 
				
			|||||||
			vec1 = new bullet.Bt.Vector3(0, 0, 0);
 | 
								vec1 = new bullet.Bt.Vector3(0, 0, 0);
 | 
				
			||||||
			vec2 = new bullet.Bt.Vector3(0, 0, 0);
 | 
								vec2 = new bullet.Bt.Vector3(0, 0, 0);
 | 
				
			||||||
			vec3 = new bullet.Bt.Vector3(0, 0, 0);
 | 
								vec3 = new bullet.Bt.Vector3(0, 0, 0);
 | 
				
			||||||
			quat1 = new bullet.Bt.Quaternion(0, 0, 0, 0);
 | 
								quat1 = new bullet.Bt.Quaternion(0, 0, 0, 1);
 | 
				
			||||||
			trans1 = new bullet.Bt.Transform();
 | 
								trans1 = new bullet.Bt.Transform();
 | 
				
			||||||
			trans2 = new bullet.Bt.Transform();
 | 
								trans2 = new bullet.Bt.Transform();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -117,6 +127,7 @@ class RigidBody extends iron.Trait {
 | 
				
			|||||||
			animated: false,
 | 
								animated: false,
 | 
				
			||||||
			trigger: false,
 | 
								trigger: false,
 | 
				
			||||||
			ccd: false,
 | 
								ccd: false,
 | 
				
			||||||
 | 
								interpolate: false,
 | 
				
			||||||
			staticObj: false,
 | 
								staticObj: false,
 | 
				
			||||||
			useDeactivation: true
 | 
								useDeactivation: true
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
@ -131,6 +142,7 @@ class RigidBody extends iron.Trait {
 | 
				
			|||||||
		this.animated = flags.animated;
 | 
							this.animated = flags.animated;
 | 
				
			||||||
		this.trigger = flags.trigger;
 | 
							this.trigger = flags.trigger;
 | 
				
			||||||
		this.ccd = flags.ccd;
 | 
							this.ccd = flags.ccd;
 | 
				
			||||||
 | 
							this.interpolate = flags.interpolate;
 | 
				
			||||||
		this.staticObj = flags.staticObj;
 | 
							this.staticObj = flags.staticObj;
 | 
				
			||||||
		this.useDeactivation = flags.useDeactivation;
 | 
							this.useDeactivation = flags.useDeactivation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -153,6 +165,7 @@ class RigidBody extends iron.Trait {
 | 
				
			|||||||
		if (!Std.isOfType(object, MeshObject)) return; // No mesh data
 | 
							if (!Std.isOfType(object, MeshObject)) return; // No mesh data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		transform = object.transform;
 | 
							transform = object.transform;
 | 
				
			||||||
 | 
							transform.buildMatrix();
 | 
				
			||||||
		physics = leenkx.trait.physics.PhysicsWorld.active;
 | 
							physics = leenkx.trait.physics.PhysicsWorld.active;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (shape == Shape.Box) {
 | 
							if (shape == Shape.Box) {
 | 
				
			||||||
@ -244,6 +257,9 @@ class RigidBody extends iron.Trait {
 | 
				
			|||||||
		quat1.setValue(quat.x, quat.y, quat.z, quat.w);
 | 
							quat1.setValue(quat.x, quat.y, quat.z, quat.w);
 | 
				
			||||||
		trans1.setRotation(quat1);
 | 
							trans1.setRotation(quat1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							currentPos.setValue(vec1.x(), vec1.y(), vec1.z());
 | 
				
			||||||
 | 
							currentRot.setValue(quat.x, quat.y, quat.z, quat.w);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var centerOfMassOffset = trans2;
 | 
							var centerOfMassOffset = trans2;
 | 
				
			||||||
		centerOfMassOffset.setIdentity();
 | 
							centerOfMassOffset.setIdentity();
 | 
				
			||||||
		motionState = new bullet.Bt.DefaultMotionState(trans1, centerOfMassOffset);
 | 
							motionState = new bullet.Bt.DefaultMotionState(trans1, centerOfMassOffset);
 | 
				
			||||||
@ -307,6 +323,7 @@ class RigidBody extends iron.Trait {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		physics.addRigidBody(this);
 | 
							physics.addRigidBody(this);
 | 
				
			||||||
		notifyOnRemove(removeFromWorld);
 | 
							notifyOnRemove(removeFromWorld);
 | 
				
			||||||
 | 
							if (!animated) notifyOnUpdate(update);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (onReady != null) onReady();
 | 
							if (onReady != null) onReady();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -317,26 +334,71 @@ class RigidBody extends iron.Trait {
 | 
				
			|||||||
		#end
 | 
							#end
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function physicsUpdate() {
 | 
					 | 
				
			||||||
		if (!ready) return;
 | 
					 | 
				
			||||||
		if (animated) {
 | 
					 | 
				
			||||||
			syncTransform();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else {
 | 
					 | 
				
			||||||
			var trans = body.getWorldTransform();
 | 
					 | 
				
			||||||
			var p = trans.getOrigin();
 | 
					 | 
				
			||||||
			var q = trans.getRotation();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			transform.loc.set(p.x(), p.y(), p.z());
 | 
						function update() {
 | 
				
			||||||
			transform.rot.set(q.x(), q.y(), q.z(), q.w());
 | 
							if (interpolate) {
 | 
				
			||||||
 | 
								time += Time.delta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								while (time >= Time.fixedStep) {
 | 
				
			||||||
 | 
									time -= Time.fixedStep;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var t: Float = time / Time.fixedStep;
 | 
				
			||||||
 | 
								t = Helper.clamp(t, 0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var tx: Float = prevPos.x() * (1.0 - t) + currentPos.x() * t;
 | 
				
			||||||
 | 
								var ty: Float = prevPos.y() * (1.0 - t) + currentPos.y() * t;
 | 
				
			||||||
 | 
								var tz: Float = prevPos.z() * (1.0 - t) + currentPos.z() * t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var tRot: bullet.Bt.Quaternion = nlerp(prevRot, currentRot, t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								transform.loc.set(tx, ty, tz, 1.0);
 | 
				
			||||||
 | 
								transform.rot.set(tRot.x(), tRot.y(), tRot.z(), tRot.w());
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								transform.loc.set(currentPos.x(), currentPos.y(), currentPos.z(), 1.0);
 | 
				
			||||||
 | 
								transform.rot.set(currentRot.x(), currentRot.y(), currentRot.z(), currentRot.w());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (object.parent != null) {
 | 
							if (object.parent != null) {
 | 
				
			||||||
			var ptransform = object.parent.transform;
 | 
								var ptransform = object.parent.transform;
 | 
				
			||||||
			transform.loc.x -= ptransform.worldx();
 | 
								transform.loc.x -= ptransform.worldx();
 | 
				
			||||||
			transform.loc.y -= ptransform.worldy();
 | 
								transform.loc.y -= ptransform.worldy();
 | 
				
			||||||
			transform.loc.z -= ptransform.worldz();
 | 
								transform.loc.z -= ptransform.worldz();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
			transform.clearDelta();
 | 
					
 | 
				
			||||||
		transform.buildMatrix();
 | 
							transform.buildMatrix();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function nlerp(q1: bullet.Bt.Quaternion, q2: bullet.Bt.Quaternion, t: Float): bullet.Bt.Quaternion {
 | 
				
			||||||
 | 
							var dot = q1.x() * q2.x() + q1.y() * q2.y() + q1.z() * q2.z() + q1.w() * q2.w();
 | 
				
			||||||
 | 
							var _q2 = dot < 0 ? new bullet.Bt.Quaternion(-q2.x(), -q2.y(), -q2.z(), -q2.w()) : q2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var x = q1.x() * (1.0 - t) + _q2.x() * t;
 | 
				
			||||||
 | 
							var y = q1.y() * (1.0 - t) + _q2.y() * t;
 | 
				
			||||||
 | 
							var z = q1.z() * (1.0 - t) + _q2.z() * t;
 | 
				
			||||||
 | 
							var w = q1.w() * (1.0 - t) + _q2.w() * t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var len = Math.sqrt(x * x + y * y + z * z + w * w);
 | 
				
			||||||
 | 
							return new bullet.Bt.Quaternion(x / len, y / len, z / len, w / len);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						function physicsUpdate() {
 | 
				
			||||||
 | 
							if (!ready) return;
 | 
				
			||||||
 | 
							if (animated) {
 | 
				
			||||||
 | 
								syncTransform();
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (interpolate) {
 | 
				
			||||||
 | 
									prevPos.setValue(currentPos.x(), currentPos.y(), currentPos.z());
 | 
				
			||||||
 | 
									prevRot.setValue(currentRot.x(), currentRot.y(), currentRot.z(), currentRot.w());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var trans = body.getWorldTransform();
 | 
				
			||||||
 | 
								var p = trans.getOrigin();
 | 
				
			||||||
 | 
								var q = trans.getRotation();
 | 
				
			||||||
 | 
								transform.clearDelta();
 | 
				
			||||||
 | 
								// transform.buildMatrix();
 | 
				
			||||||
 | 
								currentPos.setValue(p.x(), p.y(), p.z());
 | 
				
			||||||
 | 
								currentRot.setValue(q.x(), q.y(), q.z(), q.w());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			#if hl
 | 
								#if hl
 | 
				
			||||||
			p.delete();
 | 
								p.delete();
 | 
				
			||||||
@ -689,6 +751,7 @@ typedef RigidBodyFlags = {
 | 
				
			|||||||
	var animated: Bool;
 | 
						var animated: Bool;
 | 
				
			||||||
	var trigger: Bool;
 | 
						var trigger: Bool;
 | 
				
			||||||
	var ccd: Bool;
 | 
						var ccd: Bool;
 | 
				
			||||||
 | 
						var interpolate: Bool;
 | 
				
			||||||
	var staticObj: Bool;
 | 
						var staticObj: Bool;
 | 
				
			||||||
	var useDeactivation: Bool;
 | 
						var useDeactivation: Bool;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2297,6 +2297,8 @@ class LeenkxExporter:
 | 
				
			|||||||
            out_particlesys = {
 | 
					            out_particlesys = {
 | 
				
			||||||
                'name': particleRef[1]["structName"],
 | 
					                'name': particleRef[1]["structName"],
 | 
				
			||||||
                'type': 0 if psettings.type == 'EMITTER' else 1, # HAIR
 | 
					                'type': 0 if psettings.type == 'EMITTER' else 1, # HAIR
 | 
				
			||||||
 | 
					                'auto_start': psettings.lnx_auto_start,
 | 
				
			||||||
 | 
					                'is_unique': psettings.lnx_is_unique,
 | 
				
			||||||
                'loop': psettings.lnx_loop,
 | 
					                'loop': psettings.lnx_loop,
 | 
				
			||||||
                # Emission
 | 
					                # Emission
 | 
				
			||||||
                'count': int(psettings.count * psettings.lnx_count_mult),
 | 
					                'count': int(psettings.count * psettings.lnx_count_mult),
 | 
				
			||||||
@ -2813,6 +2815,7 @@ class LeenkxExporter:
 | 
				
			|||||||
            body_flags['animated'] = rb.kinematic
 | 
					            body_flags['animated'] = rb.kinematic
 | 
				
			||||||
            body_flags['trigger'] = bobject.lnx_rb_trigger
 | 
					            body_flags['trigger'] = bobject.lnx_rb_trigger
 | 
				
			||||||
            body_flags['ccd'] = bobject.lnx_rb_ccd
 | 
					            body_flags['ccd'] = bobject.lnx_rb_ccd
 | 
				
			||||||
 | 
					            body_flags['interpolate'] = bobject.lnx_rb_interpolate
 | 
				
			||||||
            body_flags['staticObj'] = is_static
 | 
					            body_flags['staticObj'] = is_static
 | 
				
			||||||
            body_flags['useDeactivation'] = rb.use_deactivation
 | 
					            body_flags['useDeactivation'] = rb.use_deactivation
 | 
				
			||||||
            x['parameters'].append(lnx.utils.get_haxe_json_string(body_params))
 | 
					            x['parameters'].append(lnx.utils.get_haxe_json_string(body_params))
 | 
				
			||||||
@ -3037,7 +3040,7 @@ class LeenkxExporter:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            rbw = self.scene.rigidbody_world
 | 
					            rbw = self.scene.rigidbody_world
 | 
				
			||||||
            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), str(wrd.lnx_physics_fixed_step)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if phys_pkg == 'bullet' or phys_pkg == 'oimo':
 | 
					                if phys_pkg == 'bullet' or phys_pkg == 'oimo':
 | 
				
			||||||
                    debug_draw_mode = 1 if wrd.lnx_physics_dbg_draw_wireframe else 0
 | 
					                    debug_draw_mode = 1 if wrd.lnx_physics_dbg_draw_wireframe else 0
 | 
				
			||||||
 | 
				
			|||||||
@ -87,6 +87,7 @@ def on_operator_post(operator_id: str) -> None:
 | 
				
			|||||||
            target_obj.lnx_rb_trigger = source_obj.lnx_rb_trigger
 | 
					            target_obj.lnx_rb_trigger = source_obj.lnx_rb_trigger
 | 
				
			||||||
            target_obj.lnx_rb_deactivation_time = source_obj.lnx_rb_deactivation_time
 | 
					            target_obj.lnx_rb_deactivation_time = source_obj.lnx_rb_deactivation_time
 | 
				
			||||||
            target_obj.lnx_rb_ccd = source_obj.lnx_rb_ccd
 | 
					            target_obj.lnx_rb_ccd = source_obj.lnx_rb_ccd
 | 
				
			||||||
 | 
					            target_obj.lnx_rb_interpolate = source_obj.lnx_rb_interpolate
 | 
				
			||||||
            target_obj.lnx_rb_collision_filter_mask = source_obj.lnx_rb_collision_filter_mask
 | 
					            target_obj.lnx_rb_collision_filter_mask = source_obj.lnx_rb_collision_filter_mask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    elif operator_id == "NODE_OT_new_node_tree":
 | 
					    elif operator_id == "NODE_OT_new_node_tree":
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,9 @@ class GetParticleDataNode(LnxLogicTreeNode):
 | 
				
			|||||||
        self.outputs.new('LnxIntSocket', 'Lifetime')
 | 
					        self.outputs.new('LnxIntSocket', 'Lifetime')
 | 
				
			||||||
        self.outputs.new('LnxFloatSocket', 'Lifetime Random')
 | 
					        self.outputs.new('LnxFloatSocket', 'Lifetime Random')
 | 
				
			||||||
        self.outputs.new('LnxIntSocket', 'Emit From')
 | 
					        self.outputs.new('LnxIntSocket', 'Emit From')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxBoolSocket', 'Auto Start')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxBoolSocket', 'Is Unique')
 | 
				
			||||||
 | 
					        self.outputs.new('LnxBoolSocket', 'Loop')
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        self.outputs.new('LnxVectorSocket', 'Velocity')
 | 
					        self.outputs.new('LnxVectorSocket', 'Velocity')
 | 
				
			||||||
        self.outputs.new('LnxFloatSocket', 'Velocity Random')
 | 
					        self.outputs.new('LnxFloatSocket', 'Velocity Random')
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,12 @@ class SetParticleDataNode(LnxLogicTreeNode):
 | 
				
			|||||||
            self.add_input('LnxFloatSocket', 'Lifetime Random')
 | 
					            self.add_input('LnxFloatSocket', 'Lifetime Random')
 | 
				
			||||||
        if self.property0 == 'Emit From':
 | 
					        if self.property0 == 'Emit From':
 | 
				
			||||||
            self.add_input('LnxIntSocket', 'Emit From')
 | 
					            self.add_input('LnxIntSocket', 'Emit From')
 | 
				
			||||||
 | 
					        if self.property0 == 'Auto Start':
 | 
				
			||||||
 | 
					            self.add_input('LnxBoolSocket', 'Auto Start')
 | 
				
			||||||
 | 
					        if self.property0 == 'Is Unique':
 | 
				
			||||||
 | 
					            self.add_input('LnxBoolSocket', 'Is Unique')
 | 
				
			||||||
 | 
					        if self.property0 == 'Loop':
 | 
				
			||||||
 | 
					            self.add_input('LnxBoolSocket', 'Loop')
 | 
				
			||||||
        if self.property0 == 'Velocity':
 | 
					        if self.property0 == 'Velocity':
 | 
				
			||||||
            self.add_input('LnxVectorSocket', 'Velocity')
 | 
					            self.add_input('LnxVectorSocket', 'Velocity')
 | 
				
			||||||
        if self.property0 == 'Velocity Random':
 | 
					        if self.property0 == 'Velocity Random':
 | 
				
			||||||
@ -39,6 +45,9 @@ class SetParticleDataNode(LnxLogicTreeNode):
 | 
				
			|||||||
             ('Lifetime', 'Lifetime', 'for the instance'),
 | 
					             ('Lifetime', 'Lifetime', 'for the instance'),
 | 
				
			||||||
             ('Lifetime Random', 'Lifetime Random', 'for the system'),
 | 
					             ('Lifetime Random', 'Lifetime Random', 'for the system'),
 | 
				
			||||||
             ('Emit From', 'Emit From', 'for the system (Vertices:0 Faces:1 Volume: 2)'),
 | 
					             ('Emit From', 'Emit From', 'for the system (Vertices:0 Faces:1 Volume: 2)'),
 | 
				
			||||||
 | 
					             ('Auto Start', 'Auto Start', 'for the system'),
 | 
				
			||||||
 | 
					             ('Is Unique', 'Is Unique', 'for the system'),
 | 
				
			||||||
 | 
					             ('Loop', 'Loop', 'for the system'),
 | 
				
			||||||
             ('Velocity', 'Velocity', 'for the instance'),
 | 
					             ('Velocity', 'Velocity', 'for the instance'),
 | 
				
			||||||
             ('Velocity Random', 'Velocity Random', 'for the system'),
 | 
					             ('Velocity Random', 'Velocity Random', 'for the system'),
 | 
				
			||||||
             ('Weight Gravity', 'Weight Gravity', 'for the instance'),
 | 
					             ('Weight Gravity', 'Weight Gravity', 'for the instance'),
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AutoExposureGetNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Returns the auto exposure post-processing settings."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNAutoExposureGetNode'
 | 
				
			||||||
 | 
					    bl_label = 'Get Auto Exposure Settings'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_output('LnxFloatSocket', 'Strength')
 | 
				
			||||||
 | 
					        self.add_output('LnxFloatSocket', 'Speed')
 | 
				
			||||||
@ -1,11 +1,20 @@
 | 
				
			|||||||
from lnx.logicnode.lnx_nodes import *
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChromaticAberrationGetNode(LnxLogicTreeNode):
 | 
					class ChromaticAberrationGetNode(LnxLogicTreeNode):
 | 
				
			||||||
    """Returns the chromatic aberration post-processing settings."""
 | 
					    """Returns the chromatic aberration post-processing settings.
 | 
				
			||||||
 | 
					    Type: Simple 0 Spectral 1.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    bl_idname = 'LNChromaticAberrationGetNode'
 | 
					    bl_idname = 'LNChromaticAberrationGetNode'
 | 
				
			||||||
    bl_label = 'Get CA Settings'
 | 
					    bl_label = 'Get CA Settings'
 | 
				
			||||||
    lnx_version = 1
 | 
					    lnx_version = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lnx_init(self, context):
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
        self.add_output('LnxFloatSocket', 'Strength')
 | 
					        self.add_output('LnxFloatSocket', 'Strength')
 | 
				
			||||||
        self.add_output('LnxFloatSocket', 'Samples')
 | 
					        self.add_output('LnxFloatSocket', 'Samples')
 | 
				
			||||||
 | 
					        self.add_output('LnxIntSocket', 'Type')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
				
			||||||
 | 
					        if self.lnx_version not in (0, 1):
 | 
				
			||||||
 | 
					            raise LookupError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return NodeReplacement.Identity(self)
 | 
				
			||||||
@ -21,6 +21,7 @@ class CameraGetNode(LnxLogicTreeNode):
 | 
				
			|||||||
        self.add_output('LnxFloatSocket', 'Film Grain')#11
 | 
					        self.add_output('LnxFloatSocket', 'Film Grain')#11
 | 
				
			||||||
        self.add_output('LnxFloatSocket', 'Sharpen')#12
 | 
					        self.add_output('LnxFloatSocket', 'Sharpen')#12
 | 
				
			||||||
        self.add_output('LnxFloatSocket', 'Vignette')#13
 | 
					        self.add_output('LnxFloatSocket', 'Vignette')#13
 | 
				
			||||||
 | 
					        self.add_output('LnxFloatSocket', 'Exposure')#14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
					    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
				
			||||||
        if self.lnx_version not in (0, 3):
 | 
					        if self.lnx_version not in (0, 3):
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SharpenGetNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Returns the sharpen post-processing settings."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNSharpenGetNode'
 | 
				
			||||||
 | 
					    bl_label = 'Get Sharpen Settings'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_output('LnxColorSocket', 'Color')
 | 
				
			||||||
 | 
					        self.add_output('LnxFloatSocket', 'Size')
 | 
				
			||||||
 | 
					        self.add_output('LnxFloatSocket', 'Strength')
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumetricFogGetNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Returns the volumetric fog post-processing settings."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNVolumetricFogGetNode'
 | 
				
			||||||
 | 
					    bl_label = 'Get Volumetric Fog Settings'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_output('LnxColorSocket', 'Color')
 | 
				
			||||||
 | 
					        self.add_output('LnxFloatSocket', 'Amount A')
 | 
				
			||||||
 | 
					        self.add_output('LnxFloatSocket', 'Amount B')
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumetricLightGetNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Returns the volumetric light post-processing settings."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNVolumetricLightGetNode'
 | 
				
			||||||
 | 
					    bl_label = 'Get Volumetric Light Settings'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_output('LnxColorSocket', 'Air Color')
 | 
				
			||||||
 | 
					        self.add_output('LnxFloatSocket', 'Air Turbidity')
 | 
				
			||||||
 | 
					        self.add_output('LnxIntSocket', 'Steps')
 | 
				
			||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AutoExposureSetNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Set the sharpen post-processing settings."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNAutoExposureSetNode'
 | 
				
			||||||
 | 
					    bl_label = 'Set Auto Exposure Settings'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Strength', default_value=1)
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Speed', default_value=1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out') 
 | 
				
			||||||
@ -1,14 +1,23 @@
 | 
				
			|||||||
from lnx.logicnode.lnx_nodes import *
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChromaticAberrationSetNode(LnxLogicTreeNode):
 | 
					class ChromaticAberrationSetNode(LnxLogicTreeNode):
 | 
				
			||||||
    """Set the chromatic aberration post-processing settings."""
 | 
					    """Set the chromatic aberration post-processing settings.
 | 
				
			||||||
 | 
					    Type: Simple 0 Spectral 1.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    bl_idname = 'LNChromaticAberrationSetNode'
 | 
					    bl_idname = 'LNChromaticAberrationSetNode'
 | 
				
			||||||
    bl_label = 'Set CA Settings'
 | 
					    bl_label = 'Set CA Settings'
 | 
				
			||||||
    lnx_version = 1
 | 
					    lnx_version = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lnx_init(self, context):
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Strength', default_value=2.0)
 | 
					        self.add_input('LnxFloatSocket', 'Strength', default_value=2.0)
 | 
				
			||||||
        self.add_input('LnxIntSocket', 'Samples', default_value=32)
 | 
					        self.add_input('LnxIntSocket', 'Samples', default_value=32)
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Type', default_value=0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
				
			||||||
 | 
					        if self.lnx_version not in (0, 1):
 | 
				
			||||||
 | 
					            raise LookupError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return NodeReplacement.Identity(self)
 | 
				
			||||||
@ -4,27 +4,74 @@ class CameraSetNode(LnxLogicTreeNode):
 | 
				
			|||||||
    """Set the post-processing effects of a camera."""
 | 
					    """Set the post-processing effects of a camera."""
 | 
				
			||||||
    bl_idname = 'LNCameraSetNode'
 | 
					    bl_idname = 'LNCameraSetNode'
 | 
				
			||||||
    bl_label = 'Set Camera Post Process'
 | 
					    bl_label = 'Set Camera Post Process'
 | 
				
			||||||
    lnx_version = 4
 | 
					    lnx_version = 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def remove_extra_inputs(self, context):
 | 
				
			||||||
 | 
					        while len(self.inputs) > 1:
 | 
				
			||||||
 | 
					                self.inputs.remove(self.inputs[-1])
 | 
				
			||||||
 | 
					        if self.property0 == 'F-stop':
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'F-stop', default_value=1.0)#0
 | 
				
			||||||
 | 
					        if self.property0 == 'Shutter Time':
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Shutter Time', default_value=2.8333)#1
 | 
				
			||||||
 | 
					        if self.property0 == 'ISO':           
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'ISO', default_value=100.0)#2
 | 
				
			||||||
 | 
					        if self.property0 == 'Exposure Compensation':           
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Exposure Compensation', default_value=0.0)#3
 | 
				
			||||||
 | 
					        if self.property0 == 'Fisheye Distortion':           
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Fisheye Distortion', default_value=0.01)#4
 | 
				
			||||||
 | 
					        if self.property0 == 'Auto Focus':
 | 
				
			||||||
 | 
					            self.add_input('LnxBoolSocket', 'Auto Focus', default_value=True)#5
 | 
				
			||||||
 | 
					        if self.property0 == 'DoF Distance':
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'DoF Distance', default_value=10.0)#6
 | 
				
			||||||
 | 
					        if self.property0 == 'DoF Length': 
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'DoF Length', default_value=160.0)#7
 | 
				
			||||||
 | 
					        if self.property0 == 'DoF F-Stop':    
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'DoF F-Stop', default_value=128.0)#8
 | 
				
			||||||
 | 
					        if self.property0 == 'Tonemapping':   
 | 
				
			||||||
 | 
					            self.add_input('LnxBoolSocket', 'Tonemapping', default_value=False)#9
 | 
				
			||||||
 | 
					        if self.property0 == 'Distort':    
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Distort', default_value=2.0)#10
 | 
				
			||||||
 | 
					        if self.property0 == 'Film Grain':    
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Film Grain', default_value=2.0)#11
 | 
				
			||||||
 | 
					        if self.property0 == 'Sharpen':    
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Sharpen', default_value=0.25)#12
 | 
				
			||||||
 | 
					        if self.property0 == 'Vignette':    
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Vignette', default_value=0.7)#13
 | 
				
			||||||
 | 
					        if self.property0 == 'Exposure':    
 | 
				
			||||||
 | 
					            self.add_input('LnxFloatSocket', 'Exposure', default_value=1)#14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    property0: HaxeEnumProperty(
 | 
				
			||||||
 | 
					    'property0',
 | 
				
			||||||
 | 
					    items = [('F-stop', 'F-stop', 'F-stop'),
 | 
				
			||||||
 | 
					             ('Shutter Time', 'Shutter Time', 'Shutter Time'),
 | 
				
			||||||
 | 
					             ('ISO', 'ISO', 'ISO'),
 | 
				
			||||||
 | 
					             ('Exposure Compensation', 'Exposure Compensation', 'Exposure Compensation'),
 | 
				
			||||||
 | 
					             ('Fisheye Distortion', 'Fisheye Distortion', 'Fisheye Distortion'),
 | 
				
			||||||
 | 
					             ('Auto Focus', 'Auto Focus', 'Auto Focus'),
 | 
				
			||||||
 | 
					             ('DoF Distance', 'DoF Distance', 'DoF Distance'),
 | 
				
			||||||
 | 
					             ('DoF Length', 'DoF Length', 'DoF Length'),
 | 
				
			||||||
 | 
					             ('DoF F-Stop', 'DoF F-Stop', 'DoF F-Stop'),
 | 
				
			||||||
 | 
					             ('Tonemapping', 'Tonemapping', 'Tonemapping'),
 | 
				
			||||||
 | 
					             ('Distort', 'Distort', 'Distort'),
 | 
				
			||||||
 | 
					             ('Film Grain', 'Film Grain', 'Film Grain'),
 | 
				
			||||||
 | 
					             ('Sharpen', 'Sharpen', 'Sharpen'),
 | 
				
			||||||
 | 
					             ('Vignette', 'Vignette', 'Vignette'),
 | 
				
			||||||
 | 
					             ('Exposure', 'Exposure', 'Exposure')],
 | 
				
			||||||
 | 
					    name='', default='F-stop', update=remove_extra_inputs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lnx_init(self, context):
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
        self.add_input('LnxNodeSocketAction', 'In')
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'F-stop', default_value=1.0)#0
 | 
					        self.add_input('LnxFloatSocket', 'F-stop', default_value=1.0)
 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Shutter Time', default_value=2.8333)#1
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'ISO', default_value=100.0)#2
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Exposure Compensation', default_value=0.0)#3
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Fisheye Distortion', default_value=0.01)#4
 | 
					 | 
				
			||||||
        self.add_input('LnxBoolSocket', 'Auto Focus', default_value=True)#5
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'DoF Distance', default_value=10.0)#6
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'DoF Length', default_value=160.0)#7
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'DoF F-Stop', default_value=128.0)#8
 | 
					 | 
				
			||||||
        self.add_input('LnxBoolSocket', 'Tonemapping', default_value=False)#9
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Distort', default_value=2.0)#10
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Film Grain', default_value=2.0)#11
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Sharpen', default_value=0.25)#12
 | 
					 | 
				
			||||||
        self.add_input('LnxFloatSocket', 'Vignette', default_value=0.7)#13
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def draw_buttons(self, context, layout):
 | 
				
			||||||
 | 
					        layout.prop(self, 'property0')
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
					    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
				
			||||||
        if self.lnx_version not in range(0, 4):
 | 
					        if self.lnx_version not in range(0, 4):
 | 
				
			||||||
            raise LookupError()
 | 
					            raise LookupError()
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SharpenSetNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Set the sharpen post-processing settings."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNSharpenSetNode'
 | 
				
			||||||
 | 
					    bl_label = 'Set Sharpen Settings'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
 | 
					        self.add_input('LnxColorSocket', 'Color', default_value=[0.0, 0.0, 0.0, 1.0])
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Size', default_value=2.5)
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Strength', default_value=0.25)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out') 
 | 
				
			||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumetricFogSetNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Set the volumetric fog post-processing settings."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNVolumetricFogSetNode'
 | 
				
			||||||
 | 
					    bl_label = 'Set Volumetric Fog Settings'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
 | 
					        self.add_input('LnxColorSocket', 'Color', default_value=[0.5, 0.6, 0.7, 1.0])
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Amount A', default_value=0.25)
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Amount B', default_value=0.50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					from lnx.logicnode.lnx_nodes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VolumetricLightSetNode(LnxLogicTreeNode):
 | 
				
			||||||
 | 
					    """Set the volumetric light post-processing settings."""
 | 
				
			||||||
 | 
					    bl_idname = 'LNVolumetricLightSetNode'
 | 
				
			||||||
 | 
					    bl_label = 'Set Volumetric Light Settings'
 | 
				
			||||||
 | 
					    lnx_version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def lnx_init(self, context):
 | 
				
			||||||
 | 
					        self.add_input('LnxNodeSocketAction', 'In')
 | 
				
			||||||
 | 
					        self.add_input('LnxColorSocket', 'Air Color', default_value=[1.0, 1.0, 1.0, 1.0])
 | 
				
			||||||
 | 
					        self.add_input('LnxFloatSocket', 'Air Turbidity', default_value=1)
 | 
				
			||||||
 | 
					        self.add_input('LnxIntSocket', 'Steps', default_value=20)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.add_output('LnxNodeSocketAction', 'Out')
 | 
				
			||||||
@ -4,12 +4,13 @@ class RpConfigNode(LnxLogicTreeNode):
 | 
				
			|||||||
    """Sets the post process quality."""
 | 
					    """Sets the post process quality."""
 | 
				
			||||||
    bl_idname = 'LNRpConfigNode'
 | 
					    bl_idname = 'LNRpConfigNode'
 | 
				
			||||||
    bl_label = 'Set Post Process Quality'
 | 
					    bl_label = 'Set Post Process Quality'
 | 
				
			||||||
    lnx_version = 1
 | 
					    lnx_version = 2
 | 
				
			||||||
    property0: HaxeEnumProperty(
 | 
					    property0: HaxeEnumProperty(
 | 
				
			||||||
        'property0',
 | 
					        'property0',
 | 
				
			||||||
        items = [('SSGI', 'SSGI', 'SSGI'),
 | 
					        items = [('SSGI', 'SSGI', 'SSGI'),
 | 
				
			||||||
                 ('SSR', 'SSR', 'SSR'),
 | 
					                 ('SSR', 'SSR', 'SSR'),
 | 
				
			||||||
                 ('Bloom', 'Bloom', 'Bloom'),
 | 
					                 ('Bloom', 'Bloom', 'Bloom'),
 | 
				
			||||||
 | 
					                 ('CA', 'CA', 'CA'),
 | 
				
			||||||
                 ('GI', 'GI', 'GI'),
 | 
					                 ('GI', 'GI', 'GI'),
 | 
				
			||||||
                 ('Motion Blur', 'Motion Blur', 'Motion Blur')
 | 
					                 ('Motion Blur', 'Motion Blur', 'Motion Blur')
 | 
				
			||||||
                 ],
 | 
					                 ],
 | 
				
			||||||
@ -23,3 +24,10 @@ class RpConfigNode(LnxLogicTreeNode):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def draw_buttons(self, context, layout):
 | 
					    def draw_buttons(self, context, layout):
 | 
				
			||||||
        layout.prop(self, 'property0')
 | 
					        layout.prop(self, 'property0')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_replacement_node(self, node_tree: bpy.types.NodeTree):
 | 
				
			||||||
 | 
					        if self.lnx_version not in (0, 1):
 | 
				
			||||||
 | 
					            raise LookupError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return NodeReplacement.Identity(self)
 | 
				
			||||||
@ -40,11 +40,11 @@ def add_world_defs():
 | 
				
			|||||||
    if rpdat.rp_hdr == False:
 | 
					    if rpdat.rp_hdr == False:
 | 
				
			||||||
        wrd.world_defs += '_LDR'
 | 
					        wrd.world_defs += '_LDR'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if wrd.lnx_light_ies_texture != '':
 | 
					    if lnx.utils.get_active_scene().world.lnx_light_ies_texture == True:
 | 
				
			||||||
        wrd.world_defs += '_LightIES'
 | 
					        wrd.world_defs += '_LightIES'
 | 
				
			||||||
        assets.add_embedded_data('iestexture.png')
 | 
					        assets.add_embedded_data('iestexture.png')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if wrd.lnx_light_clouds_texture != '':
 | 
					    if lnx.utils.get_active_scene().world.lnx_light_clouds_texture == True:
 | 
				
			||||||
        wrd.world_defs += '_LightClouds'
 | 
					        wrd.world_defs += '_LightClouds'
 | 
				
			||||||
        assets.add_embedded_data('cloudstexture.png')
 | 
					        assets.add_embedded_data('cloudstexture.png')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -82,25 +82,34 @@ def parse_clamp(node: bpy.types.ShaderNodeClamp, out_socket: bpy.types.NodeSocke
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def parse_valtorgb(node: bpy.types.ShaderNodeValToRGB, out_socket: bpy.types.NodeSocket, state: ParserState) -> Union[floatstr, vec3str]:
 | 
					def parse_valtorgb(node: bpy.types.ShaderNodeValToRGB, out_socket: bpy.types.NodeSocket, state: ParserState) -> Union[floatstr, vec3str]:
 | 
				
			||||||
    # Alpha (TODO: make ColorRamp calculation vec4-based and split afterwards)
 | 
					 | 
				
			||||||
    if out_socket == node.outputs[1]:
 | 
					 | 
				
			||||||
        return '1.0'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    input_fac: bpy.types.NodeSocket = node.inputs[0]
 | 
					    input_fac: bpy.types.NodeSocket = node.inputs[0]
 | 
				
			||||||
 | 
					    alpha_out = out_socket == node.outputs[1]
 | 
				
			||||||
    fac: str = c.parse_value_input(input_fac) if input_fac.is_linked else c.to_vec1(input_fac.default_value)
 | 
					    fac: str = c.parse_value_input(input_fac) if input_fac.is_linked else c.to_vec1(input_fac.default_value)
 | 
				
			||||||
    interp = node.color_ramp.interpolation
 | 
					    interp = node.color_ramp.interpolation
 | 
				
			||||||
    elems = node.color_ramp.elements
 | 
					    elems = node.color_ramp.elements
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if len(elems) == 1:
 | 
					    if len(elems) == 1:
 | 
				
			||||||
        return c.to_vec3(elems[0].color)
 | 
					        if alpha_out:
 | 
				
			||||||
 | 
					            return c.to_vec1(elems[0].color[3])  # Return alpha from the color
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return c.to_vec3(elems[0].color)  # Return RGB
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    # Write color array
 | 
					    name_prefix = c.node_name(node.name).upper()
 | 
				
			||||||
    # The last entry is included twice so that the interpolation
 | 
					    
 | 
				
			||||||
    # between indices works (no out of bounds error)
 | 
					    if alpha_out:
 | 
				
			||||||
    cols_var = c.node_name(node.name).upper() + '_COLS'
 | 
					        cols_var = name_prefix + '_ALPHAS'
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        cols_var = name_prefix + '_COLS'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if state.current_pass == ParserPass.REGULAR:
 | 
					    if state.current_pass == ParserPass.REGULAR:
 | 
				
			||||||
 | 
					        if alpha_out:
 | 
				
			||||||
 | 
					            cols_entries = ', '.join(f'{elem.color[3]}' for elem in elems)
 | 
				
			||||||
 | 
					            # Add last value twice to avoid out of bounds access
 | 
				
			||||||
 | 
					            cols_entries += f', {elems[len(elems) - 1].color[3]}'
 | 
				
			||||||
 | 
					            state.curshader.add_const("float", cols_var, cols_entries, array_size=len(elems) + 1)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            # Create array of RGB values for color output
 | 
				
			||||||
            cols_entries = ', '.join(f'vec3({elem.color[0]}, {elem.color[1]}, {elem.color[2]})' for elem in elems)
 | 
					            cols_entries = ', '.join(f'vec3({elem.color[0]}, {elem.color[1]}, {elem.color[2]})' for elem in elems)
 | 
				
			||||||
            cols_entries += f', vec3({elems[len(elems) - 1].color[0]}, {elems[len(elems) - 1].color[1]}, {elems[len(elems) - 1].color[2]})'
 | 
					            cols_entries += f', vec3({elems[len(elems) - 1].color[0]}, {elems[len(elems) - 1].color[1]}, {elems[len(elems) - 1].color[2]})'
 | 
				
			||||||
            state.curshader.add_const("vec3", cols_var, cols_entries, array_size=len(elems) + 1)
 | 
					            state.curshader.add_const("vec3", cols_var, cols_entries, array_size=len(elems) + 1)
 | 
				
			||||||
@ -121,21 +130,22 @@ def parse_valtorgb(node: bpy.types.ShaderNodeValToRGB, out_socket: bpy.types.Nod
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # Linear interpolation
 | 
					    # Linear interpolation
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        # Write factor array
 | 
					        # Write factor array - same for both color and alpha
 | 
				
			||||||
        facs_var = c.node_name(node.name).upper() + '_FACS'
 | 
					        facs_var = name_prefix + '_FACS'
 | 
				
			||||||
        if state.current_pass == ParserPass.REGULAR:
 | 
					        if state.current_pass == ParserPass.REGULAR:
 | 
				
			||||||
            facs_entries = ', '.join(str(elem.position) for elem in elems)
 | 
					            facs_entries = ', '.join(str(elem.position) for elem in elems)
 | 
				
			||||||
            # Add one more entry at the rightmost position so that the
 | 
					            # Add one more entry at the rightmost position to avoid out of bounds access
 | 
				
			||||||
            # interpolation between indices works (no out of bounds error)
 | 
					 | 
				
			||||||
            facs_entries += ', 1.0'
 | 
					            facs_entries += ', 1.0'
 | 
				
			||||||
            state.curshader.add_const("float", facs_var, facs_entries, array_size=len(elems) + 1)
 | 
					            state.curshader.add_const("float", facs_var, facs_entries, array_size=len(elems) + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Mix color
 | 
					        # Calculation for interpolation position
 | 
				
			||||||
        prev_stop_fac = f'{facs_var}[{index_var}]'
 | 
					        prev_stop_fac = f'{facs_var}[{index_var}]'
 | 
				
			||||||
        next_stop_fac = f'{facs_var}[{index_var} + 1]'
 | 
					        next_stop_fac = f'{facs_var}[{index_var} + 1]'
 | 
				
			||||||
        prev_stop_col = f'{cols_var}[{index_var}]'
 | 
					        prev_stop_col = f'{cols_var}[{index_var}]'
 | 
				
			||||||
        next_stop_col = f'{cols_var}[{index_var} + 1]'
 | 
					        next_stop_col = f'{cols_var}[{index_var} + 1]'
 | 
				
			||||||
        rel_pos = f'({fac_var} - {prev_stop_fac}) * (1.0 / ({next_stop_fac} - {prev_stop_fac}))'
 | 
					        rel_pos = f'({fac_var} - {prev_stop_fac}) * (1.0 / ({next_stop_fac} - {prev_stop_fac}))'
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Use mix function for both alpha and color outputs (mix works on floats too)
 | 
				
			||||||
        return f'mix({prev_stop_col}, {next_stop_col}, max({rel_pos}, 0.0))'
 | 
					        return f'mix({prev_stop_col}, {next_stop_col}, max({rel_pos}, 0.0))'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if bpy.app.version > (3, 2, 0):
 | 
					if bpy.app.version > (3, 2, 0):
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import bpy
 | 
				
			||||||
import lnx.utils
 | 
					import lnx.utils
 | 
				
			||||||
import lnx.material.mat_state as mat_state
 | 
					import lnx.material.mat_state as mat_state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,6 +11,48 @@ else:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def write(vert, particle_info=None, shadowmap=False):
 | 
					def write(vert, particle_info=None, shadowmap=False):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ramp_el_len = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ramp_positions = []
 | 
				
			||||||
 | 
					    ramp_colors_b = []
 | 
				
			||||||
 | 
					    size_over_time_factor = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use_rotations = False
 | 
				
			||||||
 | 
					    rotation_mode = 'NONE'
 | 
				
			||||||
 | 
					    rotation_factor_random = 0
 | 
				
			||||||
 | 
					    phase_factor = 0
 | 
				
			||||||
 | 
					    phase_factor_random = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for obj in bpy.data.objects:
 | 
				
			||||||
 | 
					        for psys in obj.particle_systems:
 | 
				
			||||||
 | 
					            psettings = psys.settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if psettings.instance_object:
 | 
				
			||||||
 | 
					                if psettings.instance_object.active_material:
 | 
				
			||||||
 | 
					                    # FIXME: Different particle systems may share the same particle object. This ideally should check the correct `ParticleSystem` using an id or name in the particle's object material.
 | 
				
			||||||
 | 
					                    if psettings.instance_object.active_material.name.replace(".", "_") == vert.context.matname:
 | 
				
			||||||
 | 
					                        # Rotation data
 | 
				
			||||||
 | 
					                        use_rotations = psettings.use_rotations
 | 
				
			||||||
 | 
					                        rotation_mode = psettings.rotation_mode
 | 
				
			||||||
 | 
					                        rotation_factor_random = psettings.rotation_factor_random
 | 
				
			||||||
 | 
					                        phase_factor = psettings.phase_factor
 | 
				
			||||||
 | 
					                        phase_factor_random = psettings.phase_factor_random
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        # Texture slots data
 | 
				
			||||||
 | 
					                        if psettings.texture_slots and len(psettings.texture_slots.items()) != 0:
 | 
				
			||||||
 | 
					                            for tex_slot in psettings.texture_slots:
 | 
				
			||||||
 | 
					                                if not tex_slot: break
 | 
				
			||||||
 | 
					                                if not tex_slot.use_map_size: break # TODO: check also for other influences
 | 
				
			||||||
 | 
					                                if tex_slot.texture and tex_slot.texture.use_color_ramp:
 | 
				
			||||||
 | 
					                                    if tex_slot.texture.color_ramp and tex_slot.texture.color_ramp.elements:
 | 
				
			||||||
 | 
					                                        ramp_el_len = len(tex_slot.texture.color_ramp.elements.items())
 | 
				
			||||||
 | 
					                                        for element in tex_slot.texture.color_ramp.elements:
 | 
				
			||||||
 | 
					                                            ramp_positions.append(element.position)
 | 
				
			||||||
 | 
					                                            ramp_colors_b.append(element.color[2])
 | 
				
			||||||
 | 
					                                        size_over_time_factor = tex_slot.size_factor
 | 
				
			||||||
 | 
					                                        break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Outs
 | 
					    # Outs
 | 
				
			||||||
    out_index = True if particle_info != None and particle_info['index'] else False
 | 
					    out_index = True if particle_info != None and particle_info['index'] else False
 | 
				
			||||||
    out_age = True if particle_info != None and particle_info['age'] else False
 | 
					    out_age = True if particle_info != None and particle_info['age'] else False
 | 
				
			||||||
@ -19,19 +62,50 @@ def write(vert, particle_info=None, shadowmap=False):
 | 
				
			|||||||
    out_velocity = True if particle_info != None and particle_info['velocity'] else False
 | 
					    out_velocity = True if particle_info != None and particle_info['velocity'] else False
 | 
				
			||||||
    out_angular_velocity = True if particle_info != None and particle_info['angular_velocity'] else False
 | 
					    out_angular_velocity = True if particle_info != None and particle_info['angular_velocity'] else False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Force Leenkx to create a new shader per material ID
 | 
				
			||||||
 | 
					    vert.write(f'#ifdef PARTICLE_ID_{vert.context.material.lnx_material_id}')
 | 
				
			||||||
 | 
					    vert.write('#endif')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vert.add_uniform('mat4 pd', '_particleData')
 | 
					    vert.add_uniform('mat4 pd', '_particleData')
 | 
				
			||||||
 | 
					    vert.add_uniform('float pd_size_random', '_particleSizeRandom')
 | 
				
			||||||
 | 
					    vert.add_uniform('float pd_random', '_particleRandom')
 | 
				
			||||||
 | 
					    vert.add_uniform('float pd_size', '_particleSize')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ramp_el_len != 0:
 | 
				
			||||||
 | 
					        vert.add_const('float', 'P_SIZE_OVER_TIME_FACTOR', str(size_over_time_factor))
 | 
				
			||||||
 | 
					        for i in range(ramp_el_len):
 | 
				
			||||||
 | 
					            vert.add_const('float', f'P_RAMP_POSITION_{i}', str(ramp_positions[i]))
 | 
				
			||||||
 | 
					            vert.add_const('float', f'P_RAMP_COLOR_B_{i}', str(ramp_colors_b[i]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    str_tex_hash = "float fhash(float n) { return fract(sin(n) * 43758.5453); }\n"
 | 
					    str_tex_hash = "float fhash(float n) { return fract(sin(n) * 43758.5453); }\n"
 | 
				
			||||||
    vert.add_function(str_tex_hash)
 | 
					    vert.add_function(str_tex_hash)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ramp_el_len != 0):
 | 
				
			||||||
 | 
					        str_ramp_scale = "float get_ramp_scale(float age) {\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for i in range(ramp_el_len):
 | 
				
			||||||
 | 
					            if i == 0:
 | 
				
			||||||
 | 
					                str_ramp_scale += f"if (age <= P_RAMP_POSITION_{i + 1})"
 | 
				
			||||||
 | 
					            elif i == ramp_el_len - 1:
 | 
				
			||||||
 | 
					                str_ramp_scale += f"return P_RAMP_COLOR_B_{ramp_el_len - 1};"
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                str_ramp_scale += f"else if (age <= P_RAMP_POSITION_{i + 1})"
 | 
				
			||||||
 | 
					            str_ramp_scale += f""" {{
 | 
				
			||||||
 | 
					                float t = (age - P_RAMP_POSITION_{i}) / (P_RAMP_POSITION_{i + 1} - P_RAMP_POSITION_{i});
 | 
				
			||||||
 | 
					                return mix(P_RAMP_COLOR_B_{i}, P_RAMP_COLOR_B_{i + 1}, t);
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					        str_ramp_scale += "}\n"
 | 
				
			||||||
 | 
					        vert.add_function(str_ramp_scale)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    prep = 'float '
 | 
					    prep = 'float '
 | 
				
			||||||
    if out_age:
 | 
					    if out_age:
 | 
				
			||||||
        prep = ''
 | 
					        prep = ''
 | 
				
			||||||
        vert.add_out('float p_age')
 | 
					        vert.add_out('float p_age')
 | 
				
			||||||
    # var p_age = lapTime - p.i * spawnRate
 | 
					    # var p_age = lapTime - p.i * spawnRate
 | 
				
			||||||
    vert.write(prep + 'p_age = pd[3][3] - gl_InstanceID * pd[0][1];')
 | 
					    vert.write(prep + 'p_age = pd[3][3] - gl_InstanceID * pd[0][1];')
 | 
				
			||||||
    # p_age -= p_age * fhash(i) * r.lifetime_random;
 | 
					 | 
				
			||||||
    vert.write('p_age -= p_age * fhash(gl_InstanceID) * pd[2][3];')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Loop
 | 
					    # Loop
 | 
				
			||||||
    # pd[0][0] - animtime, loop stored in sign
 | 
					    # pd[0][0] - animtime, loop stored in sign
 | 
				
			||||||
@ -43,13 +117,18 @@ def write(vert, particle_info=None, shadowmap=False):
 | 
				
			|||||||
    if out_lifetime:
 | 
					    if out_lifetime:
 | 
				
			||||||
        prep = ''
 | 
					        prep = ''
 | 
				
			||||||
        vert.add_out('float p_lifetime')
 | 
					        vert.add_out('float p_lifetime')
 | 
				
			||||||
    vert.write(prep + 'p_lifetime = pd[0][2];')
 | 
					    vert.write(prep + 'p_lifetime = pd[0][2] * (1 - (fhash(gl_InstanceID + 4 * pd[0][3] + pd_random) * pd[2][3]));')
 | 
				
			||||||
    # clip with nan
 | 
					    # clip with nan
 | 
				
			||||||
    vert.write('if (p_age < 0 || p_age > p_lifetime) {')
 | 
					    vert.write('if (p_age < 0 || p_age > p_lifetime) {')
 | 
				
			||||||
    vert.write('    gl_Position /= 0.0;')
 | 
					    vert.write('    gl_Position /= 0.0;')
 | 
				
			||||||
    vert.write('    return;')
 | 
					    vert.write('    return;')
 | 
				
			||||||
    vert.write('}')
 | 
					    vert.write('}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ramp_el_len != 0):
 | 
				
			||||||
 | 
					        vert.write('float n_age = clamp(p_age / p_lifetime, 0.0, 1.0);')
 | 
				
			||||||
 | 
					        vert.write(f'spos.xyz *= 1 + (get_ramp_scale(n_age) - 1) * {size_over_time_factor};')
 | 
				
			||||||
 | 
					    vert.write('spos.xyz *= 1 - (fhash(gl_InstanceID + 3 * pd[0][3] + pd_random) * pd_size_random);')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # vert.write('p_age /= 2;') # Match
 | 
					    # vert.write('p_age /= 2;') # Match
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # object_align_factor / 2 + gxyz
 | 
					    # object_align_factor / 2 + gxyz
 | 
				
			||||||
@ -57,20 +136,20 @@ def write(vert, particle_info=None, shadowmap=False):
 | 
				
			|||||||
    if out_velocity:
 | 
					    if out_velocity:
 | 
				
			||||||
        prep = ''
 | 
					        prep = ''
 | 
				
			||||||
        vert.add_out('vec3 p_velocity')
 | 
					        vert.add_out('vec3 p_velocity')
 | 
				
			||||||
    vert.write(prep + 'p_velocity = vec3(pd[1][0], pd[1][1], pd[1][2]);')
 | 
					    vert.write(prep + 'p_velocity = vec3(pd[1][0] * (1 / pd_size), pd[1][1] * (1 / pd_size), pd[1][2] * (1 / pd_size));')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vert.write('p_velocity.x += fhash(gl_InstanceID)                * pd[1][3] - pd[1][3] / 2;')
 | 
					    vert.write('p_velocity.x += (fhash(gl_InstanceID + pd_random)                * 2.0 / pd_size - 1.0 / pd_size) * pd[1][3];')
 | 
				
			||||||
    vert.write('p_velocity.y += fhash(gl_InstanceID +     pd[0][3]) * pd[1][3] - pd[1][3] / 2;')
 | 
					    vert.write('p_velocity.y += (fhash(gl_InstanceID + pd_random +     pd[0][3]) * 2.0 / pd_size - 1.0 / pd_size) * pd[1][3];')
 | 
				
			||||||
    vert.write('p_velocity.z += fhash(gl_InstanceID + 2 * pd[0][3]) * pd[1][3] - pd[1][3] / 2;')
 | 
					    vert.write('p_velocity.z += (fhash(gl_InstanceID + pd_random + 2 * pd[0][3]) * 2.0 / pd_size - 1.0 / pd_size) * pd[1][3];')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # factor_random = pd[1][3]
 | 
					    # factor_random = pd[1][3]
 | 
				
			||||||
    # p.i = gl_InstanceID
 | 
					    # p.i = gl_InstanceID
 | 
				
			||||||
    # particles.length = pd[0][3]
 | 
					    # particles.length = pd[0][3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # gxyz
 | 
					    # gxyz
 | 
				
			||||||
    vert.write('p_velocity.x += (pd[2][0] * p_age) / 5;')
 | 
					    vert.write('p_velocity.x += (pd[2][0] / (2 * pd_size)) * p_age;')
 | 
				
			||||||
    vert.write('p_velocity.y += (pd[2][1] * p_age) / 5;')
 | 
					    vert.write('p_velocity.y += (pd[2][1] / (2 * pd_size)) * p_age;')
 | 
				
			||||||
    vert.write('p_velocity.z += (pd[2][2] * p_age) / 5;')
 | 
					    vert.write('p_velocity.z += (pd[2][2] / (2 * pd_size)) * p_age;')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    prep = 'vec3 '
 | 
					    prep = 'vec3 '
 | 
				
			||||||
    if out_location:
 | 
					    if out_location:
 | 
				
			||||||
@ -80,6 +159,96 @@ def write(vert, particle_info=None, shadowmap=False):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    vert.write('spos.xyz += p_location;')
 | 
					    vert.write('spos.xyz += p_location;')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Rotation
 | 
				
			||||||
 | 
					    if use_rotations:
 | 
				
			||||||
 | 
					        if rotation_mode != 'NONE':
 | 
				
			||||||
 | 
					            vert.write(f'float p_angle = ({phase_factor} + (fhash(gl_InstanceID + pd_random + 5 * pd[0][3])) * {phase_factor_random});')
 | 
				
			||||||
 | 
					            vert.write('p_angle *= 3.141592;')
 | 
				
			||||||
 | 
					            vert.write('float c = cos(p_angle);')
 | 
				
			||||||
 | 
					            vert.write('float s = sin(p_angle);')
 | 
				
			||||||
 | 
					            vert.write('vec3 center = spos.xyz - p_location;')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            match rotation_mode:
 | 
				
			||||||
 | 
					                case 'OB_X':
 | 
				
			||||||
 | 
					                    vert.write('vec3 rz = vec3(center.y, -center.x, center.z);')
 | 
				
			||||||
 | 
					                    vert.write('vec2 rotation = vec2(rz.y * c - rz.z * s, rz.y * s + rz.z * c);')
 | 
				
			||||||
 | 
					                    vert.write('spos.xyz = vec3(rz.x, rotation.x, rotation.y) + p_location;')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (not shadowmap):
 | 
				
			||||||
 | 
					                        vert.write('wnormal = vec3(wnormal.y, -wnormal.x, wnormal.z);')
 | 
				
			||||||
 | 
					                        vert.write('vec2 n_rot = vec2(wnormal.y * c - wnormal.z * s, wnormal.y * s + wnormal.z * c);')
 | 
				
			||||||
 | 
					                        vert.write('wnormal = normalize(vec3(wnormal.x, n_rot.x, n_rot.y));')
 | 
				
			||||||
 | 
					                case 'OB_Y':
 | 
				
			||||||
 | 
					                    vert.write('vec2 rotation = vec2(center.x * c + center.z * s, -center.x * s + center.z * c);')
 | 
				
			||||||
 | 
					                    vert.write('spos.xyz = vec3(rotation.x, center.y, rotation.y) + p_location;')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (not shadowmap):
 | 
				
			||||||
 | 
					                        vert.write('wnormal = normalize(vec3(wnormal.x * c + wnormal.z * s, wnormal.y, -wnormal.x * s + wnormal.z * c));')
 | 
				
			||||||
 | 
					                case 'OB_Z':
 | 
				
			||||||
 | 
					                    vert.write('vec3 rz = vec3(center.y, -center.x, center.z);')
 | 
				
			||||||
 | 
					                    vert.write('vec3 ry = vec3(-rz.z, rz.y, rz.x);')
 | 
				
			||||||
 | 
					                    vert.write('vec2 rotation = vec2(ry.x * c - ry.y * s, ry.x * s + ry.y * c);')
 | 
				
			||||||
 | 
					                    vert.write('spos.xyz = vec3(rotation.x, rotation.y, ry.z) + p_location;')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (not shadowmap):
 | 
				
			||||||
 | 
					                        vert.write('wnormal = vec3(wnormal.y, -wnormal.x, wnormal.z);')
 | 
				
			||||||
 | 
					                        vert.write('wnormal = vec3(-wnormal.z, wnormal.y, wnormal.x);')
 | 
				
			||||||
 | 
					                        vert.write('vec2 n_rot = vec2(wnormal.x * c - wnormal.y * s, wnormal.x * s + wnormal.y * c);')
 | 
				
			||||||
 | 
					                        vert.write('wnormal = normalize(vec3(n_rot.x, n_rot.y, wnormal.z));')
 | 
				
			||||||
 | 
					                case 'VEL':
 | 
				
			||||||
 | 
					                    vert.write('vec3 forward = -normalize(p_velocity);')
 | 
				
			||||||
 | 
					                    vert.write('if (length(forward) > 1e-5) {')
 | 
				
			||||||
 | 
					                    vert.write('vec3 world_up = vec3(0.0, 0.0, 1.0);')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    vert.write('if (abs(dot(forward, world_up)) > 0.999) {')
 | 
				
			||||||
 | 
					                    vert.write('world_up = vec3(-1.0, 0.0, 0.0);')
 | 
				
			||||||
 | 
					                    vert.write('}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    vert.write('vec3 right = cross(world_up, forward);')
 | 
				
			||||||
 | 
					                    vert.write('if (length(right) < 1e-5) {')
 | 
				
			||||||
 | 
					                    vert.write('forward = -forward;')
 | 
				
			||||||
 | 
					                    vert.write('right = cross(world_up, forward);')
 | 
				
			||||||
 | 
					                    vert.write('}')
 | 
				
			||||||
 | 
					                    vert.write('right = normalize(right);')
 | 
				
			||||||
 | 
					                    vert.write('vec3 up = normalize(cross(forward, right));')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    vert.write('mat3 rot = mat3(right, -forward, up);')
 | 
				
			||||||
 | 
					                    vert.write('mat3 phase = mat3(vec3(c, 0.0, -s), vec3(0.0, 1.0, 0.0), vec3(s, 0.0, c));')
 | 
				
			||||||
 | 
					                    vert.write('mat3 final_rot = rot * phase;')
 | 
				
			||||||
 | 
					                    vert.write('spos.xyz = final_rot * center + p_location;')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (not shadowmap):
 | 
				
			||||||
 | 
					                        vert.write('wnormal = normalize(final_rot * wnormal);')
 | 
				
			||||||
 | 
					                    vert.write('}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if rotation_factor_random != 0:
 | 
				
			||||||
 | 
					                str_rotate_around = '''vec3 rotate_around(vec3 v, vec3 angle) {
 | 
				
			||||||
 | 
					                    // Rotate around X
 | 
				
			||||||
 | 
					                    float cx = cos(angle.x);
 | 
				
			||||||
 | 
					                    float sx = sin(angle.x);
 | 
				
			||||||
 | 
					                    v = vec3(v.x, v.y * cx - v.z * sx, v.y * sx + v.z * cx);
 | 
				
			||||||
 | 
					                    // Rotate around Y
 | 
				
			||||||
 | 
					                    float cy = cos(angle.y);
 | 
				
			||||||
 | 
					                    float sy = sin(angle.y);
 | 
				
			||||||
 | 
					                    v = vec3(v.x * cy + v.z * sy, v.y, -v.x * sy + v.z * cy);
 | 
				
			||||||
 | 
					                    // Rotate around Z
 | 
				
			||||||
 | 
					                    float cz = cos(angle.z);
 | 
				
			||||||
 | 
					                    float sz = sin(angle.z);
 | 
				
			||||||
 | 
					                    v = vec3(v.x * cz - v.y * sz, v.x * sz + v.y * cz, v.z);
 | 
				
			||||||
 | 
					                    return v;
 | 
				
			||||||
 | 
					                }'''
 | 
				
			||||||
 | 
					                vert.add_function(str_rotate_around)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                vert.write(f'''vec3 r_angle = vec3((fhash(gl_InstanceID + pd_random + 6 * pd[0][3]) * 4 - 2) * {rotation_factor_random},
 | 
				
			||||||
 | 
					                           (fhash(gl_InstanceID + pd_random + 7 * pd[0][3]) * 4 - 2) * {rotation_factor_random},
 | 
				
			||||||
 | 
					                           (fhash(gl_InstanceID + pd_random + 8 * pd[0][3]) * 4 - 2) * {rotation_factor_random});''')
 | 
				
			||||||
 | 
					                vert.write('vec3 r_center = spos.xyz - p_location;')
 | 
				
			||||||
 | 
					                vert.write('r_center = rotate_around(r_center, r_angle);')
 | 
				
			||||||
 | 
					                vert.write('spos.xyz = r_center + p_location;')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if not shadowmap:
 | 
				
			||||||
 | 
					                    vert.write('wnormal = normalize(rotate_around(wnormal, r_angle));')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Particle fade
 | 
					    # Particle fade
 | 
				
			||||||
    if mat_state.material.lnx_particle_flag and lnx.utils.get_rp().lnx_particles == 'On' and mat_state.material.lnx_particle_fade:
 | 
					    if mat_state.material.lnx_particle_flag and lnx.utils.get_rp().lnx_particles == 'On' and mat_state.material.lnx_particle_fade:
 | 
				
			||||||
        vert.add_out('float p_fade')
 | 
					        vert.add_out('float p_fade')
 | 
				
			||||||
 | 
				
			|||||||
@ -197,6 +197,10 @@ def init_properties():
 | 
				
			|||||||
        items=[('Bullet', 'Bullet', 'Bullet'),
 | 
					        items=[('Bullet', 'Bullet', 'Bullet'),
 | 
				
			||||||
               ('Oimo', 'Oimo', 'Oimo')],
 | 
					               ('Oimo', 'Oimo', 'Oimo')],
 | 
				
			||||||
        name="Physics Engine", default='Bullet', update=assets.invalidate_compiler_cache)
 | 
					        name="Physics Engine", default='Bullet', update=assets.invalidate_compiler_cache)
 | 
				
			||||||
 | 
					    bpy.types.World.lnx_physics_fixed_step = FloatProperty(
 | 
				
			||||||
 | 
					        name="Fixed Step", default=1/60, min=0, max=1,
 | 
				
			||||||
 | 
					        description="Physics steps for fixed update"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
    bpy.types.World.lnx_physics_dbg_draw_wireframe = BoolProperty(
 | 
					    bpy.types.World.lnx_physics_dbg_draw_wireframe = BoolProperty(
 | 
				
			||||||
        name="Collider Wireframes", default=False,
 | 
					        name="Collider Wireframes", default=False,
 | 
				
			||||||
        description="Draw wireframes of the physics collider meshes and suspensions of raycast vehicle simulations"
 | 
					        description="Draw wireframes of the physics collider meshes and suspensions of raycast vehicle simulations"
 | 
				
			||||||
@ -358,6 +362,7 @@ def init_properties():
 | 
				
			|||||||
    bpy.types.Object.lnx_rb_trigger = BoolProperty(name="Trigger", description="Disable contact response", default=False)
 | 
					    bpy.types.Object.lnx_rb_trigger = BoolProperty(name="Trigger", description="Disable contact response", default=False)
 | 
				
			||||||
    bpy.types.Object.lnx_rb_deactivation_time = FloatProperty(name="Deactivation Time", description="Delay putting rigid body into sleep", default=0.0)
 | 
					    bpy.types.Object.lnx_rb_deactivation_time = FloatProperty(name="Deactivation Time", description="Delay putting rigid body into sleep", default=0.0)
 | 
				
			||||||
    bpy.types.Object.lnx_rb_ccd = BoolProperty(name="Continuous Collision Detection", description="Improve collision for fast moving objects", default=False)
 | 
					    bpy.types.Object.lnx_rb_ccd = BoolProperty(name="Continuous Collision Detection", description="Improve collision for fast moving objects", default=False)
 | 
				
			||||||
 | 
					    bpy.types.Object.lnx_rb_interpolate = BoolProperty(name="Interpolation", description="Smooths out the object's transform on physics steps", default=False)
 | 
				
			||||||
    bpy.types.Object.lnx_rb_collision_filter_mask = bpy.props.BoolVectorProperty(
 | 
					    bpy.types.Object.lnx_rb_collision_filter_mask = bpy.props.BoolVectorProperty(
 | 
				
			||||||
            name="Collision Collections Filter Mask",
 | 
					            name="Collision Collections Filter Mask",
 | 
				
			||||||
            description="Collision collections rigid body interacts with",
 | 
					            description="Collision collections rigid body interacts with",
 | 
				
			||||||
@ -506,8 +511,9 @@ def init_properties():
 | 
				
			|||||||
    bpy.types.Light.lnx_clip_end = FloatProperty(name="Clip End", default=50.0)
 | 
					    bpy.types.Light.lnx_clip_end = FloatProperty(name="Clip End", default=50.0)
 | 
				
			||||||
    bpy.types.Light.lnx_fov = FloatProperty(name="Field of View", default=0.84)
 | 
					    bpy.types.Light.lnx_fov = FloatProperty(name="Field of View", default=0.84)
 | 
				
			||||||
    bpy.types.Light.lnx_shadows_bias = FloatProperty(name="Bias", description="Depth offset to fight shadow acne", default=1.0)
 | 
					    bpy.types.Light.lnx_shadows_bias = FloatProperty(name="Bias", description="Depth offset to fight shadow acne", default=1.0)
 | 
				
			||||||
    bpy.types.World.lnx_light_ies_texture = StringProperty(name="IES Texture", default="")
 | 
					    # For world
 | 
				
			||||||
    bpy.types.World.lnx_light_clouds_texture = StringProperty(name="Clouds Texture", default="")
 | 
					    bpy.types.World.lnx_light_ies_texture = BoolProperty(name="IES Texture (iestexture.png)", default=False, update=assets.invalidate_compiler_cache)
 | 
				
			||||||
 | 
					    bpy.types.World.lnx_light_clouds_texture = BoolProperty(name="Clouds Texture (cloudstexture.png)", default=False, update=assets.invalidate_compiler_cache)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bpy.types.World.lnx_rpcache_list = CollectionProperty(type=bpy.types.PropertyGroup)
 | 
					    bpy.types.World.lnx_rpcache_list = CollectionProperty(type=bpy.types.PropertyGroup)
 | 
				
			||||||
    bpy.types.World.lnx_scripts_list = CollectionProperty(type=bpy.types.PropertyGroup)
 | 
					    bpy.types.World.lnx_scripts_list = CollectionProperty(type=bpy.types.PropertyGroup)
 | 
				
			||||||
@ -542,8 +548,10 @@ def init_properties():
 | 
				
			|||||||
    bpy.types.Node.lnx_watch = BoolProperty(name="Watch", description="Watch value of this node in debug console", default=False)
 | 
					    bpy.types.Node.lnx_watch = BoolProperty(name="Watch", description="Watch value of this node in debug console", default=False)
 | 
				
			||||||
    bpy.types.Node.lnx_version = IntProperty(name="Node Version", description="The version of an instanced node", default=0)
 | 
					    bpy.types.Node.lnx_version = IntProperty(name="Node Version", description="The version of an instanced node", default=0)
 | 
				
			||||||
    # Particles
 | 
					    # Particles
 | 
				
			||||||
    bpy.types.ParticleSettings.lnx_count_mult = FloatProperty(name="Multiply Count", description="Multiply particle count when rendering in Leenkx", default=1.0)
 | 
					    bpy.types.ParticleSettings.lnx_auto_start = BoolProperty(name="Auto Start", description="Automatically start this particle system on load", default=True)
 | 
				
			||||||
 | 
					    bpy.types.ParticleSettings.lnx_is_unique = BoolProperty(name="Is Unique", description="Make this particle system look different each time it starts", default=False)
 | 
				
			||||||
    bpy.types.ParticleSettings.lnx_loop = BoolProperty(name="Loop", description="Loop this particle system", default=False)
 | 
					    bpy.types.ParticleSettings.lnx_loop = BoolProperty(name="Loop", description="Loop this particle system", default=False)
 | 
				
			||||||
 | 
					    bpy.types.ParticleSettings.lnx_count_mult = FloatProperty(name="Multiply Count", description="Multiply particle count when rendering in Leenkx", default=1.0)
 | 
				
			||||||
    # Actions
 | 
					    # Actions
 | 
				
			||||||
    bpy.types.Action.lnx_root_motion_pos = BoolProperty(name="Root Motion Position", description="Enable position root motion", default=False)
 | 
					    bpy.types.Action.lnx_root_motion_pos = BoolProperty(name="Root Motion Position", description="Enable position root motion", default=False)
 | 
				
			||||||
    bpy.types.Action.lnx_root_motion_rot = BoolProperty(name="Root Motion Rotation", description="Enable rotation root motion", default=False)
 | 
					    bpy.types.Action.lnx_root_motion_rot = BoolProperty(name="Root Motion Rotation", description="Enable rotation root motion", default=False)
 | 
				
			||||||
 | 
				
			|||||||
@ -608,6 +608,8 @@ class LnxRPListItem(bpy.types.PropertyGroup):
 | 
				
			|||||||
    lnx_grain: BoolProperty(name="Film Grain", default=False, update=assets.invalidate_shader_cache)
 | 
					    lnx_grain: BoolProperty(name="Film Grain", default=False, update=assets.invalidate_shader_cache)
 | 
				
			||||||
    lnx_grain_strength: FloatProperty(name="Strength", default=2.0, update=assets.invalidate_shader_cache)
 | 
					    lnx_grain_strength: FloatProperty(name="Strength", default=2.0, update=assets.invalidate_shader_cache)
 | 
				
			||||||
    lnx_sharpen: BoolProperty(name="Sharpen", default=False, update=assets.invalidate_shader_cache)
 | 
					    lnx_sharpen: BoolProperty(name="Sharpen", default=False, update=assets.invalidate_shader_cache)
 | 
				
			||||||
 | 
					    lnx_sharpen_color: FloatVectorProperty(name="Color", size=3, default=[0, 0, 0], subtype='COLOR', min=0, max=1, update=assets.invalidate_shader_cache)
 | 
				
			||||||
 | 
					    lnx_sharpen_size: FloatProperty(name="Size", default=2.5, update=assets.invalidate_shader_cache)
 | 
				
			||||||
    lnx_sharpen_strength: FloatProperty(name="Strength", default=0.25, update=assets.invalidate_shader_cache)
 | 
					    lnx_sharpen_strength: FloatProperty(name="Strength", default=0.25, update=assets.invalidate_shader_cache)
 | 
				
			||||||
    lnx_fog: BoolProperty(name="Volumetric Fog", default=False, update=assets.invalidate_shader_cache)
 | 
					    lnx_fog: BoolProperty(name="Volumetric Fog", default=False, update=assets.invalidate_shader_cache)
 | 
				
			||||||
    lnx_fog_color: FloatVectorProperty(name="Color", size=3, subtype='COLOR', default=[0.5, 0.6, 0.7], min=0, max=1, update=assets.invalidate_shader_cache)
 | 
					    lnx_fog_color: FloatVectorProperty(name="Color", size=3, subtype='COLOR', default=[0.5, 0.6, 0.7], min=0, max=1, update=assets.invalidate_shader_cache)
 | 
				
			||||||
 | 
				
			|||||||
@ -205,6 +205,8 @@ class LNX_PT_ParticlesPropsPanel(bpy.types.Panel):
 | 
				
			|||||||
        if obj == None:
 | 
					        if obj == None:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout.prop(obj.settings, 'lnx_auto_start')
 | 
				
			||||||
 | 
					        layout.prop(obj.settings, 'lnx_is_unique')
 | 
				
			||||||
        layout.prop(obj.settings, 'lnx_loop')
 | 
					        layout.prop(obj.settings, 'lnx_loop')
 | 
				
			||||||
        layout.prop(obj.settings, 'lnx_count_mult')
 | 
					        layout.prop(obj.settings, 'lnx_count_mult')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -240,6 +242,7 @@ class LNX_PT_PhysicsPropsPanel(bpy.types.Panel):
 | 
				
			|||||||
            layout.prop(obj, 'lnx_rb_angular_friction')
 | 
					            layout.prop(obj, 'lnx_rb_angular_friction')
 | 
				
			||||||
            layout.prop(obj, 'lnx_rb_trigger')
 | 
					            layout.prop(obj, 'lnx_rb_trigger')
 | 
				
			||||||
            layout.prop(obj, 'lnx_rb_ccd')
 | 
					            layout.prop(obj, 'lnx_rb_ccd')
 | 
				
			||||||
 | 
					            layout.prop(obj, 'lnx_rb_interpolate')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if obj.soft_body is not None:
 | 
					        if obj.soft_body is not None:
 | 
				
			||||||
            layout.prop(obj, 'lnx_soft_body_margin')
 | 
					            layout.prop(obj, 'lnx_soft_body_margin')
 | 
				
			||||||
@ -303,8 +306,6 @@ class LNX_PT_DataPropsPanel(bpy.types.Panel):
 | 
				
			|||||||
            layout.prop(obj.data, 'lnx_clip_end')
 | 
					            layout.prop(obj.data, 'lnx_clip_end')
 | 
				
			||||||
            layout.prop(obj.data, 'lnx_fov')
 | 
					            layout.prop(obj.data, 'lnx_fov')
 | 
				
			||||||
            layout.prop(obj.data, 'lnx_shadows_bias')
 | 
					            layout.prop(obj.data, 'lnx_shadows_bias')
 | 
				
			||||||
            layout.prop(wrd, 'lnx_light_ies_texture')
 | 
					 | 
				
			||||||
            layout.prop(wrd, 'lnx_light_clouds_texture')
 | 
					 | 
				
			||||||
        elif obj.type == 'SPEAKER':
 | 
					        elif obj.type == 'SPEAKER':
 | 
				
			||||||
            layout.prop(obj.data, 'lnx_play_on_start')
 | 
					            layout.prop(obj.data, 'lnx_play_on_start')
 | 
				
			||||||
            layout.prop(obj.data, 'lnx_loop')
 | 
					            layout.prop(obj.data, 'lnx_loop')
 | 
				
			||||||
@ -332,6 +333,8 @@ class LNX_PT_WorldPropsPanel(bpy.types.Panel):
 | 
				
			|||||||
        if world is None:
 | 
					        if world is None:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout.prop(world, 'lnx_light_ies_texture')
 | 
				
			||||||
 | 
					        layout.prop(world, 'lnx_light_clouds_texture')
 | 
				
			||||||
        layout.prop(world, 'lnx_use_clouds')
 | 
					        layout.prop(world, 'lnx_use_clouds')
 | 
				
			||||||
        col = layout.column(align=True)
 | 
					        col = layout.column(align=True)
 | 
				
			||||||
        col.enabled = world.lnx_use_clouds
 | 
					        col.enabled = world.lnx_use_clouds
 | 
				
			||||||
@ -1991,10 +1994,18 @@ class LNX_PT_RenderPathCompositorPanel(bpy.types.Panel):
 | 
				
			|||||||
        col.prop(rpdat, 'lnx_letterbox_size')
 | 
					        col.prop(rpdat, 'lnx_letterbox_size')
 | 
				
			||||||
        layout.separator()
 | 
					        layout.separator()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        col = layout.column()
 | 
				
			||||||
 | 
					        col.prop(rpdat, 'lnx_sharpen')
 | 
				
			||||||
 | 
					        col = col.column(align=True)
 | 
				
			||||||
 | 
					        col.enabled = rpdat.lnx_sharpen
 | 
				
			||||||
 | 
					        col.prop(rpdat, 'lnx_sharpen_color')
 | 
				
			||||||
 | 
					        col.prop(rpdat, 'lnx_sharpen_size')
 | 
				
			||||||
 | 
					        col.prop(rpdat, 'lnx_sharpen_strength')
 | 
				
			||||||
 | 
					        layout.separator()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        col = layout.column()
 | 
					        col = layout.column()
 | 
				
			||||||
        draw_conditional_prop(col, 'Distort', rpdat, 'lnx_distort', 'lnx_distort_strength')
 | 
					        draw_conditional_prop(col, 'Distort', rpdat, 'lnx_distort', 'lnx_distort_strength')
 | 
				
			||||||
        draw_conditional_prop(col, 'Film Grain', rpdat, 'lnx_grain', 'lnx_grain_strength')
 | 
					        draw_conditional_prop(col, 'Film Grain', rpdat, 'lnx_grain', 'lnx_grain_strength')
 | 
				
			||||||
        draw_conditional_prop(col, 'Sharpen', rpdat, 'lnx_sharpen', 'lnx_sharpen_strength')
 | 
					 | 
				
			||||||
        draw_conditional_prop(col, 'Vignette', rpdat, 'lnx_vignette', 'lnx_vignette_strength')
 | 
					        draw_conditional_prop(col, 'Vignette', rpdat, 'lnx_vignette', 'lnx_vignette_strength')
 | 
				
			||||||
        layout.separator()
 | 
					        layout.separator()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2732,8 +2743,33 @@ class LeenkxUpdateListInstalledVSButton(bpy.types.Operator):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return {'FINISHED'}
 | 
					        return {'FINISHED'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LNX_PT_PhysicsProps(bpy.types.Panel):
 | 
				
			||||||
 | 
					    bl_label = "Leenkx Props"
 | 
				
			||||||
 | 
					    bl_space_type = "PROPERTIES"
 | 
				
			||||||
 | 
					    bl_region_type = "WINDOW"
 | 
				
			||||||
 | 
					    bl_context = "scene"
 | 
				
			||||||
 | 
					    bl_options = {'DEFAULT_CLOSED'}
 | 
				
			||||||
 | 
					    bl_parent_id = "SCENE_PT_rigid_body_world"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LNX_PT_BulletDebugDrawingPanel(bpy.types.Panel):
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def poll(cls, context):
 | 
				
			||||||
 | 
					        return context.scene.rigidbody_world is not None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def draw(self, context):
 | 
				
			||||||
 | 
					        layout = self.layout
 | 
				
			||||||
 | 
					        layout.use_property_split = True
 | 
				
			||||||
 | 
					        layout.use_property_decorate = False
 | 
				
			||||||
 | 
					        wrd = bpy.data.worlds['Lnx']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if wrd.lnx_physics_engine != 'Bullet' and wrd.lnx_physics_engine != 'Oimo':
 | 
				
			||||||
 | 
					            row = layout.row()
 | 
				
			||||||
 | 
					            row.alert = True
 | 
				
			||||||
 | 
					            row.label(text="Physics debug drawing is only supported for the Bullet and Oimo physics engines")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        col = layout.column(align=False)
 | 
				
			||||||
 | 
					        col.prop(wrd, "lnx_physics_fixed_step")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LNX_PT_PhysicsDebugDrawingPanel(bpy.types.Panel):
 | 
				
			||||||
    bl_label = "Leenkx Debug Drawing"
 | 
					    bl_label = "Leenkx Debug Drawing"
 | 
				
			||||||
    bl_space_type = "PROPERTIES"
 | 
					    bl_space_type = "PROPERTIES"
 | 
				
			||||||
    bl_region_type = "WINDOW"
 | 
					    bl_region_type = "WINDOW"
 | 
				
			||||||
@ -2899,7 +2935,8 @@ __REG_CLASSES = (
 | 
				
			|||||||
    LeenkxUpdateListAndroidEmulatorButton,
 | 
					    LeenkxUpdateListAndroidEmulatorButton,
 | 
				
			||||||
    LeenkxUpdateListAndroidEmulatorRunButton,
 | 
					    LeenkxUpdateListAndroidEmulatorRunButton,
 | 
				
			||||||
    LeenkxUpdateListInstalledVSButton,
 | 
					    LeenkxUpdateListInstalledVSButton,
 | 
				
			||||||
    LNX_PT_BulletDebugDrawingPanel,
 | 
					    LNX_PT_PhysicsProps,
 | 
				
			||||||
 | 
					    LNX_PT_PhysicsDebugDrawingPanel,
 | 
				
			||||||
    LNX_OT_AddArmatureRootMotion,
 | 
					    LNX_OT_AddArmatureRootMotion,
 | 
				
			||||||
    scene.TLM_PT_Settings,
 | 
					    scene.TLM_PT_Settings,
 | 
				
			||||||
    scene.TLM_PT_Denoise,
 | 
					    scene.TLM_PT_Denoise,
 | 
				
			||||||
 | 
				
			|||||||
@ -453,6 +453,7 @@ def write_config(resx, resy):
 | 
				
			|||||||
        'rp_ssr': rpdat.rp_ssr != 'Off',
 | 
					        'rp_ssr': rpdat.rp_ssr != 'Off',
 | 
				
			||||||
        'rp_ss_refraction': rpdat.rp_ss_refraction != 'Off',
 | 
					        'rp_ss_refraction': rpdat.rp_ss_refraction != 'Off',
 | 
				
			||||||
        'rp_bloom': rpdat.rp_bloom != 'Off',
 | 
					        'rp_bloom': rpdat.rp_bloom != 'Off',
 | 
				
			||||||
 | 
					        'rp_chromatic_aberration': rpdat.rp_chromatic_aberration != 'Off',
 | 
				
			||||||
        'rp_motionblur': rpdat.rp_motionblur != 'Off',
 | 
					        'rp_motionblur': rpdat.rp_motionblur != 'Off',
 | 
				
			||||||
        'rp_gi': rpdat.rp_voxels != "Off",
 | 
					        'rp_gi': rpdat.rp_voxels != "Off",
 | 
				
			||||||
        'rp_dynres': rpdat.rp_dynres
 | 
					        'rp_dynres': rpdat.rp_dynres
 | 
				
			||||||
@ -772,6 +773,8 @@ const vec3 compoLetterboxColor = vec3(""" + str(round(rpdat.lnx_letterbox_color[
 | 
				
			|||||||
        if lnx.utils.get_active_scene().view_settings.exposure != 0.0:
 | 
					        if lnx.utils.get_active_scene().view_settings.exposure != 0.0:
 | 
				
			||||||
            f.write(
 | 
					            f.write(
 | 
				
			||||||
"""const float compoExposureStrength = """ + str(round(lnx.utils.get_active_scene().view_settings.exposure * 100) / 100) + """;
 | 
					"""const float compoExposureStrength = """ + str(round(lnx.utils.get_active_scene().view_settings.exposure * 100) / 100) + """;
 | 
				
			||||||
 | 
					const float compoSharpenSize = """ + str(round(rpdat.lnx_sharpen_size * 100) / 100) + """;
 | 
				
			||||||
 | 
					const vec3 compoSharpenColor = vec3(""" + str(round(rpdat.lnx_sharpen_color[0] * 100) / 100) + """, """ + str(round(rpdat.lnx_sharpen_color[1] * 100) / 100) + """, """ + str(round(rpdat.lnx_sharpen_color[2] * 100) / 100) + """);
 | 
				
			||||||
""")
 | 
					""")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if rpdat.lnx_fog:
 | 
					        if rpdat.lnx_fog:
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user