/* Copyright 2012 SionEngine
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siondream.core.physics;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.assets.AssetLoaderParameters;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.AsynchronousAssetLoader;
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Filter;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.Shape;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.JsonReader;
import com.badlogic.gdx.utils.JsonValue;
import com.badlogic.gdx.utils.JsonValue.JsonIterator;
import com.badlogic.gdx.utils.Logger;
import com.siondream.core.Env;
public class PhysicsLoader extends AsynchronousAssetLoader<PhysicsData, PhysicsLoader.PhysicsParameter > {
static public class PhysicsParameter extends AssetLoaderParameters<PhysicsData> {}
private Logger logger;
private PhysicsData physicsData = null;
public PhysicsLoader(FileHandleResolver resolver) {
super(resolver);
logger = new Logger("Physics", Env.debugLevel);
}
@Override
public void loadAsync(AssetManager manager, String fileName, FileHandle file, PhysicsParameter parameter) {
physicsData = new PhysicsData();
loadData(fileName, file);
}
@Override
public PhysicsData loadSync(AssetManager manager, String fileName, FileHandle file, PhysicsParameter parameter) {
return physicsData;
}
@SuppressWarnings("rawtypes")
@Override
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, PhysicsParameter parameter) {
return new Array<AssetDescriptor>();
}
private void loadData(String fileName, FileHandle file) {
logger.info("loading " + fileName);
try {
JsonReader reader = new JsonReader();
JsonValue root = reader.parse(file);
loadBodyDef(root);
loadMassData(root);
loadFixtureDefs(root);
} catch (Exception e) {
logger.error("error loading " + fileName + " " + e.getMessage());
}
}
private void loadBodyDef(JsonValue root) {
logger.info("loading BodyDef");
physicsData.bodyDef.bullet = root.getBoolean("bullet", false);
physicsData.bodyDef.active = root.getBoolean("active", true);
physicsData.bodyDef.fixedRotation = root.getBoolean("fixedRotation", false);
physicsData.bodyDef.gravityScale = root.getFloat("gravityScale", 1.0f);
physicsData.bodyDef.linearDamping = root.getFloat("linearDamping", 0.0f);
physicsData.bodyDef.angularDamping = root.getFloat("angularDamping", 0.0f);
String type = root.getString("type", "dynamic");
if (type.equals("dynamic")) {
physicsData.bodyDef.type = BodyDef.BodyType.DynamicBody;
}
else if (type.equals("kynematic")) {
physicsData.bodyDef.type = BodyDef.BodyType.KinematicBody;
}
else if (type.equals("static")) {
physicsData.bodyDef.type = BodyDef.BodyType.KinematicBody;
}
else {
logger.error("unknown body type " + type);
}
}
private void loadMassData(JsonValue root) {
JsonValue massData = root.get("massData");
if (massData != null) {
logger.info("loading mass data");
physicsData.massData.center.x = massData.getFloat("centerX", 0.0f);
physicsData.massData.center.y = massData.getFloat("centerY", 0.0f);
physicsData.massData.I = massData.getFloat("i", 0.0f);
physicsData.massData.mass = massData.getFloat("mass", 1.0f);
}
}
private void loadFixtureDefs(JsonValue root) {
JsonValue fixtures = root.get("fixtures");
JsonIterator fixturesIt = fixtures.iterator();
int index = 0;
while (fixturesIt.hasNext()) {
JsonValue fixture = fixturesIt.next();
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.density = fixture.getFloat("density", 1.0f);
fixtureDef.restitution = fixture.getFloat("restitution", 0.0f);
fixtureDef.friction = fixture.getFloat("friction", 1.0f);
fixtureDef.isSensor = fixture.getBoolean("isSensor", false);
fixtureDef.shape = loadShape(fixture);
loadFilter(fixture, fixtureDef.filter);
String id = fixture.getString("id", "");
logger.info("loading fixture with id " + id);
physicsData.fixtureNames.add(id);
physicsData.fixtureIdx.put(id, index);
physicsData.fixtureDefs.add(fixtureDef);
++index;
}
}
private Filter loadFilter(JsonValue root, Filter filter) {
JsonValue filterValue = root.get("filter");
if (filterValue == null) {
logger.info("no filter for shape, returning default one");
return filter;
}
logger.info("loading filter");
CategoryBitsManager categoryManager = Env.game.getCategoryBitsManager();
filter.categoryBits = categoryManager.getCategoryBits(filterValue.getString("categoryBits", ""));
filter.groupIndex = (short)filterValue.getInt("groupIndex", 0);
filter.maskBits = 0;
JsonValue maskBits = filterValue.get("maskBits");
JsonIterator maskBitsIt = maskBits.iterator();
while (maskBitsIt.hasNext()) {
filter.maskBits |= categoryManager.getCategoryBits(maskBitsIt.next().asString());
}
return filter;
}
private Shape loadShape(JsonValue root) {
Shape shape = null;
JsonValue shapeValue = root.get("shape");
if (shapeValue == null) {
return shape;
}
String type = shapeValue.getString("type");
float x = shapeValue.getFloat("centerX", 0.0f);
float y = shapeValue.getFloat("centerY", 0.0f);
if (type.equals("circle")) {
logger.info("loading cicle shape");
CircleShape circle = new CircleShape();
circle.setPosition(new Vector2(x, y));
circle.setRadius(shapeValue.getFloat("radius", 1.0f));
shape = circle;
}
else if (type.equals("polygon")) {
logger.info("loading polygon shape");
PolygonShape polygon = new PolygonShape();
polygon.setAsBox(shapeValue.getFloat("width", 1.0f),
shapeValue.getFloat("height", 1.0f),
new Vector2(x, y),
0.0f);
shape = polygon;
}
else {
logger.error("shape unknown " + type);
}
return shape;
}
}