The open source repository for the action RPG game in development by Sig Productions titled 'Adventures in Lestoria'!
https://forums.lestoria.net
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
320 lines
16 KiB
320 lines
16 KiB
#pragma region License
|
|
/*
|
|
License (OLC-3)
|
|
~~~~~~~~~~~~~~~
|
|
|
|
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions or derivations of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions or derivative works in binary form must reproduce the above
|
|
copyright notice. This list of conditions and the following disclaimer must be
|
|
reproduced in the documentation and/or other materials provided with the distribution.
|
|
|
|
3. Neither the name of the copyright holder nor the names of its contributors may
|
|
be used to endorse or promote products derived from this software without specific
|
|
prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
SUCH DAMAGE.
|
|
|
|
Portions of this software are copyright © 2024 The FreeType
|
|
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
|
All rights reserved.
|
|
*/
|
|
#pragma endregion
|
|
|
|
#include "AdventuresInLestoria.h"
|
|
#include "Menu.h"
|
|
#include "MenuComponent.h"
|
|
#include "SoundEffect.h"
|
|
#include "DEFINES.h"
|
|
#include "olcUTIL_DataFile.h"
|
|
#include "Unlock.h"
|
|
#include "State_OverworldMap.h"
|
|
#include "MenuLabel.h"
|
|
#include "Slider.h"
|
|
#include "Checkbox.h"
|
|
#include "InputDisplayComponent.h"
|
|
#include "GameSettings.h"
|
|
#include "MenuIconButton.h"
|
|
#include "ScrollableWindowComponent.h"
|
|
|
|
INCLUDE_DATA
|
|
INCLUDE_game
|
|
INCLUDE_WINDOW_SIZE
|
|
|
|
using A=Attribute;
|
|
|
|
#define UNLOCK_ALL_BUTTON
|
|
#undef UNLOCK_ALL_BUTTON //Comment out to enable unlock all button.
|
|
|
|
void Menu::InitializeSettingsWindow(){
|
|
vf2d windowSize=WINDOW_SIZE-vf2d{28,28};
|
|
Menu*settingsWindow=CreateMenu(SETTINGS,CENTERED,windowSize);
|
|
|
|
#pragma region Unlock All Button
|
|
#ifdef UNLOCK_ALL_BUTTON
|
|
settingsWindow->ADD("Unlock All Button",MenuComponent)(geom2d::rect<float>{{4,windowSize.y-20},{72,12}},"Unlock All",[](MenuFuncData data){
|
|
if(Menu::IsCurrentlyActive(SETTINGS)){
|
|
for(auto&cp:State_OverworldMap::connections){
|
|
Unlock::UnlockArea(cp.map);
|
|
}
|
|
SoundEffect::PlaySFX("Buy Item",SoundEffect::CENTERED);
|
|
}
|
|
return true;
|
|
})END;
|
|
#endif
|
|
#pragma endregion
|
|
|
|
settingsWindow->ADD("Settings Label",MenuLabel)(geom2d::rect<float>{{4,4},vf2d{windowSize.x-8,24}},"Game Settings",2.f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
|
|
|
|
settingsWindow->F(A::LAST_BGM_VOLUME)=1.f;
|
|
settingsWindow->F(A::LAST_SFX_VOLUME)=1.f;
|
|
|
|
//windowsize.y-20
|
|
auto settingsList=settingsWindow->ADD("Settings Scroll List",ScrollableWindowComponent)(geom2d::rect<float>{{4,32},{windowSize.x-8,windowSize.y-56}})END;
|
|
|
|
settingsList->ADD("BGM Slider",Slider)(geom2d::rect<float>{vf2d{windowSize.x/2-64,0},{172,16}},"BGM Volume:",Audio::GetBGMVolume(),[](float val){
|
|
if(Menu::IsCurrentlyActive(SETTINGS)){
|
|
if(abs(Menu::menus[SETTINGS]->F(A::LAST_BGM_VOLUME)-val)>=0.04f){
|
|
SoundEffect::PlaySFX("Change Volume",SoundEffect::CENTERED);
|
|
Menu::menus[SETTINGS]->F(A::LAST_BGM_VOLUME)=val;
|
|
}
|
|
Audio::SetBGMVolume(val);
|
|
}
|
|
})END;
|
|
settingsList->ADD("SFX Slider",Slider)(geom2d::rect<float>{vf2d{windowSize.x/2-64,20},{172,16}},"SFX Volume:",Audio::GetSFXVolume(),[](float val){
|
|
if(Menu::IsCurrentlyActive(SETTINGS)){
|
|
if(abs(Menu::menus[SETTINGS]->F(A::LAST_SFX_VOLUME)-val)>=0.04f){
|
|
SoundEffect::PlaySFX("Change Volume",SoundEffect::CENTERED);
|
|
Menu::menus[SETTINGS]->F(A::LAST_SFX_VOLUME)=val;
|
|
}
|
|
}
|
|
})END;
|
|
|
|
settingsList->ADD("Show Max HP Checkbox",Checkbox)(geom2d::rect<float>{{4.f,40},{16.f,16.f}},[](ToggleFuncData data){
|
|
GameSettings::SetMaxHealthDisplay(data.checked);
|
|
return true;
|
|
},GameSettings::ShowMaxHealth())END;
|
|
settingsList->ADD("Show Max HP Label",MenuLabel)(geom2d::rect<float>{{22.f,40},{windowSize.x/2-24.f,16.f}},"Show Max Health",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
settingsList->ADD("Show Max Mana Checkbox",Checkbox)(geom2d::rect<float>{{windowSize.x/2+4.f,40},{16.f,16.f}},[](ToggleFuncData data){
|
|
GameSettings::SetMaxManaDisplay(data.checked);
|
|
return true;
|
|
},GameSettings::ShowMaxMana())END;
|
|
settingsList->ADD("Show Max Mana Label",MenuLabel)(geom2d::rect<float>{{windowSize.x/2+22.f,40},{windowSize.x/2-24.f,16.f}},"Show Max Mana",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
|
|
settingsList->ADD("Screen Shake Checkbox",Checkbox)(geom2d::rect<float>{{4.f,60},{16.f,16.f}},[](ToggleFuncData data){
|
|
GameSettings::SetScreenShake(data.checked);
|
|
return true;
|
|
},GameSettings::ScreenShakeEnabled())END;
|
|
settingsList->ADD("Screen Shake Label",MenuLabel)(geom2d::rect<float>{{22.f,60},{windowSize.x/2-24.f,16.f}},"Screen Shake",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
settingsList->ADD("Controller Rumble Checkbox",Checkbox)(geom2d::rect<float>{{4.f,80},{16.f,16.f}},[](ToggleFuncData data){
|
|
if(Menu::IsCurrentlyActive(SETTINGS)){
|
|
GameSettings::SetRumble(data.checked);
|
|
if(GameSettings::RumbleEnabled(GameSettings::OVERRIDE)){
|
|
Input::StartVibration(GameSettings::OVERRIDE);
|
|
data.component.lock()->F(A::RUMBLE_TIMER)=0.3f;
|
|
}else{
|
|
Input::StopVibration();
|
|
}
|
|
}
|
|
return true;
|
|
},GameSettings::RumbleEnabled())END;
|
|
settingsList->ADD("Controller Rumble Label",MenuLabel)(geom2d::rect<float>{{22.f,80},{windowSize.x/2-24.f,16.f}},"Gamepad Rumble",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
|
|
auto vsyncToggle=settingsList->ADD("VSync Checkbox",Checkbox)(geom2d::rect<float>{{4.f,100},{16.f,16.f}},[](ToggleFuncData data){
|
|
game->SetVSync(data.checked);
|
|
GameSettings::SetVSync(data.checked);
|
|
return true;
|
|
},GameSettings::VSyncEnabled())END;
|
|
auto vsyncToggleLabel=settingsList->ADD("VSync Toggle Label",MenuLabel)(geom2d::rect<float>{{22.f,100},{windowSize.x/2-36.f,16.f}},"VSync",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
|
|
auto autoPauseToggle=settingsList->ADD("Auto Pause Checkbox",Checkbox)(geom2d::rect<float>{{4.f,120},{16.f,16.f}},[](ToggleFuncData data){
|
|
GameSettings::SetAutoPause(data.checked);
|
|
return true;
|
|
},GameSettings::AutoPauseEnabled())END;
|
|
auto autoPauseToggleLabel=settingsList->ADD("Auto Pause Toggle Label",MenuLabel)(geom2d::rect<float>{{22.f,120},{windowSize.x/2-36.f,16.f}},"Pause if Hit When\nWindow Unfocused",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
|
|
settingsList->ADD("Terrain Collision Boxes Checkbox",Checkbox)(geom2d::rect<float>{{windowSize.x/2+4.f,60},{16.f,16.f}},[](ToggleFuncData data){
|
|
GameSettings::SetTerrainCollisionBoxes(data.checked);
|
|
return true;
|
|
},GameSettings::TerrainCollisionBoxesEnabled())END;
|
|
settingsList->ADD("Terrain Collision Boxes Label",MenuLabel)(geom2d::rect<float>{{windowSize.x/2+22.f,60},{windowSize.x/2-36.f,16.f}},"Terrain Collision Boxes",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
settingsList->ADD("Keyboard Play Auto-Aim Checkbox",Checkbox)(geom2d::rect<float>{{windowSize.x/2+4.f,80},{16.f,16.f}},[](ToggleFuncData data){
|
|
GameSettings::SetKeyboardAutoAim(data.checked);
|
|
return true;
|
|
},GameSettings::KeyboardAutoAimEnabled())END;
|
|
settingsList->ADD("Keyboard Play Auto-Aim Label",MenuLabel)(geom2d::rect<float>{{windowSize.x/2+22.f,80},{windowSize.x/2-36.f,16.f}},"Aim Assist\n(No Mouse Players)",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
|
|
auto fullscreenToggle=settingsList->ADD("Fullscreen Toggle Checkbox",Checkbox)(geom2d::rect<float>{{windowSize.x/2+4.f,100},{16.f,16.f}},[](ToggleFuncData data){
|
|
if(data.checked){ //When going to fullscreen mode, the windowed mode positioning needs to be saved to be restored later.
|
|
GameSettings::SetWindowPos(game->GetActualWindowPos());
|
|
}
|
|
if(!Menu::UsingMouseNavigation()){ //This prevents the fullscreen toggle from losing focus upon a window resize.
|
|
Menu::IgnoreNextMouseNavigationAttempt();
|
|
}
|
|
game->SetFullscreen(data.checked,GameSettings::GetWindowPos());
|
|
return true;
|
|
},game->IsFullscreen())END;
|
|
auto fullscreenToggleLabel=settingsList->ADD("Fullscreen Toggle Label",MenuLabel)(geom2d::rect<float>{{windowSize.x/2+22.f,100},{windowSize.x/2-36.f,16.f}},"Fullscreen",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
|
|
#ifdef __EMSCRIPTEN__
|
|
fullscreenToggle->Disable();
|
|
fullscreenToggleLabel->Disable();
|
|
#endif
|
|
|
|
settingsList->ADD("Button Set Toggle Box",MenuIconButton)(geom2d::rect<float>{{windowSize.x/2.f-windowSize.x/8.f-6.f,140.f},{windowSize.x/4.f,16.f}},GFX["themes/xb.png"].Decal(),[](MenuFuncData data){
|
|
switch(GameSettings::GetIconType()){
|
|
case IconType::XB:{
|
|
GameSettings::SetIconType(IconType::PS);
|
|
DYNAMIC_POINTER_CAST<MenuIconButton>(data.component)->SetIcon(GFX["themes/ps.png"].Decal());
|
|
}break;
|
|
case IconType::PS:{
|
|
GameSettings::SetIconType(IconType::XB_REVERSED);
|
|
DYNAMIC_POINTER_CAST<MenuIconButton>(data.component)->SetIcon(GFX["themes/xb_reversed.png"].Decal());
|
|
}break;
|
|
case IconType::XB_REVERSED:{
|
|
GameSettings::SetIconType(IconType::XB);
|
|
DYNAMIC_POINTER_CAST<MenuIconButton>(data.component)->SetIcon(GFX["themes/xb.png"].Decal());
|
|
}break;
|
|
default:{
|
|
ERR(std::format("WARNING! Unhandled icon type {}!",int(GameSettings::GetIconType())));
|
|
}
|
|
}
|
|
if(Menu::IsCurrentlyActive(data.menu.GetType())){
|
|
SoundEffect::PlaySFX("Button Click",SoundEffect::CENTERED);
|
|
}
|
|
return true;
|
|
})END;
|
|
|
|
#pragma region Setup all input displays as keyboard controls.
|
|
//NOTE: We are shadowing code from InputKeyboardWindow! If at some point the retrival method for getting input displays changes, we likely will be changing the code here as well!
|
|
auto ChangeKeybindDisplayType=[&](InputType inputType){
|
|
const int menuRowCount=DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2+1;
|
|
const int menuColCount=2;
|
|
for(int row=0;row<menuRowCount;row++){
|
|
for(int col=0;col<menuColCount;col++){
|
|
if(DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==1&&col==1&&row==menuRowCount-1)continue; //We only continue on a blank space when we have an odd number of elements.
|
|
Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->SetKeyType(inputType);
|
|
}
|
|
}
|
|
const int ingameControlsRowCount=DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2+1;
|
|
const int ingameControlsColCount=2;
|
|
for(int row=0;row<ingameControlsRowCount;row++){
|
|
for(int col=0;col<ingameControlsColCount;col++){
|
|
if(DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==1&&col==1&&row==ingameControlsRowCount-1)continue; //We only continue on a blank space when we have an odd number of elements.
|
|
Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Gameplay Input Displayer",row,col))->SetKeyType(inputType);
|
|
}
|
|
}
|
|
};
|
|
#pragma endregion
|
|
|
|
settingsList->ADD("Keyboard Bindings Button",MenuComponent)(geom2d::rect<float>{{28,160.f},vf2d{settingsList->rect.size.x-12-56,24}},"Keyboard Bindings",[&](MenuFuncData data){
|
|
ChangeKeybindDisplayType(KEY);
|
|
Component<MenuLabel>(INPUT_KEY_DISPLAY,"Keyboard Mapping Label")->SetLabel("Keyboard Mappings");
|
|
Menu::OpenMenu(INPUT_KEY_DISPLAY);
|
|
return true;
|
|
},vf2d{1.5f,2.f})END;
|
|
settingsList->ADD("Controller Bindings Button",MenuComponent)(geom2d::rect<float>{{28,188.f},vf2d{settingsList->rect.size.x-12-56,24}},"Controller Bindings",[&](MenuFuncData data){
|
|
ChangeKeybindDisplayType(CONTROLLER);
|
|
Component<MenuLabel>(INPUT_KEY_DISPLAY,"Keyboard Mapping Label")->SetLabel("Controller Mappings");
|
|
STEAMINPUT(
|
|
SteamInput()->ShowBindingPanel(Input::steamControllers[Input::activeSteamControllerIndex]);
|
|
)else{
|
|
Menu::OpenMenu(INPUT_KEY_DISPLAY);
|
|
}
|
|
return true;
|
|
},vf2d{1.5f,2.f})END;
|
|
|
|
settingsWindow->ADD("Go Back",MenuComponent)(geom2d::rect<float>{vf2d{windowSize.x/2.f,windowSize.y-12}-vf2d{36,8},{72,12}},"Go Back",[](MenuFuncData data){
|
|
Menu::CloseMenu();
|
|
return true;
|
|
})END;
|
|
|
|
settingsWindow->SetupKeyboardNavigation(
|
|
[](MenuType type,Data&returnData){ //On Open
|
|
returnData="BGM Slider";
|
|
},
|
|
{ //Button Key
|
|
{game->KEY_SCROLL,{"Navigate",[](MenuType type){}}},
|
|
{game->KEY_BACK,{"Back",[](MenuType type){
|
|
Menu::CloseMenu();
|
|
}}},
|
|
{game->KEY_CONFIRM,{"Select",[](MenuType type){}}},
|
|
}
|
|
,{ //Button Navigation Rules
|
|
{"BGM Slider",{
|
|
.up="Go Back",
|
|
.down="SFX Slider",}},
|
|
{"SFX Slider",{
|
|
.up="BGM Slider",
|
|
.down="Show Max Mana Checkbox",}},
|
|
{"Show Max HP Checkbox",{
|
|
.up="SFX Slider",
|
|
.down="Screen Shake Checkbox",
|
|
.left="Show Max Mana Checkbox",
|
|
.right="Show Max Mana Checkbox",}},
|
|
{"Show Max Mana Checkbox",{
|
|
.up="SFX Slider",
|
|
.down="Terrain Collision Boxes Checkbox",
|
|
.left="Show Max HP Checkbox",
|
|
.right="Show Max HP Checkbox",}},
|
|
{"Terrain Collision Boxes Checkbox",{
|
|
.up="Show Max Mana Checkbox",
|
|
.down="Keyboard Play Auto-Aim Checkbox",
|
|
.left="Screen Shake Checkbox",
|
|
.right="Screen Shake Checkbox",}},
|
|
{"Keyboard Play Auto-Aim Checkbox",{
|
|
.up="Terrain Collision Boxes Checkbox",
|
|
.down="Fullscreen Toggle Checkbox",
|
|
.left="Controller Rumble Checkbox",
|
|
.right="Controller Rumble Checkbox",}},
|
|
{"Screen Shake Checkbox",{
|
|
.up="Show Max HP Checkbox",
|
|
.down="Controller Rumble Checkbox",
|
|
.left="Terrain Collision Boxes Checkbox",
|
|
.right="Terrain Collision Boxes Checkbox",}},
|
|
{"Controller Rumble Checkbox",{
|
|
.up="Screen Shake Checkbox",
|
|
.down="VSync Checkbox",
|
|
.left="Keyboard Play Auto-Aim Checkbox",
|
|
.right="Keyboard Play Auto-Aim Checkbox",}},
|
|
{"VSync Checkbox",{
|
|
.up="Controller Rumble Checkbox",
|
|
.down="Auto Pause Checkbox",
|
|
.left="Fullscreen Toggle Checkbox",
|
|
.right="Fullscreen Toggle Checkbox",}},
|
|
{"Auto Pause Checkbox",{
|
|
.up="VSync Checkbox",
|
|
.down="Button Set Toggle Box",}},
|
|
{"Fullscreen Toggle Checkbox",{
|
|
.up="Keyboard Play Auto-Aim Checkbox",
|
|
.down="Auto Pause Checkbox",
|
|
.left="VSync Checkbox",
|
|
.right="VSync Checkbox",}},
|
|
{"Button Set Toggle Box",{
|
|
.up="Auto Pause Checkbox",
|
|
.down="Keyboard Bindings Button",}},
|
|
{"Keyboard Bindings Button",{
|
|
.up="Button Set Toggle Box",
|
|
.down="Controller Bindings Button",}},
|
|
{"Controller Bindings Button",{
|
|
.up="Keyboard Bindings Button",
|
|
.down="Go Back",}},
|
|
{"Go Back",{
|
|
.up="Controller Bindings Button",
|
|
.down="BGM Slider",}},
|
|
});
|
|
} |