Overhaul mouse support and generalize direct text editing to all UI scenes

This is a large rework of the Windows64 KBM (keyboard+mouse) input layer.
It touches the mouse hover system, the mouse click dispatch, and the direct
text editing infrastructure, then applies all of it to every scene that has
text input fields or non-standard clickable elements.

MOUSE HOVER REWRITE (UIController.cpp tickInput)

The old hover code had two structural problems:

(a) Scene lookup was group-first: it iterated UI groups and checked all
layers within each group. The Tooltips layer on eUIGroup_Fullscreen (which
holds non-interactive overlays like button hints) would be found before
in-game menus on eUIGroup_Player1. The tooltip scene focusable objects
captured mouse input and prevented hover from reaching the actual menu.

Fixed by switching to layer-first lookup across all groups, and skipping
eUILayer_Tooltips entirely since those are never interactive.

(b) On tabbed menus (LaunchMoreOptionsMenu Game vs World tabs), all
controls from all tabs are registered in Flash at the same time. There was
no filtering, so controls from inactive tabs had phantom hitboxes that
overlapped the active tab controls, making certain buttons unhoverable.

Fixed by introducing parent panel tracking: each UIControl now has a
m_pParentPanel pointer, set automatically by the UI_MAP_ELEMENT macro
during mapElementsAndNames(). The hover code checks the control parent
panel against the scene GetMainPanel() and skips mismatches. This is the
same technique the Vita touch code used, but applied to mouse hover.

The coordinate conversion was also simplified. The old code had two separate
scaling paths (window dimensions for hover, display dimensions for sliders).
Now there is one conversion from window pixel coords to SWF coords using
the scene own render dimensions.

REUSING VITA TOUCH APIs FOR MOUSE (ButtonList, UIScene)

Several APIs originally gated behind __PSVITA__ are now enabled for Win64:

- UIControl_ButtonList::SetTouchFocus(x,y) and CanTouchTrigger(x,y): the
  Flash-side ActionScript methods were already registered on all platforms
  in setupControl(), only the C++ wrappers were ifdef-gated. Opening the
  ifdefs to include _WINDOWS64 lets the mouse hover code delegate to Flash
  for list item highlighting, which handles internal scrolling and item
  layout that would be impractical to replicate in C++.

- UIScene::SetFocusToElement(id): programmatic focus-by-control-ID, used as
  a fallback when Iggy focusable objects do not match the C++ hit test.

- UIScene_LaunchMoreOptionsMenu::GetMainPanel(): returns the active tab
  panel control, needed by the hover code to filter inactive tab controls.

MOUSE CLICK DISPATCH (UIScene.cpp handleMouseClick)

Left-clicking previously relied entirely on Iggy ACTION_MENU_OK dispatch,
which routes to whatever Flash considers focused. This broke for custom-
drawn elements that are not Flash buttons (crafting recipe slots), and for
scenes where Iggy focus did not match what the user visually clicked.

Added a virtual handleMouseClick(x, y) on UIScene with a default
implementation that hit-tests C++ controls. When multiple controls report
overlapping bounds (common in debug scenes where TextInputs report full
Flash-width), it picks the one whose left edge X is closest to the click.
Returns true to consume the click and suppress the normal ACTION_MENU_A
dispatch via a m_mouseClickConsumedByScene flag on UIController.

The default implementation handles buttons, text inputs, and checkboxes
(toggling state and calling handleCheckboxToggled directly).

CRAFTING MENU MOUSE CLICK (UIScene_CraftingMenu.cpp)

The crafting menu recipe slots (H slots) are rendered through Iggy custom
draw callback, not as Flash buttons. They have no focusable objects, so
mouse clicking did nothing.

The solution caches SWF-space positions during rendering: inside customDraw,
when H slot 0 and H slot 1 are drawn, the code extracts SWF coordinates
from the D3D11 transform matrix via gdraw_D3D11_CalculateCustomDraw_4J.
The X difference between slot 0 and slot 1 gives the uniform slot spacing.

handleMouseClick then uses these cached bounds to determine which recipe
slot was clicked, resets the vertical slot indices (same pattern as the
constructor), updates the highlight and vertical slots display, and re-shows
the old slot icon. This mirrors the existing controller LEFT/RIGHT
navigation in the base class handleKeyDown.

DIRECT EDIT REFACTORING (UIControl_TextInput)

The direct text editing feature (type directly into text fields instead of
opening the virtual keyboard) was originally implemented inline in
CreateWorldMenu with all the state, character consumption, cursor tracking,
caret visibility, and cooldown logic hardcoded in one scene.

Moved everything into UIControl_TextInput:
- beginDirectEdit(charLimit): captures current label, inits cursor at end
- tickDirectEdit(): consumes chars, handles Backspace/Enter/Escape, arrow
  keys (Left/Right/Home/End/Delete), enforces caret visibility every tick
  (because setLabel and Flash focus transitions continuously reset it),
  returns Confirmed/Cancelled/Continue
- cancelDirectEdit() / confirmDirectEdit(): programmatic control
- isDirectEditing() / getDirectEditCooldown() / getEditBuffer(): state query

For SWFs that lack the m_mcCaret MovieClip child (like AnvilMenu), the
existence check validates by reading a property from the resolved path,
since IggyValuePathMakeNameRef always succeeds even for undefined refs.
When no caret exists, the control inserts a _ character at the cursor
position as a visual fallback.

The caret check result is cached in m_bHasCaret/m_bCaretChecked to avoid
repeated Iggy calls that could corrupt internal state.

SCENES UPDATED WITH DIRECT EDIT + VIRTUAL KEYBOARD

Every scene with text input now supports both input modes: direct editing
when KBM is active, virtual keyboard (via NavigateToScene eUIScene_Keyboard)
when using a controller. The mode is chosen at press time based on
g_KBMInput.IsKBMActive().

- CreateWorldMenu: refactored to use the new UIControl_TextInput API,
  removing ~80 lines of inline editing code.

- AnvilMenu: item renaming now supports direct edit. The keyboard callback
  uses Win64_GetKeyboardText instead of InputManager.GetText (which reads
  from a different buffer on Win64). The virtual keyboard is opened with
  eUILayer_Fullscreen + eUIGroup_Fullscreen so it does not hide the anvil
  container menu underneath. Added null guards on getMovie() in setCostLabel
  and showCross since the AnvilMenu SWF may not fully load on Win64.

- SignEntryMenu: all 4 sign lines support direct edit. Clicking a different
  line while editing confirms the current one. Each line cooldown timer
  is checked independently to prevent Enter from re-opening the edit.

- LaunchMoreOptionsMenu: seed field direct edit with proper input blocking.

- DebugCreateSchematic: all 7 text inputs (name + start/end XYZ coords).
  handleMouseClick is overridden to always consume clicks during edit to
  prevent Iggy re-entry on empty space.

- DebugSetCamera: all 5 inputs (camera XYZ + Y rotation + elevation).
  Clicking a different field while editing confirms the current value and
  opens the new one. Float display formatting changed from %f to %.2f.

All keyboard completion callbacks on Win64 now use Win64_GetKeyboardText
(two params: buffer + size) instead of InputManager.GetText, which reads
from the correct g_Win64KeyboardResult global when using the in-game
keyboard scene.

SCROLL WHEEL

Mouse wheel events (ACTION_MENU_OTHER_STICK_UP/DOWN) are now centrally
remapped to ACTION_MENU_UP/DOWN in UIController::handleKeyPress when KBM
is active. Previously each scene would need to handle OTHER_STICK actions
separately, and most did not, so scroll wheel only worked in a few places.
This commit is contained in:
MrTheShy 2026-03-06 04:01:19 +01:00
parent cb46908268
commit 3c5613b8aa
23 changed files with 976 additions and 191 deletions

View file

@ -12,6 +12,8 @@ UIControl::UIControl()
m_isVisible = true;
m_bHidden = false;
m_eControlType = eNoControl;
m_id = -1;
m_pParentPanel = NULL;
}
bool UIControl::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName)

View file

@ -38,12 +38,14 @@ protected:
bool m_bHidden; // set by the Remove call
public:
UIControl *m_pParentPanel; // set by UI_MAP_ELEMENT macro during mapElementsAndNames
void setControlType(eUIControlType eType) {m_eControlType=eType;}
eUIControlType getControlType() {return m_eControlType;}
void setId(int iID) { m_id=iID; }
int getId() { return m_id; }
UIScene * getParentScene() {return m_parentScene;}
UIControl* getParentPanel() { return m_pParentPanel; }
protected:
IggyValuePath m_iggyPath;

View file

@ -159,7 +159,7 @@ void UIControl_ButtonList::setButtonLabel(int iButtonId, const wstring &label)
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcSetButtonLabel, 2 , value );
}
#ifdef __PSVITA__
#if defined(__PSVITA__) || defined(_WINDOWS64)
void UIControl_ButtonList::SetTouchFocus(S32 iX, S32 iY, bool bRepeat)
{
IggyDataValue result;

View file

@ -37,7 +37,7 @@ public:
void setButtonLabel(int iButtonId, const wstring &label);
#ifdef __PSVITA__
#if defined(__PSVITA__) || defined(_WINDOWS64)
void SetTouchFocus(S32 iX, S32 iY, bool bRepeat);
bool CanTouchTrigger(S32 iX, S32 iY);
#endif

View file

@ -5,6 +5,15 @@
UIControl_TextInput::UIControl_TextInput()
{
m_bHasFocus = false;
m_bHasCaret = false;
m_bCaretChecked = false;
#ifdef _WINDOWS64
m_bDirectEditing = false;
m_iCursorPos = 0;
m_iCharLimit = 0;
m_iDirectEditCooldown = 0;
m_iCaretBlinkTimer = 0;
#endif
}
bool UIControl_TextInput::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName)
@ -85,7 +94,27 @@ void UIControl_TextInput::SetCharLimit(int iLimit)
void UIControl_TextInput::setCaretVisible(bool visible)
{
// Always send to Flash — Iggy's focus system can re-enable the caret at any time
// Check once whether this SWF's FJ_TextInput actually has a m_mcCaret child.
// IggyValuePathMakeNameRef always succeeds (creates a ref to undefined),
// so we validate by trying to read a property from the resolved path.
if (!m_bCaretChecked)
{
IggyValuePath caretPath;
if (IggyValuePathMakeNameRef(&caretPath, getIggyValuePath(), "m_mcCaret"))
{
rrbool test = false;
IggyResult res = IggyValueGetBooleanRS(&caretPath, m_nameVisible, NULL, &test);
m_bHasCaret = (res == 0);
}
else
{
m_bHasCaret = false;
}
m_bCaretChecked = true;
}
if (!m_bHasCaret)
return;
IggyValuePath caretPath;
if (IggyValuePathMakeNameRef(&caretPath, getIggyValuePath(), "m_mcCaret"))
{
@ -101,3 +130,152 @@ void UIControl_TextInput::setCaretIndex(int index)
value[0].number = index;
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcSetCaretIndex , 1 , value );
}
#ifdef _WINDOWS64
void UIControl_TextInput::beginDirectEdit(int charLimit)
{
const wchar_t* current = getLabel();
m_editBuffer = current ? current : L"";
m_textBeforeEdit = m_editBuffer;
m_iCursorPos = (int)m_editBuffer.length();
m_iCharLimit = charLimit;
m_bDirectEditing = true;
m_iDirectEditCooldown = 0;
m_iCaretBlinkTimer = 0;
g_KBMInput.ClearCharBuffer();
setCaretVisible(true);
setCaretIndex(m_iCursorPos);
}
UIControl_TextInput::EDirectEditResult UIControl_TextInput::tickDirectEdit()
{
if (m_iDirectEditCooldown > 0)
m_iDirectEditCooldown--;
if (!m_bDirectEditing)
{
setCaretVisible(false);
return eDirectEdit_Continue;
}
// Enforce caret visibility and position every tick — setLabel() and Flash
// focus changes can reset both at any time.
setCaretVisible(true);
setCaretIndex(m_iCursorPos);
// For SWFs without m_mcCaret, insert '_' at the cursor position.
// All characters remain visible — '_' sits between them like a cursor.
if (!m_bHasCaret)
{
wstring display = m_editBuffer;
display.insert(m_iCursorPos, 1, L'_');
setLabel(display.c_str());
}
EDirectEditResult result = eDirectEdit_Continue;
bool changed = false;
// Consume typed characters from the KBM buffer
wchar_t ch;
while (g_KBMInput.ConsumeChar(ch))
{
if (ch == 0x08) // Backspace
{
if (m_iCursorPos > 0)
{
m_editBuffer.erase(m_iCursorPos - 1, 1);
m_iCursorPos--;
changed = true;
}
}
else if (ch == 0x0D) // Enter — confirm edit
{
m_bDirectEditing = false;
m_iDirectEditCooldown = 4;
setLabel(m_editBuffer.c_str());
setCaretVisible(false);
return eDirectEdit_Confirmed;
}
else if (m_iCharLimit <= 0 || (int)m_editBuffer.length() < m_iCharLimit)
{
m_editBuffer.insert(m_iCursorPos, 1, ch);
m_iCursorPos++;
changed = true;
}
}
// Arrow keys, Home, End, Delete for cursor movement
if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0)
{
m_iCursorPos--;
setCaretIndex(m_iCursorPos);
}
if (g_KBMInput.IsKeyPressed(VK_RIGHT) && m_iCursorPos < (int)m_editBuffer.length())
{
m_iCursorPos++;
setCaretIndex(m_iCursorPos);
}
if (g_KBMInput.IsKeyPressed(VK_HOME))
{
m_iCursorPos = 0;
setCaretIndex(m_iCursorPos);
}
if (g_KBMInput.IsKeyPressed(VK_END))
{
m_iCursorPos = (int)m_editBuffer.length();
setCaretIndex(m_iCursorPos);
}
if (g_KBMInput.IsKeyPressed(VK_DELETE) && m_iCursorPos < (int)m_editBuffer.length())
{
m_editBuffer.erase(m_iCursorPos, 1);
changed = true;
}
// Escape — cancel edit and restore original text
if (g_KBMInput.IsKeyPressed(VK_ESCAPE))
{
m_editBuffer = m_textBeforeEdit;
m_bDirectEditing = false;
m_iDirectEditCooldown = 4;
setLabel(m_editBuffer.c_str());
setCaretVisible(false);
return eDirectEdit_Cancelled;
}
if (changed)
{
if (m_bHasCaret)
{
setLabel(m_editBuffer.c_str());
setCaretIndex(m_iCursorPos);
}
// SWFs without caret: the cursor block above already updates the label every tick
}
return eDirectEdit_Continue;
}
void UIControl_TextInput::cancelDirectEdit()
{
if (m_bDirectEditing)
{
m_editBuffer = m_textBeforeEdit;
m_bDirectEditing = false;
m_iDirectEditCooldown = 4;
setLabel(m_editBuffer.c_str());
setCaretVisible(false);
}
}
void UIControl_TextInput::confirmDirectEdit()
{
if (m_bDirectEditing)
{
m_bDirectEditing = false;
setLabel(m_editBuffer.c_str());
setCaretVisible(false);
}
}
#endif

View file

@ -8,6 +8,18 @@ private:
IggyName m_textName, m_funcChangeState, m_funcSetCharLimit;
IggyName m_funcSetCaretIndex;
bool m_bHasFocus;
bool m_bHasCaret;
bool m_bCaretChecked;
#ifdef _WINDOWS64
bool m_bDirectEditing;
wstring m_textBeforeEdit;
wstring m_editBuffer;
int m_iCursorPos;
int m_iCharLimit;
int m_iDirectEditCooldown;
int m_iCaretBlinkTimer;
#endif
public:
UIControl_TextInput();
@ -23,4 +35,21 @@ public:
void setCaretVisible(bool visible);
void setCaretIndex(int index);
#ifdef _WINDOWS64
enum EDirectEditResult
{
eDirectEdit_Continue,
eDirectEdit_Confirmed,
eDirectEdit_Cancelled,
};
void beginDirectEdit(int charLimit = 0);
EDirectEditResult tickDirectEdit();
void cancelDirectEdit();
void confirmDirectEdit();
bool isDirectEditing() const { return m_bDirectEditing; }
int getDirectEditCooldown() const { return m_iDirectEditCooldown; }
const wstring& getEditBuffer() const { return m_editBuffer; }
#endif
};

View file

@ -237,6 +237,7 @@ UIController::UIController()
m_winUserIndex = 0;
m_mouseDraggingSliderScene = eUIScene_COUNT;
m_mouseDraggingSliderId = -1;
m_mouseClickConsumedByScene = false;
m_lastHoverMouseX = -1;
m_lastHoverMouseY = -1;
m_accumulatedTicks = 0;
@ -784,40 +785,36 @@ void UIController::tickInput()
#endif
{
#ifdef _WINDOWS64
m_mouseClickConsumedByScene = false;
if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
{
UIScene *pScene = NULL;
for (int grp = 0; grp < eUIGroup_COUNT && !pScene; ++grp)
// Search by layer priority across all groups (layer-first).
// Tooltip layer is skipped because it holds non-interactive
// overlays (button hints, timer) that should never capture mouse.
// Old group-first order found those tooltips on eUIGroup_Fullscreen
// before reaching in-game menus on eUIGroup_Player1.
static const EUILayer mouseLayers[] = {
#ifndef _CONTENT_PACKAGE
eUILayer_Debug,
#endif
eUILayer_Error,
eUILayer_Alert,
eUILayer_Popup,
eUILayer_Fullscreen,
eUILayer_Scene,
};
for (int l = 0; l < _countof(mouseLayers) && !pScene; ++l)
{
pScene = m_groups[grp]->GetTopScene(eUILayer_Debug);
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Tooltips);
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Error);
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Alert);
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Popup);
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Fullscreen);
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Scene);
for (int grp = 0; grp < eUIGroup_COUNT && !pScene; ++grp)
{
pScene = m_groups[grp]->GetTopScene(mouseLayers[l]);
}
}
if (pScene && pScene->getMovie())
{
Iggy *movie = pScene->getMovie();
int rawMouseX = g_KBMInput.GetMouseX();
int rawMouseY = g_KBMInput.GetMouseY();
F32 mouseX = (F32)rawMouseX;
F32 mouseY = (F32)rawMouseY;
extern HWND g_hWnd;
if (g_hWnd)
{
RECT rc;
GetClientRect(g_hWnd, &rc);
int winW = rc.right - rc.left;
int winH = rc.bottom - rc.top;
if (winW > 0 && winH > 0)
{
mouseX = mouseX * (m_fScreenWidth / (F32)winW);
mouseY = mouseY * (m_fScreenHeight / (F32)winH);
}
}
// Only update hover focus when the mouse has actually moved,
// so that mouse-wheel scrolling can change list selection
@ -826,43 +823,21 @@ void UIController::tickInput()
m_lastHoverMouseX = rawMouseX;
m_lastHoverMouseY = rawMouseY;
if (mouseMoved)
// Convert mouse to scene/movie coordinates
F32 sceneMouseX = (F32)rawMouseX;
F32 sceneMouseY = (F32)rawMouseY;
{
IggyFocusHandle currentFocus = IGGY_FOCUS_NULL;
IggyFocusableObject focusables[64];
S32 numFocusables = 0;
IggyPlayerGetFocusableObjects(movie, &currentFocus, focusables, 64, &numFocusables);
if (numFocusables > 0 && numFocusables <= 64)
extern HWND g_hWnd;
RECT rc;
if (g_hWnd && GetClientRect(g_hWnd, &rc))
{
IggyFocusHandle hitObject = IGGY_FOCUS_NULL;
for (S32 i = 0; i < numFocusables; ++i)
int winW = rc.right - rc.left;
int winH = rc.bottom - rc.top;
if (winW > 0 && winH > 0)
{
if (mouseX >= focusables[i].x0 && mouseX <= focusables[i].x1 &&
mouseY >= focusables[i].y0 && mouseY <= focusables[i].y1)
{
hitObject = focusables[i].object;
break;
}
sceneMouseX = sceneMouseX * ((F32)pScene->getRenderWidth() / (F32)winW);
sceneMouseY = sceneMouseY * ((F32)pScene->getRenderHeight() / (F32)winH);
}
if (hitObject != IGGY_FOCUS_NULL && hitObject != currentFocus)
{
IggyPlayerSetFocusRS(movie, hitObject, 0);
}
}
}
// Convert mouse to scene/movie coordinates for slider hit testing
F32 sceneMouseX = mouseX;
F32 sceneMouseY = mouseY;
{
S32 displayWidth = 0, displayHeight = 0;
pScene->GetParentLayer()->getRenderDimensions(displayWidth, displayHeight);
if (displayWidth > 0 && displayHeight > 0)
{
sceneMouseX = mouseX * ((F32)pScene->getRenderWidth() / (F32)displayWidth);
sceneMouseY = mouseY * ((F32)pScene->getRenderHeight() / (F32)displayHeight);
}
}
@ -876,6 +851,105 @@ void UIController::tickInput()
panelOffsetY = pMainPanel->getYPos();
}
// Mouse hover — hit test against C++ control bounds.
// Simple controls use SetFocusToElement; list controls
// use their own SetTouchFocus for Flash-side hit testing.
if (mouseMoved)
{
vector<UIControl *> *controls = pScene->GetControls();
if (controls)
{
int hitControlId = -1;
S32 hitCx = -1;
for (size_t i = 0; i < controls->size(); ++i)
{
UIControl *ctrl = (*controls)[i];
if (!ctrl || !ctrl->getVisible() || ctrl->getId() < 0)
continue;
UIControl::eUIControlType type = ctrl->getControlType();
if (type != UIControl::eButton && type != UIControl::eTextInput &&
type != UIControl::eCheckBox && type != UIControl::eSlider &&
type != UIControl::eButtonList)
continue;
// If the scene has an active panel (e.g. tab menus),
// skip controls that aren't children of that panel.
if (pMainPanel && ctrl->getParentPanel() != pMainPanel)
continue;
ctrl->UpdateControl();
S32 cx = ctrl->getXPos() + panelOffsetX;
S32 cy = ctrl->getYPos() + panelOffsetY;
S32 cw = ctrl->getWidth();
S32 ch = ctrl->getHeight();
if (cw <= 0 || ch <= 0)
continue;
if (sceneMouseX >= cx && sceneMouseX <= cx + cw &&
sceneMouseY >= cy && sceneMouseY <= cy + ch)
{
if (type == UIControl::eButtonList)
{
// ButtonList manages focus internally via Flash —
// pass mouse coords so it can highlight the right item.
((UIControl_ButtonList *)ctrl)->SetTouchFocus(
(S32)sceneMouseX, (S32)sceneMouseY, false);
hitControlId = -1;
hitCx = -1;
break; // ButtonList takes priority
}
else if (cx > hitCx)
{
// When multiple controls overlap (e.g. debug scenes
// with side-by-side TextInputs reporting full width),
// pick the one whose left edge is closest to mouse X.
hitControlId = ctrl->getId();
hitCx = cx;
}
}
}
if (hitControlId >= 0 && pScene->getControlFocus() != hitControlId)
{
// Set focus via Iggy's internal focus system so that
// action dispatch (ACTION_MENU_OK) targets the right
// control. SetFocusToElement calls Flash's AS SetFocus
// which triggers full focus behavior (including caret
// visibility on TextInputs), so prefer IggyPlayerSetFocusRS.
Iggy *movie = pScene->getMovie();
IggyFocusHandle currentFocus = IGGY_FOCUS_NULL;
IggyFocusableObject focusables[64];
S32 numFocusables = 0;
IggyPlayerGetFocusableObjects(movie, &currentFocus, focusables, 64, &numFocusables);
// Iggy focusable bounds may overlap (same wide-width issue
// as C++ bounds). Pick the one with largest x0 <= mouseX.
bool iggyFocusSet = false;
S32 bestFocusX0 = -1;
S32 bestFocusIdx = -1;
for (S32 fi = 0; fi < numFocusables && fi < 64; ++fi)
{
if (sceneMouseX >= focusables[fi].x0 && sceneMouseX <= focusables[fi].x1 &&
sceneMouseY >= focusables[fi].y0 && sceneMouseY <= focusables[fi].y1)
{
if (focusables[fi].x0 > bestFocusX0)
{
bestFocusX0 = focusables[fi].x0;
bestFocusIdx = fi;
}
}
}
if (bestFocusIdx >= 0)
{
IggyPlayerSetFocusRS(movie, focusables[bestFocusIdx].object, 0);
iggyFocusSet = true;
}
if (!iggyFocusSet)
pScene->SetFocusToElement(hitControlId);
}
}
}
bool leftPressed = g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT);
bool leftDown = leftPressed || g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT);
@ -890,12 +964,51 @@ void UIController::tickInput()
vector<UIControl *> *controls = pScene->GetControls();
if (controls)
{
// Set Iggy dispatch focus for TextInput on click (not hover)
// so ACTION_MENU_OK targets the correct text field.
for (size_t i = 0; i < controls->size(); ++i)
{
UIControl *ctrl = (*controls)[i];
if (!ctrl || ctrl->getControlType() != UIControl::eTextInput || !ctrl->getVisible())
continue;
if (pMainPanel && ctrl->getParentPanel() != pMainPanel)
continue;
ctrl->UpdateControl();
S32 cx = ctrl->getXPos() + panelOffsetX;
S32 cy = ctrl->getYPos() + panelOffsetY;
S32 cw = ctrl->getWidth();
S32 ch = ctrl->getHeight();
if (cw > 0 && ch > 0 &&
sceneMouseX >= cx && sceneMouseX <= cx + cw &&
sceneMouseY >= cy && sceneMouseY <= cy + ch)
{
Iggy *movie = pScene->getMovie();
IggyFocusHandle currentFocus = IGGY_FOCUS_NULL;
IggyFocusableObject focusables[64];
S32 numFocusables = 0;
IggyPlayerGetFocusableObjects(movie, &currentFocus, focusables, 64, &numFocusables);
for (S32 fi = 0; fi < numFocusables && fi < 64; ++fi)
{
if (sceneMouseX >= focusables[fi].x0 && sceneMouseX <= focusables[fi].x1 &&
sceneMouseY >= focusables[fi].y0 && sceneMouseY <= focusables[fi].y1)
{
IggyPlayerSetFocusRS(movie, focusables[fi].object, 0);
break;
}
}
break;
}
}
for (size_t i = 0; i < controls->size(); ++i)
{
UIControl *ctrl = (*controls)[i];
if (!ctrl || ctrl->getControlType() != UIControl::eSlider || !ctrl->getVisible())
continue;
if (pMainPanel && ctrl->getParentPanel() != pMainPanel)
continue;
UIControl_Slider *pSlider = (UIControl_Slider *)ctrl;
pSlider->UpdateControl();
S32 cx = pSlider->getXPos() + panelOffsetX;
@ -942,6 +1055,12 @@ void UIController::tickInput()
m_mouseDraggingSliderScene = eUIScene_COUNT;
m_mouseDraggingSliderId = -1;
}
// Let the scene handle mouse clicks for custom navigation (e.g. crafting slots)
if (leftPressed && m_mouseDraggingSliderId < 0)
{
m_mouseClickConsumedByScene = pScene->handleMouseClick(sceneMouseX, sceneMouseY);
}
}
}
#endif
@ -1206,7 +1325,7 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
if ((key == ACTION_MENU_OK || key == ACTION_MENU_A) && !g_KBMInput.IsMouseGrabbed())
{
if (m_mouseDraggingSliderId < 0)
if (m_mouseDraggingSliderId < 0 && !m_mouseClickConsumedByScene)
{
if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT)) { pressed = true; down = true; }
if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT)) { released = true; down = false; }
@ -1231,6 +1350,13 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
pressed = true;
down = true;
}
// Remap scroll wheel to UP/DOWN so all scenes get it without
// needing per-scene OTHER_STICK handling.
if (pressed && g_KBMInput.IsKBMActive())
{
key = (key == ACTION_MENU_OTHER_STICK_UP) ? ACTION_MENU_UP : ACTION_MENU_DOWN;
}
}
}
#endif

View file

@ -160,6 +160,7 @@ private:
unsigned int m_winUserIndex;
EUIScene m_mouseDraggingSliderScene;
int m_mouseDraggingSliderId;
bool m_mouseClickConsumedByScene;
int m_lastHoverMouseX;
int m_lastHoverMouseY;
//bool m_bSysUIShowing;

View file

@ -234,7 +234,7 @@ void UIScene::initialiseMovie()
m_bUpdateOpacity = true;
}
#ifdef __PSVITA__
#if defined(__PSVITA__) || defined(_WINDOWS64)
void UIScene::SetFocusToElement(int iID)
{
IggyDataValue result;
@ -454,6 +454,80 @@ UIControl* UIScene::GetMainPanel()
return NULL;
}
#ifdef _WINDOWS64
bool UIScene::handleMouseClick(F32 x, F32 y)
{
S32 panelOffsetX = 0, panelOffsetY = 0;
UIControl *pMainPanel = GetMainPanel();
if (pMainPanel)
{
pMainPanel->UpdateControl();
panelOffsetX = pMainPanel->getXPos();
panelOffsetY = pMainPanel->getYPos();
}
vector<UIControl *> *controls = GetControls();
if (!controls) return false;
// Flash may report overlapping bounds for side-by-side controls (e.g.
// TextInputs with full 630px width in debug scenes). Among all controls
// that contain the click point, pick the one whose left edge (cx) is
// closest to the click X — i.e. largest cx that is still <= x.
int bestId = -1;
S32 bestCx = -1;
UIControl *bestCtrl = NULL;
for (size_t i = 0; i < controls->size(); ++i)
{
UIControl *ctrl = (*controls)[i];
if (!ctrl || !ctrl->getVisible() || ctrl->getId() < 0)
continue;
UIControl::eUIControlType type = ctrl->getControlType();
if (type != UIControl::eButton && type != UIControl::eTextInput &&
type != UIControl::eCheckBox)
continue;
if (pMainPanel && ctrl->getParentPanel() != pMainPanel)
continue;
ctrl->UpdateControl();
S32 cx = ctrl->getXPos() + panelOffsetX;
S32 cy = ctrl->getYPos() + panelOffsetY;
S32 cw = ctrl->getWidth();
S32 ch = ctrl->getHeight();
if (cw <= 0 || ch <= 0)
continue;
if (x >= cx && x <= cx + cw && y >= cy && y <= cy + ch)
{
if (cx > bestCx)
{
bestCx = cx;
bestId = ctrl->getId();
bestCtrl = ctrl;
}
}
}
if (bestId >= 0 && bestCtrl)
{
if (bestCtrl->getControlType() == UIControl::eCheckBox)
{
UIControl_CheckBox *cb = (UIControl_CheckBox *)bestCtrl;
bool newState = !cb->IsChecked();
cb->setChecked(newState);
handleCheckboxToggled((F64)bestId, newState);
}
else
{
handlePress((F64)bestId, 0);
}
return true;
}
return false;
}
#endif
void UIScene::addTimer(int id, int ms)
{

View file

@ -16,22 +16,26 @@ class UILayer;
virtual bool mapElementsAndNames() \
{ \
parentClass::mapElementsAndNames(); \
IggyValuePath *currentRoot = IggyPlayerRootPath ( getMovie() );
IggyValuePath *currentRoot = IggyPlayerRootPath ( getMovie() ); \
UIControl *_mapPanel = NULL;
#define UI_END_MAP_ELEMENTS_AND_NAMES() \
return true; \
}
#define UI_MAP_ELEMENT( var, name) \
{ var.setupControl(this, currentRoot , name ); m_controls.push_back(&var); }
{ var.setupControl(this, currentRoot , name ); var.m_pParentPanel = _mapPanel; m_controls.push_back(&var); }
#define UI_BEGIN_MAP_CHILD_ELEMENTS( parent ) \
{ \
IggyValuePath *lastRoot = currentRoot; \
currentRoot = parent.getIggyValuePath();
UIControl *_lastPanel = _mapPanel; \
currentRoot = parent.getIggyValuePath(); \
_mapPanel = &parent;
#define UI_END_MAP_CHILD_ELEMENTS() \
currentRoot = lastRoot; \
_mapPanel = _lastPanel; \
}
#define UI_MAP_NAME( var, name ) \
@ -141,8 +145,10 @@ public:
virtual void tick();
IggyName registerFastName(const wstring &name);
#if defined(__PSVITA__) || defined(_WINDOWS64)
void SetFocusToElement(int iID);
#endif
#ifdef __PSVITA__
void SetFocusToElement(int iID);
void UpdateSceneControls();
#endif
protected:
@ -177,6 +183,13 @@ public:
// returns main panel if controls are not living in the root
virtual UIControl* GetMainPanel();
#ifdef _WINDOWS64
// Mouse click dispatch. Default implementation hit-tests C++ controls with
// "best match" logic (largest left-edge X) to handle overlapping Flash bounds,
// then calls the virtual handlePress. Override for custom behaviour (e.g. crafting).
virtual bool handleMouseClick(F32 x, F32 y);
#endif
void removeControl( UIControl_Base *control, bool centreScene);
void slideLeft();
void slideRight();

View file

@ -96,6 +96,15 @@ void UIScene_AnvilMenu::tick()
{
UIScene_AbstractContainerMenu::tick();
#ifdef _WINDOWS64
UIControl_TextInput::EDirectEditResult editResult = m_textInputAnvil.tickDirectEdit();
if (editResult == UIControl_TextInput::eDirectEdit_Confirmed)
{
m_itemName = m_textInputAnvil.getEditBuffer();
updateItemName();
}
#endif
handleTick();
}
@ -308,24 +317,52 @@ UIControl *UIScene_AnvilMenu::getSection(ESceneSection eSection)
int UIScene_AnvilMenu::KeyboardCompleteCallback(LPVOID lpParam,bool bRes)
{
// 4J HEG - No reason to set value if keyboard was cancelled
UIScene_AnvilMenu *pClass=(UIScene_AnvilMenu *)lpParam;
pClass->setIgnoreInput(false);
if (bRes)
{
#ifdef _WINDOWS64
uint16_t pchText[128];
ZeroMemory(pchText, 128 * sizeof(uint16_t));
Win64_GetKeyboardText(pchText, 128);
pClass->setEditNameValue((wchar_t *)pchText);
pClass->m_itemName = (wchar_t *)pchText;
pClass->updateItemName();
#else
uint16_t pchText[128];
ZeroMemory(pchText, 128 * sizeof(uint16_t) );
InputManager.GetText(pchText);
pClass->setEditNameValue((wchar_t *)pchText);
pClass->m_itemName = (wchar_t *)pchText;
pClass->updateItemName();
#endif
}
return 0;
}
void UIScene_AnvilMenu::handleEditNamePressed()
{
#ifdef _WINDOWS64
if (m_textInputAnvil.isDirectEditing() || m_textInputAnvil.getDirectEditCooldown() > 0)
return;
if (g_KBMInput.IsKBMActive())
{
m_textInputAnvil.beginDirectEdit(30);
}
else
{
setIgnoreInput(true);
UIKeyboardInitData kbData;
kbData.title = app.GetString(IDS_TITLE_RENAME);
kbData.defaultText = m_textInputAnvil.getLabel();
kbData.maxChars = 30;
kbData.callback = &UIScene_AnvilMenu::KeyboardCompleteCallback;
kbData.lpParam = this;
ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData, eUILayer_Fullscreen, eUIGroup_Fullscreen);
}
#else
setIgnoreInput(true);
#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__
int language = XGetLanguage();
@ -337,13 +374,13 @@ void UIScene_AnvilMenu::handleEditNamePressed()
InputManager.RequestKeyboard(app.GetString(IDS_TITLE_RENAME),m_textInputAnvil.getLabel(),(DWORD)m_iPad,30,&UIScene_AnvilMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default);
break;
default:
// 4J Stu - Use a different keyboard for non-asian languages so we don't have prediction on
InputManager.RequestKeyboard(app.GetString(IDS_TITLE_RENAME),m_textInputAnvil.getLabel(),(DWORD)m_iPad,30,&UIScene_AnvilMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Alphabet_Extended);
break;
}
#else
InputManager.RequestKeyboard(app.GetString(IDS_TITLE_RENAME),m_textInputAnvil.getLabel(),(DWORD)m_iPad,30,&UIScene_AnvilMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default);
#endif
#endif
}
void UIScene_AnvilMenu::setEditNameValue(const wstring &name)
@ -357,6 +394,8 @@ void UIScene_AnvilMenu::setEditNameEditable(bool enabled)
void UIScene_AnvilMenu::setCostLabel(const wstring &label, bool canAfford)
{
if (!getMovie()) return;
IggyDataValue result;
IggyDataValue value[2];
@ -375,6 +414,8 @@ void UIScene_AnvilMenu::showCross(bool show)
{
if(m_showingCross != show)
{
if (!getMovie()) return;
IggyDataValue result;
IggyDataValue value[1];

View file

@ -4,6 +4,9 @@
#include "..\..\MultiplayerLocalPlayer.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h"
#include "UIScene_CraftingMenu.h"
#ifdef _WINDOWS64
#include "..\..\Windows64\Iggy\gdraw\gdraw_d3d11.h"
#endif
#ifdef __PSVITA__
#define GAME_CRAFTING_TOUCHUPDATE_TIMER_ID 0
@ -12,6 +15,11 @@
UIScene_CraftingMenu::UIScene_CraftingMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
#ifdef _WINDOWS64
m_hSlotBoundsValid = false;
m_hSlotX0 = m_hSlotY0 = m_hSlotY1 = 0;
m_hSlotSpacing = 0;
#endif
m_bIgnoreKeyPresses = false;
CraftingPanelScreenInput* initData = (CraftingPanelScreenInput*)_initData;
@ -383,6 +391,39 @@ void UIScene_CraftingMenu::handleTimerComplete(int id)
}
#endif
#ifdef _WINDOWS64
bool UIScene_CraftingMenu::handleMouseClick(F32 x, F32 y)
{
if (!m_hSlotBoundsValid)
return false;
F32 rowWidth = m_hSlotSpacing * m_iCraftablesMaxHSlotC;
if (m_hSlotSpacing > 0 && x >= m_hSlotX0 && x < m_hSlotX0 + rowWidth &&
y >= m_hSlotY0 && y < m_hSlotY1)
{
int iNewSlot = (int)((x - m_hSlotX0) / m_hSlotSpacing);
if (iNewSlot >= 0 && iNewSlot < m_iCraftablesMaxHSlotC)
{
int iOldHSlot = m_iCurrentSlotHIndex;
m_iCurrentSlotHIndex = iNewSlot;
m_iCurrentSlotVIndex = 1;
iVSlotIndexA[0] = CanBeMadeA[m_iCurrentSlotHIndex].iCount - 1;
iVSlotIndexA[1] = 0;
iVSlotIndexA[2] = 1;
UpdateVerticalSlots();
UpdateHighlight();
if (CanBeMadeA[iOldHSlot].iCount > 0)
setShowCraftHSlot(iOldHSlot, true);
ui.PlayUISFX(eSFX_Focus);
return true;
}
}
return false;
}
#endif
void UIScene_CraftingMenu::handleReload()
{
m_slotListInventory.addSlots(CRAFTING_INVENTORY_SLOT_START,CRAFTING_INVENTORY_SLOT_END - CRAFTING_INVENTORY_SLOT_START);
@ -478,6 +519,32 @@ void UIScene_CraftingMenu::customDraw(IggyCustomDrawCallbackRegion *region)
{
decorations = false;
int iIndex = slotId - CRAFTING_H_SLOT_START;
#ifdef _WINDOWS64
// Cache H slot SWF-space positions from the custom draw transform matrix
if (iIndex == 0 || iIndex == 1)
{
F32 mat[16];
gdraw_D3D11_CalculateCustomDraw_4J(region, mat);
// Matrix to SWF coords (same formula as setupCustomDrawMatrices)
F32 sw = (F32)getRenderWidth();
F32 sh = (F32)getRenderHeight();
F32 swfX = sw * (1.0f + mat[3]) / 2.0f;
F32 swfY = sh * (1.0f - mat[7]) / 2.0f;
if (iIndex == 0)
{
m_hSlotX0 = swfX;
m_hSlotY0 = swfY;
// Slot visual height from matrix scale and region height
F32 slotH = sh * (-mat[5]) / 2.0f * region->y1;
m_hSlotY1 = swfY + slotH;
}
else
{
m_hSlotSpacing = swfX - m_hSlotX0;
m_hSlotBoundsValid = (m_hSlotSpacing > 0);
}
}
#endif
if(m_hSlotsInfo[iIndex].show)
{
item = m_hSlotsInfo[iIndex].item;

View file

@ -70,6 +70,13 @@ public:
virtual void handleTouchBoxRebuild();
virtual void handleTimerComplete(int id);
#endif
#ifdef _WINDOWS64
virtual bool handleMouseClick(F32 x, F32 y);
// Cached from customDraw — H slot bounding boxes in SWF space
F32 m_hSlotX0, m_hSlotY0, m_hSlotY1;
F32 m_hSlotSpacing; // x distance between slot 0 and slot 1
bool m_hSlotBoundsValid;
#endif
protected:
UIControl m_controlMainPanel;

View file

@ -84,11 +84,6 @@ UIScene_CreateWorldMenu::UIScene_CreateWorldMenu(int iPad, void *initData, UILay
m_iGameModeId = GameType::SURVIVAL->getId();
m_pDLCPack = NULL;
m_bRebuildTouchBoxes = false;
#ifdef _WINDOWS64
m_bDirectEditing = false;
m_iDirectEditCooldown = 0;
m_iCursorPos = 0;
#endif
m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
// 4J-PB - read the settings for the online flag. We'll only save this setting if the user changed it.
@ -295,92 +290,11 @@ void UIScene_CreateWorldMenu::tick()
UIScene::tick();
#ifdef _WINDOWS64
if (m_iDirectEditCooldown > 0)
m_iDirectEditCooldown--;
// Control caret visibility and position every tick — setLabel() and Flash
// focus changes reset both, so we must continuously enforce them.
if (g_KBMInput.IsKBMActive())
UIControl_TextInput::EDirectEditResult editResult = m_editWorldName.tickDirectEdit();
if (editResult == UIControl_TextInput::eDirectEdit_Confirmed || editResult == UIControl_TextInput::eDirectEdit_Cancelled)
{
m_editWorldName.setCaretVisible(m_bDirectEditing);
if (m_bDirectEditing)
m_editWorldName.setCaretIndex(m_iCursorPos);
}
if (m_bDirectEditing)
{
wchar_t ch;
bool changed = false;
while (g_KBMInput.ConsumeChar(ch))
{
if (ch == 0x08) // backspace
{
if (m_iCursorPos > 0)
{
m_worldName.erase(m_iCursorPos - 1, 1);
m_iCursorPos--;
changed = true;
}
}
else if (ch == 0x0D) // enter - confirm
{
m_bDirectEditing = false;
m_iDirectEditCooldown = 4; // absorb the matching ACTION_MENU_OK that follows
m_editWorldName.setLabel(m_worldName.c_str());
m_editWorldName.setCaretVisible(false);
break;
}
else if ((int)m_worldName.length() < 25)
{
m_worldName.insert(m_iCursorPos, 1, ch);
m_iCursorPos++;
changed = true;
}
}
// Arrow keys move the cursor within the text
if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0)
{
m_iCursorPos--;
m_editWorldName.setCaretIndex(m_iCursorPos);
}
if (g_KBMInput.IsKeyPressed(VK_RIGHT) && m_iCursorPos < (int)m_worldName.length())
{
m_iCursorPos++;
m_editWorldName.setCaretIndex(m_iCursorPos);
}
if (g_KBMInput.IsKeyPressed(VK_HOME))
{
m_iCursorPos = 0;
m_editWorldName.setCaretIndex(m_iCursorPos);
}
if (g_KBMInput.IsKeyPressed(VK_END))
{
m_iCursorPos = (int)m_worldName.length();
m_editWorldName.setCaretIndex(m_iCursorPos);
}
if (g_KBMInput.IsKeyPressed(VK_DELETE) && m_iCursorPos < (int)m_worldName.length())
{
m_worldName.erase(m_iCursorPos, 1);
changed = true;
}
// Escape cancels and restores the original name
if (m_bDirectEditing && g_KBMInput.IsKeyPressed(VK_ESCAPE))
{
m_worldName = m_worldNameBeforeEdit;
m_bDirectEditing = false;
m_iDirectEditCooldown = 4;
m_editWorldName.setLabel(m_worldName.c_str());
m_editWorldName.setCaretVisible(false);
m_buttonCreateWorld.setEnable(!m_worldName.empty());
}
else if (changed)
{
m_editWorldName.setLabel(m_worldName.c_str());
m_editWorldName.setCaretIndex(m_iCursorPos);
m_buttonCreateWorld.setEnable(!m_worldName.empty());
}
m_worldName = m_editWorldName.getEditBuffer();
m_buttonCreateWorld.setEnable(!m_worldName.empty());
}
#endif
@ -450,7 +364,7 @@ void UIScene_CreateWorldMenu::handleInput(int iPad, int key, bool repeat, bool p
{
if(m_bIgnoreInput) return;
#ifdef _WINDOWS64
if (m_bDirectEditing || m_iDirectEditCooldown > 0) { handled = true; return; }
if (m_editWorldName.isDirectEditing() || m_editWorldName.getDirectEditCooldown() > 0) { handled = true; return; }
#endif
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
@ -507,7 +421,7 @@ void UIScene_CreateWorldMenu::handlePress(F64 controlId, F64 childId)
{
if(m_bIgnoreInput) return;
#ifdef _WINDOWS64
if (m_bDirectEditing || m_iDirectEditCooldown > 0) return;
if (m_editWorldName.isDirectEditing() || m_editWorldName.getDirectEditCooldown() > 0) return;
#endif
//CD - Added for audio
@ -531,14 +445,8 @@ void UIScene_CreateWorldMenu::handlePress(F64 controlId, F64 childId)
}
else
{
// PC with KBM active: edit the name field directly in-place.
m_bIgnoreInput = false; // Don't block input - m_bDirectEditing is the guard
m_worldNameBeforeEdit = m_worldName;
m_bDirectEditing = true;
m_iCursorPos = (int)m_worldName.length();
g_KBMInput.ClearCharBuffer();
m_editWorldName.setCaretVisible(true);
m_editWorldName.setCaretIndex(m_iCursorPos);
m_bIgnoreInput = false;
m_editWorldName.beginDirectEdit(25);
}
#else
InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD),m_editWorldName.getLabel(),(DWORD)0,25,&UIScene_CreateWorldMenu::KeyboardCompleteWorldNameCallback,this,C_4JInput::EKeyboardMode_Default);

View file

@ -51,12 +51,6 @@ private:
DLCPack * m_pDLCPack;
bool m_bRebuildTouchBoxes;
#ifdef _WINDOWS64
bool m_bDirectEditing;
wstring m_worldNameBeforeEdit;
int m_iDirectEditCooldown;
int m_iCursorPos;
#endif
public:
UIScene_CreateWorldMenu(int iPad, void *initData, UILayer *parentLayer);

View file

@ -34,6 +34,10 @@ UIScene_DebugCreateSchematic::UIScene_DebugCreateSchematic(int iPad, void *initD
m_buttonCreate.init(L"Create",eControl_Create);
m_data = new ConsoleSchematicFile::XboxSchematicInitParam();
#ifdef _WINDOWS64
m_activeDirectEditControl = eControl_Create; // sentinel: no active edit
#endif
}
wstring UIScene_DebugCreateSchematic::getMoviePath()
@ -41,8 +45,76 @@ wstring UIScene_DebugCreateSchematic::getMoviePath()
return L"DebugCreateSchematic";
}
UIControl_TextInput* UIScene_DebugCreateSchematic::getTextInputForControl(eControls ctrl)
{
switch (ctrl)
{
case eControl_Name: return &m_textInputName;
case eControl_StartX: return &m_textInputStartX;
case eControl_StartY: return &m_textInputStartY;
case eControl_StartZ: return &m_textInputStartZ;
case eControl_EndX: return &m_textInputEndX;
case eControl_EndY: return &m_textInputEndY;
case eControl_EndZ: return &m_textInputEndZ;
default: return NULL;
}
}
#ifdef _WINDOWS64
bool UIScene_DebugCreateSchematic::handleMouseClick(F32 x, F32 y)
{
if (m_activeDirectEditControl != eControl_Create) return true;
UIScene::handleMouseClick(x, y);
return true; // always consume to prevent Iggy re-entry on empty space
}
#endif
void UIScene_DebugCreateSchematic::tick()
{
UIScene::tick();
#ifdef _WINDOWS64
UIControl_TextInput* allInputs[] = { &m_textInputName, &m_textInputStartX, &m_textInputStartY, &m_textInputStartZ, &m_textInputEndX, &m_textInputEndY, &m_textInputEndZ };
for (int i = 0; i < 7; i++)
allInputs[i]->tickDirectEdit();
if (m_activeDirectEditControl != eControl_Create)
{
UIControl_TextInput* active = getTextInputForControl(m_activeDirectEditControl);
if (active && !active->isDirectEditing())
{
// Edit finished — apply value
wstring value = active->getEditBuffer();
int iVal = 0;
if (!value.empty() && m_activeDirectEditControl != eControl_Name)
iVal = _fromString<int>(value);
switch (m_activeDirectEditControl)
{
case eControl_Name:
if (!value.empty())
swprintf(m_data->name, 64, L"%ls", value.c_str());
else
swprintf(m_data->name, 64, L"schematic");
break;
case eControl_StartX: m_data->startX = iVal; break;
case eControl_StartY: m_data->startY = iVal; break;
case eControl_StartZ: m_data->startZ = iVal; break;
case eControl_EndX: m_data->endX = iVal; break;
case eControl_EndY: m_data->endY = iVal; break;
case eControl_EndZ: m_data->endZ = iVal; break;
}
m_activeDirectEditControl = eControl_Create;
}
}
#endif
}
void UIScene_DebugCreateSchematic::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
#ifdef _WINDOWS64
if (m_activeDirectEditControl != eControl_Create) return;
#endif
ui.AnimateKeyPress(iPad, key, repeat, pressed, released);
switch(key)
@ -67,6 +139,9 @@ void UIScene_DebugCreateSchematic::handleInput(int iPad, int key, bool repeat, b
void UIScene_DebugCreateSchematic::handlePress(F64 controlId, F64 childId)
{
#ifdef _WINDOWS64
if (m_activeDirectEditControl != eControl_Create) return;
#endif
switch((int)controlId)
{
case eControl_Create:
@ -112,8 +187,29 @@ void UIScene_DebugCreateSchematic::handlePress(F64 controlId, F64 childId)
case eControl_EndX:
case eControl_EndY:
case eControl_EndZ:
m_keyboardCallbackControl = (eControls)((int)controlId);
InputManager.RequestKeyboard(L"Enter something",L"",(DWORD)0,25,&UIScene_DebugCreateSchematic::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default);
{
m_keyboardCallbackControl = (eControls)((int)controlId);
#ifdef _WINDOWS64
if (g_KBMInput.IsKBMActive())
{
m_activeDirectEditControl = m_keyboardCallbackControl;
UIControl_TextInput* input = getTextInputForControl(m_activeDirectEditControl);
if (input) input->beginDirectEdit(25);
}
else
{
UIKeyboardInitData kbData;
kbData.title = L"Enter something";
kbData.defaultText = L"";
kbData.maxChars = 25;
kbData.callback = &UIScene_DebugCreateSchematic::KeyboardCompleteCallback;
kbData.lpParam = this;
ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData, eUILayer_Fullscreen, eUIGroup_Fullscreen);
}
#else
InputManager.RequestKeyboard(L"Enter something",L"",(DWORD)0,25,&UIScene_DebugCreateSchematic::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default);
#endif
}
break;
};
}
@ -138,9 +234,15 @@ int UIScene_DebugCreateSchematic::KeyboardCompleteCallback(LPVOID lpParam,bool b
{
UIScene_DebugCreateSchematic *pClass=(UIScene_DebugCreateSchematic *)lpParam;
#ifdef _WINDOWS64
uint16_t pchText[128];
ZeroMemory(pchText, 128 * sizeof(uint16_t));
Win64_GetKeyboardText(pchText, 128);
#else
uint16_t pchText[128];
ZeroMemory(pchText, 128 * sizeof(uint16_t) );
InputManager.GetText(pchText);
#endif
if(pchText[0]!=0)
{

View file

@ -24,6 +24,10 @@ private:
ConsoleSchematicFile::XboxSchematicInitParam *m_data;
#ifdef _WINDOWS64
eControls m_activeDirectEditControl;
#endif
public:
UIScene_DebugCreateSchematic(int iPad, void *initData, UILayer *parentLayer);
@ -58,8 +62,12 @@ protected:
UI_END_MAP_ELEMENTS_AND_NAMES()
virtual wstring getMoviePath();
#ifdef _WINDOWS64
virtual bool handleMouseClick(F32 x, F32 y);
#endif
public:
virtual void tick();
// INPUT
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
@ -68,6 +76,7 @@ protected:
virtual void handleCheckboxToggled(F64 controlId, bool selected);
private:
UIControl_TextInput* getTextInputForControl(eControls ctrl);
static int KeyboardCompleteCallback(LPVOID lpParam,const bool bRes);
};
#endif

View file

@ -31,19 +31,19 @@ UIScene_DebugSetCamera::UIScene_DebugSetCamera(int iPad, void *initData, UILayer
WCHAR TempString[256];
swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_camX);
swprintf( (WCHAR *)TempString, 256, L"%.2f", currentPosition->m_camX);
m_textInputX.init(TempString, eControl_CamX);
swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_camY);
swprintf( (WCHAR *)TempString, 256, L"%.2f", currentPosition->m_camY);
m_textInputY.init(TempString, eControl_CamY);
swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_camZ);
swprintf( (WCHAR *)TempString, 256, L"%.2f", currentPosition->m_camZ);
m_textInputZ.init(TempString, eControl_CamZ);
swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_yRot);
swprintf( (WCHAR *)TempString, 256, L"%.2f", currentPosition->m_yRot);
m_textInputYRot.init(TempString, eControl_YRot);
swprintf( (WCHAR *)TempString, 256, L"%f", currentPosition->m_elev);
swprintf( (WCHAR *)TempString, 256, L"%.2f", currentPosition->m_elev);
m_textInputElevation.init(TempString, eControl_Elevation);
m_checkboxLockPlayer.init(L"Lock Player", eControl_LockPlayer, app.GetFreezePlayers());
@ -55,6 +55,10 @@ UIScene_DebugSetCamera::UIScene_DebugSetCamera(int iPad, void *initData, UILayer
m_labelCamY.init(L"CamY");
m_labelCamZ.init(L"CamZ");
m_labelYRotElev.init(L"Y-Rot & Elevation (Degs)");
#ifdef _WINDOWS64
m_activeDirectEditControl = eControl_Teleport; // sentinel — no active edit
#endif
}
wstring UIScene_DebugSetCamera::getMoviePath()
@ -62,8 +66,87 @@ wstring UIScene_DebugSetCamera::getMoviePath()
return L"DebugSetCamera";
}
#ifdef _WINDOWS64
UIControl_TextInput* UIScene_DebugSetCamera::getTextInputForControl(eControls ctrl)
{
switch (ctrl)
{
case eControl_CamX: return &m_textInputX;
case eControl_CamY: return &m_textInputY;
case eControl_CamZ: return &m_textInputZ;
case eControl_YRot: return &m_textInputYRot;
case eControl_Elevation: return &m_textInputElevation;
default: return NULL;
}
}
bool UIScene_DebugSetCamera::handleMouseClick(F32 x, F32 y)
{
// If currently editing, confirm the current edit before processing the click
if (m_activeDirectEditControl != eControl_Teleport)
{
UIControl_TextInput* active = getTextInputForControl(m_activeDirectEditControl);
if (active && active->isDirectEditing())
{
wstring value = active->getEditBuffer();
double val = 0;
if (!value.empty()) val = _fromString<double>(value);
switch (m_activeDirectEditControl)
{
case eControl_CamX: currentPosition->m_camX = val; break;
case eControl_CamY: currentPosition->m_camY = val; break;
case eControl_CamZ: currentPosition->m_camZ = val; break;
case eControl_YRot: currentPosition->m_yRot = val; break;
case eControl_Elevation: currentPosition->m_elev = val; break;
}
active->confirmDirectEdit();
}
m_activeDirectEditControl = eControl_Teleport;
}
UIScene::handleMouseClick(x, y);
return true; // always consume to prevent Iggy re-entry on empty space
}
#endif
void UIScene_DebugSetCamera::tick()
{
UIScene::tick();
#ifdef _WINDOWS64
UIControl_TextInput* inputs[] = { &m_textInputX, &m_textInputY, &m_textInputZ, &m_textInputYRot, &m_textInputElevation };
for (int i = 0; i < 5; i++)
{
UIControl_TextInput::EDirectEditResult result = inputs[i]->tickDirectEdit();
if (result == UIControl_TextInput::eDirectEdit_Confirmed)
{
wstring value = inputs[i]->getEditBuffer();
double val = 0;
if (!value.empty()) val = _fromString<double>(value);
eControls ctrl = (eControls)i; // eControl_CamX=0, CamY=1, CamZ=2, YRot=3, Elevation=4
switch (ctrl)
{
case eControl_CamX: currentPosition->m_camX = val; break;
case eControl_CamY: currentPosition->m_camY = val; break;
case eControl_CamZ: currentPosition->m_camZ = val; break;
case eControl_YRot: currentPosition->m_yRot = val; break;
case eControl_Elevation: currentPosition->m_elev = val; break;
}
m_activeDirectEditControl = eControl_Teleport;
}
else if (result == UIControl_TextInput::eDirectEdit_Cancelled)
{
m_activeDirectEditControl = eControl_Teleport;
}
}
#endif
}
void UIScene_DebugSetCamera::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
#ifdef _WINDOWS64
if (m_activeDirectEditControl != eControl_Teleport) { handled = true; return; }
#endif
ui.AnimateKeyPress(iPad, key, repeat, pressed, released);
switch(key)
@ -88,11 +171,14 @@ void UIScene_DebugSetCamera::handleInput(int iPad, int key, bool repeat, bool pr
void UIScene_DebugSetCamera::handlePress(F64 controlId, F64 childId)
{
#ifdef _WINDOWS64
if (m_activeDirectEditControl != eControl_Teleport) return;
#endif
switch((int)controlId)
{
case eControl_Teleport:
app.SetXuiServerAction( ProfileManager.GetPrimaryPad(),
eXuiServerAction_SetCameraLocation,
eXuiServerAction_SetCameraLocation,
(void *)currentPosition);
break;
case eControl_CamX:
@ -100,8 +186,27 @@ void UIScene_DebugSetCamera::handlePress(F64 controlId, F64 childId)
case eControl_CamZ:
case eControl_YRot:
case eControl_Elevation:
m_keyboardCallbackControl = (eControls)((int)controlId);
m_keyboardCallbackControl = (eControls)((int)controlId);
#ifdef _WINDOWS64
if (g_KBMInput.IsKBMActive())
{
m_activeDirectEditControl = m_keyboardCallbackControl;
UIControl_TextInput* input = getTextInputForControl(m_activeDirectEditControl);
if (input) input->beginDirectEdit(25);
}
else
{
UIKeyboardInitData kbData;
kbData.title = L"Enter value";
kbData.defaultText = L"";
kbData.maxChars = 25;
kbData.callback = &UIScene_DebugSetCamera::KeyboardCompleteCallback;
kbData.lpParam = this;
ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData, eUILayer_Fullscreen, eUIGroup_Fullscreen);
}
#else
InputManager.RequestKeyboard(L"Enter something",L"",(DWORD)0,25,&UIScene_DebugSetCamera::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Default);
#endif
break;
};
}
@ -119,9 +224,13 @@ void UIScene_DebugSetCamera::handleCheckboxToggled(F64 controlId, bool selected)
int UIScene_DebugSetCamera::KeyboardCompleteCallback(LPVOID lpParam,bool bRes)
{
UIScene_DebugSetCamera *pClass=(UIScene_DebugSetCamera *)lpParam;
uint16_t pchText[2048];//[128];
ZeroMemory(pchText, 2048/*128*/ * sizeof(uint16_t) );
uint16_t pchText[2048];
ZeroMemory(pchText, 2048 * sizeof(uint16_t));
#ifdef _WINDOWS64
Win64_GetKeyboardText(pchText, 2048);
#else
InputManager.GetText(pchText);
#endif
if(pchText[0]!=0)
{

View file

@ -26,6 +26,10 @@ private:
FreezePlayerParam *fpp;
eControls m_keyboardCallbackControl;
#ifdef _WINDOWS64
eControls m_activeDirectEditControl;
UIControl_TextInput* getTextInputForControl(eControls ctrl);
#endif
public:
UIScene_DebugSetCamera(int iPad, void *initData, UILayer *parentLayer);
@ -54,6 +58,10 @@ protected:
UI_END_MAP_ELEMENTS_AND_NAMES()
virtual wstring getMoviePath();
virtual void tick();
#ifdef _WINDOWS64
virtual bool handleMouseClick(F32 x, F32 y);
#endif
public:
// INPUT

View file

@ -211,6 +211,12 @@ void UIScene_LaunchMoreOptionsMenu::tick()
{
UIScene::tick();
#ifdef _WINDOWS64
UIControl_TextInput::EDirectEditResult editResult = m_editSeed.tickDirectEdit();
if (editResult == UIControl_TextInput::eDirectEdit_Confirmed)
m_params->seed = m_editSeed.getEditBuffer();
#endif
bool bMultiplayerAllowed = ProfileManager.IsSignedInLive(m_params->iPad) && ProfileManager.AllowedToPlayMultiplayer(m_params->iPad);
if (bMultiplayerAllowed != m_bMultiplayerAllowed)
@ -257,6 +263,9 @@ void UIScene_LaunchMoreOptionsMenu::handleDestroy()
void UIScene_LaunchMoreOptionsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
if(m_bIgnoreInput) return;
#ifdef _WINDOWS64
if (m_editSeed.isDirectEditing() || m_editSeed.getDirectEditCooldown() > 0) return;
#endif
//app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE");
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
@ -334,7 +343,9 @@ void UIScene_LaunchMoreOptionsMenu::handleTouchInput(unsigned int iPad, S32 x, S
}
}
}
#endif
#if defined(__PSVITA__) || defined(_WINDOWS64)
UIControl* UIScene_LaunchMoreOptionsMenu::GetMainPanel()
{
if(m_tabIndex == 0)
@ -546,11 +557,16 @@ int UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback(LPVOID lpParam,b
{
UIScene_LaunchMoreOptionsMenu *pClass=(UIScene_LaunchMoreOptionsMenu *)lpParam;
pClass->m_bIgnoreInput=false;
// 4J HEG - No reason to set value if keyboard was cancelled
if (bRes)
{
#ifdef _WINDOWS64
uint16_t pchText[128];
ZeroMemory(pchText, 128 * sizeof(uint16_t));
Win64_GetKeyboardText(pchText, 128);
pClass->m_editSeed.setLabel((wchar_t *)pchText);
pClass->m_params->seed = (wchar_t *)pchText;
#else
#ifdef __PSVITA__
//CD - Changed to 2048 [SCE_IME_MAX_TEXT_LENGTH]
uint16_t pchText[2048];
ZeroMemory(pchText, 2048 * sizeof(uint16_t) );
#else
@ -560,6 +576,7 @@ int UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback(LPVOID lpParam,b
InputManager.GetText(pchText);
pClass->m_editSeed.setLabel((wchar_t *)pchText);
pClass->m_params->seed = (wchar_t *)pchText;
#endif
}
return 0;
}
@ -567,11 +584,31 @@ int UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback(LPVOID lpParam,b
void UIScene_LaunchMoreOptionsMenu::handlePress(F64 controlId, F64 childId)
{
if(m_bIgnoreInput) return;
#ifdef _WINDOWS64
if (m_editSeed.isDirectEditing() || m_editSeed.getDirectEditCooldown() > 0) return;
#endif
switch((int)controlId)
{
case eControl_EditSeed:
{
#ifdef _WINDOWS64
if (g_KBMInput.IsKBMActive())
{
m_editSeed.beginDirectEdit(60);
}
else
{
m_bIgnoreInput = true;
UIKeyboardInitData kbData;
kbData.title = app.GetString(IDS_CREATE_NEW_WORLD_SEED);
kbData.defaultText = m_editSeed.getLabel();
kbData.maxChars = 60;
kbData.callback = &UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback;
kbData.lpParam = this;
ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData);
}
#else
m_bIgnoreInput=true;
#ifdef __PS3__
int language = XGetLanguage();
@ -583,12 +620,12 @@ void UIScene_LaunchMoreOptionsMenu::handlePress(F64 controlId, F64 childId)
InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Default);
break;
default:
// 4J Stu - Use a different keyboard for non-asian languages so we don't have prediction on
InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Alphabet_Extended);
break;
}
#else
InputManager.RequestKeyboard(app.GetString(IDS_CREATE_NEW_WORLD_SEED),m_editSeed.getLabel(),(DWORD)0,60,&UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback,this,C_4JInput::EKeyboardMode_Default);
#endif
#endif
}
break;

View file

@ -160,6 +160,8 @@ private:
#ifdef __PSVITA__
virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased);
virtual UIControl* GetMainPanel();
#endif //__PSVITA__
#if defined(__PSVITA__) || defined(_WINDOWS64)
virtual UIControl* GetMainPanel();
#endif
};

View file

@ -18,6 +18,9 @@ UIScene_SignEntryMenu::UIScene_SignEntryMenu(int iPad, void *_initData, UILayer
m_bConfirmed = false;
m_bIgnoreInput = false;
#ifdef _WINDOWS64
m_iActiveDirectEditLine = -1;
#endif
m_buttonConfirm.init(app.GetString(IDS_DONE), eControl_Confirm);
m_labelMessage.init(app.GetString(IDS_EDIT_SIGN_MESSAGE));
@ -77,6 +80,18 @@ void UIScene_SignEntryMenu::tick()
{
UIScene::tick();
#ifdef _WINDOWS64
for (int i = 0; i < 4; i++)
m_textInputLines[i].tickDirectEdit();
if (m_iActiveDirectEditLine >= 0)
{
UIControl_TextInput& line = m_textInputLines[m_iActiveDirectEditLine];
if (!line.isDirectEditing())
m_iActiveDirectEditLine = -1;
}
#endif
if(m_bConfirmed)
{
m_bConfirmed = false;
@ -107,6 +122,30 @@ void UIScene_SignEntryMenu::tick()
void UIScene_SignEntryMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
if(m_bConfirmed || m_bIgnoreInput) return;
#ifdef _WINDOWS64
if (m_iActiveDirectEditLine >= 0)
{
// Mouse click while editing — confirm current line and let click through
if (key == ACTION_MENU_OK && pressed && g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
{
m_textInputLines[m_iActiveDirectEditLine].confirmDirectEdit();
m_iActiveDirectEditLine = -1;
}
else
{
handled = true;
return;
}
}
for (int i = 0; i < 4; i++)
{
if (m_textInputLines[i].getDirectEditCooldown() > 0)
{
handled = true;
return;
}
}
#endif
ui.AnimateKeyPress(iPad, key, repeat, pressed, released);
@ -142,21 +181,36 @@ void UIScene_SignEntryMenu::handleInput(int iPad, int key, bool repeat, bool pre
int UIScene_SignEntryMenu::KeyboardCompleteCallback(LPVOID lpParam,bool bRes)
{
// 4J HEG - No reason to set value if keyboard was cancelled
UIScene_SignEntryMenu *pClass=(UIScene_SignEntryMenu *)lpParam;
pClass->m_bIgnoreInput = false;
if (bRes)
{
#ifdef _WINDOWS64
uint16_t pchText[128];
ZeroMemory(pchText, 128 * sizeof(uint16_t));
Win64_GetKeyboardText(pchText, 128);
pClass->m_textInputLines[pClass->m_iEditingLine].setLabel((wchar_t *)pchText);
#else
uint16_t pchText[128];
ZeroMemory(pchText, 128 * sizeof(uint16_t) );
InputManager.GetText(pchText);
pClass->m_textInputLines[pClass->m_iEditingLine].setLabel((wchar_t *)pchText);
#endif
}
return 0;
}
void UIScene_SignEntryMenu::handlePress(F64 controlId, F64 childId)
{
#ifdef _WINDOWS64
// After direct edit ends (Enter/Escape), skip input for a few frames
// to absorb the matching ACTION_MENU_OK that would re-open the edit.
for (int i = 0; i < 4; i++)
{
if (m_textInputLines[i].isDirectEditing() || m_textInputLines[i].getDirectEditCooldown() > 0)
return;
}
#endif
switch((int)controlId)
{
case eControl_Confirm:
@ -170,6 +224,24 @@ void UIScene_SignEntryMenu::handlePress(F64 controlId, F64 childId)
case eControl_Line4:
{
m_iEditingLine = (int)controlId;
#ifdef _WINDOWS64
if (g_KBMInput.IsKBMActive())
{
m_iActiveDirectEditLine = m_iEditingLine;
m_textInputLines[m_iEditingLine].beginDirectEdit(15);
}
else
{
m_bIgnoreInput = true;
UIKeyboardInitData kbData;
kbData.title = app.GetString(IDS_SIGN_TITLE);
kbData.defaultText = m_textInputLines[m_iEditingLine].getLabel();
kbData.maxChars = 15;
kbData.callback = &UIScene_SignEntryMenu::KeyboardCompleteCallback;
kbData.lpParam = this;
ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData, eUILayer_Fullscreen, eUIGroup_Fullscreen);
}
#else
m_bIgnoreInput = true;
#ifdef _XBOX_ONE
// 4J-PB - Xbox One uses the Windows virtual keyboard, and doesn't have the Xbox 360 Latin keyboard type, so we can't restrict the input set to alphanumeric. The closest we get is the emailSmtpAddress type.
@ -187,6 +259,7 @@ void UIScene_SignEntryMenu::handlePress(F64 controlId, F64 childId)
}
#else
InputManager.RequestKeyboard(app.GetString(IDS_SIGN_TITLE),m_textInputLines[m_iEditingLine].getLabel(),(DWORD)m_iPad,15,&UIScene_SignEntryMenu::KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Alphabet);
#endif
#endif
}
break;

View file

@ -21,6 +21,9 @@ private:
int m_iEditingLine;
bool m_bConfirmed;
bool m_bIgnoreInput;
#ifdef _WINDOWS64
int m_iActiveDirectEditLine;
#endif
UIControl_Button m_buttonConfirm;
UIControl_Label m_labelMessage;