Newer
Older
AlgebraicDataflowArchitectureModel / GameEngine / src / main / java / gameEngine / views / Window.java
package gameEngine.views;
import gameEngine.GameEditor;
import gameEngine.Time;
import gameEngine.entites.Entity;
import gameEngine.entites.GameObject;
import gameEngine.entites.gameComponents.*;
import gameEngine.input.*;
import gameEngine.scenes.*;

import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;
import java.util.HashMap;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class Window {
    private static Window window;
    private static Scene currentScene;
    public int width;
    public int height;
    private String title;
    private long glfwWindow;
    private static GameEditor gameEditor;

    private static HashMap<String , Entity> sceneEntities;

    private Window() {
        this.width = 1200;
        this.height = 900;
        this.title = "HelloWorld";
        init();
    }

    public static void changeScene(int newScene) {
        switch (newScene) {
            case 0:  // EditorScene
                if (sceneEntities == null) {
                    currentScene = new EditorScene();
                    System.out.println("new");
                } else {
                    currentScene = new EditorScene(sceneEntities);
                    System.out.println(sceneEntities);
                    // オリジナルのTransformを復元
                    for (Entity entity : currentScene.entities.values()) {
                        entity.restoreOriginalTransform();
                    }
                    // ゲームシーンのコンポーネントを削除
                    for (Entity entity : currentScene.entities.values()) {
                        if (entity instanceof GameObject) {
                            GameObject gameObject = (GameObject) entity;
                            gameObject.gameComponents.removeIf(GameComponent::isGameSceneComponent);
                        }
                    }
                }
                initializeSceneEntities();
                break;
            case 1:  // GameScene
                // Transform保存
                for (Entity entity : currentScene.entities.values()) {
                    entity.saveOriginalTransform();
                }
                sceneEntities = currentScene.entities;
                HashMap<String, Entity> gameSceneEntities = new HashMap<>(sceneEntities);

                // コピーした entities を使って GameScene を作成
                currentScene = new GameScene(gameSceneEntities);
                initializeSceneEntities();
                break;
            default:
                assert false : "Unknown Scene [" + newScene + "]";
                break;
        }
    }

    private static void initializeSceneEntities() {
        for (Entity entity : currentScene.entities.values()) {
            if (entity instanceof GameObject) {
                GameObject gameObject = (GameObject) entity;
                gameObject.initComponents();  // コンポーネントの初期化
            }
        }
        if(gameEditor != null) gameEditor.updateListByScene(currentScene);  // ゲームエディタ側にシーン情報を渡す
    }

    public static Window get() {
        if (window == null) {
            window = new Window();
        }

        return window;
    }

    public void runWithEditor() {
        gameEditor = new GameEditor();
        run();
    }

    public void run() {
        System.out.println("Hello LWJGL " + Version.getVersion() + "!");
        Window.changeScene(0);
        loop();
        glfwFreeCallbacks(glfwWindow);
        glfwDestroyWindow(glfwWindow);
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    private void init() {
        GLFWErrorCallback.createPrint(System.err).set();
        if ( !glfwInit() ) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        //Configure GLFW
        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
        glfwWindowHint(GLFW_MAXIMIZED, GLFW_FALSE);

        glfwWindow = glfwCreateWindow(this.width, this.height, this.title, NULL, NULL);
        if ( glfwWindow == NULL ) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        glfwSetCursorPosCallback(glfwWindow, MouseInput::mousePosCallback);
        glfwSetMouseButtonCallback(glfwWindow, MouseInput::mouseButtonCallback);
        glfwSetScrollCallback(glfwWindow, MouseInput::mouseScrollCallBack);
        glfwSetKeyCallback(glfwWindow, KeyInput::keyCallback);

        // Get the thread stack and push a new frame
        try ( MemoryStack stack = stackPush() ) {
            IntBuffer pWidth = stack.mallocInt(1); // int*
            IntBuffer pHeight = stack.mallocInt(1); // int*

            // Get the window size passed to glfwCreateWindow
            glfwGetWindowSize(glfwWindow, pWidth, pHeight);

            // Get the resolution of the primary monitor
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

            // Center the window
            glfwSetWindowPos(
                    glfwWindow,
                    (vidmode.width() - pWidth.get(0)) / 2,
                    (vidmode.height() - pHeight.get(0)) / 2
            );
        }

        glfwMakeContextCurrent(glfwWindow);
        glfwSwapInterval(1);
        glfwShowWindow(glfwWindow);

        GL.createCapabilities();
    }

    private void loop() {
        Time.update();

        while (!glfwWindowShouldClose(glfwWindow)) {

            glfwPollEvents(); // ウィンドウイベントをポーリング
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // フレームバッファをクリア

            float dt = Time.deltaTime;

            if (dt >= 0) {

                resetScene();
                boolean isEditorScene = currentScene instanceof EditorScene;

                for (Entity entity : currentScene.entities.values()) {
                    if (entity instanceof GameObject) {
                        GameObject gameObject = (GameObject) entity;
                        gameObject.updateComponents(isEditorScene);
                    }
                }

                // シーン全体の update を呼び出す
                currentScene.update(dt);
                currentScene.processTasks();
            }

            glfwSwapBuffers(glfwWindow); // カラーバッファを交換

            Time.update();
        }

    }

    //Gameシーン開始時にタイマーをリセット、Editorシーン戻ったときにフラグをfalseにする
    private boolean startGameScene = false;
    private void resetScene() {
        boolean isGameScene = currentScene instanceof GameScene;
        if (isGameScene && !startGameScene) {
            Time.reset();

            startGameScene = true;
        }
        if (!isGameScene) startGameScene = false;
    }

    public Scene getScene(){
        return currentScene;
    }

}