diff --git a/GameEngine/src/main/java/gameEngine/GameEditor.java b/GameEngine/src/main/java/gameEngine/GameEditor.java index 6c4bb62..3e98fa8 100644 --- a/GameEngine/src/main/java/gameEngine/GameEditor.java +++ b/GameEngine/src/main/java/gameEngine/GameEditor.java @@ -2,18 +2,22 @@ import gameEngine.entites.Entity; import gameEngine.entites.GameObject; +import gameEngine.entites.gameComponents.GameComponent; import gameEngine.scenes.*; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.List; import java.util.Map; public class GameEditor extends JFrame { private JList objectList; private DefaultListModel listModel; + private DefaultListModel componentListModel; + private JList componentList; private JLabel nameLabel, posLabel, rotLabel, scaLabel; private JTextField posXField, posYField, posZField; private JTextField rotXField, rotYField, rotZField; @@ -26,12 +30,8 @@ setSize(600, 500); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 閉じられないようにする setLayout(null); // レイアウトを絶対座標に設定 - - // 各UI要素の初期化 - initializeUIComponents(); - - // フレームを表示 - setVisible(true); + initializeUIComponents();// 各UI要素の初期化 + setVisible(true); // フレームを表示 } // UI要素を初期化し、配置関数を呼び出す @@ -40,7 +40,6 @@ objectList = new JList<>(listModel); JScrollPane scrollPane = new JScrollPane(objectList); - // カスタムレンダラーを使用して、リストにGameObjectの名前を表示する objectList.setCellRenderer(new ListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, String value, int index, boolean isSelected, boolean cellHasFocus) { @@ -60,6 +59,25 @@ } }); + componentListModel = new DefaultListModel(); + componentList = new JList(componentListModel); + JScrollPane componentScrollPane = new JScrollPane(componentList); + componentList.setCellRenderer(new ListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, GameComponent value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = new JLabel(); + label.setText(value.getClass().getSimpleName()); // クラス名を表示 + if (isSelected) { + label.setBackground(list.getSelectionBackground()); + label.setForeground(list.getSelectionForeground()); + } else { + label.setBackground(list.getBackground()); + label.setForeground(list.getForeground()); + } + label.setOpaque(true); // 背景色が表示されるようにする + return label; + } + }); // 各UIコンポーネントの作成と配置 nameField = new JTextField(20); @@ -77,73 +95,61 @@ scaleYField = new JTextField(5); scaleZField = new JTextField(5); - JButton newGameObjectButton = new JButton("New GameObject"); + JButton newGameObjectButton = new JButton("New Entity"); newGameObjectButton.addActionListener(e -> createNewGameObject()); + JButton addComponentButton = new JButton("Add Component"); + addComponentButton.addActionListener(e -> addComponentToGameObject()); + + JButton removeComponentButton = new JButton("Remove Component"); + removeComponentButton.addActionListener(e -> removeComponentFromGameObject()); + JButton applyButton = new JButton("Apply"); applyButton.addActionListener(new ApplyButtonListener()); - // 新たにAddComponentボタンを追加 - JButton addComponentButton = new JButton("Add Component"); - addComponentButton.addActionListener(e -> addComponentToGameObject()); - // 各要素の位置とサイズを設定 setComponentBounds(scrollPane, 10, 10, 150, 400); + setComponentBounds(componentScrollPane, 400, 200, 130, 200); setComponentBounds(nameLabel, 200, 10, 100, 30); setComponentBounds(nameField, 250, 10, 200, 30); - setComponentBounds(posLabel, 200, 50, 100, 30); + setComponentBounds(posLabel, 180, 50, 100, 30); setComponentBounds(posXField, 250, 50, 50, 30); setComponentBounds(posYField, 310, 50, 50, 30); setComponentBounds(posZField, 370, 50, 50, 30); - setComponentBounds(rotLabel, 200, 90, 100, 30); + setComponentBounds(rotLabel, 180, 90, 100, 30); setComponentBounds(rotXField, 250, 90, 50, 30); setComponentBounds(rotYField, 310, 90, 50, 30); setComponentBounds(rotZField, 370, 90, 50, 30); - setComponentBounds(scaLabel, 200, 130, 100, 30); + setComponentBounds(scaLabel, 180, 130, 100, 30); setComponentBounds(scaleXField, 250, 130, 50, 30); setComponentBounds(scaleYField, 310, 130, 50, 30); setComponentBounds(scaleZField, 370, 130, 50, 30); setComponentBounds(newGameObjectButton, 200, 170, 150, 30); - setComponentBounds(applyButton, 200, 210, 150, 30); setComponentBounds(addComponentButton, 200, 250, 150, 30); + setComponentBounds(removeComponentButton, 200, 290, 150, 30); + setComponentBounds(applyButton, 200, 400, 100, 25); - // コンポーネントをフレームに追加 - add(scrollPane); - add(nameLabel); - add(nameField); - add(posLabel); - add(posXField); - add(posYField); - add(posZField); - add(rotLabel); - add(rotXField); - add(rotYField); - add(rotZField); - add(scaLabel); - add(scaleXField); - add(scaleYField); - add(scaleZField); - add(newGameObjectButton); - add(applyButton); - add(addComponentButton); - - // リスト選択時の処理 - objectList.addListSelectionListener(e -> loadSelectedGameObject()); + objectList.addListSelectionListener(e -> { + if (!e.getValueIsAdjusting()) { // ユーザーが調整中でない場合のみ + loadSelectedGameObject(); // オブジェクトをロード + } + }); } - // コンポーネントの位置とサイズを設定する関数 private void setComponentBounds(Component component, int x, int y, int width, int height) { component.setBounds(x, y, width, height); + add(component); //フレームに追加 } - // New GameObjectを作成し、画面を更新 private void createNewGameObject() { - gameScene.createNewObject(); // 新しいGameObjectを作成 - applyGameObjectChanges(); - repaint(); // 画面を再描画 + gameScene.createNewObject(); // 新しいGameObjectを作成 + updateGameObjectList(gameScene); // オブジェクトリストの更新 + objectList.repaint(); // リストを再描画 + objectList.revalidate(); // リストを再構築 + objectList.setSelectedIndex(listModel.getSize() - 1); // 新規作成したオブジェクトを選択 + applyGameObjectChanges(); // 作成直後に即座にプロパティを反映させる } - // GameObjectにコンポーネントを追加する処理 private void addComponentToGameObject() { String selectedIdStr = objectList.getSelectedValue(); if (selectedIdStr != null) { @@ -151,19 +157,56 @@ Entity selectedEntity = gameScene.entities.get(selectedId); if (selectedEntity instanceof GameObject) { GameObject gameObject = (GameObject) selectedEntity; - gameScene.addComponent(gameObject); + gameScene.addComponent(gameObject); // コンポーネントの追加処理 + updateComponentList(gameObject); // コンポーネントリストの更新 + updateGameObjectList(gameScene); // オブジェクトリストの更新 JOptionPane.showMessageDialog(this, "Component Added to " + selectedEntity.name); } } } - // GameObjectのリストを更新 - public void updateGameObjectList(Scene gameScene) { - listModel.clear(); + private void removeComponentFromGameObject() { + String selectedIdStr = objectList.getSelectedValue(); + if (selectedIdStr != null) { + int selectedId = Integer.parseInt(selectedIdStr); + Entity selectedEntity = gameScene.entities.get(selectedId); + if (selectedEntity instanceof GameObject) { + GameObject gameObject = (GameObject) selectedEntity; + GameComponent selectedComponent = componentList.getSelectedValue(); // GameComponentとして取得 + if (selectedComponent != null) { + gameScene.removeComponent(gameObject, selectedComponent); // GameComponentオブジェクトを渡す + updateComponentList(gameObject); // コンポーネントリストの更新 + updateGameObjectList(gameScene); // オブジェクトリストの更新 + JOptionPane.showMessageDialog(this, "Component Removed from " + selectedEntity.name); + } + } + } + } + + private void updateGameObjectList(Scene gameScene) { + listModel.clear(); // リストの初期化 for (Map.Entry entry : gameScene.entities.entrySet()) { Entity entity = entry.getValue(); - listModel.addElement(String.valueOf(entity.getId())); // IDをリストに表示 + listModel.addElement(String.valueOf(entity.getId())); // IDをリストに追加 + } + objectList.repaint(); // リストを再描画 + objectList.revalidate(); // リストを再構築 + if (!listModel.isEmpty()) { + objectList.setSelectedIndex(0); // 最初の項目を自動選択 + } } + + private void updateComponentList(GameObject gameObject) { + componentListModel.clear(); // リストをクリア + List components = gameObject.gameComponents; + for (GameComponent component : components) { + componentListModel.addElement(component); // コンポーネントを追加 + } + if (components.isEmpty()) { + // 選択解除して、空の状態を扱う + componentList.clearSelection(); + componentList.repaint(); + } } // 選択されたGameObjectのプロパティをロードする @@ -173,16 +216,12 @@ int selectedId = Integer.parseInt(selectedIdStr); Entity selectedEntity = gameScene.entities.get(selectedId); if (selectedEntity != null) { - nameField.setText(selectedEntity.name); - posXField.setText(String.valueOf(selectedEntity.transform.position.x)); - posYField.setText(String.valueOf(selectedEntity.transform.position.y)); - posZField.setText(String.valueOf(selectedEntity.transform.position.z)); - rotXField.setText(String.valueOf(selectedEntity.transform.rotation.x)); - rotYField.setText(String.valueOf(selectedEntity.transform.rotation.y)); - rotZField.setText(String.valueOf(selectedEntity.transform.rotation.z)); - scaleXField.setText(String.valueOf(selectedEntity.transform.scale.x)); - scaleYField.setText(String.valueOf(selectedEntity.transform.scale.y)); - scaleZField.setText(String.valueOf(selectedEntity.transform.scale.z)); + loadObjectProperties(selectedEntity); + + // コンポーネントリストの更新 + if (selectedEntity instanceof GameObject) { + updateComponentList((GameObject) selectedEntity); + } } } } @@ -198,7 +237,7 @@ private void applyGameObjectChanges() { String selectedIdStr = objectList.getSelectedValue(); if (selectedIdStr != null) { - int selectedId = Integer.parseInt(selectedIdStr); // IDとして扱う + int selectedId = Integer.parseInt(selectedIdStr); Entity selectedEntity = gameScene.entities.get(selectedId); if (selectedEntity != null) { selectedEntity.name = nameField.getText(); @@ -217,7 +256,9 @@ Float.parseFloat(scaleYField.getText()), Float.parseFloat(scaleZField.getText()) ); - updateGameObjectList(gameScene); // リストの更新 + + updateGameObjectList(gameScene); // オブジェクトリストの再描画 + objectList.repaint(); // リストの再描画を強制 } } } @@ -227,6 +268,17 @@ updateGameObjectList(gameScene); } - + private void loadObjectProperties(Entity entity) { + nameField.setText(entity.name); + posXField.setText(String.valueOf(entity.transform.position.x)); + posYField.setText(String.valueOf(entity.transform.position.y)); + posZField.setText(String.valueOf(entity.transform.position.z)); + rotXField.setText(String.valueOf(entity.transform.rotation.x)); + rotYField.setText(String.valueOf(entity.transform.rotation.y)); + rotZField.setText(String.valueOf(entity.transform.rotation.z)); + scaleXField.setText(String.valueOf(entity.transform.scale.x)); + scaleYField.setText(String.valueOf(entity.transform.scale.y)); + scaleZField.setText(String.valueOf(entity.transform.scale.z)); + } } diff --git a/GameEngine/src/main/java/gameEngine/entites/Entity.java b/GameEngine/src/main/java/gameEngine/entites/Entity.java index 0f2b49e..2d08f68 100644 --- a/GameEngine/src/main/java/gameEngine/entites/Entity.java +++ b/GameEngine/src/main/java/gameEngine/entites/Entity.java @@ -4,12 +4,14 @@ import gameEngine.entites.gameComponents.MoveImage; import gameEngine.geometry.Transform; +import java.awt.*; + public class Entity { private int entityId; // 作成時に割り当て public Transform transform = new Transform(); public boolean active = true; - public String name = "GameEntity"; + public String name = "Entity"; public Entity(int id) { entityId = id; diff --git a/GameEngine/src/main/java/gameEngine/entites/GameObject.java b/GameEngine/src/main/java/gameEngine/entites/GameObject.java index b3c852a..4bd9c1c 100644 --- a/GameEngine/src/main/java/gameEngine/entites/GameObject.java +++ b/GameEngine/src/main/java/gameEngine/entites/GameObject.java @@ -7,14 +7,29 @@ public class GameObject extends Entity { - private final List gameComponents = new ArrayList<>(); + public final List gameComponents = new ArrayList<>(); public GameObject(int id) { super(id); } public void addComponent(GameComponent component) { + for (GameComponent existingComponent : gameComponents) { + if (existingComponent.getClass().equals(component.getClass())) { + System.out.println("Component already exists: " + component.getClass().getSimpleName()); + return; + } + } this.gameComponents.add(component); + System.out.println("Component added: " + component.getClass().getSimpleName()); + } + public void removeComponent(GameComponent component) { + boolean removed = this.gameComponents.remove(component); + if (removed) { + System.out.println("Component removed: " + component.getClass().getSimpleName()); + } else { + System.out.println("Component not found: " + component.getClass().getSimpleName()); + } } public void initComponents() { diff --git a/GameEngine/src/main/java/gameEngine/entites/gameComponents/Mesh.java b/GameEngine/src/main/java/gameEngine/entites/gameComponents/Mesh.java index 8cf17a0..bef102c 100644 --- a/GameEngine/src/main/java/gameEngine/entites/gameComponents/Mesh.java +++ b/GameEngine/src/main/java/gameEngine/entites/gameComponents/Mesh.java @@ -29,6 +29,9 @@ @Override public void init() { + if (type == MeshType.SPRITE) { + renderSprite(); // スプライトの描画 + } } @Override diff --git a/GameEngine/src/main/java/gameEngine/scenes/EditorScene.java b/GameEngine/src/main/java/gameEngine/scenes/EditorScene.java index 259d813..4e03dc9 100644 --- a/GameEngine/src/main/java/gameEngine/scenes/EditorScene.java +++ b/GameEngine/src/main/java/gameEngine/scenes/EditorScene.java @@ -1,40 +1,101 @@ package gameEngine.scenes; +import gameEngine.GameEditor; +import gameEngine.entites.Entity; +import gameEngine.entites.GameObject; +import gameEngine.entites.gameComponents.ColorController; +import gameEngine.entites.gameComponents.GameComponent; +import gameEngine.entites.gameComponents.Mesh; +import gameEngine.entites.gameComponents.MoveImage; import gameEngine.input.*; import gameEngine.views.Color; import gameEngine.views.Window; import java.awt.event.KeyEvent; +import java.util.HashMap; import static org.lwjgl.opengl.GL11.glClearColor; public class EditorScene extends Scene { + private boolean isCreateObject = false; + private boolean isAddComponent = false; + private boolean isRemoveComponent = false; + private GameObject addComponentObject; + private GameObject removeComponentObject; + private GameComponent removeComponent; - private boolean changingScene = false; - private float timeToChangeScene = 2.0f; - private final Color editorBackColor = new Color(1,1,1,0); public EditorScene(){ + this.entities = entities; System.out.println("Active Editor scene"); + glClearColor(1, 1, 1, 0); + + //GameObjectの追加 + entities.put(0, new GameObject(0)); + GameObject g0 = (GameObject) entities.get(0); + g0.addComponent(new ColorController()); + g0.setName("ColorController"); + } + public EditorScene(HashMap entities){ + this.entities = entities; + System.out.println("Active Editor scene"); + glClearColor(1, 1, 1, 0); } @Override public void update(float dt) { - //System.out.println("" + (1.0f / dt) + "FPS"); + changeScene(1, dt); //Gameシーンへの以降処理 - if(!changingScene && Input.GetKeyDown(KeyEvent.VK_SPACE)){ - changingScene = true; + if(isCreateObject){ + createGameObject(); + isCreateObject = false; } - if(changingScene && timeToChangeScene > 0){ - timeToChangeScene -= dt; - editorBackColor.r -= dt * 5.0f; - editorBackColor.g -= dt * 5.0f; - editorBackColor.b -= dt * 5.0f; - } - else if(changingScene){ - Window.changeScene(1); + if(isAddComponent){ + addComponent(); + addComponentObject = null; + isAddComponent = false; } - glClearColor(editorBackColor.r, editorBackColor.g, editorBackColor.b, editorBackColor.a); + if(isRemoveComponent){ + removeComponent(); + removeComponentObject = null; + removeComponent = null; + isRemoveComponent = false; + } } + + public void createNewObject(){ + if(isCreateObject) return; + isCreateObject = true; + } + + public void addComponent(GameObject gameObject){ + if(isAddComponent) return; + addComponentObject = gameObject; + isAddComponent = true; + } + + public void removeComponent(GameObject gameObject, GameComponent gameComponent){ + if(isRemoveComponent) return; + removeComponentObject = gameObject; + removeComponent = gameComponent; + isRemoveComponent = true; + } + + private void createGameObject(){ + int newId = entities.size(); + entities.put(newId, new GameObject(newId)); + GameObject newGameObject = (GameObject) entities.get(newId); + newGameObject.addComponent(new Mesh(entities.get(newId), Mesh.MeshType.SPRITE, "test.png")); + newGameObject.setName("NewEntity" + newId); + } + + private void addComponent(){ + addComponentObject.addComponent(new MoveImage(addComponentObject)); + } + + private void removeComponent(){ + removeComponentObject.removeComponent(removeComponent); + } + } diff --git a/GameEngine/src/main/java/gameEngine/scenes/GameScene.java b/GameEngine/src/main/java/gameEngine/scenes/GameScene.java index 5b9551a..f8d0b57 100644 --- a/GameEngine/src/main/java/gameEngine/scenes/GameScene.java +++ b/GameEngine/src/main/java/gameEngine/scenes/GameScene.java @@ -6,67 +6,25 @@ import gameEngine.entites.gameComponents.GameComponent; import gameEngine.entites.gameComponents.Mesh; import gameEngine.entites.gameComponents.MoveImage; +import gameEngine.input.Input; +import gameEngine.views.Window; + +import java.awt.event.KeyEvent; +import java.util.HashMap; + import static org.lwjgl.opengl.GL11.glClearColor; public class GameScene extends Scene { - private boolean isCreateObject = false; - private boolean isAddComponent = false; - private GameObject addComponentObject; - - public GameScene() { + public GameScene(HashMap entities) { + this.entities = entities;//Editorのentitiesを持ってくる System.out.println("Active Game scene"); glClearColor(1, 1, 1, 0); - - entities.put(0, new GameObject(0)); - GameObject g0 = (GameObject) entities.get(0); - g0.addComponent(new ColorController()); - g0.setName("ColorController"); - - entities.put(1, new GameObject(1)); - GameObject g1 = (GameObject) entities.get(1); - g1.addComponent(new Mesh(entities.get(1), Mesh.MeshType.SPRITE, "test.png")); - g1.addComponent(new MoveImage(entities.get(1))); - entities.get(1).setName("Player"); } @Override public void update(float dt) { - - if(isCreateObject){ - createGameObject(); - isCreateObject = false; - } - - if(isAddComponent){ - addComponent(); - addComponentObject = null; - isAddComponent = false; - } + changeScene(0, dt); //Editorシーンへの以降処理 } - public void createNewObject(){ - if(isCreateObject) return; - isCreateObject = true; - } - - public void addComponent(GameObject gameObject){ - if(isAddComponent) return; - addComponentObject = gameObject; - isAddComponent = true; - } - - private void createGameObject(){ - int newId = entities.size(); - entities.put(newId, new GameObject(newId)); - GameObject newGameObject = (GameObject) entities.get(newId); - newGameObject.addComponent(new Mesh(entities.get(newId), Mesh.MeshType.SPRITE, "test.png")); - newGameObject.setName("NewEntity" + newId); - } - - private void addComponent(){ - addComponentObject.addComponent(new MoveImage(addComponentObject)); - } - - } diff --git a/GameEngine/src/main/java/gameEngine/scenes/Scene.java b/GameEngine/src/main/java/gameEngine/scenes/Scene.java index 326e32f..8db3b0a 100644 --- a/GameEngine/src/main/java/gameEngine/scenes/Scene.java +++ b/GameEngine/src/main/java/gameEngine/scenes/Scene.java @@ -3,14 +3,25 @@ import gameEngine.entites.Camera; import gameEngine.entites.Entity; import gameEngine.entites.GameObject; +import gameEngine.entites.gameComponents.GameComponent; +import gameEngine.input.Input; +import gameEngine.views.Color; +import gameEngine.views.Window; +import java.awt.event.KeyEvent; import java.util.HashMap; +import static org.lwjgl.opengl.GL11.glClearColor; + public abstract class Scene { private Camera camera; public HashMap entities = new HashMap<>(); + private boolean changingScene = false; + private float timeToChangeScene = 2.0f; + private final Color editorBackColor = new Color(1,1,1,0); + public Scene(){ } @@ -20,5 +31,25 @@ } public void addComponent(GameObject gameObject) { } + public void removeComponent(GameObject gameObject, GameComponent selectedComponent) { + } + + void changeScene(int scene, float dt){ + if(!changingScene && Input.GetKeyDown(KeyEvent.VK_SPACE)){ + changingScene = true; + } + + if(changingScene && timeToChangeScene > 0){ + timeToChangeScene -= dt * 1.5f; + editorBackColor.r -= dt * 5.0f; + editorBackColor.g -= dt * 5.0f; + editorBackColor.b -= dt * 5.0f; + } + else if(changingScene){ + Window.changeScene(scene); + } + + glClearColor(editorBackColor.r, editorBackColor.g, editorBackColor.b, editorBackColor.a); + } } diff --git a/GameEngine/src/main/java/gameEngine/views/Window.java b/GameEngine/src/main/java/gameEngine/views/Window.java index b5cb4a1..d91d73a 100644 --- a/GameEngine/src/main/java/gameEngine/views/Window.java +++ b/GameEngine/src/main/java/gameEngine/views/Window.java @@ -12,6 +12,7 @@ import org.lwjgl.system.*; import java.nio.*; +import java.util.HashMap; import static org.lwjgl.glfw.Callbacks.*; import static org.lwjgl.glfw.GLFW.*; @@ -28,6 +29,8 @@ private long glfwWindow; private static GameEditor gameEditor; + private static HashMap sceneEntities; + private Window() { this.width = 1200; this.height = 900; @@ -38,7 +41,8 @@ public static void changeScene(int newScene) { switch (newScene) { case 0: - currentScene = new EditorScene(); + if(sceneEntities == null) currentScene = new EditorScene(); + else currentScene = new EditorScene(sceneEntities); for (Entity entity : currentScene.entities.values()) { if (entity instanceof GameObject) { GameObject gameObject = (GameObject) entity; @@ -48,7 +52,8 @@ gameEditor.updateListByScene(currentScene); break; case 1: - currentScene = new GameScene(); + sceneEntities = currentScene.entities; + currentScene = new GameScene(sceneEntities); for (Entity entity : currentScene.entities.values()) { if (entity instanceof GameObject) { GameObject gameObject = (GameObject) entity; @@ -141,16 +146,17 @@ glfwPollEvents(); // ウィンドウイベントをポーリング glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // フレームバッファをクリア - if(dt >= 0){ - currentScene.update((float)dt); - - //現在のシーンのゲームコンポーネントのUpdate - for (Entity entity : currentScene.entities.values()) { - if (entity instanceof GameObject) { - GameObject gameObject = (GameObject) entity; - gameObject.updateComponents(); + if (dt >= 0) { + if (!(currentScene instanceof EditorScene)) { + for (Entity entity : currentScene.entities.values()) { + if (entity instanceof GameObject) { + GameObject gameObject = (GameObject) entity; + gameObject.updateComponents(); + } } } + // シーン全体の update を呼び出す + currentScene.update((float) dt); } glfwSwapBuffers(glfwWindow); // カラーバッファを交換