mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Merge branch 'main' into fix-controller-usage
This commit is contained in:
commit
aebb6afeaa
|
|
@ -1,14 +1,27 @@
|
|||
#include "stdafx.h"
|
||||
#include "ChatScreen.h"
|
||||
#include "ClientConnection.h"
|
||||
#include "Font.h"
|
||||
#include "MultiplayerLocalPlayer.h"
|
||||
#include "..\Minecraft.World\SharedConstants.h"
|
||||
#include "..\Minecraft.World\StringHelpers.h"
|
||||
#include "..\Minecraft.World\ChatPacket.h"
|
||||
|
||||
const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters;
|
||||
vector<wstring> ChatScreen::s_chatHistory;
|
||||
int ChatScreen::s_historyIndex = -1;
|
||||
wstring ChatScreen::s_historyDraft;
|
||||
|
||||
bool ChatScreen::isAllowedChatChar(wchar_t c)
|
||||
{
|
||||
return c >= 0x20 && (c == L'\u00A7' || allowedChars.empty() || allowedChars.find(c) != wstring::npos);
|
||||
}
|
||||
|
||||
ChatScreen::ChatScreen()
|
||||
{
|
||||
frame = 0;
|
||||
cursorIndex = 0;
|
||||
s_historyIndex = -1;
|
||||
}
|
||||
|
||||
void ChatScreen::init()
|
||||
|
|
@ -24,6 +37,50 @@ void ChatScreen::removed()
|
|||
void ChatScreen::tick()
|
||||
{
|
||||
frame++;
|
||||
if (cursorIndex > static_cast<int>(message.length()))
|
||||
cursorIndex = static_cast<int>(message.length());
|
||||
}
|
||||
|
||||
void ChatScreen::handlePasteRequest()
|
||||
{
|
||||
wstring pasted = Screen::getClipboard();
|
||||
for (size_t i = 0; i < pasted.length() && static_cast<int>(message.length()) < SharedConstants::maxChatLength; i++)
|
||||
{
|
||||
if (isAllowedChatChar(pasted[i]))
|
||||
{
|
||||
message.insert(cursorIndex, 1, pasted[i]);
|
||||
cursorIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatScreen::applyHistoryMessage()
|
||||
{
|
||||
message = s_historyIndex >= 0 ? s_chatHistory[s_historyIndex] : s_historyDraft;
|
||||
cursorIndex = static_cast<int>(message.length());
|
||||
}
|
||||
|
||||
void ChatScreen::handleHistoryUp()
|
||||
{
|
||||
if (s_chatHistory.empty()) return;
|
||||
if (s_historyIndex == -1)
|
||||
{
|
||||
s_historyDraft = message;
|
||||
s_historyIndex = static_cast<int>(s_chatHistory.size()) - 1;
|
||||
}
|
||||
else if (s_historyIndex > 0)
|
||||
s_historyIndex--;
|
||||
applyHistoryMessage();
|
||||
}
|
||||
|
||||
void ChatScreen::handleHistoryDown()
|
||||
{
|
||||
if (s_chatHistory.empty()) return;
|
||||
if (s_historyIndex < static_cast<int>(s_chatHistory.size()) - 1)
|
||||
s_historyIndex++;
|
||||
else
|
||||
s_historyIndex = -1;
|
||||
applyHistoryMessage();
|
||||
}
|
||||
|
||||
void ChatScreen::keyPressed(wchar_t ch, int eventKey)
|
||||
|
|
@ -35,31 +92,67 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
|
|||
}
|
||||
if (eventKey == Keyboard::KEY_RETURN)
|
||||
{
|
||||
wstring msg = trimString(message);
|
||||
if (msg.length() > 0)
|
||||
wstring trim = trimString(message);
|
||||
if (trim.length() > 0)
|
||||
{
|
||||
wstring trim = trimString(message);
|
||||
if (!minecraft->handleClientSideCommand(trim))
|
||||
{
|
||||
minecraft->player->chat(trim);
|
||||
MultiplayerLocalPlayer* mplp = dynamic_cast<MultiplayerLocalPlayer*>(minecraft->player.get());
|
||||
if (mplp && mplp->connection)
|
||||
mplp->connection->send(shared_ptr<ChatPacket>(new ChatPacket(trim)));
|
||||
}
|
||||
if (s_chatHistory.empty() || s_chatHistory.back() != trim)
|
||||
{
|
||||
s_chatHistory.push_back(trim);
|
||||
if (s_chatHistory.size() > CHAT_HISTORY_MAX)
|
||||
s_chatHistory.erase(s_chatHistory.begin());
|
||||
}
|
||||
}
|
||||
minecraft->setScreen(NULL);
|
||||
return;
|
||||
}
|
||||
if (eventKey == Keyboard::KEY_BACK && message.length() > 0) message = message.substr(0, message.length() - 1);
|
||||
if (allowedChars.find(ch) >= 0 && message.length() < SharedConstants::maxChatLength)
|
||||
if (eventKey == Keyboard::KEY_UP) { handleHistoryUp(); return; }
|
||||
if (eventKey == Keyboard::KEY_DOWN) { handleHistoryDown(); return; }
|
||||
if (eventKey == Keyboard::KEY_LEFT)
|
||||
{
|
||||
message += ch;
|
||||
if (cursorIndex > 0)
|
||||
cursorIndex--;
|
||||
return;
|
||||
}
|
||||
if (eventKey == Keyboard::KEY_RIGHT)
|
||||
{
|
||||
if (cursorIndex < static_cast<int>(message.length()))
|
||||
cursorIndex++;
|
||||
return;
|
||||
}
|
||||
if (eventKey == Keyboard::KEY_BACK && cursorIndex > 0)
|
||||
{
|
||||
message.erase(cursorIndex - 1, 1);
|
||||
cursorIndex--;
|
||||
return;
|
||||
}
|
||||
if (isAllowedChatChar(ch) && static_cast<int>(message.length()) < SharedConstants::maxChatLength)
|
||||
{
|
||||
message.insert(cursorIndex, 1, ch);
|
||||
cursorIndex++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ChatScreen::render(int xm, int ym, float a)
|
||||
{
|
||||
fill(2, height - 14, width - 2, height - 2, 0x80000000);
|
||||
drawString(font, L"> " + message + (frame / 6 % 2 == 0 ? L"_" : L""), 4, height - 12, 0xe0e0e0);
|
||||
|
||||
const wstring prefix = L"> ";
|
||||
int x = 4;
|
||||
drawString(font, prefix, x, height - 12, 0xe0e0e0);
|
||||
x += font->width(prefix);
|
||||
wstring beforeCursor = message.substr(0, cursorIndex);
|
||||
wstring afterCursor = message.substr(cursorIndex);
|
||||
drawStringLiteral(font, beforeCursor, x, height - 12, 0xe0e0e0);
|
||||
x += font->widthLiteral(beforeCursor);
|
||||
if (frame / 6 % 2 == 0)
|
||||
drawString(font, L"_", x, height - 12, 0xe0e0e0);
|
||||
x += font->width(L"_");
|
||||
drawStringLiteral(font, afterCursor, x, height - 12, 0xe0e0e0);
|
||||
Screen::render(xm, ym, a);
|
||||
}
|
||||
|
||||
|
|
@ -71,13 +164,15 @@ void ChatScreen::mouseClicked(int x, int y, int buttonNum)
|
|||
{
|
||||
if (message.length() > 0 && message[message.length()-1]!=L' ')
|
||||
{
|
||||
message += L" ";
|
||||
message = message.substr(0, cursorIndex) + L" " + message.substr(cursorIndex);
|
||||
cursorIndex++;
|
||||
}
|
||||
message += minecraft->gui->selectedName;
|
||||
unsigned int maxLength = SharedConstants::maxChatLength;
|
||||
if (message.length() > maxLength)
|
||||
size_t nameLen = minecraft->gui->selectedName.length();
|
||||
size_t insertLen = (message.length() + nameLen <= SharedConstants::maxChatLength) ? nameLen : (SharedConstants::maxChatLength - message.length());
|
||||
if (insertLen > 0)
|
||||
{
|
||||
message = message.substr(0, maxLength);
|
||||
message = message.substr(0, cursorIndex) + minecraft->gui->selectedName.substr(0, insertLen) + message.substr(cursorIndex);
|
||||
cursorIndex += static_cast<int>(insertLen);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -85,5 +180,4 @@ void ChatScreen::mouseClicked(int x, int y, int buttonNum)
|
|||
Screen::mouseClicked(x, y, buttonNum);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,21 +1,33 @@
|
|||
#pragma once
|
||||
#include "Screen.h"
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
class ChatScreen : public Screen
|
||||
{
|
||||
protected:
|
||||
wstring message;
|
||||
int cursorIndex;
|
||||
void applyHistoryMessage();
|
||||
|
||||
private:
|
||||
int frame;
|
||||
static const size_t CHAT_HISTORY_MAX = 100;
|
||||
static std::vector<wstring> s_chatHistory;
|
||||
static int s_historyIndex;
|
||||
static wstring s_historyDraft;
|
||||
static const wstring allowedChars;
|
||||
static bool isAllowedChatChar(wchar_t c);
|
||||
|
||||
public:
|
||||
ChatScreen(); //4J added
|
||||
ChatScreen();
|
||||
virtual void init();
|
||||
virtual void removed();
|
||||
virtual void tick();
|
||||
private:
|
||||
static const wstring allowedChars;
|
||||
virtual void removed();
|
||||
virtual void tick();
|
||||
virtual void handlePasteRequest();
|
||||
virtual void handleHistoryUp();
|
||||
virtual void handleHistoryDown();
|
||||
|
||||
protected:
|
||||
void keyPressed(wchar_t ch, int eventKey);
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -1441,6 +1441,9 @@ void ClientConnection::handleChat(shared_ptr<ChatPacket> packet)
|
|||
|
||||
switch(packet->m_messageType)
|
||||
{
|
||||
case ChatPacket::e_ChatCustom:
|
||||
message = (packet->m_stringArgs.size() >= 1) ? packet->m_stringArgs[0] : L"";
|
||||
break;
|
||||
case ChatPacket::e_ChatBedOccupied:
|
||||
message = app.GetString(IDS_TILE_BED_OCCUPIED);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1486,12 +1486,26 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b
|
|||
}
|
||||
break;
|
||||
case ACTION_MENU_UP:
|
||||
#ifdef _WINDOWS64
|
||||
if (g_KBMInput.WasMouseWheelConsumed())
|
||||
{
|
||||
handleAdditionalKeyPress(ACTION_MENU_OTHER_STICK_UP);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
//ui.PlayUISFX(eSFX_Focus);
|
||||
m_eCurrTapState = eTapStateUp;
|
||||
}
|
||||
break;
|
||||
case ACTION_MENU_DOWN:
|
||||
#ifdef _WINDOWS64
|
||||
if (g_KBMInput.WasMouseWheelConsumed())
|
||||
{
|
||||
handleAdditionalKeyPress(ACTION_MENU_OTHER_STICK_DOWN);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
//ui.PlayUISFX(eSFX_Focus);
|
||||
m_eCurrTapState = eTapStateDown;
|
||||
|
|
|
|||
|
|
@ -1099,13 +1099,7 @@ void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction)
|
|||
break;
|
||||
case ACTION_MENU_OTHER_STICK_DOWN:
|
||||
{
|
||||
int pageStep = TabSpec::rows;
|
||||
#ifdef _WINDOWS64
|
||||
if (g_KBMInput.WasMouseWheelConsumed())
|
||||
{
|
||||
pageStep = 1;
|
||||
}
|
||||
#endif
|
||||
int pageStep = 1;
|
||||
m_tabPage[m_curTab] += pageStep;
|
||||
if(m_tabPage[m_curTab] >= specs[m_curTab]->getPageCount())
|
||||
{
|
||||
|
|
@ -1119,13 +1113,7 @@ void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction)
|
|||
break;
|
||||
case ACTION_MENU_OTHER_STICK_UP:
|
||||
{
|
||||
int pageStep = TabSpec::rows;
|
||||
#ifdef _WINDOWS64
|
||||
if (g_KBMInput.WasMouseWheelConsumed())
|
||||
{
|
||||
pageStep = 1;
|
||||
}
|
||||
#endif
|
||||
int pageStep = 1;
|
||||
m_tabPage[m_curTab] -= pageStep;
|
||||
if(m_tabPage[m_curTab] < 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,10 +55,16 @@ void UIComponent_Chat::handleTimerComplete(int id)
|
|||
float opacity = pGui->getOpacity(m_iPad, i);
|
||||
if( opacity > 0 )
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
// Chat drawn by Gui::render with color codes. Hides Iggy chat to avoid double chats.
|
||||
m_controlLabelBackground[i].setOpacity(0);
|
||||
m_labelChatText[i].setOpacity(0);
|
||||
m_labelChatText[i].setLabel(L"");
|
||||
#else
|
||||
m_controlLabelBackground[i].setOpacity(opacity);
|
||||
m_labelChatText[i].setOpacity(opacity);
|
||||
m_labelChatText[i].setLabel( pGui->getMessage(m_iPad,i) );
|
||||
|
||||
#endif
|
||||
anyVisible = true;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -62,10 +64,8 @@ public:
|
|||
|
||||
virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName);
|
||||
void UpdateControl();
|
||||
#ifdef __PSVITA__
|
||||
void setHidden(bool bHidden) {m_bHidden=bHidden;}
|
||||
bool getHidden(void) {return m_bHidden;}
|
||||
#endif
|
||||
|
||||
IggyValuePath *getIggyValuePath();
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -16,6 +25,7 @@ bool UIControl_TextInput::setupControl(UIScene *scene, IggyValuePath *parent, co
|
|||
m_textName = registerFastName(L"text");
|
||||
m_funcChangeState = registerFastName(L"ChangeState");
|
||||
m_funcSetCharLimit = registerFastName(L"SetCharLimit");
|
||||
m_funcSetCaretIndex = registerFastName(L"SetCaretIndex");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
@ -81,3 +91,197 @@ void UIControl_TextInput::SetCharLimit(int iLimit)
|
|||
value[0].number = iLimit;
|
||||
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_funcSetCharLimit , 1 , value );
|
||||
}
|
||||
|
||||
void UIControl_TextInput::setCaretVisible(bool visible)
|
||||
{
|
||||
if (!m_parentScene || !m_parentScene->getMovie())
|
||||
return;
|
||||
|
||||
// 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"))
|
||||
{
|
||||
IggyValueSetBooleanRS(&caretPath, m_nameVisible, NULL, visible);
|
||||
}
|
||||
}
|
||||
|
||||
void UIControl_TextInput::setCaretIndex(int index)
|
||||
{
|
||||
if (!m_parentScene || !m_parentScene->getMovie())
|
||||
return;
|
||||
|
||||
IggyDataValue result;
|
||||
IggyDataValue value[1];
|
||||
value[0].type = IGGY_DATATYPE_number;
|
||||
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(), true);
|
||||
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(), true);
|
||||
setCaretVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void UIControl_TextInput::confirmDirectEdit()
|
||||
{
|
||||
if (m_bDirectEditing)
|
||||
{
|
||||
m_bDirectEditing = false;
|
||||
setLabel(m_editBuffer.c_str(), true);
|
||||
setCaretVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,7 +6,20 @@ class UIControl_TextInput : public UIControl_Base
|
|||
{
|
||||
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();
|
||||
|
|
@ -19,4 +32,24 @@ public:
|
|||
virtual void setFocus(bool focus);
|
||||
|
||||
void SetCharLimit(int iLimit);
|
||||
|
||||
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
|
||||
};
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include "UI.h"
|
||||
#include "UIScene.h"
|
||||
#include "UIControl_Slider.h"
|
||||
#include "UIControl_TexturePackList.h"
|
||||
#include "..\..\..\Minecraft.World\StringHelpers.h"
|
||||
#include "..\..\LocalPlayer.h"
|
||||
#include "..\..\DLCTexturePack.h"
|
||||
|
|
@ -237,6 +238,8 @@ UIController::UIController()
|
|||
m_winUserIndex = 0;
|
||||
m_mouseDraggingSliderScene = eUIScene_COUNT;
|
||||
m_mouseDraggingSliderId = -1;
|
||||
m_mouseClickConsumedByScene = false;
|
||||
m_bMouseHoverHorizontalList = false;
|
||||
m_lastHoverMouseX = -1;
|
||||
m_lastHoverMouseY = -1;
|
||||
m_wasControllerConnected = false;
|
||||
|
|
@ -785,72 +788,36 @@ void UIController::tickInput()
|
|||
#endif
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
// When a controller is plugged in and focus is NULL then set focus to the first button
|
||||
{
|
||||
bool controllerConnected = Win64_IsControllerConnected();
|
||||
if (controllerConnected && !m_wasControllerConnected)
|
||||
{
|
||||
UIScene* pFocusScene = NULL;
|
||||
for (int grp = 0; grp < eUIGroup_COUNT && !pFocusScene; ++grp)
|
||||
{
|
||||
pFocusScene = m_groups[grp]->GetTopScene(eUILayer_Debug);
|
||||
if (!pFocusScene) pFocusScene = m_groups[grp]->GetTopScene(eUILayer_Tooltips);
|
||||
if (!pFocusScene) pFocusScene = m_groups[grp]->GetTopScene(eUILayer_Error);
|
||||
if (!pFocusScene) pFocusScene = m_groups[grp]->GetTopScene(eUILayer_Alert);
|
||||
if (!pFocusScene) pFocusScene = m_groups[grp]->GetTopScene(eUILayer_Popup);
|
||||
if (!pFocusScene) pFocusScene = m_groups[grp]->GetTopScene(eUILayer_Fullscreen);
|
||||
if (!pFocusScene) pFocusScene = m_groups[grp]->GetTopScene(eUILayer_Scene);
|
||||
}
|
||||
if (pFocusScene && pFocusScene->getMovie())
|
||||
{
|
||||
Iggy* focusMovie = pFocusScene->getMovie();
|
||||
IggyFocusHandle currentFocus = IGGY_FOCUS_NULL;
|
||||
IggyFocusableObject focusables[64];
|
||||
S32 numFocusables = 0;
|
||||
IggyPlayerGetFocusableObjects(focusMovie, ¤tFocus, focusables, 64, &numFocusables);
|
||||
if (currentFocus == IGGY_FOCUS_NULL && numFocusables > 0)
|
||||
{
|
||||
IggyPlayerSetFocusRS(focusMovie, focusables[0].object, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_wasControllerConnected = controllerConnected;
|
||||
}
|
||||
|
||||
m_mouseClickConsumedByScene = false;
|
||||
if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
|
||||
{
|
||||
UIScene* pScene = NULL;
|
||||
for (int grp = 0; grp < eUIGroup_COUNT && !pScene; ++grp)
|
||||
UIScene *pScene = NULL;
|
||||
// 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
|
||||
|
|
@ -859,42 +826,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 != currentFocus && (hitObject != IGGY_FOCUS_NULL || !Win64_IsControllerConnected()))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -907,6 +853,111 @@ void UIController::tickInput()
|
|||
panelOffsetX = pMainPanel->getXPos();
|
||||
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)
|
||||
{
|
||||
m_bMouseHoverHorizontalList = false;
|
||||
vector<UIControl *> *controls = pScene->GetControls();
|
||||
if (controls)
|
||||
{
|
||||
int hitControlId = -1;
|
||||
S32 hitArea = INT_MAX;
|
||||
UIControl *hitCtrl = NULL;
|
||||
for (size_t i = 0; i < controls->size(); ++i)
|
||||
{
|
||||
UIControl *ctrl = (*controls)[i];
|
||||
if (!ctrl || ctrl->getHidden() || !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 && type != UIControl::eTexturePackList)
|
||||
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();
|
||||
// TexturePackList origin is where the slot area starts,
|
||||
// not the top-left of the whole control — use GetRealHeight.
|
||||
if (type == UIControl::eTexturePackList)
|
||||
ch = ((UIControl_TexturePackList *)ctrl)->GetRealHeight();
|
||||
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;
|
||||
hitArea = INT_MAX;
|
||||
hitCtrl = NULL;
|
||||
break; // ButtonList takes priority
|
||||
}
|
||||
if (type == UIControl::eTexturePackList)
|
||||
{
|
||||
// TexturePackList expects coords relative to its origin.
|
||||
UIControl_TexturePackList *pList = (UIControl_TexturePackList *)ctrl;
|
||||
pScene->SetFocusToElement(ctrl->getId());
|
||||
pList->SetTouchFocus(
|
||||
(S32)(sceneMouseX - cx), (S32)(sceneMouseY - cy), false);
|
||||
m_bMouseHoverHorizontalList = true;
|
||||
hitControlId = -1;
|
||||
hitArea = INT_MAX;
|
||||
hitCtrl = NULL;
|
||||
break;
|
||||
}
|
||||
S32 area = cw * ch;
|
||||
if (area < hitArea)
|
||||
{
|
||||
hitControlId = ctrl->getId();
|
||||
hitArea = area;
|
||||
hitCtrl = ctrl;
|
||||
if (type == UIControl::eSlider)
|
||||
m_bMouseHoverHorizontalList = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hitControlId >= 0 && pScene->getControlFocus() != hitControlId)
|
||||
{
|
||||
// During direct editing, don't let hover move focus
|
||||
// away to other TextInputs (e.g. sign lines).
|
||||
if (hitCtrl && hitCtrl->getControlType() == UIControl::eTextInput
|
||||
&& pScene->isDirectEditBlocking())
|
||||
{
|
||||
// Skip — keep focus on the actively-edited input
|
||||
}
|
||||
else
|
||||
{
|
||||
pScene->SetFocusToElement(hitControlId);
|
||||
// TextInput: SetFocusToElement triggers ChangeState which
|
||||
// shows the caret. Hide it immediately — the render pass
|
||||
// happens after both tickInput and scene tick, so no flicker.
|
||||
if (hitCtrl && hitCtrl->getControlType() == UIControl::eTextInput)
|
||||
{
|
||||
((UIControl_TextInput *)hitCtrl)->setCaretVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool leftPressed = g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT);
|
||||
bool leftDown = leftPressed || g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT);
|
||||
if (m_mouseDraggingSliderScene != eUIScene_COUNT && m_mouseDraggingSliderScene != pScene->getSceneType())
|
||||
|
|
@ -919,12 +970,52 @@ 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;
|
||||
UIControl_Slider* pSlider = (UIControl_Slider*)ctrl;
|
||||
|
||||
if (pMainPanel && ctrl->getParentPanel() != pMainPanel)
|
||||
continue;
|
||||
|
||||
UIControl_Slider *pSlider = (UIControl_Slider *)ctrl;
|
||||
pSlider->UpdateControl();
|
||||
S32 cx = pSlider->getXPos() + panelOffsetX;
|
||||
S32 cy = pSlider->getYPos() + panelOffsetY;
|
||||
|
|
@ -968,6 +1059,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
|
||||
|
|
@ -1232,7 +1329,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; }
|
||||
|
|
@ -1240,6 +1337,14 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
|
|||
}
|
||||
}
|
||||
|
||||
// Right click → ACTION_MENU_X (pick up half stack in inventory)
|
||||
if (key == ACTION_MENU_X && !g_KBMInput.IsMouseGrabbed())
|
||||
{
|
||||
if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT)) { pressed = true; down = true; }
|
||||
if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT)) { released = true; down = false; }
|
||||
if (!pressed && !released && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_RIGHT)) { down = true; }
|
||||
}
|
||||
|
||||
// Scroll wheel for list scrolling — only consume the wheel value when the
|
||||
// action key actually matches, so the other direction isn't lost.
|
||||
if (!g_KBMInput.IsMouseGrabbed() && (key == ACTION_MENU_OTHER_STICK_UP || key == ACTION_MENU_OTHER_STICK_DOWN))
|
||||
|
|
@ -1257,6 +1362,16 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
|
|||
pressed = true;
|
||||
down = true;
|
||||
}
|
||||
|
||||
// Remap scroll wheel to navigation actions. Use LEFT/RIGHT when
|
||||
// hovering a horizontal list (e.g. TexturePackList), UP/DOWN otherwise.
|
||||
if (pressed && g_KBMInput.IsKBMActive())
|
||||
{
|
||||
if (m_bMouseHoverHorizontalList)
|
||||
key = (key == ACTION_MENU_OTHER_STICK_UP) ? ACTION_MENU_LEFT : ACTION_MENU_RIGHT;
|
||||
else
|
||||
key = (key == ACTION_MENU_OTHER_STICK_UP) ? ACTION_MENU_UP : ACTION_MENU_DOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ private:
|
|||
unsigned int m_winUserIndex;
|
||||
EUIScene m_mouseDraggingSliderScene;
|
||||
int m_mouseDraggingSliderId;
|
||||
bool m_mouseClickConsumedByScene;
|
||||
bool m_bMouseHoverHorizontalList;
|
||||
int m_lastHoverMouseX;
|
||||
int m_lastHoverMouseY;
|
||||
bool m_wasControllerConnected;
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ void UIScene::initialiseMovie()
|
|||
m_bUpdateOpacity = true;
|
||||
}
|
||||
|
||||
#ifdef __PSVITA__
|
||||
#if defined(__PSVITA__) || defined(_WINDOWS64)
|
||||
void UIScene::SetFocusToElement(int iID)
|
||||
{
|
||||
IggyDataValue result;
|
||||
|
|
@ -447,6 +447,19 @@ void UIScene::tick()
|
|||
IggyPlayerTickRS( swf );
|
||||
m_hasTickedOnce = true;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
{
|
||||
vector<UIControl_TextInput*> inputs;
|
||||
getDirectEditInputs(inputs);
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
UIControl_TextInput::EDirectEditResult result = inputs[i]->tickDirectEdit();
|
||||
if (result != UIControl_TextInput::eDirectEdit_Continue)
|
||||
onDirectEditFinished(inputs[i], result);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UIControl* UIScene::GetMainPanel()
|
||||
|
|
@ -454,6 +467,113 @@ UIControl* UIScene::GetMainPanel()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
bool UIScene::isDirectEditBlocking()
|
||||
{
|
||||
vector<UIControl_TextInput*> inputs;
|
||||
getDirectEditInputs(inputs);
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
if (inputs[i]->isDirectEditing() || inputs[i]->getDirectEditCooldown() > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// Click-outside-to-deselect: confirm any active direct edit if
|
||||
// the click landed outside the editing text input.
|
||||
{
|
||||
vector<UIControl_TextInput*> deInputs;
|
||||
getDirectEditInputs(deInputs);
|
||||
for (size_t i = 0; i < deInputs.size(); i++)
|
||||
{
|
||||
if (!deInputs[i]->isDirectEditing())
|
||||
continue;
|
||||
deInputs[i]->UpdateControl();
|
||||
S32 cx = deInputs[i]->getXPos() + panelOffsetX;
|
||||
S32 cy = deInputs[i]->getYPos() + panelOffsetY;
|
||||
S32 cw = deInputs[i]->getWidth();
|
||||
S32 ch = deInputs[i]->getHeight();
|
||||
if (!(cw > 0 && ch > 0 && x >= cx && x <= cx + cw && y >= cy && y <= cy + ch))
|
||||
{
|
||||
deInputs[i]->confirmDirectEdit();
|
||||
onDirectEditFinished(deInputs[i], UIControl_TextInput::eDirectEdit_Confirmed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<UIControl *> *controls = GetControls();
|
||||
if (!controls) return false;
|
||||
|
||||
// Hit-test controls and pick the smallest-area match to handle
|
||||
// overlapping Flash bounds correctly without sacrificing precision.
|
||||
int bestId = -1;
|
||||
S32 bestArea = INT_MAX;
|
||||
UIControl *bestCtrl = NULL;
|
||||
|
||||
for (size_t i = 0; i < controls->size(); ++i)
|
||||
{
|
||||
UIControl *ctrl = (*controls)[i];
|
||||
if (!ctrl || ctrl->getHidden() || !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)
|
||||
{
|
||||
S32 area = cw * ch;
|
||||
if (area < bestArea)
|
||||
{
|
||||
bestArea = area;
|
||||
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)
|
||||
{
|
||||
|
|
@ -534,12 +654,13 @@ void UIScene::removeControl( UIControl_Base *control, bool centreScene)
|
|||
// update the button positions since they may have changed
|
||||
UpdateSceneControls();
|
||||
|
||||
// mark the button as removed
|
||||
control->setHidden(true);
|
||||
// remove it from the touchboxes
|
||||
ui.TouchBoxRebuild(control->getParentScene());
|
||||
#endif
|
||||
|
||||
// mark the button as removed so hover/touch hit-tests skip it
|
||||
control->setHidden(true);
|
||||
|
||||
}
|
||||
|
||||
void UIScene::slideLeft()
|
||||
|
|
@ -900,6 +1021,25 @@ void UIScene::sendInputToMovie(int key, bool repeat, bool pressed, bool released
|
|||
app.DebugPrintf("UI WARNING: Ignoring input as game action does not translate to an Iggy keycode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
// If a navigation key is pressed with no focused element, focus the first
|
||||
// available one so arrow keys work even when the mouse is over empty space.
|
||||
if(pressed && (iggyKeyCode == IGGY_KEYCODE_UP || iggyKeyCode == IGGY_KEYCODE_DOWN ||
|
||||
iggyKeyCode == IGGY_KEYCODE_LEFT || iggyKeyCode == IGGY_KEYCODE_RIGHT))
|
||||
{
|
||||
IggyFocusHandle currentFocus = IGGY_FOCUS_NULL;
|
||||
IggyFocusableObject focusables[64];
|
||||
S32 numFocusables = 0;
|
||||
IggyPlayerGetFocusableObjects(swf, ¤tFocus, focusables, 64, &numFocusables);
|
||||
if(currentFocus == IGGY_FOCUS_NULL && numFocusables > 0)
|
||||
{
|
||||
IggyPlayerSetFocusRS(swf, focusables[0].object, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
IggyEvent keyEvent;
|
||||
// 4J Stu - Keyloc is always standard as we don't care about shift/alt
|
||||
IggyMakeEventKey( &keyEvent, pressed?IGGY_KEYEVENT_Down:IGGY_KEYEVENT_Up, (IggyKeycode)iggyKeyCode, IGGY_KEYLOC_Standard );
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using namespace std;
|
|||
|
||||
#include "UIEnums.h"
|
||||
#include "UIControl_Base.h"
|
||||
#include "UIControl_TextInput.h"
|
||||
|
||||
class ItemRenderer;
|
||||
class UILayer;
|
||||
|
|
@ -16,22 +17,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 +146,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 +184,19 @@ public:
|
|||
// returns main panel if controls are not living in the root
|
||||
virtual UIControl* GetMainPanel();
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
// Direct edit support: scenes override to register their text inputs.
|
||||
// Base class handles tickDirectEdit in tick(), click-outside-to-deselect
|
||||
// in handleMouseClick(), and provides isDirectEditBlocking() for guards.
|
||||
virtual void getDirectEditInputs(vector<UIControl_TextInput*> &inputs) {}
|
||||
virtual void onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result) {}
|
||||
bool isDirectEditBlocking();
|
||||
|
||||
// Mouse click dispatch. Hit-tests C++ controls and picks the smallest-area
|
||||
// match, then calls 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,19 @@ void UIScene_AnvilMenu::tick()
|
|||
{
|
||||
UIScene_AbstractContainerMenu::tick();
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
// Live update: sync item name per-keystroke while editing (like Java edition)
|
||||
if (m_textInputAnvil.isDirectEditing())
|
||||
{
|
||||
const wstring& buf = m_textInputAnvil.getEditBuffer();
|
||||
if (buf != m_itemName)
|
||||
{
|
||||
m_itemName = buf;
|
||||
updateItemName();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
handleTick();
|
||||
}
|
||||
|
||||
|
|
@ -306,26 +319,67 @@ UIControl *UIScene_AnvilMenu::getSection(ESceneSection eSection)
|
|||
return control;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
void UIScene_AnvilMenu::getDirectEditInputs(vector<UIControl_TextInput*> &inputs)
|
||||
{
|
||||
inputs.push_back(&m_textInputAnvil);
|
||||
}
|
||||
|
||||
void UIScene_AnvilMenu::onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result)
|
||||
{
|
||||
m_itemName = input->getEditBuffer();
|
||||
updateItemName();
|
||||
}
|
||||
#endif
|
||||
|
||||
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 (isDirectEditBlocking())
|
||||
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 +391,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 +411,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 +431,8 @@ void UIScene_AnvilMenu::showCross(bool show)
|
|||
{
|
||||
if(m_showingCross != show)
|
||||
{
|
||||
if (!getMovie()) return;
|
||||
|
||||
IggyDataValue result;
|
||||
IggyDataValue value[1];
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ protected:
|
|||
|
||||
virtual UIControl *getSection(ESceneSection eSection);
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
virtual void getDirectEditInputs(vector<UIControl_TextInput*> &inputs);
|
||||
virtual void onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result);
|
||||
#endif
|
||||
static int KeyboardCompleteCallback(LPVOID lpParam,bool bRes);
|
||||
virtual void handleEditNamePressed();
|
||||
virtual void setEditNameValue(const wstring &name);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -254,12 +262,14 @@ wstring UIScene_CraftingMenu::getMoviePath()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __PSVITA__
|
||||
#if defined(__PSVITA__) || defined(_WINDOWS64)
|
||||
UIControl* UIScene_CraftingMenu::GetMainPanel()
|
||||
{
|
||||
return &m_controlMainPanel;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __PSVITA__
|
||||
void UIScene_CraftingMenu::handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased)
|
||||
{
|
||||
// perform action on release
|
||||
|
|
@ -383,6 +393,85 @@ void UIScene_CraftingMenu::handleTimerComplete(int id)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
bool UIScene_CraftingMenu::handleMouseClick(F32 x, F32 y)
|
||||
{
|
||||
if (!m_hSlotBoundsValid || m_hSlotSpacing <= 0)
|
||||
return false;
|
||||
|
||||
// Tab click — tabs sit directly above the H slot row. We derive their
|
||||
// bounds from the H slot positions cached in customDraw, since the Vita
|
||||
// TouchPanel controls are full-screen overlays with unusable bounds.
|
||||
int maxTabs = (m_iContainerType == RECIPE_TYPE_3x3) ? m_iMaxGroup3x3 : m_iMaxGroup2x2;
|
||||
F32 slotHeight = m_hSlotY1 - m_hSlotY0;
|
||||
F32 tabRowY0 = (m_hSlotY0 * 0.75f) - slotHeight * 1.55f;
|
||||
F32 tabRowY1 = tabRowY0 + (slotHeight * 1.7f);
|
||||
F32 tabRowWidth = m_hSlotSpacing * m_iCraftablesMaxHSlotC;
|
||||
F32 tabWidth = tabRowWidth / maxTabs;
|
||||
|
||||
if (tabWidth > 0 && x >= m_hSlotX0 && x < m_hSlotX0 + tabRowWidth &&
|
||||
y >= tabRowY0 && y < tabRowY1)
|
||||
{
|
||||
int iTab = (int)((x - m_hSlotX0) / tabWidth);
|
||||
if (iTab >= 0 && iTab < maxTabs && iTab != m_iGroupIndex)
|
||||
{
|
||||
showTabHighlight(m_iGroupIndex, false);
|
||||
m_iGroupIndex = iTab;
|
||||
showTabHighlight(m_iGroupIndex, true);
|
||||
m_iCurrentSlotHIndex = 0;
|
||||
m_iCurrentSlotVIndex = 1;
|
||||
CheckRecipesAvailable();
|
||||
iVSlotIndexA[0] = CanBeMadeA[m_iCurrentSlotHIndex].iCount - 1;
|
||||
iVSlotIndexA[1] = 0;
|
||||
iVSlotIndexA[2] = 1;
|
||||
ui.PlayUISFX(eSFX_Focus);
|
||||
UpdateVerticalSlots();
|
||||
UpdateHighlight();
|
||||
setGroupText(GetGroupNameText(m_pGroupA[m_iGroupIndex]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// H slot click — select or craft
|
||||
F32 rowWidth = m_hSlotSpacing * m_iCraftablesMaxHSlotC;
|
||||
if (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)
|
||||
{
|
||||
// Only interact with populated slots
|
||||
if (CanBeMadeA[iNewSlot].iCount == 0)
|
||||
return true;
|
||||
|
||||
if (iNewSlot == m_iCurrentSlotHIndex)
|
||||
{
|
||||
// Click on already-selected slot — craft the item
|
||||
handleKeyDown(m_iPad, ACTION_MENU_A, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
// Consume all mouse clicks so misses don't generate ACTION_MENU_A
|
||||
// and accidentally craft. Only blocks mouse-originated presses.
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIScene_CraftingMenu::handleReload()
|
||||
{
|
||||
m_slotListInventory.addSlots(CRAFTING_INVENTORY_SLOT_START,CRAFTING_INVENTORY_SLOT_END - CRAFTING_INVENTORY_SLOT_START);
|
||||
|
|
@ -478,6 +567,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;
|
||||
|
|
|
|||
|
|
@ -66,10 +66,19 @@ public:
|
|||
|
||||
#ifdef __PSVITA__
|
||||
virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased);
|
||||
virtual UIControl* GetMainPanel();
|
||||
virtual void handleTouchBoxRebuild();
|
||||
virtual void handleTimerComplete(int id);
|
||||
#endif
|
||||
#if defined(__PSVITA__) || defined(_WINDOWS64)
|
||||
virtual UIControl* GetMainPanel();
|
||||
#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;
|
||||
|
|
@ -97,7 +106,7 @@ protected:
|
|||
ETouchInput_TouchPanel_5,
|
||||
ETouchInput_TouchPanel_6,
|
||||
ETouchInput_CraftingHSlots,
|
||||
|
||||
|
||||
ETouchInput_Count,
|
||||
};
|
||||
UIControl_Touch m_TouchInput[ETouchInput_Count];
|
||||
|
|
|
|||
|
|
@ -84,10 +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;
|
||||
#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.
|
||||
|
|
@ -293,53 +289,6 @@ void UIScene_CreateWorldMenu::tick()
|
|||
{
|
||||
UIScene::tick();
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
if (m_iDirectEditCooldown > 0)
|
||||
m_iDirectEditCooldown--;
|
||||
|
||||
if (m_bDirectEditing)
|
||||
{
|
||||
wchar_t ch;
|
||||
bool changed = false;
|
||||
while (g_KBMInput.ConsumeChar(ch))
|
||||
{
|
||||
if (ch == 0x08) // backspace
|
||||
{
|
||||
if (!m_worldName.empty())
|
||||
{
|
||||
m_worldName.pop_back();
|
||||
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());
|
||||
}
|
||||
else if ((int)m_worldName.length() < 25)
|
||||
{
|
||||
m_worldName += ch;
|
||||
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_buttonCreateWorld.setEnable(!m_worldName.empty());
|
||||
}
|
||||
else if (changed)
|
||||
{
|
||||
m_editWorldName.setLabel(m_worldName.c_str());
|
||||
m_buttonCreateWorld.setEnable(!m_worldName.empty());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(m_iSetTexturePackDescription >= 0 )
|
||||
{
|
||||
|
|
@ -403,11 +352,24 @@ int UIScene_CreateWorldMenu::ContinueOffline(void *pParam,int iPad,C4JStorage::E
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
void UIScene_CreateWorldMenu::getDirectEditInputs(vector<UIControl_TextInput*> &inputs)
|
||||
{
|
||||
inputs.push_back(&m_editWorldName);
|
||||
}
|
||||
|
||||
void UIScene_CreateWorldMenu::onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result)
|
||||
{
|
||||
m_worldName = input->getEditBuffer();
|
||||
m_buttonCreateWorld.setEnable(!m_worldName.empty());
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIScene_CreateWorldMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
|
||||
{
|
||||
if(m_bIgnoreInput) return;
|
||||
#ifdef _WINDOWS64
|
||||
if (m_bDirectEditing || m_iDirectEditCooldown > 0) { handled = true; return; }
|
||||
if (isDirectEditBlocking()) { handled = true; return; }
|
||||
#endif
|
||||
|
||||
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
|
||||
|
|
@ -464,7 +426,7 @@ void UIScene_CreateWorldMenu::handlePress(F64 controlId, F64 childId)
|
|||
{
|
||||
if(m_bIgnoreInput) return;
|
||||
#ifdef _WINDOWS64
|
||||
if (m_bDirectEditing || m_iDirectEditCooldown > 0) return;
|
||||
if (isDirectEditBlocking()) return;
|
||||
#endif
|
||||
|
||||
//CD - Added for audio
|
||||
|
|
@ -476,7 +438,7 @@ void UIScene_CreateWorldMenu::handlePress(F64 controlId, F64 childId)
|
|||
{
|
||||
m_bIgnoreInput=true;
|
||||
#ifdef _WINDOWS64
|
||||
if (Win64_IsControllerConnected())
|
||||
if (!g_KBMInput.IsKBMActive())
|
||||
{
|
||||
UIKeyboardInitData kbData;
|
||||
kbData.title = app.GetString(IDS_CREATE_NEW_WORLD);
|
||||
|
|
@ -488,11 +450,8 @@ void UIScene_CreateWorldMenu::handlePress(F64 controlId, F64 childId)
|
|||
}
|
||||
else
|
||||
{
|
||||
// PC without controller: 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;
|
||||
g_KBMInput.ClearCharBuffer();
|
||||
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,11 +51,6 @@ private:
|
|||
DLCPack * m_pDLCPack;
|
||||
bool m_bRebuildTouchBoxes;
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
bool m_bDirectEditing;
|
||||
wstring m_worldNameBeforeEdit;
|
||||
int m_iDirectEditCooldown;
|
||||
#endif
|
||||
|
||||
public:
|
||||
UIScene_CreateWorldMenu(int iPad, void *initData, UILayer *parentLayer);
|
||||
|
|
@ -83,6 +78,10 @@ protected:
|
|||
public:
|
||||
// INPUT
|
||||
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
|
||||
#ifdef _WINDOWS64
|
||||
virtual void getDirectEditInputs(vector<UIControl_TextInput*> &inputs);
|
||||
virtual void onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void StartSharedLaunchFlow();
|
||||
|
|
|
|||
|
|
@ -41,8 +41,72 @@ 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
|
||||
void UIScene_DebugCreateSchematic::getDirectEditInputs(vector<UIControl_TextInput*> &inputs)
|
||||
{
|
||||
inputs.push_back(&m_textInputName);
|
||||
inputs.push_back(&m_textInputStartX);
|
||||
inputs.push_back(&m_textInputStartY);
|
||||
inputs.push_back(&m_textInputStartZ);
|
||||
inputs.push_back(&m_textInputEndX);
|
||||
inputs.push_back(&m_textInputEndY);
|
||||
inputs.push_back(&m_textInputEndZ);
|
||||
}
|
||||
|
||||
void UIScene_DebugCreateSchematic::onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result)
|
||||
{
|
||||
wstring value = input->getEditBuffer();
|
||||
int iVal = 0;
|
||||
if (!value.empty())
|
||||
iVal = _fromString<int>(value);
|
||||
|
||||
if (input == &m_textInputName)
|
||||
{
|
||||
if (!value.empty())
|
||||
swprintf(m_data->name, 64, L"%ls", value.c_str());
|
||||
else
|
||||
swprintf(m_data->name, 64, L"schematic");
|
||||
}
|
||||
else if (input == &m_textInputStartX) m_data->startX = iVal;
|
||||
else if (input == &m_textInputStartY) m_data->startY = iVal;
|
||||
else if (input == &m_textInputStartZ) m_data->startZ = iVal;
|
||||
else if (input == &m_textInputEndX) m_data->endX = iVal;
|
||||
else if (input == &m_textInputEndY) m_data->endY = iVal;
|
||||
else if (input == &m_textInputEndZ) m_data->endZ = iVal;
|
||||
}
|
||||
|
||||
bool UIScene_DebugCreateSchematic::handleMouseClick(F32 x, F32 y)
|
||||
{
|
||||
UIScene::handleMouseClick(x, y);
|
||||
return true; // always consume to prevent Iggy re-entry on empty space
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIScene_DebugCreateSchematic::tick()
|
||||
{
|
||||
UIScene::tick();
|
||||
}
|
||||
|
||||
void UIScene_DebugCreateSchematic::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
if (isDirectEditBlocking()) return;
|
||||
#endif
|
||||
ui.AnimateKeyPress(iPad, key, repeat, pressed, released);
|
||||
|
||||
switch(key)
|
||||
|
|
@ -67,6 +131,9 @@ void UIScene_DebugCreateSchematic::handleInput(int iPad, int key, bool repeat, b
|
|||
|
||||
void UIScene_DebugCreateSchematic::handlePress(F64 controlId, F64 childId)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
if (isDirectEditBlocking()) return;
|
||||
#endif
|
||||
switch((int)controlId)
|
||||
{
|
||||
case eControl_Create:
|
||||
|
|
@ -112,8 +179,28 @@ 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())
|
||||
{
|
||||
UIControl_TextInput* input = getTextInputForControl(m_keyboardCallbackControl);
|
||||
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 +225,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,7 @@ private:
|
|||
|
||||
ConsoleSchematicFile::XboxSchematicInitParam *m_data;
|
||||
|
||||
|
||||
public:
|
||||
UIScene_DebugCreateSchematic(int iPad, void *initData, UILayer *parentLayer);
|
||||
|
||||
|
|
@ -58,8 +59,14 @@ protected:
|
|||
UI_END_MAP_ELEMENTS_AND_NAMES()
|
||||
|
||||
virtual wstring getMoviePath();
|
||||
#ifdef _WINDOWS64
|
||||
virtual void getDirectEditInputs(vector<UIControl_TextInput*> &inputs);
|
||||
virtual void onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result);
|
||||
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 +75,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,7 @@ 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)");
|
||||
|
||||
}
|
||||
|
||||
wstring UIScene_DebugSetCamera::getMoviePath()
|
||||
|
|
@ -62,8 +63,59 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
void UIScene_DebugSetCamera::getDirectEditInputs(vector<UIControl_TextInput*> &inputs)
|
||||
{
|
||||
inputs.push_back(&m_textInputX);
|
||||
inputs.push_back(&m_textInputY);
|
||||
inputs.push_back(&m_textInputZ);
|
||||
inputs.push_back(&m_textInputYRot);
|
||||
inputs.push_back(&m_textInputElevation);
|
||||
}
|
||||
|
||||
void UIScene_DebugSetCamera::onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result)
|
||||
{
|
||||
wstring value = input->getEditBuffer();
|
||||
double val = 0;
|
||||
if (!value.empty()) val = _fromString<double>(value);
|
||||
|
||||
if (input == &m_textInputX) currentPosition->m_camX = val;
|
||||
else if (input == &m_textInputY) currentPosition->m_camY = val;
|
||||
else if (input == &m_textInputZ) currentPosition->m_camZ = val;
|
||||
else if (input == &m_textInputYRot) currentPosition->m_yRot = val;
|
||||
else if (input == &m_textInputElevation) currentPosition->m_elev = val;
|
||||
}
|
||||
|
||||
bool UIScene_DebugSetCamera::handleMouseClick(F32 x, F32 y)
|
||||
{
|
||||
UIScene::handleMouseClick(x, y);
|
||||
return true; // always consume to prevent Iggy re-entry on empty space
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIScene_DebugSetCamera::tick()
|
||||
{
|
||||
UIScene::tick();
|
||||
}
|
||||
|
||||
void UIScene_DebugSetCamera::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
if (isDirectEditBlocking()) { handled = true; return; }
|
||||
#endif
|
||||
ui.AnimateKeyPress(iPad, key, repeat, pressed, released);
|
||||
|
||||
switch(key)
|
||||
|
|
@ -88,11 +140,14 @@ void UIScene_DebugSetCamera::handleInput(int iPad, int key, bool repeat, bool pr
|
|||
|
||||
void UIScene_DebugSetCamera::handlePress(F64 controlId, F64 childId)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
if (isDirectEditBlocking()) return;
|
||||
#endif
|
||||
switch((int)controlId)
|
||||
{
|
||||
case eControl_Teleport:
|
||||
app.SetXuiServerAction( ProfileManager.GetPrimaryPad(),
|
||||
eXuiServerAction_SetCameraLocation,
|
||||
eXuiServerAction_SetCameraLocation,
|
||||
(void *)currentPosition);
|
||||
break;
|
||||
case eControl_CamX:
|
||||
|
|
@ -100,8 +155,26 @@ 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())
|
||||
{
|
||||
UIControl_TextInput* input = getTextInputForControl(m_keyboardCallbackControl);
|
||||
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 +192,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,9 @@ private:
|
|||
FreezePlayerParam *fpp;
|
||||
|
||||
eControls m_keyboardCallbackControl;
|
||||
#ifdef _WINDOWS64
|
||||
UIControl_TextInput* getTextInputForControl(eControls ctrl);
|
||||
#endif
|
||||
|
||||
public:
|
||||
UIScene_DebugSetCamera(int iPad, void *initData, UILayer *parentLayer);
|
||||
|
|
@ -54,6 +57,12 @@ protected:
|
|||
UI_END_MAP_ELEMENTS_AND_NAMES()
|
||||
|
||||
virtual wstring getMoviePath();
|
||||
virtual void tick();
|
||||
#ifdef _WINDOWS64
|
||||
virtual void getDirectEditInputs(vector<UIControl_TextInput*> &inputs);
|
||||
virtual void onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result);
|
||||
virtual bool handleMouseClick(F32 x, F32 y);
|
||||
#endif
|
||||
|
||||
public:
|
||||
// INPUT
|
||||
|
|
|
|||
|
|
@ -753,10 +753,16 @@ void UIScene_HUD::handleTimerComplete(int id)
|
|||
float opacity = pGui->getOpacity(m_iPad, i);
|
||||
if( opacity > 0 )
|
||||
{
|
||||
#if 0 // def _WINDOWS64 // Use Iggy chat until Gui::render has visual parity
|
||||
// Chat drawn by Gui::render with color codes. Hides Iggy chat to avoid double chats.
|
||||
m_controlLabelBackground[i].setOpacity(0);
|
||||
m_labelChatText[i].setOpacity(0);
|
||||
m_labelChatText[i].setLabel(L"");
|
||||
#else
|
||||
m_controlLabelBackground[i].setOpacity(opacity);
|
||||
m_labelChatText[i].setOpacity(opacity);
|
||||
m_labelChatText[i].setLabel( pGui->getMessagesCount(m_iPad) ? pGui->getMessage(m_iPad,i) : L"" );
|
||||
|
||||
#endif
|
||||
anyVisible = true;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -163,6 +163,12 @@ void UIScene_Keyboard::tick()
|
|||
{
|
||||
UIScene::tick();
|
||||
|
||||
// Sync our buffer from Flash so we pick up changes made via controller/on-screen buttons.
|
||||
// Without this, switching between controller and keyboard would use stale text.
|
||||
const wchar_t* flashText = m_KeyboardTextInput.getLabel();
|
||||
if (flashText)
|
||||
m_win64TextBuffer = flashText;
|
||||
|
||||
// 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.
|
||||
|
|
|
|||
|
|
@ -257,6 +257,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 (isDirectEditBlocking()) 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 +337,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 +551,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,18 +570,52 @@ 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;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
void UIScene_LaunchMoreOptionsMenu::getDirectEditInputs(vector<UIControl_TextInput*> &inputs)
|
||||
{
|
||||
inputs.push_back(&m_editSeed);
|
||||
}
|
||||
|
||||
void UIScene_LaunchMoreOptionsMenu::onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result)
|
||||
{
|
||||
if (result == UIControl_TextInput::eDirectEdit_Confirmed)
|
||||
m_params->seed = input->getEditBuffer();
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIScene_LaunchMoreOptionsMenu::handlePress(F64 controlId, F64 childId)
|
||||
{
|
||||
if(m_bIgnoreInput) return;
|
||||
#ifdef _WINDOWS64
|
||||
if (isDirectEditBlocking()) 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 +627,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;
|
||||
|
|
|
|||
|
|
@ -140,6 +140,10 @@ protected:
|
|||
public:
|
||||
virtual void tick();
|
||||
virtual void handleDestroy();
|
||||
#ifdef _WINDOWS64
|
||||
virtual void getDirectEditInputs(vector<UIControl_TextInput*> &inputs);
|
||||
virtual void onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result);
|
||||
#endif
|
||||
// INPUT
|
||||
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
|
||||
virtual void handleFocusChange(F64 controlId, F64 childId);
|
||||
|
|
@ -160,6 +164,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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,43 @@ void UIScene_LoadOrJoinMenu::handleInput(int iPad, int key, bool repeat, bool pr
|
|||
LaunchSaveTransfer();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef _WINDOWS64
|
||||
// Right click on a save opens save options (same as RB / ACTION_MENU_RIGHT_SCROLL)
|
||||
if(pressed && !repeat && ProfileManager.IsFullVersion() && !StorageManager.GetSaveDisabled())
|
||||
{
|
||||
if(DoesSavesListHaveFocus() && (m_iDefaultButtonsC > 0) && (m_iSaveListIndex >= m_iDefaultButtonsC))
|
||||
{
|
||||
m_bIgnoreInput = true;
|
||||
if(StorageManager.EnoughSpaceForAMinSaveGame())
|
||||
{
|
||||
UINT uiIDA[3];
|
||||
uiIDA[0]=IDS_CONFIRM_CANCEL;
|
||||
uiIDA[1]=IDS_TITLE_RENAMESAVE;
|
||||
uiIDA[2]=IDS_TOOLTIPS_DELETESAVE;
|
||||
ui.RequestAlertMessage(IDS_TOOLTIPS_SAVEOPTIONS, IDS_TEXT_SAVEOPTIONS, uiIDA, 3, iPad,&UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned,this);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT uiIDA[2];
|
||||
uiIDA[0]=IDS_CONFIRM_CANCEL;
|
||||
uiIDA[1]=IDS_CONFIRM_OK;
|
||||
ui.RequestAlertMessage(IDS_TOOLTIPS_DELETESAVE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, iPad,&UIScene_LoadOrJoinMenu::DeleteSaveDialogReturned,this);
|
||||
}
|
||||
ui.PlayUISFX(eSFX_Press);
|
||||
}
|
||||
else if(DoesMashUpWorldHaveFocus() && (m_iSaveListIndex != JOIN_LOAD_CREATE_BUTTON_INDEX))
|
||||
{
|
||||
LevelGenerationOptions *levelGen = m_generators.at(m_iSaveListIndex - 1);
|
||||
if(!levelGen->isTutorial() && levelGen->requiresTexturePack())
|
||||
{
|
||||
m_bIgnoreInput = true;
|
||||
app.HideMashupPackWorld(m_iPad, levelGen->getRequiredTexturePackId());
|
||||
m_iState = e_SavesRepopulateAfterMashupHide;
|
||||
}
|
||||
ui.PlayUISFX(eSFX_Press);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case ACTION_MENU_Y:
|
||||
|
|
@ -2394,7 +2431,7 @@ int UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned(void *pParam,int iPad,C4JS
|
|||
kbData.maxChars = 25;
|
||||
kbData.callback = &UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback;
|
||||
kbData.lpParam = pClass;
|
||||
kbData.pcMode = !Win64_IsControllerConnected();
|
||||
kbData.pcMode = g_KBMInput.IsKBMActive();
|
||||
ui.NavigateToScene(pClass->m_iPad, eUIScene_Keyboard, &kbData);
|
||||
}
|
||||
#elif defined _DURANGO
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@ UIScene_SignEntryMenu::UIScene_SignEntryMenu(int iPad, void *_initData, UILayer
|
|||
|
||||
m_bConfirmed = false;
|
||||
m_bIgnoreInput = false;
|
||||
m_iSignCursorFrame = 0;
|
||||
#ifdef _WINDOWS64
|
||||
m_iActiveDirectEditLine = -1;
|
||||
m_bNeedsInitialEdit = true;
|
||||
m_bSkipTickNav = false;
|
||||
#endif
|
||||
|
||||
m_buttonConfirm.init(app.GetString(IDS_DONE), eControl_Confirm);
|
||||
m_labelMessage.init(app.GetString(IDS_EDIT_SIGN_MESSAGE));
|
||||
|
|
@ -53,6 +59,7 @@ UIScene_SignEntryMenu::UIScene_SignEntryMenu(int iPad, void *_initData, UILayer
|
|||
|
||||
UIScene_SignEntryMenu::~UIScene_SignEntryMenu()
|
||||
{
|
||||
m_sign->SetSelectedLine(-1);
|
||||
m_parentLayer->removeComponent(eUIComponent_MenuBackground);
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +84,79 @@ void UIScene_SignEntryMenu::tick()
|
|||
{
|
||||
UIScene::tick();
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
// On first tick, auto-start editing line 1 if KBM is active (Java-style flow)
|
||||
if (m_bNeedsInitialEdit)
|
||||
{
|
||||
m_bNeedsInitialEdit = false;
|
||||
if (g_KBMInput.IsKBMActive())
|
||||
{
|
||||
SetFocusToElement(eControl_Line1);
|
||||
m_iActiveDirectEditLine = 0;
|
||||
m_textInputLines[0].beginDirectEdit(15);
|
||||
}
|
||||
}
|
||||
|
||||
// UP/DOWN navigation — must happen after tickDirectEdit (so typed chars are consumed)
|
||||
// and before sign cursor update (so the cursor is correct for this frame's render)
|
||||
// m_bSkipTickNav prevents double-processing when handleInput auto-started editing this frame
|
||||
if (m_iActiveDirectEditLine >= 0 && !m_bSkipTickNav)
|
||||
{
|
||||
int navDir = 0;
|
||||
if (g_KBMInput.IsKeyPressed(VK_DOWN)) navDir = 1;
|
||||
else if (g_KBMInput.IsKeyPressed(VK_UP)) navDir = -1;
|
||||
|
||||
if (navDir != 0)
|
||||
{
|
||||
int newLine = m_iActiveDirectEditLine + navDir;
|
||||
if (newLine >= eControl_Line1 && newLine <= eControl_Line4)
|
||||
{
|
||||
m_textInputLines[m_iActiveDirectEditLine].confirmDirectEdit();
|
||||
SetFocusToElement(newLine);
|
||||
m_iActiveDirectEditLine = newLine;
|
||||
m_textInputLines[newLine].beginDirectEdit(15);
|
||||
}
|
||||
else if (navDir > 0)
|
||||
{
|
||||
m_textInputLines[m_iActiveDirectEditLine].confirmDirectEdit();
|
||||
SetFocusToElement(eControl_Confirm);
|
||||
m_iActiveDirectEditLine = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_bSkipTickNav = false;
|
||||
|
||||
if (m_iActiveDirectEditLine >= 0 && !m_textInputLines[m_iActiveDirectEditLine].isDirectEditing())
|
||||
m_iActiveDirectEditLine = -1;
|
||||
#endif
|
||||
|
||||
// Blinking > text < cursor on the 3D sign
|
||||
m_iSignCursorFrame++;
|
||||
if (m_iSignCursorFrame / 6 % 2 == 0)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
if (m_iActiveDirectEditLine >= 0)
|
||||
m_sign->SetSelectedLine(m_iActiveDirectEditLine);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int focusedLine = -1;
|
||||
for (int i = eControl_Line1; i <= eControl_Line4; i++)
|
||||
{
|
||||
if (controlHasFocus(i))
|
||||
{
|
||||
focusedLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_sign->SetSelectedLine(focusedLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sign->SetSelectedLine(-1);
|
||||
}
|
||||
|
||||
if(m_bConfirmed)
|
||||
{
|
||||
m_bConfirmed = false;
|
||||
|
|
@ -107,6 +187,9 @@ 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 (isDirectEditBlocking()) { handled = true; return; }
|
||||
#endif
|
||||
|
||||
ui.AnimateKeyPress(iPad, key, repeat, pressed, released);
|
||||
|
||||
|
|
@ -132,31 +215,124 @@ void UIScene_SignEntryMenu::handleInput(int iPad, int key, bool repeat, bool pre
|
|||
#ifdef __ORBIS__
|
||||
case ACTION_MENU_TOUCHPAD_PRESS:
|
||||
#endif
|
||||
sendInputToMovie(key, repeat, pressed, released);
|
||||
handled = true;
|
||||
break;
|
||||
case ACTION_MENU_UP:
|
||||
case ACTION_MENU_DOWN:
|
||||
sendInputToMovie(key, repeat, pressed, released);
|
||||
#ifdef _WINDOWS64
|
||||
// Auto-start editing if focus moved to a line (e.g. UP from Confirm)
|
||||
if (g_KBMInput.IsKBMActive())
|
||||
{
|
||||
for (int i = eControl_Line1; i <= eControl_Line4; i++)
|
||||
{
|
||||
if (controlHasFocus(i))
|
||||
{
|
||||
m_iActiveDirectEditLine = i;
|
||||
m_textInputLines[i].beginDirectEdit(15);
|
||||
m_bSkipTickNav = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
void UIScene_SignEntryMenu::getDirectEditInputs(vector<UIControl_TextInput*> &inputs)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
inputs.push_back(&m_textInputLines[i]);
|
||||
}
|
||||
|
||||
void UIScene_SignEntryMenu::onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result)
|
||||
{
|
||||
int line = -1;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (input == &m_textInputLines[i]) { line = i; break; }
|
||||
}
|
||||
if (line != m_iActiveDirectEditLine) return;
|
||||
|
||||
if (result == UIControl_TextInput::eDirectEdit_Confirmed)
|
||||
{
|
||||
int newLine = line + 1;
|
||||
if (newLine <= eControl_Line4)
|
||||
{
|
||||
SetFocusToElement(newLine);
|
||||
m_iActiveDirectEditLine = newLine;
|
||||
m_textInputLines[newLine].beginDirectEdit(15);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iActiveDirectEditLine = -1;
|
||||
m_bConfirmed = true;
|
||||
}
|
||||
}
|
||||
else if (result == UIControl_TextInput::eDirectEdit_Cancelled)
|
||||
{
|
||||
m_iActiveDirectEditLine = -1;
|
||||
wstring temp = L"";
|
||||
for (int j = 0; j < 4; j++)
|
||||
m_sign->SetMessage(j, temp);
|
||||
navigateBack();
|
||||
ui.PlayUISFX(eSFX_Back);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIScene_SignEntryMenu::handleMouseClick(F32 x, F32 y)
|
||||
{
|
||||
if (m_iActiveDirectEditLine >= 0)
|
||||
{
|
||||
// During direct edit, only the Done button is clickable.
|
||||
// Hit-test it manually — all other clicks are consumed but ignored.
|
||||
m_buttonConfirm.UpdateControl();
|
||||
S32 cx = m_buttonConfirm.getXPos();
|
||||
S32 cy = m_buttonConfirm.getYPos();
|
||||
S32 cw = m_buttonConfirm.getWidth();
|
||||
S32 ch = m_buttonConfirm.getHeight();
|
||||
if (cw > 0 && ch > 0 && x >= cx && x <= cx + cw && y >= cy && y <= cy + ch)
|
||||
{
|
||||
m_textInputLines[m_iActiveDirectEditLine].confirmDirectEdit();
|
||||
m_iActiveDirectEditLine = -1;
|
||||
m_bConfirmed = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return UIScene::handleMouseClick(x, y);
|
||||
}
|
||||
#endif
|
||||
|
||||
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
|
||||
if (isDirectEditBlocking()) return;
|
||||
#endif
|
||||
switch((int)controlId)
|
||||
{
|
||||
case eControl_Confirm:
|
||||
|
|
@ -170,6 +346,28 @@ void UIScene_SignEntryMenu::handlePress(F64 controlId, F64 childId)
|
|||
case eControl_Line4:
|
||||
{
|
||||
m_iEditingLine = (int)controlId;
|
||||
#ifdef _WINDOWS64
|
||||
if (g_KBMInput.IsKBMActive())
|
||||
{
|
||||
// Only start editing from keyboard (Enter on focused line), not mouse clicks
|
||||
if (!g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
|
||||
{
|
||||
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 +385,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,12 @@ private:
|
|||
int m_iEditingLine;
|
||||
bool m_bConfirmed;
|
||||
bool m_bIgnoreInput;
|
||||
int m_iSignCursorFrame;
|
||||
#ifdef _WINDOWS64
|
||||
int m_iActiveDirectEditLine;
|
||||
bool m_bNeedsInitialEdit;
|
||||
bool m_bSkipTickNav;
|
||||
#endif
|
||||
|
||||
UIControl_Button m_buttonConfirm;
|
||||
UIControl_Label m_labelMessage;
|
||||
|
|
@ -50,6 +56,11 @@ protected:
|
|||
public:
|
||||
// INPUT
|
||||
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
|
||||
#ifdef _WINDOWS64
|
||||
virtual void getDirectEditInputs(vector<UIControl_TextInput*> &inputs);
|
||||
virtual void onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result);
|
||||
virtual bool handleMouseClick(F32 x, F32 y);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void handlePress(F64 controlId, F64 childId);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor
|
|||
enforceUnicodeSheet = false;
|
||||
bidirectional = false;
|
||||
xPos = yPos = 0.0f;
|
||||
m_bold = false;
|
||||
m_italic = false;
|
||||
m_underline = false;
|
||||
m_strikethrough = false;
|
||||
|
||||
// Set up member variables
|
||||
m_cols = cols;
|
||||
|
|
@ -126,6 +130,60 @@ Font::~Font()
|
|||
}
|
||||
#endif
|
||||
|
||||
void Font::renderStyleLine(float x0, float y0, float x1, float y1)
|
||||
{
|
||||
Tesselator* t = Tesselator::getInstance();
|
||||
float u = 0.0f, v = 0.0f;
|
||||
t->begin();
|
||||
t->tex(u, v);
|
||||
t->vertex(x0, y1, 0.0f);
|
||||
t->tex(u, v);
|
||||
t->vertex(x1, y1, 0.0f);
|
||||
t->tex(u, v);
|
||||
t->vertex(x1, y0, 0.0f);
|
||||
t->tex(u, v);
|
||||
t->vertex(x0, y0, 0.0f);
|
||||
t->end();
|
||||
}
|
||||
|
||||
void Font::addCharacterQuad(wchar_t c)
|
||||
{
|
||||
float xOff = c % m_cols * m_charWidth;
|
||||
float yOff = c / m_cols * m_charWidth;
|
||||
float width = charWidths[c] - .01f;
|
||||
float height = m_charHeight - .01f;
|
||||
float fontWidth = m_cols * m_charWidth;
|
||||
float fontHeight = m_rows * m_charHeight;
|
||||
const float shear = m_italic ? (height * 0.25f) : 0.0f;
|
||||
float x0 = xPos, x1 = xPos + width + shear;
|
||||
float y0 = yPos, y1 = yPos + height;
|
||||
|
||||
Tesselator *t = Tesselator::getInstance();
|
||||
t->tex(xOff / fontWidth, (yOff + 7.99f) / fontHeight);
|
||||
t->vertex(x0, y1, 0.0f);
|
||||
t->tex((xOff + width) / fontWidth, (yOff + 7.99f) / fontHeight);
|
||||
t->vertex(x1, y1, 0.0f);
|
||||
t->tex((xOff + width) / fontWidth, yOff / fontHeight);
|
||||
t->vertex(x1, y0, 0.0f);
|
||||
t->tex(xOff / fontWidth, yOff / fontHeight);
|
||||
t->vertex(x0, y0, 0.0f);
|
||||
|
||||
if (m_bold)
|
||||
{
|
||||
float dx = 1.0f;
|
||||
t->tex(xOff / fontWidth, (yOff + 7.99f) / fontHeight);
|
||||
t->vertex(x0 + dx, y1, 0.0f);
|
||||
t->tex((xOff + width) / fontWidth, (yOff + 7.99f) / fontHeight);
|
||||
t->vertex(x1 + dx, y1, 0.0f);
|
||||
t->tex((xOff + width) / fontWidth, yOff / fontHeight);
|
||||
t->vertex(x1 + dx, y0, 0.0f);
|
||||
t->tex(xOff / fontWidth, yOff / fontHeight);
|
||||
t->vertex(x0 + dx, y0, 0.0f);
|
||||
}
|
||||
|
||||
xPos += static_cast<float>(charWidths[c]);
|
||||
}
|
||||
|
||||
void Font::renderCharacter(wchar_t c)
|
||||
{
|
||||
float xOff = c % m_cols * m_charWidth;
|
||||
|
|
@ -137,37 +195,47 @@ void Font::renderCharacter(wchar_t c)
|
|||
float fontWidth = m_cols * m_charWidth;
|
||||
float fontHeight = m_rows * m_charHeight;
|
||||
|
||||
Tesselator *t = Tesselator::getInstance();
|
||||
// 4J Stu - Changed to a quad so that we can use within a command buffer
|
||||
#if 1
|
||||
const float shear = m_italic ? (height * 0.25f) : 0.0f;
|
||||
float x0 = xPos, x1 = xPos + width + shear;
|
||||
float y0 = yPos, y1 = yPos + height;
|
||||
|
||||
Tesselator *t = Tesselator::getInstance();
|
||||
t->begin();
|
||||
t->tex(xOff / fontWidth, (yOff + 7.99f) / fontHeight);
|
||||
t->vertex(xPos, yPos + height, 0.0f);
|
||||
|
||||
t->vertex(x0, y1, 0.0f);
|
||||
t->tex((xOff + width) / fontWidth, (yOff + 7.99f) / fontHeight);
|
||||
t->vertex(xPos + width, yPos + height, 0.0f);
|
||||
|
||||
t->vertex(x1, y1, 0.0f);
|
||||
t->tex((xOff + width) / fontWidth, yOff / fontHeight);
|
||||
t->vertex(xPos + width, yPos, 0.0f);
|
||||
|
||||
t->vertex(x1, y0, 0.0f);
|
||||
t->tex(xOff / fontWidth, yOff / fontHeight);
|
||||
t->vertex(xPos, yPos, 0.0f);
|
||||
|
||||
t->vertex(x0, y0, 0.0f);
|
||||
t->end();
|
||||
#else
|
||||
t->begin(GL_TRIANGLE_STRIP);
|
||||
t->tex(xOff / 128.0F, yOff / 128.0F);
|
||||
t->vertex(xPos, yPos, 0.0f);
|
||||
t->tex(xOff / 128.0F, (yOff + 7.99f) / 128.0F);
|
||||
t->vertex(xPos, yPos + 7.99f, 0.0f);
|
||||
t->tex((xOff + width) / 128.0F, yOff / 128.0F);
|
||||
t->vertex(xPos + width, yPos, 0.0f);
|
||||
t->tex((xOff + width) / 128.0F, (yOff + 7.99f) / 128.0F);
|
||||
t->vertex(xPos + width, yPos + 7.99f, 0.0f);
|
||||
t->end();
|
||||
#endif
|
||||
|
||||
xPos += (float) charWidths[c];
|
||||
if (m_bold)
|
||||
{
|
||||
float dx = 1.0f;
|
||||
t->begin();
|
||||
t->tex(xOff / fontWidth, (yOff + 7.99f) / fontHeight);
|
||||
t->vertex(x0 + dx, y1, 0.0f);
|
||||
t->tex((xOff + width) / fontWidth, (yOff + 7.99f) / fontHeight);
|
||||
t->vertex(x1 + dx, y1, 0.0f);
|
||||
t->tex((xOff + width) / fontWidth, yOff / fontHeight);
|
||||
t->vertex(x1 + dx, y0, 0.0f);
|
||||
t->tex(xOff / fontWidth, yOff / fontHeight);
|
||||
t->vertex(x0 + dx, y0, 0.0f);
|
||||
t->end();
|
||||
}
|
||||
|
||||
if (m_underline)
|
||||
renderStyleLine(x0, y1 - 1.0f, xPos + static_cast<float>(charWidths[c]), y1);
|
||||
|
||||
if (m_strikethrough)
|
||||
{
|
||||
float mid = y0 + height * 0.5f;
|
||||
renderStyleLine(x0, mid - 0.5f, xPos + static_cast<float>(charWidths[c]), mid + 0.5f);
|
||||
}
|
||||
|
||||
xPos += static_cast<float>(charWidths[c]);
|
||||
}
|
||||
|
||||
void Font::drawShadow(const wstring& str, int x, int y, int color)
|
||||
|
|
@ -176,6 +244,26 @@ void Font::drawShadow(const wstring& str, int x, int y, int color)
|
|||
draw(str, x, y, color, false);
|
||||
}
|
||||
|
||||
void Font::drawShadowLiteral(const wstring& str, int x, int y, int color)
|
||||
{
|
||||
int shadowColor = (color & 0xFCFCFC) >> 2 | (color & 0xFF000000);
|
||||
drawLiteral(str, x + 1, y + 1, shadowColor);
|
||||
drawLiteral(str, x, y, color);
|
||||
}
|
||||
|
||||
void Font::drawLiteral(const wstring& str, int x, int y, int color)
|
||||
{
|
||||
if (str.empty()) return;
|
||||
if ((color & 0xFC000000) == 0) color |= 0xFF000000;
|
||||
textures->bindTexture(m_textureLocation);
|
||||
glColor4f((color >> 16 & 255) / 255.0F, (color >> 8 & 255) / 255.0F, (color & 255) / 255.0F, (color >> 24 & 255) / 255.0F);
|
||||
xPos = static_cast<float>(x);
|
||||
yPos = static_cast<float>(y);
|
||||
wstring cleanStr = sanitize(str);
|
||||
for (size_t i = 0; i < cleanStr.length(); ++i)
|
||||
renderCharacter(cleanStr.at(i));
|
||||
}
|
||||
|
||||
void Font::drawShadowWordWrap(const wstring &str, int x, int y, int w, int color, int h)
|
||||
{
|
||||
drawWordWrapInternal(str, x + 1, y + 1, w, color, true, h);
|
||||
|
|
@ -193,24 +281,42 @@ wstring Font::reorderBidi(const wstring &str)
|
|||
return str;
|
||||
}
|
||||
|
||||
static bool isSectionFormatCode(wchar_t ca)
|
||||
{
|
||||
if ((ca >= L'0' && ca <= L'9') || (ca >= L'a' && ca <= L'f') || (ca >= L'A' && ca <= L'F'))
|
||||
return true;
|
||||
wchar_t l = static_cast<wchar_t>(ca | 32);
|
||||
return l == L'l' || l == L'o' || l == L'n' || l == L'm' || l == L'r' || l == L'k';
|
||||
}
|
||||
|
||||
void Font::draw(const wstring &str, bool dropShadow)
|
||||
{
|
||||
// Bind the texture
|
||||
textures->bindTexture(m_textureLocation);
|
||||
|
||||
bool noise = false;
|
||||
m_bold = m_italic = m_underline = m_strikethrough = false;
|
||||
wstring cleanStr = sanitize(str);
|
||||
|
||||
for (int i = 0; i < (int)cleanStr.length(); ++i)
|
||||
Tesselator *t = Tesselator::getInstance();
|
||||
t->begin();
|
||||
|
||||
for (int i = 0; i < static_cast<int>(cleanStr.length()); ++i)
|
||||
{
|
||||
// Map character
|
||||
wchar_t c = cleanStr.at(i);
|
||||
|
||||
if (c == 167 && i + 1 < cleanStr.length())
|
||||
{
|
||||
// 4J - following block was:
|
||||
// int colorN = L"0123456789abcdefk".indexOf(str.toLowerCase().charAt(i + 1));
|
||||
wchar_t ca = cleanStr[i+1];
|
||||
if (!isSectionFormatCode(ca))
|
||||
{
|
||||
t->end();
|
||||
renderCharacter(167);
|
||||
renderCharacter(ca);
|
||||
t->begin();
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
int colorN = 16;
|
||||
if(( ca >= L'0' ) && (ca <= L'9')) colorN = ca - L'0';
|
||||
else if(( ca >= L'a' ) && (ca <= L'f')) colorN = (ca - L'a') + 10;
|
||||
|
|
@ -218,20 +324,22 @@ void Font::draw(const wstring &str, bool dropShadow)
|
|||
|
||||
if (colorN == 16)
|
||||
{
|
||||
noise = true;
|
||||
wchar_t l = static_cast<wchar_t>(ca | 32);
|
||||
if (l == L'l') m_bold = true;
|
||||
else if (l == L'o') m_italic = true;
|
||||
else if (l == L'n') m_underline = true;
|
||||
else if (l == L'm') m_strikethrough = true;
|
||||
else if (l == L'r') m_bold = m_italic = m_underline = m_strikethrough = noise = false;
|
||||
else if (l == L'k') noise = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
noise = false;
|
||||
if (colorN < 0 || colorN > 15) colorN = 15;
|
||||
|
||||
if (dropShadow) colorN += 16;
|
||||
|
||||
int color = colors[colorN];
|
||||
glColor3f((color >> 16) / 255.0F, ((color >> 8) & 255) / 255.0F, (color & 255) / 255.0F);
|
||||
}
|
||||
|
||||
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -247,8 +355,10 @@ void Font::draw(const wstring &str, bool dropShadow)
|
|||
c = newc;
|
||||
}
|
||||
|
||||
renderCharacter(c);
|
||||
addCharacterQuad(c);
|
||||
}
|
||||
|
||||
t->end();
|
||||
}
|
||||
|
||||
void Font::draw(const wstring& str, int x, int y, int color, bool dropShadow)
|
||||
|
|
@ -280,20 +390,34 @@ int Font::width(const wstring& str)
|
|||
{
|
||||
wchar_t c = cleanStr.at(i);
|
||||
|
||||
if(c == 167)
|
||||
if (c == 167)
|
||||
{
|
||||
// Ignore the character used to define coloured text
|
||||
++i;
|
||||
if (i + 1 < cleanStr.length() && isSectionFormatCode(cleanStr[i+1]))
|
||||
++i;
|
||||
else
|
||||
{
|
||||
len += charWidths[167];
|
||||
if (i + 1 < cleanStr.length())
|
||||
len += charWidths[static_cast<unsigned>(cleanStr[++i])];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len += charWidths[c];
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int Font::widthLiteral(const wstring& str)
|
||||
{
|
||||
wstring cleanStr = sanitize(str);
|
||||
if (cleanStr == L"") return 0;
|
||||
int len = 0;
|
||||
for (size_t i = 0; i < cleanStr.length(); ++i)
|
||||
len += charWidths[static_cast<unsigned>(cleanStr.at(i))];
|
||||
return len;
|
||||
}
|
||||
|
||||
wstring Font::sanitize(const wstring& str)
|
||||
{
|
||||
wstring sb = str;
|
||||
|
|
@ -467,7 +591,7 @@ void Font::setBidirectional(bool bidirectional)
|
|||
|
||||
bool Font::AllCharactersValid(const wstring &str)
|
||||
{
|
||||
for (int i = 0; i < (int)str.length(); ++i)
|
||||
for (int i = 0; i < static_cast<int>(str.length()); ++i)
|
||||
{
|
||||
wchar_t c = str.at(i);
|
||||
|
||||
|
|
@ -512,15 +636,15 @@ void Font::renderFakeCB(IntBuffer *ib)
|
|||
float uo = (0.0f) / 128.0f;
|
||||
float vo = (0.0f) / 128.0f;
|
||||
|
||||
t->vertexUV((float)(0), (float)( 0 + s), (float)( 0), (float)( ix / 128.0f + uo), (float)( (iy + s) / 128.0f + vo));
|
||||
t->vertexUV((float)(0 + s), (float)( 0 + s), (float)( 0), (float)( (ix + s) / 128.0f + uo), (float)( (iy + s) / 128.0f + vo));
|
||||
t->vertexUV((float)(0 + s), (float)( 0), (float)( 0), (float)( (ix + s) / 128.0f + uo), (float)( iy / 128.0f + vo));
|
||||
t->vertexUV((float)(0), (float)( 0), (float)( 0), (float)( ix / 128.0f + uo), (float)( iy / 128.0f + vo));
|
||||
t->vertexUV(static_cast<float>(0), static_cast<float>(0 + s), static_cast<float>(0), static_cast<float>(ix / 128.0f + uo), static_cast<float>((iy + s) / 128.0f + vo));
|
||||
t->vertexUV(static_cast<float>(0 + s), static_cast<float>(0 + s), static_cast<float>(0), static_cast<float>((ix + s) / 128.0f + uo), static_cast<float>((iy + s) / 128.0f + vo));
|
||||
t->vertexUV(static_cast<float>(0 + s), static_cast<float>(0), static_cast<float>(0), static_cast<float>((ix + s) / 128.0f + uo), static_cast<float>(iy / 128.0f + vo));
|
||||
t->vertexUV(static_cast<float>(0), static_cast<float>(0), static_cast<float>(0), static_cast<float>(ix / 128.0f + uo), static_cast<float>(iy / 128.0f + vo));
|
||||
// target.colorBlit(texture, x + xo, y, color, ix, iy,
|
||||
// charWidths[chars[i]], 8);
|
||||
t->end();
|
||||
|
||||
glTranslatef((float)charWidths[i], 0, 0);
|
||||
glTranslatef(static_cast<float>(charWidths[i]), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@ private:
|
|||
float xPos;
|
||||
float yPos;
|
||||
|
||||
// § format state (bold, italic, underline, strikethrough); set during draw(), reset by §r
|
||||
bool m_bold;
|
||||
bool m_italic;
|
||||
bool m_underline;
|
||||
bool m_strikethrough;
|
||||
|
||||
bool enforceUnicodeSheet; // use unicode sheet for ascii
|
||||
bool bidirectional; // use bidi to flip strings
|
||||
|
||||
|
|
@ -41,9 +47,12 @@ public:
|
|||
|
||||
private:
|
||||
void renderCharacter(wchar_t c); // 4J added
|
||||
void addCharacterQuad(wchar_t c);
|
||||
void renderStyleLine(float x0, float y0, float x1, float y1); // solid line for underline/strikethrough
|
||||
|
||||
public:
|
||||
void drawShadow(const wstring& str, int x, int y, int color);
|
||||
void drawShadowLiteral(const wstring& str, int x, int y, int color); // draw without interpreting § codes
|
||||
void drawShadowWordWrap(const wstring &str, int x, int y, int w, int color, int h); // 4J Added h param
|
||||
void draw(const wstring &str, int x, int y, int color);
|
||||
/**
|
||||
|
|
@ -58,11 +67,13 @@ private:
|
|||
|
||||
void draw(const wstring &str, bool dropShadow);
|
||||
void draw(const wstring& str, int x, int y, int color, bool dropShadow);
|
||||
void drawLiteral(const wstring& str, int x, int y, int color); // no § parsing
|
||||
int MapCharacter(wchar_t c); // 4J added
|
||||
bool CharacterExists(wchar_t c); // 4J added
|
||||
|
||||
public:
|
||||
int width(const wstring& str);
|
||||
int widthLiteral(const wstring& str); // width without skipping § codes (for chat input)
|
||||
wstring sanitize(const wstring& str);
|
||||
void drawWordWrap(const wstring &string, int x, int y, int w, int col, int h); // 4J Added h param
|
||||
|
||||
|
|
|
|||
|
|
@ -1169,8 +1169,6 @@ void GameRenderer::render(float a, bool bFirst)
|
|||
|
||||
lastNsTime = System::nanoTime();
|
||||
|
||||
ApplyGammaPostProcess();
|
||||
|
||||
if (!mc->options->hideGui || mc->screen != NULL)
|
||||
{
|
||||
mc->gui->render(a, mc->screen != NULL, xMouse, yMouse);
|
||||
|
|
@ -1196,6 +1194,7 @@ void GameRenderer::render(float a, bool bFirst)
|
|||
if (mc->screen != NULL && mc->screen->particles != NULL) mc->screen->particles->render(a);
|
||||
}
|
||||
|
||||
ApplyGammaPostProcess();
|
||||
}
|
||||
|
||||
void GameRenderer::renderLevel(float a)
|
||||
|
|
|
|||
|
|
@ -971,15 +971,10 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
|
|||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
|
||||
// 4J Stu - We have moved the chat text to a xui
|
||||
#if 0
|
||||
#if 0 // defined(_WINDOWS64) // Temporarily disable this chat in favor of iggy chat until we have better visual parity
|
||||
glPushMatrix();
|
||||
// 4J-PB we need to move this up a bit because we've moved the quick select
|
||||
//glTranslatef(0, ((float)screenHeight) - 48, 0);
|
||||
glTranslatef(0.0f, (float)(screenHeight - iSafezoneYHalf - iTooltipsYOffset - 16 - 3 + 22) - 24.0f, 0.0f);
|
||||
// glScalef(1.0f / ssc.scale, 1.0f / ssc.scale, 1);
|
||||
glTranslatef(0.0f, static_cast<float>(screenHeight - iSafezoneYHalf - iTooltipsYOffset - 16 - 3 + 22) - 24.0f, 0.0f);
|
||||
|
||||
// 4J-PB - we need gui messages for each of the possible 4 splitscreen players
|
||||
if(bDisplayGui)
|
||||
{
|
||||
int iPad=minecraft->player->GetXboxPad();
|
||||
|
|
@ -993,23 +988,21 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
|
|||
if (t < 0) t = 0;
|
||||
if (t > 1) t = 1;
|
||||
t = t * t;
|
||||
int alpha = (int) (255 * t);
|
||||
int alpha = static_cast<int>(255 * t);
|
||||
if (isChatting) alpha = 255;
|
||||
|
||||
if (alpha > 0)
|
||||
{
|
||||
int x = iSafezoneXHalf+2;
|
||||
int y = -((int)i) * 9;
|
||||
int y = -(static_cast<int>(i)) * 9;
|
||||
if(bTwoPlayerSplitscreen)
|
||||
{
|
||||
y+= iHeightOffset;
|
||||
}
|
||||
|
||||
wstring msg = guiMessages[iPad][i].string;
|
||||
// 4J-PB - fill the black bar across the whole screen, otherwise it looks odd due to the safe area
|
||||
this->fill(0, y - 1, screenWidth/fScaleFactorWidth, y + 8, (alpha / 2) << 24);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
font->drawShadow(msg, iSafezoneXHalf+4, y, 0xffffff + (alpha << 24));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ void GuiComponent::fill(int x0, int y0, int x1, int y1, int col)
|
|||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(r, g, b, a);
|
||||
t->begin();
|
||||
t->vertex((float)(x0), (float)( y1), (float)( 0));
|
||||
t->vertex((float)(x1), (float)( y1), (float)( 0));
|
||||
t->vertex((float)(x1), (float)( y0), (float)( 0));
|
||||
t->vertex((float)(x0), (float)( y0), (float)( 0));
|
||||
t->vertex(static_cast<float>(x0), static_cast<float>(y1), static_cast<float>(0));
|
||||
t->vertex(static_cast<float>(x1), static_cast<float>(y1), static_cast<float>(0));
|
||||
t->vertex(static_cast<float>(x1), static_cast<float>(y0), static_cast<float>(0));
|
||||
t->vertex(static_cast<float>(x0), static_cast<float>(y0), static_cast<float>(0));
|
||||
t->end();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
|
|
@ -77,11 +77,11 @@ void GuiComponent::fillGradient(int x0, int y0, int x1, int y1, int col1, int co
|
|||
Tesselator *t = Tesselator::getInstance();
|
||||
t->begin();
|
||||
t->color(r1, g1, b1, a1);
|
||||
t->vertex((float)(x1), (float)( y0), blitOffset);
|
||||
t->vertex((float)(x0), (float)( y0), blitOffset);
|
||||
t->vertex(static_cast<float>(x1), static_cast<float>(y0), blitOffset);
|
||||
t->vertex(static_cast<float>(x0), static_cast<float>(y0), blitOffset);
|
||||
t->color(r2, g2, b2, a2);
|
||||
t->vertex((float)(x0), (float)( y1), blitOffset);
|
||||
t->vertex((float)(x1), (float)( y1), blitOffset);
|
||||
t->vertex(static_cast<float>(x0), static_cast<float>(y1), blitOffset);
|
||||
t->vertex(static_cast<float>(x1), static_cast<float>(y1), blitOffset);
|
||||
t->end();
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
|
|
@ -105,6 +105,11 @@ void GuiComponent::drawString(Font *font, const wstring& str, int x, int y, int
|
|||
font->drawShadow(str, x, y, color);
|
||||
}
|
||||
|
||||
void GuiComponent::drawStringLiteral(Font *font, const wstring& str, int x, int y, int color)
|
||||
{
|
||||
font->drawShadowLiteral(str, x, y, color);
|
||||
}
|
||||
|
||||
void GuiComponent::blit(int x, int y, int sx, int sy, int w, int h)
|
||||
{
|
||||
float us = 1 / 256.0f;
|
||||
|
|
@ -117,20 +122,20 @@ void GuiComponent::blit(int x, int y, int sx, int sy, int w, int h)
|
|||
const float extraShift = 0.75f;
|
||||
|
||||
// 4J - subtracting extraShift (actual screen pixels, so need to compensate for physical & game width) from each x & y coordinate to compensate for centre of pixels in directx vs openGL
|
||||
float dx = ( extraShift * (float)Minecraft::GetInstance()->width ) / (float)Minecraft::GetInstance()->width_phys;
|
||||
float dx = ( extraShift * static_cast<float>(Minecraft::GetInstance()->width) ) / static_cast<float>(Minecraft::GetInstance()->width_phys);
|
||||
// 4J - Also factor in the scaling from gui coordinate space to the screen. This varies based on user-selected gui scale, and whether we are in a viewport mode or not
|
||||
dx /= Gui::currentGuiScaleFactor;
|
||||
float dy = extraShift / Gui::currentGuiScaleFactor;
|
||||
// Ensure that the x/y, width and height are actually pixel aligned at our current scale factor - in particular, for split screen mode with the default (3X)
|
||||
// scale, we have an overall scale factor of 3 * 0.5 = 1.5, and so any odd pixels won't align
|
||||
float fx = (floorf((float)x * Gui::currentGuiScaleFactor)) / Gui::currentGuiScaleFactor;
|
||||
float fy = (floorf((float)y * Gui::currentGuiScaleFactor)) / Gui::currentGuiScaleFactor;
|
||||
float fw = (floorf((float)w * Gui::currentGuiScaleFactor)) / Gui::currentGuiScaleFactor;
|
||||
float fh = (floorf((float)h * Gui::currentGuiScaleFactor)) / Gui::currentGuiScaleFactor;
|
||||
float fx = (floorf(static_cast<float>(x) * Gui::currentGuiScaleFactor)) / Gui::currentGuiScaleFactor;
|
||||
float fy = (floorf(static_cast<float>(y) * Gui::currentGuiScaleFactor)) / Gui::currentGuiScaleFactor;
|
||||
float fw = (floorf(static_cast<float>(w) * Gui::currentGuiScaleFactor)) / Gui::currentGuiScaleFactor;
|
||||
float fh = (floorf(static_cast<float>(h) * Gui::currentGuiScaleFactor)) / Gui::currentGuiScaleFactor;
|
||||
|
||||
t->vertexUV(fx + 0 - dx, fy + fh - dy, (float)( blitOffset), (float)( (sx + 0) * us), (float)( (sy + h) * vs));
|
||||
t->vertexUV(fx + fw - dx, fy + fh - dy, (float)( blitOffset), (float)( (sx + w) * us), (float)( (sy + h) * vs));
|
||||
t->vertexUV(fx + fw - dx, fy + 0 - dy, (float)( blitOffset), (float)( (sx + w) * us), (float)( (sy + 0) * vs));
|
||||
t->vertexUV(fx + 0 - dx, fy + 0 - dy, (float)( blitOffset), (float)( (sx + 0) * us), (float)( (sy + 0) * vs));
|
||||
t->vertexUV(fx + 0 - dx, fy + fh - dy, static_cast<float>(blitOffset), static_cast<float>((sx + 0) * us), static_cast<float>((sy + h) * vs));
|
||||
t->vertexUV(fx + fw - dx, fy + fh - dy, static_cast<float>(blitOffset), static_cast<float>((sx + w) * us), static_cast<float>((sy + h) * vs));
|
||||
t->vertexUV(fx + fw - dx, fy + 0 - dy, static_cast<float>(blitOffset), static_cast<float>((sx + w) * us), static_cast<float>((sy + 0) * vs));
|
||||
t->vertexUV(fx + 0 - dx, fy + 0 - dy, static_cast<float>(blitOffset), static_cast<float>((sx + 0) * us), static_cast<float>((sy + 0) * vs));
|
||||
t->end();
|
||||
}
|
||||
|
|
@ -15,5 +15,6 @@ public:
|
|||
GuiComponent(); // 4J added
|
||||
void drawCenteredString(Font *font, const wstring& str, int x, int y, int color);
|
||||
void drawString(Font *font, const wstring& str, int x, int y, int color);
|
||||
void drawStringLiteral(Font* font, const wstring& str, int x, int y, int color);
|
||||
void blit(int x, int y, int sx, int sy, int w, int h);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1499,7 +1499,7 @@ void Minecraft::run_middle()
|
|||
}
|
||||
|
||||
// Utility keys always work regardless of KBM active state
|
||||
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE) && !ui.IsTutorialVisible(i) && !ui.GetMenuDisplayed(i))
|
||||
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE) && !ui.GetMenuDisplayed(i))
|
||||
{
|
||||
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_PAUSEMENU;
|
||||
app.DebugPrintf("PAUSE PRESSED (keyboard) - ipad = %d\n",i);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "..\Minecraft.World\AABB.h"
|
||||
#include "..\Minecraft.World\Pos.h"
|
||||
#include "..\Minecraft.World\SharedConstants.h"
|
||||
#include "..\Minecraft.World\ChatPacket.h"
|
||||
#include "..\Minecraft.World\StringHelpers.h"
|
||||
#include "..\Minecraft.World\Socket.h"
|
||||
#include "..\Minecraft.World\Achievements.h"
|
||||
#include "..\Minecraft.World\net.minecraft.h"
|
||||
|
|
@ -607,38 +609,26 @@ void PlayerConnection::handleSetCarriedItem(shared_ptr<SetCarriedItemPacket> pac
|
|||
|
||||
void PlayerConnection::handleChat(shared_ptr<ChatPacket> packet)
|
||||
{
|
||||
// 4J - TODO
|
||||
#if 0
|
||||
wstring message = packet->message;
|
||||
if (packet->m_stringArgs.empty()) return;
|
||||
wstring message = trimString(packet->m_stringArgs[0]);
|
||||
if (message.length() > SharedConstants::maxChatLength)
|
||||
{
|
||||
disconnect(L"Chat message too long");
|
||||
disconnect(DisconnectPacket::eDisconnect_None); // or a specific reason
|
||||
return;
|
||||
}
|
||||
message = message.trim();
|
||||
for (int i = 0; i < message.length(); i++)
|
||||
{
|
||||
if (SharedConstants.acceptableLetters.indexOf(message.charAt(i)) < 0 && (int) message.charAt(i) < 32)
|
||||
{
|
||||
disconnect(L"Illegal characters in chat");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (message.startsWith("/"))
|
||||
// Optional: validate characters (acceptableLetters)
|
||||
if (message.length() > 0 && message[0] == L'/')
|
||||
{
|
||||
handleCommand(message);
|
||||
} else {
|
||||
message = "<" + player.name + "> " + message;
|
||||
logger.info(message);
|
||||
server.players.broadcastAll(new ChatPacket(message));
|
||||
return;
|
||||
}
|
||||
wstring formatted = L"<" + player->name + L"> " + message;
|
||||
server->getPlayers()->broadcastAll(shared_ptr<ChatPacket>(new ChatPacket(formatted)));
|
||||
chatSpamTickCount += SharedConstants::TICKS_PER_SECOND;
|
||||
if (chatSpamTickCount > SharedConstants::TICKS_PER_SECOND * 10)
|
||||
{
|
||||
disconnect("disconnect.spam");
|
||||
disconnect(DisconnectPacket::eDisconnect_None); // spam
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlayerConnection::handleCommand(const wstring& message)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "Screen.h"
|
||||
#include "Button.h"
|
||||
#include "ChatScreen.h"
|
||||
#include "GuiParticles.h"
|
||||
#include "Tesselator.h"
|
||||
#include "Textures.h"
|
||||
|
|
@ -42,13 +43,32 @@ void Screen::keyPressed(wchar_t eventCharacter, int eventKey)
|
|||
|
||||
wstring Screen::getClipboard()
|
||||
{
|
||||
// 4J - removed
|
||||
return NULL;
|
||||
#ifdef _WINDOWS64
|
||||
if (!OpenClipboard(NULL)) return wstring();
|
||||
HANDLE h = GetClipboardData(CF_UNICODETEXT);
|
||||
wstring out;
|
||||
if (h)
|
||||
{
|
||||
const wchar_t *p = reinterpret_cast<const wchar_t*>(GlobalLock(h));
|
||||
if (p) { out = p; GlobalUnlock(h); }
|
||||
}
|
||||
CloseClipboard();
|
||||
return out;
|
||||
#else
|
||||
return wstring();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::setClipboard(const wstring& str)
|
||||
{
|
||||
// 4J - removed
|
||||
#ifdef _WINDOWS64
|
||||
if (!OpenClipboard(NULL)) return;
|
||||
EmptyClipboard();
|
||||
size_t len = (str.length() + 1) * sizeof(wchar_t);
|
||||
HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, len);
|
||||
if (h) { memcpy(GlobalLock(h), str.c_str(), len); GlobalUnlock(h); SetClipboardData(CF_UNICODETEXT, h); }
|
||||
CloseClipboard();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::mouseClicked(int x, int y, int buttonNum)
|
||||
|
|
@ -121,34 +141,88 @@ void Screen::updateEvents()
|
|||
}
|
||||
}
|
||||
|
||||
// Poll keyboard events
|
||||
// Only drain WM_CHAR when this screen wants text input (e.g. ChatScreen); otherwise we'd steal keys from the game
|
||||
if (dynamic_cast<ChatScreen*>(this) != nullptr)
|
||||
{
|
||||
wchar_t ch;
|
||||
while (g_KBMInput.ConsumeChar(ch))
|
||||
{
|
||||
if (ch >= 0x20)
|
||||
keyPressed(ch, -1);
|
||||
else if (ch == 0x08)
|
||||
keyPressed(0, Keyboard::KEY_BACK);
|
||||
else if (ch == 0x0D)
|
||||
keyPressed(0, Keyboard::KEY_RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
// Arrow key repeat: deliver on first press (when key down and last==0) and while held (throttled)
|
||||
static DWORD s_arrowLastTime[2] = { 0, 0 };
|
||||
static bool s_arrowFirstRepeat[2] = { false, false };
|
||||
const DWORD ARROW_REPEAT_DELAY_MS = 250;
|
||||
const DWORD ARROW_REPEAT_INTERVAL_MS = 50;
|
||||
DWORD now = GetTickCount();
|
||||
|
||||
// Poll keyboard events (special keys that may not come through WM_CHAR, e.g. Escape, arrows)
|
||||
for (int vk = 0; vk < 256; vk++)
|
||||
{
|
||||
if (g_KBMInput.IsKeyPressed(vk))
|
||||
bool deliver = g_KBMInput.IsKeyPressed(vk);
|
||||
if (vk == VK_LEFT || vk == VK_RIGHT)
|
||||
{
|
||||
// Map Windows virtual key to the Keyboard constants used by Screen::keyPressed
|
||||
int mappedKey = -1;
|
||||
wchar_t ch = 0;
|
||||
if (vk == VK_ESCAPE) mappedKey = Keyboard::KEY_ESCAPE;
|
||||
else if (vk == VK_RETURN) mappedKey = Keyboard::KEY_RETURN;
|
||||
else if (vk == VK_BACK) mappedKey = Keyboard::KEY_BACK;
|
||||
else if (vk == VK_UP) mappedKey = Keyboard::KEY_UP;
|
||||
else if (vk == VK_DOWN) mappedKey = Keyboard::KEY_DOWN;
|
||||
else if (vk == VK_LEFT) mappedKey = Keyboard::KEY_LEFT;
|
||||
else if (vk == VK_RIGHT) mappedKey = Keyboard::KEY_RIGHT;
|
||||
else if (vk == VK_LSHIFT || vk == VK_RSHIFT) mappedKey = Keyboard::KEY_LSHIFT;
|
||||
else if (vk == VK_TAB) mappedKey = Keyboard::KEY_TAB;
|
||||
else if (vk >= 'A' && vk <= 'Z')
|
||||
int idx = (vk == VK_LEFT) ? 0 : 1;
|
||||
if (!g_KBMInput.IsKeyDown(vk))
|
||||
{
|
||||
ch = (wchar_t)(vk - 'A' + L'a');
|
||||
if (g_KBMInput.IsKeyDown(VK_LSHIFT) || g_KBMInput.IsKeyDown(VK_RSHIFT)) ch = (wchar_t)vk;
|
||||
s_arrowLastTime[idx] = 0;
|
||||
s_arrowFirstRepeat[idx] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD last = s_arrowLastTime[idx];
|
||||
if (last == 0)
|
||||
deliver = true;
|
||||
else if (!deliver)
|
||||
{
|
||||
DWORD interval = s_arrowFirstRepeat[idx] ? ARROW_REPEAT_INTERVAL_MS : ARROW_REPEAT_DELAY_MS;
|
||||
if ((now - last) >= interval)
|
||||
{
|
||||
deliver = true;
|
||||
s_arrowFirstRepeat[idx] = true;
|
||||
}
|
||||
}
|
||||
if (deliver)
|
||||
s_arrowLastTime[idx] = now;
|
||||
}
|
||||
else if (vk >= '0' && vk <= '9') ch = (wchar_t)vk;
|
||||
else if (vk == VK_SPACE) ch = L' ';
|
||||
|
||||
if (mappedKey != -1) keyPressed(ch, mappedKey);
|
||||
else if (ch != 0) keyPressed(ch, -1);
|
||||
}
|
||||
// Escape: deliver when key is down so we don't miss it (IsKeyPressed can be one frame late)
|
||||
if (vk == VK_ESCAPE && g_KBMInput.IsKeyDown(VK_ESCAPE))
|
||||
deliver = true;
|
||||
if (!deliver) continue;
|
||||
|
||||
if (dynamic_cast<ChatScreen*>(this) != nullptr &&
|
||||
(vk >= 'A' && vk <= 'Z' || vk >= '0' && vk <= '9' || vk == VK_SPACE || vk == VK_RETURN || vk == VK_BACK))
|
||||
continue;
|
||||
// Map to Screen::keyPressed
|
||||
int mappedKey = -1;
|
||||
wchar_t ch = 0;
|
||||
if (vk == VK_ESCAPE) mappedKey = Keyboard::KEY_ESCAPE;
|
||||
else if (vk == VK_RETURN) mappedKey = Keyboard::KEY_RETURN;
|
||||
else if (vk == VK_BACK) mappedKey = Keyboard::KEY_BACK;
|
||||
else if (vk == VK_UP) mappedKey = Keyboard::KEY_UP;
|
||||
else if (vk == VK_DOWN) mappedKey = Keyboard::KEY_DOWN;
|
||||
else if (vk == VK_LEFT) mappedKey = Keyboard::KEY_LEFT;
|
||||
else if (vk == VK_RIGHT) mappedKey = Keyboard::KEY_RIGHT;
|
||||
else if (vk == VK_LSHIFT || vk == VK_RSHIFT) mappedKey = Keyboard::KEY_LSHIFT;
|
||||
else if (vk == VK_TAB) mappedKey = Keyboard::KEY_TAB;
|
||||
else if (vk >= 'A' && vk <= 'Z')
|
||||
{
|
||||
ch = static_cast<wchar_t>(vk - 'A' + L'a');
|
||||
if (g_KBMInput.IsKeyDown(VK_LSHIFT) || g_KBMInput.IsKeyDown(VK_RSHIFT)) ch = static_cast<wchar_t>(vk);
|
||||
}
|
||||
else if (vk >= '0' && vk <= '9') ch = static_cast<wchar_t>(vk);
|
||||
else if (vk == VK_SPACE) ch = L' ';
|
||||
|
||||
if (mappedKey != -1) keyPressed(ch, mappedKey);
|
||||
else if (ch != 0) keyPressed(ch, -1);
|
||||
}
|
||||
#else
|
||||
/* 4J - TODO
|
||||
|
|
@ -232,10 +306,10 @@ void Screen::renderDirtBackground(int vo)
|
|||
float s = 32;
|
||||
t->begin();
|
||||
t->color(0x404040);
|
||||
t->vertexUV((float)(0), (float)( height), (float)( 0), (float)( 0), (float)( height / s + vo));
|
||||
t->vertexUV((float)(width), (float)( height), (float)( 0), (float)( width / s), (float)( height / s + vo));
|
||||
t->vertexUV((float)(width), (float)( 0), (float)( 0), (float)( width / s), (float)( 0 + vo));
|
||||
t->vertexUV((float)(0), (float)( 0), (float)( 0), (float)( 0), (float)( 0 + vo));
|
||||
t->vertexUV(static_cast<float>(0), static_cast<float>(height), static_cast<float>(0), static_cast<float>(0), static_cast<float>(height / s + vo));
|
||||
t->vertexUV(static_cast<float>(width), static_cast<float>(height), static_cast<float>(0), static_cast<float>(width / s), static_cast<float>(height / s + vo));
|
||||
t->vertexUV(static_cast<float>(width), static_cast<float>(0), static_cast<float>(0), static_cast<float>(width / s), static_cast<float>(0 + vo));
|
||||
t->vertexUV(static_cast<float>(0), static_cast<float>(0), static_cast<float>(0), static_cast<float>(0), static_cast<float>(0 + vo));
|
||||
t->end();
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,9 +36,12 @@ protected:
|
|||
virtual void mouseReleased(int x, int y, int buttonNum);
|
||||
virtual void buttonClicked(Button *button);
|
||||
public:
|
||||
virtual void init(Minecraft *minecraft, int width, int height);
|
||||
virtual void init(Minecraft *minecraft, int width, int height);
|
||||
virtual void setSize(int width, int height);
|
||||
virtual void init();
|
||||
virtual void handlePasteRequest() {}
|
||||
virtual void handleHistoryUp() {}
|
||||
virtual void handleHistoryDown() {}
|
||||
virtual void updateEvents();
|
||||
virtual void mouseEvent();
|
||||
virtual void keyboardEvent();
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ void KeyboardMouseInput::Tick()
|
|||
}
|
||||
}
|
||||
|
||||
if ((m_mouseGrabbed || m_cursorHiddenForUI) && g_hWnd)
|
||||
if ((m_mouseGrabbed || m_cursorHiddenForUI) && m_windowFocused && g_hWnd)
|
||||
{
|
||||
RECT rc;
|
||||
GetClientRect(g_hWnd, &rc);
|
||||
|
|
@ -257,8 +257,8 @@ bool KeyboardMouseInput::IsMouseButtonReleased(int button) const
|
|||
|
||||
void KeyboardMouseInput::ConsumeMouseDelta(float &dx, float &dy)
|
||||
{
|
||||
dx = (float)m_mouseDeltaAccumX;
|
||||
dy = (float)m_mouseDeltaAccumY;
|
||||
dx = static_cast<float>(m_mouseDeltaAccumX);
|
||||
dy = static_cast<float>(m_mouseDeltaAccumY);
|
||||
m_mouseDeltaAccumX = 0;
|
||||
m_mouseDeltaAccumY = 0;
|
||||
}
|
||||
|
|
@ -375,12 +375,12 @@ float KeyboardMouseInput::GetMoveY() const
|
|||
|
||||
float KeyboardMouseInput::GetLookX(float sensitivity) const
|
||||
{
|
||||
return (float)m_mouseDeltaX * sensitivity;
|
||||
return static_cast<float>(m_mouseDeltaX) * sensitivity;
|
||||
}
|
||||
|
||||
float KeyboardMouseInput::GetLookY(float sensitivity) const
|
||||
{
|
||||
return (float)(-m_mouseDeltaY) * sensitivity;
|
||||
return static_cast<float>(-m_mouseDeltaY) * sensitivity;
|
||||
}
|
||||
|
||||
void KeyboardMouseInput::OnChar(wchar_t c)
|
||||
|
|
|
|||
|
|
@ -143,4 +143,4 @@ private:
|
|||
|
||||
extern KeyboardMouseInput g_KBMInput;
|
||||
|
||||
#endif // _WINDOWS64
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
#include "..\..\Minecraft.World\net.minecraft.world.level.tile.h"
|
||||
|
||||
#include "..\ClientConnection.h"
|
||||
#include "..\Minecraft.h"
|
||||
#include "..\ChatScreen.h"
|
||||
#include "KeyboardMouseInput.h"
|
||||
#include "..\User.h"
|
||||
#include "..\..\Minecraft.World\Socket.h"
|
||||
#include "..\..\Minecraft.World\ThreadName.h"
|
||||
|
|
@ -572,14 +575,28 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
case WM_CHAR:
|
||||
// Buffer typed characters so UIScene_Keyboard can dispatch them to the Iggy Flash player
|
||||
if (wParam >= 0x20 || wParam == 0x08 || wParam == 0x0D) // printable chars + backspace + enter
|
||||
g_KBMInput.OnChar((wchar_t)wParam);
|
||||
g_KBMInput.OnChar(static_cast<wchar_t>(wParam));
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
{
|
||||
int vk = (int)wParam;
|
||||
if (lParam & 0x40000000) break; // ignore auto-repeat
|
||||
int vk = static_cast<int>(wParam);
|
||||
if ((lParam & 0x40000000) && vk != VK_LEFT && vk != VK_RIGHT && vk != VK_BACK)
|
||||
break;
|
||||
#ifdef _WINDOWS64
|
||||
Minecraft* pm = Minecraft::GetInstance();
|
||||
ChatScreen* chat = pm && pm->screen ? dynamic_cast<ChatScreen*>(pm->screen) : nullptr;
|
||||
if (chat)
|
||||
{
|
||||
if (vk == 'V' && (GetKeyState(VK_CONTROL) & 0x8000))
|
||||
{ chat->handlePasteRequest(); break; }
|
||||
if ((vk == VK_UP || vk == VK_DOWN) && !(lParam & 0x40000000))
|
||||
{ if (vk == VK_UP) chat->handleHistoryUp(); else chat->handleHistoryDown(); break; }
|
||||
if (vk >= '1' && vk <= '9') // Prevent hotkey conflicts
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (vk == VK_SHIFT)
|
||||
vk = (MapVirtualKey((lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK_EX) == VK_RSHIFT) ? VK_RSHIFT : VK_LSHIFT;
|
||||
else if (vk == VK_CONTROL)
|
||||
|
|
@ -587,12 +604,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
else if (vk == VK_MENU)
|
||||
vk = (lParam & (1 << 24)) ? VK_RMENU : VK_LMENU;
|
||||
g_KBMInput.OnKeyDown(vk);
|
||||
break;
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
{
|
||||
int vk = (int)wParam;
|
||||
int vk = static_cast<int>(wParam);
|
||||
if (vk == VK_SHIFT)
|
||||
vk = (MapVirtualKey((lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK_EX) == VK_RSHIFT) ? VK_RSHIFT : VK_LSHIFT;
|
||||
else if (vk == VK_CONTROL)
|
||||
|
|
@ -1612,6 +1629,14 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||
}
|
||||
}
|
||||
|
||||
// Open chat
|
||||
if (g_KBMInput.IsKeyPressed('T') && app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL)
|
||||
{
|
||||
g_KBMInput.ClearCharBuffer();
|
||||
pMinecraft->setScreen(new ChatScreen());
|
||||
SetFocus(g_hWnd);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// has the game defined profile data been changed (by a profile load)
|
||||
if(app.uiGameDefinedDataChangedBitmask!=0)
|
||||
|
|
|
|||
|
|
@ -463,6 +463,23 @@ BOOL ConsoleSaveFileOriginal::closeHandle( FileEntry *file )
|
|||
void ConsoleSaveFileOriginal::finalizeWrite()
|
||||
{
|
||||
LockSaveAccess();
|
||||
|
||||
// Ensure buffer is large enough for the full file including header table.
|
||||
// New file entries (e.g. from RegionFile creation) increase GetFileSize()
|
||||
// without triggering MoveDataBeyond, so the committed pages may be short.
|
||||
DWORD currentHeapSize = pagesCommitted * CSF_PAGE_SIZE;
|
||||
DWORD desiredSize = header.GetFileSize();
|
||||
if( desiredSize > currentHeapSize )
|
||||
{
|
||||
unsigned int pagesRequired = ( desiredSize + (CSF_PAGE_SIZE - 1 ) ) / CSF_PAGE_SIZE;
|
||||
void *pvRet = VirtualAlloc(pvHeap, pagesRequired * CSF_PAGE_SIZE, COMMIT_ALLOCATION, PAGE_READWRITE);
|
||||
if( pvRet == NULL )
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
pagesCommitted = pagesRequired;
|
||||
}
|
||||
|
||||
header.WriteHeader( pvSaveMem );
|
||||
ReleaseSaveAccess();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,10 +187,10 @@ void StemTile::spawnResources(Level *level, int x, int y, int z, int data, float
|
|||
Item *seed = NULL;
|
||||
if (fruit == Tile::pumpkin) seed = Item::seeds_pumpkin;
|
||||
if (fruit == Tile::melon) seed = Item::seeds_melon;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
popResource(level, x, y, z, shared_ptr<ItemInstance>(new ItemInstance(seed)));
|
||||
}
|
||||
if (seed != NULL)
|
||||
{
|
||||
popResource(level, x, y, z, shared_ptr<ItemInstance>(new ItemInstance(seed)));
|
||||
}
|
||||
}
|
||||
|
||||
int StemTile::getResource(int data, Random *random, int playerBonusLevel)
|
||||
|
|
|
|||
|
|
@ -115,6 +115,11 @@ Icon *WoolTileItem::getIcon(int itemAuxValue)
|
|||
#ifndef _CONTENT_PACKAGE
|
||||
if(Tile::tiles[id])
|
||||
{
|
||||
if (id == Tile::stained_glass_Id || id == Tile::stained_glass_pane_Id)
|
||||
{
|
||||
return Tile::tiles[id]->getTexture(2, itemAuxValue);
|
||||
}
|
||||
|
||||
return Tile::tiles[id]->getTexture(2, ColoredTile::getTileDataForItemAuxValue(itemAuxValue));
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ Basic LAN multiplayer is available on the Windows build
|
|||
- Game connections use TCP port `25565` by default
|
||||
- LAN discovery uses UDP port `25566`
|
||||
|
||||
This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP/)
|
||||
This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP)
|
||||
|
||||
### Launch Arguments
|
||||
|
||||
|
|
@ -65,6 +65,7 @@ The headless server also reads and writes `server.properties` in the working dir
|
|||
- **Sneak / Fly (Down)**: `Shift` (Hold)
|
||||
- **Sprint**: `Ctrl` (Hold) or Double-tap `W`
|
||||
- **Inventory**: `E`
|
||||
- **Chat**: `T`
|
||||
- **Drop Item**: `Q`
|
||||
- **Crafting**: `C` Use `Q` and `E` to move through tabs (cycles Left/Right)
|
||||
- **Toggle View (FPS/TPS)**: `F5`
|
||||
|
|
|
|||
Loading…
Reference in a new issue