aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp
diff options
context:
space:
mode:
authordtentiion <dtentiongit@gmail.com>2026-03-05 20:57:37 +0000
committerGitHub <noreply@github.com>2026-03-05 14:57:37 -0600
commitaadb5115040cfe0199e79a3e32dada6aa4b99fda (patch)
tree7aba2ccfc2d3361272ad0380ec69c98a4f6c3efe /Minecraft.Client/Common/UI/UIScene_Keyboard.cpp
parentf48a39ae3d72fc47ed3a050f6419716dc398d8f5 (diff)
Fix save list, delete save, exit without saving, and blank username on Windows64 (#539)
* Fix world save rename not applying new name KeyboardCompleteWorldNameCallback had no _WINDOWS64 branch, so the typed name was validated then silently discarded on every rename attempt. Write the new name to a worldname.txt sidecar file next to the save (Windows64\GameHDD\{folder}\worldname.txt) and update the in-memory display name immediately. ReadLevelNameFromSaveFile now checks for this sidecar first so renamed saves persist correctly across restarts. * Fixed gamertag being blank upon renaming and re-joining a save * Save deletion fix, exiting without saving fix * Add native in-game keyboard UI for world naming and renaming
Diffstat (limited to 'Minecraft.Client/Common/UI/UIScene_Keyboard.cpp')
-rw-r--r--Minecraft.Client/Common/UI/UIScene_Keyboard.cpp178
1 files changed, 163 insertions, 15 deletions
diff --git a/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp b/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp
index fb1cc301..9e46a42e 100644
--- a/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp
@@ -2,6 +2,12 @@
#include "UI.h"
#include "UIScene_Keyboard.h"
+#ifdef _WINDOWS64
+// Global buffer that stores the text entered in the native keyboard scene.
+// Callbacks retrieve it via Win64_GetKeyboardText() declared in UIStructs.h.
+wchar_t g_Win64KeyboardResult[256] = {};
+#endif
+
#define KEYBOARD_DONE_TIMER_ID 0
#define KEYBOARD_DONE_TIMER_TIME 100
@@ -10,31 +16,103 @@ UIScene_Keyboard::UIScene_Keyboard(int iPad, void *initData, UILayer *parentLaye
// Setup all the Iggy references we need for this scene
initialiseMovie();
+#ifdef _WINDOWS64
+ m_win64Callback = NULL;
+ m_win64CallbackParam = NULL;
+ m_win64TextBuffer = L"";
+ m_win64MaxChars = 25;
+
+ const wchar_t* titleText = L"Enter text";
+ const wchar_t* defaultText = L"";
+
+ m_bPCMode = false;
+ if (initData)
+ {
+ UIKeyboardInitData* kbData = (UIKeyboardInitData*)initData;
+ m_win64Callback = kbData->callback;
+ m_win64CallbackParam = kbData->lpParam;
+ if (kbData->title) titleText = kbData->title;
+ if (kbData->defaultText) defaultText = kbData->defaultText;
+ m_win64MaxChars = kbData->maxChars;
+ m_bPCMode = kbData->pcMode;
+ }
+
+ m_win64TextBuffer = defaultText;
+
+ m_EnterTextLabel.init(titleText);
+ m_KeyboardTextInput.init(defaultText, -1);
+ m_KeyboardTextInput.SetCharLimit(m_win64MaxChars);
+
+ // Clear any leftover typed characters from a previous keyboard session
+ g_KBMInput.ClearCharBuffer();
+ g_Win64KeyboardResult[0] = L'\0';
+#else
m_EnterTextLabel.init(L"Enter Sign Text");
m_KeyboardTextInput.init(L"", -1);
m_KeyboardTextInput.SetCharLimit(15);
+#endif
m_ButtonSpace.init(L"Space", -1);
- m_ButtonCursorLeft.init(L"Cursor Left", -1);
- m_ButtonCursorRight.init(L"Cursor Right", -1);
+ m_ButtonCursorLeft.init(L"Cur L", -1);
+ m_ButtonCursorRight.init(L"Cur R", -1);
m_ButtonCaps.init(L"Caps", -1);
m_ButtonDone.init(L"Done", 0); // only the done button needs an id, the others will never call back!
m_ButtonSymbols.init(L"Symbols", -1);
m_ButtonBackspace.init(L"Backspace", -1);
// Initialise function keyboard Buttons and set alternative symbol button string
- wstring label = L"Abc";
- IggyStringUTF16 stringVal;
- stringVal.string = (IggyUTF16*)label.c_str();
- stringVal.length = label.length();
-
- IggyDataValue result;
- IggyDataValue value[1];
- value[0].type = IGGY_DATATYPE_string_UTF16;
- value[0].string16 = stringVal;
+#ifdef _WINDOWS64
+ if (!m_bPCMode)
+#endif
+ {
+ wstring label = L"Abc";
+ IggyStringUTF16 stringVal;
+ stringVal.string = (IggyUTF16*)label.c_str();
+ stringVal.length = label.length();
- IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcInitFunctionButtons , 1 , value );
+ IggyDataValue result;
+ IggyDataValue value[1];
+ value[0].type = IGGY_DATATYPE_string_UTF16;
+ value[0].string16 = stringVal;
+
+ IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcInitFunctionButtons , 1 , value );
+ }
+
+#ifdef _WINDOWS64
+ if (m_bPCMode)
+ {
+ // PC text-input mode: hide all on-screen buttons, user types with physical keyboard
+
+ // Hide the mapped function-row buttons
+ m_ButtonSpace.setVisible(false);
+ m_ButtonCursorLeft.setVisible(false);
+ m_ButtonCursorRight.setVisible(false);
+ m_ButtonCaps.setVisible(false);
+ m_ButtonSymbols.setVisible(false);
+ m_ButtonBackspace.setVisible(false);
+
+ // Hide the letter/number key grid (Flash-baked, not mapped as UIControls)
+ static const char* s_keyNames[] = {
+ "Button_q", "Button_w", "Button_e", "Button_r", "Button_t",
+ "Button_y", "Button_u", "Button_i", "Button_o", "Button_p",
+ "Button_a", "Button_s", "Button_d", "Button_f", "Button_g",
+ "Button_h", "Button_j", "Button_k", "Button_l", "Button_apostraphy",
+ "Button_z", "Button_x", "Button_c", "Button_v", "Button_b",
+ "Button_n", "Button_m", "Button_comma", "Button_stop", "Button_qmark",
+ "Button_0", "Button_1", "Button_2", "Button_3", "Button_4",
+ "Button_5", "Button_6", "Button_7", "Button_8", "Button_9"
+ };
+ IggyName nameVisible = registerFastName(L"visible");
+ IggyValuePath* root = IggyPlayerRootPath(getMovie());
+ for (int i = 0; i < (int)(sizeof(s_keyNames) / sizeof(s_keyNames[0])); ++i)
+ {
+ IggyValuePath keyPath;
+ if (IggyValuePathMakeNameRef(&keyPath, root, s_keyNames[i]))
+ IggyValueSetBooleanRS(&keyPath, nameVisible, NULL, false);
+ }
+ }
+#endif
m_bKeyboardDonePressed = false;
@@ -80,6 +158,46 @@ bool UIScene_Keyboard::allowRepeat(int key)
return true;
}
+#ifdef _WINDOWS64
+void UIScene_Keyboard::tick()
+{
+ UIScene::tick();
+
+ // Accumulate physical keyboard chars into our own buffer, then push to Flash via setLabel.
+ // This bypasses Iggy's focus system (char events only route to the focused element).
+ // The char buffer is cleared on open so Enter/clicks from the triggering action don't leak in.
+ wchar_t ch;
+ bool changed = false;
+ while (g_KBMInput.ConsumeChar(ch))
+ {
+ if (ch == 0x08) // backspace
+ {
+ if (!m_win64TextBuffer.empty())
+ {
+ m_win64TextBuffer.pop_back();
+ changed = true;
+ }
+ }
+ else if (ch == 0x0D) // enter - confirm
+ {
+ if (!m_bKeyboardDonePressed)
+ {
+ addTimer(KEYBOARD_DONE_TIMER_ID, KEYBOARD_DONE_TIMER_TIME);
+ m_bKeyboardDonePressed = true;
+ }
+ }
+ else if ((int)m_win64TextBuffer.length() < m_win64MaxChars)
+ {
+ m_win64TextBuffer += ch;
+ changed = true;
+ }
+ }
+
+ if (changed)
+ m_KeyboardTextInput.setLabel(m_win64TextBuffer.c_str(), true /*instant*/);
+}
+#endif
+
void UIScene_Keyboard::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
IggyDataValue result;
@@ -90,7 +208,18 @@ void UIScene_Keyboard::handleInput(int iPad, int key, bool repeat, bool pressed,
switch(key)
{
case ACTION_MENU_CANCEL:
+#ifdef _WINDOWS64
+ {
+ // Cache before navigateBack() destroys this scene
+ int(*cb)(LPVOID, const bool) = m_win64Callback;
+ LPVOID cbParam = m_win64CallbackParam;
+ navigateBack();
+ if (cb)
+ cb(cbParam, false);
+ }
+#else
navigateBack();
+#endif
handled = true;
break;
case ACTION_MENU_X: // X
@@ -173,9 +302,28 @@ void UIScene_Keyboard::handleTimerComplete(int id)
void UIScene_Keyboard::KeyboardDonePressed()
{
- // Debug
- app.DebugPrintf("UI Keyboard - DONE - [%ls]\n", m_KeyboardTextInput.getLabel());
+#ifdef _WINDOWS64
+ // Use getLabel() here — this is a timer callback (not an Iggy callback) so it's safe.
+ // getLabel() reflects both physical keyboard input (pushed via setLabel) and
+ // on-screen button input (set directly by Flash ActionScript).
+ const wchar_t* finalText = m_KeyboardTextInput.getLabel();
+ app.DebugPrintf("UI Keyboard - DONE - [%ls]\n", finalText);
- // ToDo: Keyboard can now pass on its final string value and close itself down
+ // Store the typed text so callbacks can retrieve it via Win64_GetKeyboardText()
+ wcsncpy_s(g_Win64KeyboardResult, 256, finalText, _TRUNCATE);
+
+ // Cache callback and param before navigateBack() which destroys this scene
+ int(*cb)(LPVOID, const bool) = m_win64Callback;
+ LPVOID cbParam = m_win64CallbackParam;
+
+ // Navigate back so the scene stack is restored before the callback runs
+ navigateBack();
+
+ // Fire callback: bRes=true means confirmed
+ if (cb)
+ cb(cbParam, true);
+#else
+ app.DebugPrintf("UI Keyboard - DONE - [%ls]\n", m_KeyboardTextInput.getLabel());
navigateBack();
+#endif
} \ No newline at end of file