/* * Copyright (c) 2012, 2013 Hemanta Sapkota. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Hemanta Sapkota (laex.pearl@gmail.com) */ package com.laex.cg2d.model.model; import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.PropertyDescriptor; import org.eclipse.ui.views.properties.TextPropertyDescriptor; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.JointDef; import com.badlogic.gdx.physics.box2d.JointDef.JointType; import com.laex.cg2d.model.descs.Vec2PropertySource; import com.laex.cg2d.model.util.BooleanUtil; /** * The Class Joint. */ public abstract class Joint extends ModelElement { /** * This class exists because JointDef (LibGDX Box2D) cannot be instantiated. * This change happened from LibGDX 0.9.6 * * @author hemantasapkota * */ public class BEJointDef extends JointDef { } /** The Constant JOINT_TYPE_PROP. */ public static final String JOINT_TYPE_PROP = "JointDef.JointType"; /** The Constant COLLIDE_CONNECTED_PROP. */ public static final String COLLIDE_CONNECTED_PROP = "JointDef.CollideConnected"; /** The Constant LOCAL_ANCHOR_A. */ public static final String LOCAL_ANCHOR_A = "JointDef.LocalAnchorA"; /** The Constant LOCAL_ANCHOR_B. */ public static final String LOCAL_ANCHOR_B = "JointDef.LocalAnchorB"; /** The Constant USE_LOCAL_ANCHORS. */ public static final String USE_LOCAL_ANCHORS = "JointDef.UseLocalAnchors"; /** The descriptors. */ private static IPropertyDescriptor[] descriptors; /** The is connected. */ private Boolean isConnected = Boolean.FALSE; /** The source. */ private Shape source; /** The target. */ private Shape target; /** The local anchor a. */ private Vector2 localAnchorA = new Vector2(); /** The local anchor b. */ private Vector2 localAnchorB = new Vector2(); /** The joint def. */ private BEJointDef jointDef = new BEJointDef(); // For some strange reason, jointDef.collideConnected cannot persist the // boolean value. // Therefore, an extra booelan had to be created. This correctly persists // the value. /** The coolide connected. */ private boolean coolideConnected = false; /** The use local anchors. */ private boolean useLocalAnchors = false; static { PropertyDescriptor jointType = new TextPropertyDescriptor(JOINT_TYPE_PROP, "1.Type"); PropertyDescriptor collideConnectedProp = new ComboBoxPropertyDescriptor(COLLIDE_CONNECTED_PROP, "2.Collided Connected", BooleanUtil.BOOLEAN_STRING_VALUES); PropertyDescriptor useLocalAnchors = new ComboBoxPropertyDescriptor(USE_LOCAL_ANCHORS, "3.Use Local Anchors", BooleanUtil.BOOLEAN_STRING_VALUES); PropertyDescriptor locAncA = new PropertyDescriptor(LOCAL_ANCHOR_A, "4.localAnchorA"); PropertyDescriptor locAncB = new PropertyDescriptor(LOCAL_ANCHOR_B, "5.localAnchorB"); descriptors = new PropertyDescriptor[] { jointType, collideConnectedProp, useLocalAnchors, locAncA, locAncB }; } /** * Instantiates a new joint. * * @param source * the source * @param target * the target */ public Joint(Shape source, Shape target) { reconnect(source, target); jointDef.type = getJointType(); } /** * Gets the joint type. * * @return the joint type */ public abstract JointType getJointType(); /** * Compute local anchors. * * @param ptmRatio the ptm ratio */ public abstract void computeLocalAnchors(int ptmRatio); /* * (non-Javadoc) * * @see com.laex.cg2d.shared.model.ModelElement#getEditableValue() */ @Override public Object getEditableValue() { return jointDef; } /** * Checks if is collide connected. * * @return true, if is collide connected */ public boolean isCollideConnected() { return coolideConnected; } /* * (non-Javadoc) * * @see * com.laex.cg2d.shared.model.ModelElement#setPropertyValue(java.lang.Object, * java.lang.Object) */ public void setPropertyValue(Object id, Object value) { if (shouldUseLocalAnchors(id)) { this.useLocalAnchors = BooleanUtil.toBool(value); } else if (isCollideConnected(id)) { this.jointDef.collideConnected = BooleanUtil.toBool(value); this.coolideConnected = BooleanUtil.toBool(value); } else if (isLocalAnchorA(id)) { this.localAnchorA = (Vector2) value; } else if (isLocalAnchorB(id)) { this.localAnchorB = (Vector2) value; } else { super.setPropertyValue(id, value); } } /* * (non-Javadoc) * * @see * com.laex.cg2d.shared.model.ModelElement#getPropertyValue(java.lang.Object) */ public Object getPropertyValue(Object id) { if (shouldUseLocalAnchors(id)) { return BooleanUtil.getIntegerFromBoolean(this.useLocalAnchors); } if (isCollideConnected(id)) { return BooleanUtil.getIntegerFromBoolean(this.coolideConnected); } if (isLocalAnchorA(id)) { return new Vec2PropertySource(localAnchorA); } if (isLocalAnchorB(id)) { return new Vec2PropertySource(localAnchorB); } if (isJointTypeProp(id)) { return jointDef.type.toString(); } return super.getPropertyValue(id); } /** * Checks if is joint type prop. * * @param id * the id * @return true, if is joint type prop */ private boolean isJointTypeProp(Object id) { return JOINT_TYPE_PROP.equals(id); } /** * Checks if is local anchor a. * * @param id the id * @return true, if is local anchor a */ private boolean isLocalAnchorA(Object id) { return LOCAL_ANCHOR_A.equals(id); } /** * Checks if is local anchor b. * * @param id the id * @return true, if is local anchor b */ private boolean isLocalAnchorB(Object id) { return LOCAL_ANCHOR_B.equals(id); } /** * Should use local anchors. * * @param id the id * @return true, if successful */ private boolean shouldUseLocalAnchors(Object id) { return USE_LOCAL_ANCHORS.equals(id); } /** * Checks if is collide connected. * * @param id * the id * @return true, if is collide connected */ private boolean isCollideConnected(Object id) { return COLLIDE_CONNECTED_PROP.equals(id); } /* * (non-Javadoc) * * @see com.laex.cg2d.shared.model.ModelElement#getPropertyDescriptors() */ public IPropertyDescriptor[] getPropertyDescriptors() { return descriptors; } /** * Gets the source. * * @return the source */ public Shape getSource() { return source; } /** * Gets the local anchor a. * * @return the local anchor a */ public Vector2 getLocalAnchorA() { return localAnchorA; } /** * Sets the local anchor a. * * @param localAnchorA the new local anchor a */ public void setLocalAnchorA(Vector2 localAnchorA) { this.localAnchorA = localAnchorA; } /** * Gets the local anchor b. * * @return the local anchor b */ public Vector2 getLocalAnchorB() { return localAnchorB; } /** * Should use local anchors. * * @return true, if successful */ public boolean shouldUseLocalAnchors() { return useLocalAnchors; } /** * Sets the use local anchors. * * @param useLocalAnchors the new use local anchors */ public void setUseLocalAnchors(boolean useLocalAnchors) { this.useLocalAnchors = useLocalAnchors; } /** * Sets the local anchor b. * * @param localAnchorB the new local anchor b */ public void setLocalAnchorB(Vector2 localAnchorB) { this.localAnchorB = localAnchorB; } /** * Gets the target. * * @return the target */ public Shape getTarget() { return target; } /** * Reconnect. */ public void reconnect() { if (!isConnected) { source.addJoint(this); target.addJoint(this); isConnected = true; } } /** * Disconnect. */ public void disconnect() { if (isConnected) { source.removeJoint(this); target.removeJoint(this); isConnected = false; } } /** * Reconnect. * * @param newSource * the new source * @param newTarget * the new target */ public void reconnect(Shape newSource, Shape newTarget) { if (newSource == null || newTarget == null || newSource == newTarget) { throw new IllegalArgumentException(); } disconnect(); this.source = newSource; this.target = newTarget; reconnect(); } }