159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * To change this template, choose Tools | Templates
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and open the template in the editor.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.bullet.control;
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.PhysicsSpace;
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.collision.shapes.CollisionShape;
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bullet.objects.PhysicsGhostObject;
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.InputCapsule;
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeExporter;
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeImporter;
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.OutputCapsule;
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Quaternion;
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f;
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.RenderManager;
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.ViewPort;
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Spatial;
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.control.Control;
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * A GhostControl moves with the spatial it is attached to and can be used to check
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * overlaps with other physics objects (e.g. aggro radius).
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author normenhansen
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class GhostControl extends PhysicsGhostObject implements PhysicsControl {
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Spatial spatial;
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected boolean enabled = true;
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected boolean added = false;
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected PhysicsSpace space = null;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected boolean applyLocal = false;
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public GhostControl() {
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public GhostControl(CollisionShape shape) {
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super(shape);
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isApplyPhysicsLocal() {
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return applyLocal;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * When set to true, the physics coordinates will be applied to the local
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * translation of the Spatial
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param applyPhysicsLocal
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setApplyPhysicsLocal(boolean applyPhysicsLocal) {
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        applyLocal = applyPhysicsLocal;
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Vector3f getSpatialTranslation() {
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (applyLocal) {
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return spatial.getLocalTranslation();
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return spatial.getWorldTranslation();
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Quaternion getSpatialRotation() {
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (applyLocal) {
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return spatial.getLocalRotation();
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return spatial.getWorldRotation();
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Control cloneForSpatial(Spatial spatial) {
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        GhostControl control = new GhostControl(collisionShape);
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setCcdMotionThreshold(getCcdMotionThreshold());
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setCcdSweptSphereRadius(getCcdSweptSphereRadius());
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setCollideWithGroups(getCollideWithGroups());
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setCollisionGroup(getCollisionGroup());
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setPhysicsLocation(getPhysicsLocation());
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setPhysicsRotation(getPhysicsRotationMatrix());
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setApplyPhysicsLocal(isApplyPhysicsLocal());
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        control.setSpatial(spatial);
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return control;
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setSpatial(Spatial spatial) {
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (getUserObject() == null || getUserObject() == this.spatial) {
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            setUserObject(spatial);
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.spatial = spatial;
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (spatial == null) {
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (getUserObject() == spatial) {
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                setUserObject(null);
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setPhysicsLocation(getSpatialTranslation());
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setPhysicsRotation(getSpatialRotation());
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setEnabled(boolean enabled) {
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.enabled = enabled;
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (space != null) {
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (enabled && !added) {
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (spatial != null) {
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    setPhysicsLocation(getSpatialTranslation());
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    setPhysicsRotation(getSpatialRotation());
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                space.addCollisionObject(this);
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                added = true;
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else if (!enabled && added) {
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                space.removeCollisionObject(this);
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                added = false;
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isEnabled() {
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return enabled;
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void update(float tpf) {
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!enabled) {
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setPhysicsLocation(getSpatialTranslation());
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setPhysicsRotation(getSpatialRotation());
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void render(RenderManager rm, ViewPort vp) {
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (enabled && space != null && space.getDebugManager() != null) {
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (debugShape == null) {
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                attachDebugShape(space.getDebugManager());
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            debugShape.setLocalTranslation(spatial.getWorldTranslation());
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            debugShape.setLocalRotation(spatial.getWorldRotation());
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            debugShape.updateLogicalState(0);
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            debugShape.updateGeometricState();
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            rm.renderScene(debugShape, vp);
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setPhysicsSpace(PhysicsSpace space) {
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (space == null) {
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (this.space != null) {
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                this.space.removeCollisionObject(this);
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                added = false;
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (this.space == space) {
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                return;
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            space.addCollisionObject(this);
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            added = true;
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.space = space;
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public PhysicsSpace getPhysicsSpace() {
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return space;
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void write(JmeExporter ex) throws IOException {
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.write(ex);
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        OutputCapsule oc = ex.getCapsule(this);
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        oc.write(enabled, "enabled", true);
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        oc.write(applyLocal, "applyLocalPhysics", false);
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        oc.write(spatial, "spatial", null);
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void read(JmeImporter im) throws IOException {
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        super.read(im);
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        InputCapsule ic = im.getCapsule(this);
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        enabled = ic.readBoolean("enabled", true);
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        spatial = (Spatial) ic.readSavable("spatial", null);
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        applyLocal = ic.readBoolean("applyLocalPhysics", false);
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setUserObject(spatial);
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
179