Merge branch 'master' into psp

This commit is contained in:
VoxelTek 2025-07-13 22:28:27 +10:00 committed by GitHub
commit 4974d3a62c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 152 additions and 44 deletions

View File

@ -180,6 +180,7 @@ IsleApp::IsleApp()
m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20; m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20;
m_transitionType = MxTransitionManager::e_mosaic; m_transitionType = MxTransitionManager::e_mosaic;
m_cursorSensitivity = 4; m_cursorSensitivity = 4;
m_touchScheme = LegoInputManager::e_gamepad;
} }
// FUNCTION: ISLE 0x4011a0 // FUNCTION: ISLE 0x4011a0
@ -658,7 +659,12 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
float y = SDL_clamp(event->tfinger.y, 0, 1) * g_targetHeight; float y = SDL_clamp(event->tfinger.y, 0, 1) * g_targetHeight;
if (InputManager()) { if (InputManager()) {
InputManager()->QueueEvent(c_notificationMouseMove, LegoEventNotificationParam::c_lButtonState, x, y, 0); MxU8 modifier = LegoEventNotificationParam::c_lButtonState;
if (InputManager()->HandleTouchEvent(event, g_isle->GetTouchScheme())) {
modifier |= LegoEventNotificationParam::c_motionHandled;
}
InputManager()->QueueEvent(c_notificationMouseMove, modifier, x, y, 0);
} }
g_lastMouseX = x; g_lastMouseX = x;
@ -699,6 +705,7 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
float y = SDL_clamp(event->tfinger.y, 0, 1) * g_targetHeight; float y = SDL_clamp(event->tfinger.y, 0, 1) * g_targetHeight;
if (InputManager()) { if (InputManager()) {
InputManager()->HandleTouchEvent(event, g_isle->GetTouchScheme());
InputManager()->QueueEvent(c_notificationButtonDown, LegoEventNotificationParam::c_lButtonState, x, y, 0); InputManager()->QueueEvent(c_notificationButtonDown, LegoEventNotificationParam::c_lButtonState, x, y, 0);
} }
@ -746,6 +753,7 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
float y = SDL_clamp(event->tfinger.y, 0, 1) * g_targetHeight; float y = SDL_clamp(event->tfinger.y, 0, 1) * g_targetHeight;
if (InputManager()) { if (InputManager()) {
InputManager()->HandleTouchEvent(event, g_isle->GetTouchScheme());
InputManager()->QueueEvent(c_notificationButtonUp, 0, x, y, 0); InputManager()->QueueEvent(c_notificationButtonUp, 0, x, y, 0);
} }
break; break;
@ -1043,6 +1051,7 @@ bool IsleApp::LoadConfig()
iniparser_set(dict, "isle:Max LOD", buf); iniparser_set(dict, "isle:Max LOD", buf);
iniparser_set(dict, "isle:Max Allowed Extras", SDL_itoa(m_maxAllowedExtras, buf, 10)); iniparser_set(dict, "isle:Max Allowed Extras", SDL_itoa(m_maxAllowedExtras, buf, 10));
iniparser_set(dict, "isle:Transition Type", SDL_itoa(m_transitionType, buf, 10)); iniparser_set(dict, "isle:Transition Type", SDL_itoa(m_transitionType, buf, 10));
iniparser_set(dict, "isle:Touch Scheme", SDL_itoa(m_touchScheme, buf, 10));
#ifdef EXTENSIONS #ifdef EXTENSIONS
iniparser_set(dict, "extensions", NULL); iniparser_set(dict, "extensions", NULL);
@ -1113,6 +1122,7 @@ bool IsleApp::LoadConfig()
m_maxAllowedExtras = iniparser_getint(dict, "isle:Max Allowed Extras", m_maxAllowedExtras); m_maxAllowedExtras = iniparser_getint(dict, "isle:Max Allowed Extras", m_maxAllowedExtras);
m_transitionType = m_transitionType =
(MxTransitionManager::TransitionType) iniparser_getint(dict, "isle:Transition Type", m_transitionType); (MxTransitionManager::TransitionType) iniparser_getint(dict, "isle:Transition Type", m_transitionType);
m_touchScheme = (LegoInputManager::TouchScheme) iniparser_getint(dict, "isle:Touch Scheme", m_touchScheme);
const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL); const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL);
if (deviceId != NULL) { if (deviceId != NULL) {
@ -1128,13 +1138,19 @@ bool IsleApp::LoadConfig()
strcpy(m_savePath, savePath); strcpy(m_savePath, savePath);
#ifdef EXTENSIONS #ifdef EXTENSIONS
std::vector<const char*> keys; for (const char* key : Extensions::availableExtensions) {
keys.resize(iniparser_getsecnkeys(dict, "extensions"));
iniparser_getseckeys(dict, "extensions", keys.data());
for (const char* key : keys) {
if (iniparser_getboolean(dict, key, 0)) { if (iniparser_getboolean(dict, key, 0)) {
Extensions::Enable(key); std::vector<const char*> extensionKeys;
const char* section = SDL_strchr(key, ':') + 1;
extensionKeys.resize(iniparser_getsecnkeys(dict, section));
iniparser_getseckeys(dict, section, extensionKeys.data());
std::map<std::string, std::string> extensionDict;
for (const char* key : extensionKeys) {
extensionDict[key] = iniparser_getstring(dict, key, NULL);
}
Extensions::Enable(key, std::move(extensionDict));
} }
} }
#endif #endif

View File

@ -3,6 +3,7 @@
#include "cursor.h" #include "cursor.h"
#include "lego1_export.h" #include "lego1_export.h"
#include "legoinputmanager.h"
#include "legoutils.h" #include "legoutils.h"
#include "mxtransitionmanager.h" #include "mxtransitionmanager.h"
#include "mxtypes.h" #include "mxtypes.h"
@ -53,6 +54,7 @@ class IsleApp {
MxS32 GetDrawCursor() { return m_drawCursor; } MxS32 GetDrawCursor() { return m_drawCursor; }
MxS32 GetGameStarted() { return m_gameStarted; } MxS32 GetGameStarted() { return m_gameStarted; }
MxFloat GetCursorSensitivity() { return m_cursorSensitivity; } MxFloat GetCursorSensitivity() { return m_cursorSensitivity; }
LegoInputManager::TouchScheme GetTouchScheme() { return m_touchScheme; }
void SetWindowActive(MxS32 p_windowActive) { m_windowActive = p_windowActive; } void SetWindowActive(MxS32 p_windowActive) { m_windowActive = p_windowActive; }
void SetGameStarted(MxS32 p_gameStarted) { m_gameStarted = p_gameStarted; } void SetGameStarted(MxS32 p_gameStarted) { m_gameStarted = p_gameStarted; }
@ -102,6 +104,7 @@ class IsleApp {
MxFloat m_maxLod; MxFloat m_maxLod;
MxU32 m_maxAllowedExtras; MxU32 m_maxAllowedExtras;
MxTransitionManager::TransitionType m_transitionType; MxTransitionManager::TransitionType m_transitionType;
LegoInputManager::TouchScheme m_touchScheme;
}; };
extern IsleApp* g_isle; extern IsleApp* g_isle;

View File

@ -18,6 +18,7 @@ class LegoEventNotificationParam : public MxNotificationParam {
c_rButtonState = 2, c_rButtonState = 2,
c_modKey1 = 4, c_modKey1 = 4,
c_modKey2 = 8, c_modKey2 = 8,
c_motionHandled = 16,
}; };
// FUNCTION: LEGO1 0x10028690 // FUNCTION: LEGO1 0x10028690

View File

@ -18,6 +18,8 @@
#include <windows.h> #include <windows.h>
#endif #endif
#include <map>
class LegoCameraController; class LegoCameraController;
class LegoControlManager; class LegoControlManager;
class LegoWorld; class LegoWorld;
@ -89,6 +91,12 @@ class LegoInputManager : public MxPresenter {
c_upOrDown = c_up | c_down c_upOrDown = c_up | c_down
}; };
enum TouchScheme {
e_mouse = 0,
e_arrowKeys,
e_gamepad,
};
LegoInputManager(); LegoInputManager();
~LegoInputManager() override; ~LegoInputManager() override;
@ -144,6 +152,7 @@ class LegoInputManager : public MxPresenter {
void GetKeyboardState(); void GetKeyboardState();
MxResult GetNavigationKeyStates(MxU32& p_keyFlags); MxResult GetNavigationKeyStates(MxU32& p_keyFlags);
MxResult GetNavigationTouchStates(MxU32& p_keyFlags); MxResult GetNavigationTouchStates(MxU32& p_keyFlags);
LEGO1_EXPORT MxBool HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme);
// SYNTHETIC: LEGO1 0x1005b8d0 // SYNTHETIC: LEGO1 0x1005b8d0
// LegoInputManager::`scalar deleting destructor' // LegoInputManager::`scalar deleting destructor'
@ -171,6 +180,10 @@ class LegoInputManager : public MxPresenter {
MxBool m_useJoystick; // 0x334 MxBool m_useJoystick; // 0x334
MxBool m_unk0x335; // 0x335 MxBool m_unk0x335; // 0x335
MxBool m_unk0x336; // 0x336 MxBool m_unk0x336; // 0x336
std::map<SDL_FingerID, SDL_FPoint> m_touchOrigins;
std::map<SDL_FingerID, MxU32> m_touchFlags;
std::map<SDL_FingerID, Uint64> m_touchLastMotion;
}; };
// TEMPLATE: LEGO1 0x10028850 // TEMPLATE: LEGO1 0x10028850

View File

@ -41,6 +41,10 @@ MxResult LegoCameraController::Create()
// FUNCTION: BETA10 0x10067852 // FUNCTION: BETA10 0x10067852
MxLong LegoCameraController::Notify(MxParam& p_param) MxLong LegoCameraController::Notify(MxParam& p_param)
{ {
if (((LegoEventNotificationParam&) p_param).GetModifier() & LegoEventNotificationParam::c_motionHandled) {
return SUCCESS;
}
switch (((MxNotificationParam&) p_param).GetNotification()) { switch (((MxNotificationParam&) p_param).GetNotification()) {
case c_notificationDragEnd: { case c_notificationDragEnd: {
if (((((LegoEventNotificationParam&) p_param).GetModifier()) & LegoEventNotificationParam::c_lButtonState) == if (((((LegoEventNotificationParam&) p_param).GetModifier()) & LegoEventNotificationParam::c_lButtonState) ==

View File

@ -528,42 +528,91 @@ void LegoInputManager::EnableInputProcessing()
MxResult LegoInputManager::GetNavigationTouchStates(MxU32& p_keyStates) MxResult LegoInputManager::GetNavigationTouchStates(MxU32& p_keyStates)
{ {
int count; for (auto& [fingerID, touchFlags] : m_touchFlags) {
SDL_TouchID* touchDevices = SDL_GetTouchDevices(&count); p_keyStates |= touchFlags;
if (touchDevices) { // We need to clear these as they are not meant to be persistent in e_gamepad mode.
auto applyFingerNavigation = [&p_keyStates](SDL_TouchID p_touchId) { if (m_touchOrigins.count(fingerID) && SDL_GetTicks() - m_touchLastMotion[fingerID] > 5) {
int count; touchFlags &= ~c_left;
SDL_Finger** fingers = SDL_GetTouchFingers(p_touchId, &count); touchFlags &= ~c_right;
if (fingers) {
for (int i = 0; i < count; i++) {
if (fingers[i]->y > 3.0 / 4.0) {
if (fingers[i]->x < 1.0 / 3.0) {
p_keyStates |= c_left;
}
else if (fingers[i]->x > 2.0 / 3.0) {
p_keyStates |= c_right;
}
else {
p_keyStates |= c_down;
}
}
else {
p_keyStates |= c_up;
}
}
SDL_free(fingers);
}
};
for (int i = 0; i < count; i++) {
applyFingerNavigation(touchDevices[i]);
} }
SDL_free(touchDevices);
} }
return SUCCESS; return SUCCESS;
} }
MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme)
{
const SDL_TouchFingerEvent& event = p_event->tfinger;
switch (p_touchScheme) {
case e_mouse:
// Handled in LegoCameraController
return FALSE;
case e_arrowKeys:
switch (p_event->type) {
case SDL_EVENT_FINGER_UP:
m_touchFlags.erase(event.fingerID);
break;
case SDL_EVENT_FINGER_DOWN:
case SDL_EVENT_FINGER_MOTION:
m_touchFlags[event.fingerID] = 0;
if (event.y > 3.0 / 4.0) {
if (event.x < 1.0 / 3.0) {
m_touchFlags[event.fingerID] |= c_left;
}
else if (event.x > 2.0 / 3.0) {
m_touchFlags[event.fingerID] |= c_right;
}
else {
m_touchFlags[event.fingerID] |= c_down;
}
}
else {
m_touchFlags[event.fingerID] |= c_up;
}
break;
}
break;
case e_gamepad:
switch (p_event->type) {
case SDL_EVENT_FINGER_DOWN:
m_touchOrigins[event.fingerID] = {event.x, event.y};
break;
case SDL_EVENT_FINGER_UP:
m_touchOrigins.erase(event.fingerID);
m_touchFlags.erase(event.fingerID);
break;
case SDL_EVENT_FINGER_MOTION:
if (m_touchOrigins.count(event.fingerID)) {
m_touchFlags[event.fingerID] = 0;
m_touchLastMotion[event.fingerID] = SDL_GetTicks();
const float deltaY = event.y - m_touchOrigins[event.fingerID].y;
const float activationThreshold = 0.05f;
if (SDL_fabsf(deltaY) > activationThreshold) {
if (deltaY > 0) {
m_touchFlags[event.fingerID] |= c_down;
}
else if (deltaY < 0) {
m_touchFlags[event.fingerID] |= c_up;
}
}
const float deltaX = event.dx;
if (deltaX > 0) {
m_touchFlags[event.fingerID] |= c_right;
}
else if (deltaX < 0) {
m_touchFlags[event.fingerID] |= c_left;
}
}
break;
}
break;
}
return TRUE;
}

View File

@ -3,6 +3,7 @@
#include "lego1_export.h" #include "lego1_export.h"
#include <functional> #include <functional>
#include <map>
#include <optional> #include <optional>
#include <string> #include <string>
@ -10,7 +11,7 @@ namespace Extensions
{ {
constexpr const char* availableExtensions[] = {"extensions:texture loader"}; constexpr const char* availableExtensions[] = {"extensions:texture loader"};
LEGO1_EXPORT void Enable(const char* p_key); LEGO1_EXPORT void Enable(const char* p_key, std::map<std::string, std::string> p_options);
template <typename T> template <typename T>
struct Extension { struct Extension {

View File

@ -3,16 +3,24 @@
#include "extensions/extensions.h" #include "extensions/extensions.h"
#include "legotextureinfo.h" #include "legotextureinfo.h"
#include <array>
#include <map>
namespace Extensions namespace Extensions
{ {
class TextureLoader { class TextureLoader {
public: public:
static void Initialize();
static bool PatchTexture(LegoTextureInfo* p_textureInfo); static bool PatchTexture(LegoTextureInfo* p_textureInfo);
static std::map<std::string, std::string> options;
static bool enabled; static bool enabled;
private: static constexpr std::array<std::pair<std::string_view, std::string_view>, 1> defaults = {
static constexpr const char* texturePath = "/textures/"; {{"texture loader:texture path", "/textures/"}}
};
private:
static SDL_Surface* FindTexture(const char* p_name); static SDL_Surface* FindTexture(const char* p_name);
}; };

View File

@ -4,12 +4,14 @@
#include <SDL3/SDL_log.h> #include <SDL3/SDL_log.h>
void Extensions::Enable(const char* p_key) void Extensions::Enable(const char* p_key, std::map<std::string, std::string> p_options)
{ {
for (const char* key : availableExtensions) { for (const char* key : availableExtensions) {
if (!SDL_strcasecmp(p_key, key)) { if (!SDL_strcasecmp(p_key, key)) {
if (!SDL_strcasecmp(p_key, "extensions:texture loader")) { if (!SDL_strcasecmp(p_key, "extensions:texture loader")) {
TextureLoader::options = std::move(p_options);
TextureLoader::enabled = true; TextureLoader::enabled = true;
TextureLoader::Initialize();
} }
SDL_Log("Enabled extension: %s", p_key); SDL_Log("Enabled extension: %s", p_key);

View File

@ -2,8 +2,18 @@
using namespace Extensions; using namespace Extensions;
std::map<std::string, std::string> TextureLoader::options;
bool TextureLoader::enabled = false; bool TextureLoader::enabled = false;
void TextureLoader::Initialize()
{
for (const auto& option : defaults) {
if (!options.count(option.first.data())) {
options[option.first.data()] = option.second;
}
}
}
bool TextureLoader::PatchTexture(LegoTextureInfo* p_textureInfo) bool TextureLoader::PatchTexture(LegoTextureInfo* p_textureInfo)
{ {
SDL_Surface* surface = FindTexture(p_textureInfo->m_name); SDL_Surface* surface = FindTexture(p_textureInfo->m_name);
@ -88,6 +98,7 @@ bool TextureLoader::PatchTexture(LegoTextureInfo* p_textureInfo)
SDL_Surface* TextureLoader::FindTexture(const char* p_name) SDL_Surface* TextureLoader::FindTexture(const char* p_name)
{ {
SDL_Surface* surface; SDL_Surface* surface;
const char* texturePath = options["texture loader:texture path"].c_str();
MxString path = MxString(MxOmni::GetHD()) + texturePath + p_name + ".bmp"; MxString path = MxString(MxOmni::GetHD()) + texturePath + p_name + ".bmp";
path.MapPathToFilesystem(); path.MapPathToFilesystem();