Skip to content

Conversation

BlueWitherer
Copy link

@BlueWitherer BlueWitherer commented Aug 16, 2025

Since the base game doesn't use a class to create its progress bar UI, I would like to propose a helper class that I wrote that can help developers easily re-create them without having to use and set up the sprites and set the texture rects themselves.

ProgressBar

This class creates a progress bar. It can mimic the style of the progress bar shown while playing a level, or the style of the Normal/Practice mode progress bars shown when looking at your current best progress in the level. It inherits cocos2d::CCNode.

static ProgressBar* create(); // Create the custom progress bar

void setStyle(ProgressBarStyle style); // Set the style of the progress bar
void setProgressBarFillColor(ccColor3B color); // Set the color of the fill of the bar

virtual void updateProgress(float value); // Update the size of the fill of the bar

float getProgress() const; // Get the current progress percentage of the bar
CCLabelBMFont* getProgressLabel() const; // Get the progress percentage text label node
ProgressBarStyle getProgressBarStyle() const; // Get the current style of the progress bar

void showProgressLabel(bool show); // Show the label displaying the current percentage of progress
Example
auto bar = ProgressBar::create();
bar->setProgressBarFillColor({100, 100, 255});
bar->setStyle(ProgressBarStyle::Solid);
bar->showProgressLabel(false); // Don't show percentage text

bar->updateProgress(20.5f); // Sets to 20.5% full

this->addChild(bar);

progresstest.mp4

@BlueWitherer BlueWitherer marked this pull request as ready for review August 16, 2025 12:44
Copy link
Member

@HJfod HJfod left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for this PR! Left a few comments & fix suggestions, but looking good overall :)

Comment on lines 9 to 15
Ref<CCSprite> m_progressBar = nullptr; // Progress bar outline
CCSprite* m_progressBarFill = nullptr; // Progress bar fill

float m_progress = 0.f; // Current progress bar fill percentage ranging from 0 to 100

float m_progressBarFillMaxWidth = 0.f; // Max width for the progress fill bar node
float m_progressBarFillMaxHeight = 0.f; // Max height for the progress fill bar node
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class members should be PIMPL; aka these should be behind a source-defined Impl class and std::unique_ptr<Impl> m_impl. See other Geode classes for examples

@BlueWitherer
Copy link
Author

appreciate the feedback! i've made adjustments based on what you mentioned and asked for - lmk if anything else could use further tweaking :D

@BlueWitherer BlueWitherer changed the title Progress bar helper classes Progress bar helper class Sep 1, 2025
@BlueWitherer BlueWitherer requested a review from HJfod September 1, 2025 22:33
*
* @param color RGB color object
*/
void setProgressBarFillColor(ccColor3B color);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally just setFillColor is enough

/**
* Get the current style of the progress bar
*/
ProgressBarStyle getProgressBarStyle() const;
Copy link
Member

@matcool matcool Sep 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should just be getStyle, like how setStyle is

Comment on lines 8 to 20
Ref<CCSprite> progressBar = nullptr; // Progress bar outline
CCSprite* progressBarFill = nullptr; // Progress bar fill
CCLabelBMFont* progressPercentLabel = nullptr; // The text label displaying the percentage

float progress = 0.0f; // Current progress bar fill percentage ranging from 0 to 100

ccColor3B progressBarFillColor = { 255, 255, 255 }; // Current color of the filled progress bar
bool showProgressPercentLabel = false; // Whether to show the label showing the percentage of the current progress

ProgressBarStyle style = ProgressBarStyle::Level; // Style of the progress bar

float progressBarFillMaxWidth = 0.0f; // Max width for the progress fill bar node
float progressBarFillMaxHeight = 0.0f; // Max height for the progress fill bar node
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo comments should be on the line before, not at the end of the line

m_impl->style = style;

this->removeAllChildren();
init(); // init again with new style
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

calling CCNode::init multiple times 😟

@BlueWitherer
Copy link
Author

sorry about all that, hopefully this fixes it!

Copy link
Member

@HJfod HJfod left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, don't have any major complaints, just some styling suggestions! Tyvm for this PR!

std::unique_ptr<Impl> m_impl;

ProgressBar();
~ProgressBar();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The destructor should be marked virtual

Comment on lines 39 to 63
case ProgressBarStyle::Level:
m_impl->progressBar = CCSprite::create("slidergroove2.png");
m_impl->progressBar->setID("progress-bar");
m_impl->progressBar->setAnchorPoint({ 0.5, 0.5 });
m_impl->progressBar->setPosition({ m_impl->progressBar->getScaledContentWidth() / 2.0f, m_impl->progressBar->getScaledContentHeight() / 2.0f });
m_impl->progressBar->setZOrder(1);

m_impl->progressBarFill = CCSprite::create("sliderBar2.png");
m_impl->progressBarFill->setID("progress-bar-fill");
m_impl->progressBarFill->setAnchorPoint({ 0, 0.5 });
m_impl->progressBarFill->setPosition({ 2.0f, m_impl->progressBar->getScaledContentHeight() / 2.0f });
m_impl->progressBarFill->setColor(m_impl->progressBarFillColor);
m_impl->progressBarFill->setZOrder(-1);

m_impl->progressBarFillMaxWidth = m_impl->progressBar->getScaledContentWidth() - 4.0f;
m_impl->progressBarFillMaxHeight = m_impl->progressBarFill->getScaledContentHeight() - 0.5f;

m_impl->progressPercentLabel = CCLabelBMFont::create("0%", "bigFont.fnt");
m_impl->progressPercentLabel->setID("progress-percent-label");
m_impl->progressPercentLabel->setScale(0.5f);
m_impl->progressPercentLabel->setAnchorPoint({ 0, 0.5 });
m_impl->progressPercentLabel->setPosition({ m_impl->progressBar->getScaledContentWidth() + 2.5f, m_impl->progressBar->getScaledContentHeight() / 2.0f });
m_impl->progressPercentLabel->setAlignment(CCTextAlignment::kCCTextAlignmentLeft);
m_impl->progressPercentLabel->setVisible(m_impl->showProgressPercentLabel);
m_impl->progressPercentLabel->setZOrder(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a styling thing but I would indent this whole thing one tab and then surround the block with braces, like so:

switch (x) {
    case y: {
        // code here...
    } break;
}

ProgressBar();
~ProgressBar();

void customSetup();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to call functions like this reload or reloadStyle instead to make it clear that it may (and should) be called multiple times

};

if (m_impl->progressPercentLabel) {
auto percentString = fmt::format("{}%", static_cast<int>(m_impl->progress));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably use geode::utils::numToString with a precision of 0. The class should probably also have a way to customize the precision of the percentage

@BlueWitherer
Copy link
Author

happy to contribute! hopefully i've made this as best as it could possibly be!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants