Newer
Older
AlgebraicDataflowArchitectureModel / GameEngine / src / main / java / gameEngine / simulator / interfaces / GameEnginePresenter.java
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);
	}
}