Skip to content

Commit 1de972a

Browse files
committed
Updateed docs for SagoLogicalResize and ran astyle for the rest
1 parent 3dd1e2f commit 1de972a

File tree

9 files changed

+155
-38
lines changed

9 files changed

+155
-38
lines changed

source/code/HelpGamepadState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void HelpGamepadState::ProcessInput(const SDL_Event& event, bool& processed) {
6767

6868
#define OFFSETX (-512+globalData.xsize/2)
6969

70-
static void RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) {
70+
static void RenderDrawLine(SDL_Renderer* renderer, int x1, int y1, int x2, int y2) {
7171
globalData.logicalResize.LogicalToPhysical(&x1, &y1);
7272
globalData.logicalResize.LogicalToPhysical(&x2, &y2);
7373
SDL_RenderDrawLine(renderer, x1, y1, x2, y2);

source/code/HelpHowtoState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ HelpHowtoState::~HelpHowtoState() {
131131

132132
const double PI =3.141592653589793238463;
133133

134-
static void RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2) {
134+
static void RenderDrawLine(SDL_Renderer* renderer, int x1, int y1, int x2, int y2) {
135135
globalData.logicalResize.LogicalToPhysical(&x1, &y1);
136136
globalData.logicalResize.LogicalToPhysical(&x2, &y2);
137137
SDL_RenderDrawLine(renderer, x1, y1, x2, y2);

source/code/SagoImGui.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ void InitImGui(SDL_Window* window, SDL_Renderer* renderer, int width, int height
2929
// Setup Dear ImGui context
3030
IMGUI_CHECKVERSION();
3131
ImGui::CreateContext();
32-
ImGuiIO& io = ImGui::GetIO(); (void)io;
32+
ImGuiIO& io = ImGui::GetIO();
33+
(void)io;
3334
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
3435
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
3536
io.DisplaySize.x = static_cast<float>(width);

source/code/highscore.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ Highscore::Highscore(const std::string& type, double speed) : filename(type+".js
5858
json j = json::parse(readFileContent);
5959
try {
6060
j.at("highscore").get_to(table);
61-
} catch (json::exception& e) {
61+
}
62+
catch (json::exception& e) {
6263
std::cerr << "Failed to read highscore " << filename << " due to formatting errors. Resetting the file. Reason: " <<
6364
e.what() << "\n";
6465
table.clear();

source/code/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1761,7 +1761,7 @@ int runGame(Gametype gametype, int level) {
17611761
bool pressed = false;
17621762
int x = 0;
17631763
int y = 0;
1764-
1764+
17651765
theGame.GetBrickCoordinateFromMouse(pressed, mousex, mousey, x, y);
17661766
if (pressed) {
17671767
a.action = BlockGameAction::Action::MOUSE_DOWN;

source/code/puzzlehandler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ void LoadClearData() {
9696
json j = json::parse(readFileContent);
9797
try {
9898
j.at("cleared").get_to(puzzleCleared);
99-
} catch (json::exception& e) {
99+
}
100+
catch (json::exception& e) {
100101
std::cerr << "Failed to read \"" << puzzleSavePath << "\". File will be regenerated. Reason: " << e.what() << "\n";
101102
puzzleCleared.clear();
102103
}
@@ -180,8 +181,7 @@ void EditorAddPuzzle(size_t level) {
180181
if (nrOfPuzzles >= maxNrOfPuzzleStages) {
181182
return;
182183
}
183-
if (level >= maxNrOfPuzzleStages)
184-
{
184+
if (level >= maxNrOfPuzzleStages) {
185185
level = 0;
186186
}
187187
memmove( puzzleLevels[level+1], puzzleLevels[level], sizeof(puzzleLevels[0])*(maxNrOfPuzzleStages-level-1) );

source/code/sago/SagoLogicalResize.hpp

Lines changed: 140 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,30 +29,99 @@ SOFTWARE.
2929

3030
namespace sago {
3131

32-
class SagoLogicalResize
33-
{
32+
/**
33+
* @brief Provides coordinate transformation between logical and physical screen coordinates.
34+
*
35+
* This class helps create resolution-independent layouts by defining coordinates in a fixed
36+
* "logical" resolution and automatically converting them to the actual "physical" screen size.
37+
* It maintains aspect ratio by adding letterboxing/pillarboxing margins when needed.
38+
*
39+
* Key concepts:
40+
* - Logical coordinates: Fixed coordinate system you design for (e.g., 1920x1080)
41+
* - Physical coordinates: Actual screen/window size (e.g., 1280x720, 3840x2160, etc.)
42+
* - Scale factor: Calculated to fit logical size into physical size while preserving aspect ratio
43+
* - Margins: Black bars added to maintain aspect ratio (letterboxing/pillarboxing)
44+
* - Tile alignment: As long as tiles are resized with LogicalToPhysical, they will align correctly. No gaps or overlaps.
45+
*
46+
* Example usage:
47+
* @code
48+
* // Design your UI for 1920x1080
49+
* SagoLogicalResize resize(1920, 1080);
50+
* resize.SetPhysicalSize(window_width, window_height);
51+
*
52+
* // Draw at logical position (100, 100)
53+
* int phys_x, phys_y;
54+
* resize.LogicalToPhysical(100, 100, phys_x, phys_y);
55+
* DrawSprite(renderer, phys_x, phys_y);
56+
*
57+
* // Handle mouse input
58+
* int log_x, log_y;
59+
* resize.PhysicalToLogical(mouse_x, mouse_y, log_x, log_y);
60+
* if (log_x > 100 && log_x < 200) { ... }
61+
* @endcode
62+
*/
63+
class SagoLogicalResize {
3464
public:
35-
SagoLogicalResize() : logical_width_(1), logical_height_(1), physical_width_(1), physical_height_(1) { SetScaleFactor(); }
65+
/**
66+
* @brief Default constructor with minimal 1x1 logical size.
67+
*/
68+
SagoLogicalResize() : logical_width_(1), logical_height_(1), physical_width_(1), physical_height_(1) {
69+
SetScaleFactor();
70+
}
71+
72+
/**
73+
* @brief Constructor with specified logical resolution.
74+
* @param logical_width The width of the logical coordinate system (minimum 1)
75+
* @param logical_height The height of the logical coordinate system (minimum 1)
76+
*/
3677
SagoLogicalResize(int logical_width, int logical_height)
37-
: logical_width_(std::max(1, logical_width)), logical_height_(std::max(1, logical_height)), physical_width_(1), physical_height_(1) { SetScaleFactor(); }
78+
: logical_width_(std::max(1, logical_width)), logical_height_(std::max(1, logical_height)), physical_width_(1), physical_height_(1) {
79+
SetScaleFactor();
80+
}
3881

39-
void SetPhysicalSize(int physical_width, int physical_height)
40-
{
82+
/**
83+
* @brief Updates the physical (actual) screen size and recalculates scaling.
84+
*
85+
* Call this when the window is resized or when initializing the physical display size.
86+
* This recalculates the scale factor and margins to fit the logical size into the physical size.
87+
*
88+
* @param physical_width The actual width of the screen/window (minimum 1)
89+
* @param physical_height The actual height of the screen/window (minimum 1)
90+
*/
91+
void SetPhysicalSize(int physical_width, int physical_height) {
4192
//Physical size must be at least 1. Less than 1 is not drawn anyway and it prevents division by zero.
4293
physical_width_ = std::max(1, physical_width);
4394
physical_height_ = std::max(1, physical_height);
4495
SetScaleFactor();
4596
}
4697

47-
void LogicalToPhysical(int logical_x, int logical_y, int &physical_x, int &physical_y) const
48-
{
98+
/**
99+
* @brief Converts logical coordinates to physical screen coordinates.
100+
*
101+
* This applies the scale factor and adds the appropriate margins.
102+
* Use this to convert positions where you want to draw elements on screen.
103+
*
104+
* @param logical_x The x coordinate in logical space
105+
* @param logical_y The y coordinate in logical space
106+
* @param physical_x Output: the x coordinate in physical screen space
107+
* @param physical_y Output: the y coordinate in physical screen space
108+
*/
109+
void LogicalToPhysical(int logical_x, int logical_y, int& physical_x, int& physical_y) const {
49110
physical_x = logical_x;
50111
physical_y = logical_y;
51112
LogicalToPhysical(&physical_x, &physical_y);
52113
}
53114

54-
void LogicalToPhysical(int *x, int *y) const
55-
{
115+
/**
116+
* @brief Converts logical coordinates to physical screen coordinates (pointer version).
117+
*
118+
* This applies the scale factor and adds the appropriate margins.
119+
* Null pointers are safely ignored.
120+
*
121+
* @param x Pointer to x coordinate (will be converted in place), can be null
122+
* @param y Pointer to y coordinate (will be converted in place), can be null
123+
*/
124+
void LogicalToPhysical(int* x, int* y) const {
56125
if (x) {
57126
*x = *x * scale_factor_ + left_margin_;
58127
}
@@ -61,46 +130,90 @@ class SagoLogicalResize
61130
}
62131
}
63132

64-
void LogicalToPhysical(SDL_Rect &inout) const
65-
{
133+
/**
134+
* @brief Converts a logical rectangle to physical screen coordinates.
135+
*
136+
* This converts both the position AND size of a rectangle. The rectangle
137+
* is transformed in place. Use this for converting areas/regions rather than
138+
* just single points.
139+
*
140+
* Note: This properly handles the size conversion by converting the bottom-right
141+
* corner and calculating the new width/height from the difference.
142+
*
143+
* @param inout The rectangle in logical coordinates (input), converted to physical coordinates (output)
144+
*/
145+
void LogicalToPhysical(SDL_Rect& inout) const {
66146
SDL_Rect input = inout;
67147
LogicalToPhysical(&inout.x, &inout.y);
68148
LogicalToPhysical(input.x + input.w + 1, input.y + input.h + 1, inout.w, inout.h);
69149
inout.w -= inout.x - 1;
70150
inout.h -= inout.y - 1;
71151
}
72152

73-
void PhysicalToLogical(int physical_x, int physical_y, int &logical_x, int &logical_y) const
74-
{
153+
/**
154+
* @brief Converts physical screen coordinates to logical coordinates.
155+
*
156+
* Use this to convert mouse input or other physical positions back to your
157+
* logical coordinate system for hit detection and input handling.
158+
* This removes margins and applies inverse scaling.
159+
*
160+
* @param physical_x The x coordinate in physical screen space
161+
* @param physical_y The y coordinate in physical screen space
162+
* @param logical_x Output: the x coordinate in logical space
163+
* @param logical_y Output: the y coordinate in logical space
164+
*/
165+
void PhysicalToLogical(int physical_x, int physical_y, int& logical_x, int& logical_y) const {
75166
logical_x = (physical_x - left_margin_) / scale_factor_;
76167
logical_y = (physical_y - top_margin_) / scale_factor_;
77168
}
78169

79-
int GetTopMargin() const
80-
{
170+
/**
171+
* @brief Gets the top margin (letterboxing/pillarboxing offset).
172+
*
173+
* This is the black bar size at the top when the aspect ratio requires vertical margins.
174+
* Useful for debugging or custom rendering that needs to know the drawable area.
175+
*
176+
* @return The top margin in physical pixels
177+
*/
178+
int GetTopMargin() const {
81179
return top_margin_;
82180
}
83181

84-
int GetLeftMargin() const
85-
{
182+
/**
183+
* @brief Gets the left margin (letterboxing/pillarboxing offset).
184+
*
185+
* This is the black bar size on the left when the aspect ratio requires horizontal margins.
186+
* Useful for debugging or custom rendering that needs to know the drawable area.
187+
*
188+
* @return The left margin in physical pixels
189+
*/
190+
int GetLeftMargin() const {
86191
return left_margin_;
87192
}
88193

89194
private:
90-
void SetScaleFactor()
91-
{
195+
/**
196+
* @brief Calculates the scale factor and margins based on current logical and physical sizes.
197+
*
198+
* The scale factor is chosen to fit the logical size into the physical size while
199+
* maintaining aspect ratio. The margins center the content on screen.
200+
*
201+
* Scale factor = min(physical_width/logical_width, physical_height/logical_height)
202+
* This ensures the content fits in both dimensions without distortion.
203+
*/
204+
void SetScaleFactor() {
92205
scale_factor_ = std::min(physical_width_ / logical_width_, physical_height_ / logical_height_);
93206
left_margin_ = (physical_width_ - logical_width_ * scale_factor_) / 2;
94207
top_margin_ = (physical_height_ - logical_height_ * scale_factor_) / 2;
95208
}
96209

97-
double scale_factor_;
98-
int top_margin_;
99-
int left_margin_;
100-
double logical_width_;
101-
double logical_height_;
102-
double physical_width_;
103-
double physical_height_;
210+
double scale_factor_; ///< Multiplier to convert logical size to physical size
211+
int top_margin_; ///< Vertical offset for centering (letterboxing)
212+
int left_margin_; ///< Horizontal offset for centering (pillarboxing)
213+
double logical_width_; ///< Width of the logical coordinate system
214+
double logical_height_; ///< Height of the logical coordinate system
215+
double physical_width_; ///< Actual width of the screen/window
216+
double physical_height_; ///< Actual height of the screen/window
104217
};
105218

106219
} // namespace sago

source/code/stageclearhandler.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ void LoadStageClearStages() {
8585
json j = json::parse(readFileContent);
8686
try {
8787
j.at("stages").get_to(stages);
88-
} catch (json::exception& e) {
88+
}
89+
catch (json::exception& e) {
8990
std::cerr << "Failed to read highscore " << stageClearSaveName << " due to formatting errors. Resetting the file. Reason: " <<
9091
e.what() << "\n";
9192
stages.clear();
@@ -98,7 +99,8 @@ void LoadStageClearStages() {
9899
json j = json::parse(readFileContent);
99100
try {
100101
j.at("stages").get_to(parScores);
101-
} catch (json::exception& e) {
102+
}
103+
catch (json::exception& e) {
102104
std::cerr << "Failed to read par times. Reason: " << e.what() << "\n";
103105
}
104106
stages.resize(nrOfStageLevels);

source/code/themes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ static size_t current_theme = 0;
138138

139139

140140
void ThemesFillMissingFields(Theme& theme) {
141-
if (theme.background.name.empty() || !ThemesBackgroundExists(theme.background.name) ){
141+
if (theme.background.name.empty() || !ThemesBackgroundExists(theme.background.name) ) {
142142
//If the theme does not define a background then use the standard.
143143
theme.background.name = "standard";
144144
}

0 commit comments

Comments
 (0)