package com.lyeeedar.Roguelike3D.Graphics.Models.RiggedModels;
import java.io.Serializable;
import java.util.ArrayList;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import com.badlogic.gdx.utils.Pools;
import com.lyeeedar.Graphics.ParticleEffects.ParticleEffect;
import com.lyeeedar.Graphics.ParticleEffects.ParticleEmitter;
import com.lyeeedar.Roguelike3D.Game.GameData;
import com.lyeeedar.Roguelike3D.Game.Actor.GameActor;
import com.lyeeedar.Roguelike3D.Game.LevelObjects.LevelObject;
import com.lyeeedar.Roguelike3D.Graphics.Lights.LightManager;
import com.lyeeedar.Roguelike3D.Graphics.Renderers.Renderer;
public class RiggedModelNode implements Serializable
{
public static final Matrix4 tmpMat = new Matrix4();
public static final Vector3 tmpVec = new Vector3();
private static final long serialVersionUID = -3949208107618544807L;
public final RiggedSubMesh[] submeshes;
public final int[] submeshMaterials;
public transient Matrix4[] meshMatrixes;
public RiggedModelNode[] childNodes;
public transient RiggedModelNode parent;
public RiggedModelBehaviour behaviour;
public ParticleEffect particleEffect;
public final String ID;
public float radius;
public float renderRadius;
public final float rigidity;
public final boolean collidable;
public final Matrix4 position;
public final Matrix4 rotation;
public final Matrix4 offsetPosition = new Matrix4();
public final Matrix4 offsetRotation = new Matrix4();
public transient Matrix4 composedMatrix;
public boolean collideMode = false;
public RiggedModelNode(String ID, RiggedSubMesh[] submeshes, int[] submeshMaterials, Matrix4 position, Matrix4 rotation, int rigidity, boolean collidable)
{
this.ID = ID;
if (submeshes.length != submeshMaterials.length)
{
throw new RuntimeException("Invalid number of materials to submeshes in RiggedModelNode!");
}
this.submeshes = submeshes;
this.submeshMaterials = submeshMaterials;
this.position = position;
this.rotation = rotation;
this.rigidity = rigidity;
this.collidable = collidable;
}
public void equip(GameActor holder, int side)
{
if (behaviour != null) behaviour.equip(holder, side);
for (RiggedModelNode rmn : childNodes) rmn.equip(holder, side);
}
public void setParticleEffect(ParticleEffect effect)
{
if (particleEffect != null) {
particleEffect.dispose();
particleEffect.delete();
}
this.particleEffect = effect;
}
public void setBehaviour(RiggedModelBehaviour behaviour)
{
this.behaviour = behaviour;
}
public void setParent(RiggedModelNode parent)
{
this.parent = parent;
}
public void setChilden(RiggedModelNode... children)
{
this.childNodes = children;
}
public void composeMatrixes(Matrix4 composed)
{
composedMatrix.set(composed).mul(position).mul(rotation).mul(offsetPosition).mul(offsetRotation);
for (int i = 0; i < submeshes.length; i++)
{
meshMatrixes[i].set(composed).scale(submeshes[i].scale, submeshes[i].scale, submeshes[i].scale);
}
for (RiggedModelNode rgn : childNodes)
{
rgn.composeMatrixes(composedMatrix);
}
if (particleEffect != null) {
Vector3 tmp = Pools.obtain(Vector3.class);
particleEffect.setPosition(tmp.set(0, 0, 0).mul(composedMatrix));
Pools.free(tmp);
}
}
public void render(RiggedModel model, Renderer renderer, ArrayList<ParticleEmitter> emitters, Camera cam)
{
if (particleEffect != null) {
particleEffect.getVisibleEmitters(emitters, cam);
}
for (int i = 0; i < submeshes.length; i++)
{
renderer.draw(submeshes[i], meshMatrixes[i], model.materials[submeshMaterials[i]], renderRadius);
}
for (RiggedModelNode rgn : childNodes)
{
rgn.render(model, renderer, emitters, cam);
}
}
public GameActor checkCollision(GameActor holder)
{
tmpVec.set(0, 0, 0).mul(composedMatrix);
if (collidable && collideMode) {
GameActor ga = GameData.level.collideSphereActorsAll(tmpVec.x, tmpVec.y, tmpVec.z, radius, holder.UID);
LevelObject lo = GameData.level.collideSphereLevelObjectsAll(tmpVec.x, tmpVec.y, tmpVec.z, radius);
if (lo != null) ga = holder;
if (GameData.level.collideSphereAll(tmpVec.x, tmpVec.y, tmpVec.z, radius, holder.UID)) ga = holder;
if (ga != null) {
rotation.rotate(0, 1, 0, (100-rigidity)/50);
return ga;
}
}
for (RiggedModelNode rmn : childNodes)
{
GameActor ga = rmn.checkCollision(holder);
if (ga != null) return ga;
}
return null;
}
public void update(float delta, Camera cam)
{
if (particleEffect != null)
{
particleEffect.update(delta, cam);
}
if (behaviour != null) behaviour.update(delta);
for (RiggedModelNode rmn : childNodes)
{
rmn.update(delta, cam);
}
}
public void held()
{
if (behaviour != null) behaviour.held();
for (RiggedModelNode rmn : childNodes)
{
rmn.held();
}
}
public void released()
{
if (behaviour != null) behaviour.released();
for (RiggedModelNode rmn : childNodes)
{
rmn.released();
}
}
public void cancel()
{
if (behaviour != null) behaviour.cancel();
for (RiggedModelNode rmn : childNodes)
{
rmn.cancel();
}
}
public void setCollideMode(boolean mode, boolean propogateUp)
{
if (propogateUp)
{
if (parent != null)
{
parent.setCollideMode(mode, true);
}
else
{
for (RiggedModelNode rmn : childNodes)
{
rmn.setCollideMode(mode, false);
}
}
}
else
{
collideMode = mode;
if (behaviour != null) behaviour.proccessCollideMode(mode);
for (RiggedModelNode rmn : childNodes)
{
rmn.setCollideMode(mode, false);
}
}
}
public void create()
{
composedMatrix = Pools.obtain(Matrix4.class).idt();
meshMatrixes = new Matrix4[submeshes.length];
for (int i = 0; i < meshMatrixes.length; i++)
{
meshMatrixes[i] = Pools.obtain(Matrix4.class).idt();
}
for (RiggedSubMesh rsm : submeshes)
{
rsm.create();
}
BoundingBox box = new BoundingBox();
for (RiggedSubMesh sm : submeshes)
{
box.ext(sm.getBoundingBox());
}
float longest = (box.getDimensions().x > box.getDimensions().z) ? box.getDimensions().x : box.getDimensions().z;
longest = (box.getDimensions().y > longest) ? box.getDimensions().y : longest;
this.radius = (longest / 2.0f);
this.renderRadius = (radius > 1) ? radius : 1;
for (RiggedModelNode rmn : childNodes)
{
rmn.create();
}
if (particleEffect != null) {
particleEffect.create();
}
}
public void fixReferences()
{
for (RiggedModelNode rmn : childNodes)
{
rmn.setParent(this);
rmn.fixReferences();
}
}
public void dispose()
{
Pools.free(composedMatrix);
composedMatrix = null;
for (int i = 0; i < meshMatrixes.length; i++)
{
Pools.free(meshMatrixes[i]);
meshMatrixes[i] = null;
}
for (RiggedSubMesh rsm : submeshes)
{
rsm.dispose();
}
for (RiggedModelNode rmn : childNodes)
{
rmn.dispose();
}
if (particleEffect!= null) particleEffect.dispose();
}
public void getLight(LightManager lightManager)
{
if (particleEffect != null)
{
particleEffect.getLight(lightManager);
}
for (RiggedModelNode rmn : childNodes)
{
rmn.getLight(lightManager);
}
}
public void bakeLight(LightManager lights, boolean bakeStatics)
{
for (int i = 0; i < submeshes.length; i++)
{
submeshes[i].bakeLight(lights, bakeStatics, meshMatrixes[i]);
}
for (RiggedModelNode rmn : childNodes)
{
rmn.bakeLight(lights, bakeStatics);
}
}
public RiggedModelNode getNode(String ID)
{
if (this.ID.equalsIgnoreCase(ID))
{
return this;
}
for (RiggedModelNode rmn : childNodes)
{
RiggedModelNode returned = rmn.getNode(ID);
if (returned != null) return returned;
}
return null;
}
}