package gameEngine;
import algorithms.TypeInference;
import gameEngine.entites.EditorEntity;
import gameEngine.entites.Entity;
import gameEngine.entites.editorComponents.EntityView;
import gameEngine.geometry.Transform;
import gameEngine.scenes.EditorScene;
import gameEngine.scenes.Scene;
import gameEngine.views.Window;
import models.algebra.Constant;
import models.algebra.Expression;
import models.algebra.Variable;
import models.dataConstraintModel.*;
import models.dataFlowModel.DataTransferChannel;
import models.dataFlowModel.DataTransferModel;
import parser.Parser;
import parser.Parser.TokenStream;
import parser.exceptions.*;
import simulator.Event;
import simulator.ResourceIdentifier;
import simulator.Simulator;
import gameEngine.simulator.interfaces.GameEnginePresenter;
import simulator.SystemState;
import simulator.interfaces.timers.TimerService;
import javax.xml.crypto.Data;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class GameEngineModelFileGenerator {
private DataTransferModel model;
private final String modelFilePath = "GameEngine/resources/";
Parser.TokenStream stream = new Parser.TokenStream();
Parser parser = new Parser(stream);
public void generate(){
try {
EditorScene editorScene = (EditorScene) Window.get().getScene();
model = new DataTransferModel();
ResourcePath scene = new ResourcePath("scene"); // "scene"
ResourcePath scene_time = new ResourcePath(scene, "time"); // "scene.time"
ResourcePath scene_camera = new ResourcePath(scene, "camera"); // "scene.camera"
ResourcePath scene_camera_transform = new ResourcePath(scene_camera, "transform"); // "scene.camera.transform"
ResourcePath scene_camera_transform_position = new ResourcePath(scene_camera_transform, "position"); // "scene.camera.transform.position"
ResourcePath scene_camera_transform_rotation = new ResourcePath(scene_camera_transform, "rotation"); // "scene.camera.transform.rotation"
ResourcePath scene_camera_transform_scale = new ResourcePath(scene_camera_transform, "scale"); // "scene.camera.transform.scale"
ResourcePath scene_camera_projection = new ResourcePath(scene_camera, "projection"); // "scene.camera.projection"
ResourcePath entities = new ResourcePath(scene, "entities"); // "scene.entities"
ResourcePath entity = new ResourcePath(entities, new Variable("eid", DataConstraintModel.typeString)); // "scene.entities.{eid}"
ResourcePath entity_transform = new ResourcePath(entity, "transform"); // "scene.entities.{eid}.transform"
ResourcePath entity_transform_position = new ResourcePath(entity_transform, "position"); // "scene.entities.{eid}.transform.position"
ResourcePath entity_transform_rotation = new ResourcePath(entity_transform, "rotation"); // "scene.entities.{eid}.transform.rotation"
ResourcePath entity_transform_scale = new ResourcePath(entity_transform, "scale"); // "scene.entities.{eid}.transform.scale"
ResourcePath entity_mesh = new ResourcePath(entity, "mesh"); // "scene.entities.{eid}.mesh"
ResourcePath keys = new ResourcePath(scene, "keys"); // "scene.keys"
ResourcePath key = new ResourcePath(keys, new Variable("kno", DataConstraintModel.typeInt)); // "scene.keys.{kno}"
ResourcePath key_state = new ResourcePath(key, "state"); // "scene.keys.{kno}.state
ResourcePath timers = new ResourcePath("timers"); // "timers"
ResourcePath timer = new ResourcePath(timers, new Variable("tid", DataConstraintModel.typeString)); // "timers.{tid}"
ResourcePath timer_count = new ResourcePath(timer, "count"); //"timer.{tid}.count
List<ResourcePath> enemy = new ArrayList<>();
List<ResourcePath> enemy_transform = new ArrayList<>();
List<ResourcePath> enemy_transform_position = new ArrayList<>();
List<ResourcePath> enemy_transform_rotation = new ArrayList<>();
List<ResourcePath> enemy_move = new ArrayList<>();
List<ResourcePath> enemy_move_type = new ArrayList<>();
List<ResourcePath> enemy_move_speed = new ArrayList<>();
List<ResourcePath> enemy_eid = new ArrayList<>();
for (int i = 1; i < editorScene.editorEntities.size(); i++) {
EditorEntity editorEntity = (EditorEntity) editorScene.getEditorEntity("" + i);
String id = editorEntity.getId();
ResourcePath e = new ResourcePath("enemy" + id);
ResourcePath et = new ResourcePath(e, "transform");
ResourcePath etp = new ResourcePath(et, "position");
ResourcePath etr = new ResourcePath(et, "rotation");
ResourcePath em = new ResourcePath(e,"move");
ResourcePath emt = new ResourcePath(em,"type");
ResourcePath ems = new ResourcePath(em,"speed");
ResourcePath eid = new ResourcePath(e, "eid");
enemy.add(e);
enemy_transform.add(et);
enemy_transform_position.add(etp);
enemy_transform_rotation.add(etr);
enemy_move.add(em);
enemy_move_type.add(emt);
enemy_move_speed.add(ems);
enemy_eid.add(eid);
}
model.addResourcePath(scene_time);
model.addResourcePath(scene_camera);
model.addResourcePath(scene_camera_transform);
model.addResourcePath(scene_camera_transform_position);
model.addResourcePath(scene_camera_transform_rotation);
model.addResourcePath(scene_camera_transform_scale);
model.addResourcePath(scene_camera_projection);
model.addResourcePath(entity_transform);
model.addResourcePath(entity_transform_position);
model.addResourcePath(entity_transform_rotation);
model.addResourcePath(entity_transform_scale);
model.addResourcePath(entity_mesh);
model.addResourcePath(key_state);
model.addResourcePath(timers);
model.addResourcePath(timer_count);
for (ResourcePath et : enemy_transform) model.addResourcePath(et);
for (ResourcePath etp : enemy_transform) model.addResourcePath(etp);
for (ResourcePath etr : enemy_transform) model.addResourcePath(etr);
for (ResourcePath em : enemy_transform) model.addResourcePath(em);
for (ResourcePath emt : enemy_transform) model.addResourcePath(emt);
for (ResourcePath ems : enemy_transform) model.addResourcePath(ems);
addInit();
addNativeChannel(
new DataTransferChannel("SceneUpdateEvent"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
scene_time,
"time: Long",
"updateEvent(dt: Long)",
"time + dt"
)
);
addNativeChannel(
new DataTransferChannel("SceneUpdate"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
scene,
"curSc: Json",
"update(curSc, nextSc)",
"nextSc"
)
);
addNativeChannel(
new DataTransferChannel("CameraPositionUpdate"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
scene_camera_transform_position,
"curPos: Json",
"updatePosition(nextPos.x, nextPos.y, nextPos.z)",
"nextPos"
)
);
addNativeChannel(
new DataTransferChannel("CameraRotationUpdate"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
scene_camera_transform_rotation,
"curRot: Json",
"updateRotation(nextRot.x, nextRot.y, nextRot.z)",
"nextRot"
)
);
addNativeChannel(
new DataTransferChannel("CameraScaleUpdate"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
scene_camera_transform_scale,
"curScale: Json",
"updateScale(nextScale.x, nextScale.y, nextScale.z)",
"nextScale"
)
);
addNativeChannel(
new DataTransferChannel("CameraProjectionUpdate"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
scene_camera_projection,
"curProj: Json",
"updateProjection(curProj, nextProj)",
"nextProj"
)
);
addNativeChannel(
new DataTransferChannel("EntityPositionUpdate", new Variable("eid", DataConstraintModel.typeString)),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
entity_transform_position,
"curPos: Json",
"updatePosition(nextPos.x, nextPos.y, nextPos.z)",
"nextPos"
)
);
addNativeChannel(
new DataTransferChannel("EntityRotationUpdate", new Variable("eid", DataConstraintModel.typeString)),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
entity_transform_rotation,
"curRot: Json",
"updateRotation(nextRot.x, nextRot.y, nextRot.z)",
"nextRot"
)
);
addNativeChannel(
new DataTransferChannel("EntityScaleUpdate", new Variable("eid", DataConstraintModel.typeString)),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
entity_transform_scale,
"curScale: Json",
"updateScale(nextScale.x, nextScale.y, nextScale.z)",
"nextScale"
)
);
addNativeChannel(
new DataTransferChannel("EntitySpriteUpdate", new Variable("eid", DataConstraintModel.typeString)),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
entity_mesh,
"curMesh: Json",
"updateSprite(spritePath: Str)",
"{\"type\": \"sprite\", \"sprite\": spritePath}"
)
);
addNativeChannel(
new DataTransferChannel("KeyEvent", new Variable("kno", DataConstraintModel.typeInt)),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
key_state,
"curState: Int",
"keyEvent(nextState)",
"nextState"
)
);
addNativeChannel(
new DataTransferChannel("TimersUpdated"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
timers,
"curTimers: Map",
"update(curTimers, nextTimers)",
"nextTimers"
)
);
addNativeChannel(
new DataTransferChannel("TimerEvent", new Variable("tid", DataConstraintModel.typeString)),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
timer_count,
"count: Long",
"tick()",
"count + 1"
)
);
addChannel(
new DataTransferChannel("UpdateCameraPosition"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
scene_camera_transform_position,
"curPos: Json",
"updateCameraPosition(x: Double, y: Double, z: Double)",
"{\"x\": x, \"y\": y, \"z\": z}")
);
for (int i = 1; i < editorScene.editorEntities.size(); i++) {
EditorEntity editorEntity = (EditorEntity) editorScene.getEditorEntity("" + i);
String id = editorEntity.getId();
if (editorEntity.getEditorComponent(EntityView.class) != null) {
addChannel(
new DataTransferChannel("UpdateEnemy" + id, new Variable("tid", DataConstraintModel.typeString)),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
timer_count,
"curCount: Long",
"updateEnemy" + id + "(type, speed)",
"nextCount"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Ref,
enemy_move_type.get(i - 1),
"type: Str",
"updateEnemy" + id + "(type, speed)"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Ref,
enemy_move_speed.get(i - 1),
"speed: Float",
"updateEnemy" + id + "(type, speed)"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
enemy_transform_position.get(i - 1),
"curPos: Json",
"updateEnemy" + id + "(type, speed)",
"{\"x\": curPos.x, \"y\": curPos.y + speed, \"z\": curPos.z}")
);
addChannel(
new DataTransferChannel("MoveEnemy" + id),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
enemy_transform_position.get(i - 1),
"curPos: Json",
"moveEnemy" + id + "(nextPos, eid)",
"nextPos"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Ref,
enemy_eid.get(i - 1),
"eid",
"moveEnemy" + id + "(nextPos, eid)"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
entity_transform_position,
"curPos: Json",
"moveEnemy" + id + "(nextPos, eid)",
"nextPos")
);
addChannel(
new DataTransferChannel("RotateEnemy" + id),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.In,
enemy_transform_rotation.get(i - 1),
"curRot: Json",
"rotateEnemy" + id + "(nextRot, eid)",
"nextRot"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Ref,
enemy_eid.get(i - 1),
"eid",
"rotateEnemy" + id + "(nextRot, eid)"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
entity_transform_rotation,
"curRot: Json",
"rotateEnemy" + id + "(nextRot, eid)",
"nextRot")
);
}
}
DataTransferChannel startTimerChannel = addChannel(
new DataTransferChannel("StartTimer"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
timers,
"timers: Map",
"startTimer(tid: Str, interval: Long)",
"insert(timers, tid, {\"interval\": interval, \"count\": 0})")
);
addChannel(
new DataTransferChannel("ClearTimer"),
new ChannelMemberDefinition(
ChannelMemberDefinition.ChannelMemberType.Out,
timers,
"timers: Map",
"clearTimer(tid: Str)",
"delete(timers, tid)")
);
if (stream.hasNext()) stream.next();
save();
TypeInference.infer(model);
Simulator simulator = new Simulator(model);
Window window = Window.get();
window.changeScene(2);
GameEnginePresenter presenter = new GameEnginePresenter(window.getScene(), simulator);
TimerService timerService = new TimerService(simulator);
SystemState initialState = simulator.init();
stream.addLine("startTimer(\"000\", 100)");
Expression messageStartTimer = parser.parseTerm(stream, model);
Event startTimer = new Event(startTimerChannel, messageStartTimer, timer, initialState.getResource(ResourceIdentifier.createFrom(timer)));
simulator.transition(startTimer);
} catch (Exception e) {
e.printStackTrace();
}
}
private JsonTerm createTransformTerm(Transform transform){
JsonTerm positionTerm = new JsonTerm();
positionTerm.addMember("x", new Constant(String.valueOf(transform.position.x)));
positionTerm.addMember("y", new Constant(String.valueOf(transform.position.y)));
positionTerm.addMember("z", new Constant(String.valueOf(transform.position.z)));
JsonTerm rotationTerm = new JsonTerm();
rotationTerm.addMember("x", new Constant(String.valueOf(transform.rotation.x)));
rotationTerm.addMember("y", new Constant(String.valueOf(transform.rotation.y)));
rotationTerm.addMember("z", new Constant(String.valueOf(transform.rotation.z)));
JsonTerm scaleTerm = new JsonTerm();
scaleTerm.addMember("x", new Constant(String.valueOf(transform.scale.x)));
scaleTerm.addMember("y", new Constant(String.valueOf(transform.scale.y)));
scaleTerm.addMember("z", new Constant(String.valueOf(transform.scale.z)));
JsonTerm transformTerm = new JsonTerm();
transformTerm.addMember("position", positionTerm);
transformTerm.addMember("rotation", rotationTerm);
transformTerm.addMember("scale", scaleTerm);
return transformTerm;
}
public JsonTerm createEnemyJsonTerm(Entity entity){
EditorEntity editorEntity = (EditorEntity) entity;
JsonTerm moveTerm = new JsonTerm();
JsonTerm meshTerm = new JsonTerm();
JsonTerm enemyTerm = new JsonTerm();
enemyTerm.addMember("transform", createTransformTerm(entity.transform));
enemyTerm.addMember("eid", new Constant(entity.getId(), DataConstraintModel.typeString));
for(EditorEntity.Connectiontype connectionType: editorEntity.ComponentConnections) {
if (connectionType == EditorEntity.Connectiontype.Mesh) {
meshTerm.addMember("type", new Constant("sprite", DataConstraintModel.typeString));
meshTerm.addMember("sprite", new Constant(Window.resourcePath + "enemy1.png", DataConstraintModel.typeString));
enemyTerm.addMember("mesh", meshTerm);
}
if (connectionType == EditorEntity.Connectiontype.Move) {
moveTerm.addMember("type", new Constant("straight", DataConstraintModel.typeString));
moveTerm.addMember("speed", new Constant(String.valueOf(5.0)));
enemyTerm.addMember("move", moveTerm);
}
}
return enemyTerm;
}
public JsonTerm createPlayerJsonTerm(){
JsonTerm meshTerm = new JsonTerm();
meshTerm.addMember("type", new Constant("sprite", DataConstraintModel.typeString));
meshTerm.addMember("sprite", new Constant(Window.resourcePath + "enemy1.png", DataConstraintModel.typeString));
JsonTerm playerTerm = new JsonTerm();
playerTerm.addMember("transform", createTransformTerm(new Transform()));
playerTerm.addMember("mesh", meshTerm);
return playerTerm;
}
// public JsonTerm createSceneTerm(){
//
//
// }
private void addInit() {
EditorScene editorScene = (EditorScene) Window.get().getScene();
ResourceHierarchy playerHierarchy = new ResourceHierarchy("player", DataConstraintModel.typeJson);
playerHierarchy = model.getOrPutResourceHierarchy(playerHierarchy);
JsonTerm playerRightTerm = createPlayerJsonTerm();
playerHierarchy.setInitialValue(playerRightTerm);
playerHierarchy.setInitText(playerRightTerm.toString());
ResourceHierarchy sceneHierarchy = new ResourceHierarchy("scene", DataConstraintModel.typeJson);
sceneHierarchy = model.getOrPutResourceHierarchy(sceneHierarchy);
JsonTerm entitiesTerm = new JsonTerm();
// 0番はカメラのため
for (int i = 1; i < editorScene.editorEntities.size(); i++) {
EditorEntity editorEntity = (EditorEntity) editorScene.getEditorEntity("" + i);
if(editorEntity.getEditorComponent(EntityView.class) != null) {
ResourceHierarchy enemyHierarchy = new ResourceHierarchy("enemy" + editorScene.getEditorEntity("" + i).getId(), DataConstraintModel.typeJson);
enemyHierarchy = model.getOrPutResourceHierarchy(enemyHierarchy);
JsonTerm enemyTerm = createEnemyJsonTerm(editorScene.getEditorEntity("" + i));
entitiesTerm.addMember(editorScene.getEditorEntity("" + i).getId() ,enemyTerm);
enemyHierarchy.setInitialValue(enemyTerm);
enemyHierarchy.setInitText(enemyTerm.toString());
}
}
JsonTerm sceneTerm = new JsonTerm();
sceneTerm.addMember("entities", entitiesTerm);
sceneHierarchy.setInitialValue(sceneTerm);
sceneHierarchy.setInitText(sceneTerm.toString());
}
public void save() {
String outputFileName = modelFilePath + File.separator + "GameEngineTest.model";
try {
File file = new File(outputFileName);
FileWriter fileWriter = new FileWriter(file);
fileWriter.write(model.getSourceText());
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public DataTransferChannel addNativeChannel(DataTransferChannel dataTransferChannel, ChannelMemberDefinition... definitions) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon, ExpectedDoubleQuotation {
dataTransferChannel.setNative(true);
return addChannel(dataTransferChannel, definitions);
}
public DataTransferChannel addChannel(DataTransferChannel dataTransferChannel, ChannelMemberDefinition... definitions)
throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon, ExpectedDoubleQuotation {
DataTransferChannel channel = dataTransferChannel;
boolean hasInputChannel = false;
for (ChannelMemberDefinition def : definitions) {
if (def.channelType == ChannelMemberDefinition.ChannelMemberType.Out) {
ChannelMember member = addChannelMember(stream, parser, def.path, def.curStateName, def.messageName, def.nextStateName);
channel.addChannelMemberAsOutput(member);
} else if (def.channelType == ChannelMemberDefinition.ChannelMemberType.In) {
ChannelMember member = addChannelMember(stream, parser, def.path, def.curStateName, def.messageName, def.nextStateName);
channel.addChannelMemberAsInput(member);
hasInputChannel = true;
} else if (def.channelType == ChannelMemberDefinition.ChannelMemberType.Ref){
ChannelMember member = addChannelMember(stream, parser, def.path, def.curStateName, def.messageName);
channel.addChannelMemberAsReference(member);
}
}
if(hasInputChannel) model.addChannel(channel);
else model.addInputChannel(channel);
return channel;
}
//inが一つでもあればInputChannel
private ChannelMember addChannelMember(TokenStream stream, Parser parser, ResourcePath path, String curStateName, String messageName, String nextStateName) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon, ExpectedDoubleQuotation {
ChannelMember member = new ChannelMember(path);
stream.addLine(curStateName);
Expression curState = parser.parseTerm(stream, model);
stream.addLine(messageName);
Expression message = parser.parseTerm(stream, model);
stream.addLine(nextStateName);
Expression nextState = parser.parseTerm(stream, model);
member.getStateTransition().setCurStateExpression(curState);
member.getStateTransition().setMessageExpression(message);
member.getStateTransition().setNextStateExpression(nextState);
return member;
}
private ChannelMember addChannelMember(TokenStream stream, Parser parser, ResourcePath path, String curStateName, String messageName) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon, ExpectedDoubleQuotation {
ChannelMember member = new ChannelMember(path);
stream.addLine(curStateName);
Expression curState = parser.parseTerm(stream, model);
stream.addLine(messageName);
Expression message = parser.parseTerm(stream, model);
member.getStateTransition().setCurStateExpression(curState);
member.getStateTransition().setMessageExpression(message);
return member;
}
public static class ChannelMemberDefinition {
public enum ChannelMemberType {In, Out, Ref}
public final ChannelMemberType channelType;
public final ResourcePath path;
public final String curStateName;
public final String messageName;
public String nextStateName;
public ChannelMemberDefinition(ChannelMemberType channelType, ResourcePath path , String curStateName, String messageName, String nextStateName) {
this.path = path;
this.channelType = channelType;
this.curStateName = curStateName;
this.messageName = messageName;
this.nextStateName = nextStateName;
}
public ChannelMemberDefinition(ChannelMemberType channelType, ResourcePath path , String curStateName, String messageName) {
this.path = path;
this.channelType = channelType;
this.curStateName = curStateName;
this.messageName = messageName;
}
}
}