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