package com.uwsoft.editor.renderer.systems;
import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Matrix3;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.SnapshotArray;
import com.uwsoft.editor.renderer.components.*;
import com.uwsoft.editor.renderer.utils.TransformMathUtils;
public class CompositeSystem extends IteratingSystem {
private ComponentMapper<DimensionsComponent> dimensionsMapper;
private ComponentMapper<TransformComponent> transformMapper;
private ComponentMapper<NodeComponent> nodeMapper;
private ComponentMapper<CompositeTransformComponent> compositeMapper;
private DimensionsComponent dimensionsComponent;
private NodeComponent nodeComponent;
private final Vector2 p1 = new Vector2();
private final Vector2 p2 = new Vector2();
private final Vector2 p3 = new Vector2();
private final Vector2 p4 = new Vector2();
private final Vector2 tmpBoundPoints = new Vector2();
public CompositeSystem() {
super(Family.all(CompositeTransformComponent.class).get());
dimensionsMapper = ComponentMapper.getFor(DimensionsComponent.class);
transformMapper = ComponentMapper.getFor(TransformComponent.class);
nodeMapper = ComponentMapper.getFor(NodeComponent.class);
compositeMapper = ComponentMapper.getFor(CompositeTransformComponent.class);
}
@Override
public void processEntity(Entity entity, float deltaTime) {
dimensionsComponent = dimensionsMapper.get(entity);
nodeComponent = nodeMapper.get(entity);
// if(dimensionsComponent.boundBox == null){
// dimensionsComponent.boundBox = new Rectangle();
// }
// recalculateSize();
CompositeTransformComponent compositeTransformComponent = compositeMapper.get(entity);
ViewPortComponent viewPortComponent = entity.getComponent(ViewPortComponent.class);
if (compositeTransformComponent != null && compositeTransformComponent.automaticResize && viewPortComponent == null) {
recalculateSize();
}
}
private void recalculateSize() {
float lowerX = Float.MAX_VALUE;
float lowerY = Float.MAX_VALUE;
float upperX = Float.MIN_VALUE;
float upperY = Float.MIN_VALUE;
SnapshotArray<Entity> entities = nodeComponent.children;
for (Entity entity : entities) {
TransformComponent transformComponent = transformMapper.get(entity);
DimensionsComponent childDimCom = dimensionsMapper.get(entity);
float x = transformComponent.x;
float y = transformComponent.y;
float width = childDimCom.width;
float height = childDimCom.height;
Matrix3 transMat = TransformMathUtils.transform(transformComponent);
p1.set(x, y).mul(transMat);
p2.set(x + width, y).mul(transMat);
p3.set(x + width, y + height).mul(transMat);
p4.set(x, y + height).mul(transMat);
tmpBoundPoints.set(lowerX, 0);
lowerX = getX(MinMaxOp.MIN, p1, p2, p3, p4, tmpBoundPoints);
tmpBoundPoints.set(upperX, 0);
upperX = getX(MinMaxOp.MAX, p1, p2, p3, p4, tmpBoundPoints);
tmpBoundPoints.set(0, lowerY);
lowerY = getY(MinMaxOp.MIN, p1, p2, p3, p4, tmpBoundPoints);
tmpBoundPoints.set(0, upperY);
upperY = getY(MinMaxOp.MAX, p1, p2, p3, p4, tmpBoundPoints);
}
for (Entity entity : entities) {
if (lowerX == 0 && lowerY == 0) break;
TransformComponent transformComponent = transformMapper.get(entity);
transformComponent.x -= lowerX;
transformComponent.y -= lowerY;
}
dimensionsComponent.width = (upperX - lowerX);
dimensionsComponent.height = (upperY - lowerY);
lowerX = 0;
lowerY = 0;
dimensionsComponent.boundBox.set(lowerX, lowerY, dimensionsComponent.width, dimensionsComponent.height);
}
private float getX(MinMaxOp op, Vector2... points) {
float pointX = points[0].x;
for (Vector2 point : points) {
pointX = op.compare(pointX, point.x);
}
return pointX;
}
private float getY(MinMaxOp op, Vector2... points) {
float pointY = points[0].y;
for (Vector2 point : points) {
pointY = op.compare(pointY, point.y);
}
return pointY;
}
private enum MinMaxOp {
MIN("<") {
@Override
public float compare(float a, float b) {
return (a < b) ? a : b;
}
},
MAX(">") {
@Override
public float compare(float a, float b) {
return (a > b) ? a : b;
}
};
private String minMaxOperator;
MinMaxOp(String minMaxOperator) {
this.minMaxOperator = minMaxOperator;
}
public abstract float compare(float a, float b);
}
}