diff --git a/GameEngine/src/main/java/gameEngine/GameEditor.java b/GameEngine/src/main/java/gameEngine/GameEditor.java index 65fdf84..f3baceb 100644 --- a/GameEngine/src/main/java/gameEngine/GameEditor.java +++ b/GameEngine/src/main/java/gameEngine/GameEditor.java @@ -3,14 +3,14 @@ import gameEngine.entites.Entity; import gameEngine.entites.GameObject; import gameEngine.entites.gameComponents.GameComponent; -import gameEngine.entites.gameComponents.Mesh; import gameEngine.entites.gameComponents.MoveImage; import gameEngine.scenes.*; +import org.joml.Vector3f; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; import java.util.List; import java.util.Map; @@ -20,7 +20,7 @@ private DefaultListModel listModel; private DefaultListModel componentListModel; private JList componentList; - private JLabel nameLabel, posLabel, rotLabel, scaLabel; + private JLabel entityLabel, nameLabel, posLabel, rotLabel, scaLabel; private JTextField posXField, posYField, posZField; private JTextField rotXField, rotYField, rotZField; private JTextField scaleXField, scaleYField, scaleZField; @@ -28,9 +28,13 @@ private Scene gameScene; private Timer updateTimer; + private String lastLoadedName; + private Vector3f lastLoadedPos, lastLoadedRot, lastLoadedScale; + + public GameEditor() { setTitle("Game Object Editor"); - setSize(600, 500); + setSize(500, 400); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 閉じられないようにする setLayout(null); // レイアウトを絶対座標に設定 initializeUIComponents();// 各UI要素の初期化 @@ -51,6 +55,7 @@ componentList.setCellRenderer(createComponentRenderer()); // 各UIコンポーネントの作成と配置 + entityLabel = new JLabel("Entity:"); nameField = new JTextField(20); nameLabel = new JLabel("Name:"); posLabel = new JLabel("Position:"); @@ -66,60 +71,84 @@ scaleYField = new JTextField(5); scaleZField = new JTextField(5); + addChangeListener(posXField, posYField, posZField, rotXField, rotYField, rotZField, scaleXField, scaleYField, scaleZField, nameField); + JButton newGameObjectButton = new JButton("Add Entity"); newGameObjectButton.addActionListener(e -> createNewGameObject()); - JButton addComponentButton = new JButton("Add Component"); + JButton addComponentButton = new JButton("+ Component"); addComponentButton.addActionListener(e -> addComponentToGameObject()); - JButton removeComponentButton = new JButton("Remove Component"); + JButton removeComponentButton = new JButton("- Component"); removeComponentButton.addActionListener(e -> removeComponentFromGameObject()); - JButton applyButton = new JButton("Apply"); - applyButton.addActionListener(new ApplyButtonListener()); + int pos = 170; // 各要素の位置とサイズを設定 - 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, 180, 50, 100, 30); - setComponentBounds(posXField, 250, 50, 50, 30); - setComponentBounds(posYField, 310, 50, 50, 30); - setComponentBounds(posZField, 370, 50, 50, 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, 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(addComponentButton, 200, 250, 150, 30); - setComponentBounds(removeComponentButton, 200, 290, 150, 30); - setComponentBounds(applyButton, 200, 400, 100, 25); + setComponentBounds(entityLabel, 10, 5, 100, 30); + setComponentBounds(scrollPane, 10, 30, 150, 300); + setComponentBounds(componentScrollPane, 350, 170, 130, 165); + setComponentBounds(nameLabel, pos, 10, 100, 30); + setComponentBounds(nameField, pos+50, 10, 170, 25); + setComponentBounds(posLabel, pos, 50, 100, 30); + setComponentBounds(posXField, pos + 50, 50, 50, 30); + setComponentBounds(posYField, pos + 110, 50, 50, 30); + setComponentBounds(posZField, pos + 170, 50, 50, 30); + setComponentBounds(rotLabel, pos, 90, 100, 30); + setComponentBounds(rotXField, pos + 50, 90, 50, 30); + setComponentBounds(rotYField, pos + 110, 90, 50, 30); + setComponentBounds(rotZField, pos + 170, 90, 50, 30); + setComponentBounds(scaLabel, pos, 130, 100, 30); + setComponentBounds(scaleXField, pos + 50, 130, 50, 30); + setComponentBounds(scaleYField, pos + 110, 130, 50, 30); + setComponentBounds(scaleZField, pos + 170, 130, 50, 30); + setComponentBounds(newGameObjectButton, 200, 170, 110, 20); + setComponentBounds(addComponentButton, 200, 260, 130, 20); + setComponentBounds(removeComponentButton, 200, 290, 130, 20); objectList.addListSelectionListener(e -> { if (!e.getValueIsAdjusting()) { // ユーザーが調整中でない場合のみ - loadSelectedGameObject(); // オブジェクトをロード + loadSelectedGameObject(); // オブジェクトのプロパティをロード } }); } - private JTextField createTextField() { - return new JTextField(5); + private void addChangeListener(JTextField... fields) { + for (JTextField field : fields) { + field.addActionListener(e -> applyGameObjectChanges()); + + field.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + updateTimer.stop(); + } + + @Override + public void focusLost(FocusEvent e) { + applyGameObjectChanges(); + updateTimer.start(); + } + }); + } } - // タイマーによる定期的なリスト更新 private void initializeUpdateTimer() { - updateTimer = new Timer(1000, e -> { + updateTimer = new Timer(750, e -> { + String selectedObject = objectList.getSelectedValue(); + GameComponent selectedComponent = componentList.getSelectedValue(); + updateGameObjectList(gameScene); - if (objectList.getSelectedValue() != null) { - Entity selectedEntity = gameScene.getEntity(objectList.getSelectedValue()); + + if (selectedObject != null) { + objectList.setSelectedValue(selectedObject, true); + Entity selectedEntity = gameScene.getEntity(selectedObject); if (selectedEntity instanceof GameObject) { updateComponentList((GameObject) selectedEntity); } } + + if (selectedComponent != null) { + componentList.setSelectedValue(selectedComponent, true); + } }); updateTimer.start(); } @@ -128,14 +157,13 @@ return (list, value, index, isSelected, cellHasFocus) -> { JLabel label = new JLabel(); Entity entity = gameScene.getEntity(value); - label.setText(entity.name); + label.setText(entity.getName()); label.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground()); label.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground()); label.setOpaque(true); return label; }; } - private ListCellRenderer createComponentRenderer() { return (list, value, index, isSelected, cellHasFocus) -> { JLabel label = new JLabel(value.getClass().getSimpleName()); @@ -159,18 +187,34 @@ } private void addComponentToGameObject() { - String selectedIdStr = objectList.getSelectedValue(); - if (selectedIdStr != null) { - Entity selectedEntity = gameScene.getEntity(selectedIdStr); + // 現在の選択状態を保存 + String selectedObject = objectList.getSelectedValue(); + GameComponent selectedComponent = componentList.getSelectedValue(); + + // コンポーネントの追加処理 + if (selectedObject != null) { + Entity selectedEntity = gameScene.getEntity(selectedObject); if (selectedEntity instanceof GameObject) { GameObject gameObject = (GameObject) selectedEntity; System.out.println("仮でMeshコンポーネントを付与します"); gameScene.addComponentToGameObject(gameObject, new MoveImage(gameObject)); - updateComponentList(gameObject); // コンポーネントリストの更新 + + // リストの更新 + updateComponentList(gameObject); updateGameObjectList(gameScene); // オブジェクトリストの更新 + + //ダイアログ JOptionPane.showMessageDialog(this, "Component Added to " + selectedEntity.name); } } + + // 選択状態を復元 + if (selectedObject != null) { + objectList.setSelectedValue(selectedObject, true); + } + if (selectedComponent != null) { + componentList.setSelectedValue(selectedComponent, true); + } } private void removeComponentFromGameObject() { @@ -190,14 +234,15 @@ } private void updateGameObjectList(Scene gameScene) { - listModel.clear(); // リストの初期化 + listModel.clear(); for (Map.Entry entry : gameScene.entities.entrySet()) { Entity entity = entry.getValue(); - listModel.addElement(entity.getId()); // そのままIDをリストに追加 + listModel.addElement(entity.getId()); } - objectList.repaint(); // リストを再描画 + objectList.repaint(); } + private void updateComponentList(GameObject gameObject) { componentListModel.clear(); // リストをクリア List components = gameObject.gameComponents; @@ -207,11 +252,10 @@ componentList.repaint(); } - // 選択されたGameObjectのプロパティをロードする private void loadSelectedGameObject() { String selectedIdStr = objectList.getSelectedValue(); if (selectedIdStr != null) { - Entity selectedEntity = gameScene.getEntity(selectedIdStr); // IDのまま取得 + Entity selectedEntity = gameScene.getEntity(selectedIdStr); if (selectedEntity != null) { loadObjectProperties(selectedEntity); if (selectedEntity instanceof GameObject) { @@ -221,57 +265,81 @@ } } - // 選択されたGameObjectのプロパティを更新 - private class ApplyButtonListener implements ActionListener { - @Override - public void actionPerformed(ActionEvent e) { - applyGameObjectChanges(); - } - } - private void applyGameObjectChanges() { String selectedIdStr = objectList.getSelectedValue(); if (selectedIdStr != null) { - Entity selectedEntity = gameScene.getEntity(selectedIdStr); // IDのまま取得 + Entity selectedEntity = gameScene.getEntity(selectedIdStr); if (selectedEntity != null) { - selectedEntity.name = nameField.getText(); - selectedEntity.transform.setPosition( - Float.parseFloat(posXField.getText()), - Float.parseFloat(posYField.getText()), - Float.parseFloat(posZField.getText()) - ); - selectedEntity.transform.setRotation( - Float.parseFloat(rotXField.getText()), - Float.parseFloat(rotYField.getText()), - Float.parseFloat(rotZField.getText()) - ); - selectedEntity.transform.setScale( - Float.parseFloat(scaleXField.getText()), - Float.parseFloat(scaleYField.getText()), - Float.parseFloat(scaleZField.getText()) - ); + try { + String newName = nameField.getText(); + if (!newName.equals(lastLoadedName)) { + selectedEntity.setName(newName); + } - updateGameObjectList(gameScene); // オブジェクトリストの再描画 + Vector3f newPos = new Vector3f( + Float.parseFloat(posXField.getText()), + Float.parseFloat(posYField.getText()), + Float.parseFloat(posZField.getText()) + ); + if (!newPos.equals(lastLoadedPos)) { + selectedEntity.transform.setPosition(newPos); + } + + Vector3f newRot = new Vector3f( + Float.parseFloat(rotXField.getText()), + Float.parseFloat(rotYField.getText()), + Float.parseFloat(rotZField.getText()) + ); + if (!newRot.equals(lastLoadedRot)) { + selectedEntity.transform.setRotation(newRot); + } + + Vector3f newScale = new Vector3f( + Float.parseFloat(scaleXField.getText()), + Float.parseFloat(scaleYField.getText()), + Float.parseFloat(scaleZField.getText()) + ); + if (!newScale.equals(lastLoadedScale)) { + selectedEntity.transform.setScale(newScale); + } + + updateGameObjectList(gameScene); + + } catch (NumberFormatException e) { + JOptionPane.showMessageDialog(this, "Invalid input. Please enter valid numbers.", "Error", JOptionPane.ERROR_MESSAGE); + } } } } + public void updateListByScene(Scene gameScene) { this.gameScene = gameScene; updateGameObjectList(gameScene); } + //entityの情報を取得 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)); + nameField.setText(entity.getName()); + Vector3f pos = entity.transform.position; + posXField.setText(String.valueOf(pos.x)); + posYField.setText(String.valueOf(pos.y)); + posZField.setText(String.valueOf(pos.z)); + + Vector3f rot = entity.transform.rotation; + rotXField.setText(String.valueOf(rot.x)); + rotYField.setText(String.valueOf(rot.y)); + rotZField.setText(String.valueOf(rot.z)); + + Vector3f scale = entity.transform.scale; + scaleXField.setText(String.valueOf(scale.x)); + scaleYField.setText(String.valueOf(scale.y)); + scaleZField.setText(String.valueOf(scale.z)); + + lastLoadedName = entity.getName(); + lastLoadedPos = pos; + lastLoadedRot = rot; + lastLoadedScale = scale; } }