Skip to content

Instantly share code, notes, and snippets.

@musicm122
Created September 28, 2013 22:35
Show Gist options
  • Select an option

  • Save musicm122/6747466 to your computer and use it in GitHub Desktop.

Select an option

Save musicm122/6747466 to your computer and use it in GitHub Desktop.
around line 213 of b2dJson.cpp case b2Shape::e_edge: { b2EdgeShape* edge = (b2EdgeShape*)shape; vecToJson("vertex1", edge->m_vertex1, fixtureValue["edge"]); vecToJson("vertex2", edge->m_vertex2, fixtureValue["edge"]); if ( edge->m_hasVertex0 ) fixtureValue["edge"]["hasVertex0"] = true; if ( edge->m_hasVertex3 ) fixtureValue["edge"]["hasVertex3"]…
/*
* Author: Chris Campbell - www.iforce2d.net
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "StdAfx.h"
#include <istream>
#include <fstream>
#include "b2dJson.h"
#include "json/json.h"
#include "b2dJsonImage.h"
#include "Infrastructure\Log.h"
using namespace std;
#define sysLog CompoundLog::GetSystemLog()
inline bool b2dJsonImage_renderOrder_ascending(const b2dJsonImage* a, const b2dJsonImage* b)
{
return a->renderOrder < b->renderOrder;
}
b2dJson::b2dJson(bool useHumanReadableFloats)
{
m_useHumanReadableFloats = useHumanReadableFloats;
}
b2dJson::~b2dJson()
{
for (int i = 0; i < (int)m_images.size(); i++)
delete m_images[i];
for (std::map<void*,b2dJsonCustomProperties*>::iterator it = m_customPropertiesMap.begin(); it != m_customPropertiesMap.end(); ++it)
delete it->second;
}
Json::Value b2dJson::writeToValue(b2World *world)
{
if (!world)
return Json::Value();
return b2j(world);
}
std::string b2dJson::writeToString(b2World* world)
{
if (!world)
return std::string();
Json::StyledWriter writer;
return writer.write( b2j(world) );
}
bool b2dJson::writeToFile(b2World* world, const char* filename)
{
if ( !world || !filename )
return false;
std::ofstream ofs;
ofs.open(filename, std::ios::out);
if (!ofs) {
std::cout << "Could not open file " << filename << " for writing\n";
return false;
}
Json::StyledStreamWriter writer(" ");
writer.write( ofs, b2j(world) );
ofs.close();
return true;
}
Json::Value b2dJson::b2j(b2World* world)
{
m_bodyToIndexMap.clear();
m_jointToIndexMap.clear();
Json::Value worldValue;
vecToJson("gravity", world->GetGravity(), worldValue);
worldValue["allowSleep"] = world->GetAllowSleeping();
worldValue["autoClearForces"] = world->GetAutoClearForces();
worldValue["warmStarting"] = world->GetWarmStarting();
worldValue["continuousPhysics"] = world->GetContinuousPhysics();
worldValue["subStepping"] = world->GetSubStepping();
//worldValue["hasDestructionListener"] = world->HasDestructionListener();
//worldValue["hasContactFilter"] = world->HasContactFilter();
//worldValue["hasContactListener"] = world->HasContactListener();
int i = 0;
for (b2Body* body = world->GetBodyList(); body; body = body->GetNext()) {
m_bodyToIndexMap[body] = i;
worldValue["body"][i] = b2j(body);
i++;
}
//need two passes for joints because gear joints reference other joints
i = 0;
for (b2Joint* joint = world->GetJointList(); joint; joint = joint->GetNext()) {
if ( joint->GetType() == e_gearJoint )
continue;
worldValue["joint"][i] = b2j(joint);
m_jointToIndexMap[joint] = i;
i++;
}
for (b2Joint* joint = world->GetJointList(); joint; joint = joint->GetNext()) {
if ( joint->GetType() != e_gearJoint )
continue;
worldValue["joint"][i] = b2j(joint);
m_jointToIndexMap[joint] = i;
i++;
}
i = 0;
{
std::map<b2dJsonImage*,string>::iterator it = m_imageToNameMap.begin();
std::map<b2dJsonImage*,string>::iterator end = m_imageToNameMap.end();
while (it != end) {
b2dJsonImage* image = it->first;
worldValue["image"][i] = b2j(image);
i++;
++it;
}
}
Json::Value customPropertyValue = writeCustomPropertiesToJson(NULL);
if ( ! customPropertyValue.empty() )
worldValue["customProperties"] = customPropertyValue;
m_bodyToIndexMap.clear();
m_jointToIndexMap.clear();
return worldValue;
}
Json::Value b2dJson::b2j(b2Body* body)
{
Json::Value bodyValue;
string bodyName = getBodyName(body);
if ( bodyName != "" )
bodyValue["name"] = bodyName;
bodyValue["type"] = body->GetType();
switch( body->GetType() )
{
case b2_staticBody:
bodyValue["type"].setComment("//static", Json::commentAfterOnSameLine);
break;
case b2_dynamicBody:
bodyValue["type"].setComment("//dynamic", Json::commentAfterOnSameLine);
break;
case b2_kinematicBody:
bodyValue["type"].setComment("//kinematic", Json::commentAfterOnSameLine);
break;
}
vecToJson("position", body->GetPosition(), bodyValue);
floatToJson("angle", body->GetAngle(), bodyValue );
vecToJson("linearVelocity", body->GetLinearVelocity(), bodyValue);
floatToJson("angularVelocity", body->GetAngularVelocity(), bodyValue);
if ( body->GetLinearDamping() != 0 )
floatToJson("linearDamping", body->GetLinearDamping(), bodyValue);
if ( body->GetAngularDamping() != 0 )
floatToJson("angularDamping", body->GetAngularDamping(), bodyValue);
if ( body->GetGravityScale() != 1 )
floatToJson("gravityScale", body->GetGravityScale(), bodyValue);
if ( body->IsBullet() )
bodyValue["bullet"] = true;
if ( ! body->IsSleepingAllowed() )
bodyValue["allowSleep"] = false;
if ( body->IsAwake() )
bodyValue["awake"] = true;
if ( ! body->IsActive() )
bodyValue["active"] = false;
if ( body->IsFixedRotation() )
bodyValue["fixedRotation"] = true;
b2MassData massData;
body->GetMassData(&massData);
if ( massData.mass != 0 )
floatToJson("massData-mass", massData.mass, bodyValue);
if ( massData.center.x != 0 || massData.center.y != 0 )
vecToJson("massData-center", massData.center, bodyValue);
if ( massData.I != 0 )
floatToJson("massData-I", massData.I, bodyValue);
int i = 0;
for (b2Fixture* fixture = body->GetFixtureList(); fixture; fixture = fixture->GetNext())
bodyValue["fixture"][i++] = b2j(fixture);
Json::Value customPropertyValue = writeCustomPropertiesToJson(body);
if ( ! customPropertyValue.empty() )
bodyValue["customProperties"] = customPropertyValue;
return bodyValue;
}
Json::Value b2dJson::b2j(b2Fixture *fixture)
{
Json::Value fixtureValue;
string fixtureName = getFixtureName(fixture);
if ( fixtureName != "" )
fixtureValue["name"] = fixtureName;
if ( fixture->GetRestitution() != 0 )
floatToJson("restitution", fixture->GetRestitution(), fixtureValue);
if ( fixture->GetFriction() != 0 )
floatToJson("friction", fixture->GetFriction(), fixtureValue);
if ( fixture->GetDensity() != 0 )
floatToJson("density", fixture->GetDensity(), fixtureValue);
if ( fixture->IsSensor() )
fixtureValue["sensor"] = true;
b2Filter filter = fixture->GetFilterData();
if ( filter.categoryBits != 0x0001 )
fixtureValue["filter-categoryBits"] = filter.categoryBits;
if ( filter.maskBits != 0xffff )
fixtureValue["filter-maskBits"] = filter.maskBits;
if ( filter.groupIndex != 0 )
fixtureValue["filter-groupIndex"] = filter.groupIndex;
b2Shape* shape = fixture->GetShape();
switch (shape->GetType())
{
case b2Shape::e_circle:
{
b2CircleShape* circle = (b2CircleShape*)shape;
floatToJson("radius", circle->m_radius, fixtureValue["circle"]);
vecToJson("center", circle->m_p, fixtureValue["circle"]);
}
break;
case b2Shape::e_edge:
{
b2EdgeShape* edge = (b2EdgeShape*)shape;
vecToJson("vertex1", edge->m_vertex1, fixtureValue["edge"]);
vecToJson("vertex2", edge->m_vertex2, fixtureValue["edge"]);
if ( edge->m_hasVertex0 )
fixtureValue["edge"]["hasVertex0"] = true;
if ( edge->m_hasVertex3 )
fixtureValue["edge"]["hasVertex3"] = true;
if ( edge->m_hasVertex0 )
vecToJson("vertex0", edge->m_vertex0, fixtureValue["edge"]);
if ( edge->m_hasVertex3 )
vecToJson("vertex3", edge->m_vertex3, fixtureValue["edge"]);
}
break;
case b2Shape::e_chain:
{
b2ChainShape* chain = (b2ChainShape*)shape;
int32 count = chain->m_count;
const b2Vec2* vertices = chain->m_vertices;
for (int32 i = 0; i < count; ++i)
vecToJson("vertices", vertices[i], fixtureValue["chain"], i);
if ( chain->m_hasPrevVertex )
fixtureValue["chain"]["hasPrevVertex"] = true;
if ( chain->m_hasNextVertex )
fixtureValue["chain"]["hasNextVertex"] = true;
if ( chain->m_hasPrevVertex )
vecToJson("prevVertex", chain->m_prevVertex, fixtureValue["chain"]);
if ( chain->m_hasNextVertex )
vecToJson("nextVertex", chain->m_nextVertex, fixtureValue["chain"]);
}
break;
case b2Shape::e_polygon:
{
b2PolygonShape* poly = (b2PolygonShape*)shape;
int32 vertexCount = poly->GetVertexCount();
b2Assert(vertexCount <= b2_maxPolygonVertices);
for (int32 i = 0; i < vertexCount; ++i)
vecToJson("vertices", poly->m_vertices[i], fixtureValue["polygon"], i);
}
break;
default:
std::cout << "Unknown shape type : " << shape->GetType() << std::endl;
}
Json::Value customPropertyValue = writeCustomPropertiesToJson(fixture);
if ( ! customPropertyValue.empty() )
fixtureValue["customProperties"] = customPropertyValue;
return fixtureValue;
}
Json::Value b2dJson::b2j(b2Joint* joint)
{
Json::Value jointValue;
int bodyIndexA = lookupBodyIndex( joint->GetBodyA() );
int bodyIndexB = lookupBodyIndex( joint->GetBodyB() );
jointValue["bodyA"] = bodyIndexA;
jointValue["bodyB"] = bodyIndexB;
if ( joint->GetCollideConnected() )
jointValue["collideConnected"] = true;
string jointName = getJointName(joint);
if ( jointName != "" )
jointValue["name"] = jointName;
b2Body* bodyA = joint->GetBodyA();
b2Body* bodyB = joint->GetBodyB();
switch ( joint->GetType() )
{
case e_revoluteJoint:
{
jointValue["type"] = "revolute";
b2RevoluteJoint* revoluteJoint = (b2RevoluteJoint*)joint;
vecToJson("anchorA", bodyA->GetLocalPoint(revoluteJoint->GetAnchorA()), jointValue);
vecToJson("anchorB", bodyB->GetLocalPoint(revoluteJoint->GetAnchorB()), jointValue);
floatToJson("refAngle", bodyB->GetAngle() - bodyA->GetAngle() - revoluteJoint->GetJointAngle(), jointValue);
floatToJson("jointSpeed", revoluteJoint->GetJointSpeed(), jointValue);
jointValue["enableLimit"] = revoluteJoint->IsLimitEnabled();
floatToJson("lowerLimit", revoluteJoint->GetLowerLimit(), jointValue);
floatToJson("upperLimit", revoluteJoint->GetUpperLimit(), jointValue);
jointValue["enableMotor"] = revoluteJoint->IsMotorEnabled();
floatToJson("motorSpeed", revoluteJoint->GetMotorSpeed(), jointValue);
floatToJson("maxMotorTorque", revoluteJoint->GetMaxMotorTorque(), jointValue);
}
break;
case e_prismaticJoint:
{
jointValue["type"] = "prismatic";
b2PrismaticJoint* prismaticJoint = (b2PrismaticJoint*)joint;
vecToJson("anchorA", bodyA->GetLocalPoint(prismaticJoint->GetAnchorA()), jointValue);
vecToJson("anchorB", bodyB->GetLocalPoint(prismaticJoint->GetAnchorB()), jointValue);
vecToJson("localAxisA", prismaticJoint->GetLocalAxisA(), jointValue);
floatToJson("refAngle", prismaticJoint->GetReferenceAngle(), jointValue);
jointValue["enableLimit"] = prismaticJoint->IsLimitEnabled();
floatToJson("lowerLimit", prismaticJoint->GetLowerLimit(), jointValue);
floatToJson("upperLimit", prismaticJoint->GetUpperLimit(), jointValue);
jointValue["enableMotor"] = prismaticJoint->IsMotorEnabled();
floatToJson("maxMotorForce", prismaticJoint->GetMaxMotorForce(), jointValue);
floatToJson("motorSpeed", prismaticJoint->GetMotorSpeed(), jointValue);
}
break;
case e_distanceJoint:
{
jointValue["type"] = "distance";
b2DistanceJoint* distanceJoint = (b2DistanceJoint*)joint;
vecToJson("anchorA", bodyA->GetLocalPoint(distanceJoint->GetAnchorA()), jointValue);
vecToJson("anchorB", bodyB->GetLocalPoint(distanceJoint->GetAnchorB()), jointValue);
floatToJson("length", distanceJoint->GetLength(), jointValue);
floatToJson("frequency", distanceJoint->GetFrequency(), jointValue);
floatToJson("dampingRatio", distanceJoint->GetDampingRatio(), jointValue);
}
break;
case e_pulleyJoint:
{
jointValue["type"] = "pulley";
b2PulleyJoint* pulleyJoint = (b2PulleyJoint*)joint;
vecToJson("groundAnchorA", pulleyJoint->GetGroundAnchorA(), jointValue);
vecToJson("groundAnchorB", pulleyJoint->GetGroundAnchorB(), jointValue);
vecToJson("anchorA", bodyA->GetLocalPoint(pulleyJoint->GetAnchorA()), jointValue);
vecToJson("anchorB", bodyB->GetLocalPoint(pulleyJoint->GetAnchorB()), jointValue);
floatToJson("lengthA", (pulleyJoint->GetGroundAnchorA() - pulleyJoint->GetAnchorA()).Length(), jointValue);
floatToJson("lengthB", (pulleyJoint->GetGroundAnchorB() - pulleyJoint->GetAnchorB()).Length(), jointValue);
floatToJson("ratio", pulleyJoint->GetRatio(), jointValue);
}
break;
case e_mouseJoint:
{
jointValue["type"] = "mouse";
b2MouseJoint* mouseJoint = (b2MouseJoint*)joint;
vecToJson("target", mouseJoint->GetTarget(), jointValue);
vecToJson("anchorB", mouseJoint->GetAnchorB(), jointValue);
floatToJson("maxForce", mouseJoint->GetMaxForce(), jointValue);
floatToJson("frequency", mouseJoint->GetFrequency(), jointValue);
floatToJson("dampingRatio", mouseJoint->GetDampingRatio(), jointValue);
}
break;
case e_gearJoint:
{
jointValue["type"] = "gear";
b2GearJoint* gearJoint = (b2GearJoint*)joint;
int jointIndex1 = lookupJointIndex( gearJoint->GetJoint1() );
int jointIndex2 = lookupJointIndex( gearJoint->GetJoint2() );
jointValue["joint1"] = jointIndex1;
jointValue["joint2"] = jointIndex2;
jointValue["ratio"] = gearJoint->GetRatio();
}
break;
case e_wheelJoint:
{
jointValue["type"] = "wheel";
b2WheelJoint* wheelJoint = (b2WheelJoint*)joint;
vecToJson("anchorA", bodyA->GetLocalPoint(wheelJoint->GetAnchorA()), jointValue);
vecToJson("anchorB", bodyB->GetLocalPoint(wheelJoint->GetAnchorB()), jointValue);
vecToJson("localAxisA", wheelJoint->GetLocalAxisA(), jointValue);
jointValue["enableMotor"] = wheelJoint->IsMotorEnabled();
floatToJson("motorSpeed", wheelJoint->GetMotorSpeed(), jointValue);
floatToJson("maxMotorTorque", wheelJoint->GetMaxMotorTorque(), jointValue);
floatToJson("springFrequency", wheelJoint->GetSpringFrequencyHz(), jointValue);
floatToJson("springDampingRatio", wheelJoint->GetSpringDampingRatio(), jointValue);
}
break;
//case e_motorJoint:
// {
// jointValue["type"] = "motor";
// b2MotorJoint* motorJoint = (b2MotorJoint*)joint;
// vecToJson("anchorA", bodyA->GetLocalPoint(motorJoint->GetAnchorA()), jointValue);
// vecToJson("anchorB", bodyB->GetLocalPoint(motorJoint->GetAnchorB()), jointValue);
// floatToJson("refAngle", motorJoint->GetAngularOffset(), jointValue);
// floatToJson("maxForce", motorJoint->GetMaxForce(), jointValue);
// floatToJson("maxTorque", motorJoint->GetMaxTorque(), jointValue);
// //floatToJson("correctionFactor", motorJoint->GetCorrectionFactor(), jointValue);
// }
// break;
case e_weldJoint:
{
jointValue["type"] = "weld";
b2WeldJoint* weldJoint = (b2WeldJoint*)joint;
vecToJson("anchorA", bodyA->GetLocalPoint(weldJoint->GetAnchorA()), jointValue);
vecToJson("anchorB", bodyB->GetLocalPoint(weldJoint->GetAnchorB()), jointValue);
floatToJson("refAngle", weldJoint->GetReferenceAngle(), jointValue);
floatToJson("frequency", weldJoint->GetFrequency(), jointValue);
floatToJson("dampingRatio", weldJoint->GetDampingRatio(), jointValue);
}
break;
case e_frictionJoint:
{
jointValue["type"] = "friction";
b2FrictionJoint* frictionJoint = (b2FrictionJoint*)joint;
vecToJson("anchorA", bodyA->GetLocalPoint(frictionJoint->GetAnchorA()), jointValue);
vecToJson("anchorB", bodyB->GetLocalPoint(frictionJoint->GetAnchorB()), jointValue);
floatToJson("maxForce", frictionJoint->GetMaxForce(), jointValue);
floatToJson("maxTorque", frictionJoint->GetMaxTorque(), jointValue);
}
break;
case e_ropeJoint:
{
jointValue["type"] = "rope";
b2RopeJoint* ropeJoint = (b2RopeJoint*)joint;
vecToJson("anchorA", bodyA->GetLocalPoint(ropeJoint->GetAnchorA()), jointValue);
vecToJson("anchorB", bodyB->GetLocalPoint(ropeJoint->GetAnchorB()), jointValue);
floatToJson("maxLength", ropeJoint->GetMaxLength(), jointValue);
}
break;
case e_unknownJoint:
default:
std::cout << "Unknown joint type not stored in snapshot : " << joint->GetType() << std::endl;
}
Json::Value customPropertyValue = writeCustomPropertiesToJson(joint);
if ( ! customPropertyValue.empty() )
jointValue["customProperties"] = customPropertyValue;
return jointValue;
}
Json::Value b2dJson::b2j(b2dJsonImage *image)
{
Json::Value imageValue;
if ( image->body )
imageValue["body"] = lookupBodyIndex( image->body );
else
imageValue["body"] = -1;
if ( image->name != "" )
imageValue["name"] = image->name;
if ( image->file != "" )
imageValue["file"] = image->file;
vecToJson("center", image->center, imageValue);
floatToJson("angle", image->angle, imageValue );
floatToJson("scale", image->scale, imageValue );
if ( image->flip )
imageValue["flip"] = true;
floatToJson("opacity", image->opacity, imageValue );
imageValue["filter"] = image->filter;
floatToJson("renderOrder", image->renderOrder, imageValue );
bool defaultColorTint = true;
for (int i = 0; i < 4; i++) {
if ( image->colorTint[i] != 255 ) {
defaultColorTint = false;
break;
}
}
if ( !defaultColorTint ) {
for (int i = 0; i < 4; i++)
imageValue["colorTint"][i] = image->colorTint[i];
}
//image->updateCorners();
for (int i = 0; i < 4; i++)
vecToJson("corners", image->corners[i], imageValue, i);
//image->updateUVs();
for (int i = 0; i < 2*image->numPoints; i++) {
vecToJson("glVertexPointer", image->points[i], imageValue, i);
vecToJson("glTexCoordPointer", image->uvCoords[i], imageValue, i);
}
for (int i = 0; i < image->numIndices; i++)
vecToJson("glDrawElements", (unsigned int)image->indices[i], imageValue, i);
Json::Value customPropertyValue = writeCustomPropertiesToJson(image);
if ( ! customPropertyValue.empty() )
imageValue["customProperties"] = customPropertyValue;
return imageValue;
}
void b2dJson::setBodyName(b2Body* body, const char* name)
{
m_bodyToNameMap[body] = name;
}
void b2dJson::setFixtureName(b2Fixture* fixture, const char* name)
{
m_fixtureToNameMap[fixture] = name;
}
void b2dJson::setJointName(b2Joint* joint, const char* name)
{
m_jointToNameMap[joint] = name;
}
void b2dJson::setImageName(b2dJsonImage* image, const char* name)
{
m_imageToNameMap[image] = name;
}
void b2dJson::addImage(b2dJsonImage *image)
{
setImageName(image, image->name.c_str());
}
/////////
b2dJsonCustomProperties *b2dJson::getCustomPropertiesForItem(void *item, bool createIfNotExisting)
{
std::map<void*,b2dJsonCustomProperties*>::iterator it = m_customPropertiesMap.find(item);
if ( it != m_customPropertiesMap.end() )
return it->second;
if ( !createIfNotExisting )
return NULL;
b2dJsonCustomProperties* props = new b2dJsonCustomProperties();
m_customPropertiesMap[item] = props;
return props;
}
void b2dJson::setCustomInt(void* item, string propertyName, int val) { getCustomPropertiesForItem(item, true)->m_customPropertyMap_int[propertyName] = val; }
void b2dJson::setCustomFloat(void* item, string propertyName, float val) { getCustomPropertiesForItem(item, true)->m_customPropertyMap_float[propertyName] = val; }
void b2dJson::setCustomString(void* item, string propertyName, string val) { getCustomPropertiesForItem(item, true)->m_customPropertyMap_string[propertyName] = val; }
void b2dJson::setCustomVector(void* item, string propertyName, b2Vec2 val) { getCustomPropertiesForItem(item, true)->m_customPropertyMap_b2Vec2[propertyName] = val; }
void b2dJson::setCustomBool(void* item, string propertyName, bool val) { getCustomPropertiesForItem(item, true)->m_customPropertyMap_bool[propertyName] = val; }
bool b2dJson::hasCustomInt(void *item, string propertyName) { return getCustomPropertiesForItem(item, false) != NULL && getCustomPropertiesForItem(item, false)->m_customPropertyMap_int.count(propertyName) > 0; }
bool b2dJson::hasCustomFloat(void *item, string propertyName) { return getCustomPropertiesForItem(item, false) != NULL && getCustomPropertiesForItem(item, false)->m_customPropertyMap_float.count(propertyName) > 0; }
bool b2dJson::hasCustomString(void *item, string propertyName) { return getCustomPropertiesForItem(item, false) != NULL && getCustomPropertiesForItem(item, false)->m_customPropertyMap_string.count(propertyName) > 0; }
bool b2dJson::hasCustomVector(void *item, string propertyName) { return getCustomPropertiesForItem(item, false) != NULL && getCustomPropertiesForItem(item, false)->m_customPropertyMap_b2Vec2.count(propertyName) > 0; }
bool b2dJson::hasCustomBool(void *item, string propertyName) { return getCustomPropertiesForItem(item, false) != NULL && getCustomPropertiesForItem(item, false)->m_customPropertyMap_bool.count(propertyName) > 0; }
int b2dJson::getCustomInt(void *item, string propertyName, int defaultVal)
{
b2dJsonCustomProperties* props = getCustomPropertiesForItem(item, false);
if ( !props )
return defaultVal;
std::map<string,int>::iterator it = props->m_customPropertyMap_int.find(propertyName);
if ( it != props->m_customPropertyMap_int.end() )
return it->second;
return defaultVal;
}
float b2dJson::getCustomFloat(void *item, string propertyName, float defaultVal)
{
b2dJsonCustomProperties* props = getCustomPropertiesForItem(item, false);
if ( !props )
return defaultVal;
std::map<string,float>::iterator it = props->m_customPropertyMap_float.find(propertyName);
if ( it != props->m_customPropertyMap_float.end() )
return it->second;
return defaultVal;
}
string b2dJson::getCustomString(void *item, string propertyName, string defaultVal)
{
b2dJsonCustomProperties* props = getCustomPropertiesForItem(item, false);
if ( !props )
return defaultVal;
std::map<string,string>::iterator it = props->m_customPropertyMap_string.find(propertyName);
if ( it != props->m_customPropertyMap_string.end() )
return it->second;
return defaultVal;
}
b2Vec2 b2dJson::getCustomVector(void *item, string propertyName, b2Vec2 defaultVal)
{
b2dJsonCustomProperties* props = getCustomPropertiesForItem(item, false);
if ( !props )
return defaultVal;
std::map<string,b2Vec2>::iterator it = props->m_customPropertyMap_b2Vec2.find(propertyName);
if ( it != props->m_customPropertyMap_b2Vec2.end() )
return it->second;
return defaultVal;
}
bool b2dJson::getCustomBool(void *item, string propertyName, bool defaultVal)
{
b2dJsonCustomProperties* props = getCustomPropertiesForItem(item, false);
if ( !props )
return defaultVal;
std::map<string,bool>::iterator it = props->m_customPropertyMap_bool.find(propertyName);
if ( it != props->m_customPropertyMap_bool.end() )
return it->second;
return defaultVal;
}
//this define saves us writing out 20 functions which are almost exactly the same
#define IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Type, ucName, lcName, ucValType, lcValType)\
int b2dJson::get##ucName##ByCustom##ucValType( std::string propertyName, lcValType valueToMatch, std::vector<b2Type*>& items )\
{\
set<b2Type*>::iterator it = m_##lcName##WithCustomProperties.begin();\
set<b2Type*>::iterator end = m_##lcName##WithCustomProperties.end();\
while (it != end)\
{\
b2Type* item = *it;\
if ( hasCustom##ucValType( item, propertyName ) && getCustom##ucValType( item, propertyName ) == valueToMatch )\
items.push_back( item );\
++it;\
}\
return items.size();\
}
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Body, Bodies, bodies, Int, int)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Body, Bodies, bodies, Float, float)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Body, Bodies, bodies, String, string)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Body, Bodies, bodies, Vector, b2Vec2)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Body, Bodies, bodies, Bool, bool)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Fixture, Fixtures, fixtures, Int, int)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Fixture, Fixtures, fixtures, Float, float)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Fixture, Fixtures, fixtures, String, string)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Fixture, Fixtures, fixtures, Vector, b2Vec2)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Fixture, Fixtures, fixtures, Bool, bool)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Joint, Joints, joints, Int, int)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Joint, Joints, joints, Float, float)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Joint, Joints, joints, String, string)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Joint, Joints, joints, Vector, b2Vec2)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2Joint, Joints, joints, Bool, bool)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2dJsonImage, Images, images, Int, int)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2dJsonImage, Images, images, Float, float)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2dJsonImage, Images, images, String, string)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2dJsonImage, Images, images, Vector, b2Vec2)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_VECTOR(b2dJsonImage, Images, images, Bool, bool)
//this define saves us writing out 20 functions which are almost exactly the same
#define IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Type, ucName, lcName, ucValType, lcValType)\
b2Type* b2dJson::get##ucName##ByCustom##ucValType( std::string propertyName, lcValType valueToMatch )\
{\
set<b2Type*>::iterator it = m_##lcName##WithCustomProperties.begin();\
set<b2Type*>::iterator end = m_##lcName##WithCustomProperties.end();\
while (it != end)\
{\
b2Type* item = *it;\
if ( hasCustom##ucValType( item, propertyName ) && getCustom##ucValType( item, propertyName ) == valueToMatch )\
return item;\
++it;\
}\
return NULL;\
}
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Body, Body, bodies, Int, int)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Body, Body, bodies, Float, float)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Body, Body, bodies, String, string)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Body, Body, bodies, Vector, b2Vec2)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Body, Body, bodies, Bool, bool)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Fixture, Fixture, fixtures, Int, int)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Fixture, Fixture, fixtures, Float, float)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Fixture, Fixture, fixtures, String, string)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Fixture, Fixture, fixtures, Vector, b2Vec2)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Fixture, Fixture, fixtures, Bool, bool)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Joint, Joint, joints, Int, int)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Joint, Joint, joints, Float, float)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Joint, Joint, joints, String, string)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Joint, Joint, joints, Vector, b2Vec2)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2Joint, Joint, joints, Bool, bool)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2dJsonImage, Image, images, Int, int)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2dJsonImage, Image, images, Float, float)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2dJsonImage, Image, images, String, string)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2dJsonImage, Image, images, Vector, b2Vec2)
IMPLEMENT_GET_BY_CUSTOM_PROPERTY_FUNCTIONS_SINGLE(b2dJsonImage, Image, images, Bool, bool)
Json::Value b2dJson::writeCustomPropertiesToJson(void* item)
{
Json::Value customPropertiesValue;
b2dJsonCustomProperties* props = getCustomPropertiesForItem(item, false);
if ( !props )
return customPropertiesValue;
int i = 0;
#define FILL_CUSTOM_PROPERTY_JSON_VALUE(theName,theType)\
for (std::map<string,theType>::iterator it = props->m_customPropertyMap_##theType.begin(); it != props->m_customPropertyMap_##theType.end(); ++it) {\
Json::Value propValue;\
propValue["name"] = it->first;\
propValue[""#theName] = it->second;\
customPropertiesValue[i++] = propValue;\
}
FILL_CUSTOM_PROPERTY_JSON_VALUE(int,int)
FILL_CUSTOM_PROPERTY_JSON_VALUE(float,float)
FILL_CUSTOM_PROPERTY_JSON_VALUE(string,string)
//FILL_CUSTOM_PROPERTY_JSON_VALUE(vec2,b2Vec2) handled separately below
FILL_CUSTOM_PROPERTY_JSON_VALUE(bool,bool)
for (std::map<string,b2Vec2>::iterator it = props->m_customPropertyMap_b2Vec2.begin(); it != props->m_customPropertyMap_b2Vec2.end(); ++it) {
Json::Value propValue;
propValue["name"] = it->first;
vecToJson("vec2", it->second, propValue);
customPropertiesValue[i++] = propValue;
}
return customPropertiesValue;
}
#define IMPLEMENT_READ_CUSTOM_PROPERTIES_FROM_JSON(b2Type)\
void b2dJson::readCustomPropertiesFromJson(b2Type* item, Json::Value value)\
{\
if ( ! item )\
return;\
if ( ! value.isMember("customProperties") )\
return;\
\
int i = 0;\
Json::Value propValue = value["customProperties"][i++];\
while ( !propValue.isNull() ) {\
string propertyName = propValue.get("name", "").asString();\
\
if ( propValue.isMember("int") ) {\
int val = propValue.get("int", 0).asInt();\
setCustomInt(item, propertyName, val);\
}\
if ( propValue.isMember("float") ) {\
float val = propValue.get("float", 0).asFloat();\
setCustomFloat(item, propertyName, val);\
}\
if ( propValue.isMember("string") ) {\
string val = propValue.get("string", 0).asString();\
setCustomString(item, propertyName, val);\
}\
if ( propValue.isMember("vec2") ) {\
b2Vec2 val = jsonToVec("vec2", propValue);\
setCustomVector(item, propertyName, val);\
}\
if ( propValue.isMember("bool") ) {\
bool val = propValue.get("bool", 0).asBool();\
setCustomBool(item, propertyName, val);\
}\
\
propValue = value["customProperties"][i++];\
}\
}
IMPLEMENT_READ_CUSTOM_PROPERTIES_FROM_JSON(b2Body)
IMPLEMENT_READ_CUSTOM_PROPERTIES_FROM_JSON(b2Fixture)
IMPLEMENT_READ_CUSTOM_PROPERTIES_FROM_JSON(b2Joint)
IMPLEMENT_READ_CUSTOM_PROPERTIES_FROM_JSON(b2dJsonImage)
IMPLEMENT_READ_CUSTOM_PROPERTIES_FROM_JSON(b2World)
/////////
void b2dJson::floatToJson(const char* name, float f, Json::Value& value)
{
//cut down on file space for common values
if ( f == 0 )
value[name] = 0;
else if ( f == 1 )
value[name] = 1;
else {
if ( m_useHumanReadableFloats )
value[name] = f;
else
value[name] = floatToHex(f);
}
}
inline void b2dJson::vecToJson(const char* name, unsigned int v, Json::Value& value, int index)
{
if (index > -1)
value[name][index] = v;
else
value[name] = v;
}
void b2dJson::vecToJson(const char *name, float v, Json::Value &value, int index)
{
if (index > -1) {
if ( m_useHumanReadableFloats ) {
value[name][index] = v;
}
else {
if ( v == 0 )
value[name][index] = 0;
else if ( v == 1 )
value[name][index] = 1;
else
value[name][index] = floatToHex(v);
}
}
else
floatToJson(name, v, value);
}
inline void b2dJson::vecToJson(const char* name, b2Vec2 vec, Json::Value& value, int index)
{
if (index > -1) {
if ( m_useHumanReadableFloats ) {
value[name]["x"][index] = vec.x;
value[name]["y"][index] = vec.y;
}
else {
if ( vec.x == 0 )
value[name]["x"][index] = 0;
else if ( vec.x == 1 )
value[name]["x"][index] = 1;
else
value[name]["x"][index] = floatToHex(vec.x);
if ( vec.y == 0 )
value[name]["y"][index] = 0;
else if ( vec.y == 1 )
value[name]["y"][index] = 1;
else
value[name]["y"][index] = floatToHex(vec.y);
}
}
else {
if ( vec.x == 0 && vec.y == 0 )
value[name] = 0;//cut down on file space for common values
else {
floatToJson("x", vec.x, value[name]);
floatToJson("y", vec.y, value[name]);
}
}
}
void b2dJson::clear()
{
m_indexToBodyMap.clear();
m_bodyToIndexMap.clear();
m_jointToIndexMap.clear();
m_bodies.clear();
m_joints.clear();
m_images.clear();
m_bodyToNameMap.clear();
m_fixtureToNameMap.clear();
m_jointToNameMap.clear();
m_imageToNameMap.clear();
}
b2World *b2dJson::readFromValue(Json::Value worldValue)
{
clear();
return j2b2World(worldValue);
}
b2World* b2dJson::readFromString(std::string str, std::string& errorMsg)
{
Json::Value worldValue;
Json::Reader reader;
if ( ! reader.parse(str, worldValue) )
{
//std::cout << "Failed to parse string\n" << reader.getFormattedErrorMessages();
errorMsg = string("Failed to parse JSON:\n") + reader.getFormatedErrorMessages();
return NULL;
}
return j2b2World(worldValue);
}
b2World* b2dJson::readFromFile(const char* filename, std::string& errorMsg)
{
if (!filename)
return NULL;
std::ifstream ifs;
ifs.open(filename, std::ios::in);
if (!ifs) {
//std::cout << "Could not open file " << filename << " for reading\n";
errorMsg = string("Could not open file '") + string(filename) + string("' for reading");
return NULL;
}
Json::Value worldValue;
Json::Reader reader;
if ( ! reader.parse(ifs, worldValue) )
{
//std::cout << "Failed to parse " << filename << std::endl << reader.getFormattedErrorMessages();
errorMsg = string("Failed to parse '") + string(filename) + string("' : ") + reader.getFormatedErrorMessages();
ifs.close();
return NULL;
}
ifs.close();
return j2b2World(worldValue);
}
b2World* b2dJson::j2b2World(Json::Value worldValue)
{
m_bodies.clear();
b2World* world = new b2World( jsonToVec("gravity", worldValue) );
world->SetAllowSleeping( worldValue["allowSleep"].asBool() );
world->SetAutoClearForces( worldValue["autoClearForces"].asBool() );
world->SetWarmStarting( worldValue["warmStarting"].asBool() );
world->SetContinuousPhysics( worldValue["continuousPhysics"].asBool() );
world->SetSubStepping( worldValue["subStepping"].asBool() );
readCustomPropertiesFromJson(world, worldValue);
//bool recreationMayDiffer = false; //hahaha
//if ( ! world->GetAutoClearForces() ) { std::cout << "Note: world is not set to auto clear forces.\n"; recreationMayDiffer = true; }
//if ( world->GetWarmStarting() ) { std::cout << "Note: world is set to use warm starting.\n"; recreationMayDiffer = true; }
//if ( world->GetContinuousPhysics() ) { std::cout << "Note: world is set to use continuous physics.\n"; recreationMayDiffer = true; }
//if ( world->GetSubStepping() ) { std::cout << "Note: world is set to use sub stepping.\n"; recreationMayDiffer = true; }
//if ( worldValue["hasDestructionListener"].asBool() ) { std::cout << "Note: world originally had a destruction listener set.\n"; recreationMayDiffer = true; }
//if ( worldValue["hasContactFilter"].asBool() ) { std::cout << "Note: world originally had a contact filter set.\n"; recreationMayDiffer = true; }
//if ( worldValue["hasContactListener"].asBool() ) { std::cout << "Note: world originally had a contact listener set.\n"; recreationMayDiffer = true; }
//if ( recreationMayDiffer )
// std::cout << "Recreated behaviour may differ from original.\n";
int i = 0;
Json::Value bodyValue = worldValue["body"][i];
while ( !bodyValue.isNull() ) {
b2Body* body = j2b2Body(world, bodyValue);
readCustomPropertiesFromJson(body, bodyValue);
m_bodies.push_back(body);
m_indexToBodyMap[i] = body;
i++;
bodyValue = worldValue["body"][i];
}
//need two passes for joints because gear joints reference other joints
i = 0;
Json::Value jointValue = worldValue["joint"][i++];
while ( !jointValue.isNull() ) {
if ( jointValue["type"].asString() != "gear" ) {
b2Joint* joint = j2b2Joint(world, jointValue);
readCustomPropertiesFromJson(joint, jointValue);
m_joints.push_back(joint);
}
jointValue = worldValue["joint"][i++];
}
i = 0;
jointValue = worldValue["joint"][i++];
while ( !jointValue.isNull() ) {
if ( jointValue["type"].asString() == "gear" ) {
b2Joint* joint = j2b2Joint(world, jointValue);
readCustomPropertiesFromJson(joint, jointValue);
m_joints.push_back(joint);
}
jointValue = worldValue["joint"][i++];
}
i = 0;
Json::Value imageValue = worldValue["image"][i++];
while ( !imageValue.isNull() ) {
b2dJsonImage* img = j2b2dJsonImage(imageValue);
readCustomPropertiesFromJson(img, imageValue);
m_images.push_back(img);
addImage(img);
imageValue = worldValue["image"][i++];
}
return world;
}
b2Body* b2dJson::j2b2Body(b2World* world, Json::Value bodyValue)
{
b2Body* body = NULL;
b2BodyDef bodyDef;
bodyDef.type = (b2BodyType)bodyValue["type"].asInt();
bodyDef.position = jsonToVec("position", bodyValue);
bodyDef.angle = jsonToFloat("angle", bodyValue );
bodyDef.linearVelocity = jsonToVec("linearVelocity", bodyValue);
bodyDef.angularVelocity = jsonToFloat("angularVelocity", bodyValue);
bodyDef.linearDamping = jsonToFloat("linearDamping", bodyValue, -1, 0);
bodyDef.angularDamping = jsonToFloat("angularDamping", bodyValue, -1, 0);
bodyDef.gravityScale = jsonToFloat("gravityScale", bodyValue, -1, 1);
bodyDef.allowSleep = bodyValue.get("allowSleep",true).asBool();
bodyDef.awake = bodyValue.get("awake", false).asBool();
bodyDef.fixedRotation = bodyValue.get("fixedRotation",false).asBool();
bodyDef.bullet = bodyValue.get("bullet",false).asBool();
bodyDef.active = bodyValue.get("active",true).asBool();
body = world->CreateBody(&bodyDef);
string bodyName = bodyValue.get("name","").asString();
if ( bodyName != "" ) {
//printf("Found named body: %s\n",bodyName.c_str());
setBodyName(body, bodyName.c_str());
}
int i = 0;
Json::Value fixtureValue = bodyValue["fixture"][i++];
while ( !fixtureValue.isNull() ) {
b2Fixture* fixture = j2b2Fixture(body, fixtureValue);
readCustomPropertiesFromJson(fixture, fixtureValue);
fixtureValue = bodyValue["fixture"][i++];
}
//may be necessary if user has overridden mass characteristics
b2MassData massData;
massData.mass = jsonToFloat("massData-mass", bodyValue);
massData.center = jsonToVec("massData-center", bodyValue);
massData.I = jsonToFloat("massData-I", bodyValue);
body->SetMassData(&massData);
return body;
}
b2Fixture* b2dJson::j2b2Fixture(b2Body* body, Json::Value fixtureValue)
{
b2Fixture* fixture = NULL;
b2FixtureDef fixtureDef;
fixtureDef.restitution = jsonToFloat("restitution", fixtureValue);
fixtureDef.friction = jsonToFloat("friction", fixtureValue);
fixtureDef.density = jsonToFloat("density", fixtureValue);
fixtureDef.isSensor = fixtureValue.get("sensor",false).asBool();
fixtureDef.filter.categoryBits = fixtureValue.get("filter-categoryBits",0x0001).asInt();
fixtureDef.filter.maskBits = fixtureValue.get("filter-maskBits",0xffff).asInt();
fixtureDef.filter.groupIndex = fixtureValue.get("filter-groupIndex",0).asInt();
if ( fixtureValue.isNull() )
return NULL;
if ( !fixtureValue["circle"].isNull() ) {
b2CircleShape circleShape;
circleShape.m_radius = jsonToFloat("radius", fixtureValue["circle"]);
circleShape.m_p = jsonToVec("center", fixtureValue["circle"]);
fixtureDef.shape = &circleShape;
fixture = body->CreateFixture(&fixtureDef);
}
else if ( !fixtureValue["edge"].isNull() ) {
b2EdgeShape edgeShape;
edgeShape.m_vertex1 = jsonToVec("vertex1", fixtureValue["edge"]);
edgeShape.m_vertex2 = jsonToVec("vertex2", fixtureValue["edge"]);
edgeShape.m_hasVertex0 = fixtureValue["edge"].get("hasVertex0",false).asBool();
edgeShape.m_hasVertex3 = fixtureValue["edge"].get("hasVertex3",false).asBool();
if ( edgeShape.m_hasVertex0 )
edgeShape.m_vertex0 = jsonToVec("vertex0", fixtureValue["edge"]);
if ( edgeShape.m_hasVertex3 )
edgeShape.m_vertex3 = jsonToVec("vertex3", fixtureValue["edge"]);
fixtureDef.shape = &edgeShape;
fixture = body->CreateFixture(&fixtureDef);
}
else if ( !fixtureValue["loop"].isNull() ) { //support old format (r197)
b2ChainShape chainShape;
int numVertices = fixtureValue["loop"]["vertices"]["x"].size();
b2Vec2* vertices = new b2Vec2[numVertices];
for (int i = 0; i < numVertices; i++)
vertices[i] = jsonToVec("vertices", fixtureValue["loop"], i);
chainShape.CreateLoop(vertices, numVertices);
fixtureDef.shape = &chainShape;
fixture = body->CreateFixture(&fixtureDef);
delete[] vertices;
}
else if ( !fixtureValue["chain"].isNull() ) {
b2ChainShape chainShape;
int numVertices = fixtureValue["chain"]["vertices"]["x"].size();
b2Vec2* vertices = new b2Vec2[numVertices];
for (int i = 0; i < numVertices; i++)
vertices[i] = jsonToVec("vertices", fixtureValue["chain"], i);
chainShape.CreateChain(vertices, numVertices);
chainShape.m_hasPrevVertex = fixtureValue["chain"].get("hasPrevVertex",false).asBool();
chainShape.m_hasNextVertex = fixtureValue["chain"].get("hasNextVertex",false).asBool();
if ( chainShape.m_hasPrevVertex )
chainShape.m_prevVertex = jsonToVec("prevVertex", fixtureValue["chain"]);
if ( chainShape.m_hasNextVertex )
chainShape.m_nextVertex = jsonToVec("nextVertex", fixtureValue["chain"]);
fixtureDef.shape = &chainShape;
fixture = body->CreateFixture(&fixtureDef);
delete[] vertices;
}
else if ( !fixtureValue["polygon"].isNull() ) {
b2Vec2 vertices[b2_maxPolygonVertices];
int numVertices = fixtureValue["polygon"]["vertices"]["x"].size();
if ( numVertices > b2_maxPolygonVertices ) {
std::cout << "Ignoring polygon fixture with too many vertices.\n";
}
else if ( numVertices < 2 ) {
std::cout << "Ignoring polygon fixture less than two vertices.\n";
}
else if ( numVertices == 2 ) {
std::cout << "Creating edge shape instead of polygon with two vertices.\n";
b2EdgeShape edgeShape;
edgeShape.m_vertex1 = jsonToVec("vertices", fixtureValue["polygon"], 0);
edgeShape.m_vertex2 = jsonToVec("vertices", fixtureValue["polygon"], 1);
fixtureDef.shape = &edgeShape;
fixture = body->CreateFixture(&fixtureDef);
}
else {
b2PolygonShape polygonShape;
for (int i = 0; i < numVertices; i++)
vertices[i] = jsonToVec("vertices", fixtureValue["polygon"], i);
polygonShape.Set(vertices, numVertices);
fixtureDef.shape = &polygonShape;
fixture = body->CreateFixture(&fixtureDef);
}
}
string fixtureName = fixtureValue.get("name","").asString();
if ( fixtureName != "" ) {
setFixtureName(fixture, fixtureName.c_str());
}
return fixture;
}
b2Joint* b2dJson::j2b2Joint(b2World* world, Json::Value jointValue)
{
b2Joint* joint = NULL;
int bodyIndexA = jointValue["bodyA"].asInt();
int bodyIndexB = jointValue["bodyB"].asInt();
if ( bodyIndexA >= (int)m_bodies.size() || bodyIndexB >= (int)m_bodies.size() )
return NULL;
//keep these in scope after the if/else below
b2RevoluteJointDef revoluteDef;
b2PrismaticJointDef prismaticDef;
b2DistanceJointDef distanceDef;
b2PulleyJointDef pulleyDef;
b2MouseJointDef mouseDef;
b2GearJointDef gearDef;
b2WheelJointDef wheelDef;
//b2MotorJointDef motorDef;
b2WeldJointDef weldDef;
b2FrictionJointDef frictionDef;
b2RopeJointDef ropeDef;
//will be used to select one of the above to work with
b2JointDef* jointDef = NULL;
b2Vec2 mouseJointTarget;
std::string type = jointValue["type"].asString();
if ( type == "revolute" )
{
jointDef = &revoluteDef;
revoluteDef.localAnchorA = jsonToVec("anchorA", jointValue);
revoluteDef.localAnchorB = jsonToVec("anchorB", jointValue);
revoluteDef.referenceAngle = jsonToFloat("refAngle", jointValue);
revoluteDef.enableLimit = jointValue["enableLimit"].asBool();
revoluteDef.lowerAngle = jsonToFloat("lowerLimit", jointValue);
revoluteDef.upperAngle = jsonToFloat("upperLimit", jointValue);
revoluteDef.enableMotor = jointValue["enableMotor"].asBool();
revoluteDef.motorSpeed = jsonToFloat("motorSpeed", jointValue);
revoluteDef.maxMotorTorque = jsonToFloat("maxMotorTorque", jointValue);
}
else if ( type == "prismatic" )
{
jointDef = &prismaticDef;
prismaticDef.localAnchorA = jsonToVec("anchorA", jointValue);
prismaticDef.localAnchorB = jsonToVec("anchorB", jointValue);
if ( !jointValue["localAxisA"].isNull() )
prismaticDef.localAxisA = jsonToVec("localAxisA", jointValue);
else
prismaticDef.localAxisA = jsonToVec("localAxis1", jointValue);
prismaticDef.referenceAngle = jsonToFloat("refAngle", jointValue);
prismaticDef.enableLimit = jointValue["enableLimit"].asBool();
prismaticDef.lowerTranslation = jsonToFloat("lowerLimit", jointValue);
prismaticDef.upperTranslation = jsonToFloat("upperLimit", jointValue);
prismaticDef.enableMotor = jointValue["enableMotor"].asBool();
prismaticDef.motorSpeed = jsonToFloat("motorSpeed", jointValue);
prismaticDef.maxMotorForce = jsonToFloat("maxMotorForce", jointValue);
}
else if ( type == "distance" )
{
jointDef = &distanceDef;
distanceDef.localAnchorA = jsonToVec("anchorA", jointValue);
distanceDef.localAnchorB = jsonToVec("anchorB", jointValue);
distanceDef.length = jsonToFloat("length", jointValue);
distanceDef.frequencyHz = jsonToFloat("frequency", jointValue);
distanceDef.dampingRatio = jsonToFloat("dampingRatio", jointValue);
}
else if ( type == "pulley" )
{
jointDef = &pulleyDef;
pulleyDef.groundAnchorA = jsonToVec("groundAnchorA", jointValue);
pulleyDef.groundAnchorB = jsonToVec("groundAnchorB", jointValue);
pulleyDef.localAnchorA = jsonToVec("anchorA", jointValue);
pulleyDef.localAnchorB = jsonToVec("anchorB", jointValue);
pulleyDef.lengthA = jsonToFloat("lengthA", jointValue);
pulleyDef.lengthB = jsonToFloat("lengthB", jointValue);
pulleyDef.ratio = jsonToFloat("ratio", jointValue);
}
else if ( type == "mouse" )
{
jointDef = &mouseDef;
mouseJointTarget = jsonToVec("target", jointValue);
mouseDef.target = jsonToVec("anchorB", jointValue);//alter after creating joint
mouseDef.maxForce = jsonToFloat("maxForce", jointValue);
mouseDef.frequencyHz = jsonToFloat("frequency", jointValue);
mouseDef.dampingRatio = jsonToFloat("dampingRatio", jointValue);
}
else if ( type == "gear" )
{
jointDef = &gearDef;
int jointIndex1 = jointValue["joint1"].asInt();
int jointIndex2 = jointValue["joint2"].asInt();
gearDef.joint1 = m_joints[jointIndex1];
gearDef.joint2 = m_joints[jointIndex2];
gearDef.ratio = jsonToFloat("ratio", jointValue);
}
else if ( type == "wheel" )
{
jointDef = &wheelDef;
wheelDef.localAnchorA = jsonToVec("anchorA", jointValue);
wheelDef.localAnchorB = jsonToVec("anchorB", jointValue);
wheelDef.localAxisA = jsonToVec("localAxisA", jointValue);
wheelDef.enableMotor = jointValue["enableMotor"].asBool();
wheelDef.motorSpeed = jsonToFloat("motorSpeed", jointValue);
wheelDef.maxMotorTorque = jsonToFloat("maxMotorTorque", jointValue);
wheelDef.frequencyHz = jsonToFloat("springFrequency", jointValue);
wheelDef.dampingRatio = jsonToFloat("springDampingRatio", jointValue);
}
//else if ( type == "motor" )
//{
// jointDef = &motorDef;
// motorDef.linearOffset = jsonToVec("anchorA", jointValue);//editor uses anchorA as the linear offset
// motorDef.angularOffset = jsonToFloat("refAngle", jointValue);
// motorDef.maxForce = jsonToFloat("maxForce", jointValue);
// motorDef.maxTorque = jsonToFloat("maxTorque", jointValue);
// motorDef.correctionFactor = jsonToFloat("correctionFactor", jointValue);
//}
else if ( type == "weld" )
{
jointDef = &weldDef;
weldDef.localAnchorA = jsonToVec("anchorA", jointValue);
weldDef.localAnchorB = jsonToVec("anchorB", jointValue);
weldDef.referenceAngle = jsonToFloat("refAngle", jointValue);
weldDef.frequencyHz = jsonToFloat("frequency", jointValue);
weldDef.dampingRatio = jsonToFloat("dampingRatio", jointValue);
}
else if ( type == "friction" )
{
jointDef = &frictionDef;
frictionDef.localAnchorA = jsonToVec("anchorA", jointValue);
frictionDef.localAnchorB = jsonToVec("anchorB", jointValue);
frictionDef.maxForce = jsonToFloat("maxForce", jointValue);
frictionDef.maxTorque = jsonToFloat("maxTorque", jointValue);
}
else if ( type == "rope" )
{
jointDef = &ropeDef;
ropeDef.localAnchorA = jsonToVec("anchorA", jointValue);
ropeDef.localAnchorB = jsonToVec("anchorB", jointValue);
ropeDef.maxLength = jsonToFloat("maxLength", jointValue);
}
if ( jointDef ) {
//set features common to all joints
jointDef->bodyA = m_bodies[bodyIndexA];
jointDef->bodyB = m_bodies[bodyIndexB];
jointDef->collideConnected = jointValue.get("collideConnected",false).asBool();
joint = world->CreateJoint(jointDef);
if ( type == "mouse" )
((b2MouseJoint*)joint)->SetTarget(mouseJointTarget);
string jointName = jointValue.get("name","").asString();
if ( jointName != "" ) {
setJointName(joint, jointName.c_str());
}
}
return joint;
}
b2dJsonImage* b2dJson::j2b2dJsonImage(Json::Value imageValue)
{
b2dJsonImage* img = new b2dJsonImage();
if ( imageValue["body"].isInt() )
img->body = lookupBodyFromIndex( imageValue["body"].asInt() );
if ( imageValue["name"].isString() ) {
img->name = imageValue["name"].asString();
setImageName(img, img->name.c_str());
}
if ( imageValue["file"].isString() )
img->file = imageValue["file"].asString();
img->center = jsonToVec("center", imageValue);
img->angle = jsonToFloat("angle", imageValue);
img->scale = jsonToFloat("scale", imageValue);
img->opacity = jsonToFloat("opacity", imageValue);
img->renderOrder = jsonToFloat("renderOrder", imageValue);
if ( imageValue.isMember("colorTint") ) {
for (int i = 0; i < 4; i++) {
if ( imageValue["colorTint"][i].isInt() )
img->colorTint[i] = imageValue["colorTint"][i].asInt();
}
}
if ( imageValue["flip"].isBool() )
img->flip = imageValue["flip"].asBool();
if ( imageValue["filter"].isInt() )
img->filter = imageValue["filter"].asInt();
for (int i = 0; i < 4; i++)
img->corners[i] = jsonToVec("corners", imageValue, i);
if ( imageValue["glVertexPointer"].isArray() && imageValue["glTexCoordPointer"].isArray() &&
(imageValue["glVertexPointer"].size() == imageValue["glTexCoordPointer"].size()) ) {
int numFloats = imageValue["glVertexPointer"].size();
img->numPoints = numFloats / 2;
img->points = new float[numFloats];
img->uvCoords = new float[numFloats];
for (int i = 0; i < numFloats; i++) {
img->points[i] = jsonToFloat("glVertexPointer", imageValue, i);
img->uvCoords[i] = jsonToFloat("glTexCoordPointer", imageValue, i);
}
}
if ( imageValue["glDrawElements"].isArray() ) {
img->numIndices = imageValue["glDrawElements"].size();
img->indices = new unsigned short[img->numIndices];
for (int i = 0; i < img->numIndices; i++)
img->indices[i] = imageValue["glDrawElements"][i].asInt();
}
sysLog.Log("Checking for file.....");
sysLog.Log("In b2dJsonImage* b2dJson::j2b2dJsonImage(Json::Value imageValue)");
if(!img->fileExists(&img->file))
{
sysLog.Log(img->file+" = File does not exist");
}
return img;
}
float b2dJson::jsonToFloat(const char* name, Json::Value& value, int index, float defaultValue)
{
if ( ! value.isMember(name) )
return defaultValue;
if ( index > -1 ) {
if ( value[name][index].isNull() )
return defaultValue;
else if ( value[name][index].isInt() )
return value[name][index].asInt();//usually 0 or 1
else if ( value[name][index].isString() )
return hexToFloat( value[name][index].asString() );
else
return value[name][index].asFloat();
}
else {
if ( value[name].isNull() )
return defaultValue;
else if ( value[name].isInt() )
return value[name].asInt();//usually 0 or 1
else if ( value[name].isString() )
return hexToFloat( value[name].asString() );
else
return value[name].asFloat();
}
}
b2Vec2 b2dJson::jsonToVec(const char* name, Json::Value& value, int index, b2Vec2 defaultValue)
{
b2Vec2 vec = defaultValue;
if ( ! value.isMember(name) )
return defaultValue;
if (index > -1) {
if ( value[name]["x"][index].isInt() ) //usually 0 or 1
vec.x = value[name]["x"][index].asInt();
else if ( value[name]["x"][index].isString() )
vec.x = hexToFloat(value[name]["x"][index].asString());
else
vec.x = value[name]["x"][index].asFloat();
if ( value[name]["y"][index].isInt() ) //usually 0 or 1
vec.y = value[name]["y"][index].asInt();
else if ( value[name]["y"][index].isString() )
vec.y = hexToFloat(value[name]["y"][index].asString());
else
vec.y = value[name]["y"][index].asFloat();
}
else {
if ( value[name].isInt() ) //zero vector
vec.Set(0,0);
else {
vec.x = jsonToFloat("x", value[name]);
vec.y = jsonToFloat("y", value[name]);
}
}
return vec;
}
std::string b2dJson::floatToHex(float f)
{
char buf[16];
//sprintf(buf, "%08X", *((int*)(&f)) ); dereferencing type-punned pointer will break strict-aliasing rules
int* i = (int*)(&f);
sprintf(buf, "%08X", *i );
return std::string(buf);
}
float b2dJson::hexToFloat(std::string str)
{
int strLen = 8;//32 bit float
unsigned char bytes[4];
int bptr = (strLen / 2) - 1;
for (int i = 0; i < strLen; i++){
unsigned char c;
c = str[i];
if (c > '9') c -= 7;
c <<= 4;
bytes[bptr] = c;
++i;
c = str[i];
if (c > '9') c -= 7;
c -= '0';
bytes[bptr] |= c;
--bptr;
}
//return *((float*)bytes); dereferencing type-punned pointer will break strict-aliasing rules
float* f = (float*)bytes;
return *f;
}
b2Body* b2dJson::lookupBodyFromIndex( unsigned int index )
{
std::map<int,b2Body*>::iterator it = m_indexToBodyMap.find(index);
if ( it != m_indexToBodyMap.end() )
return it->second;
else
return NULL;
}
int b2dJson::lookupBodyIndex( b2Body* body )
{
std::map<b2Body*,int>::iterator it = m_bodyToIndexMap.find(body);
if ( it != m_bodyToIndexMap.end() )
return it->second;
else
return -1;
}
int b2dJson::lookupJointIndex( b2Joint* joint )
{
std::map<b2Joint*,int>::iterator it = m_jointToIndexMap.find(joint);
if ( it != m_jointToIndexMap.end() )
return it->second;
else
return -1;
}
string b2dJson::getBodyName(b2Body* body)
{
map<b2Body*,string>::iterator it = m_bodyToNameMap.find( body );
if ( it == m_bodyToNameMap.end() )
return "";
return it->second;
}
string b2dJson::getFixtureName(b2Fixture* fixture)
{
map<b2Fixture*,string>::iterator it = m_fixtureToNameMap.find( fixture );
if ( it == m_fixtureToNameMap.end() )
return "";
return it->second;
}
string b2dJson::getJointName(b2Joint* joint)
{
map<b2Joint*,string>::iterator it = m_jointToNameMap.find( joint );
if ( it == m_jointToNameMap.end() )
return "";
return it->second;
}
string b2dJson::getImageName(b2dJsonImage *img)
{
map<b2dJsonImage*,string>::iterator it = m_imageToNameMap.find( img );
if ( it == m_imageToNameMap.end() )
return "";
return it->second;
}
int b2dJson::getBodiesByName(string name, vector<b2Body*>& bodies)
{
map<b2Body*,string>::iterator it = m_bodyToNameMap.begin();
map<b2Body*,string>::iterator end = m_bodyToNameMap.end();
while (it != end) {
if ( it->second == name )
bodies.push_back(it->first);
++it;
}
return bodies.size();
}
int b2dJson::getFixturesByName(string name, vector<b2Fixture*>& fixtures)
{
map<b2Fixture*,string>::iterator it = m_fixtureToNameMap.begin();
map<b2Fixture*,string>::iterator end = m_fixtureToNameMap.end();
while (it != end) {
if ( it->second == name )
fixtures.push_back(it->first);
++it;
}
return fixtures.size();
}
int b2dJson::getJointsByName(string name, vector<b2Joint*>& joints)
{
map<b2Joint*,string>::iterator it = m_jointToNameMap.begin();
map<b2Joint*,string>::iterator end = m_jointToNameMap.end();
while (it != end) {
if ( it->second == name )
joints.push_back(it->first);
++it;
}
return joints.size();
}
int b2dJson::getImagesByName(string name, vector<b2dJsonImage*> &images)
{
map<b2dJsonImage*,string>::iterator it = m_imageToNameMap.begin();
map<b2dJsonImage*,string>::iterator end = m_imageToNameMap.end();
while (it != end) {
if ( it->second == name )
images.push_back(it->first);
++it;
}
return images.size();
}
int b2dJson::getAllImages(vector<b2dJsonImage*> &images)
{
images.insert( images.begin(), m_images.begin(), m_images.end() );
std::sort(images.begin(), images.end(), b2dJsonImage_renderOrder_ascending);
return images.size();
}
b2Body* b2dJson::getBodyByName(string name)
{
map<b2Body*,string>::iterator it = m_bodyToNameMap.begin();
map<b2Body*,string>::iterator end = m_bodyToNameMap.end();
while (it != end) {
if ( it->second == name )
return it->first;
++it;
}
return NULL;
}
b2Fixture* b2dJson::getFixtureByName(string name)
{
map<b2Fixture*,string>::iterator it = m_fixtureToNameMap.begin();
map<b2Fixture*,string>::iterator end = m_fixtureToNameMap.end();
while (it != end) {
if ( it->second == name )
return it->first;
++it;
}
return NULL;
}
b2Joint* b2dJson::getJointByName(string name)
{
map<b2Joint*,string>::iterator it = m_jointToNameMap.begin();
map<b2Joint*,string>::iterator end = m_jointToNameMap.end();
while (it != end) {
if ( it->second == name )
return it->first;
++it;
}
return NULL;
}
b2dJsonImage* b2dJson::getImageByName(string name)
{
map<b2dJsonImage*,string>::iterator it = m_imageToNameMap.begin();
map<b2dJsonImage*,string>::iterator end = m_imageToNameMap.end();
while (it != end) {
if ( it->second == name )
return it->first;
++it;
}
return NULL;
}
#include "PhysicsEdgeActor.h"
PhysicsEdgeActor::PhysicsEdgeActor(void)
{
this->_shapeType = SHAPETYPE_EDGE;
this->_edge = b2EdgeShape();
PhysicsActor::SetShapeType(SHAPETYPE_EDGE);
}
PhysicsEdgeActor::~PhysicsEdgeActor(void)
{
if( _physBody != NULL )
{
_physBody->SetUserData(NULL);
theWorld.GetPhysicsWorld().DestroyBody(_physBody);
}
}
void PhysicsEdgeActor::Set(b2Vec2 v1, b2Vec2 v2)
{
_edge.Set(v1, v2);
}
void PhysicsEdgeActor::Set(b2EdgeShape edge)
{
this->_edge = edge;
}
b2EdgeShape PhysicsEdgeActor::GetB2EdgeShape()
{
return this->_edge;
}
void PhysicsActor::InitPhysics()
{
//todo:add specific init logic for additional shapes (see eShapeType for shapes)
if (!theWorld.IsPhysicsSetUp())
{
sysLog.Log("ERROR: World physics must be initialized before Actor's.");
return;
}
this->_shapeType = SHAPETYPE_EDGE;
b2Shape* shape = NULL;
b2FixtureDef fixtureDef;
fixtureDef.shape = shape;
fixtureDef.density = _density;
fixtureDef.friction = _friction;
fixtureDef.restitution = _restitution;
fixtureDef.filter.groupIndex = _groupIndex;
fixtureDef.isSensor = _isSensor;
InitShape( shape );
b2BodyDef bd;
bd.userData = this;
bd.position.Set(_position.X, _position.Y);
bd.angle = MathUtil::ToRadians(_rotation);
bd.fixedRotation = _fixedRotation;
if (MathUtil::FuzzyEquals(_density, 0.0f))
{
bd.type = b2_staticBody;
}
else
{
bd.type = b2_dynamicBody;
}
_physBody = theWorld.GetPhysicsWorld().CreateBody(&bd);
_physBody->CreateFixture(&fixtureDef);
_physBody->SetUserData(this);
CustomInitPhysics();
}
#pragma once
#include "../Actors/PhysicsActor.h"
#include "../Infrastructure/World.h"
#include "../Infrastructure/Log.h"
#include "../Util/MathUtil.h"
#include <Box2D/Box2D.h>
struct b2ShapeDef;
class PhysicsEdgeActor:public PhysicsActor
{
public:
PhysicsEdgeActor(void);
void InitPhysics();
virtual void CustomInitPhysics();
virtual const String GetClassName() const { return "PhysicsEdgeActor"; }
b2Vec2 GetVertexAt(int index);
void SetVertexAt(int index, );
b2Vec2 GetFirstVertex();
b2Vec2 GetLastVertex();
void Set(b2Vec2 start, b2Vec2 end);
void Set(b2EdgeShape edge);
b2EdgeShape GetB2EdgeShape();
~PhysicsEdgeActor(void);
private:
friend class World;
b2EdgeShape _edge;
void _syncPosRot(float x, float y, float rotation);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment