forked from LeenkxTeam/LNXSDK
Compare commits
178 Commits
Author | SHA1 | Date | |
---|---|---|---|
cdc425fbcb | |||
846bb28c86 | |||
7fabd77ef8 | |||
fb1a5c88bf | |||
e05c83a8bb | |||
ee4f62e881 | |||
59f8dff22f | |||
5572226ac5 | |||
d04874e0b3 | |||
ef8b3a99ab | |||
1d3254a237 | |||
188af4a50f | |||
c45baaf396 | |||
4b1da08819 | |||
aeb353fb20 | |||
65961b1593 | |||
1c472155e2 | |||
4238f0b2a0 | |||
b40aadf76c | |||
7277987335 | |||
a48ec4d034 | |||
7f0153f816 | |||
40d893e139 | |||
9b9289d27d | |||
8786798edd | |||
fa425a98a5 | |||
5165769088 | |||
feabf446db | |||
e770120f7d | |||
7c1b1f2dd9 | |||
88a4f0e76a | |||
d9e613b3eb | |||
a0c84dc807 | |||
5a92920b1f | |||
30a624c857 | |||
8153d67eac | |||
9963a42c76 | |||
885385d7cb | |||
c433a7f09e | |||
c7e2c7d452 | |||
2a1235b3d8 | |||
074962d158 | |||
3ea0d7da9d | |||
00b580a4fa | |||
f779462f36 | |||
2c7343aa31 | |||
85912d84fb | |||
ad0d750dd0 | |||
9914d53045 | |||
9daf6c15ab | |||
9ac3de67aa | |||
fd02f6bca3 | |||
2cc0d3db3b | |||
fe730a65ee | |||
18ec9712fd | |||
0d80f3fb6d | |||
be06b222cb | |||
3f0984e227 | |||
15a10ea3aa | |||
012abfeaf6 | |||
dd6cd16661 | |||
d8b37efe1b | |||
a40a035c03 | |||
a318758cbf | |||
7c13a25caf | |||
141567467f | |||
047983a280 | |||
48ad4322cf | |||
eaa34308d0 | |||
741a12de78 | |||
9749467cd7 | |||
91ae053346 | |||
b7b7edb5e2 | |||
dfa99fcb14 | |||
bc0bf41b91 | |||
535e69dcd0 | |||
2eaf83d89c | |||
6e62917819 | |||
03106eff02 | |||
0c5d71ecd2 | |||
d6a7b7e305 | |||
3d91f2f1e7 | |||
d76c295786 | |||
79422337ae | |||
b0e624ef75 | |||
9d78aabf35 | |||
a3930d7761 | |||
c958113c94 | |||
385c683fe3 | |||
1050337751 | |||
114bf7544a | |||
0199ee9877 | |||
6e02aeee53 | |||
6c3d71c4c9 | |||
78592b245f | |||
80d4422c90 | |||
32df55d636 | |||
eede86e278 | |||
1b855f953f | |||
59df400b0d | |||
4af244e3e2 | |||
ae91f8801f | |||
7f5786d47c | |||
ea12d5b951 | |||
d37468a6ab | |||
d0b3dc2ff8 | |||
85bbc10d06 | |||
2fca73aebd | |||
8b187940ee | |||
00369aa90b | |||
26a10020ac | |||
421463a642 | |||
8d9f248d2f | |||
ed72206a26 | |||
6b7460dd4c | |||
447af740be | |||
3ff6c32ac9 | |||
b752d70109 | |||
a6f83e2d37 | |||
016e223fb8 | |||
502601e684 | |||
29a4bb6803 | |||
cfbe7c83cb | |||
a6d9cb9201 | |||
32cdbd8c54 | |||
1a17b646e4 | |||
cdf79de36b | |||
2aa6be6496 | |||
25c391d244 | |||
a3c2be4e79 | |||
3413e10134 | |||
fa91348428 | |||
d40d3eb96e | |||
16e019be26 | |||
2e77f67683 | |||
9824dc5a44 | |||
1c20e03e0c | |||
98f334c883 | |||
8ac8a780e1 | |||
25e5700084 | |||
28d60a652b | |||
778be03472 | |||
fff8b5c29e | |||
a70d0bd601 | |||
8fc14ac793 | |||
13add8f60b | |||
2c1605c855 | |||
3524676fcc | |||
a577d57263 | |||
58440bb347 | |||
f3808c4251 | |||
95c08e3424 | |||
ce762b3cfa | |||
15bcf4a374 | |||
634aaa0b6a | |||
69fc090f55 | |||
f42041ccb6 | |||
a8787bd315 | |||
b5e77aeef8 | |||
f379685fdd | |||
32ff286691 | |||
38ab682978 | |||
8efe115698 | |||
38f72101eb | |||
f6d03b060c | |||
f450c00ff1 | |||
751f960b82 | |||
9558ded5c4 | |||
8066756605 | |||
ac2507e0ae | |||
205d4ccc41 | |||
7565818d0e | |||
fc093eca3e | |||
61b8f21037 | |||
d988ce8c99 | |||
727d82f268 | |||
c3c89c320b | |||
0b5bb877fb |
@ -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
|
||||||
|
|
||||||
@ -131,7 +144,7 @@ float ConvertEV100ToExposure(float EV100) {
|
|||||||
return 1/0.8 * exp2(-EV100);
|
return 1/0.8 * exp2(-EV100);
|
||||||
}
|
}
|
||||||
float ComputeEV(float avgLuminance) {
|
float ComputeEV(float avgLuminance) {
|
||||||
const float sqAperture = PPComp1[0].x * PPComp1.x;
|
const float sqAperture = PPComp1.x * PPComp1.x;
|
||||||
const float shutterTime = 1.0 / PPComp1.y;
|
const float shutterTime = 1.0 / PPComp1.y;
|
||||||
const float ISO = PPComp1.z;
|
const float ISO = PPComp1.z;
|
||||||
const float EC = PPComp2.x;
|
const float EC = PPComp2.x;
|
||||||
@ -349,16 +362,22 @@ 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,7 +426,11 @@ void main() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _CExposure
|
#ifdef _CExposure
|
||||||
fragColor.rgb += fragColor.rgb * compoExposureStrength;
|
#ifdef _CPostprocess
|
||||||
|
fragColor.rgb+=fragColor.rgb*PPComp8.x;
|
||||||
|
#else
|
||||||
|
fragColor.rgb+= fragColor.rgb*compoExposureStrength;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
#ifdef _CPostprocess
|
||||||
@ -415,8 +438,13 @@ void main() {
|
|||||||
#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
|
||||||
@ -480,9 +508,7 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5);
|
|||||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||||
} else if (PPComp4.x == 10){
|
} else if (PPComp4.x == 10){
|
||||||
fragColor.rgb = tonemapAgXFull(fragColor.rgb);
|
fragColor.rgb = tonemapAgXFull(fragColor.rgb);
|
||||||
} else {
|
} //else { fragColor.rgb = vec3(0,1,0); //ERROR}
|
||||||
fragColor.rgb = vec3(0,1,0); //ERROR
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -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() {
|
||||||
fragColor.a = 0.01 * autoExposureSpeed;
|
#ifdef _CPostprocess
|
||||||
|
fragColor.a = 0.01 * PPComp8.z;
|
||||||
|
#else
|
||||||
|
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,8 @@ vec3 uncharted2Tonemap(const vec3 x) {
|
|||||||
vec3 tonemapUncharted2(const vec3 color) {
|
vec3 tonemapUncharted2(const vec3 color) {
|
||||||
const float W = 11.2;
|
const float W = 11.2;
|
||||||
const float exposureBias = 2.0;
|
const float exposureBias = 2.0;
|
||||||
|
// TODO - Find out why black world value of 0.0,0.0,0.0 turns to white pixels
|
||||||
|
if (dot(color, color) < 0.001) return vec3(0.001);
|
||||||
vec3 curr = uncharted2Tonemap(exposureBias * color);
|
vec3 curr = uncharted2Tonemap(exposureBias * color);
|
||||||
vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
|
vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
|
||||||
return curr * whiteScale;
|
return curr * whiteScale;
|
||||||
|
@ -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;
|
||||||
const float stepLen = 1.0 / volumSteps;
|
#ifdef _CPostprocess
|
||||||
|
float stepLen = 1.0 / int(PPComp11.y);
|
||||||
|
float AirTurbidity = PPComp17.w;
|
||||||
|
#else
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -775,6 +775,7 @@ class Scene {
|
|||||||
// Attach particle systems
|
// Attach particle systems
|
||||||
#if lnx_particles
|
#if lnx_particles
|
||||||
if (o.particle_refs != null) {
|
if (o.particle_refs != null) {
|
||||||
|
cast(object, MeshObject).render_emitter = o.render_emitter;
|
||||||
for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref);
|
for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref);
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
@ -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;
|
||||||
|
50
leenkx/Sources/iron/format/bmp/Data.hx
Normal file
50
leenkx/Sources/iron/format/bmp/Data.hx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* format - Haxe File Formats
|
||||||
|
*
|
||||||
|
* BMP File Format
|
||||||
|
* Copyright (C) 2007-2009 Trevor McCauley, Baluta Cristian (hx port) & Robert Sköld (format conversion)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, The Haxe Project Contributors
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*/
|
||||||
|
package iron.format.bmp;
|
||||||
|
|
||||||
|
typedef Data = {
|
||||||
|
var header : iron.format.bmp.Header;
|
||||||
|
var pixels : haxe.io.Bytes;
|
||||||
|
#if (haxe_ver < 4)
|
||||||
|
var colorTable : Null<haxe.io.Bytes>;
|
||||||
|
#else
|
||||||
|
var ?colorTable : haxe.io.Bytes;
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef Header = {
|
||||||
|
var width : Int; // real width (in pixels)
|
||||||
|
var height : Int; // real height (in pixels)
|
||||||
|
var paddedStride : Int; // number of bytes in a stride (including padding)
|
||||||
|
var topToBottom : Bool; // whether the bitmap is stored top to bottom
|
||||||
|
var bpp : Int; // bits per pixel
|
||||||
|
var dataLength : Int; // equal to `paddedStride` * `height`
|
||||||
|
var compression : Int; // which compression is being used, 0 for no compression
|
||||||
|
}
|
122
leenkx/Sources/iron/format/bmp/Reader.hx
Normal file
122
leenkx/Sources/iron/format/bmp/Reader.hx
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* format - Haxe File Formats
|
||||||
|
*
|
||||||
|
* BMP File Format
|
||||||
|
* Copyright (C) 2007-2009 Robert Sköld
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, The Haxe Project Contributors
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iron.format.bmp;
|
||||||
|
|
||||||
|
import iron.format.bmp.Data;
|
||||||
|
|
||||||
|
|
||||||
|
class Reader {
|
||||||
|
|
||||||
|
var input : haxe.io.Input;
|
||||||
|
|
||||||
|
public function new( i ) {
|
||||||
|
input = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only supports uncompressed 24bpp bitmaps (the most common format).
|
||||||
|
*
|
||||||
|
* The returned bytes in `Data.pixels` will be in BGR order, and with padding (if present).
|
||||||
|
*
|
||||||
|
* @see https://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx
|
||||||
|
* @see https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header
|
||||||
|
*/
|
||||||
|
public function read() : format.bmp.Data {
|
||||||
|
// Read Header
|
||||||
|
for (b in ["B".code, "M".code]) {
|
||||||
|
if (input.readByte() != b) throw "Invalid header";
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileSize = input.readInt32();
|
||||||
|
input.readInt32(); // Reserved
|
||||||
|
var offset = input.readInt32();
|
||||||
|
|
||||||
|
// Read InfoHeader
|
||||||
|
var infoHeaderSize = input.readInt32(); // InfoHeader size
|
||||||
|
if (infoHeaderSize != 40) {
|
||||||
|
throw 'Info headers with size $infoHeaderSize not supported.';
|
||||||
|
}
|
||||||
|
var width = input.readInt32(); // Image width (actual, not padded)
|
||||||
|
var height = input.readInt32(); // Image height
|
||||||
|
var numPlanes = input.readInt16(); // Number of planes
|
||||||
|
var bits = input.readInt16(); // Bits per pixel
|
||||||
|
var compression = input.readInt32(); // Compression type
|
||||||
|
var dataLength = input.readInt32(); // Image data size (includes padding!)
|
||||||
|
input.readInt32(); // Horizontal resolution
|
||||||
|
input.readInt32(); // Vertical resolution
|
||||||
|
var colorsUsed = input.readInt32(); // Colors used (0 when uncompressed)
|
||||||
|
input.readInt32(); // Important colors (0 when uncompressed)
|
||||||
|
|
||||||
|
// If there's no compression, the dataLength may be 0
|
||||||
|
if ( compression == 0 && dataLength == 0 ) dataLength = fileSize - offset;
|
||||||
|
|
||||||
|
var bytesRead = 54; // total read above
|
||||||
|
|
||||||
|
var colorTable : haxe.io.Bytes = null;
|
||||||
|
if ( bits <= 8 ) {
|
||||||
|
if ( colorsUsed == 0 ) {
|
||||||
|
colorsUsed = Tools.getNumColorsForBitDepth(bits);
|
||||||
|
}
|
||||||
|
var colorTableLength = 4 * colorsUsed;
|
||||||
|
colorTable = haxe.io.Bytes.alloc( colorTableLength );
|
||||||
|
input.readFullBytes( colorTable, 0, colorTableLength );
|
||||||
|
bytesRead += colorTableLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.read( offset - bytesRead );
|
||||||
|
|
||||||
|
var p = haxe.io.Bytes.alloc( dataLength );
|
||||||
|
|
||||||
|
// Read Raster Data
|
||||||
|
var paddedStride = Tools.computePaddedStride(width, bits);
|
||||||
|
var topToBottom = false;
|
||||||
|
if ( height < 0 ) { // if bitmap is stored top to bottom
|
||||||
|
topToBottom = true;
|
||||||
|
height = -height;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.readFullBytes(p, 0, dataLength);
|
||||||
|
|
||||||
|
return {
|
||||||
|
header: {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
paddedStride: paddedStride,
|
||||||
|
topToBottom: topToBottom,
|
||||||
|
bpp: bits,
|
||||||
|
dataLength: dataLength,
|
||||||
|
compression: compression
|
||||||
|
},
|
||||||
|
pixels: p,
|
||||||
|
colorTable: colorTable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
256
leenkx/Sources/iron/format/bmp/Tools.hx
Normal file
256
leenkx/Sources/iron/format/bmp/Tools.hx
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* format - Haxe File Formats
|
||||||
|
*
|
||||||
|
* BMP File Format
|
||||||
|
* Copyright (C) 2007-2009 Trevor McCauley, Baluta Cristian (hx port) & Robert Sköld (format conversion)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, The Haxe Project Contributors
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*/
|
||||||
|
package iron.format.bmp;
|
||||||
|
|
||||||
|
|
||||||
|
class Tools {
|
||||||
|
|
||||||
|
// a r g b
|
||||||
|
static var ARGB_MAP(default, never):Array<Int> = [0, 1, 2, 3];
|
||||||
|
static var BGRA_MAP(default, never):Array<Int> = [3, 2, 1, 0];
|
||||||
|
|
||||||
|
static var COLOR_SIZE(default, never):Int = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Extract BMP pixel data (24bpp in BGR format) and expands it to BGRA, removing any padding in the process.
|
||||||
|
**/
|
||||||
|
inline static public function extractBGRA( bmp : iron.format.bmp.Data ) : haxe.io.Bytes {
|
||||||
|
return _extract32(bmp, BGRA_MAP, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Extract BMP pixel data (24bpp in BGR format) and converts it to ARGB.
|
||||||
|
**/
|
||||||
|
inline static public function extractARGB( bmp : iron.format.bmp.Data ) : haxe.io.Bytes {
|
||||||
|
return _extract32(bmp, ARGB_MAP, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates BMP data from bytes in BGRA format for each pixel.
|
||||||
|
**/
|
||||||
|
inline static public function buildFromBGRA( width : Int, height : Int, srcBytes : haxe.io.Bytes, topToBottom : Bool = false ) : Data {
|
||||||
|
return _buildFrom32(width, height, srcBytes, BGRA_MAP, topToBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates BMP data from bytes in ARGB format for each pixel.
|
||||||
|
**/
|
||||||
|
inline static public function buildFromARGB( width : Int, height : Int, srcBytes : haxe.io.Bytes, topToBottom : Bool = false ) : Data {
|
||||||
|
return _buildFrom32(width, height, srcBytes, ARGB_MAP, topToBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static public function computePaddedStride(width:Int, bpp:Int):Int {
|
||||||
|
return ((((width * bpp) + 31) & ~31) >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets number of colors for indexed palettes
|
||||||
|
*/
|
||||||
|
inline static public function getNumColorsForBitDepth(bpp:Int):Int {
|
||||||
|
return switch (bpp) {
|
||||||
|
case 1: 2;
|
||||||
|
case 4: 16;
|
||||||
|
case 8: 256;
|
||||||
|
case 16: 65536;
|
||||||
|
default: throw 'Unsupported bpp $bpp';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// `channelMap` contains indices to map into ARGB (f.e. the mapping for ARGB is [0,1,2,3], while for BGRA is [3,2,1,0])
|
||||||
|
static function _extract32( bmp : iron.format.bmp.Data, channelMap : Array<Int>, alpha : Int = 0xFF) : haxe.io.Bytes {
|
||||||
|
var srcBytes = bmp.pixels;
|
||||||
|
var dstLen = bmp.header.width * bmp.header.height * 4;
|
||||||
|
var dstBytes = haxe.io.Bytes.alloc( dstLen );
|
||||||
|
var srcPaddedStride = bmp.header.paddedStride;
|
||||||
|
|
||||||
|
var yDir = -1;
|
||||||
|
var dstPos = 0;
|
||||||
|
var srcPos = srcPaddedStride * (bmp.header.height - 1);
|
||||||
|
|
||||||
|
if ( bmp.header.topToBottom ) {
|
||||||
|
yDir = 1;
|
||||||
|
srcPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bmp.header.bpp < 8 || bmp.header.bpp == 16 ) {
|
||||||
|
throw 'bpp ${bmp.header.bpp} not supported';
|
||||||
|
}
|
||||||
|
|
||||||
|
var colorTable:haxe.io.Bytes = null;
|
||||||
|
if ( bmp.header.bpp <= 8 ) {
|
||||||
|
var colorTableLength = getNumColorsForBitDepth(bmp.header.bpp);
|
||||||
|
colorTable = haxe.io.Bytes.alloc(colorTableLength * COLOR_SIZE);
|
||||||
|
var definedColorTableLength = Std.int( bmp.colorTable.length / COLOR_SIZE );
|
||||||
|
for( i in 0...definedColorTableLength ) {
|
||||||
|
var b = bmp.colorTable.get( i * COLOR_SIZE);
|
||||||
|
var g = bmp.colorTable.get( i * COLOR_SIZE + 1);
|
||||||
|
var r = bmp.colorTable.get( i * COLOR_SIZE + 2);
|
||||||
|
|
||||||
|
colorTable.set(i * COLOR_SIZE + channelMap[0], alpha);
|
||||||
|
colorTable.set(i * COLOR_SIZE + channelMap[1], r);
|
||||||
|
colorTable.set(i * COLOR_SIZE + channelMap[2], g);
|
||||||
|
colorTable.set(i * COLOR_SIZE + channelMap[3], b);
|
||||||
|
}
|
||||||
|
// We want to have the table the full length in case indices outside the range are present
|
||||||
|
colorTable.fill(definedColorTableLength, colorTableLength - definedColorTableLength, 0);
|
||||||
|
for( i in definedColorTableLength...colorTableLength ) {
|
||||||
|
colorTable.set(i * COLOR_SIZE + channelMap[0], alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch bmp.header.compression {
|
||||||
|
case 0:
|
||||||
|
while( dstPos < dstLen ) {
|
||||||
|
for( i in 0...bmp.header.width ) {
|
||||||
|
if (bmp.header.bpp == 8) {
|
||||||
|
|
||||||
|
var currentSrcPos = srcPos + i;
|
||||||
|
var index = srcBytes.get(currentSrcPos);
|
||||||
|
dstBytes.blit( dstPos, colorTable, index * COLOR_SIZE, COLOR_SIZE );
|
||||||
|
|
||||||
|
} else if (bmp.header.bpp == 24) {
|
||||||
|
|
||||||
|
var currentSrcPos = srcPos + i * 3;
|
||||||
|
var b = srcBytes.get(currentSrcPos);
|
||||||
|
var g = srcBytes.get(currentSrcPos + 1);
|
||||||
|
var r = srcBytes.get(currentSrcPos + 2);
|
||||||
|
|
||||||
|
dstBytes.set(dstPos + channelMap[0], alpha);
|
||||||
|
dstBytes.set(dstPos + channelMap[1], r);
|
||||||
|
dstBytes.set(dstPos + channelMap[2], g);
|
||||||
|
dstBytes.set(dstPos + channelMap[3], b);
|
||||||
|
|
||||||
|
} else if (bmp.header.bpp == 32) {
|
||||||
|
|
||||||
|
var currentSrcPos = srcPos + i * 4;
|
||||||
|
var b = srcBytes.get(currentSrcPos);
|
||||||
|
var g = srcBytes.get(currentSrcPos + 1);
|
||||||
|
var r = srcBytes.get(currentSrcPos + 2);
|
||||||
|
|
||||||
|
dstBytes.set(dstPos + channelMap[0], alpha);
|
||||||
|
dstBytes.set(dstPos + channelMap[1], r);
|
||||||
|
dstBytes.set(dstPos + channelMap[2], g);
|
||||||
|
dstBytes.set(dstPos + channelMap[3], b);
|
||||||
|
|
||||||
|
}
|
||||||
|
dstPos += 4;
|
||||||
|
}
|
||||||
|
srcPos += yDir * srcPaddedStride;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
srcPos = 0;
|
||||||
|
var x = 0;
|
||||||
|
var y = bmp.header.topToBottom ? 0 : bmp.header.height - 1;
|
||||||
|
while( srcPos < bmp.header.dataLength ) {
|
||||||
|
var count = srcBytes.get(srcPos++);
|
||||||
|
var index = srcBytes.get(srcPos++);
|
||||||
|
if ( count == 0 ) {
|
||||||
|
if ( index == 0 ) {
|
||||||
|
x = 0;
|
||||||
|
y += yDir;
|
||||||
|
} else if ( index == 1 ) {
|
||||||
|
break;
|
||||||
|
} else if ( index == 2 ) {
|
||||||
|
x += srcBytes.get(srcPos++);
|
||||||
|
y += srcBytes.get(srcPos++);
|
||||||
|
} else {
|
||||||
|
count = index;
|
||||||
|
for( i in 0...count ) {
|
||||||
|
index = srcBytes.get(srcPos++);
|
||||||
|
dstBytes.blit( COLOR_SIZE * ((x+i) + y * bmp.header.width), colorTable, index * COLOR_SIZE, COLOR_SIZE );
|
||||||
|
}
|
||||||
|
if (srcPos % 2 != 0) srcPos++;
|
||||||
|
x += count;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for( i in 0...count ) {
|
||||||
|
dstBytes.blit( COLOR_SIZE * ((x+i) + y * bmp.header.width), colorTable, index * COLOR_SIZE, COLOR_SIZE );
|
||||||
|
}
|
||||||
|
x += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw 'compression ${bmp.header.compression} not supported';
|
||||||
|
}
|
||||||
|
|
||||||
|
return dstBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `channelMap` contains indices to map into ARGB (f.e. the mapping for ARGB is [0,1,2,3], while for BGRA is [3,2,1,0])
|
||||||
|
static function _buildFrom32( width : Int, height : Int, srcBytes : haxe.io.Bytes, channelMap : Array<Int>, topToBottom : Bool = false ) : Data {
|
||||||
|
var bpp = 24;
|
||||||
|
var paddedStride = computePaddedStride(width, bpp);
|
||||||
|
var bytesBGR = haxe.io.Bytes.alloc(paddedStride * height);
|
||||||
|
var topToBottom = topToBottom;
|
||||||
|
var dataLength = bytesBGR.length;
|
||||||
|
|
||||||
|
var dstStride = width * 3;
|
||||||
|
var srcLen = width * height * 4;
|
||||||
|
var yDir = -1;
|
||||||
|
var dstPos = dataLength - paddedStride;
|
||||||
|
var srcPos = 0;
|
||||||
|
|
||||||
|
if ( topToBottom ) {
|
||||||
|
yDir = 1;
|
||||||
|
dstPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( srcPos < srcLen ) {
|
||||||
|
var i = dstPos;
|
||||||
|
while( i < dstPos + dstStride ) {
|
||||||
|
var r = srcBytes.get(srcPos + channelMap[1]);
|
||||||
|
var g = srcBytes.get(srcPos + channelMap[2]);
|
||||||
|
var b = srcBytes.get(srcPos + channelMap[3]);
|
||||||
|
|
||||||
|
bytesBGR.set(i++, b);
|
||||||
|
bytesBGR.set(i++, g);
|
||||||
|
bytesBGR.set(i++, r);
|
||||||
|
|
||||||
|
srcPos += 4;
|
||||||
|
}
|
||||||
|
dstPos += yDir * paddedStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
header: {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
paddedStride: paddedStride,
|
||||||
|
topToBottom: topToBottom,
|
||||||
|
bpp: bpp,
|
||||||
|
dataLength: dataLength,
|
||||||
|
compression: 0
|
||||||
|
},
|
||||||
|
pixels: bytesBGR,
|
||||||
|
colorTable: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
leenkx/Sources/iron/format/bmp/Writer.hx
Normal file
74
leenkx/Sources/iron/format/bmp/Writer.hx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* format - Haxe File Formats
|
||||||
|
*
|
||||||
|
* BMP File Format
|
||||||
|
* Copyright (C) 2007-2009 Robert Sköld
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009, The Haxe Project Contributors
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iron.format.bmp;
|
||||||
|
|
||||||
|
import iron.format.bmp.Data;
|
||||||
|
|
||||||
|
|
||||||
|
class Writer {
|
||||||
|
|
||||||
|
static var DATA_OFFSET : Int = 0x36;
|
||||||
|
|
||||||
|
var output : haxe.io.Output;
|
||||||
|
|
||||||
|
public function new(o) {
|
||||||
|
output = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specs: http://s223767089.online.de/en/file-format-bmp
|
||||||
|
*/
|
||||||
|
public function write( bmp : Data ) {
|
||||||
|
// Write Header (14 bytes)
|
||||||
|
output.writeString( "BM" ); // Signature
|
||||||
|
output.writeInt32(bmp.pixels.length + DATA_OFFSET ); // FileSize
|
||||||
|
output.writeInt32( 0 ); // Reserved
|
||||||
|
output.writeInt32( DATA_OFFSET ); // Offset
|
||||||
|
|
||||||
|
// Write InfoHeader (40 bytes)
|
||||||
|
output.writeInt32( 40 ); // InfoHeader size
|
||||||
|
output.writeInt32( bmp.header.width ); // Image width
|
||||||
|
var height = bmp.header.height;
|
||||||
|
if (bmp.header.topToBottom) height = -height;
|
||||||
|
output.writeInt32( height ); // Image height
|
||||||
|
output.writeInt16( 1 ); // Number of planes
|
||||||
|
output.writeInt16( 24 ); // Bits per pixel (24bit RGB)
|
||||||
|
output.writeInt32( 0 ); // Compression type (no compression)
|
||||||
|
output.writeInt32( bmp.header.dataLength ); // Image data size (0 when uncompressed)
|
||||||
|
output.writeInt32( 0x2e30 ); // Horizontal resolution
|
||||||
|
output.writeInt32( 0x2e30 ); // Vertical resolution
|
||||||
|
output.writeInt32( 0 ); // Colors used (0 when uncompressed)
|
||||||
|
output.writeInt32( 0 ); // Important colors (0 when uncompressed)
|
||||||
|
|
||||||
|
// Write Raster Data
|
||||||
|
output.write(bmp.pixels);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
@ -21,6 +21,7 @@ class MeshObject extends Object {
|
|||||||
public var particleChildren: Array<MeshObject> = null;
|
public var particleChildren: Array<MeshObject> = null;
|
||||||
public var particleOwner: MeshObject = null; // Particle object
|
public var particleOwner: MeshObject = null; // Particle object
|
||||||
public var particleIndex = -1;
|
public var particleIndex = -1;
|
||||||
|
public var render_emitter = true;
|
||||||
#end
|
#end
|
||||||
public var cameraDistance: Float;
|
public var cameraDistance: Float;
|
||||||
public var screenSize = 0.0;
|
public var screenSize = 0.0;
|
||||||
@ -255,11 +256,11 @@ class MeshObject extends Object {
|
|||||||
particleSystems[i].update(particleChildren[i], this);
|
particleSystems[i].update(particleChildren[i], this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (particleSystems != null && particleSystems.length > 0 && !raw.render_emitter) return;
|
if (particleSystems != null && particleSystems.length > 0 && !render_emitter) return;
|
||||||
|
if (particleSystems == null && cullMaterial(context)) return;
|
||||||
|
#else
|
||||||
|
if (cullMaterial(context)) return;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
if (cullMaterial(context)) return;
|
|
||||||
|
|
||||||
// Get lod
|
// Get lod
|
||||||
var mats = materials;
|
var mats = materials;
|
||||||
var lod = this;
|
var lod = this;
|
||||||
|
@ -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,10 +17,12 @@ 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;
|
||||||
var frameRate = 24;
|
var frameRate = 24;
|
||||||
var lifetime = 0.0;
|
var lifetime = 0.0;
|
||||||
|
var looptime = 0.0;
|
||||||
var animtime = 0.0;
|
var animtime = 0.0;
|
||||||
var time = 0.0;
|
var time = 0.0;
|
||||||
var spawnRate = 0.0;
|
var spawnRate = 0.0;
|
||||||
@ -46,9 +49,13 @@ class ParticleSystem {
|
|||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1109,6 +1109,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,37 +1,58 @@
|
|||||||
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 {
|
||||||
if (frequency == null) initFrequency();
|
if (frequency == null) initFrequency();
|
||||||
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 last = 0.0;
|
static var lastTime = 0.0;
|
||||||
public static var realDelta = 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;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
public static function update() {
|
||||||
|
_delta = realTime() - lastTime;
|
||||||
static function initFrequency() {
|
lastTime = realTime();
|
||||||
frequency = kha.Display.primary != null ? kha.Display.primary.frequency : 60;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function update() {
|
public static function render() {
|
||||||
realDelta = realTime() - last;
|
_renderDelta = realTime() - lastRenderTime;
|
||||||
last = realTime();
|
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
|
||||||
|
99
leenkx/Sources/leenkx/logicnode/AddParticleToObjectNode.hx
Normal file
99
leenkx/Sources/leenkx/logicnode/AddParticleToObjectNode.hx
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.data.SceneFormat.TSceneFormat;
|
||||||
|
import iron.data.Data;
|
||||||
|
import iron.object.Object;
|
||||||
|
|
||||||
|
class AddParticleToObjectNode extends LogicNode {
|
||||||
|
|
||||||
|
public var property0: String;
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from: Int) {
|
||||||
|
#if lnx_particles
|
||||||
|
|
||||||
|
if (property0 == 'Scene Active'){
|
||||||
|
var objFrom: Object = inputs[1].get();
|
||||||
|
var slot: Int = inputs[2].get();
|
||||||
|
var objTo: Object = inputs[3].get();
|
||||||
|
|
||||||
|
if (objFrom == null || objTo == null) return;
|
||||||
|
|
||||||
|
var mobjFrom = cast(objFrom, iron.object.MeshObject);
|
||||||
|
|
||||||
|
var psys = mobjFrom.particleSystems != null ? mobjFrom.particleSystems[slot] :
|
||||||
|
mobjFrom.particleOwner != null && mobjFrom.particleOwner.particleSystems != null ? mobjFrom.particleOwner.particleSystems[slot] : null;
|
||||||
|
|
||||||
|
if (psys == null) return;
|
||||||
|
|
||||||
|
var mobjTo = cast(objTo, iron.object.MeshObject);
|
||||||
|
|
||||||
|
mobjTo.setupParticleSystem(iron.Scene.active.raw.name, {name: 'LnxPS', seed: 0, particle: @:privateAccess psys.r.name});
|
||||||
|
|
||||||
|
mobjTo.render_emitter = inputs[4].get();
|
||||||
|
|
||||||
|
iron.Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
|
||||||
|
if (o != null) {
|
||||||
|
var c: iron.object.MeshObject = cast o;
|
||||||
|
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
|
||||||
|
mobjTo.particleChildren.push(c);
|
||||||
|
c.particleOwner = mobjTo;
|
||||||
|
c.particleIndex = mobjTo.particleChildren.length - 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var oslot: Int = mobjTo.particleSystems.length-1;
|
||||||
|
var opsys = mobjTo.particleSystems[oslot];
|
||||||
|
@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
var sceneName: String = inputs[1].get();
|
||||||
|
var objectName: String = inputs[2].get();
|
||||||
|
var slot: Int = inputs[3].get();
|
||||||
|
|
||||||
|
var mobjTo: Object = inputs[4].get();
|
||||||
|
var mobjTo = cast(mobjTo, iron.object.MeshObject);
|
||||||
|
|
||||||
|
#if lnx_json
|
||||||
|
sceneName += ".json";
|
||||||
|
#elseif lnx_compress
|
||||||
|
sceneName += ".lz4";
|
||||||
|
#end
|
||||||
|
|
||||||
|
Data.getSceneRaw(sceneName, (rawScene: TSceneFormat) -> {
|
||||||
|
|
||||||
|
for (obj in rawScene.objects) {
|
||||||
|
if (obj.name == objectName) {
|
||||||
|
mobjTo.setupParticleSystem(sceneName, obj.particle_refs[slot]);
|
||||||
|
mobjTo.render_emitter = inputs[5].get();
|
||||||
|
|
||||||
|
iron.Scene.active.spawnObject(rawScene.particle_datas[slot].instance_object, null, function(o: Object) {
|
||||||
|
if (o != null) {
|
||||||
|
var c: iron.object.MeshObject = cast o;
|
||||||
|
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
|
||||||
|
mobjTo.particleChildren.push(c);
|
||||||
|
c.particleOwner = mobjTo;
|
||||||
|
c.particleIndex = mobjTo.particleChildren.length - 1;
|
||||||
|
}
|
||||||
|
}, true, rawScene);
|
||||||
|
|
||||||
|
var oslot: Int = mobjTo.particleSystems.length-1;
|
||||||
|
var opsys = mobjTo.particleSystems[oslot];
|
||||||
|
@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#end
|
||||||
|
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
}
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,49 @@
|
|||||||
package leenkx.logicnode;
|
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) {
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[0] = inputs[1].get();//Camera: F-Number
|
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[1] = inputs[2].get();//Camera: Shutter time
|
switch (property0) {
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[2] = inputs[3].get();//Camera: ISO
|
case 'F-stop':
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[3] = inputs[4].get();//Camera: Exposure Compensation
|
leenkx.renderpath.Postprocess.camera_uniforms[0] = inputs[1].get();//Camera: F-Number
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[4] = inputs[5].get();//Fisheye Distortion
|
case 'Shutter Time':
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[5] = inputs[6].get();//DoF AutoFocus §§ If true, it ignores the DoF Distance setting
|
leenkx.renderpath.Postprocess.camera_uniforms[1] = inputs[1].get();//Camera: Shutter time
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[6] = inputs[7].get();//DoF Distance
|
case 'ISO':
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[7] = inputs[8].get();//DoF Focal Length mm
|
leenkx.renderpath.Postprocess.camera_uniforms[2] = inputs[1].get();//Camera: ISO
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[8] = inputs[9].get();//DoF F-Stop
|
case 'Exposure Compensation':
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[9] = inputs[10].get();//Tonemapping Method
|
leenkx.renderpath.Postprocess.camera_uniforms[3] = inputs[1].get();//Camera: Exposure Compensation
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[10] = inputs[11].get();//Distort
|
case 'Fisheye Distortion':
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[11] = inputs[12].get();//Film Grain
|
leenkx.renderpath.Postprocess.camera_uniforms[4] = inputs[1].get();//Fisheye Distortion
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[12] = inputs[13].get();//Sharpen
|
case 'Auto Focus':
|
||||||
leenkx.renderpath.Postprocess.camera_uniforms[13] = inputs[14].get();//Vignette
|
leenkx.renderpath.Postprocess.camera_uniforms[5] = inputs[1].get();//DoF AutoFocus §§ If true, it ignores the DoF Distance setting
|
||||||
|
case 'DoF Distance':
|
||||||
|
leenkx.renderpath.Postprocess.camera_uniforms[6] = inputs[1].get();//DoF Distance
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@ package leenkx.logicnode;
|
|||||||
|
|
||||||
import iron.Scene;
|
import iron.Scene;
|
||||||
import iron.object.CameraObject;
|
import iron.object.CameraObject;
|
||||||
|
import iron.math.Vec4;
|
||||||
|
import iron.math.Quat;
|
||||||
|
import leenkx.math.Helper;
|
||||||
|
|
||||||
import leenkx.renderpath.RenderPathCreator;
|
import leenkx.renderpath.RenderPathCreator;
|
||||||
|
|
||||||
@ -27,11 +30,19 @@ class DrawCameraTextureNode extends LogicNode {
|
|||||||
final c = inputs[2].get();
|
final c = inputs[2].get();
|
||||||
assert(Error, Std.isOfType(c, CameraObject), "Camera must be a camera object!");
|
assert(Error, Std.isOfType(c, CameraObject), "Camera must be a camera object!");
|
||||||
cam = cast(c, CameraObject);
|
cam = cast(c, CameraObject);
|
||||||
rt = kha.Image.createRenderTarget(iron.App.w(), iron.App.h());
|
rt = kha.Image.createRenderTarget(iron.App.w(), iron.App.h(),
|
||||||
|
kha.graphics4.TextureFormat.RGBA32,
|
||||||
|
kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
|
||||||
|
|
||||||
assert(Error, mo.materials[matSlot].contexts[0].textures != null, 'Object "${mo.name}" has no diffuse texture to render to');
|
assert(Error, mo.materials[matSlot].contexts[0].textures != null, 'Object "${mo.name}" has no diffuse texture to render to');
|
||||||
mo.materials[matSlot].contexts[0].textures[0] = rt; // Override diffuse texture
|
|
||||||
|
|
||||||
|
final n = inputs[5].get();
|
||||||
|
for (i => node in mo.materials[matSlot].contexts[0].raw.bind_textures){
|
||||||
|
if (node.name == n){
|
||||||
|
mo.materials[matSlot].contexts[0].textures[i] = rt; // Override diffuse texture
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
tree.notifyOnRender(render);
|
tree.notifyOnRender(render);
|
||||||
runOutput(0);
|
runOutput(0);
|
||||||
|
|
||||||
@ -48,8 +59,20 @@ class DrawCameraTextureNode extends LogicNode {
|
|||||||
iron.Scene.active.camera = cam;
|
iron.Scene.active.camera = cam;
|
||||||
cam.renderTarget = rt;
|
cam.renderTarget = rt;
|
||||||
|
|
||||||
|
#if kha_html5
|
||||||
|
var q: Quat = new Quat();
|
||||||
|
q.fromAxisAngle(new Vec4(0, 0, 1, 1), Helper.degToRad(180));
|
||||||
|
cam.transform.rot.mult(q);
|
||||||
|
cam.transform.buildMatrix();
|
||||||
|
#end
|
||||||
|
|
||||||
cam.renderFrame(g);
|
cam.renderFrame(g);
|
||||||
|
|
||||||
|
#if kha_html5
|
||||||
|
cam.transform.rot.mult(q);
|
||||||
|
cam.transform.buildMatrix();
|
||||||
|
#end
|
||||||
|
|
||||||
cam.renderTarget = oldRT;
|
cam.renderTarget = oldRT;
|
||||||
iron.Scene.active.camera = sceneCam;
|
iron.Scene.active.camera = sceneCam;
|
||||||
}
|
}
|
||||||
|
@ -99,8 +99,6 @@ class DrawImageSequenceNode extends LogicNode {
|
|||||||
final colorVec = inputs[4].get();
|
final colorVec = inputs[4].get();
|
||||||
g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
|
g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
|
||||||
|
|
||||||
trace(currentImgIdx);
|
|
||||||
|
|
||||||
g.drawScaledImage(images[currentImgIdx], inputs[5].get(), inputs[6].get(), inputs[7].get(), inputs[8].get());
|
g.drawScaledImage(images[currentImgIdx], inputs[5].get(), inputs[6].get(), inputs[7].get(), inputs[8].get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
59
leenkx/Sources/leenkx/logicnode/DrawSubImageNode.hx
Normal file
59
leenkx/Sources/leenkx/logicnode/DrawSubImageNode.hx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.math.Vec4;
|
||||||
|
import kha.Image;
|
||||||
|
import kha.Color;
|
||||||
|
import leenkx.renderpath.RenderToTexture;
|
||||||
|
|
||||||
|
class DrawSubImageNode extends LogicNode {
|
||||||
|
var img: Image;
|
||||||
|
var lastImgName = "";
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from: Int) {
|
||||||
|
RenderToTexture.ensure2DContext("DrawImageNode");
|
||||||
|
|
||||||
|
final imgName: String = inputs[1].get();
|
||||||
|
final colorVec: Vec4 = inputs[2].get();
|
||||||
|
final anchorH: Int = inputs[3].get();
|
||||||
|
final anchorV: Int = inputs[4].get();
|
||||||
|
final x: Float = inputs[5].get();
|
||||||
|
final y: Float = inputs[6].get();
|
||||||
|
final width: Float = inputs[7].get();
|
||||||
|
final height: Float = inputs[8].get();
|
||||||
|
final sx: Float = inputs[9].get();
|
||||||
|
final sy: Float = inputs[10].get();
|
||||||
|
final swidth: Float = inputs[11].get();
|
||||||
|
final sheight: Float = inputs[12].get();
|
||||||
|
final angle: Float = inputs[13].get();
|
||||||
|
|
||||||
|
final drawx = x - 0.5 * width * anchorH;
|
||||||
|
final drawy = y - 0.5 * height * anchorV;
|
||||||
|
final sdrawx = sx - 0.5 * swidth * anchorH;
|
||||||
|
final sdrawy = sy - 0.5 * sheight * anchorV;
|
||||||
|
|
||||||
|
RenderToTexture.g.rotate(angle, x, y);
|
||||||
|
|
||||||
|
if (imgName != lastImgName) {
|
||||||
|
// Load new image
|
||||||
|
lastImgName = imgName;
|
||||||
|
iron.data.Data.getImage(imgName, (image: Image) -> {
|
||||||
|
img = image;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (img == null) {
|
||||||
|
runOutput(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderToTexture.g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
|
||||||
|
RenderToTexture.g.drawScaledSubImage(img, sdrawx, sdrawy, swidth, sheight, drawx, drawy, width, height);
|
||||||
|
RenderToTexture.g.rotate(-angle, x, y);
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
72
leenkx/Sources/leenkx/logicnode/GetParticleDataNode.hx
Normal file
72
leenkx/Sources/leenkx/logicnode/GetParticleDataNode.hx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.object.Object;
|
||||||
|
|
||||||
|
class GetParticleDataNode extends LogicNode {
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function get(from: Int): Dynamic {
|
||||||
|
var object: Object = inputs[0].get();
|
||||||
|
var slot: Int = inputs[1].get();
|
||||||
|
|
||||||
|
if (object == null) return null;
|
||||||
|
|
||||||
|
#if lnx_particles
|
||||||
|
|
||||||
|
var mo = cast(object, iron.object.MeshObject);
|
||||||
|
|
||||||
|
var psys = mo.particleSystems != null ? mo.particleSystems[slot] :
|
||||||
|
mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null;
|
||||||
|
|
||||||
|
if (psys == null) return null;
|
||||||
|
|
||||||
|
return switch (from) {
|
||||||
|
case 0:
|
||||||
|
@:privateAccess psys.r.name;
|
||||||
|
case 1:
|
||||||
|
@:privateAccess psys.r.particle_size;
|
||||||
|
case 2:
|
||||||
|
@:privateAccess psys.r.frame_start;
|
||||||
|
case 3:
|
||||||
|
@:privateAccess psys.r.frame_end;
|
||||||
|
case 4:
|
||||||
|
@:privateAccess psys.lifetime;
|
||||||
|
case 5:
|
||||||
|
@:privateAccess psys.r.lifetime;
|
||||||
|
case 6:
|
||||||
|
@:privateAccess psys.r.emit_from;
|
||||||
|
case 7:
|
||||||
|
@:privateAccess psys.r.auto_start;
|
||||||
|
case 8:
|
||||||
|
@:privateAccess psys.r.is_unique;
|
||||||
|
case 9:
|
||||||
|
@:privateAccess psys.r.loop;
|
||||||
|
case 10:
|
||||||
|
new iron.math.Vec3(@:privateAccess psys.alignx, @:privateAccess psys.aligny, @:privateAccess psys.alignz);
|
||||||
|
case 11:
|
||||||
|
@:privateAccess psys.r.factor_random;
|
||||||
|
case 12:
|
||||||
|
new iron.math.Vec3(@:privateAccess psys.gx, @:privateAccess psys.gy, @:privateAccess psys.gz);
|
||||||
|
case 13:
|
||||||
|
@:privateAccess psys.r.weight_gravity;
|
||||||
|
case 14:
|
||||||
|
psys.speed;
|
||||||
|
case 15:
|
||||||
|
@:privateAccess psys.time;
|
||||||
|
case 16:
|
||||||
|
@:privateAccess psys.lap;
|
||||||
|
case 17:
|
||||||
|
@:privateAccess psys.lapTime;
|
||||||
|
case 18:
|
||||||
|
@:privateAccess psys.count;
|
||||||
|
default:
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
38
leenkx/Sources/leenkx/logicnode/GetParticleNode.hx
Normal file
38
leenkx/Sources/leenkx/logicnode/GetParticleNode.hx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.object.Object;
|
||||||
|
|
||||||
|
class GetParticleNode extends LogicNode {
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function get(from: Int): Dynamic {
|
||||||
|
var object: Object = inputs[0].get();
|
||||||
|
|
||||||
|
if (object == null) return null;
|
||||||
|
|
||||||
|
#if lnx_particles
|
||||||
|
|
||||||
|
var mo = cast(object, iron.object.MeshObject);
|
||||||
|
|
||||||
|
switch (from) {
|
||||||
|
case 0:
|
||||||
|
var names: Array<String> = [];
|
||||||
|
if (mo.particleSystems != null)
|
||||||
|
for (psys in mo.particleSystems)
|
||||||
|
names.push(@:privateAccess psys.r.name);
|
||||||
|
return names;
|
||||||
|
case 1:
|
||||||
|
return mo.particleSystems != null ? mo.particleSystems.length : 0;
|
||||||
|
case 2:
|
||||||
|
return mo.render_emitter;
|
||||||
|
default:
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,12 @@
|
|||||||
package leenkx.logicnode;
|
package leenkx.logicnode;
|
||||||
|
|
||||||
import iron.object.Object;
|
|
||||||
import iron.math.Vec4;
|
|
||||||
|
|
||||||
class GetWorldNode extends LogicNode {
|
class GetWorldNode extends LogicNode {
|
||||||
|
|
||||||
public var property0: String;
|
|
||||||
|
|
||||||
public function new(tree: LogicTree) {
|
public function new(tree: LogicTree) {
|
||||||
super(tree);
|
super(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function get(from: Int): Dynamic {
|
override function get(from: Int): Dynamic {
|
||||||
var object: Object = inputs[0].get();
|
return iron.Scene.active.raw.world_ref;
|
||||||
|
|
||||||
if (object == null) return null;
|
|
||||||
|
|
||||||
return switch (property0) {
|
|
||||||
case "Right": object.transform.world.right();
|
|
||||||
case "Look": object.transform.world.look();
|
|
||||||
case "Up": object.transform.world.up();
|
|
||||||
default: null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
26
leenkx/Sources/leenkx/logicnode/GetWorldOrientationNode.hx
Normal file
26
leenkx/Sources/leenkx/logicnode/GetWorldOrientationNode.hx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.object.Object;
|
||||||
|
import iron.math.Vec4;
|
||||||
|
|
||||||
|
class GetWorldNode extends LogicNode {
|
||||||
|
|
||||||
|
public var property0: String;
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function get(from: Int): Dynamic {
|
||||||
|
var object: Object = inputs[0].get();
|
||||||
|
|
||||||
|
if (object == null) return null;
|
||||||
|
|
||||||
|
return switch (property0) {
|
||||||
|
case "Right": object.transform.world.right();
|
||||||
|
case "Look": object.transform.world.look();
|
||||||
|
case "Up": object.transform.world.up();
|
||||||
|
default: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,6 @@ class ProbabilisticOutputNode extends LogicNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sum > 1){
|
if (sum > 1){
|
||||||
trace(sum);
|
|
||||||
for (p in 0...probs.length)
|
for (p in 0...probs.length)
|
||||||
probs[p] /= sum;
|
probs[p] /= sum;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.object.Object;
|
||||||
|
|
||||||
|
class RemoveParticleFromObjectNode extends LogicNode {
|
||||||
|
|
||||||
|
public var property0: String;
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from: Int) {
|
||||||
|
#if lnx_particles
|
||||||
|
var object: Object = inputs[1].get();
|
||||||
|
|
||||||
|
if (object == null) return;
|
||||||
|
|
||||||
|
var mo = cast(object, iron.object.MeshObject);
|
||||||
|
|
||||||
|
if (mo.particleSystems == null) return;
|
||||||
|
|
||||||
|
if (property0 == 'All'){
|
||||||
|
mo.particleSystems = null;
|
||||||
|
for (c in mo.particleChildren) c.remove();
|
||||||
|
mo.particleChildren = null;
|
||||||
|
mo.particleOwner = null;
|
||||||
|
mo.render_emitter = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
var slot: Int = -1;
|
||||||
|
if (property0 == 'Name'){
|
||||||
|
var name: String = inputs[2].get();
|
||||||
|
for (i => psys in mo.particleSystems){
|
||||||
|
if (@:privateAccess psys.r.name == name){ slot = i; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else slot = inputs[2].get();
|
||||||
|
|
||||||
|
if (mo.particleSystems.length > slot){
|
||||||
|
for (i in slot+1...mo.particleSystems.length){
|
||||||
|
var mi = cast(mo.particleChildren[i], iron.object.MeshObject);
|
||||||
|
mi.particleIndex = mi.particleIndex - 1;
|
||||||
|
}
|
||||||
|
mo.particleSystems.splice(slot, 1);
|
||||||
|
mo.particleChildren[slot].remove();
|
||||||
|
mo.particleChildren.splice(slot, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot == 0){
|
||||||
|
mo.particleSystems = null;
|
||||||
|
mo.particleChildren = null;
|
||||||
|
mo.particleOwner = null;
|
||||||
|
mo.render_emitter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#end
|
||||||
|
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
}
|
16
leenkx/Sources/leenkx/logicnode/ResolutionGetNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/ResolutionGetNode.hx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
class ResolutionGetNode extends LogicNode {
|
||||||
|
|
||||||
|
public function new(tree:LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function get(from:Int):Dynamic {
|
||||||
|
return switch (from) {
|
||||||
|
case 0: leenkx.renderpath.Postprocess.resolution_uniforms[0];
|
||||||
|
case 1: leenkx.renderpath.Postprocess.resolution_uniforms[1];
|
||||||
|
default: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
leenkx/Sources/leenkx/logicnode/ResolutionSetNode.hx
Normal file
33
leenkx/Sources/leenkx/logicnode/ResolutionSetNode.hx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import kha.graphics4.TextureFilter;
|
||||||
|
|
||||||
|
class ResolutionSetNode extends LogicNode {
|
||||||
|
|
||||||
|
public function new(tree:LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from:Int) {
|
||||||
|
|
||||||
|
var size: Int = inputs[1].get();
|
||||||
|
var filter: Int = inputs[2].get();
|
||||||
|
|
||||||
|
#if rp_resolution_filter
|
||||||
|
if (filter == 0)
|
||||||
|
iron.object.Uniforms.defaultFilter = TextureFilter.LinearFilter;
|
||||||
|
else
|
||||||
|
iron.object.Uniforms.defaultFilter = TextureFilter.PointFilter;
|
||||||
|
|
||||||
|
leenkx.renderpath.Postprocess.resolution_uniforms[0] = size;
|
||||||
|
leenkx.renderpath.Postprocess.resolution_uniforms[1] = filter;
|
||||||
|
|
||||||
|
var npath = leenkx.renderpath.RenderPathCreator.get();
|
||||||
|
var world = iron.Scene.active.raw.world_ref;
|
||||||
|
npath.loadShader("shader_datas/World_" + world + "/World_" + world);
|
||||||
|
iron.RenderPath.setActive(npath);
|
||||||
|
#end
|
||||||
|
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
}
|
@ -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":
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.object.MeshObject;
|
||||||
|
import iron.data.MaterialData;
|
||||||
|
|
||||||
|
class SetMaterialTextureFilterNode extends LogicNode {
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from: Int) {
|
||||||
|
var object: MeshObject = inputs[1].get();
|
||||||
|
var mat: MaterialData = inputs[2].get();
|
||||||
|
var slot: Int = inputs[3].get();
|
||||||
|
var name: String = inputs[4].get();
|
||||||
|
var filter: Int = inputs[5].get();
|
||||||
|
|
||||||
|
if (object == null) return;
|
||||||
|
if (slot >= object.materials.length) return;
|
||||||
|
|
||||||
|
var mo = cast(object, iron.object.MeshObject);
|
||||||
|
|
||||||
|
for (i => node in mo.materials[slot].contexts[0].raw.bind_textures)
|
||||||
|
if (node.name == name){
|
||||||
|
var moImgt = mo.materials[slot].contexts[0].raw.bind_textures[i];
|
||||||
|
switch(filter){
|
||||||
|
case 0: //Linear
|
||||||
|
moImgt.min_filter = null;
|
||||||
|
moImgt.mag_filter = null;
|
||||||
|
moImgt.mipmap_filter = null;
|
||||||
|
moImgt.generate_mipmaps = null;
|
||||||
|
case 1: //Closest
|
||||||
|
moImgt.min_filter = 'point';
|
||||||
|
moImgt.mag_filter = 'point';
|
||||||
|
moImgt.mipmap_filter = null;
|
||||||
|
moImgt.generate_mipmaps = null;
|
||||||
|
case 2: //Cubic
|
||||||
|
moImgt.min_filter = null;
|
||||||
|
moImgt.mag_filter = null;
|
||||||
|
moImgt.mipmap_filter = 'linear';
|
||||||
|
moImgt.generate_mipmaps = true;
|
||||||
|
case 3: //Smart
|
||||||
|
moImgt.min_filter = 'anisotropic';
|
||||||
|
moImgt.mag_filter = null;
|
||||||
|
moImgt.mipmap_filter = 'linear';
|
||||||
|
moImgt.generate_mipmaps = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
}
|
81
leenkx/Sources/leenkx/logicnode/SetParticleDataNode.hx
Normal file
81
leenkx/Sources/leenkx/logicnode/SetParticleDataNode.hx
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.object.Object;
|
||||||
|
|
||||||
|
class SetParticleDataNode extends LogicNode {
|
||||||
|
|
||||||
|
public var property0: String;
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from: Int) {
|
||||||
|
#if lnx_particles
|
||||||
|
var object: Object = inputs[1].get();
|
||||||
|
var slot: Int = inputs[2].get();
|
||||||
|
|
||||||
|
if (object == null) return;
|
||||||
|
|
||||||
|
var mo = cast(object, iron.object.MeshObject);
|
||||||
|
|
||||||
|
var psys = mo.particleSystems != null ? mo.particleSystems[slot] :
|
||||||
|
mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null; if (psys == null) return;
|
||||||
|
|
||||||
|
switch (property0) {
|
||||||
|
case 'Particle Size':
|
||||||
|
@:privateAccess psys.r.particle_size = inputs[3].get();
|
||||||
|
case 'Frame Start':
|
||||||
|
@:privateAccess psys.r.frame_start = inputs[3].get();
|
||||||
|
@:privateAccess psys.animtime = (@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.frameRate;
|
||||||
|
@:privateAccess psys.spawnRate = ((@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.count) / @:privateAccess psys.frameRate;
|
||||||
|
case 'Frame End':
|
||||||
|
@:privateAccess psys.r.frame_end = inputs[3].get();
|
||||||
|
@:privateAccess psys.animtime = (@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.frameRate;
|
||||||
|
@:privateAccess psys.spawnRate = ((@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.count) / @:privateAccess psys.frameRate;
|
||||||
|
case 'Lifetime':
|
||||||
|
@:privateAccess psys.lifetime = inputs[3].get() / @:privateAccess psys.frameRate;
|
||||||
|
case 'Lifetime Random':
|
||||||
|
@:privateAccess psys.r.lifetime_random = inputs[3].get();
|
||||||
|
case 'Emit From':
|
||||||
|
var emit_from: Int = inputs[3].get();
|
||||||
|
if (emit_from == 0 || emit_from == 1 || emit_from == 2) {
|
||||||
|
@:privateAccess psys.r.emit_from = emit_from;
|
||||||
|
@: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':
|
||||||
|
var vel: iron.math.Vec3 = inputs[3].get();
|
||||||
|
@:privateAccess psys.alignx = vel.x;
|
||||||
|
@:privateAccess psys.aligny = vel.y;
|
||||||
|
@:privateAccess psys.alignz = vel.z;
|
||||||
|
case 'Velocity Random':
|
||||||
|
psys.r.factor_random = inputs[3].get();
|
||||||
|
case 'Weight Gravity':
|
||||||
|
psys.r.weight_gravity = inputs[3].get();
|
||||||
|
if (iron.Scene.active.raw.gravity != null) {
|
||||||
|
@:privateAccess psys.gx = iron.Scene.active.raw.gravity[0] * @:privateAccess psys.r.weight_gravity;
|
||||||
|
@:privateAccess psys.gy = iron.Scene.active.raw.gravity[1] * @:privateAccess psys.r.weight_gravity;
|
||||||
|
@:privateAccess psys.gz = iron.Scene.active.raw.gravity[2] * @:privateAccess psys.r.weight_gravity;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
@:privateAccess psys.gx = 0;
|
||||||
|
@:privateAccess psys.gy = 0;
|
||||||
|
@:privateAccess psys.gz = -9.81 * @:privateAccess psys.r.weight_gravity;
|
||||||
|
}
|
||||||
|
case 'Speed':
|
||||||
|
psys.speed = inputs[3].get();
|
||||||
|
default:
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#end
|
||||||
|
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.object.Object;
|
||||||
|
|
||||||
|
class SetParticleRenderEmitterNode extends LogicNode {
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from: Int) {
|
||||||
|
#if lnx_particles
|
||||||
|
var object: Object = inputs[1].get();
|
||||||
|
|
||||||
|
if (object == null) return;
|
||||||
|
|
||||||
|
cast(object, iron.object.MeshObject).render_emitter = inputs[2].get();
|
||||||
|
|
||||||
|
#end
|
||||||
|
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
}
|
@ -11,13 +11,16 @@ class SetParticleSpeedNode extends LogicNode {
|
|||||||
override function run(from: Int) {
|
override function run(from: Int) {
|
||||||
#if lnx_particles
|
#if lnx_particles
|
||||||
var object: Object = inputs[1].get();
|
var object: Object = inputs[1].get();
|
||||||
var speed: Float = inputs[2].get();
|
var slot: Int = inputs[2].get();
|
||||||
|
var speed: Float = inputs[3].get();
|
||||||
|
|
||||||
if (object == null) return;
|
if (object == null) return;
|
||||||
|
|
||||||
var mo = cast(object, iron.object.MeshObject);
|
var mo = cast(object, iron.object.MeshObject);
|
||||||
var psys = mo.particleSystems.length > 0 ? mo.particleSystems[0] : null;
|
var psys = mo.particleSystems != null ? mo.particleSystems[slot] :
|
||||||
if (psys == null) mo.particleOwner.particleSystems[0];
|
mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null;
|
||||||
|
|
||||||
|
if (psys == null) return;
|
||||||
|
|
||||||
psys.speed = speed;
|
psys.speed = speed;
|
||||||
|
|
||||||
|
40
leenkx/Sources/leenkx/logicnode/SetWorldNode.hx
Normal file
40
leenkx/Sources/leenkx/logicnode/SetWorldNode.hx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
class SetWorldNode extends LogicNode {
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from: Int) {
|
||||||
|
var world: String = inputs[1].get();
|
||||||
|
|
||||||
|
if (world != null){
|
||||||
|
|
||||||
|
//check if world shader data exists
|
||||||
|
var file: String = 'World_'+world+'_data';
|
||||||
|
#if lnx_json
|
||||||
|
file += ".json";
|
||||||
|
#elseif lnx_compress
|
||||||
|
file += ".lz4";
|
||||||
|
#else
|
||||||
|
file += '.lnx';
|
||||||
|
#end
|
||||||
|
|
||||||
|
var exists: Bool = false;
|
||||||
|
|
||||||
|
iron.data.Data.getBlob(file, function(b: kha.Blob) {
|
||||||
|
if (b != null) exists = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(Error, exists == true, "World must be either associated to a scene or have fake user");
|
||||||
|
|
||||||
|
iron.Scene.active.raw.world_ref = world;
|
||||||
|
var npath = leenkx.renderpath.RenderPathCreator.get();
|
||||||
|
npath.loadShader("shader_datas/World_" + world + "/World_" + world);
|
||||||
|
iron.RenderPath.setActive(npath);
|
||||||
|
}
|
||||||
|
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
}
|
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);
|
||||||
|
}
|
||||||
|
}
|
105
leenkx/Sources/leenkx/logicnode/WriteImageNode.hx
Normal file
105
leenkx/Sources/leenkx/logicnode/WriteImageNode.hx
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package leenkx.logicnode;
|
||||||
|
|
||||||
|
import iron.object.CameraObject;
|
||||||
|
|
||||||
|
class WriteImageNode extends LogicNode {
|
||||||
|
|
||||||
|
var file: String;
|
||||||
|
var camera: CameraObject;
|
||||||
|
var renderTarget: kha.Image;
|
||||||
|
|
||||||
|
public function new(tree: LogicTree) {
|
||||||
|
super(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
override function run(from: Int) {
|
||||||
|
// Relative or absolute path to file
|
||||||
|
file = inputs[1].get();
|
||||||
|
|
||||||
|
assert(Error, iron.App.w() % inputs[3].get() == 0 && iron.App.h() % inputs[4].get() == 0, "Aspect ratio must match display resolution ratio");
|
||||||
|
|
||||||
|
camera = inputs[2].get();
|
||||||
|
renderTarget = kha.Image.createRenderTarget(inputs[3].get(), inputs[4].get(),
|
||||||
|
kha.graphics4.TextureFormat.RGBA32,
|
||||||
|
kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
|
||||||
|
|
||||||
|
tree.notifyOnRender(render);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function render(g: kha.graphics4.Graphics) {
|
||||||
|
|
||||||
|
var ready = false;
|
||||||
|
final sceneCam = iron.Scene.active.camera;
|
||||||
|
final oldRT = camera.renderTarget;
|
||||||
|
|
||||||
|
iron.Scene.active.camera = camera;
|
||||||
|
camera.renderTarget = renderTarget;
|
||||||
|
|
||||||
|
camera.renderFrame(g);
|
||||||
|
|
||||||
|
var tex = camera.renderTarget;
|
||||||
|
|
||||||
|
camera.renderTarget = oldRT;
|
||||||
|
iron.Scene.active.camera = sceneCam;
|
||||||
|
|
||||||
|
var pixels = tex.getPixels();
|
||||||
|
|
||||||
|
for (i in 0...pixels.length){
|
||||||
|
if (pixels.get(i) != 0){ ready = true; break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//wait for getPixels ready
|
||||||
|
if (ready) {
|
||||||
|
|
||||||
|
var tx = inputs[5].get();
|
||||||
|
var ty = inputs[6].get();
|
||||||
|
var tw = inputs[7].get();
|
||||||
|
var th = inputs[8].get();
|
||||||
|
|
||||||
|
var bo = new haxe.io.BytesOutput();
|
||||||
|
var rgb = haxe.io.Bytes.alloc(tw * th * 4);
|
||||||
|
for (j in ty...ty + th) {
|
||||||
|
for (i in tx...tx + tw) {
|
||||||
|
var k = j * tex.width + i;
|
||||||
|
var m = (j - ty) * tw + i - tx;
|
||||||
|
|
||||||
|
#if kha_krom
|
||||||
|
var l = k;
|
||||||
|
#elseif kha_html5
|
||||||
|
var l = (tex.height - j) * tex.width + i;
|
||||||
|
#end
|
||||||
|
|
||||||
|
//ARGB 0xff
|
||||||
|
rgb.set(m * 4 + 0, pixels.get(l * 4 + 3));
|
||||||
|
rgb.set(m * 4 + 1, pixels.get(l * 4 + 0));
|
||||||
|
rgb.set(m * 4 + 2, pixels.get(l * 4 + 1));
|
||||||
|
rgb.set(m * 4 + 3, pixels.get(l * 4 + 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var imgwriter = new iron.format.bmp.Writer(bo);
|
||||||
|
imgwriter.write(iron.format.bmp.Tools.buildFromARGB(tw, th, rgb));
|
||||||
|
|
||||||
|
#if kha_krom
|
||||||
|
Krom.fileSaveBytes(Krom.getFilesLocation() + "/" + file, bo.getBytes().getData());
|
||||||
|
|
||||||
|
#elseif kha_html5
|
||||||
|
var blob = new js.html.Blob([bo.getBytes().getData()], {type: "application"});
|
||||||
|
var url = js.html.URL.createObjectURL(blob);
|
||||||
|
var a = cast(js.Browser.document.createElement("a"), js.html.AnchorElement);
|
||||||
|
a.href = url;
|
||||||
|
a.download = file;
|
||||||
|
a.click();
|
||||||
|
js.html.URL.revokeObjectURL(url);
|
||||||
|
#end
|
||||||
|
|
||||||
|
runOutput(0);
|
||||||
|
|
||||||
|
tree.removeRender(render);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -529,22 +529,29 @@ 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.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) {
|
if (l != null){
|
||||||
l.data.raw.shadowmap_size = config.rp_shadowmap_cascade;
|
if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) {
|
||||||
var rt = path.renderTargets.get("shadowMap");
|
l.data.raw.shadowmap_size = config.rp_shadowmap_cascade;
|
||||||
if (rt != null) {
|
var rt = path.renderTargets.get("shadowMap");
|
||||||
rt.unload();
|
if (rt != null) {
|
||||||
path.renderTargets.remove("shadowMap");
|
rt.unload();
|
||||||
|
path.renderTargets.remove("shadowMap");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) {
|
||||||
else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) {
|
l.data.raw.shadowmap_size = config.rp_shadowmap_cube;
|
||||||
l.data.raw.shadowmap_size = config.rp_shadowmap_cube;
|
var rt = path.renderTargets.get("shadowMapCube");
|
||||||
var rt = path.renderTargets.get("shadowMapCube");
|
if (rt != null) {
|
||||||
if (rt != null) {
|
rt.unload();
|
||||||
rt.unload();
|
path.renderTargets.remove("shadowMapCube");
|
||||||
path.renderTargets.remove("shadowMapCube");
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (superSample != config.rp_supersample) {
|
if (superSample != config.rp_supersample) {
|
||||||
@ -778,7 +785,11 @@ class Inc {
|
|||||||
|
|
||||||
public static inline function getDisplayp(): Null<Int> {
|
public static inline function getDisplayp(): Null<Int> {
|
||||||
#if rp_resolution_filter // Custom resolution set
|
#if rp_resolution_filter // Custom resolution set
|
||||||
|
#if rp_pp
|
||||||
|
return leenkx.renderpath.Postprocess.resolution_uniforms[0];
|
||||||
|
#else
|
||||||
return Main.resolutionSize;
|
return Main.resolutionSize;
|
||||||
|
#end
|
||||||
#else
|
#else
|
||||||
return null;
|
return null;
|
||||||
#end
|
#end
|
||||||
|
@ -49,15 +49,20 @@ class Postprocess {
|
|||||||
0.01, //4: Fisheye Distortion
|
0.01, //4: Fisheye Distortion
|
||||||
1, //5: DoF AutoFocus §§ If true, it ignores the DoF Distance setting
|
1, //5: DoF AutoFocus §§ If true, it ignores the DoF Distance setting
|
||||||
10.0, //6: DoF Distance
|
10.0, //6: DoF Distance
|
||||||
160.0, //7: DoF Focal Length mm
|
50.0, //7: DoF Focal Length mm
|
||||||
128, //8: DoF F-Stop
|
128, //8: DoF F-Stop
|
||||||
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,35 @@ 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 var resolution_uniforms = [
|
||||||
|
720, //0: Size
|
||||||
|
0 //1: Filter
|
||||||
];
|
];
|
||||||
|
|
||||||
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 +317,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 +335,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 +346,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 +377,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;
|
||||||
|
@ -45,7 +45,7 @@ class DebugDrawHelper {
|
|||||||
|
|
||||||
iron.App.notifyOnRender2D(onRender);
|
iron.App.notifyOnRender2D(onRender);
|
||||||
if (debugDrawMode & DrawRayCast != 0) {
|
if (debugDrawMode & DrawRayCast != 0) {
|
||||||
iron.App.notifyOnUpdate(function () {
|
iron.App.notifyOnFixedUpdate(function () {
|
||||||
rayCasts.resize(0);
|
rayCasts.resize(0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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,10 +137,10 @@ 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);
|
||||||
|
|
||||||
iron.Scene.active.notifyOnRemove(function() {
|
iron.Scene.active.notifyOnRemove(function() {
|
||||||
@ -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();
|
||||||
@ -436,8 +434,8 @@ class PhysicsWorld extends Trait {
|
|||||||
from: from,
|
from: from,
|
||||||
to: to,
|
to: to,
|
||||||
hasHit: rc.hasHit(),
|
hasHit: rc.hasHit(),
|
||||||
hitPoint: hitPointWorld,
|
hitPoint: hitPointWorld.clone(),
|
||||||
hitNormal: hitNormalWorld
|
hitNormal: hitNormalWorld.clone()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,7 +323,8 @@ 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();
|
||||||
|
|
||||||
#if js
|
#if js
|
||||||
@ -317,26 +334,71 @@ class RigidBody extends iron.Trait {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
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) {
|
||||||
|
var ptransform = object.parent.transform;
|
||||||
|
transform.loc.x -= ptransform.worldx();
|
||||||
|
transform.loc.y -= ptransform.worldy();
|
||||||
|
transform.loc.z -= ptransform.worldz();
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
function physicsUpdate() {
|
||||||
if (!ready) return;
|
if (!ready) return;
|
||||||
if (animated) {
|
if (animated) {
|
||||||
syncTransform();
|
syncTransform();
|
||||||
}
|
} else {
|
||||||
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 trans = body.getWorldTransform();
|
||||||
var p = trans.getOrigin();
|
var p = trans.getOrigin();
|
||||||
var q = trans.getRotation();
|
var q = trans.getRotation();
|
||||||
|
|
||||||
transform.loc.set(p.x(), p.y(), p.z());
|
|
||||||
transform.rot.set(q.x(), q.y(), q.z(), q.w());
|
|
||||||
if (object.parent != null) {
|
|
||||||
var ptransform = object.parent.transform;
|
|
||||||
transform.loc.x -= ptransform.worldx();
|
|
||||||
transform.loc.y -= ptransform.worldy();
|
|
||||||
transform.loc.z -= ptransform.worldz();
|
|
||||||
}
|
|
||||||
transform.clearDelta();
|
transform.clearDelta();
|
||||||
transform.buildMatrix();
|
// 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;
|
||||||
}
|
}
|
||||||
|
@ -540,7 +540,7 @@ class LeenkxExporter:
|
|||||||
o['material_refs'].append(lnx.utils.asset_name(material))
|
o['material_refs'].append(lnx.utils.asset_name(material))
|
||||||
|
|
||||||
def export_particle_system_ref(self, psys: bpy.types.ParticleSystem, out_object):
|
def export_particle_system_ref(self, psys: bpy.types.ParticleSystem, out_object):
|
||||||
if psys.settings.instance_object is None or psys.settings.render_type != 'OBJECT' or not psys.settings.instance_object.lnx_export:
|
if psys.settings.instance_object is None or psys.settings.render_type != 'OBJECT' or not psys.settings.instance_object.lnx_export or not bpy.data.objects[out_object['name']].modifiers[psys.name].show_render:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.particle_system_array[psys.settings] = {"structName": psys.settings.name}
|
self.particle_system_array[psys.settings] = {"structName": psys.settings.name}
|
||||||
@ -910,7 +910,8 @@ class LeenkxExporter:
|
|||||||
out_object['particle_refs'] = []
|
out_object['particle_refs'] = []
|
||||||
out_object['render_emitter'] = bobject.show_instancer_for_render
|
out_object['render_emitter'] = bobject.show_instancer_for_render
|
||||||
for i in range(num_psys):
|
for i in range(num_psys):
|
||||||
self.export_particle_system_ref(bobject.particle_systems[i], out_object)
|
if bobject.modifiers[bobject.particle_systems[i].name].show_render:
|
||||||
|
self.export_particle_system_ref(bobject.particle_systems[i], out_object)
|
||||||
|
|
||||||
aabb = bobject.data.lnx_aabb
|
aabb = bobject.data.lnx_aabb
|
||||||
if aabb[0] == 0 and aabb[1] == 0 and aabb[2] == 0:
|
if aabb[0] == 0 and aabb[1] == 0 and aabb[2] == 0:
|
||||||
@ -2280,6 +2281,15 @@ class LeenkxExporter:
|
|||||||
if len(self.particle_system_array) > 0:
|
if len(self.particle_system_array) > 0:
|
||||||
self.output['particle_datas'] = []
|
self.output['particle_datas'] = []
|
||||||
for particleRef in self.particle_system_array.items():
|
for particleRef in self.particle_system_array.items():
|
||||||
|
padd = False;
|
||||||
|
for obj in self.output['objects']:
|
||||||
|
if 'particle_refs' in obj:
|
||||||
|
for pref in obj['particle_refs']:
|
||||||
|
if pref['particle'] == particleRef[1]["structName"]:
|
||||||
|
if bpy.data.objects[obj['name']].modifiers[pref['name']].show_render == True:
|
||||||
|
padd = True;
|
||||||
|
if not padd:
|
||||||
|
continue;
|
||||||
psettings = particleRef[0]
|
psettings = particleRef[0]
|
||||||
|
|
||||||
if psettings is None:
|
if psettings is None:
|
||||||
@ -2297,6 +2307,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 +2825,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 +3050,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":
|
||||||
|
@ -191,7 +191,7 @@ def apply_materials(load_atlas=0):
|
|||||||
|
|
||||||
mainNode = outputNode.inputs[0].links[0].from_node.inputs[0].links[0].from_node
|
mainNode = outputNode.inputs[0].links[0].from_node.inputs[0].links[0].from_node
|
||||||
|
|
||||||
if (mainNode.type == "ShaderNodeMixRGB"):
|
if (mainNode.type == "ShaderNodeMix"):
|
||||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||||
print("Mix RGB shader found")
|
print("Mix RGB shader found")
|
||||||
|
|
||||||
@ -199,9 +199,11 @@ def apply_materials(load_atlas=0):
|
|||||||
|
|
||||||
#Add all nodes first
|
#Add all nodes first
|
||||||
#Add lightmap multipliction texture
|
#Add lightmap multipliction texture
|
||||||
mixNode = node_tree.nodes.new(type="ShaderNodeMixRGB")
|
mixNode = node_tree.nodes.new(type="ShaderNodeMix")
|
||||||
mixNode.name = "Lightmap_Multiplication"
|
mixNode.name = "Lightmap_Multiplication"
|
||||||
mixNode.location = -800, 300
|
mixNode.location = -800, 300
|
||||||
|
mixNode.data_type = 'RGBA'
|
||||||
|
mixNode.inputs[0].default_value = 1
|
||||||
if scene.TLM_EngineProperties.tlm_lighting_mode == "indirect" or scene.TLM_EngineProperties.tlm_lighting_mode == "indirectAO":
|
if scene.TLM_EngineProperties.tlm_lighting_mode == "indirect" or scene.TLM_EngineProperties.tlm_lighting_mode == "indirectAO":
|
||||||
mixNode.blend_type = 'MULTIPLY'
|
mixNode.blend_type = 'MULTIPLY'
|
||||||
else:
|
else:
|
||||||
@ -312,8 +314,8 @@ def apply_materials(load_atlas=0):
|
|||||||
else:
|
else:
|
||||||
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
|
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
|
||||||
|
|
||||||
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect decode node to mixnode
|
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[6]) #Connect decode node to mixnode
|
||||||
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect exposure node to mixnode
|
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[6]) #Connect exposure node to mixnode
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@ -323,10 +325,10 @@ def apply_materials(load_atlas=0):
|
|||||||
else:
|
else:
|
||||||
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
|
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
|
||||||
|
|
||||||
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
|
||||||
|
|
||||||
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
|
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[7]) #Connect basecolor to pbr node
|
||||||
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
|
mat.node_tree.links.new(mixNode.outputs[2], mainNode.inputs[0]) #Connect mixnode to pbr node
|
||||||
|
|
||||||
if not scene.TLM_EngineProperties.tlm_target == "vertex":
|
if not scene.TLM_EngineProperties.tlm_target == "vertex":
|
||||||
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
|
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
|
||||||
@ -338,11 +340,11 @@ def apply_materials(load_atlas=0):
|
|||||||
|
|
||||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||||
mat.node_tree.links.new(lightmapNode.outputs[0], ExposureNode.inputs[0]) #Connect lightmap node to mixnode
|
mat.node_tree.links.new(lightmapNode.outputs[0], ExposureNode.inputs[0]) #Connect lightmap node to mixnode
|
||||||
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
|
||||||
else:
|
else:
|
||||||
mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
|
||||||
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
|
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[7]) #Connect basecolor to pbr node
|
||||||
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
|
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[2]) #Connect mixnode to pbr node
|
||||||
if not scene.TLM_EngineProperties.tlm_target == "vertex":
|
if not scene.TLM_EngineProperties.tlm_target == "vertex":
|
||||||
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
|
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
|
||||||
|
|
||||||
@ -491,8 +493,9 @@ def applyAOPass():
|
|||||||
AOMap.image = AOImage
|
AOMap.image = AOImage
|
||||||
AOMap.location = -800, 0
|
AOMap.location = -800, 0
|
||||||
|
|
||||||
AOMult = nodes.new(type="ShaderNodeMixRGB")
|
AOMult = nodes.new(type="ShaderNodeMix")
|
||||||
AOMult.name = "TLM_AOMult"
|
AOMult.name = "TLM_AOMult"
|
||||||
|
AOMult.data_type = 'RGBA'
|
||||||
AOMult.blend_type = 'MULTIPLY'
|
AOMult.blend_type = 'MULTIPLY'
|
||||||
AOMult.inputs[0].default_value = 1.0
|
AOMult.inputs[0].default_value = 1.0
|
||||||
AOMult.location = -300, 300
|
AOMult.location = -300, 300
|
||||||
|
@ -518,7 +518,7 @@ def configure_meshes(self):
|
|||||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||||
print("The material group is not supported!")
|
print("The material group is not supported!")
|
||||||
|
|
||||||
if (mainNode.type == "ShaderNodeMixRGB"):
|
if (mainNode.type == "ShaderNodeMix"):
|
||||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||||
print("Mix shader found")
|
print("Mix shader found")
|
||||||
|
|
||||||
@ -811,7 +811,7 @@ def set_settings():
|
|||||||
|
|
||||||
print(bpy.app.version)
|
print(bpy.app.version)
|
||||||
|
|
||||||
if bpy.app.version[0] == 3:
|
if bpy.app.version[0] == 3 or byp.app.version[0] == 4:
|
||||||
if cycles.device == "GPU":
|
if cycles.device == "GPU":
|
||||||
scene.cycles.tile_size = 256
|
scene.cycles.tile_size = 256
|
||||||
else:
|
else:
|
||||||
|
@ -28,7 +28,11 @@ class ViewportDraw:
|
|||||||
w = 400
|
w = 400
|
||||||
h = 200
|
h = 200
|
||||||
|
|
||||||
self.shader = gpu.shader.from_builtin('2D_IMAGE')
|
if bpy.app.version[0] == 3:
|
||||||
|
self.shader = gpu.shader.from_builtin('2D_IMAGE')
|
||||||
|
else:
|
||||||
|
self.shader = gpu.shader.from_builtin('IMAGE')
|
||||||
|
|
||||||
self.batch = batch_for_shader(
|
self.batch = batch_for_shader(
|
||||||
self.shader, 'TRI_FAN',
|
self.shader, 'TRI_FAN',
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ class Shader_Node_Types:
|
|||||||
normal = "ShaderNodeNormalMap"
|
normal = "ShaderNodeNormalMap"
|
||||||
ao = "ShaderNodeAmbientOcclusion"
|
ao = "ShaderNodeAmbientOcclusion"
|
||||||
uv = "ShaderNodeUVMap"
|
uv = "ShaderNodeUVMap"
|
||||||
mix = "ShaderNodeMixRGB"
|
mix = "ShaderNodeMix"
|
||||||
|
|
||||||
def select_object(self,obj):
|
def select_object(self,obj):
|
||||||
C = bpy.context
|
C = bpy.context
|
||||||
|
@ -47,7 +47,8 @@ def init_categories():
|
|||||||
lnx_nodes.add_category('Navmesh', icon='UV_VERTEXSEL', section="motion")
|
lnx_nodes.add_category('Navmesh', icon='UV_VERTEXSEL', section="motion")
|
||||||
lnx_nodes.add_category('Transform', icon='TRANSFORM_ORIGINS', section="motion")
|
lnx_nodes.add_category('Transform', icon='TRANSFORM_ORIGINS', section="motion")
|
||||||
lnx_nodes.add_category('Physics', icon='PHYSICS', section="motion")
|
lnx_nodes.add_category('Physics', icon='PHYSICS', section="motion")
|
||||||
|
lnx_nodes.add_category('Particle', icon='PARTICLE_DATA', section="motion")
|
||||||
|
|
||||||
lnx_nodes.add_category('Array', icon='MOD_ARRAY', section="values")
|
lnx_nodes.add_category('Array', icon='MOD_ARRAY', section="values")
|
||||||
lnx_nodes.add_category('Map', icon='SHORTDISPLAY', section="values")
|
lnx_nodes.add_category('Map', icon='SHORTDISPLAY', section="values")
|
||||||
lnx_nodes.add_category('Database', icon='MESH_CYLINDER', section="values")
|
lnx_nodes.add_category('Database', icon='MESH_CYLINDER', section="values")
|
||||||
|
@ -11,14 +11,15 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
|
|||||||
@input Object: Object of which to choose the material in the `Material Slot` input.
|
@input Object: Object of which to choose the material in the `Material Slot` input.
|
||||||
@input Material Slot: Index of the material slot of which the diffuse
|
@input Material Slot: Index of the material slot of which the diffuse
|
||||||
texture is replaced with the camera's render target.
|
texture is replaced with the camera's render target.
|
||||||
|
@input Node: Node name of the Image Texture Node.
|
||||||
|
|
||||||
@output On Start: Activated after the `Start` input has been activated.
|
@output On Start: Activated after the `Start` input has been activated.
|
||||||
@output On Stop: Activated after the `Stop` input has been activated.
|
@output On Stop: Activated after the `Stop` input has been activated.
|
||||||
"""
|
"""
|
||||||
bl_idname = 'LNDrawCameraTextureNode'
|
bl_idname = 'LNDrawCameraTextureNode'
|
||||||
bl_label = 'Draw Camera to Texture'
|
bl_label = 'Draw Camera to Texture'
|
||||||
lnx_section = 'draw'
|
lnx_section = 'draw'
|
||||||
lnx_version = 1
|
lnx_version = 2
|
||||||
|
|
||||||
def lnx_init(self, context):
|
def lnx_init(self, context):
|
||||||
self.add_input('LnxNodeSocketAction', 'Start')
|
self.add_input('LnxNodeSocketAction', 'Start')
|
||||||
@ -26,6 +27,13 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
|
|||||||
self.add_input('LnxNodeSocketObject', 'Camera')
|
self.add_input('LnxNodeSocketObject', 'Camera')
|
||||||
self.add_input('LnxNodeSocketObject', 'Object')
|
self.add_input('LnxNodeSocketObject', 'Object')
|
||||||
self.add_input('LnxIntSocket', 'Material Slot')
|
self.add_input('LnxIntSocket', 'Material Slot')
|
||||||
|
self.add_input('LnxStringSocket', 'Node')
|
||||||
|
|
||||||
self.add_output('LnxNodeSocketAction', 'On Start')
|
self.add_output('LnxNodeSocketAction', 'On Start')
|
||||||
self.add_output('LnxNodeSocketAction', 'On Stop')
|
self.add_output('LnxNodeSocketAction', 'On Stop')
|
||||||
|
|
||||||
|
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||||
|
if self.lnx_version not in (0, 1):
|
||||||
|
raise LookupError()
|
||||||
|
|
||||||
|
return NodeReplacement.Identity(self)
|
44
leenkx/blender/lnx/logicnode/draw/LN_draw_sub_image.py
Normal file
44
leenkx/blender/lnx/logicnode/draw/LN_draw_sub_image.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
|
||||||
|
class DrawSubImageNode(LnxLogicTreeNode):
|
||||||
|
"""Draws an image.
|
||||||
|
@input Draw: Activate to draw the image on this frame. The input must
|
||||||
|
be (indirectly) called from an `On Render2D` node.
|
||||||
|
@input Image: The filename of the image.
|
||||||
|
@input Color: The color that the image's pixels are multiplied with.
|
||||||
|
@input Left/Center/Right: Horizontal anchor point of the image.
|
||||||
|
0 = Left, 1 = Center, 2 = Right
|
||||||
|
@input Top/Middle/Bottom: Vertical anchor point of the image.
|
||||||
|
0 = Top, 1 = Middle, 2 = Bottom
|
||||||
|
@input X/Y: Position of the anchor point in pixels.
|
||||||
|
@input Width/Height: Size of the sub image in pixels.
|
||||||
|
@input sX/Y: Position of the sub anchor point in pixels.
|
||||||
|
@input sWidth/Height: Size of the image in pixels.
|
||||||
|
@input Angle: Rotation angle in radians. Image will be rotated cloclwiswe
|
||||||
|
at the anchor point.
|
||||||
|
@output Out: Activated after the image has been drawn.
|
||||||
|
@see [`kha.graphics2.Graphics.drawImage()`](http://kha.tech/api/kha/graphics2/Graphics.html#drawImage).
|
||||||
|
"""
|
||||||
|
bl_idname = 'LNDrawSubImageNode'
|
||||||
|
bl_label = 'Draw Sub Image'
|
||||||
|
lnx_section = 'draw'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_input('LnxNodeSocketAction', 'Draw')
|
||||||
|
self.add_input('LnxStringSocket', 'Image File')
|
||||||
|
self.add_input('LnxColorSocket', 'Color', default_value=[1.0, 1.0, 1.0, 1.0])
|
||||||
|
self.add_input('LnxIntSocket', '0/1/2 = Left/Center/Right', default_value=0)
|
||||||
|
self.add_input('LnxIntSocket', '0/1/2 = Top/Middle/Bottom', default_value=0)
|
||||||
|
self.add_input('LnxFloatSocket', 'X')
|
||||||
|
self.add_input('LnxFloatSocket', 'Y')
|
||||||
|
self.add_input('LnxFloatSocket', 'Width')
|
||||||
|
self.add_input('LnxFloatSocket', 'Height')
|
||||||
|
self.add_input('LnxFloatSocket', 'sX')
|
||||||
|
self.add_input('LnxFloatSocket', 'sY')
|
||||||
|
self.add_input('LnxFloatSocket', 'sWidth')
|
||||||
|
self.add_input('LnxFloatSocket', 'sHeight')
|
||||||
|
self.add_input('LnxFloatSocket', 'Angle')
|
||||||
|
|
||||||
|
self.add_output('LnxNodeSocketAction', 'Out')
|
@ -0,0 +1,23 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class SetMaterialTextureFilterNode(LnxLogicTreeNode):
|
||||||
|
"""Sets texture filter interpolation."""
|
||||||
|
bl_idname = 'LNSetMaterialTextureFilterNode'
|
||||||
|
bl_label = 'Set Object Material Texture Filter'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_input('LnxNodeSocketAction', 'In')
|
||||||
|
self.add_input('LnxNodeSocketObject', 'Object')
|
||||||
|
self.add_input('LnxDynamicSocket', 'Material')
|
||||||
|
self.add_input('LnxIntSocket', 'Slot')
|
||||||
|
self.add_input('LnxStringSocket', 'Node')
|
||||||
|
self.add_input('LnxIntSocket', 'Texture Filter')
|
||||||
|
|
||||||
|
self.add_output('LnxNodeSocketAction', 'Out')
|
||||||
|
|
||||||
|
def draw_buttons(self, context, layout):
|
||||||
|
layout.label(text='Tex Filter 0: Linear')
|
||||||
|
layout.label(text='Tex Filter 1: Closest')
|
||||||
|
layout.label(text='Tex Filter 2: Cubic')
|
||||||
|
layout.label(text='Tex Filter 3: Smart')
|
@ -5,8 +5,6 @@ class WriteFileNode(LnxLogicTreeNode):
|
|||||||
"""Writes the given string content to the given file. If the file
|
"""Writes the given string content to the given file. If the file
|
||||||
already exists, the existing content of the file is overwritten.
|
already exists, the existing content of the file is overwritten.
|
||||||
|
|
||||||
> **This node is currently only implemented on Krom**
|
|
||||||
|
|
||||||
@input File: the name of the file, relative to `Krom.getFilesLocation()`
|
@input File: the name of the file, relative to `Krom.getFilesLocation()`
|
||||||
@input Content: the content to write to the file.
|
@input Content: the content to write to the file.
|
||||||
|
|
||||||
|
34
leenkx/blender/lnx/logicnode/native/LN_write_image.py
Normal file
34
leenkx/blender/lnx/logicnode/native/LN_write_image.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
|
||||||
|
class WriteImageNode(LnxLogicTreeNode):
|
||||||
|
"""Writes the given image to the given file. If the image
|
||||||
|
already exists, the existing content of the image is overwritten.
|
||||||
|
Aspect ratio must match display resolution ratio.
|
||||||
|
@input Image File: the name of the image, relative to `Krom.getFilesLocation()`
|
||||||
|
@input Camera: the render target image of the camera to write to the image file.
|
||||||
|
@input Width: width of the image file.
|
||||||
|
@input Height: heigth of the image file.
|
||||||
|
@input sX: sub position of first x pixel of the sub image (0 for start).
|
||||||
|
@input sY: sub position of first y pixel of the sub image (0 for start).
|
||||||
|
@input sWidth: width of the sub image.
|
||||||
|
@input sHeight: height of the sub image.
|
||||||
|
@seeNode Read File
|
||||||
|
"""
|
||||||
|
bl_idname = 'LNWriteImageNode'
|
||||||
|
bl_label = 'Write Image'
|
||||||
|
lnx_section = 'file'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_input('LnxNodeSocketAction', 'In')
|
||||||
|
self.add_input('LnxStringSocket', 'Image File')
|
||||||
|
self.add_input('LnxNodeSocketObject', 'Camera')
|
||||||
|
self.add_input('LnxIntSocket', 'Width')
|
||||||
|
self.add_input('LnxIntSocket', 'Height')
|
||||||
|
self.add_input('LnxIntSocket', 'sX')
|
||||||
|
self.add_input('LnxIntSocket', 'sY')
|
||||||
|
self.add_input('LnxIntSocket', 'sWidth')
|
||||||
|
self.add_input('LnxIntSocket', 'sHeight')
|
||||||
|
|
||||||
|
self.add_output('LnxNodeSocketAction', 'Out')
|
@ -5,8 +5,6 @@ class WriteJsonNode(LnxLogicTreeNode):
|
|||||||
"""Writes the given content to the given JSON file. If the file
|
"""Writes the given content to the given JSON file. If the file
|
||||||
already exists, the existing content of the file is overwritten.
|
already exists, the existing content of the file is overwritten.
|
||||||
|
|
||||||
> **This node is currently only implemented on Krom**
|
|
||||||
|
|
||||||
@input File: the name of the file, relative to `Krom.getFilesLocation()`,
|
@input File: the name of the file, relative to `Krom.getFilesLocation()`,
|
||||||
including the file extension.
|
including the file extension.
|
||||||
@input Dynamic: the content to write to the file. Can be any type that can
|
@input Dynamic: the content to write to the file. Can be any type that can
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class AddParticleToObjectNode(LnxLogicTreeNode):
|
||||||
|
"""Sets the speed of the given particle source."""
|
||||||
|
bl_idname = 'LNAddParticleToObjectNode'
|
||||||
|
bl_label = 'Add Particle To Object'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def remove_extra_inputs(self, context):
|
||||||
|
while len(self.inputs) > 1:
|
||||||
|
self.inputs.remove(self.inputs[-1])
|
||||||
|
if self.property0 == 'Scene':
|
||||||
|
self.add_input('LnxStringSocket', 'Scene From Name')
|
||||||
|
self.add_input('LnxStringSocket', 'Object From Name')
|
||||||
|
else:
|
||||||
|
self.add_input('LnxNodeSocketObject', 'Object From')
|
||||||
|
self.add_input('LnxIntSocket', 'Slot')
|
||||||
|
self.add_input('LnxNodeSocketObject', 'Object To')
|
||||||
|
self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True)
|
||||||
|
|
||||||
|
|
||||||
|
property0: HaxeEnumProperty(
|
||||||
|
'property0',
|
||||||
|
items = [('Scene Active', 'Scene Active', 'Scene Active'),
|
||||||
|
('Scene', 'Scene', 'Scene')],
|
||||||
|
name='', default='Scene Active', update=remove_extra_inputs)
|
||||||
|
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_input('LnxNodeSocketAction', 'In')
|
||||||
|
self.add_input('LnxNodeSocketObject', 'Object From')
|
||||||
|
self.add_input('LnxIntSocket', 'Slot')
|
||||||
|
self.add_input('LnxNodeSocketObject', 'Object To')
|
||||||
|
self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True)
|
||||||
|
|
||||||
|
self.add_output('LnxNodeSocketAction', 'Out')
|
||||||
|
|
||||||
|
def draw_buttons(self, context, layout):
|
||||||
|
layout.prop(self, 'property0')
|
||||||
|
|
||||||
|
|
14
leenkx/blender/lnx/logicnode/particle/LN_get_particle.py
Normal file
14
leenkx/blender/lnx/logicnode/particle/LN_get_particle.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class GetParticleNode(LnxLogicTreeNode):
|
||||||
|
"""Returns the Particle Systems of an object."""
|
||||||
|
bl_idname = 'LNGetParticleNode'
|
||||||
|
bl_label = 'Get Particle'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.inputs.new('LnxNodeSocketObject', 'Object')
|
||||||
|
|
||||||
|
self.outputs.new('LnxNodeSocketArray', 'Names')
|
||||||
|
self.outputs.new('LnxIntSocket', 'Length')
|
||||||
|
self.outputs.new('LnxBoolSocket', 'Render Emitter')
|
@ -0,0 +1,34 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class GetParticleDataNode(LnxLogicTreeNode):
|
||||||
|
"""Returns the data of the given Particle System."""
|
||||||
|
bl_idname = 'LNGetParticleDataNode'
|
||||||
|
bl_label = 'Get Particle Data'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.inputs.new('LnxNodeSocketObject', 'Object')
|
||||||
|
self.inputs.new('LnxIntSocket', 'Slot')
|
||||||
|
|
||||||
|
self.outputs.new('LnxStringSocket', 'Name')
|
||||||
|
self.outputs.new('LnxFloatSocket', 'Particle Size')
|
||||||
|
self.outputs.new('LnxIntSocket', 'Frame Start')
|
||||||
|
self.outputs.new('LnxIntSocket', 'Frame End')
|
||||||
|
self.outputs.new('LnxIntSocket', 'Lifetime')
|
||||||
|
self.outputs.new('LnxFloatSocket', 'Lifetime Random')
|
||||||
|
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('LnxFloatSocket', 'Velocity Random')
|
||||||
|
self.outputs.new('LnxVectorSocket', 'Gravity')
|
||||||
|
self.outputs.new('LnxFloatSocket', 'Weight Gravity')
|
||||||
|
|
||||||
|
self.outputs.new('LnxFloatSocket', 'Speed')
|
||||||
|
|
||||||
|
self.outputs.new('LnxFloatSocket', 'Time')
|
||||||
|
self.outputs.new('LnxFloatSocket', 'Lap')
|
||||||
|
self.outputs.new('LnxFloatSocket', 'Lap Time')
|
||||||
|
self.outputs.new('LnxIntSocket', 'Count')
|
@ -0,0 +1,33 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class RemoveParticleFromObjectNode(LnxLogicTreeNode):
|
||||||
|
"""Remove Particle From Object."""
|
||||||
|
bl_idname = 'LNRemoveParticleFromObjectNode'
|
||||||
|
bl_label = 'Remove Particle From Object'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def remove_extra_inputs(self, context):
|
||||||
|
while len(self.inputs) > 2:
|
||||||
|
self.inputs.remove(self.inputs[-1])
|
||||||
|
if self.property0 == 'Slot':
|
||||||
|
self.add_input('LnxIntSocket', 'Slot')
|
||||||
|
if self.property0 == 'Name':
|
||||||
|
self.add_input('LnxStringSocket', 'Name')
|
||||||
|
|
||||||
|
property0: HaxeEnumProperty(
|
||||||
|
'property0',
|
||||||
|
items = [('Slot', 'Slot', 'Slot'),
|
||||||
|
('Name', 'Name', 'Name'),
|
||||||
|
('All', 'All', 'All')],
|
||||||
|
name='', default='Slot', update=remove_extra_inputs)
|
||||||
|
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_input('LnxNodeSocketAction', 'In')
|
||||||
|
self.add_input('LnxNodeSocketObject', 'Object')
|
||||||
|
self.add_input('LnxIntSocket', 'Slot')
|
||||||
|
|
||||||
|
self.add_output('LnxNodeSocketAction', 'Out')
|
||||||
|
|
||||||
|
def draw_buttons(self, context, layout):
|
||||||
|
layout.prop(self, 'property0')
|
@ -0,0 +1,67 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class SetParticleDataNode(LnxLogicTreeNode):
|
||||||
|
"""Sets the parameters of the given particle system."""
|
||||||
|
bl_idname = 'LNSetParticleDataNode'
|
||||||
|
bl_label = 'Set Particle Data'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def remove_extra_inputs(self, context):
|
||||||
|
while len(self.inputs) > 3:
|
||||||
|
self.inputs.remove(self.inputs[-1])
|
||||||
|
if self.property0 == 'Particle Size':
|
||||||
|
self.add_input('LnxFloatSocket', 'Particle Size')
|
||||||
|
if self.property0 == 'Frame End':
|
||||||
|
self.add_input('LnxIntSocket', 'Frame End')
|
||||||
|
if self.property0 == 'Frame Start':
|
||||||
|
self.add_input('LnxIntSocket', 'Frame Start')
|
||||||
|
if self.property0 == 'Lifetime':
|
||||||
|
self.add_input('LnxIntSocket', 'Lifetime')
|
||||||
|
if self.property0 == 'Lifetime Random':
|
||||||
|
self.add_input('LnxFloatSocket', 'Lifetime Random')
|
||||||
|
if self.property0 == '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':
|
||||||
|
self.add_input('LnxVectorSocket', 'Velocity')
|
||||||
|
if self.property0 == 'Velocity Random':
|
||||||
|
self.add_input('LnxFloatSocket', 'Velocity Random')
|
||||||
|
if self.property0 == 'Weight Gravity':
|
||||||
|
self.add_input('LnxFloatSocket', 'Weight Gravity')
|
||||||
|
if self.property0 == 'Speed':
|
||||||
|
self.add_input('LnxFloatSocket', 'Speed')
|
||||||
|
|
||||||
|
|
||||||
|
property0: HaxeEnumProperty(
|
||||||
|
'property0',
|
||||||
|
items = [('Particle Size', 'Particle Size', 'for the system'),
|
||||||
|
('Frame Start', 'Frame Start', 'for the system'),
|
||||||
|
('Frame End', 'Frame End', 'for the system'),
|
||||||
|
('Lifetime', 'Lifetime', 'for the instance'),
|
||||||
|
('Lifetime Random', 'Lifetime Random', 'for the system'),
|
||||||
|
('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 Random', 'Velocity Random', 'for the system'),
|
||||||
|
('Weight Gravity', 'Weight Gravity', 'for the instance'),
|
||||||
|
('Speed', 'Speed', 'for the instance')],
|
||||||
|
name='', default='Speed', update=remove_extra_inputs)
|
||||||
|
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_input('LnxNodeSocketAction', 'In')
|
||||||
|
self.add_input('LnxNodeSocketObject', 'Object')
|
||||||
|
self.add_input('LnxIntSocket', 'Slot')
|
||||||
|
self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
|
||||||
|
|
||||||
|
self.add_output('LnxNodeSocketAction', 'Out')
|
||||||
|
|
||||||
|
def draw_buttons(self, context, layout):
|
||||||
|
layout.prop(self, 'property0')
|
@ -1,14 +1,22 @@
|
|||||||
from lnx.logicnode.lnx_nodes import *
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
class SetParticleSpeedNode(LnxLogicTreeNode):
|
class SetParticleSpeedNode(LnxLogicTreeNode):
|
||||||
"""Sets the speed of the given particle source."""
|
"""Sets the speed of the given particle source."""
|
||||||
bl_idname = 'LNSetParticleSpeedNode'
|
bl_idname = 'LNSetParticleSpeedNode'
|
||||||
bl_label = 'Set Particle Speed'
|
bl_label = 'Set Particle Speed'
|
||||||
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('LnxNodeSocketObject', 'Object')
|
self.add_input('LnxNodeSocketObject', 'Object')
|
||||||
self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
|
self.add_input('LnxIntSocket', 'Slot')
|
||||||
|
self.add_input('LnxFloatSocket', 'Speed', default_value=1.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)
|
3
leenkx/blender/lnx/logicnode/particle/__init__.py
Normal file
3
leenkx/blender/lnx/logicnode/particle/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import add_node_section
|
||||||
|
|
||||||
|
add_node_section(name='default', category='Particle')
|
@ -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)
|
@ -16,11 +16,12 @@ class CameraGetNode(LnxLogicTreeNode):
|
|||||||
self.add_output('LnxFloatSocket', 'DOF Distance')#6
|
self.add_output('LnxFloatSocket', 'DOF Distance')#6
|
||||||
self.add_output('LnxFloatSocket', 'DOF Length')#7
|
self.add_output('LnxFloatSocket', 'DOF Length')#7
|
||||||
self.add_output('LnxFloatSocket', 'DOF F-Stop')#8
|
self.add_output('LnxFloatSocket', 'DOF F-Stop')#8
|
||||||
self.add_output('LnxBoolSocket', 'Tonemapping')#9
|
self.add_output('LnxIntSocket', 'Tonemapping')#9
|
||||||
self.add_output('LnxFloatSocket', 'Distort')#10
|
self.add_output('LnxFloatSocket', 'Distort')#10
|
||||||
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 ResolutionGetNode(LnxLogicTreeNode):
|
||||||
|
"""Returns the resolution parameters.
|
||||||
|
"""
|
||||||
|
bl_idname = 'LNResolutionGetNode'
|
||||||
|
bl_label = 'Get Resolution Settings'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_output('LnxIntSocket', 'Size')
|
||||||
|
self.add_output('LnxIntSocket', 'Filter')
|
@ -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,27 @@
|
|||||||
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 draw_buttons(self, context, layout):
|
||||||
|
layout.label(text="Type 0: Simple")
|
||||||
|
layout.label(text="Type 1: Spectral")
|
||||||
|
|
||||||
|
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,81 @@ 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 = 6
|
||||||
|
|
||||||
|
|
||||||
|
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('LnxIntSocket', 'Tonemapping', default_value=5)#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):
|
||||||
|
if self.property0 == 'Tonemapping':
|
||||||
|
layout.label(text="0: Filmic")
|
||||||
|
layout.label(text="1: Filmic2")
|
||||||
|
layout.label(text="2: Reinhard")
|
||||||
|
layout.label(text="3: Uncharted2")
|
||||||
|
layout.label(text="5: Agx")
|
||||||
|
layout.label(text="6: None")
|
||||||
|
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,20 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class ResolutionSetNode(LnxLogicTreeNode):
|
||||||
|
"""Set the resolution post-processing settings.
|
||||||
|
Filter 0: Lineal 1: Closest
|
||||||
|
"""
|
||||||
|
bl_idname = 'LNResolutionSetNode'
|
||||||
|
bl_label = 'Set Resolution Settings'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_input('LnxNodeSocketAction', 'In')
|
||||||
|
self.add_input('LnxIntSocket', 'Size', default_value=720)
|
||||||
|
self.add_input('LnxIntSocket', 'Filter', default_value=0)
|
||||||
|
|
||||||
|
self.add_output('LnxNodeSocketAction', 'Out')
|
||||||
|
|
||||||
|
def draw_buttons(self, context, layout):
|
||||||
|
layout.label(text="Type 0: Lineal")
|
||||||
|
layout.label(text="Type 1: Closest")
|
@ -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)
|
@ -1,8 +1,8 @@
|
|||||||
from lnx.logicnode.lnx_nodes import *
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
class GetWorldNode(LnxLogicTreeNode):
|
class GetWorldOrientationNode(LnxLogicTreeNode):
|
||||||
"""Returns the world orientation of the given object."""
|
"""Returns the world orientation of the given object."""
|
||||||
bl_idname = 'LNGetWorldNode'
|
bl_idname = 'LNGetWorldOrientationNode'
|
||||||
bl_label = 'Get World Orientation'
|
bl_label = 'Get World Orientation'
|
||||||
lnx_section = 'rotation'
|
lnx_section = 'rotation'
|
||||||
lnx_version = 1
|
lnx_version = 1
|
||||||
|
10
leenkx/blender/lnx/logicnode/world/LN_get_world.py
Normal file
10
leenkx/blender/lnx/logicnode/world/LN_get_world.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class GetWorldNode(LnxLogicTreeNode):
|
||||||
|
"""Gets the World of the active scene."""
|
||||||
|
bl_idname = 'LNGetWorldNode'
|
||||||
|
bl_label = 'Get World'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_output('LnxStringSocket', 'World')
|
13
leenkx/blender/lnx/logicnode/world/LN_set_world.py
Normal file
13
leenkx/blender/lnx/logicnode/world/LN_set_world.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from lnx.logicnode.lnx_nodes import *
|
||||||
|
|
||||||
|
class SetWorldNode(LnxLogicTreeNode):
|
||||||
|
"""Sets the World of the active scene."""
|
||||||
|
bl_idname = 'LNSetWorldNode'
|
||||||
|
bl_label = 'Set World'
|
||||||
|
lnx_version = 1
|
||||||
|
|
||||||
|
def lnx_init(self, context):
|
||||||
|
self.add_input('LnxNodeSocketAction', 'In')
|
||||||
|
self.add_input('LnxStringSocket', 'World')
|
||||||
|
|
||||||
|
self.add_output('LnxNodeSocketAction', 'Out')
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user