Adapt Android mobile controls and native client UI
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
# port_logic — mirror of the 40250 client logic (extension/src/port/<Lib>/<File>.{h,cpp}).
|
||||
# No godot-cpp dependency: libmtgodot links it, and it also builds on its own (top-level
|
||||
# -DMTGODOT_BUILD_EXTENSION=OFF -DMTGODOT_BUILD_PORT=ON) for targets without an extension build.
|
||||
# This library and port_platform are built directly for the SDL/Vulkan client and port tests.
|
||||
# See docs/PORT-PLAN.md batch 2A.
|
||||
|
||||
file(GLOB_RECURSE MT_PORT_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||
@@ -31,8 +30,7 @@ target_include_directories(port_logic PUBLIC ${MT_PORT_SHIMS})
|
||||
# Libraries 40250 links that are vendored as-is: <lzo/lzo1x.h> (EterBase/lzo.h), <cryptopp/*>
|
||||
# (EterBase/cipher.h), <Python-2.7/*> (ScriptLib).
|
||||
target_link_libraries(port_logic PUBLIC mt3p::minilzo mt3p::cryptopp)
|
||||
# common/Win32Crt.cpp converts ANSI code pages with mt_codepage. extension/CMakeLists.txt adds it for
|
||||
# mtnet; the port-only build (script/port_gate.sh, native_render) never reads that file.
|
||||
# common/Win32Crt.cpp converts ANSI code pages with mt_codepage.
|
||||
if(NOT TARGET mt_codepage)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../codepage ${CMAKE_CURRENT_BINARY_DIR}/../codepage)
|
||||
endif()
|
||||
@@ -241,8 +239,7 @@ if(BUILD_TESTING AND CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
|
||||
# Locale packs in the original format (script/build_zh_locale.py packs locale/zh with it).
|
||||
add_executable(eterpack_pack ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/eterpack_pack.cpp)
|
||||
target_link_libraries(eterpack_pack PRIVATE port_platform)
|
||||
# 2V2-e: the same fake server as a process, for the Godot-driven render run
|
||||
# (script/python_game_render_test.sh).
|
||||
# The same fake server as a process, for native rendering tests.
|
||||
add_executable(port_fake_login_server ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/port_fake_login_server_main.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../tests/port_login_flow_server.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../net/classic/classic_cipher.cpp)
|
||||
|
||||
@@ -33,6 +33,32 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#if !defined(_WIN32)
|
||||
#include <dirent.h> // PORT: resolve separately cased .eix/.epk names on case-sensitive mobile filesystems
|
||||
#include <strings.h> // PORT: strcasecmp for the on-disk pack name lookup
|
||||
|
||||
// PORT: 40250 ships pairs such as ETC.eix and Etc.epk. Windows opens both through the
|
||||
// same stem; Android must locate each file using its actual on-disk spelling.
|
||||
static std::string ResolvePackFileName(const std::string& requested)
|
||||
{
|
||||
const std::string::size_type slash = requested.find_last_of('/');
|
||||
const std::string folder = slash == std::string::npos ? "." : requested.substr(0, slash);
|
||||
const std::string name = requested.substr(slash == std::string::npos ? 0 : slash + 1);
|
||||
DIR* dir = opendir(folder.c_str());
|
||||
if (!dir) return requested;
|
||||
std::string result = requested;
|
||||
while (dirent* entry = readdir(dir))
|
||||
{
|
||||
if (strcasecmp(entry->d_name, name.c_str()) == 0)
|
||||
{
|
||||
result = folder + "/" + entry->d_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CMakePackLog::SetFileName(const char* c_szFileName)
|
||||
{
|
||||
@@ -257,6 +283,18 @@ bool CEterPack::Create(CEterFileDict& rkFileDict, const char * dbname, const cha
|
||||
|
||||
m_stDataFileName = dbname;
|
||||
m_stDataFileName += ".epk";
|
||||
// PORT: the two extensions may have different capitalization in the original Client/pack.
|
||||
#if !defined(_WIN32)
|
||||
if (bReadOnly)
|
||||
{
|
||||
const std::string indexName = ResolvePackFileName(m_indexFileName);
|
||||
if (indexName.size() < sizeof(m_indexFileName))
|
||||
{
|
||||
strcpy(m_indexFileName, indexName.c_str());
|
||||
}
|
||||
m_stDataFileName = ResolvePackFileName(m_stDataFileName);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_bReadOnly = bReadOnly;
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "StdAfx.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include "../EterBase/CRC32.h"
|
||||
#include "PythonWindow.h"
|
||||
#include "PythonSlotWindow.h"
|
||||
@@ -1392,7 +1394,7 @@ namespace UI
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CExpandedImageBox::CExpandedImageBox(PyObject * ppyObject) : CImageBox(ppyObject)
|
||||
CExpandedImageBox::CExpandedImageBox(PyObject * ppyObject) : CImageBox(ppyObject), m_bAspectFill(false)
|
||||
{
|
||||
}
|
||||
CExpandedImageBox::~CExpandedImageBox()
|
||||
@@ -1400,6 +1402,73 @@ namespace UI
|
||||
OnDestroyInstance();
|
||||
}
|
||||
|
||||
void CExpandedImageBox::SetAspectFill(bool bEnable)
|
||||
{
|
||||
m_bAspectFill = bEnable;
|
||||
}
|
||||
|
||||
bool CExpandedImageBox::IsAutoAspectFillBackground() const
|
||||
{
|
||||
const char* c_szFileName = "";
|
||||
if (m_pImageInstance && m_pImageInstance->GetGraphicImagePointer())
|
||||
c_szFileName = m_pImageInstance->GetGraphicImagePointer()->GetFileName();
|
||||
if (!c_szFileName)
|
||||
c_szFileName = "";
|
||||
|
||||
std::string lowerFile = c_szFileName;
|
||||
std::transform(lowerFile.begin(), lowerFile.end(), lowerFile.begin(), ::tolower);
|
||||
|
||||
const std::string& name = m_strName;
|
||||
std::string parentName = m_pParent ? m_pParent->GetName() : "";
|
||||
|
||||
// 1. Server list and login backgrounds (LoginWindow bg1 and bg2)
|
||||
if (name == "bg1" || name == "bg2")
|
||||
{
|
||||
if (parentName == "LoginWindow")
|
||||
return true;
|
||||
if (lowerFile.find("serverlist") != std::string::npos || lowerFile.find("login") != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. Character selection & creation backgrounds (BackGround with select.sub / select.jpg)
|
||||
if (name == "BackGround")
|
||||
{
|
||||
if (parentName == "SelectCharacterWindow" || parentName == "CreateCharacterWindow")
|
||||
return true;
|
||||
if (lowerFile.find("select.sub") != std::string::npos ||
|
||||
lowerFile.find("select.jpg") != std::string::npos ||
|
||||
lowerFile.find("select.png") != std::string::npos ||
|
||||
lowerFile.find("ui/select") != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. Loading screen backgrounds (BackGround with Line_Pattern.tga or uiloading/*.sub)
|
||||
if (name == "BackGround")
|
||||
{
|
||||
if (parentName == "LoadingWindow")
|
||||
return true;
|
||||
if (lowerFile.find("uiloading") != std::string::npos ||
|
||||
lowerFile.find("line_pattern") != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback check by file name directly if element name wasn't set or is generic
|
||||
if (lowerFile.find("serverlist.sub") != std::string::npos ||
|
||||
lowerFile.find("serverlist.jpg") != std::string::npos ||
|
||||
lowerFile.find("uiloading/") != std::string::npos ||
|
||||
lowerFile.find("uiloading\\") != std::string::npos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CExpandedImageBox::IsAspectFill() const
|
||||
{
|
||||
return m_bAspectFill || IsAutoAspectFillBackground();
|
||||
}
|
||||
|
||||
void CExpandedImageBox::OnCreateInstance()
|
||||
{
|
||||
OnDestroyInstance();
|
||||
@@ -1420,9 +1489,56 @@ namespace UI
|
||||
if (!m_pImageInstance)
|
||||
return;
|
||||
|
||||
if (IsAspectFill())
|
||||
{
|
||||
long screenWidth = UI::CWindowManager::Instance().GetScreenWidth();
|
||||
long screenHeight = UI::CWindowManager::Instance().GetScreenHeight();
|
||||
int imgWidth = GetWidth();
|
||||
int imgHeight = GetHeight();
|
||||
if (screenWidth > 0 && screenHeight > 0 && imgWidth > 0 && imgHeight > 0)
|
||||
{
|
||||
float sx = float(screenWidth) / float(imgWidth);
|
||||
float sy = float(screenHeight) / float(imgHeight);
|
||||
float s = std::max(sx, sy);
|
||||
((CGraphicExpandedImageInstance*)m_pImageInstance)->SetScale(s, s);
|
||||
CWindow::SetSize(screenWidth, screenHeight);
|
||||
float posX = (float(screenWidth) - float(imgWidth) * s) * 0.5f;
|
||||
float posY = (float(screenHeight) - float(imgHeight) * s) * 0.5f;
|
||||
m_pImageInstance->SetPosition(posX, posY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
((CGraphicExpandedImageInstance*)m_pImageInstance)->SetScale(fx, fy);
|
||||
CWindow::SetSize(long(float(GetWidth())*fx), long(float(GetHeight())*fy));
|
||||
}
|
||||
|
||||
void CExpandedImageBox::OnChangePosition()
|
||||
{
|
||||
if (!m_pImageInstance)
|
||||
return;
|
||||
|
||||
if (IsAspectFill())
|
||||
{
|
||||
long screenWidth = UI::CWindowManager::Instance().GetScreenWidth();
|
||||
long screenHeight = UI::CWindowManager::Instance().GetScreenHeight();
|
||||
int imgWidth = GetWidth();
|
||||
int imgHeight = GetHeight();
|
||||
if (screenWidth > 0 && screenHeight > 0 && imgWidth > 0 && imgHeight > 0)
|
||||
{
|
||||
float sx = float(screenWidth) / float(imgWidth);
|
||||
float sy = float(screenHeight) / float(imgHeight);
|
||||
float s = std::max(sx, sy);
|
||||
float posX = (float(screenWidth) - float(imgWidth) * s) * 0.5f;
|
||||
float posY = (float(screenHeight) - float(imgHeight) * s) * 0.5f;
|
||||
m_pImageInstance->SetPosition(posX, posY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CImageBox::OnChangePosition();
|
||||
}
|
||||
|
||||
void CExpandedImageBox::SetOrigin(float fx, float fy)
|
||||
{
|
||||
if (!m_pImageInstance)
|
||||
@@ -1458,6 +1574,24 @@ namespace UI
|
||||
if (!m_pImageInstance)
|
||||
return;
|
||||
|
||||
if (IsAspectFill())
|
||||
{
|
||||
long screenWidth = UI::CWindowManager::Instance().GetScreenWidth();
|
||||
long screenHeight = UI::CWindowManager::Instance().GetScreenHeight();
|
||||
int imgWidth = GetWidth();
|
||||
int imgHeight = GetHeight();
|
||||
if (screenWidth > 0 && screenHeight > 0 && imgWidth > 0 && imgHeight > 0)
|
||||
{
|
||||
float sx = float(screenWidth) / float(imgWidth);
|
||||
float sy = float(screenHeight) / float(imgHeight);
|
||||
float s = std::max(sx, sy);
|
||||
((CGraphicExpandedImageInstance*)m_pImageInstance)->SetScale(s, s);
|
||||
float posX = (float(screenWidth) - float(imgWidth) * s) * 0.5f;
|
||||
float posY = (float(screenHeight) - float(imgHeight) * s) * 0.5f;
|
||||
m_pImageInstance->SetPosition(posX, posY);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsShow())
|
||||
m_pImageInstance->Render();
|
||||
}
|
||||
|
||||
@@ -386,6 +386,8 @@ namespace UI
|
||||
void SetRotation(float fRotation);
|
||||
void SetRenderingRect(float fLeft, float fTop, float fRight, float fBottom);
|
||||
void SetRenderingMode(int iMode);
|
||||
void SetAspectFill(bool bEnable);
|
||||
bool IsAspectFill() const;
|
||||
|
||||
protected:
|
||||
void OnCreateInstance();
|
||||
@@ -393,8 +395,14 @@ namespace UI
|
||||
|
||||
virtual void OnUpdate();
|
||||
virtual void OnRender();
|
||||
virtual void OnChangePosition();
|
||||
|
||||
BOOL OnIsType(DWORD dwType);
|
||||
|
||||
bool IsAutoAspectFillBackground() const;
|
||||
|
||||
protected:
|
||||
bool m_bAspectFill;
|
||||
};
|
||||
class CAniImageBox : public CWindow
|
||||
{
|
||||
|
||||
@@ -2012,6 +2012,27 @@ PyObject * wndImageSetScale(PyObject * poSelf, PyObject * poArgs)
|
||||
|
||||
return Py_BuildNone();
|
||||
}
|
||||
PyObject * wndImageSetAspectFill(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
UI::CWindow * pWindow;
|
||||
if (!PyTuple_GetWindow(poArgs, 0, &pWindow))
|
||||
return Py_BuildException();
|
||||
|
||||
bool bEnable = true;
|
||||
if (PyTuple_Size(poArgs) > 1)
|
||||
{
|
||||
int iEnable;
|
||||
if (PyTuple_GetInteger(poArgs, 1, &iEnable))
|
||||
bEnable = (iEnable != 0);
|
||||
}
|
||||
|
||||
if (pWindow->IsType(UI::CExpandedImageBox::Type()))
|
||||
{
|
||||
((UI::CExpandedImageBox*)pWindow)->SetAspectFill(bEnable);
|
||||
}
|
||||
|
||||
return Py_BuildNone();
|
||||
}
|
||||
PyObject * wndImageSetOrigin(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
UI::CWindow * pWindow;
|
||||
@@ -2454,6 +2475,7 @@ void initwndMgr()
|
||||
{ "GetHeight", wndImageGetHeight, METH_VARARGS },
|
||||
// ExpandedImageBox
|
||||
{ "SetScale", wndImageSetScale, METH_VARARGS },
|
||||
{ "SetAspectFill", wndImageSetAspectFill, METH_VARARGS },
|
||||
{ "SetOrigin", wndImageSetOrigin, METH_VARARGS },
|
||||
{ "SetRotation", wndImageSetRotation, METH_VARARGS },
|
||||
{ "SetRenderingRect", wndImageSetRenderingRect, METH_VARARGS },
|
||||
|
||||
Reference in New Issue
Block a user