package gameEngine.simulator.interfaces;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import gameEngine.entites.*;
import gameEngine.entites.gameComponents.*;
import gameEngine.scenes.Scene;
import gameEngine.views.Sprite;
import models.algebra.Expression;
import models.algebra.Term;
import models.algebra.Constant;
import models.dataConstraintModel.JsonTerm;
import models.dataConstraintModel.MapTerm;
import models.dataFlowModel.DataTransferChannel;
import simulator.Event;
import simulator.Resource;
import simulator.Simulator;
import simulator.SystemState;
import simulator.interfaces.INativeInitializer;
import simulator.interfaces.INativeReceiver;
public class GameEnginePresenter implements INativeReceiver, INativeInitializer {
public final String sceneUpdateChannelName = "SceneUpdate";
public final String cameraPositionUpdateChannelName = "CameraPositionUpdate";
public final String cameraRotationUpdateChannelName = "CameraRotationUpdate";
public final String cameraScaleUpdateChannelName = "CameraScaleUpdate";
public final String cameraProjectionUpdateChannelName = "CameraProjectionUpdate";
public final String entityPositionUpdateChannelName = "EntityPositionUpdate";
public final String entityRotationUpdateChannelName = "EntityRotationUpdate";
public final String entityScaleUpdateChannelName = "EntityScaleUpdate";
public final String spriteUpdateChannelName = "SpriteUpdate";
public final String sceneUpdateEventChannelName = "SceneUpdateEvent";
public final String keyEventChannelName = "KeyEvent";
protected Scene scene;
protected Simulator simulator;
protected DataTransferChannel sceneUpdateChannel;
protected DataTransferChannel cameraPositionUpdateChannel;
protected DataTransferChannel cameraRotationUpdateChannel;
protected DataTransferChannel cameraScaleUpdateChannel;
protected DataTransferChannel cameraProjectionUpdateChannel;
protected DataTransferChannel entityPositionUpdateChannel;
protected DataTransferChannel entityRotationUpdateChannel;
protected DataTransferChannel entityScaleUpdateChannel;
protected DataTransferChannel spriteUpdateChannel;
protected DataTransferChannel sceneUpdateEventChannel;
protected DataTransferChannel keyEventChannel;
protected Map<DataTransferChannel, Map<String, Resource>> channelAndResourcesForEntityReceiving = new HashMap<>();
protected Map<DataTransferChannel, Resource> channelAndResourcesForCameraReceiving = new HashMap<>();
public GameEnginePresenter(Scene scene, Simulator simulator) {
this.scene = scene;
this.simulator = simulator;
sceneUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(sceneUpdateChannelName);
cameraPositionUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(cameraPositionUpdateChannelName);
cameraRotationUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(cameraRotationUpdateChannelName);
cameraScaleUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(cameraScaleUpdateChannelName);
cameraProjectionUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(cameraProjectionUpdateChannelName);
entityPositionUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(entityPositionUpdateChannelName);
entityRotationUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(entityRotationUpdateChannelName);
entityScaleUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(entityScaleUpdateChannelName);
spriteUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(spriteUpdateChannelName);
sceneUpdateEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(sceneUpdateEventChannelName);
keyEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(keyEventChannelName);
simulator.addNativeReceiver(this, sceneUpdateChannel);
simulator.addSystemInitializer(this);
}
@Override
public void onInitFromModel(SystemState initialSystemState) {
Resource sceneResource = initialSystemState.getResource("scene");
if (sceneResource != null) {
Resource entitiesResource = sceneResource.getChildrenMap().get("entities");
if (entitiesResource != null) {
for (Map.Entry<String, Resource> entity: entitiesResource.getChildrenMap().entrySet()) {
String eId = entity.getKey();
Resource entityResource = entity.getValue();
Resource transformResource = entityResource.getChildrenMap().get("transform");
Resource meshResource = entityResource.getChildrenMap().get("mesh");
Resource positionResource = transformResource.getChildrenMap().get("position");
Resource rotationResource = transformResource.getChildrenMap().get("rotation");
Resource scaleResource = transformResource.getChildrenMap().get("scale");
if (meshResource != null && positionResource != null && rotationResource != null && scaleResource != null) {
// Add a game entity to scene.
String px = positionResource.getChildrenMap().get("x").getState().getValue().toString();
String py = positionResource.getChildrenMap().get("y").getState().getValue().toString();
String pz = positionResource.getChildrenMap().get("z").getState().getValue().toString();
String rx = rotationResource.getChildrenMap().get("x").getState().getValue().toString();
String ry = rotationResource.getChildrenMap().get("y").getState().getValue().toString();
String rz = rotationResource.getChildrenMap().get("z").getState().getValue().toString();
String sx = scaleResource.getChildrenMap().get("x").getState().getValue().toString();
String sy = scaleResource.getChildrenMap().get("y").getState().getValue().toString();
String sz = scaleResource.getChildrenMap().get("z").getState().getValue().toString();
String type = (String) ((Constant) meshResource.getChildrenMap().get("type").getState().getValue()).getValue();
String texturePath = (String) ((Constant) meshResource.getChildrenMap().get("sprite").getState().getValue()).getValue();
GameObject gameObj = addGameObjectToScene(eId, meshResource, px, py, pz, rx, ry, rz, sx, sy, sz, type, texturePath);
// Connect game entity and model.
connectGameEntiotyAndModel(eId, gameObj, positionResource, rotationResource, scaleResource);
}
}
}
}
}
@Override
public void onReceiveFromModel(Event event, SystemState nextSystemState) {
Expression message = event.getMessage();
if (message instanceof Term && ((Term) message).getChildren().size() >= 2) {
Expression curScExp = ((Term) message).getChild(0);
Expression nextScExp = ((Term) message).getChild(1);
if (curScExp instanceof JsonTerm && nextScExp instanceof JsonTerm) {
JsonTerm curSc = (JsonTerm) curScExp;
JsonTerm nextSc = (JsonTerm) nextScExp;
Resource sceneResource = nextSystemState.getResource(event.getInputResource().getResourceIdentifier());
Expression cameraExp = nextSc.get("camera");
if (cameraExp != null && cameraExp instanceof JsonTerm) {
// Connect camera and model.
JsonTerm camera = (JsonTerm) cameraExp;
Resource cameraResource = sceneResource.getChildrenMap().get("camera");
Camera cameraObj = scene.getCamera();
Resource cameraTransformResource = cameraResource.getChildrenMap().get("transform");
Resource cameraProjectionResource = cameraResource.getChildrenMap().get("projection");
Resource cameraPositionResource = cameraTransformResource.getChildrenMap().get("position");
Resource cameraRotationResource = cameraTransformResource.getChildrenMap().get("rotation");
Resource cameraScaleResource = cameraTransformResource.getChildrenMap().get("scale");
if (channelAndResourcesForCameraReceiving.get(cameraPositionUpdateChannel) == null) {
CameraPositionReceiver nativePositionReceiver = new CameraPositionReceiver(cameraObj);
simulator.addNativeReceiver(nativePositionReceiver, cameraPositionUpdateChannel, cameraPositionResource);
channelAndResourcesForCameraReceiving.put(cameraPositionUpdateChannel, cameraPositionResource);
}
if (channelAndResourcesForCameraReceiving.get(cameraRotationUpdateChannel) == null) {
CameraRotationReceiver nativeRotationReceiver = new CameraRotationReceiver(cameraObj);
simulator.addNativeReceiver(nativeRotationReceiver, cameraRotationUpdateChannel, cameraRotationResource);
channelAndResourcesForCameraReceiving.put(cameraRotationUpdateChannel, cameraRotationResource);
}
if (channelAndResourcesForCameraReceiving.get(cameraScaleUpdateChannel) == null) {
CameraScaleReceiver nativeScaleReceiver = new CameraScaleReceiver(cameraObj);
simulator.addNativeReceiver(nativeScaleReceiver, cameraScaleUpdateChannel, cameraScaleResource);
channelAndResourcesForCameraReceiving.put(cameraScaleUpdateChannel, cameraScaleResource);
}
if (channelAndResourcesForCameraReceiving.get(cameraProjectionUpdateChannel) == null) {
CameraProjectionReceiver nativeProjectionReceiver = new CameraProjectionReceiver(cameraObj);
simulator.addNativeReceiver(nativeProjectionReceiver, cameraProjectionUpdateChannel, cameraProjectionResource);
channelAndResourcesForCameraReceiving.put(cameraProjectionUpdateChannel, cameraProjectionResource);
}
}
Expression oldEntities = curSc.get("entities");
Expression newEntities = nextSc.get("entities");
Set<String> oldEidSet = new HashSet<>(((MapTerm) oldEntities).keySet());
Set<String> newEidSet = new HashSet<>(((MapTerm) newEntities).keySet());
oldEidSet.removeAll(((MapTerm) newEntities).keySet());
newEidSet.removeAll(((MapTerm) oldEntities).keySet());
if (!oldEidSet.isEmpty() || !newEidSet.isEmpty()) {
// If the set of scene entities is changed.
// Remove old entities and their native receivers.
for (String oldEid: oldEidSet) {
scene.removeEntity(oldEid);
}
for (DataTransferChannel channel: channelAndResourcesForEntityReceiving.keySet()) {
Map<String, Resource> widToResource = channelAndResourcesForEntityReceiving.get(channel);
for (String oldEid: oldEidSet) {
Resource resource = widToResource.remove(oldEid);
if (resource != null) {
simulator.removeNativeReceiver(channel, resource);
}
}
}
// Add new entities.
Resource entitiesResource = sceneResource.getChildrenMap().get("entities");
for (String newEid: newEidSet) {
Expression entityExp = ((MapTerm) newEntities).get(newEid);
if (entityExp instanceof JsonTerm) {
JsonTerm entity = (JsonTerm) entityExp;
Resource entityResource = entitiesResource.getChildrenMap().get(newEid);
Expression transformExp = entity.get("transform");
Expression meshExp = entity.get("mesh");
if (transformExp instanceof JsonTerm && meshExp instanceof JsonTerm) {
JsonTerm transform = (JsonTerm) transformExp;
JsonTerm mesh = (JsonTerm) meshExp;
Resource transformResource = entityResource.getChildrenMap().get("transform");
Resource meshResource = entityResource.getChildrenMap().get("mesh");
Expression positionExp = transform.get("position");
Expression rotationExp = transform.get("rotation");
Expression scaleExp = transform.get("scale");
Resource positionResource = transformResource.getChildrenMap().get("position");
Resource rotationResource = transformResource.getChildrenMap().get("rotation");
Resource scaleResource = transformResource.getChildrenMap().get("scale");
if (positionExp instanceof JsonTerm
&& rotationExp instanceof JsonTerm
&& scaleExp instanceof JsonTerm) {
// Add a game entity to scene.
JsonTerm position = (JsonTerm) positionExp;
JsonTerm rotation = (JsonTerm) rotationExp;
JsonTerm scale = (JsonTerm) scaleExp;
String px = position.get("x").toString();
String py = position.get("y").toString();
String pz = position.get("z").toString();
String rx = rotation.get("x").toString();
String ry = rotation.get("y").toString();
String rz = rotation.get("z").toString();
String sx = scale.get("x").toString();
String sy = scale.get("y").toString();
String sz = scale.get("z").toString();
String type = (String) ((Constant) mesh.get("type")).getValue();
String texturePath = (String) ((Constant) mesh.get("sprite")).getValue();
GameObject gameObj = addGameObjectToScene(newEid, meshResource, px, py, pz, rx, ry, rz, sx, sy, sz, type, texturePath);
// Connect game entity and model.
connectGameEntiotyAndModel(newEid, gameObj, positionResource, rotationResource, scaleResource);
}
}
}
}
}
}
}
}
private GameObject addGameObjectToScene(String eId, Resource meshResource, String px, String py, String pz,
String rx, String ry, String rz, String sx, String sy, String sz, String type, String texturePath) {
GameObject gameObj = new GameObject(eId);//新しいIDが必要あり
gameObj.transform.setPosition(Float.parseFloat(px), Float.parseFloat(py), Float.parseFloat(pz));
gameObj.transform.setRotation(Float.parseFloat(rx), Float.parseFloat(ry), Float.parseFloat(rz));
gameObj.transform.setScale(Float.parseFloat(sx), Float.parseFloat(sy), Float.parseFloat(sz));
if (type.equals("sprite")) {
Mesh meshObj = new Mesh(gameObj, Mesh.MeshType.SPRITE, texturePath);
gameObj.addComponent(meshObj);
SpriteReceiver nativeSpriteReceiver = new SpriteReceiver(meshObj);
simulator.addNativeReceiver(nativeSpriteReceiver, spriteUpdateChannel, meshResource);
Map<String, Resource> resources = channelAndResourcesForEntityReceiving.get(spriteUpdateChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForEntityReceiving.put(spriteUpdateChannel, resources);
}
resources.put(eId, meshResource);
}
scene.addEntity(eId, gameObj);
return gameObj;
}
private void connectGameEntiotyAndModel(String eId, GameObject gameObj, Resource positionResource,
Resource rotationResource, Resource scaleResource) {
EntityPositionReceiver nativePositionReceiver = new EntityPositionReceiver(gameObj);
simulator.addNativeReceiver(nativePositionReceiver, entityPositionUpdateChannel, positionResource);
Map<String, Resource> resources = channelAndResourcesForEntityReceiving.get(entityPositionUpdateChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForEntityReceiving.put(entityPositionUpdateChannel, resources);
}
resources.put(eId, positionResource);
EntityRotationReceiver nativeRotationReceiver = new EntityRotationReceiver(gameObj);
simulator.addNativeReceiver(nativeRotationReceiver, entityRotationUpdateChannel, rotationResource);
resources = channelAndResourcesForEntityReceiving.get(entityRotationUpdateChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForEntityReceiving.put(entityRotationUpdateChannel, resources);
}
resources.put(eId, rotationResource);
EntityScaleReceiver nativeScaleReceiver = new EntityScaleReceiver(gameObj);
simulator.addNativeReceiver(nativeScaleReceiver, entityScaleUpdateChannel, scaleResource);
resources = channelAndResourcesForEntityReceiving.get(entityScaleUpdateChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForEntityReceiving.put(entityScaleUpdateChannel, resources);
}
resources.put(eId, scaleResource);
}
}