Files
jminos/src/GraphicalUI/Settings.cpp
zulianc 34d781fcfe
All checks were successful
Linux arm64 / Build (push) Successful in 12m32s
better main
2025-06-19 19:13:43 +02:00

417 lines
11 KiB
C++

#include "Settings.h"
#include "../Core/Menu.h"
#include "Keybinds.h"
#include "PiecesType.h"
#include <vector>
#include <optional>
#include <fstream>
#include <algorithm>
#include <SFML/Graphics.hpp>
static const sf::Vector2u BASE_WINDOW_SIZE = {80, 50};
static const int WINDOW_SIZE_MULTIPLIERS[] = {4, 6, 10, 14, 20, 30, 40};
static const int WINDOW_SIZE_LAST_MODE = (sizeof(WINDOW_SIZE_MULTIPLIERS) / sizeof(int)) - 1;
static const int START_TIMER_MAX = 4;
static const int DISTRIBUTION_MAX = 20;
Settings::Settings(bool loadPieces) {
this->keybinds.clear();
this->keybinds.reserve(NUMBER_OF_KEYBINDS);
for (int i = 0; i < NUMBER_OF_KEYBINDS; i++) {
this->keybinds.emplace_back(i);
}
this->loadSettingsFromFile(loadPieces, {});
}
void Settings::loadPieces(int loadablePiecesSizeRequest) {
if (loadablePiecesSizeRequest < MINIMUM_PIECES_SIZE) {
loadablePiecesSizeRequest = MINIMUM_PIECES_SIZE;
}
else if (loadablePiecesSizeRequest > MAXIMUM_PIECES_SIZE) {
loadablePiecesSizeRequest = MAXIMUM_PIECES_SIZE;
}
bool succeeded = true;
int i = 1;
while (succeeded && (i <= loadablePiecesSizeRequest)) {
succeeded = this->menu.getPiecesList().loadPieces(i);
i++;
}
if (succeeded) {
this->loadablePiecesSize = loadablePiecesSizeRequest;
}
this->loadedPieces = succeeded;
}
void Settings::loadSettingsFromFile(bool loadPieces, std::optional<int> loadablePiecesSizeRequest) {
std::ifstream settingsFile("data/config/settings.bin", std::ios::binary);
char byte;
// file format version
settingsFile.get(byte);
// loadable pieces size
settingsFile.get(byte);
this->loadablePiecesSize = byte;
if (loadPieces) {
if (loadablePiecesSizeRequest.has_value()) {
this->loadPieces(loadablePiecesSizeRequest.value());
}
else {
this->loadPieces(byte);
}
}
else {
this->loadedPieces = false;
}
// keybind layout
settingsFile.get(byte);
this->chosenKeybinds = byte;
// DAS tuning
settingsFile.get(byte);
this->menu.getPlayerControls().setDAS(byte);
// ARR tuning
settingsFile.get(byte);
this->menu.getPlayerControls().setARR(byte);
// SDR tuning
settingsFile.get(byte);
this->menu.getPlayerControls().setSDR(byte);
// window size mode
settingsFile.get(byte);
this->windowSizeMode = byte;
// start timer length
settingsFile.get(byte);
this->startTimerLength = byte;
// gamemode
settingsFile.get(byte);
this->gamemode = Gamemode(byte);
// board width
settingsFile.get(byte);
this->menu.setBoardWidth(byte);
// board height
settingsFile.get(byte);
this->menu.setBoardHeight(byte);
if (this->loadedPieces) {
// piece distribution
settingsFile.get(byte);
this->menu.getPiecesList().setDistributionMode(DistributionMode(byte));
this->distributions.clear();
this->distributions.push_back(0);
for (int i = 1; i <= 15; i++) {
settingsFile.get(byte);
this->distributions.push_back(byte);
}
this->confirmDistribution();
// selected pieces
char pieceType;
char pieceSize;
char lowByte;
char midByte;
char highByte;
this->selectedPieces.clear();
while (settingsFile.get(pieceType)) {
if (settingsFile.eof()) break;
if (getSizeOfPieces(PiecesType(pieceType)) == 0) {
settingsFile.get(pieceSize);
this->selectedPieces.emplace_back(PiecesType(pieceType), pieceSize);
}
else {
settingsFile.get(lowByte);
settingsFile.get(midByte);
settingsFile.get(highByte);
int pieceNumber = ((unsigned char) lowByte) + ((unsigned char) midByte << 8) + ((unsigned char) highByte << 16);
this->selectedPieces.emplace_back(PiecesType(pieceType), pieceNumber);
}
}
this->confirmSelectedPieces();
}
else {
this->distributions.clear();
this->selectedPieces.clear();
}
}
void Settings::saveSettingsToFile() const {
if (!this->loadedPieces) return;
this->keybinds.at(CUSTOMIZABLE_KEYBINDS).saveKeybindsToFile();
std::ofstream settingsFile("data/config/settings.bin", std::ios::trunc | std::ios::binary);
char byte;
// file format version
byte = CURRENT_FILE_FORMAT_VERSION;
settingsFile.write(&byte, 1);
// loadable pieces size
byte = this->loadablePiecesSize;
settingsFile.write(&byte, 1);
// keybind layout
byte = this->chosenKeybinds;
settingsFile.write(&byte, 1);
// DAS tuning
byte = this->menu.readPlayerControls().getDAS();
settingsFile.write(&byte, 1);
// ARR tuning
byte = this->menu.readPlayerControls().getARR();
settingsFile.write(&byte, 1);
// SDR tuning
byte = this->menu.readPlayerControls().getSDR();
settingsFile.write(&byte, 1);
// window size mode
byte = this->windowSizeMode;
settingsFile.write(&byte, 1);
// start timer length
byte = this->startTimerLength;
settingsFile.write(&byte, 1);
// gamemode
byte = this->gamemode;
settingsFile.write(&byte, 1);
// board width
byte = this->menu.getBoardWidth();
settingsFile.write(&byte, 1);
// board height
byte = this->menu.getBoardHeight();
settingsFile.write(&byte, 1);
// piece distribution
byte = this->menu.readPiecesList().getDistributionMode();
settingsFile.write(&byte, 1);
for (int i = 1; i <= 15; i++) {
byte = this->distributions.at(i);
settingsFile.write(&byte, 1);
}
// selected pieces
for (const auto& [type, value] : this->selectedPieces) {
byte = type;
settingsFile.write(&byte, 1);
if (getSizeOfPieces(type) == 0) {
byte = value;
settingsFile.write(&byte, 1);
}
else {
int number = value;
for (int i = 0; i < 3; i++) {
byte = (number % 256);
settingsFile.write(&byte, 1);
number = (number >> 8);
}
}
}
}
bool Settings::selectNextKeybinds() {
if (this->chosenKeybinds < (NUMBER_OF_KEYBINDS - 1)) {
this->chosenKeybinds++;
return true;
}
return false;
}
bool Settings::selectPreviousKeybinds() {
if (this->chosenKeybinds > 0) {
this->chosenKeybinds--;
return true;
}
return false;
}
bool Settings::canModifyCurrentKeybinds() const {
return (this->chosenKeybinds == CUSTOMIZABLE_KEYBINDS);
}
bool Settings::widenWindow() {
if (this->windowSizeMode < WINDOW_SIZE_LAST_MODE) {
this->windowSizeMode++;
return true;
}
return false;
}
bool Settings::shortenWindow() {
if (this->windowSizeMode > 0) {
this->windowSizeMode--;
return true;
}
return false;
}
void Settings::changeVideoMode(sf::RenderWindow& window) const {
sf::VideoMode videoMode(BASE_WINDOW_SIZE * (unsigned int) WINDOW_SIZE_MULTIPLIERS[this->windowSizeMode]);
window.create(videoMode, "jminos", sf::Style::Close | sf::Style::Titlebar);
sf::Vector2u desktopSize = sf::VideoMode::getDesktopMode().size;
sf::Vector2u windowSize = window.getSize();
window.setPosition(sf::Vector2i((desktopSize.x / 2) - (windowSize.x / 2), (desktopSize.y / 2) - (windowSize.y / 2)));
}
bool Settings::lengthenStartTimer() {
if (this->startTimerLength < START_TIMER_MAX) {
this->startTimerLength++;
return true;
}
return false;
}
bool Settings::shortenStartTimer() {
if (this->startTimerLength > 0) {
this->startTimerLength--;
return true;
}
return false;
}
void Settings::setGamemode(Gamemode gamemode) {
this->gamemode = gamemode;
}
void Settings::selectPieces(PiecesType type, int value) {
if (!this->loadedPieces) return;
this->selectedPieces.emplace_back(type, value);
}
void Settings::unselectPieces(int index) {
if (!this->loadedPieces) return;
if (index >= this->selectedPieces.size()) return;
this->selectedPieces.erase(this->selectedPieces.begin() + index);
}
void Settings::confirmSelectedPieces() {
if (!this->loadedPieces) return;
this->menu.getPiecesList().unselectAll();
bool selectedNone = true;
for (const auto& [type, value] : this->selectedPieces) {
int size = getSizeOfPieces(type);
if (size == 0) {
if (!(value > this->loadablePiecesSize)) {
switch (type) {
case CONVEX_PIECES : {this->menu.getPiecesList().selectConvexPieces(value); break;}
case HOLELESS_PIECES : {this->menu.getPiecesList().selectHolelessPieces(value); break;}
case OTHER_PIECES : {this->menu.getPiecesList().selectOtherPieces(value); break;}
case ALL_PIECES : {this->menu.getPiecesList().selectAllPieces(value); break;}
}
selectedNone = false;
}
}
else {
if (!(getSizeOfPieces(type) > this->loadablePiecesSize)) {
this->menu.getPiecesList().selectPiece(size, value);
selectedNone = false;
}
}
}
if (selectedNone) {
this->selectedPieces.push_back(DEFAULT_SELECTION);
this->confirmSelectedPieces();
}
}
bool Settings::increaseDistribution(int size) {
if (!this->loadedPieces) return false;
if (size < 1 || size > this->loadablePiecesSize) return false;
if (this->distributions.at(size) < DISTRIBUTION_MAX) {
this->distributions.at(size)++;
return true;
}
return false;
}
bool Settings::decreaseDistribution(int size) {
if (!this->loadedPieces) return false;
if (size < 1 || size > this->loadablePiecesSize) return false;
if (this->distributions.at(size) > 0) {
this->distributions.at(size)--;
return true;
}
return false;
}
void Settings::confirmDistribution() {
if (!this->loadedPieces) return;
for (int i = 1; i <= 15; i++) {
this->menu.getPiecesList().changeCustomDistribution(i, (double) 1 / (this->distributions.at(i) + 0.001));
}
}
Menu& Settings::getMenu() {
return this->menu;
}
Keybinds& Settings::getKeybinds() {
return this->keybinds.at(this->chosenKeybinds);
}
int Settings::getLoadablePiecesSize() const {
return this->loadablePiecesSize;
}
bool Settings::hasLoadedPieces() const {
return this->loadedPieces;
}
int Settings::getKeybindsLayout() const {
return this->chosenKeybinds;
}
Gamemode Settings::getGamemode() const {
return this->gamemode;
}
int Settings::getWindowSizeMultiplier() const {
return WINDOW_SIZE_MULTIPLIERS[this->windowSizeMode];
}
int Settings::getStartTimerLength() const {
return this->startTimerLength;
}
const std::vector<std::pair<PiecesType, int>>& Settings::getSelectedPieces() const {
return this->selectedPieces;
}
const std::vector<int>& Settings::getDistributions() const {
return this->distributions;
}