mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
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:
parent
cb46908268
commit
3c5613b8aa
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
@ -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, ¤tFocus, 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, ¤tFocus, 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, ¤tFocus, 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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue