Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions loader/include/Geode/UI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "ui/MDTextArea.hpp"
#include "ui/Notification.hpp"
#include "ui/Popup.hpp"
#include "ui/ProgressBar.hpp"
#include "ui/SceneManager.hpp"
#include "ui/Scrollbar.hpp"
#include "ui/ScrollLayer.hpp"
Expand Down
70 changes: 70 additions & 0 deletions loader/include/Geode/ui/ProgressBar.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#pragma once

#include <cocos2d.h>

namespace geode {
// Enum for progress bar style
enum class ProgressBarStyle {
Level = 0,
Solid = 1,
};

// Custom class for the progress bar
class ProgressBar : public cocos2d::CCNode {
protected:
class Impl;
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


bool init() override;

public:
// Create a custom progress bar
static ProgressBar* create();

/**
* Set the style of the progress bar
*
* @param style Style to switch to
*/
void setStyle(ProgressBarStyle style);

/**
* Set the color of the fill of the bar
*
* @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


/**
* Update the size of the fill of the bar
*
* @param value A float from 0 to 100
*/
virtual void updateProgress(float value);

/**
* Get the current progress percentage of the bar
*/
float getProgress() const;

/**
* Get the progress percentage text label node
*/
CCLabelBMFont* getProgressLabel() const;

/**
* 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


/**
* Show the label displaying the current percentage of progress
*
* @param bool Whether to toggle visibility
*/
void showProgressLabel(bool show);
};
}
162 changes: 162 additions & 0 deletions loader/src/ui/nodes/ProgressBar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include <cocos2d.h>
#include <Geode/ui/ProgressBar.hpp>

using namespace geode::prelude;

class ProgressBar::Impl final {
public:
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

};

ProgressBar::ProgressBar() {
m_impl = std::make_unique<Impl>();
};

ProgressBar::~ProgressBar() {};

bool ProgressBar::init() {
if (!CCNode::init()) return false;

switch (m_impl->style) {
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;
}

break;

case ProgressBarStyle::Solid:
m_impl->progressBar = CCSprite::create("GJ_progressBar_001.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->setColor({ 0, 0, 0 });
m_impl->progressBar->setOpacity(125);
m_impl->progressBar->setZOrder(-1);

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

m_impl->progressBarFillMaxWidth = m_impl->progressBar->getScaledContentWidth();
m_impl->progressBarFillMaxHeight = 20.0f;

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.5, 0.5 });
m_impl->progressPercentLabel->setPosition({ m_impl->progressBar->getScaledContentWidth() / 2.0f, m_impl->progressBar->getScaledContentHeight() / 2.0f });
m_impl->progressPercentLabel->setAlignment(CCTextAlignment::kCCTextAlignmentCenter);
m_impl->progressPercentLabel->setVisible(m_impl->showProgressPercentLabel);
m_impl->progressPercentLabel->setZOrder(1);
break;
};

this->setScaledContentSize(m_impl->progressBar->getScaledContentSize());

m_impl->progressBar->addChild(m_impl->progressBarFill);

this->addChild(m_impl->progressBar);
this->addChild(m_impl->progressPercentLabel);

this->updateProgress(m_impl->progress);

return true;
};

void ProgressBar::setStyle(ProgressBarStyle style) {
if (m_impl->style != style) {
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 😟

};
};

void ProgressBar::setProgressBarFillColor(ccColor3B color) {
m_impl->progressBarFillColor = color;
if (m_impl->progressBarFill) m_impl->progressBarFill->setColor(color);
};

void ProgressBar::updateProgress(float value) {
if (value > 100.0f) value = 100.0f;
if (value < 0.0f) value = 0.0f;

m_impl->progress = value;

if (m_impl->progressBarFill) {
float width = m_impl->progressBarFillMaxWidth * (m_impl->progress / 100.0f);
m_impl->progressBarFill->setTextureRect({ 0.0f, 0.0f, width, m_impl->progressBarFillMaxHeight });
};

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

m_impl->progressPercentLabel->setCString(percentString.c_str());
};
};

float ProgressBar::getProgress() const {
return m_impl->progress;
};

CCLabelBMFont* ProgressBar::getProgressLabel() const {
return m_impl->progressPercentLabel;
};

ProgressBarStyle ProgressBar::getProgressBarStyle() const {
return m_impl->style;
};

void ProgressBar::showProgressLabel(bool show) {
m_impl->showProgressPercentLabel = show;
if (m_impl->progressPercentLabel) m_impl->progressPercentLabel->setVisible(show);
};

ProgressBar* ProgressBar::create() {
auto ret = new ProgressBar();

if (ret && ret->init()) {
ret->autorelease();
return ret;
};

delete ret;
return nullptr;
};