Skip to content

Commit 437db76

Browse files
committed
label for unused options
1 parent ef011ee commit 437db76

6 files changed

Lines changed: 124 additions & 44 deletions

File tree

include/Horrible.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
struct HorribleOptionSave final {
1818
bool enabled = false;
1919
bool pin = false;
20-
unsigned int chance = 0;
21-
int64_t min = 0;
22-
int64_t max = 1;
20+
bool viewed = false;
2321
};
2422

2523
template <>
@@ -99,6 +97,15 @@ namespace horrible {
9997
*/
10098
[[nodiscard]] bool isPinned(std::string_view id) const;
10199

100+
/**
101+
* Quickly check the viewed state of an option
102+
*
103+
* @param id The ID of the option to check
104+
*
105+
* @returns Boolean of the current value
106+
*/
107+
[[nodiscard]] bool isViewed(std::string_view id) const;
108+
102109
/**
103110
* Get the saved data of an option
104111
*
@@ -140,8 +147,9 @@ namespace horrible {
140147
* @param id The ID of the option to toggle
141148
* @param enable Boolean to toggle to
142149
* @param pin If this option is pinned by the user
150+
* @param viewed If this option was already viewed by the user
143151
*/
144-
void setOption(geode::ZStringView id, bool enable, bool pin = false);
152+
void setOption(geode::ZStringView id, bool enable, bool pin = false, bool viewed = true);
145153

146154
/**
147155
* Upsert a new hook delegate

src/hooks/Placebo.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ void placeboEffect() {
2727
log::info("Placebo effect activated! Toggling all options...");
2828

2929
for (auto const& option : options::getAll()) {
30-
auto toggle = options::isEnabled(option.getID());
31-
log::debug("Placebo {} option {}", toggle ? "disabled" : "enabled", option.getID());
32-
options::set(option.getID(), !toggle);
30+
auto saved = options::get(option.getID());
31+
log::debug("Placebo {} option {}", saved.enabled ? "enabled" : "disabled", option.getID());
32+
options::set(option.getID(), !saved.enabled, saved.pin, saved.viewed);
3333
};
3434
};
3535
};

src/include/Horrible.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,16 @@ using namespace horrible;
1212
Result<HorribleOptionSave> matjson::Serialize<HorribleOptionSave>::fromJson(matjson::Value const& value) {
1313
GEODE_UNWRAP_INTO(bool enabled, value["enabled"].asBool());
1414
GEODE_UNWRAP_INTO(bool pin, value["pin"].asBool());
15-
GEODE_UNWRAP_INTO(unsigned int chance, value["chance"].asUInt());
16-
GEODE_UNWRAP_INTO(int64_t min, value["min"].asInt());
17-
GEODE_UNWRAP_INTO(int64_t max, value["max"].asInt());
15+
GEODE_UNWRAP_INTO(bool viewed, value["viewed"].asBool());
1816

19-
return Ok(HorribleOptionSave{enabled, pin, chance, min, max});
17+
return Ok(HorribleOptionSave{enabled, pin, viewed});
2018
};
2119

2220
matjson::Value matjson::Serialize<HorribleOptionSave>::toJson(HorribleOptionSave const& value) {
2321
auto obj = matjson::Value();
2422
obj["enabled"] = value.enabled;
2523
obj["pin"] = value.pin;
26-
obj["chance"] = value.chance;
27-
obj["min"] = value.min;
28-
obj["max"] = value.max;
24+
obj["viewed"] = value.viewed;
2925

3026
return obj;
3127
};
@@ -141,6 +137,10 @@ bool OptionManager::isPinned(std::string_view id) const {
141137
return getOption(id).pin;
142138
};
143139

140+
bool OptionManager::isViewed(std::string_view id) const {
141+
return getOption(id).viewed;
142+
};
143+
144144
HorribleOptionSave OptionManager::getOption(std::string_view id) const {
145145
return Mod::get()->getSavedValue<HorribleOptionSave>(id);
146146
};
@@ -165,15 +165,15 @@ void OptionManager::toggleOption(ZStringView id, bool enable) {
165165
setOption(id, enable, isPinned(id));
166166
};
167167

168-
void OptionManager::setOption(ZStringView id, bool enable, bool pin) {
168+
void OptionManager::setOption(ZStringView id, bool enable, bool pin, bool viewed) {
169169
auto it = m_delegates.find(id);
170170
if (it != m_delegates.end()) {
171171
for (auto& cb : it->second) cb(enable);
172172
};
173173

174174
log::trace("Called {} delegates {} for option {}", it != m_delegates.end() ? it->second.size() : 0, enable ? "on" : "off", id);
175175

176-
auto save = HorribleOptionSave{enable, pin};
176+
auto save = HorribleOptionSave{enable, pin, viewed};
177177

178178
(void)Mod::get()->setSavedValue(id, save);
179179
(void)OptionEvent(id).send(std::move(save));

src/menu/src/OptionItem.cpp

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ class OptionItem::Impl final {
1616

1717
CCMenuItemToggler* toggler = nullptr; // The toggler for the option
1818

19+
CCNode* newContainer = nullptr;
20+
1921
// Save the current state of the toggler as the option state
2022
void saveTogglerState() {
21-
if (toggler) options::set(option.getID(), toggler->isToggled(), options::isPinned(option.getID()));
23+
auto saved = options::get(option.getID());
24+
if (toggler) options::set(option.getID(), toggler->isToggled(), saved.pin, saved.viewed);
25+
26+
clearNewLabel();
2227
};
2328

2429
// Notify the user if this option is not compatible for their current platform
@@ -29,6 +34,10 @@ class OptionItem::Impl final {
2934
};
3035
};
3136

37+
void clearNewLabel() {
38+
if (auto label = WeakRef(newContainer).lock()) label->setVisible(false);
39+
};
40+
3241
constexpr const char* getTierDescString(SillyTier silly, bool compat) noexcept {
3342
if (!compat) return "<cp>OPTION UNAVAILABLE</c>";
3443

@@ -134,22 +143,10 @@ bool OptionItem::init(CCSize const& size, Option option, bool devMode) {
134143
addChild(nameLabel);
135144
addChild(categoryLabel);
136145

137-
if (devMode) {
138-
auto str = fmt::format("{} | {} delegate(s)", m_impl->option.getID(), options::getDelegates(m_impl->option.getID()));
139-
140-
auto idLabel = CCLabelBMFont::create(str.c_str(), "chatFont.fnt", getScaledContentWidth() - 20.f, kCCTextAlignmentLeft);
141-
idLabel->setID("id-label");
142-
idLabel->setLineBreakWithoutSpace(true);
143-
idLabel->setPosition({x, yCenter - 10.f});
144-
idLabel->setAnchorPoint({0.f, 0.5f});
145-
idLabel->setColor(colors::black);
146-
idLabel->setOpacity(125);
147-
idLabel->setScale(0.5f);
148-
149-
addChild(idLabel);
150-
};
151-
152-
auto menuLayout = RowLayout::create()->setGap(5.f)->setAxisReverse(true)->setAutoGrowAxis(0.f);
146+
auto menuLayout = RowLayout::create()
147+
->setGap(5.f)
148+
->setAxisReverse(true)
149+
->setAutoGrowAxis(0.f);
153150

154151
auto menu = CCMenu::create();
155152
menu->setID("menu");
@@ -161,7 +158,7 @@ bool OptionItem::init(CCSize const& size, Option option, bool devMode) {
161158
addChild(menu);
162159

163160
// info button
164-
auto helpBtn = Button::createWithSpriteFrameName(
161+
auto infoBtn = Button::createWithSpriteFrameName(
165162
m_impl->compatible ? "GJ_infoIcon_001.png" : "geode.loader/info-alert.png",
166163
[this](Button*) {
167164
m_impl->notifyIncompat();
@@ -175,11 +172,17 @@ bool OptionItem::init(CCSize const& size, Option option, bool devMode) {
175172
"OK",
176173
nullptr,
177174
375.f)) popup->show();
175+
176+
auto saved = options::get(m_impl->option.getID());
177+
if (!saved.viewed) {
178+
options::set(m_impl->option.getID(), saved.enabled, saved.pin, true);
179+
m_impl->clearNewLabel();
180+
};
178181
});
179-
helpBtn->setID("help-btn");
180-
helpBtn->setScale(0.625f);
182+
infoBtn->setID("info-btn");
183+
infoBtn->setScale(0.625f);
181184

182-
menu->addChild(helpBtn);
185+
menu->addChild(infoBtn);
183186

184187
// @geode-ignore(unknown-resource)
185188
auto pinOff = CCSprite::createWithSpriteFrameName("geode.loader/pin.png");
@@ -202,6 +205,36 @@ bool OptionItem::init(CCSize const& size, Option option, bool devMode) {
202205

203206
menu->updateLayout();
204207

208+
auto newContainerLayout = RowLayout::create()
209+
->setGap(1.25f)
210+
->setAutoScale(false)
211+
->setAutoGrowAxis(0.f);
212+
213+
m_impl->newContainer = CCNode::create();
214+
m_impl->newContainer->setID("new-option-container");
215+
m_impl->newContainer->setAnchorPoint({0, 0.5});
216+
m_impl->newContainer->setPosition({x, 5.25f});
217+
m_impl->newContainer->setLayout(newContainerLayout);
218+
219+
addChild(m_impl->newContainer, 9);
220+
221+
auto newIcon = CCSprite::createWithSpriteFrameName("geode.loader/updates-available.png");
222+
newIcon->setID("new-option-icon");
223+
newIcon->setScale(0.25f);
224+
225+
auto newLabel = CCLabelBMFont::create("New!", "bigFont.fnt");
226+
newLabel->setID("new-option-label");
227+
newLabel->setScale(0.25f);
228+
newLabel->setColor(colors::cyan);
229+
230+
m_impl->newContainer->addChild(newIcon);
231+
m_impl->newContainer->addChild(newLabel);
232+
233+
m_impl->newContainer->updateLayout();
234+
235+
m_impl->newContainer->setVisible(!options::isViewed(m_impl->option.getID()));
236+
m_impl->newContainer->setScale(0.75f);
237+
205238
if (!m_impl->compatible) {
206239
m_impl->toggler->toggle(false);
207240

@@ -218,21 +251,39 @@ bool OptionItem::init(CCSize const& size, Option option, bool devMode) {
218251
m_impl->saveTogglerState();
219252
};
220253

254+
if (devMode) {
255+
auto str = fmt::format("{} | {} delegate(s)", m_impl->option.getID(), options::getDelegates(m_impl->option.getID()));
256+
257+
auto idLabel = CCLabelBMFont::create(str.c_str(), "chatFont.fnt", getScaledContentWidth() - 20.f, kCCTextAlignmentLeft);
258+
idLabel->setID("id-label");
259+
idLabel->setLineBreakWithoutSpace(true);
260+
idLabel->setPosition({getScaledContentWidth() - 7.5f, 5.25f});
261+
idLabel->setAnchorPoint({1, 0.5});
262+
idLabel->setColor(colors::black);
263+
idLabel->setOpacity(125);
264+
idLabel->setScale(0.5f);
265+
266+
addChild(idLabel);
267+
};
268+
221269
return true;
222270
};
223271

224272
void OptionItem::onToggle(CCObject*) {
225273
if (m_impl->toggler && m_impl->compatible) {
226274
auto now = !m_impl->toggler->isToggled();
227275

228-
options::set(m_impl->option.getID(), now, options::isPinned(m_impl->option.getID()));
276+
auto saved = options::get(m_impl->option.getID());
277+
options::set(m_impl->option.getID(), now, saved.pin, true);
229278

230279
if (m_impl->option.isRestartRequired()) {
231280
Notification::create("Restart required!", NotificationIcon::Warning, 2.5f)->show();
232281
log::warn("Restart required to apply option {}", m_impl->option.getID());
233282
};
234283

235284
log::info("Option {} now set to {}", m_impl->option.getName(), now ? "enabled" : "disabled");
285+
286+
m_impl->clearNewLabel();
236287
} else if (m_impl->toggler) {
237288
m_impl->notifyIncompat();
238289

@@ -242,14 +293,20 @@ void OptionItem::onToggle(CCObject*) {
242293

243294
void OptionItem::onPin(CCObject* sender) {
244295
if (auto pinBtn = typeinfo_cast<CCMenuItemToggler*>(sender)) {
245-
options::set(m_impl->option.getID(), options::isEnabled(m_impl->option.getID()), !pinBtn->isToggled());
296+
options::set(m_impl->option.getID(), options::isEnabled(m_impl->option.getID()), !pinBtn->isToggled(), true);
246297
PinEvent().send();
298+
299+
m_impl->clearNewLabel();
247300
};
248301
};
249302

250-
Option const& OptionItem::getOption() const noexcept { return m_impl->option; };
303+
Option const& OptionItem::getOption() const noexcept {
304+
return m_impl->option;
305+
};
251306

252-
bool OptionItem::isCompatible() const noexcept { return m_impl->compatible; };
307+
bool OptionItem::isCompatible() const noexcept {
308+
return m_impl->compatible;
309+
};
253310

254311
OptionItem* OptionItem::create(CCSize const& size, Option option, bool devMode) {
255312
auto ret = new OptionItem();

src/util/Options.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ namespace horrible {
3333
*/
3434
bool isPinned(std::string_view id);
3535

36+
/**
37+
* Quickly check the viewed state of an option
38+
*
39+
* @param id The ID of the option to check
40+
*
41+
* @returns Boolean of the current value
42+
*/
43+
bool isViewed(std::string_view id);
44+
3645
/**
3746
* Returns the chance value for an option
3847
*
@@ -57,8 +66,9 @@ namespace horrible {
5766
* @param id The ID of the option to toggle
5867
* @param enable Boolean to toggle to
5968
* @param pin If this option is pinned by the user
69+
* @param viewed If this option was already viewed by the user
6070
*/
61-
void set(geode::ZStringView id, bool enable, bool pin = false);
71+
void set(geode::ZStringView id, bool enable, bool pin = false, bool viewed = true);
6272

6373
/**
6474
* Returns the amount of delegate callbacks registered for an option

src/util/src/Options.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ bool options::isPinned(std::string_view id) {
2020
return false;
2121
};
2222

23+
bool options::isViewed(std::string_view id) {
24+
if (auto om = OptionManager::get()) return om->isViewed(id);
25+
return false;
26+
};
27+
2328
unsigned int options::getChance(std::string_view id) {
2429
return thisMod->getSettingValue<unsigned int>(fmt::format("{}-chance", id));
2530
};
@@ -29,8 +34,8 @@ HorribleOptionSave options::get(std::string_view id) {
2934
return {};
3035
};
3136

32-
void options::set(ZStringView id, bool enable, bool pin) {
33-
if (auto om = OptionManager::get()) om->setOption(id, enable, pin);
37+
void options::set(ZStringView id, bool enable, bool pin, bool viewed) {
38+
if (auto om = OptionManager::get()) om->setOption(id, enable, pin, viewed);
3439
};
3540

3641
size_t options::getDelegates(std::string_view id) noexcept {

0 commit comments

Comments
 (0)