Newer
Older
AlgebraicDataflowArchitectureModel / GameEngine / src / main / java / gameEngine / GameEngineModelFileGenerator.java
NoranekoFelician 3 days ago 28 KB ・modelファイル出力を更新
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.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 Variable("eid", DataConstraintModel.typeString)),
                            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,
                                    enemy_transform_position.get(i - 1),
                                    "curPos: Json",
                                    "moveEnemy" + id + "(nextPos, eid)",
                                    "nextPos")
                    );

                    addChannel(
                            new DataTransferChannel("RotateEnemy" + id, new Variable("eid", DataConstraintModel.typeString)),
                            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,
                                    enemy_transform_rotation.get(i - 1),
                                    "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"));
                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;
    }

    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());

        // 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));
                enemyHierarchy.setInitialValue(enemyTerm);
                enemyHierarchy.setInitText(enemyTerm.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 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;
        }

    }

}