diff --git a/GameEngine/src/main/java/gameEngine/GameEditor.java b/GameEngine/src/main/java/gameEngine/GameEditor.java index 2a3a5a5..f759374 100644 --- a/GameEngine/src/main/java/gameEngine/GameEditor.java +++ b/GameEngine/src/main/java/gameEngine/GameEditor.java @@ -1,11 +1,8 @@ package gameEngine; import gameEngine.scenes.EditorScene; -import gameEngine.views.Button; +import gameEngine.views.*; import gameEngine.scenes.Scene; -import gameEngine.views.Sprite; -import gameEngine.views.Text; -import gameEngine.views.Window; public class GameEditor { private EditorScene scene; @@ -26,6 +23,8 @@ private Button createEntityViewButton; private Text createEntityViewButtonText; + private InputField inputField; + public GameEditor(Scene scene, float windowWidth, float windowHeight) { this.scene = (EditorScene) scene; this.windowWidth = windowWidth; @@ -48,6 +47,8 @@ createEntityViewButton = new Button(240, 33, 3.2f, 0.5f); createEntityViewButtonText = new Text(240 +5.25f, 30.4f, "Add Entity", 24); + inputField = new InputField(400,400,160,40,"InputField",32); + setButtonListeners(); } @@ -80,6 +81,7 @@ createMoveImageComponentViewButtonText.update(); createEntityViewButton.update(); createEntityViewButtonText.update(); + inputField.update(); } private void createFrame(){ diff --git a/GameEngine/src/main/java/gameEngine/Time.java b/GameEngine/src/main/java/gameEngine/Time.java index a020435..49abfd7 100644 --- a/GameEngine/src/main/java/gameEngine/Time.java +++ b/GameEngine/src/main/java/gameEngine/Time.java @@ -5,7 +5,7 @@ private static long lastFrameTime = System.nanoTime(); public static float deltaTime = 0; - private static final long targetFrameTimeNanos = (long) (1E9 / 120); // <- フレームタイム + private static final long targetFrameTimeNanos = (long) (1E9 / 180); // <- フレームタイム private static long lastFpsCheckTime = System.nanoTime(); private static int frameCount = 0; private static float currentFps = 0; diff --git a/GameEngine/src/main/java/gameEngine/views/InputField.java b/GameEngine/src/main/java/gameEngine/views/InputField.java new file mode 100644 index 0000000..dde292b --- /dev/null +++ b/GameEngine/src/main/java/gameEngine/views/InputField.java @@ -0,0 +1,174 @@ +package gameEngine.views; + +import gameEngine.Time; +import gameEngine.input.MouseInput; +import org.joml.Vector3f; +import gameEngine.input.Input; +import static org.lwjgl.glfw.GLFW.*; + +public class InputField { + + private Text displayText; + private boolean isFocused; + private Vector3f position; + private float width, height; + private String placeholder; + private String inputText; + private Sprite backgroundSprite; + private int cursorPosition; // カーソル位置 + private boolean showCursor; // カーソルの表示フラグ + private float cursorBlinkTimer; // カーソルの点滅タイマー + private final float CURSOR_BLINK_INTERVAL = 0.5f; // カーソルの点滅間隔(秒) + private Color defaultColor; + private Color focusColor; + + public InputField(float posX, float posY, float width, float height, String placeholder, int textSize) { + this.position = new Vector3f(posX, posY, 0); + this.width = width; + this.height = height; + this.placeholder = placeholder; + this.inputText = ""; + this.isFocused = false; + this.cursorPosition = 0; + this.showCursor = true; + this.cursorBlinkTimer = 0.0f; + + this.backgroundSprite = new Sprite(Window.resourcePath + "EditorFrame.png", posX, posY, width, height); + this.backgroundSprite.setSize(width, height); + + displayText = new Text(posX, posY, placeholder, textSize); + defaultColor = new Color(1, 1, 1, 1); // 通常時の色 + focusColor = new Color(0.7f, 0.7f, 0.7f, 1); // フォーカス中の色 + displayText.setColor(defaultColor); + } + + public void update() { + handleInput(); + updateCursorBlink(Time.deltaTime); + render(); + } + + private void handleInput() { + float mouseX = MouseInput.getX(); + float mouseY = MouseInput.getY(); + + if (Input.GetMouseButtonDown(GLFW_MOUSE_BUTTON_LEFT)) { + isFocused = isMouseOver(mouseX, mouseY); + if (isFocused) { + setCursorPositionAtMouse(mouseX); + displayText.setColor(focusColor); // フォーカス中は色を薄く + } else { + displayText.setColor(defaultColor); // フォーカスが外れたら元の色 + } + } + + if (isFocused) { + handleTextInput(); + + if (Input.GetKeyDown(GLFW_KEY_ENTER)) { + isFocused = false; // Enterで確定 + displayText.setColor(defaultColor); // 色をリセット + } + + if (Input.GetKeyDown(GLFW_KEY_BACKSPACE) && cursorPosition > 0) { + inputText = inputText.substring(0, cursorPosition - 1) + inputText.substring(cursorPosition); + cursorPosition--; + displayText.setText(inputText.isEmpty() ? placeholder : inputText); + } + } + } + + private void handleTextInput() { + boolean isShiftPressed = Input.GetKey(GLFW_KEY_LEFT_SHIFT) || Input.GetKey(GLFW_KEY_RIGHT_SHIFT); + + // 英字入力 + for (int key = GLFW_KEY_A; key <= GLFW_KEY_Z; key++) { + if (Input.GetKeyDown(key)) { + char typedChar = (char) (isShiftPressed ? key : key + 32); // シフトキーで大文字、小文字切り替え + inputText = inputText.substring(0, cursorPosition) + typedChar + inputText.substring(cursorPosition); + cursorPosition++; + displayText.setText(inputText.isEmpty() ? placeholder : inputText); + } + } + + // 数字入力 (メインの数字キー 0-9) + for (int key = GLFW_KEY_0; key <= GLFW_KEY_9; key++) { + if (Input.GetKeyDown(key)) { + char typedChar = (char) ('0' + (key - GLFW_KEY_0)); + inputText = inputText.substring(0, cursorPosition) + typedChar + inputText.substring(cursorPosition); + cursorPosition++; + displayText.setText(inputText.isEmpty() ? placeholder : inputText); + } + } + + // テンキーの数字入力 (0-9) + for (int key = GLFW_KEY_KP_0; key <= GLFW_KEY_KP_9; key++) { + if (Input.GetKeyDown(key)) { + char typedChar = (char) ('0' + (key - GLFW_KEY_KP_0)); + inputText = inputText.substring(0, cursorPosition) + typedChar + inputText.substring(cursorPosition); + cursorPosition++; + displayText.setText(inputText.isEmpty() ? placeholder : inputText); + } + } + + // Deleteキーでカーソル右側の文字を削除 + if (Input.GetKeyDown(GLFW_KEY_DELETE) && cursorPosition < inputText.length()) { + inputText = inputText.substring(0, cursorPosition) + inputText.substring(cursorPosition + 1); + displayText.setText(inputText.isEmpty() ? placeholder : inputText); + } + + // 左右キーでカーソル移動 + if (Input.GetKeyDown(GLFW_KEY_LEFT) && cursorPosition > 0) { + cursorPosition--; + } + if (Input.GetKeyDown(GLFW_KEY_RIGHT) && cursorPosition < inputText.length()) { + cursorPosition++; + } + } + + + private void updateCursorBlink(float deltaTime) { + cursorBlinkTimer += deltaTime; + if (cursorBlinkTimer > CURSOR_BLINK_INTERVAL) { + cursorBlinkTimer = 0.0f; + showCursor = !showCursor; + } + } + + private void setCursorPositionAtMouse(float mouseX) { + float relativeMouseX = mouseX - position.x; + + if (relativeMouseX <= 0) { + cursorPosition = 0; + } else if (relativeMouseX >= displayText.getDisplayedWidth()) { + cursorPosition = inputText.length(); + } else { + float cumulativeWidth = 0; + for (int i = 0; i < inputText.length(); i++) { + cumulativeWidth += displayText.getWidthAtIndex(i); // 各文字の幅を取得 + if (cumulativeWidth >= relativeMouseX) { + cursorPosition = i; // 最も近い文字位置 + break; + } + } + } + } + + public boolean isMouseOver(float mouseX, float mouseY) { + return mouseX >= position.x && mouseX <= position.x + width && + mouseY >= position.y && mouseY <= position.y + height; + } + + public void render() { + backgroundSprite.update(); + displayText.update(); + + if (isFocused && showCursor) { + float cursorX = position.x + displayText.getWidthAtIndex(cursorPosition); + float cursorHeight = displayText.getDisplayedHeight(); + Sprite sprite = new Sprite(Window.resourcePath + "button.png", cursorX, position.y, 1, 1); + sprite.setSize(2, height); + sprite.update(); + } + } +} diff --git a/GameEngine/src/main/java/gameEngine/views/Sprite.java b/GameEngine/src/main/java/gameEngine/views/Sprite.java index 60b4432..8ee8482 100644 --- a/GameEngine/src/main/java/gameEngine/views/Sprite.java +++ b/GameEngine/src/main/java/gameEngine/views/Sprite.java @@ -14,18 +14,18 @@ public Sprite(String texturePath, Vector3f pos, Vector3f scale) { this.texture = new Texture(texturePath); // テクスチャの読み込み this.position = pos; - this.rotation = new Vector3f(0,0,0); + this.rotation = new Vector3f(0, 0, 0); this.scale = scale; updateSpriteDimensions(); } public Sprite(String texturePath, float posX, float posY, float scaleX, float scaleY) { - this(texturePath, new Vector3f(posX, posY,0), new Vector3f(scaleX, scaleY ,1.0f)); + this(texturePath, new Vector3f(posX, posY, 0), new Vector3f(scaleX, scaleY , 1.0f)); updateSpriteDimensions(); } public Sprite(String texturePath) { - this(texturePath, new Vector3f(0, 0,0), new Vector3f(1.0f, 1.0f, 1.0f)); + this(texturePath, new Vector3f(0, 0, 0), new Vector3f(1.0f, 1.0f, 1.0f)); } public void update(){ @@ -45,6 +45,12 @@ updateSpriteDimensions(); } + public void setSize(float width, float height) { + float scaleX = width / spriteWidth; + float scaleY = height / spriteHeight; + setScale(scaleX, scaleY); + } + public float getDisplayedWidth() { return spriteWidth * scale.x; } @@ -81,4 +87,4 @@ endRendering(); } -} \ No newline at end of file +} diff --git a/GameEngine/src/main/java/gameEngine/views/Text.java b/GameEngine/src/main/java/gameEngine/views/Text.java index 489aa1a..8b6902f 100644 --- a/GameEngine/src/main/java/gameEngine/views/Text.java +++ b/GameEngine/src/main/java/gameEngine/views/Text.java @@ -144,6 +144,25 @@ return width * scale.x; } + public float getWidthAtIndex(int index) { + float width = 0; + float drawX = 0; + + for (int i = 0; i < index; i++) { + char ch = text.charAt(i); + if (ch == '\n') { + drawX = 0; + continue; + } + + Glyph g = fontGlyphs.get(ch); + if (g != null) { + drawX += g.width; // 文字の幅を加算 + } + } + return drawX * scale.x; + } + public float getDisplayedHeight() { int numLines = 1; // 初期行は1行 for (int i = 0; i < text.length(); i++) { @@ -153,4 +172,6 @@ } return numLines * fontHeight * scale.y; } + + } diff --git a/GameEngine/src/main/java/gameEngine/views/Window.java b/GameEngine/src/main/java/gameEngine/views/Window.java index afea17e..116d4c9 100644 --- a/GameEngine/src/main/java/gameEngine/views/Window.java +++ b/GameEngine/src/main/java/gameEngine/views/Window.java @@ -31,7 +31,7 @@ private Window() { this.width = 1200; this.height = 900; - this.title = "HelloWorld"; + this.title = "PuniPuniGameEngine"; init(); }