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.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.INativeReceiver;

public class GameEnginePresenter implements INativeReceiver {
	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);
	}

	@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) {
									JsonTerm position = (JsonTerm) positionExp;
									JsonTerm rotation = (JsonTerm) rotationExp;
									JsonTerm scale = (JsonTerm) scaleExp;
									GameObject gameObj = new GameObject(newEid);//新しいIDが必要あり
									gameObj.transform.setPosition(Float.parseFloat(position.get("x").toString()), 
																	Float.parseFloat(position.get("y").toString()), 
																	Float.parseFloat(position.get("z").toString()));
									gameObj.transform.setRotation(Float.parseFloat(rotation.get("x").toString()), 
																	Float.parseFloat(rotation.get("y").toString()), 
																	Float.parseFloat(rotation.get("z").toString()));
									gameObj.transform.setScale(Float.parseFloat(scale.get("x").toString()), 
																Float.parseFloat(scale.get("y").toString()), 
																Float.parseFloat(scale.get("z").toString()));
									Expression type = mesh.get("type");
									if (type.toString().equals("\"sprite\"")) {
										String texturePath = mesh.get("sprite").toString().replace("\"", "");
										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(newEid, meshResource);
									}
									scene.addEntity(newEid, gameObj);
									
									// Connect game entity and model.
									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(newEid, 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(newEid, 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(newEid, scaleResource);
								}
							}
						}
					}
				}
			}
		}
	}
}