forked from LeenkxTeam/LNXSDK
merge upstream
This commit is contained in:
@ -12,6 +12,7 @@ class App {
|
||||
static var traitInits: Array<Void->Void> = [];
|
||||
static var traitUpdates: 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 traitRenders2D: Array<kha.graphics2.Graphics->Void> = [];
|
||||
public static var framebuffer: kha.Framebuffer;
|
||||
@ -23,6 +24,8 @@ class App {
|
||||
public static var renderPathTime: Float;
|
||||
public static var endFrameCallbacks: Array<Void->Void> = [];
|
||||
#end
|
||||
static var last = 0.0;
|
||||
static var time = 0.0;
|
||||
static var lastw = -1;
|
||||
static var lasth = -1;
|
||||
public static var onResize: Void->Void = null;
|
||||
@ -34,13 +37,14 @@ class App {
|
||||
function new(done: Void->Void) {
|
||||
done();
|
||||
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() {
|
||||
traitInits = [];
|
||||
traitUpdates = [];
|
||||
traitLateUpdates = [];
|
||||
traitFixedUpdates = [];
|
||||
traitRenders = [];
|
||||
traitRenders2D = [];
|
||||
if (onResets != null) for (f in onResets) f();
|
||||
@ -48,6 +52,8 @@ class App {
|
||||
|
||||
static function update() {
|
||||
if (Scene.active == null || !Scene.active.ready) return;
|
||||
|
||||
iron.system.Time.update();
|
||||
if (pauseUpdates) return;
|
||||
|
||||
#if lnx_debug
|
||||
@ -56,6 +62,14 @@ class App {
|
||||
|
||||
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 l = traitUpdates.length;
|
||||
while (i < l) {
|
||||
@ -106,7 +120,7 @@ class App {
|
||||
var frame = frames[0];
|
||||
framebuffer = frame;
|
||||
|
||||
iron.system.Time.update();
|
||||
iron.system.Time.render();
|
||||
|
||||
if (Scene.active == null || !Scene.active.ready) {
|
||||
render2D(frame);
|
||||
@ -172,6 +186,14 @@ class App {
|
||||
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) {
|
||||
traitRenders.push(f);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ class Trait {
|
||||
var _remove: Array<Void->Void> = null;
|
||||
var _update: 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 _render2D: Array<kha.graphics2.Graphics->Void> = null;
|
||||
|
||||
@ -87,6 +88,23 @@ class Trait {
|
||||
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.
|
||||
**/
|
||||
|
@ -392,6 +392,8 @@ typedef TParticleData = {
|
||||
#end
|
||||
public var name: String;
|
||||
public var type: Int; // 0 - Emitter, Hair
|
||||
public var auto_start: Bool;
|
||||
public var is_unique: Bool;
|
||||
public var loop: Bool;
|
||||
public var count: Int;
|
||||
public var frame_start: FastFloat;
|
||||
|
@ -159,9 +159,17 @@ class Animation {
|
||||
if(markerEvents.get(sampler) != null){
|
||||
for (i in 0...anim.marker_frames.length) {
|
||||
if (frameIndex == anim.marker_frames[i]) {
|
||||
var marketAct = markerEvents.get(sampler);
|
||||
var ar = marketAct.get(anim.marker_names[i]);
|
||||
var markerAct = markerEvents.get(sampler);
|
||||
var ar = markerAct.get(anim.marker_names[i]);
|
||||
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;
|
||||
|
@ -172,6 +172,10 @@ class Object {
|
||||
for (f in t._init) App.removeInit(f);
|
||||
t._init = null;
|
||||
}
|
||||
if (t._fixedUpdate != null) {
|
||||
for (f in t._fixedUpdate) App.removeFixedUpdate(f);
|
||||
t._fixedUpdate = null;
|
||||
}
|
||||
if (t._update != null) {
|
||||
for (f in t._update) App.removeUpdate(f);
|
||||
t._update = null;
|
||||
|
@ -2,6 +2,7 @@ package iron.object;
|
||||
|
||||
#if lnx_particles
|
||||
|
||||
import kha.FastFloat;
|
||||
import kha.graphics4.Usage;
|
||||
import kha.arrays.Float32Array;
|
||||
import iron.data.Data;
|
||||
@ -16,39 +17,45 @@ import iron.math.Vec4;
|
||||
class ParticleSystem {
|
||||
public var data: ParticleData;
|
||||
public var speed = 1.0;
|
||||
var currentSpeed = 0.0;
|
||||
var particles: Array<Particle>;
|
||||
var ready: Bool;
|
||||
public var frameRate = 24;
|
||||
public var lifetime = 0.0;
|
||||
public var animtime = 0.0;
|
||||
public var time = 0.0;
|
||||
public var spawnRate = 0.0;
|
||||
var frameRate = 24;
|
||||
var lifetime = 0.0;
|
||||
var looptime = 0.0;
|
||||
var animtime = 0.0;
|
||||
var time = 0.0;
|
||||
var spawnRate = 0.0;
|
||||
var seed = 0;
|
||||
|
||||
public var r: TParticleData;
|
||||
public var gx: Float;
|
||||
public var gy: Float;
|
||||
public var gz: Float;
|
||||
public var alignx: Float;
|
||||
public var aligny: Float;
|
||||
public var alignz: Float;
|
||||
var r: TParticleData;
|
||||
var gx: Float;
|
||||
var gy: Float;
|
||||
var gz: Float;
|
||||
var alignx: Float;
|
||||
var aligny: Float;
|
||||
var alignz: Float;
|
||||
var dimx: Float;
|
||||
var dimy: Float;
|
||||
var tilesx: Int;
|
||||
var tilesy: Int;
|
||||
var tilesFramerate: Int;
|
||||
|
||||
public var count = 0;
|
||||
public var lap = 0;
|
||||
public var lapTime = 0.0;
|
||||
var count = 0;
|
||||
var lap = 0;
|
||||
var lapTime = 0.0;
|
||||
var m = Mat4.identity();
|
||||
|
||||
var ownerLoc = new Vec4();
|
||||
var ownerRot = new Quat();
|
||||
var ownerScl = new Vec4();
|
||||
|
||||
var random = 0.0;
|
||||
|
||||
public function new(sceneName: String, pref: TParticleReference) {
|
||||
seed = pref.seed;
|
||||
currentSpeed = speed;
|
||||
speed = 0;
|
||||
particles = [];
|
||||
ready = false;
|
||||
|
||||
@ -65,33 +72,61 @@ class ParticleSystem {
|
||||
gy = 0;
|
||||
gz = -9.81 * r.weight_gravity;
|
||||
}
|
||||
alignx = r.object_align_factor[0] / 2;
|
||||
aligny = r.object_align_factor[1] / 2;
|
||||
alignz = r.object_align_factor[2] / 2;
|
||||
alignx = r.object_align_factor[0];
|
||||
aligny = r.object_align_factor[1];
|
||||
alignz = r.object_align_factor[2];
|
||||
looptime = (r.frame_end - r.frame_start) / 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;
|
||||
|
||||
for (i in 0...r.count) {
|
||||
var particle = new Particle(i);
|
||||
particle.sr = 1 - Math.random() * r.size_random;
|
||||
particles.push(particle);
|
||||
particles.push(new Particle(i));
|
||||
}
|
||||
|
||||
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() {
|
||||
lifetime = 0;
|
||||
speed = 0;
|
||||
}
|
||||
|
||||
public function resume() {
|
||||
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) {
|
||||
if (!ready || object == null || speed == 0.0) return;
|
||||
if (iron.App.pauseUpdates) return;
|
||||
|
||||
var prevLap = lap;
|
||||
|
||||
// Copy owner world transform but discard scale
|
||||
owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl);
|
||||
@ -115,17 +150,21 @@ class ParticleSystem {
|
||||
}
|
||||
|
||||
// Animate
|
||||
time += Time.delta * speed;
|
||||
time += Time.renderDelta * speed; // realDelta to renderDelta
|
||||
lap = Std.int(time / animtime);
|
||||
lapTime = time - lap * animtime;
|
||||
count = Std.int(lapTime / spawnRate);
|
||||
|
||||
if (lap > prevLap && !r.loop) {
|
||||
end();
|
||||
}
|
||||
|
||||
updateGpu(object, owner);
|
||||
}
|
||||
|
||||
public function getData(): Mat4 {
|
||||
var hair = r.type == 1;
|
||||
m._00 = r.loop ? animtime : -animtime;
|
||||
m._00 = animtime;
|
||||
m._01 = hair ? 1 / particles.length : spawnRate;
|
||||
m._02 = hair ? 1 : lifetime;
|
||||
m._03 = particles.length;
|
||||
@ -133,9 +172,9 @@ class ParticleSystem {
|
||||
m._11 = hair ? 0 : aligny;
|
||||
m._12 = hair ? 0 : alignz;
|
||||
m._13 = hair ? 0 : r.factor_random;
|
||||
m._20 = hair ? 0 : gx * r.mass;
|
||||
m._21 = hair ? 0 : gy * r.mass;
|
||||
m._22 = hair ? 0 : gz * r.mass;
|
||||
m._20 = hair ? 0 : gx;
|
||||
m._21 = hair ? 0 : gy;
|
||||
m._22 = hair ? 0 : gz;
|
||||
m._23 = hair ? 0 : r.lifetime_random;
|
||||
m._30 = tilesx;
|
||||
m._31 = tilesy;
|
||||
@ -144,13 +183,25 @@ class ParticleSystem {
|
||||
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) {
|
||||
if (!object.data.geom.instanced) setupGeomGpu(object, owner);
|
||||
// GPU particles transform is attached to owner object
|
||||
}
|
||||
|
||||
public function setupGeomGpu(object: MeshObject, owner: MeshObject) {
|
||||
var instancedData = new Float32Array(particles.length * 6);
|
||||
function setupGeomGpu(object: MeshObject, owner: MeshObject) {
|
||||
var instancedData = new Float32Array(particles.length * 3);
|
||||
var i = 0;
|
||||
|
||||
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 + 1] * normFactor * scaleFactor.y); 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
|
||||
@ -196,10 +243,6 @@ class ParticleSystem {
|
||||
instancedData.set(i, pos.x * normFactor * scaleFactor.x); i++;
|
||||
instancedData.set(i, pos.y * normFactor * scaleFactor.y); 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
|
||||
@ -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.y); 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 {
|
||||
@ -255,10 +294,11 @@ class ParticleSystem {
|
||||
|
||||
class Particle {
|
||||
public var i: Int;
|
||||
public var px = 0.0;
|
||||
public var py = 0.0;
|
||||
public var pz = 0.0;
|
||||
public var sr = 1.0; // Size random
|
||||
|
||||
public var x = 0.0;
|
||||
public var y = 0.0;
|
||||
public var z = 0.0;
|
||||
|
||||
public var cameraDistance: Float;
|
||||
|
||||
public function new(i: Int) {
|
||||
|
@ -80,7 +80,7 @@ class Tilesheet {
|
||||
function update() {
|
||||
if (!ready || paused || action.start >= action.end) return;
|
||||
|
||||
time += Time.realDelta;
|
||||
time += Time.renderDelta;
|
||||
|
||||
var frameTime = 1 / raw.framerate;
|
||||
var framesToAdvance = 0;
|
||||
|
@ -1113,6 +1113,26 @@ class Uniforms {
|
||||
case "_texUnpack": {
|
||||
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) {
|
||||
|
@ -1,37 +1,58 @@
|
||||
package iron.system;
|
||||
|
||||
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;
|
||||
static function get_step(): Float {
|
||||
if (frequency == null) initFrequency();
|
||||
return 1 / frequency;
|
||||
}
|
||||
|
||||
public static var scale = 1.0;
|
||||
public static var delta(get, never): Float;
|
||||
static function get_delta(): Float {
|
||||
if (frequency == null) initFrequency();
|
||||
return (1 / frequency) * scale;
|
||||
|
||||
static var _fixedStep: Null<Float>;
|
||||
public static var fixedStep(get, never): Float;
|
||||
static function get_fixedStep(): Float {
|
||||
return _fixedStep;
|
||||
}
|
||||
|
||||
public static function initFixedStep(value: Float = 1 / 60) {
|
||||
_fixedStep = value;
|
||||
}
|
||||
|
||||
static var last = 0.0;
|
||||
public static var realDelta = 0.0;
|
||||
static var lastTime = 0.0;
|
||||
static var _delta = 0.0;
|
||||
public static var delta(get, never): Float;
|
||||
static function get_delta(): Float {
|
||||
return _delta;
|
||||
}
|
||||
|
||||
static var lastRenderTime = 0.0;
|
||||
static var _renderDelta = 0.0;
|
||||
public static var renderDelta(get, never): Float;
|
||||
static function get_renderDelta(): Float {
|
||||
return _renderDelta;
|
||||
}
|
||||
|
||||
public static inline function time(): Float {
|
||||
return kha.Scheduler.time();
|
||||
}
|
||||
|
||||
public static inline function realTime(): Float {
|
||||
return kha.Scheduler.realTime();
|
||||
}
|
||||
|
||||
static var frequency: Null<Int> = null;
|
||||
|
||||
static function initFrequency() {
|
||||
frequency = kha.Display.primary != null ? kha.Display.primary.frequency : 60;
|
||||
public static function update() {
|
||||
_delta = realTime() - lastTime;
|
||||
lastTime = realTime();
|
||||
}
|
||||
|
||||
public static function update() {
|
||||
realDelta = realTime() - last;
|
||||
last = realTime();
|
||||
public static function render() {
|
||||
_renderDelta = realTime() - lastRenderTime;
|
||||
lastRenderTime = realTime();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user