/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package automenta.spacenet.space;
import automenta.spacenet.space.surface.ColorSurface;
import automenta.spacenet.var.physical.Color;
import com.ardor3d.math.Vector3;
import com.ardor3d.math.type.ReadOnlyMatrix3;
import com.ardor3d.renderer.Renderer;
import com.ardor3d.scenegraph.Node;
import com.ardor3d.scenegraph.Spatial;
import com.ardor3d.scenegraph.hint.CullHint;
import com.ardor3d.util.scenegraph.RenderDelegate;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/** wraps Ardor3D node with some convenient abilities and assumptions */
public class Space extends Node {
private Map<Class<? extends SpaceState>, SpaceState> properties = new HashMap();
private Spacetime spacetime;
@Override
public String toString() {
if (getName() == null) {
return "? " + getClass().getName();
}
return super.toString();
}
public <S extends Spatial> S add(S s) {
if (attachChild(s) == -1) {
return null;
}
return s;
}
public <S extends Spatial> S remove(S s) {
if (detachChild(s) == -1) {
return null;
}
return s;
}
public Spacetime getSpacetime() {
if (spacetime == null) {
updateSpacetime();
}
return spacetime;
}
protected void updateSpacetime() {
spacetime = null;
if (this instanceof Spacetime) {
spacetime = ((Spacetime) this);
return;
} else {
Node n = getParent();
while (n != null) {
if (n instanceof Spacetime) {
spacetime = ((Spacetime) n);
return;
}
n = n.getParent();
}
}
}
public <R extends Repeat> R add(R r) {
addController(r);
return r;
}
public <R extends Repeat> R remove(R r) {
if (!removeController(r)) {
return null;
}
return r;
}
public <S extends SpaceState> S add(S spaceState) {
SpaceState removed = properties.put(spaceState.getClass(), spaceState);
if (removed != null) {
removed.unapply(this);
}
spaceState.apply(this);
return spaceState;
}
public <S extends SpaceState> S remove(S cs) {
if (properties.remove(cs.getClass()) != null) {
cs.unapply(this);
}
return cs;
}
public ColorSurface color(Color c) {
ColorSurface cs = new ColorSurface(c);
add(cs);
return cs;
}
public ColorSurface color(float r, float g, float b) {
return add(new ColorSurface(r, g, b));
}
@Override
protected void setParent(Node parent) {
Spatial previousParent = getParent();
if (parent == null) {
beforeDetached(previousParent);
}
super.setParent(parent);
if (parent != null) {
updateSpacetime();
afterAttached(parent);
}
}
protected void afterAttached(Spatial parent) {
}
protected void beforeDetached(Spatial previousParent) {
}
public void removeAll(Collection<? extends Spatial> c) {
for (Spatial s : c) {
remove(s);
}
}
public void removeAll() {
detachAllChildren();
}
public static void applyAspectXY(Vector3 worldScale, Vector3 worldTranslation, ReadOnlyMatrix3 worldRotation, double a, double alX, double alY, Vector3 vA) {
if (a != 0) {
// float wx = worldScale.getX();
// float wy = worldScale.getY();
double sx = worldScale.getX();
double sy = worldScale.getY();
double sz = worldScale.getZ();
//original values
double ox = sx;
double oy = sy;
double oz = sz;
double px = 0, py = 0, pz = 0;
double ex = 0, ey = 0, ez = 0;
//constraint sx, sy according to aspect
double n = sy / sx;
if (a > n) {
//visually taller, so shrink width & preserve height
ex = 1.0 - (n / a);
sx = (n / a) * sx;
} else {
//visually wider, so shrink height & preserve width
ey = 1.0 - (a / n);
sy = (a / n) * sy;
}
px = alX * (ox - sx) / 2.0;
py = alY * (oy - sy) / 2.0;
//rotate the delta vector by the absolute orientation
vA.set((float) px, (float) py, (float) pz);
worldRotation.applyPost(vA, vA);
px = vA.getX();
py = vA.getY();
pz = vA.getZ();
//"correct" the scale
worldScale.set((float) sx, (float) sy, (float) sz);
worldTranslation.addLocal((float) px, (float) py, (float) pz);
// System.out.println(" scale=" + worldScale);
// System.out.println(" translat=" + worldTranslation);
}
}
public synchronized void visible(boolean b) {
getSceneHints().setCullHint(b ? CullHint.Inherit : CullHint.Always);
}
// private Stack<RenderState> localStack = new Stack<RenderState>();
//
// private Map<RenderState.StateType, Stack<RenderState>> localStacks = Maps.newHashMap();
//
// @Override public void propagateStatesFromRoot(final Map<RenderState.StateType, Stack<RenderState>> stateStack) {
// // traverse to root to allow downward state propagation
// if (_parent != null) {
// _parent.propagateStatesFromRoot(stateStack);
// }
//
// // push states onto current render state stack
// Stack<RenderState> stack;
// for (final RenderState state : _renderStateList.values()) {
// stack = stateStack.get(state.getType());
// if (stack == null) {
// stack = new Stack<RenderState>();
// stateStack.put(state.getType(), stack);
// }
// stack.push(state);
// }
// }
//
// @Override protected void updateWorldRenderStates(final boolean recurse, final Map<RenderState.StateType, Stack<RenderState>> stateStacks) {
// Map<RenderState.StateType, Stack<RenderState>> stacks = stateStacks;
//
// final boolean initiator = (stacks == null);
//
// // first we need to get all the states from parent to us.
// if (initiator) {
// // grab all states from root to here.
//
// localStacks.clear();
// stacks = localStacks;
//
// propagateStatesFromRoot(stacks);
// } else {
// Stack<RenderState> stack;
// for (final RenderState state : _renderStateList.values()) {
// stack = stacks.get(state.getType());
// if (stack == null) {
// //System.out.println("new stack");
// localStack.clear();
// stack = localStack;
// stacks.put(state.getType(), stack);
// }
// stack.push(state);
// }
// }
//
// applyWorldRenderStates(recurse, stacks);
//
// // restore previous if we are not the initiator
// if (!initiator) {
// for (final RenderState state : _renderStateList.values()) {
// stacks.get(state.getType()).pop();
// }
// }
// }
private boolean drawnReverse = false;
public void setDrawnReverse(boolean drawnReverse) {
this.drawnReverse = drawnReverse;
}
public boolean isDrawnReverse() {
return drawnReverse;
}
@Override
public void draw(final Renderer r) {
final RenderDelegate delegate = getCurrentRenderDelegate();
if (delegate == null) {
if (!isDrawnReverse()) {
for (int i = getNumberOfChildren() - 1; i >= 0; i--) {
Spatial child = _children.get(i);
if (child != null) {
child.onDraw(r);
}
}
}
else {
for (int i = 0; i < getNumberOfChildren() ; i++) {
Spatial child = _children.get(i);
if (child != null) {
child.onDraw(r);
}
}
}
} else {
// Queue as needed
if (!r.isProcessingQueue()) {
if (r.checkAndAdd(this)) {
return;
}
}
delegate.render(this, r);
}
}
}