Skip to content

Commit c1e5ed3

Browse files
committed
Pretty buttons
1 parent e55220f commit c1e5ed3

File tree

8 files changed

+107
-105
lines changed

8 files changed

+107
-105
lines changed

Prism.Game/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ add_custom_target(
4040
COMMAND
4141
${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/res")
4242

43-
#add_custom_command(TARGET Prism.Game POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/res")
43+
add_custom_command(TARGET Prism.Game POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/res")

Prism.Game/include/Variables.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ namespace Variables {
2121
constexpr SpritePath NEW_GAME = "img/NewGameButton.png";
2222
constexpr SpritePath LEVEL_SLOT_FILLED = "img/LoadLevelButton_Filled.png";
2323
constexpr SpritePath LEVEL_SLOT_EMPTY = "img/LoadLevelButton_Empty.png";
24+
constexpr SpritePath PREVIOUS_BUTTON = "img/PreviousPageButton.png";
25+
constexpr SpritePath PREVIOUS_BUTTON_DISABLED = "img/PreviousPageButton_Disabled.png";
26+
constexpr SpritePath NEXT_BUTTON = "img/NextPageButton.png";
27+
constexpr SpritePath NEXT_BUTTON_DISABLED = "img/NextPageButton_Disabled.png";
2428
}
2529
}
2630
namespace Visual {

Prism.Game/res/img/NextPageButton.png

16.5 KB
Loading
19.1 KB
Loading
16.6 KB
Loading
23.6 KB
Loading

Prism.Game/src/States/WorldSelectionState.cpp

Lines changed: 101 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -15,109 +15,106 @@ using namespace Variables::Visual::LevelSelection;
1515

1616
namespace States {
1717

18-
void WorldSelectionState::onInit(Context &context) {
19-
auto saves = Util::FileSystem().getFilenamesInDirectory(levelDirectory);
20-
saves.erase(std::remove_if(saves.begin(), saves.end(), [](const std::string &v) {
21-
constexpr std::string_view extension = LEVEL_EXTENSION;
22-
const auto canFit = extension.size() <= v.size();
23-
const auto matchesEnd = std::equal(v.begin() + v.size() - extension.size(), v.end(), extension.begin());
24-
return !(canFit && matchesEnd);
25-
}), saves.end());
26-
27-
std::copy_n(saves.begin(), std::min(levels.size(), saves.size()), levels.begin());
28-
29-
renderDevice = Renderer::Graphics::OpenGL::OGLRenderDevice::getRenderDevice();
30-
renderDevice->setClearColour(1.f, 1.f, 1.f, 1.f);
31-
32-
makeButtons(context);
33-
}
34-
35-
void WorldSelectionState::makeButtons(Context &context) {
36-
constexpr auto width = (2 - OUTER_MARGIN * 2) / COLUMNS - GRID_MARGIN;
37-
constexpr auto height = (1.5f - OUTER_MARGIN * 2) / ROWS - GRID_MARGIN;
38-
39-
Menu::MenuBuilder menuBuilder;
40-
menuBuilder.addControl(-0.5f, 0.5, 1, 0.24, Sprites::GAME_OVER);
41-
// TODO: Make a uniform GUI design with a standard location for this button.
42-
menuBuilder.addControl(-0.9f, 0.8, 0.3, 0.1, Sprites::BACK, [&context]() {
43-
context.stateMachine->setState<MainMenuState>(context);
44-
});
45-
46-
47-
const auto pageCount = std::ceil(1.0 * levels.size() / pageSize) + 1;
48-
const auto pageStr = fmt::format("{:^25}", fmt::format("{} / {}", currentPage + 1,
49-
pageCount));
50-
menuBuilder.addTextControl(-.25f, -.95f, 0.001f, Math::Vector3f(0, 0, 0), pageStr);
51-
52-
if (currentPage > 0) {
53-
menuBuilder.addControl(-0.4f, -.95f, 0.1, 0.1, Sprites::LEVEL_SLOT_FILLED, [&]() {
54-
currentPage -= 1;
55-
makeButtons(context);
56-
});
57-
} else {
58-
menuBuilder.addControl(-0.4f, -.95f, 0.1, 0.1, Sprites::LEVEL_SLOT_EMPTY);
59-
}
60-
61-
if (currentPage < pageCount - 1) {
62-
menuBuilder.addControl(0.3f, -.95f, 0.1, 0.1, Sprites::LEVEL_SLOT_FILLED, [&]() {
63-
currentPage += 1;
64-
makeButtons(context);
65-
});
66-
} else {
67-
menuBuilder.addControl(0.3f, -.95f, 0.1, 0.1, Sprites::LEVEL_SLOT_EMPTY);
68-
}
69-
70-
71-
const int pageOffset = currentPage * COLUMNS * ROWS;
72-
// TODO: Draw these from top-left to bottom-right
73-
for (int r = 0; r < ROWS; ++r) {
74-
for (int c = 0; c < COLUMNS; ++c) {
75-
const auto levelIndex = pageOffset + r * ROWS + c;
76-
77-
const auto x = -1 + OUTER_MARGIN + c * (width + GRID_MARGIN);// + -.045 * r;
78-
const auto y = -1 + OUTER_MARGIN + (ROWS - 1 - r) * (height + GRID_MARGIN);
79-
80-
// TODO: Use proper button images
81-
// TODO: Show the level names
82-
if (levels.size() > levelIndex) {
83-
const auto levelName = levels[levelIndex];
84-
const auto path = levelDirectory + '/' + levelName;
85-
const auto readableLevelName = levelName.substr(0, levelName.find(".json"));
86-
menuBuilder.addControl(x, y, width, height, Sprites::LEVEL_SLOT_FILLED, [&context, path]() {
87-
if (context.stateMachine->hasState<PrismGame>()) {
88-
context.stateMachine->removeState<PrismGame>();
89-
}
90-
context.stateMachine->addState<PrismGame>(context, path);
91-
context.stateMachine->setState<PrismGame>(context);
92-
});
93-
menuBuilder.addControl(x, y, width, height, Sprites::LEVEL_SLOT_FILLED);
94-
menuBuilder.addTextControl(x + .03f, y + height / 2, 0.001, Math::Vector3f(1, 1, 1),
95-
fmt::format("{:^13}", readableLevelName));
96-
} else {
97-
menuBuilder.addControl(x, y, width, height, Sprites::LEVEL_SLOT_EMPTY);
98-
99-
menuBuilder.addControl(x + .025f, y + height / 4 + .09f, width - 0.05f, .11,
100-
Sprites::WHITE_BORDERED);
101-
102-
menuBuilder.addTextControl(x + .05f, y + height / 2, 0.001, Math::Vector3f(0, 0, 0), "Empty Slot");
103-
}
104-
105-
}
106-
}
107-
menu = menuBuilder.buildMenu();
108-
}
109-
110-
void WorldSelectionState::onUpdate(Context &context) {
111-
// TODO: Move this generic code to shared function or superclass.
112-
renderDevice->clearScreen();
113-
menuRenderer.renderMenu(*menu, float(context.window->width) / float(context.window->height));
114-
115-
auto input = context.inputManager;
116-
if (menu->handleInput(*context.inputManager, context.window->width, context.window->height)) {
117-
return;
118-
}
119-
120-
context.window->swapScreen();
121-
}
18+
void WorldSelectionState::onInit(Context &context) {
19+
levels = Util::FileSystem().getFilenamesInDirectory(levelDirectory);
20+
levels.erase(std::remove_if(levels.begin(), levels.end(), [](const std::string &v) {
21+
constexpr std::string_view extension = LEVEL_EXTENSION;
22+
const auto canFit = extension.size() <= v.size();
23+
const auto matchesEnd = std::equal(v.begin() + v.size() - extension.size(), v.end(), extension.begin());
24+
return !(canFit && matchesEnd);
25+
}), levels.end());
26+
27+
renderDevice = Renderer::Graphics::OpenGL::OGLRenderDevice::getRenderDevice();
28+
renderDevice->setClearColour(1.f, 1.f, 1.f, 1.f);
29+
30+
makeButtons(context);
31+
}
32+
33+
void WorldSelectionState::makeButtons(Context &context) {
34+
constexpr auto width{(2 - OUTER_MARGIN * 2) / COLUMNS - GRID_MARGIN};
35+
constexpr auto height{(1.5f - OUTER_MARGIN * 2) / ROWS - GRID_MARGIN};
36+
37+
Menu::MenuBuilder menuBuilder;
38+
menuBuilder.addControl(-0.5f, 0.5, 1, 0.24, Sprites::GAME_OVER);
39+
// TODO: Make a uniform GUI design with a standard location for this button.
40+
menuBuilder.addControl(-0.9f, 0.8, 0.3, 0.1, Sprites::BACK, [&context]() {
41+
context.stateMachine->setState<MainMenuState>(context);
42+
});
43+
44+
const auto pageCount{std::ceil(1.0 * levels.size() / pageSize) + 1};
45+
const auto pageStr{fmt::format("{: ^7}", fmt::format("{} / {}", currentPage + 1, pageCount))};
46+
menuBuilder.addTextControl(-.08f, -.95f, 0.001f, Math::Vector3f(0, 0, 0), pageStr);
47+
48+
if (currentPage > 0) {
49+
menuBuilder.addControl(-0.32f, -.95f, 0.05, 0.080, Sprites::PREVIOUS_BUTTON, [&]() {
50+
currentPage -= 1;
51+
makeButtons(context);
52+
});
53+
} else {
54+
menuBuilder.addControl(-0.32f, -.95f, 0.05, 0.080, Sprites::PREVIOUS_BUTTON_DISABLED);
55+
}
56+
57+
if (currentPage < pageCount - 1) {
58+
menuBuilder.addControl(0.24f, -.95f, 0.05, 0.080, Sprites::NEXT_BUTTON, [&]() {
59+
currentPage += 1;
60+
makeButtons(context);
61+
});
62+
} else {
63+
menuBuilder.addControl(0.24f, -.95f, 0.05, 0.080, Sprites::NEXT_BUTTON_DISABLED);
64+
}
65+
66+
67+
const int pageOffset{currentPage * COLUMNS * ROWS};
68+
// TODO: Draw these from top-left to bottom-right
69+
for (int r{0}; r < ROWS; ++r) {
70+
for (int c = 0; c < COLUMNS; ++c) {
71+
const auto levelIndex = pageOffset + r * COLUMNS + c;
72+
73+
const auto x{-1 + OUTER_MARGIN + c * (width + GRID_MARGIN)};
74+
const auto y{-1 + OUTER_MARGIN + (ROWS - 1 - r) * (height + GRID_MARGIN)};
75+
76+
if (levels.size() > levelIndex) {
77+
const auto levelName{levels[levelIndex]};
78+
const auto path{levelDirectory + '/' + levelName};
79+
std::string readableLevelName{levelName.substr(0, levelName.find(".json"))};
80+
menuBuilder.addControl(x, y, width, height, Sprites::LEVEL_SLOT_FILLED, [&context, path]() {
81+
if (context.stateMachine->hasState<PrismGame>()) {
82+
context.stateMachine->removeState<PrismGame>();
83+
}
84+
context.stateMachine->addState<PrismGame>(context, path);
85+
context.stateMachine->setState<PrismGame>(context);
86+
});
87+
readableLevelName = fmt::format("{:^13}", readableLevelName);
88+
if (readableLevelName.size() > 13)
89+
readableLevelName = readableLevelName.substr(0, 10) + "...";
90+
91+
menuBuilder.addControl(x, y, width, height, Sprites::LEVEL_SLOT_FILLED);
92+
menuBuilder.addTextControl(x + .03f, y + height / 2, 0.001, Math::Vector3f(1, 1, 1),
93+
readableLevelName);
94+
} else {
95+
menuBuilder.addControl(x, y, width, height, Sprites::LEVEL_SLOT_EMPTY);
96+
97+
menuBuilder.addControl(x + .025f, y + height / 4 + .09f, width - 0.05f, .11,
98+
Sprites::WHITE_BORDERED);
99+
100+
menuBuilder.addTextControl(x + .05f, y + height / 2, 0.001, Math::Vector3f(0, 0, 0), "Empty Slot");
101+
}
102+
103+
}
104+
}
105+
menu = menuBuilder.buildMenu();
106+
}
107+
108+
void WorldSelectionState::onUpdate(Context &context) {
109+
// TODO: Move this generic code to shared function or superclass.
110+
renderDevice->clearScreen();
111+
menuRenderer.renderMenu(*menu, float(context.window->width) / float(context.window->height));
112+
113+
if (menu->handleInput(*context.inputManager, context.window->width, context.window->height)) {
114+
return;
115+
}
116+
117+
context.window->swapScreen();
118+
}
122119

123120
}

default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ in
1414
buildInputs = [
1515
cmake
1616
freetype
17+
fmt
1718
pkgconfig
1819
SDL2
1920
SDL2_image

0 commit comments

Comments
 (0)