Fixes, mouse AUX buttons, joystick detect menu

This commit is contained in:
eray orçunus 2020-09-30 20:02:47 +03:00
parent 8235fe08d1
commit 595421da39
14 changed files with 456 additions and 60 deletions

View File

@ -161,7 +161,7 @@ cMusicManager::DisplayRadioStationName()
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetFontStyle(FONT_HEADING); CFont::SetFontStyle(FONT_HEADING);
CFont::SetCentreOn(); CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_STRETCH_X(640.0f)); CFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));
CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation); CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation);

View File

@ -854,6 +854,13 @@ CMenuManager::Draw()
str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);
break; break;
default: default:
#ifdef CUSTOM_FRONTEND_OPTIONS
if (aScreens[m_nCurrScreen].m_aEntries[0].m_SaveSlot == SAVESLOT_CFO) {
FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[0].m_TargetMenu];
str = (wchar*)option.leftText;
}
else
#endif
str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName); str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);
break; break;
} }
@ -3443,6 +3450,7 @@ CMenuManager::LoadSettings()
CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Read(fileHandle, m_PrefsSkinFile, 256);
CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1);
CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1); CFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1);
/*
#ifdef CUSTOM_FRONTEND_OPTIONS #ifdef CUSTOM_FRONTEND_OPTIONS
for (int i = 0; i < numCustomFrontendOptions; i++) { for (int i = 0; i < numCustomFrontendOptions; i++) {
FrontendOption& option = customFrontendOptions[i]; FrontendOption& option = customFrontendOptions[i];
@ -3456,6 +3464,7 @@ CMenuManager::LoadSettings()
CFileMgr::Read(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1); CFileMgr::Read(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1);
CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading; CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading;
#endif #endif
*/
} }
} }
@ -3546,6 +3555,7 @@ CMenuManager::SaveSettings()
CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256); CFileMgr::Write(fileHandle, m_PrefsSkinFile, 256);
CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1); CFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1);
CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1); CFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1);
/*
#ifdef CUSTOM_FRONTEND_OPTIONS #ifdef CUSTOM_FRONTEND_OPTIONS
for (int i = 0; i < numCustomFrontendOptions; i++) { for (int i = 0; i < numCustomFrontendOptions; i++) {
FrontendOption &option = customFrontendOptions[i]; FrontendOption &option = customFrontendOptions[i];
@ -3557,6 +3567,7 @@ CMenuManager::SaveSettings()
#ifdef NO_ISLAND_LOADING #ifdef NO_ISLAND_LOADING
CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1); CFileMgr::Write(fileHandle, (char *)&CMenuManager::m_PrefsIslandLoading, 1);
#endif #endif
*/
} }
CFileMgr::CloseFile(fileHandle); CFileMgr::CloseFile(fileHandle);
@ -3880,7 +3891,10 @@ CMenuManager::Process(void)
MouseButtonJustClicked = 4; MouseButtonJustClicked = 4;
else if (CPad::GetPad(0)->GetMouseWheelDownJustUp()) else if (CPad::GetPad(0)->GetMouseWheelDownJustUp())
MouseButtonJustClicked = 5; MouseButtonJustClicked = 5;
// TODO two more buttons else if (CPad::GetPad(0)->GetMouseX1JustUp())
MouseButtonJustClicked = 6;
else if (CPad::GetPad(0)->GetMouseX2JustUp())
MouseButtonJustClicked = 7;
JoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown(); JoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown();
@ -5106,7 +5120,8 @@ CMenuManager::ProcessButtonPresses(void)
*option.value = option.lastSavedValue = option.displayedValue; *option.value = option.lastSavedValue = option.displayedValue;
} else if (option.type == FEOPTION_DYNAMIC) { } else if (option.type == FEOPTION_DYNAMIC) {
option.buttonPressFunc(FEOPTION_ACTION_SELECT); if (option.buttonPressFunc)
option.buttonPressFunc(FEOPTION_ACTION_SELECT);
} else if (option.type == FEOPTION_REDIRECT) { } else if (option.type == FEOPTION_REDIRECT) {
ChangeScreen(option.to, option.option, true, option.fadeIn); ChangeScreen(option.to, option.option, true, option.fadeIn);
} else if (option.type == FEOPTION_GOBACK) { } else if (option.type == FEOPTION_GOBACK) {
@ -5349,7 +5364,7 @@ CMenuManager::ProcessButtonPresses(void)
option.changeFunc(option.displayedValue); option.changeFunc(option.displayedValue);
*option.value = option.lastSavedValue = option.displayedValue; *option.value = option.lastSavedValue = option.displayedValue;
} }
} else if (option.type == FEOPTION_DYNAMIC) { } else if (option.type == FEOPTION_DYNAMIC && option.buttonPressFunc) {
option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT); option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT);
} }
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);

View File

@ -297,7 +297,6 @@ bool CGame::InitialiseOnceAfterRW(void)
#ifdef CUSTOM_FRONTEND_OPTIONS #ifdef CUSTOM_FRONTEND_OPTIONS
if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) { if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) {
CustomFrontendOptionsPopulate(); CustomFrontendOptionsPopulate();
FrontEndMenuManager.LoadSettings();
} }
#endif #endif
return true; return true;

View File

@ -277,6 +277,8 @@ public:
bool GetMiddleMouseJustUp() { return !!(!NewMouseControllerState.MMB && OldMouseControllerState.MMB); } bool GetMiddleMouseJustUp() { return !!(!NewMouseControllerState.MMB && OldMouseControllerState.MMB); }
bool GetMouseWheelUpJustUp() { return !!(!NewMouseControllerState.WHEELUP && OldMouseControllerState.WHEELUP); } bool GetMouseWheelUpJustUp() { return !!(!NewMouseControllerState.WHEELUP && OldMouseControllerState.WHEELUP); }
bool GetMouseWheelDownJustUp() { return !!(!NewMouseControllerState.WHEELDN && OldMouseControllerState.WHEELDN); } bool GetMouseWheelDownJustUp() { return !!(!NewMouseControllerState.WHEELDN && OldMouseControllerState.WHEELDN); }
bool GetMouseX1JustUp() { return !!(!NewMouseControllerState.MXB1 && OldMouseControllerState.MXB1); }
bool GetMouseX2JustUp() { return !!(!NewMouseControllerState.MXB2 && OldMouseControllerState.MXB2); }
bool GetLeftMouse() { return NewMouseControllerState.LMB; } bool GetLeftMouse() { return NewMouseControllerState.LMB; }
bool GetRightMouse() { return NewMouseControllerState.RMB; } bool GetRightMouse() { return NewMouseControllerState.RMB; }

View File

@ -226,6 +226,9 @@ enum Config {
#if !defined(RW_GL3) && defined(_WIN32) #if !defined(RW_GL3) && defined(_WIN32)
#define XINPUT #define XINPUT
#endif #endif
#if defined(RW_GL3) && !defined(__SWITCH__) // TODO
#define DONT_TRUST_RECOGNIZED_JOYSTICKS // Then we'll only rely on GLFW gamepad DB, and want user to enter Cpntroller->Detect joysticks if his joystick isn't on that list.
#endif
#define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m #define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m
#define KANGAROO_CHEAT #define KANGAROO_CHEAT
#define ALLCARSHELI_CHEAT #define ALLCARSHELI_CHEAT

View File

@ -32,6 +32,7 @@
#include "MBlur.h" #include "MBlur.h"
#include "postfx.h" #include "postfx.h"
#include "custompipes.h" #include "custompipes.h"
#include "ControllerConfig.h"
#ifndef _WIN32 #ifndef _WIN32
#include "assert.h" #include "assert.h"
@ -195,6 +196,7 @@ wchar* MultiSamplingDraw(bool *disabled, bool userHovering) {
return unicodeTemp; return unicodeTemp;
} }
} }
char* multisamplingKey = "MultiSampling";
#endif #endif
#ifdef MORE_LANGUAGES #ifdef MORE_LANGUAGES
@ -247,6 +249,8 @@ void FreeCamChange(int8 displayedValue)
TheCamera.bFreeCam = !!displayedValue; TheCamera.bFreeCam = !!displayedValue;
FrontEndMenuManager.SaveSettings(); FrontEndMenuManager.SaveSettings();
} }
const wchar* freeCamText = (wchar*)L"FREE CAM";
char* freeCamKey = "FreeCam";
#endif #endif
#ifdef CUTSCENE_BORDERS_SWITCH #ifdef CUTSCENE_BORDERS_SWITCH
@ -255,6 +259,7 @@ void BorderModeChange(int8 displayedValue)
CMenuManager::m_PrefsCutsceneBorders = !!displayedValue; CMenuManager::m_PrefsCutsceneBorders = !!displayedValue;
FrontEndMenuManager.SaveSettings(); FrontEndMenuManager.SaveSettings();
} }
char* cutsceneBordersKey = "CutsceneBorders";
#endif #endif
#ifdef PS2_ALPHA_TEST #ifdef PS2_ALPHA_TEST
@ -263,11 +268,52 @@ void PS2AlphaTestChange(int8 displayedValue)
gPS2alphaTest = !!displayedValue; gPS2alphaTest = !!displayedValue;
FrontEndMenuManager.SaveSettings(); FrontEndMenuManager.SaveSettings();
} }
char* ps2alphaKey = "PS2AlphaTest";
#endif #endif
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
const wchar* detectJoystickText = (wchar*)L"Detect Joystick";
const wchar* detectJoystickExplanation = (wchar*)L"Press any key on your preferred joystick that you would like to use on the game.";
const wchar* detectedJoystickText = (wchar*)L"Detected Joystick";
wchar selectedJoystickUnicode[128];
wchar* DetectJoystickDraw(bool* disabled, bool userHovering) {
int numButtons;
int found = -1;
const char *joyname;
if (userHovering) {
for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {
if (joyname = glfwGetJoystickName(i)) {
const uint8* buttons = glfwGetJoystickButtons(i, &numButtons);
for (int j = 0; j < numButtons; j++) {
if (buttons[j]) {
strcpy(gSelectedJoystickName, joyname);
found = i;
break;
}
}
if (found != -1)
break;
}
}
if (found != -1 && PSGLOBAL(joy1id) != found) {
if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found)
PSGLOBAL(joy2id) = PSGLOBAL(joy1id);
else
PSGLOBAL(joy2id) = -1;
PSGLOBAL(joy1id) = found;
}
}
AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode);
return selectedJoystickUnicode;
}
#endif
// Important: Make sure to read the warnings/informations in frontendoption.h!! // Important: Make sure to read the warnings/informations in frontendoption.h!!
// For texts: Either use TheText.Get, or use wcsdup(wchar version of strdup) // If you won't use GXT entry as text, you may want to declare them globally, to not alloc them on each reload. (static declared texts has some problems on Linux etc.)
void void
CustomFrontendOptionsPopulate(void) CustomFrontendOptionsPopulate(void)
{ {
@ -342,14 +388,14 @@ CustomFrontendOptionsPopulate(void)
#ifdef MULTISAMPLING #ifdef MULTISAMPLING
SWITCH_TO_GRAPHICS_MENU SWITCH_TO_GRAPHICS_MENU
FrontendOptionAddDynamic(TheText.Get("FED_AAS"), MultiSamplingDraw, (int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, MultiSamplingButtonPress, MultiSamplingGoBack, true); FrontendOptionAddDynamic(TheText.Get("FED_AAS"), MultiSamplingDraw, (int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, MultiSamplingButtonPress, MultiSamplingGoBack, multisamplingKey);
#endif #endif
CLONE_OPTION(TheText.Get("FED_TRA"), MENUACTION_TRAILS, nil, nil); CLONE_OPTION(TheText.Get("FED_TRA"), MENUACTION_TRAILS, nil, nil);
#ifdef PS2_ALPHA_TEST #ifdef PS2_ALPHA_TEST
SWITCH_TO_GRAPHICS_MENU SWITCH_TO_GRAPHICS_MENU
FrontendOptionAddSelect(TheText.Get("FEM_2PR"), off_on, 2, (int8*)&gPS2alphaTest, false, PS2AlphaTestChange, nil, true); FrontendOptionAddSelect(TheText.Get("FEM_2PR"), off_on, 2, (int8*)&gPS2alphaTest, false, PS2AlphaTestChange, nil, ps2alphaKey);
#endif #endif
ADD_RESTORE_DEFAULTS(RestoreDefGraphics) ADD_RESTORE_DEFAULTS(RestoreDefGraphics)
@ -365,13 +411,12 @@ CustomFrontendOptionsPopulate(void)
#ifdef CUTSCENE_BORDERS_SWITCH #ifdef CUTSCENE_BORDERS_SWITCH
SWITCH_TO_DISPLAY_MENU SWITCH_TO_DISPLAY_MENU
FrontendOptionAddSelect(TheText.Get("FEM_CSB"), off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil, true); FrontendOptionAddSelect(TheText.Get("FEM_CSB"), off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil, cutsceneBordersKey);
#endif #endif
#ifdef FREE_CAM #ifdef FREE_CAM
SWITCH_TO_DISPLAY_MENU SWITCH_TO_DISPLAY_MENU
static const wchar* text = (wchar*)wcsdup(L"FREE CAM"); FrontendOptionAddSelect(freeCamText, off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, freeCamKey);
FrontendOptionAddSelect(text, off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, true);
#endif #endif
CLONE_OPTION(TheText.Get("FED_SUB"), MENUACTION_SUBTITLES, nil, nil); CLONE_OPTION(TheText.Get("FED_SUB"), MENUACTION_SUBTITLES, nil, nil);
@ -388,7 +433,21 @@ CustomFrontendOptionsPopulate(void)
#endif #endif
ADD_RESTORE_DEFAULTS(RestoreDefDisplay) ADD_RESTORE_DEFAULTS(RestoreDefDisplay)
ADD_BACK ADD_BACK
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
int detectJoystickMenu = FrontendScreenAdd("FET_CON", MENUSPRITE_MAINMENU, MENUPAGE_CONTROLLER_PC, 50, 60, 20,
FONT_BANK, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, false);
FrontendOptionSetCursor(detectJoystickMenu, 0);
FrontendOptionAddBuiltinAction(detectJoystickExplanation, MENUACTION_LABEL, nil, nil);
FrontendOptionAddDynamic(detectedJoystickText, DetectJoystickDraw, nil, nil, nil);
FrontendOptionAddBackButton(TheText.Get("FEDS_TB"));
FrontendOptionSetCursor(MENUPAGE_CONTROLLER_PC, 2);
FrontendOptionAddRedirect(detectJoystickText, detectJoystickMenu, 1);
#endif
} }
#endif #endif

View File

@ -89,7 +89,7 @@ void tbDisplay()
CFont::SetScale(0.48f, 1.12f); CFont::SetScale(0.48f, 1.12f);
CFont::SetCentreOff(); CFont::SetCentreOff();
CFont::SetJustifyOff(); CFont::SetJustifyOff();
CFont::SetWrapx(640.0f); CFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));
CFont::SetRightJustifyOff(); CFont::SetRightJustifyOff();
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetFontStyle(FONT_BANK); CFont::SetFontStyle(FONT_BANK);

View File

@ -213,10 +213,10 @@ void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPre
TextCopy(option.leftText, leftText); TextCopy(option.leftText, leftText);
option.screenOptionOrder = screenOptionOrder; option.screenOptionOrder = screenOptionOrder;
option.returnPrevPageFunc = returnPrevPageFunc; option.returnPrevPageFunc = returnPrevPageFunc;
option.save = false; option.save = nil;
} }
void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save) void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName)
{ {
int8 screenOptionOrder = RegisterNewOption(); int8 screenOptionOrder = RegisterNewOption();
@ -229,14 +229,14 @@ void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, in
option.value = var; option.value = var;
option.displayedValue = *var; option.displayedValue = *var;
option.lastSavedValue = *var; option.lastSavedValue = *var;
option.save = save; option.save = saveName;
option.onlyApplyOnEnter = onlyApplyOnEnter; option.onlyApplyOnEnter = onlyApplyOnEnter;
option.changeFunc = changeFunc; option.changeFunc = changeFunc;
option.screenOptionOrder = screenOptionOrder; option.screenOptionOrder = screenOptionOrder;
option.returnPrevPageFunc = returnPrevPageFunc; option.returnPrevPageFunc = returnPrevPageFunc;
} }
void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save) void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName)
{ {
int8 screenOptionOrder = RegisterNewOption(); int8 screenOptionOrder = RegisterNewOption();
@ -246,7 +246,7 @@ void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc drawFunc, int8 *va
option.buttonPressFunc = buttonPressFunc; option.buttonPressFunc = buttonPressFunc;
TextCopy(option.leftText, leftText); TextCopy(option.leftText, leftText);
option.value = var; option.value = var;
option.save = save; option.save = saveName;
option.screenOptionOrder = screenOptionOrder; option.screenOptionOrder = screenOptionOrder;
option.returnPrevPageFunc = returnPrevPageFunc; option.returnPrevPageFunc = returnPrevPageFunc;
} }
@ -263,7 +263,7 @@ void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption, b
TextCopy(option.leftText, text); TextCopy(option.leftText, text);
option.screenOptionOrder = screenOptionOrder; option.screenOptionOrder = screenOptionOrder;
option.returnPrevPageFunc = nil; option.returnPrevPageFunc = nil;
option.save = false; option.save = nil;
} }
void FrontendOptionAddBackButton(const wchar* text, bool fadeIn) void FrontendOptionAddBackButton(const wchar* text, bool fadeIn)
@ -276,7 +276,7 @@ void FrontendOptionAddBackButton(const wchar* text, bool fadeIn)
TextCopy(option.leftText, text); TextCopy(option.leftText, text);
option.screenOptionOrder = screenOptionOrder; option.screenOptionOrder = screenOptionOrder;
option.returnPrevPageFunc = nil; option.returnPrevPageFunc = nil;
option.save = false; option.save = nil;
} }
uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight, uint8 FrontendScreenAdd(const char* gxtKey, eMenuSprites sprite, int prevPage, int columnWidth, int headerHeight, int lineHeight,

View File

@ -10,7 +10,7 @@
// About texts: // About texts:
// All text parameters accept wchar(including hardcoded wchar* and TheText.Get) // All text parameters accept wchar(including hardcoded wchar* and TheText.Get)
// except FrontendScreenAdd(it's char[8] by the design of Frontend). // except FrontendScreenAdd(it's char[8] GXT key by the design of Frontend).
// All texts reload if custom options reloaded too, which includes language changes and via live reload feature in debug menu! // All texts reload if custom options reloaded too, which includes language changes and via live reload feature in debug menu!
// Execute direction: // Execute direction:
@ -26,7 +26,7 @@
// //
// Static/select: You allocate the variable, pass it to function and game sets it from user input among the strings given to function, // Static/select: You allocate the variable, pass it to function and game sets it from user input among the strings given to function,
// then you can handle ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately) // then you can handle ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately)
// and ReturnPrevPageFunc optionally. You can store the option in gta3.set if you pass true to corresponding parameter. // and ReturnPrevPageFunc optionally. You can store the option in an INI file if you pass the key(as a char array) to corresponding parameter.
// //
// Dynamic: Passing variable to function is only needed if you want to store it, otherwise you should do // Dynamic: Passing variable to function is only needed if you want to store it, otherwise you should do
// all the operations with ButtonPressFunc, this includes allocating the variable. // all the operations with ButtonPressFunc, this includes allocating the variable.
@ -95,7 +95,7 @@ struct FrontendOption
ReturnPrevPageFunc returnPrevPageFunc; ReturnPrevPageFunc returnPrevPageFunc;
int8* value; int8* value;
int8 displayedValue; // only if onlyApplyOnEnter enabled for now int8 displayedValue; // only if onlyApplyOnEnter enabled for now
bool save; char* save;
int32 ogOptionId; // for replacements, see overwrite parameter of SetCursor int32 ogOptionId; // for replacements, see overwrite parameter of SetCursor
union { union {
@ -151,10 +151,10 @@ uint8 GetNumberOfMenuOptions(int screen);
void FrontendOptionSetCursor(int screen, int8 option, bool overwrite = false); void FrontendOptionSetCursor(int screen, int8 option, bool overwrite = false);
// var is optional in AddDynamic, you can enable save parameter if you pass one, otherwise pass nil/0 // var is optional in AddDynamic, enables you to save them in an INI file(also needs passing char array to saveName param. obv), otherwise pass nil/0
void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc); void FrontendOptionAddBuiltinAction(const wchar* leftText, int action, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc);
void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save = false); void FrontendOptionAddSelect(const wchar* leftText, const wchar** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName = nil);
void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, bool save = false); void FrontendOptionAddDynamic(const wchar* leftText, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, ReturnPrevPageFunc returnPrevPageFunc, char* saveName = nil);
void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption = 0, bool fadeIn = true); void FrontendOptionAddRedirect(const wchar* text, int to, int8 selectedOption = 0, bool fadeIn = true);
void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true); void FrontendOptionAddBackButton(const wchar* text, bool fadeIn = true);

314
src/extras/ini_parser.hpp Normal file
View File

@ -0,0 +1,314 @@
/*
* Copyright (c) 2013-2015 Denilson das Mercês Amorim <dma_2012@hotmail.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
#ifndef LINB_INI_PARSER_HPP
#define LINB_INI_PARSER_HPP
/*
* STL-like INI Container
*/
#include <string> // for std::string
#include <map> // for std::map
#include <cstdio> // for std::FILE
#include <algorithm> // for std::find_if
#include <functional> // for std::function
namespace linb
{
template<
class CharT = char, /* Not compatible with other type here, since we're using C streams */
class StringType = std::basic_string<CharT>,
class KeyContainer = std::map<StringType, StringType>,
class SectionContainer = std::map<StringType, KeyContainer>
> class basic_ini
{
public:
typedef CharT char_type;
typedef StringType string_type;
typedef KeyContainer key_container;
typedef SectionContainer section_container;
// Typedef container values types
typedef typename section_container::value_type value_type;
typedef typename section_container::key_type key_type;
typedef typename section_container::mapped_type mapped_type;
// Typedef common types
typedef typename section_container::size_type size_type;
typedef typename section_container::difference_type difference_type;
// Typedef iterators
typedef typename section_container::iterator iterator;
typedef typename section_container::const_iterator const_iterator;
typedef typename section_container::reverse_iterator reverse_iterator;
typedef typename section_container::const_reverse_iterator const_reverse_iterator;
// typedef References and pointers
typedef typename section_container::reference reference;
typedef typename section_container::const_reference const_reference;
typedef typename section_container::pointer pointer;
typedef typename section_container::const_pointer const_pointer;
private:
section_container data;
public:
basic_ini()
{ }
basic_ini(const char_type* filename)
{ this->read_file(filename); }
/* Iterator methods */
iterator begin()
{ return data.begin(); }
const_iterator begin() const
{ return data.begin(); }
iterator end()
{ return data.end(); }
const_iterator end() const
{ return data.end(); }
const_iterator cbegin() const
{ return data.cbegin(); }
const_iterator cend() const
{ return data.cend(); }
/* Reverse iterator methods */
reverse_iterator rbegin()
{ return data.rbegin(); }
const_reverse_iterator rbegin() const
{ return data.rbegin(); }
reverse_iterator rend()
{ return data.rend(); }
const_reverse_iterator rend() const
{ return data.rend(); }
const_reverse_iterator crbegin() const
{ return data.crbegin(); }
const_reverse_iterator crend() const
{ return data.crend(); }
/* Acessing index methods */
mapped_type& operator[](const string_type& sect)
{ return data[sect]; }
mapped_type& operator[](string_type&& sect)
{ return data[std::forward<string_type>(sect)]; }
mapped_type& at( const string_type& sect)
{ return data.at(sect); }
const mapped_type& at(const string_type& sect) const
{ return data.at(sect); }
/* Capacity information */
bool empty() const
{ return data.empty(); }
size_type size() const
{ return data.size(); }
size_type max_size() const
{ return data.max_size(); }
/* Modifiers */
void clear()
{ return data.clear(); }
/* Lookup */
size_type count(const string_type& sect)
{ return data.count(sect); }
iterator find(const string_type& sect)
{ return data.find(sect); }
/* Gets a value from the specified section & key, default_value is returned if the sect & key doesn't exist */
string_type get(const string_type& sect, const key_type& key, const string_type& default_value)
{
auto it = this->find(sect);
if(it != this->end())
{
auto itv = it->second.find(key);
if(itv != it->second.end())
return itv->second;
}
return default_value;
}
/* Sets the value of a value in the ini */
void set(const string_type& sect, const key_type& key, const string_type& value)
{
(*this)[sect][key] = value; // no emplace since overwrite!
}
/* Too lazy to continue this container... If you need more methods, just add it */
#if 1
bool read_file(const char_type* filename)
{
/* Using C stream in a STL-like container, funny?
*/
if(FILE* f = fopen(filename, "r"))
{
key_container* keys = nullptr;
char_type buf[2048];
string_type line;
string_type key;
string_type value;
string_type null_string;
size_type pos;
// Trims an string
auto trim = [](string_type& s, bool trimLeft, bool trimRight) -> string_type&
{
if(s.size())
{
// Ignore UTF-8 BOM
while(s.size() >= 3 && s[0] == (char)(0xEF) && s[1] == (char)(0xBB) && s[2] == (char)(0xBF))
s.erase(s.begin(), s.begin() + 3);
if(trimLeft)
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::function<int(int)>(::isspace))));
if(trimRight)
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::function<int(int)>(::isspace))).base(), s.end());
}
return s;
};
// Start parsing
while(fgets(buf, sizeof(buf), f))
{
// What a thing, reading into a char buffer and then putting in the string...
line = buf;
// Find comment and remove anything after it from the line
if((pos = line.find_first_of(';')) != line.npos)
line.erase(pos);
// Trim the string, and if it gets empty, skip this line
if(trim(line, true, true).empty())
continue;
// Find section name
if(line.front() == '[' && line.back() == ']')
{
pos = line.length() - 1; //line.find_first_of(']');
if(pos != line.npos)
{
trim(key.assign(line, 1, pos-1), true, true);
keys = &data[std::move(key)]; // Create section
}
else
keys = nullptr;
}
else
{
// Find key and value positions
pos = line.find_first_of('=');
if(pos == line.npos)
{
// There's only the key
key = line; // No need for trim, line is already trimmed
value.clear();
}
else
{
// There's the key and the value
trim(key.assign(line, 0, pos), false, true); // trim the right
trim(value.assign(line, pos + 1, line.npos), true, false); // trim the left
}
// Put the key/value into the current keys object, or into the section "" if no section has been found
#if __cplusplus >= 201103L || _MSC_VER >= 1800
(keys ? *keys : data[null_string]).emplace(std::move(key), std::move(value));
#else
(keys ? *keys : data[null_string])[key] = value;
key.clear(); value.clear();
#endif
}
}
fclose(f);
return true;
}
return false;
}
/*
* Dumps the content of this container into an ini file
*/
bool write_file(const char_type* filename)
{
if(FILE* f = fopen(filename, "w"))
{
bool first = true;
for(auto& sec : this->data)
{
fprintf(f, first? "[%s]\n" : "\n[%s]\n", sec.first.c_str());
first = false;
for(auto& kv : sec.second)
{
if(kv.second.empty())
fprintf(f, "%s\n", kv.first.c_str());
else
fprintf(f, "%s = %s\n", kv.first.c_str(), kv.second.c_str());
}
}
fclose(f);
return true;
}
return false;
}
/*
*/
bool load_file(const char_type* filename)
{
return read_file(filename);
}
bool load_file(const StringType& filename)
{
return load_file(filename.c_str());
}
bool write_file(const StringType& filename)
{
return write_file(filename.c_str());
}
#endif
};
/* Use default basic_ini
*
* Limitations:
* * Not unicode aware
* * Case sensitive
* * Sections must have unique keys
*/
typedef basic_ini<> ini;
}
#endif

View File

@ -997,7 +997,7 @@ void CHud::Draw()
} }
else { else {
BigMessageAlpha[0] = 0.0f; BigMessageAlpha[0] = 0.0f;
BigMessageX[0] = SCALE_AND_CENTER_X(-60.0f); BigMessageX[0] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f);
BigMessageInUse[0] = 1.0f; BigMessageInUse[0] = 1.0f;
} }
} }
@ -1008,7 +1008,7 @@ void CHud::Draw()
// WastedBustedText // WastedBustedText
if (m_BigMessage[2][0]) { if (m_BigMessage[2][0]) {
if (BigMessageInUse[2] != 0.0f) { if (BigMessageInUse[2] != 0.0f) {
BigMessageAlpha[2] += (CTimer::GetTimeStepInSeconds() * 255.0f); BigMessageAlpha[2] += (CTimer::GetTimeStepInMilliseconds() * 0.4f);
if (BigMessageAlpha[2] > 255.0f) if (BigMessageAlpha[2] > 255.0f)
BigMessageAlpha[2] = 255.0f; BigMessageAlpha[2] = 255.0f;
@ -1261,7 +1261,7 @@ void CHud::DrawAfterFade()
} }
break; break;
case 2: case 2:
OddJob2Timer += (20.0f * CTimer::GetTimeStep()); OddJob2Timer += CTimer::GetTimeStepInMilliseconds();
if (OddJob2Timer > 1500) { if (OddJob2Timer > 1500) {
OddJob2On = 3; OddJob2On = 3;
} }
@ -1355,7 +1355,7 @@ void CHud::DrawAfterFade()
} }
else { else {
BigMessageAlpha[1] = 0.0f; BigMessageAlpha[1] = 0.0f;
BigMessageX[1] = SCALE_AND_CENTER_X(-60.0f); BigMessageX[1] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f);
BigMessageInUse[1] = 1.0f; BigMessageInUse[1] = 1.0f;
} }
} }

View File

@ -67,6 +67,10 @@ void CapturePad(RwInt32 padID);
void joysChangeCB(int jid, int event); void joysChangeCB(int jid, int event);
#endif #endif
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
extern char gSelectedJoystickName[128];
#endif
enum eGameState enum eGameState
{ {
GS_START_UP = 0, GS_START_UP = 0,

View File

@ -87,6 +87,11 @@ long _dwOperatingSystemVersion;
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
char gSelectedJoystickName[128] = "";
#endif
/* /*
***************************************************************************** *****************************************************************************
*/ */
@ -822,31 +827,19 @@ void joysChangeCB(int jid, int event);
bool IsThisJoystickBlacklisted(int i) bool IsThisJoystickBlacklisted(int i)
{ {
#ifndef DONT_TRUST_RECOGNIZED_JOYSTICKS
return false;
#else
if (glfwJoystickIsGamepad(i)) if (glfwJoystickIsGamepad(i))
return false; return false;
const char* joyname = glfwGetJoystickName(i); const char* joyname = glfwGetJoystickName(i);
// this is just a keyboard and mouse if (strncmp(joyname, gSelectedJoystickName, sizeof(gSelectedJoystickName)) == 0)
// Microsoft Microsoft® 2.4GHz Transceiver v8.0 Consumer Control return false;
// Microsoft Microsoft® 2.4GHz Transceiver v8.0 System Control
if (strstr(joyname, "2.4GHz Transceiver"))
return true;
// COMPANY USB Device System Control
// COMPANY USB Device Consumer Control
if (strstr(joyname, "COMPANY USB"))
return true;
// i.e. Synaptics TM2438-005
if (strstr(joyname, "Synaptics "))
return true;
// i.e. ELAN Touchscreen
if (strstr(joyname, "ELAN "))
return true;
// i.e. Primax Electronics, Ltd HP Wireless Keyboard Mouse Kit Consumer Control
if (strstr(joyname, "Keyboard"))
return true;
return false; return true;
#endif
} }
void _InputInitialiseJoys() void _InputInitialiseJoys()
@ -865,6 +858,7 @@ void _InputInitialiseJoys()
if (PSGLOBAL(joy1id) != -1) { if (PSGLOBAL(joy1id) != -1) {
int count; int count;
glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); glfwGetJoystickButtons(PSGLOBAL(joy1id), &count);
strcpy(gSelectedJoystickName, glfwGetJoystickName(PSGLOBAL(joy1id)));
ControlsManager.InitDefaultControlConfigJoyPad(count); ControlsManager.InitDefaultControlConfigJoyPad(count);
} }
} }
@ -2070,18 +2064,18 @@ void CapturePad(RwInt32 padID)
void joysChangeCB(int jid, int event) void joysChangeCB(int jid, int event)
{ {
if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) {
{ if (PSGLOBAL(joy1id) == -1) {
if (PSGLOBAL(joy1id) == -1)
PSGLOBAL(joy1id) = jid; PSGLOBAL(joy1id) = jid;
else if (PSGLOBAL(joy2id) == -1) strcpy(gSelectedJoystickName, glfwGetJoystickName(jid));
} else if (PSGLOBAL(joy2id) == -1)
PSGLOBAL(joy2id) = jid; PSGLOBAL(joy2id) = jid;
}
else if (event == GLFW_DISCONNECTED) } else if (event == GLFW_DISCONNECTED) {
{ if (PSGLOBAL(joy1id) == jid) {
if (PSGLOBAL(joy1id) == jid)
PSGLOBAL(joy1id) = -1; PSGLOBAL(joy1id) = -1;
else if (PSGLOBAL(joy2id) == jid) strcpy(gSelectedJoystickName, "");
} else if (PSGLOBAL(joy2id) == jid)
PSGLOBAL(joy2id) = -1; PSGLOBAL(joy2id) = -1;
} }
} }

View File

@ -74,11 +74,12 @@ void CCarGenerator::DoInternalProcessing()
} }
m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pBoat); m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pBoat);
}else{ }else{
bool groundFound = false; bool groundFound;
CVector pos = m_vecPos; CVector pos = m_vecPos;
if (pos.z > -100.0f){ if (pos.z > -100.0f){
pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound); pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound);
}else{ }else{
groundFound = false;
CColPoint cp; CColPoint cp;
CEntity* pEntity; CEntity* pEntity;
groundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f, groundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f,
@ -89,7 +90,12 @@ void CCarGenerator::DoInternalProcessing()
if (!groundFound) { if (!groundFound) {
debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y); debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y);
}else{ }else{
CAutomobile* pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE); CAutomobile* pCar;
// So game crashes if it's bike :D
if (((CVehicleModelInfo*)CModelInfo::GetModelInfo(m_nModelIndex))->m_vehicleType != VEHICLE_TYPE_BIKE)
pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE);
pCar->bIsStatic = false; pCar->bIsStatic = false;
pCar->bEngineOn = false; pCar->bEngineOn = false;
pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel(); pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel();