forked from LeenkxTeam/LNXSDK
		
	merge upstream
This commit is contained in:
		| @ -2,9 +2,11 @@ package leenkx.logicnode; | ||||
|  | ||||
| import iron.object.Object; | ||||
|  | ||||
| #if lnx_physics | ||||
| #if lnx_bullet | ||||
| import leenkx.trait.physics.PhysicsConstraint; | ||||
| import leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintType; | ||||
| #elseif lnx_oimo | ||||
| // TODO | ||||
| #end | ||||
|  | ||||
| class AddPhysicsConstraintNode extends LogicNode { | ||||
| @ -25,7 +27,7 @@ class AddPhysicsConstraintNode extends LogicNode { | ||||
|  | ||||
| 		if (pivotObject == null || rb1 == null || rb2 == null) return; | ||||
|  | ||||
| #if lnx_physics | ||||
| #if lnx_bullet | ||||
|  | ||||
| 		var disableCollisions: Bool = inputs[4].get(); | ||||
| 		var breakable: Bool = inputs[5].get(); | ||||
| @ -108,6 +110,8 @@ class AddPhysicsConstraintNode extends LogicNode { | ||||
| 			} | ||||
| 			pivotObject.addTrait(con); | ||||
| 		} | ||||
| #elseif lnx_oimo | ||||
| // TODO | ||||
| #end | ||||
| 		runOutput(0); | ||||
| 	} | ||||
|  | ||||
| @ -4,7 +4,7 @@ import iron.object.Object; | ||||
|  | ||||
| #if lnx_physics | ||||
| import leenkx.trait.physics.RigidBody; | ||||
| import leenkx.trait.physics.bullet.RigidBody.Shape; | ||||
| import leenkx.trait.physics.RigidBody.Shape; | ||||
| #end | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										26
									
								
								leenkx/Sources/leenkx/logicnode/ArrayIndexListNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								leenkx/Sources/leenkx/logicnode/ArrayIndexListNode.hx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| package leenkx.logicnode; | ||||
|  | ||||
| class ArrayIndexListNode extends LogicNode { | ||||
|  | ||||
| 	public function new(tree: LogicTree) { | ||||
| 		super(tree); | ||||
| 	} | ||||
|  | ||||
| 	override function get(from: Int): Dynamic { | ||||
| 		var array: Array<Dynamic> = inputs[0].get(); | ||||
| 		array = array.map(item -> Std.string(item)); | ||||
| 		var value: Dynamic = inputs[1].get(); | ||||
| 		var from: Int = 0; | ||||
|  | ||||
| 		var arrayList: Array<Int> = []; | ||||
|  | ||||
| 		var index: Int = array.indexOf(Std.string(value), from); | ||||
|  | ||||
| 		while(index != -1){ | ||||
| 			arrayList.push(index); | ||||
| 			index = array.indexOf(Std.string(value), index+1); | ||||
| 		} | ||||
|  | ||||
| 		return arrayList; | ||||
| 	} | ||||
| } | ||||
| @ -1,7 +1,7 @@ | ||||
| package leenkx.logicnode; | ||||
|  | ||||
| #if lnx_physics | ||||
| import leenkx.trait.physics.bullet.PhysicsWorld; | ||||
| import leenkx.trait.physics.PhysicsWorld; | ||||
| #end | ||||
| import leenkx.trait.navigation.Navigation; | ||||
| import iron.object.Object; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| package leenkx.logicnode; | ||||
|  | ||||
| #if lnx_physics | ||||
| import leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintAxis; | ||||
| import leenkx.trait.physics.PhysicsConstraint.ConstraintAxis; | ||||
| #end | ||||
|  | ||||
| class PhysicsConstraintNode extends LogicNode { | ||||
|  | ||||
| @ -10,6 +10,10 @@ class KinematicCharacterController extends iron.Trait { public function new() { | ||||
|  | ||||
| 	typedef KinematicCharacterController = leenkx.trait.physics.bullet.KinematicCharacterController; | ||||
|  | ||||
| 	#else | ||||
|  | ||||
| 	typedef KinematicCharacterController = leenkx.trait.physics.oimo.KinematicCharacterController; | ||||
|  | ||||
| 	#end | ||||
|  | ||||
| #end | ||||
|  | ||||
| @ -3,17 +3,16 @@ package leenkx.trait.physics; | ||||
| #if (!lnx_physics) | ||||
|  | ||||
| class PhysicsConstraint extends iron.Trait { public function new() { super(); } } | ||||
| @:enum abstract ConstraintAxis(Int) from Int to Int { } | ||||
|  | ||||
| #else | ||||
|  | ||||
| 	#if lnx_bullet | ||||
|  | ||||
| 	typedef PhysicsConstraint = leenkx.trait.physics.bullet.PhysicsConstraint; | ||||
|  | ||||
| 	typedef ConstraintAxis = leenkx.trait.physics.bullet.PhysicsConstraint.ConstraintAxis; | ||||
| 	#else | ||||
|  | ||||
| 	typedef PhysicsConstraint = leenkx.trait.physics.oimo.PhysicsConstraint; | ||||
|  | ||||
| 	typedef ConstraintAxis = leenkx.trait.physics.oimo.PhysicsConstraint.ConstraintAxis; | ||||
| 	#end | ||||
|  | ||||
| #end | ||||
|  | ||||
| @ -2,6 +2,7 @@ package leenkx.trait.physics; | ||||
|  | ||||
| #if (!lnx_physics) | ||||
|  | ||||
| class Hit { } | ||||
| class PhysicsWorld extends iron.Trait { public function new() { super(); } } | ||||
|  | ||||
| #else | ||||
| @ -9,11 +10,11 @@ class PhysicsWorld extends iron.Trait { public function new() { super(); } } | ||||
| 	#if lnx_bullet | ||||
|  | ||||
| 	typedef PhysicsWorld = leenkx.trait.physics.bullet.PhysicsWorld; | ||||
|  | ||||
| 	typedef Hit = leenkx.trait.physics.bullet.PhysicsWorld.Hit; | ||||
| 	#else | ||||
|  | ||||
| 	typedef PhysicsWorld = leenkx.trait.physics.oimo.PhysicsWorld; | ||||
|  | ||||
| 	typedef Hit = leenkx.trait.physics.oimo.PhysicsWorld.Hit; | ||||
| 	#end | ||||
|  | ||||
| #end | ||||
|  | ||||
| @ -3,17 +3,20 @@ package leenkx.trait.physics; | ||||
| #if (!lnx_physics) | ||||
|  | ||||
| class RigidBody extends iron.Trait { public function new() { super(); } } | ||||
| @:enum abstract Shape(Int) from Int to Int { } | ||||
|  | ||||
| #else | ||||
|  | ||||
| 	#if lnx_bullet | ||||
|  | ||||
| 	typedef RigidBody = leenkx.trait.physics.bullet.RigidBody; | ||||
|  | ||||
| 	typedef Shape = leenkx.trait.physics.bullet.RigidBody.Shape; | ||||
| 	 | ||||
| 	#else | ||||
|  | ||||
| 	typedef RigidBody = leenkx.trait.physics.oimo.RigidBody; | ||||
|  | ||||
| 	typedef Shape = leenkx.trait.physics.oimo.RigidBody.Shape; | ||||
| 	 | ||||
| 	#end | ||||
|  | ||||
| #end | ||||
|  | ||||
| @ -1,5 +1,8 @@ | ||||
| package leenkx.trait.physics.bullet; | ||||
|  | ||||
| #if lnx_bullet | ||||
| import leenkx.trait.physics.bullet.PhysicsWorld.DebugDrawMode; | ||||
|  | ||||
| import bullet.Bt.Vector3; | ||||
|  | ||||
| import kha.FastFloat; | ||||
| @ -18,15 +21,21 @@ class DebugDrawHelper { | ||||
| 	static inline var contactPointNormalColor = 0xffffffff; | ||||
| 	static inline var contactPointDrawLifetime = true; | ||||
|  | ||||
| 	final rayCastColor: Vec4 = new Vec4(0.0, 1.0, 0.0); | ||||
| 	final rayCastHitColor: Vec4 = new Vec4(1.0, 0.0, 0.0); | ||||
| 	final rayCastHitPointColor: Vec4 = new Vec4(1.0, 1.0, 0.0); | ||||
|  | ||||
| 	final physicsWorld: PhysicsWorld; | ||||
| 	final lines: Array<LineData> = []; | ||||
| 	final texts: Array<TextData> = []; | ||||
| 	var font: kha.Font = null; | ||||
|  | ||||
| 	var debugMode: PhysicsWorld.DebugDrawMode = NoDebug; | ||||
| 	var rayCasts:Array<TRayCastData> = []; | ||||
| 	var debugDrawMode: DebugDrawMode = NoDebug; | ||||
|  | ||||
| 	public function new(physicsWorld: PhysicsWorld) { | ||||
| 	public function new(physicsWorld: PhysicsWorld, debugDrawMode: DebugDrawMode) { | ||||
| 		this.physicsWorld = physicsWorld; | ||||
| 		this.debugDrawMode = debugDrawMode; | ||||
|  | ||||
| 		#if lnx_ui | ||||
| 		iron.data.Data.getFont(Canvas.defaultFontName, function(defaultFont: kha.Font) { | ||||
| @ -35,6 +44,11 @@ class DebugDrawHelper { | ||||
| 		#end | ||||
|  | ||||
| 		iron.App.notifyOnRender2D(onRender); | ||||
| 		if (debugDrawMode & DrawRayCast != 0) { | ||||
| 			iron.App.notifyOnUpdate(function () { | ||||
| 				rayCasts.resize(0); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public function drawLine(from: bullet.Bt.Vector3, to: bullet.Bt.Vector3, color: bullet.Bt.Vector3) { | ||||
| @ -63,25 +77,6 @@ class DebugDrawHelper { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Draws raycast in its own function because  | ||||
| 	// something is conflicting with the btVector3 and JS pointer wrapping | ||||
| 	public function drawRayCast(fx:FastFloat, fy:FastFloat, fz:FastFloat, tx:FastFloat, ty:FastFloat, tz:FastFloat, r:FastFloat, g:FastFloat, b:FastFloat) { | ||||
| 		final fromScreenSpace = worldToScreenFast(new Vec4(fx, fy, fz, 1.0)); | ||||
| 		final toScreenSpace = worldToScreenFast(new Vec4(tx, ty, tz, 1.0)); | ||||
|  | ||||
| 		// TO DO: May still go off screen sides. | ||||
| 		if (fromScreenSpace.w == 1 || toScreenSpace.w == 1) { | ||||
| 			final color = kha.Color.fromFloats(r, g, b, 1.0); | ||||
| 			lines.push({ | ||||
| 				fromX: fromScreenSpace.x, | ||||
| 				fromY: fromScreenSpace.y, | ||||
| 				toX: toScreenSpace.x, | ||||
| 				toY: toScreenSpace.y, | ||||
| 				color: color | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public function drawContactPoint(pointOnB: Vector3, normalOnB: Vector3, distance: kha.FastFloat, lifeTime: Int, color: Vector3) { | ||||
| 		#if js | ||||
| 			pointOnB = js.Syntax.code("Ammo.wrapPointer({0}, Ammo.btVector3)", pointOnB); | ||||
| @ -126,7 +121,62 @@ class DebugDrawHelper { | ||||
| 					x: contactPointScreenSpace.x, | ||||
| 					y: contactPointScreenSpace.y, | ||||
| 					color: color, | ||||
| 					text: Std.string(lifeTime), | ||||
| 					text: Std.string(lifeTime), // lifeTime: number of frames the contact point existed | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public function rayCast(rayCastData:TRayCastData) { | ||||
| 		rayCasts.push(rayCastData); | ||||
| 	} | ||||
|  | ||||
| 	function drawRayCast(f: Vec4, t: Vec4, hit: Bool) { | ||||
| 		final from = worldToScreenFast(f.clone()); | ||||
| 		final to = worldToScreenFast(t.clone()); | ||||
| 		var c: kha.Color; | ||||
|  | ||||
| 		if (from.w == 1 && to.w == 1) { | ||||
| 			if (hit) c = kha.Color.fromFloats(rayCastHitColor.x, rayCastHitColor.y, rayCastHitColor.z); | ||||
| 			else c = kha.Color.fromFloats(rayCastColor.x, rayCastColor.y, rayCastColor.z); | ||||
|  | ||||
| 			lines.push({ | ||||
| 				fromX: from.x, | ||||
| 				fromY: from.y, | ||||
| 				toX: to.x, | ||||
| 				toY: to.y, | ||||
| 				color: c | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	function drawHitPoint(hp: Vec4) { | ||||
| 		final hitPoint = worldToScreenFast(hp.clone()); | ||||
| 		final c = kha.Color.fromFloats(rayCastHitPointColor.x, rayCastHitPointColor.y, rayCastHitPointColor.z); | ||||
|  | ||||
| 		if (hitPoint.w == 1) { | ||||
| 			lines.push({ | ||||
| 				fromX: hitPoint.x - contactPointSizePx, | ||||
| 				fromY: hitPoint.y - contactPointSizePx, | ||||
| 				toX: hitPoint.x + contactPointSizePx, | ||||
| 				toY: hitPoint.y + contactPointSizePx, | ||||
| 				color: c | ||||
| 			}); | ||||
|  | ||||
| 			lines.push({ | ||||
| 				fromX: hitPoint.x - contactPointSizePx, | ||||
| 				fromY: hitPoint.y + contactPointSizePx, | ||||
| 				toX: hitPoint.x + contactPointSizePx, | ||||
| 				toY: hitPoint.y - contactPointSizePx, | ||||
| 				color: c | ||||
| 			}); | ||||
|  | ||||
| 			if (font != null) { | ||||
| 				texts.push({ | ||||
| 					x: hitPoint.x, | ||||
| 					y: hitPoint.y, | ||||
| 					color: c, | ||||
| 					text: 'RAYCAST HIT' | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| @ -155,13 +205,13 @@ class DebugDrawHelper { | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	public function setDebugMode(debugMode: PhysicsWorld.DebugDrawMode) { | ||||
| 		this.debugMode = debugMode; | ||||
| 	public function setDebugMode(debugDrawMode: DebugDrawMode) { | ||||
| 		this.debugDrawMode = debugDrawMode; | ||||
| 	} | ||||
|  | ||||
| 	public function getDebugMode(): PhysicsWorld.DebugDrawMode { | ||||
| 	public function getDebugMode(): DebugDrawMode { | ||||
| 		#if js | ||||
| 			return debugMode; | ||||
| 			return debugDrawMode; | ||||
| 		#elseif hl | ||||
| 			return physicsWorld.getDebugDrawMode(); | ||||
| 		#else | ||||
| @ -170,7 +220,7 @@ class DebugDrawHelper { | ||||
| 	} | ||||
|  | ||||
| 	function onRender(g: kha.graphics2.Graphics) { | ||||
| 		if (getDebugMode() == NoDebug && !physicsWorld.drawRaycasts) { | ||||
| 		if (getDebugMode() == NoDebug) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| @ -179,7 +229,9 @@ class DebugDrawHelper { | ||||
| 		// will cause Bullet to call the btIDebugDraw callbacks), but this way | ||||
| 		// we can ensure that--within a frame--the function will not be called | ||||
| 		// before some user-specific physics update, which would result in a | ||||
| 		// one-frame drawing delay... | ||||
| 		// one-frame drawing delay... Ideally we would ensure that debugDrawWorld() | ||||
| 		// is called when all other (late) update callbacks are already executed... | ||||
| 		 | ||||
| 		physicsWorld.world.debugDrawWorld(); | ||||
|  | ||||
| 		g.opacity = 1.0; | ||||
| @ -199,6 +251,17 @@ class DebugDrawHelper { | ||||
| 			} | ||||
| 			texts.resize(0); | ||||
| 		} | ||||
| 		 | ||||
| 		if (debugDrawMode & DrawRayCast != 0) { | ||||
| 			for (rayCastData in rayCasts) { | ||||
| 				if (rayCastData.hasHit) { | ||||
| 					drawRayCast(rayCastData.from, rayCastData.hitPoint, true); | ||||
| 					drawHitPoint(rayCastData.hitPoint); | ||||
| 				} else { | ||||
| 					drawRayCast(rayCastData.from, rayCastData.to, false); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @ -241,3 +304,14 @@ class TextData { | ||||
| 	public var color: kha.Color; | ||||
| 	public var text: String; | ||||
| } | ||||
|  | ||||
| @:structInit | ||||
| typedef TRayCastData = { | ||||
| 	var from: Vec4; | ||||
| 	var to: Vec4; | ||||
| 	var hasHit: Bool; | ||||
| 	@:optional var hitPoint: Vec4; | ||||
| 	@:optional var hitNormal: Vec4; | ||||
| } | ||||
|  | ||||
| #end | ||||
| @ -71,7 +71,6 @@ class PhysicsWorld extends Trait { | ||||
| 	public var convexHitPointWorld = new Vec4(); | ||||
| 	public var convexHitNormalWorld = new Vec4(); | ||||
| 	var pairCache: Bool = false; | ||||
| 	public var drawRaycasts: Bool = false; | ||||
|  | ||||
| 	static var nullvec = true; | ||||
| 	static var vec1: bullet.Bt.Vector3 = null; | ||||
| @ -102,7 +101,7 @@ class PhysicsWorld extends Trait { | ||||
|  | ||||
|  | ||||
|  | ||||
| 	public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug, drawRaycasts: Bool = false) { | ||||
| 	public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug) { | ||||
| 		super(); | ||||
|  | ||||
| 		if (nullvec) { | ||||
| @ -121,7 +120,6 @@ class PhysicsWorld extends Trait { | ||||
| 		this.timeScale = timeScale; | ||||
| 		this.maxSteps = maxSteps; | ||||
| 		this.solverIterations = solverIterations; | ||||
| 		this.drawRaycasts = drawRaycasts; | ||||
|  | ||||
| 		// First scene | ||||
| 		if (active == null) { | ||||
| @ -408,14 +406,6 @@ class PhysicsWorld extends Trait { | ||||
| 		var worldDyn: bullet.Bt.DynamicsWorld = world; | ||||
| 		var worldCol: bullet.Bt.CollisionWorld = worldDyn; | ||||
|  | ||||
| 		if (this.drawRaycasts && this.debugDrawHelper != null) { | ||||
| 			this.debugDrawHelper.drawRayCast( | ||||
| 				rayFrom.x(), rayFrom.y(), rayFrom.z(),  | ||||
| 				rayTo.x(),   rayTo.y(),   rayTo.z(),    | ||||
| 				0.73, 0.341, 1.0  | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
| 		worldCol.rayTest(rayFrom, rayTo, rayCallback); | ||||
| 		var rb: RigidBody = null; | ||||
| 		var hitInfo: Hit = null; | ||||
| @ -441,6 +431,16 @@ class PhysicsWorld extends Trait { | ||||
| 			#end | ||||
| 		} | ||||
|  | ||||
| 		if (getDebugDrawMode() & DrawRayCast != 0) { | ||||
| 			debugDrawHelper.rayCast({ | ||||
| 				from: from, | ||||
| 				to: to, | ||||
| 				hasHit: rc.hasHit(), | ||||
| 				hitPoint: hitPointWorld, | ||||
| 				hitNormal: hitNormalWorld | ||||
| 			}); | ||||
| 		} | ||||
|  | ||||
| 		#if js | ||||
| 		bullet.Bt.Ammo.destroy(rayCallback); | ||||
| 		#else | ||||
| @ -519,22 +519,14 @@ class PhysicsWorld extends Trait { | ||||
|  | ||||
| 	public function setDebugDrawMode(debugDrawMode: DebugDrawMode) { | ||||
| 		if (debugDrawHelper == null) { | ||||
| 			// Initialize if helper is null AND (standard debug mode is requested OR our custom raycast drawing is requested) | ||||
| 			if (debugDrawMode != NoDebug || this.drawRaycasts) { | ||||
| 				initDebugDrawing(); | ||||
| 			} | ||||
| 			else { | ||||
| 				// Helper is null and no debug drawing needed, so exit | ||||
| 			if (debugDrawMode == NoDebug) { | ||||
| 				return; | ||||
| 			} | ||||
| 			initDebugDrawing(debugDrawMode); | ||||
| 		} | ||||
|  | ||||
| 		// If we reached here, the helper is initialized (or was already) | ||||
| 		// Now set the standard Bullet debug mode on the actual drawer | ||||
| 		#if js | ||||
| 			// Ensure drawer exists before setting mode (might have just been initialized) | ||||
| 			var drawer = world.getDebugDrawer(); | ||||
| 			if (drawer != null) drawer.setDebugMode(debugDrawMode); | ||||
| 			world.getDebugDrawer().setDebugMode(debugDrawMode); | ||||
| 		#elseif hl | ||||
| 			hlDebugDrawer_setDebugMode(debugDrawMode); | ||||
| 		#end | ||||
| @ -554,8 +546,8 @@ class PhysicsWorld extends Trait { | ||||
| 		#end | ||||
| 	} | ||||
|  | ||||
| 	function initDebugDrawing() { | ||||
| 		debugDrawHelper = new DebugDrawHelper(this); | ||||
| 	function initDebugDrawing(debugDrawMode: DebugDrawMode) { | ||||
| 		debugDrawHelper = new DebugDrawHelper(this, debugDrawMode); | ||||
|  | ||||
| 		#if js | ||||
| 			final drawer = new bullet.Bt.DebugDrawer(); | ||||
| @ -691,6 +683,8 @@ enum abstract DebugDrawMode(Int) from Int to Int { | ||||
| 	 **/ | ||||
| 	var DrawFrames = 1 << 15; | ||||
|  | ||||
| 	var DrawRayCast = 1 << 16; | ||||
|  | ||||
| 	@:op(~A) public inline function bitwiseNegate(): DebugDrawMode { | ||||
| 		return ~this; | ||||
| 	} | ||||
|  | ||||
		Reference in New Issue
	
	Block a user