mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-25 16:04:28 -04:00
Improve add_child and Button APIs
This commit is contained in:
+15
-14
@@ -18,20 +18,6 @@ Rml::Element* createRoot(Rml::Element* parent, const Rml::String& tagName) {
|
||||
Button::Button(Rml::Element* parent, ButtonProps props, const Rml::String& tagName)
|
||||
: Component(createRoot(parent, tagName)) {
|
||||
update_props(std::move(props));
|
||||
listen(mRoot, Rml::EventId::Click, [this](Rml::Event& event) {
|
||||
if (mProps.onPressed) {
|
||||
mProps.onPressed(event);
|
||||
}
|
||||
});
|
||||
listen(mRoot, Rml::EventId::Keydown, [this](Rml::Event& event) {
|
||||
const auto cmd = map_nav_event(event);
|
||||
if (cmd == NavCommand::Confirm) {
|
||||
if (mProps.onPressed) {
|
||||
mProps.onPressed(event);
|
||||
}
|
||||
event.StopPropagation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Button::set_text(const Rml::String& text) {
|
||||
@@ -48,6 +34,21 @@ void Button::set_selected(bool selected) {
|
||||
}
|
||||
}
|
||||
|
||||
Button& Button::on_pressed(ButtonCallback callback) {
|
||||
if (!callback) {
|
||||
return *this;
|
||||
}
|
||||
listen(mRoot, Rml::EventId::Click, [callback](Rml::Event&) { callback(); });
|
||||
listen(mRoot, Rml::EventId::Keydown, [callback = std::move(callback)](Rml::Event& event) {
|
||||
const auto cmd = map_nav_event(event);
|
||||
if (cmd == NavCommand::Confirm) {
|
||||
callback();
|
||||
event.StopPropagation();
|
||||
}
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Button::update_props(Props props) {
|
||||
set_text(props.text);
|
||||
set_selected(props.selected);
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
namespace dusk::ui {
|
||||
|
||||
using ButtonCallback = std::function<void()>;
|
||||
|
||||
struct ButtonProps {
|
||||
Rml::String text;
|
||||
std::function<void(Rml::Event&)> onPressed;
|
||||
bool selected = false;
|
||||
};
|
||||
|
||||
@@ -14,17 +15,20 @@ class Button : public Component {
|
||||
public:
|
||||
using Props = ButtonProps;
|
||||
|
||||
Button(Rml::Element* parent, ButtonProps props, const Rml::String& tagName = "button");
|
||||
Button(Rml::Element* parent, Props props, const Rml::String& tagName = "button");
|
||||
Button(Rml::Element* parent, Rml::String text, const Rml::String& tagName = "button")
|
||||
: Button(parent, Props{std::move(text)}, tagName) {}
|
||||
|
||||
void set_text(const Rml::String& text);
|
||||
void set_selected(bool selected);
|
||||
Button& on_pressed(ButtonCallback callback);
|
||||
|
||||
const Rml::String& get_text() const { return mProps.text; }
|
||||
|
||||
private:
|
||||
void update_props(Props props);
|
||||
|
||||
ButtonProps mProps;
|
||||
Props mProps;
|
||||
};
|
||||
|
||||
} // namespace dusk::ui
|
||||
@@ -31,11 +31,15 @@ public:
|
||||
void listen(Rml::EventId event, ScopedEventListener::Callback callback, bool capture = false) {
|
||||
listen(mRoot, event, std::move(callback), capture);
|
||||
}
|
||||
void on_hover(ScopedEventListener::Callback callback) {
|
||||
listen(Rml::EventId::Mouseover, callback);
|
||||
listen(Rml::EventId::Focus, std::move(callback));
|
||||
}
|
||||
bool contains(Rml::Element* element) const;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
requires std::is_base_of_v<Component, T> T& add_child(Args&&... args) {
|
||||
auto child = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
auto child = std::make_unique<T>(mRoot, std::forward<Args>(args)...);
|
||||
T& ref = *child;
|
||||
mChildren.emplace_back(std::move(child));
|
||||
return ref;
|
||||
|
||||
+339
-36
@@ -45,6 +45,284 @@ void set_horse_name(Rml::String name) {
|
||||
dComIfGs_setHorseName(name.c_str());
|
||||
}
|
||||
|
||||
enum ItemType {
|
||||
ITEMTYPE_DEFAULT_e,
|
||||
ITEMTYPE_EQUIP_e,
|
||||
};
|
||||
|
||||
struct itemInfo {
|
||||
std::string m_name;
|
||||
u8 m_type = ITEMTYPE_DEFAULT_e;
|
||||
};
|
||||
|
||||
std::map<int, itemInfo> itemMap = {
|
||||
{dItemNo_HEART_e, {"Heart"}},
|
||||
{dItemNo_GREEN_RUPEE_e, {"Green Rupee"}},
|
||||
{dItemNo_BLUE_RUPEE_e, {"Blue Rupee"}},
|
||||
{dItemNo_YELLOW_RUPEE_e, {"Yellow Rupee"}},
|
||||
{dItemNo_RED_RUPEE_e, {"Red Rupee"}},
|
||||
{dItemNo_PURPLE_RUPEE_e, {"Purple Rupee"}},
|
||||
{dItemNo_ORANGE_RUPEE_e, {"Orange Rupee"}},
|
||||
{dItemNo_SILVER_RUPEE_e, {"Silver Rupee"}},
|
||||
{dItemNo_S_MAGIC_e, {"Small Magic"}},
|
||||
{dItemNo_L_MAGIC_e, {"Large Magic"}},
|
||||
{dItemNo_BOMB_5_e, {"Bombs (5)"}},
|
||||
{dItemNo_BOMB_10_e, {"Bombs (10)"}},
|
||||
{dItemNo_BOMB_20_e, {"Bombs (20)"}},
|
||||
{dItemNo_BOMB_30_e, {"Bombs (30)"}},
|
||||
{dItemNo_ARROW_10_e, {"Arrows (10)"}},
|
||||
{dItemNo_ARROW_20_e, {"Arrows (20)"}},
|
||||
{dItemNo_ARROW_30_e, {"Arrows (30)"}},
|
||||
{dItemNo_ARROW_1_e, {"Arrows (1)"}},
|
||||
{dItemNo_PACHINKO_SHOT_e, {"Pumpkin Seeds"}},
|
||||
{dItemNo_NOENTRY_19_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_20_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_21_e, {"Reserved"}},
|
||||
{dItemNo_WATER_BOMB_5_e, {"Water Bombs (5)"}},
|
||||
{dItemNo_WATER_BOMB_10_e, {"Water Bombs (10)"}},
|
||||
{dItemNo_WATER_BOMB_20_e, {"Water Bombs (20)"}},
|
||||
{dItemNo_WATER_BOMB_30_e, {"Water Bombs (30)"}},
|
||||
{dItemNo_BOMB_INSECT_5_e, {"Bomblings (5)"}},
|
||||
{dItemNo_BOMB_INSECT_10_e, {"Bomblings (10)"}},
|
||||
{dItemNo_BOMB_INSECT_20_e, {"Bomblings (20)"}},
|
||||
{dItemNo_BOMB_INSECT_30_e, {"Bomblings (30)"}},
|
||||
{dItemNo_RECOVERY_FAILY_e, {"Fairy"}},
|
||||
{dItemNo_TRIPLE_HEART_e, {"Triple Hearts"}},
|
||||
{dItemNo_SMALL_KEY_e, {"Small Key"}},
|
||||
{dItemNo_KAKERA_HEART_e, {"Piece of Heart"}},
|
||||
{dItemNo_UTAWA_HEART_e, {"Heart Container"}},
|
||||
{dItemNo_MAP_e, {"Dungeon Map"}},
|
||||
{dItemNo_COMPUS_e, {"Compass"}},
|
||||
{dItemNo_DUNGEON_EXIT_e, {"Ooccoo Sr. (First Time)", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_BOSS_KEY_e, {"Boss Key"}},
|
||||
{dItemNo_DUNGEON_BACK_e, {"Ooccoo Jr.", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_SWORD_e, {"Ordon Sword"}},
|
||||
{dItemNo_MASTER_SWORD_e, {"Master Sword"}},
|
||||
{dItemNo_WOOD_SHIELD_e, {"Wooden Shield"}},
|
||||
{dItemNo_SHIELD_e, {"Ordon Shield"}},
|
||||
{dItemNo_HYLIA_SHIELD_e, {"Hylian Shield"}},
|
||||
{dItemNo_TKS_LETTER_e, {"Ooccoo's Note", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_WEAR_CASUAL_e, {"Ordon Clothes"}},
|
||||
{dItemNo_WEAR_KOKIRI_e, {"Hero's Clothes"}},
|
||||
{dItemNo_ARMOR_e, {"Magic Armor"}},
|
||||
{dItemNo_WEAR_ZORA_e, {"Zora Armor"}},
|
||||
{dItemNo_MAGIC_LV1_e, {"Magic Level 1"}},
|
||||
{dItemNo_DUNGEON_EXIT_2_e, {"Ooccoo Sr.", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_WALLET_LV1_e, {"Wallet"}},
|
||||
{dItemNo_WALLET_LV2_e, {"Big Wallet"}},
|
||||
{dItemNo_WALLET_LV3_e, {"Giant Wallet"}},
|
||||
{dItemNo_NOENTRY_55_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_56_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_57_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_58_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_59_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_60_e, {"Reserved"}},
|
||||
{dItemNo_ZORAS_JEWEL_e, {"Coral Earring", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_HAWK_EYE_e, {"Hawkeye", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_WOOD_STICK_e, {"Wooden Sword"}},
|
||||
{dItemNo_BOOMERANG_e, {"Gale Boomerang", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_SPINNER_e, {"Spinner", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_IRONBALL_e, {"Ball and Chain", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_BOW_e, {"Hero's Bow", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_HOOKSHOT_e, {"Clawshot", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_HVY_BOOTS_e, {"Iron Boots", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_COPY_ROD_e, {"Dominion Rod", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_W_HOOKSHOT_e, {"Double Clawshots", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_KANTERA_e, {"Lantern", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_LIGHT_SWORD_e, {"Light Sword"}},
|
||||
{dItemNo_FISHING_ROD_1_e, {"Fishing Rod", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_PACHINKO_e, {"Slingshot", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_COPY_ROD_2_e, {"Dominion Rod (Uncharged)"}},
|
||||
{dItemNo_NOENTRY_77_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_78_e, {"Reserved"}},
|
||||
{dItemNo_BOMB_BAG_LV2_e, {"Giant Bomb Bag"}},
|
||||
{dItemNo_BOMB_BAG_LV1_e, {"Empty Bomb Bag", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_BOMB_IN_BAG_e, {"Bomb Bag"}},
|
||||
{dItemNo_NOENTRY_82_e, {"Reserved"}},
|
||||
{dItemNo_LIGHT_ARROW_e, {"Light Arrow"}},
|
||||
{dItemNo_ARROW_LV1_e, {"Quiver"}},
|
||||
{dItemNo_ARROW_LV2_e, {"Big Quiver"}},
|
||||
{dItemNo_ARROW_LV3_e, {"Giant Quiver"}},
|
||||
{dItemNo_NOENTRY_87_e, {"Reserved"}},
|
||||
{dItemNo_LURE_ROD_e, {"Fishing Rod (Lure)"}},
|
||||
{dItemNo_BOMB_ARROW_e, {"Bomb Arrow"}},
|
||||
{dItemNo_HAWK_ARROW_e, {"Hawk Arrow"}},
|
||||
{dItemNo_BEE_ROD_e, {"Fishing Rod (Bee Larva)", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_JEWEL_ROD_e, {"Fishing Rod (Earring)", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_WORM_ROD_e, {"Fishing Rod (Worm)", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_JEWEL_BEE_ROD_e, {"Fishing Rod (Earring + Bee Larva)", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_JEWEL_WORM_ROD_e, {"Fishing Rod (Earring + Worm)", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_EMPTY_BOTTLE_e, {"Empty Bottle", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_RED_BOTTLE_e, {"Red Potion", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_GREEN_BOTTLE_e, {"Green Potion", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_BLUE_BOTTLE_e, {"Blue Potion", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_MILK_BOTTLE_e, {"Milk Bottle", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_HALF_MILK_BOTTLE_e, {"Half Milk Bottle", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_OIL_BOTTLE_e, {"Lantern Oil", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_WATER_BOTTLE_e, {"Water Bottle", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_OIL_BOTTLE_2_e, {"Lantern Oil (Scooped)"}},
|
||||
{dItemNo_RED_BOTTLE_2_e, {"Red Potion (Scooped)"}},
|
||||
{dItemNo_UGLY_SOUP_e, {"Nasty Soup", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_HOT_SPRING_e, {"Hotspring Water", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_FAIRY_e, {"Fairy", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_HOT_SPRING_2_e, {"Hotspring Water (Shop)"}},
|
||||
{dItemNo_OIL2_e, {"Lantern Refill (Scooped)"}},
|
||||
{dItemNo_OIL_e, {"Lantern Refill (Shop)"}},
|
||||
{dItemNo_NORMAL_BOMB_e, {"Bombs", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_WATER_BOMB_e, {"Water Bombs", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_POKE_BOMB_e, {"Bomblings", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_FAIRY_DROP_e, {"Great Fairy's Tears", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_WORM_e, {"Worm", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_DROP_BOTTLE_e, {"Great Fairy Tears (Jovani)"}},
|
||||
{dItemNo_BEE_CHILD_e, {"Bee Larva", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_CHUCHU_RARE_e, {"Rare Chu Jelly", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_CHUCHU_RED_e, {"Red Chu Jelly", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_CHUCHU_BLUE_e, {"Blue Chu Jelly", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_CHUCHU_GREEN_e, {"Green Chu Jelly", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_CHUCHU_YELLOW_e, {"Yellow Chu Jelly", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_CHUCHU_PURPLE_e, {"Purple Chu Jelly", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_LV1_SOUP_e, {"Simple Soup", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_LV2_SOUP_e, {"Good Soup", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_LV3_SOUP_e, {"Superb Soup", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_LETTER_e, {"Renado's Letter", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_BILL_e, {"Invoice", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_WOOD_STATUE_e, {"Wooden Statue", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_IRIAS_PENDANT_e, {"Ilia's Charm", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_HORSE_FLUTE_e, {"Horse Call", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_NOENTRY_133_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_134_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_135_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_136_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_137_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_138_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_139_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_140_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_141_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_142_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_143_e, {"Reserved"}},
|
||||
{dItemNo_RAFRELS_MEMO_e, {"Auru's Memo", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_ASHS_SCRIBBLING_e, {"Ashei's Sketch", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_NOENTRY_146_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_147_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_148_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_149_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_150_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_151_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_152_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_153_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_154_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_155_e, {"Reserved"}},
|
||||
{dItemNo_CHUCHU_YELLOW2_e, {"Lantern Refill (Yellow Chu)"}},
|
||||
{dItemNo_OIL_BOTTLE3_e, {"Lantern Oil (Coro)"}},
|
||||
{dItemNo_SHOP_BEE_CHILD_e, {"Bee Larve (Shop)"}},
|
||||
{dItemNo_CHUCHU_BLACK_e, {"Black Chu Jelly", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_LIGHT_DROP_e, {"Tear of Light"}},
|
||||
{dItemNo_DROP_CONTAINER_e, {"Vessel of Light (Faron)"}},
|
||||
{dItemNo_DROP_CONTAINER02_e, {"Vessel of Light (Eldin)"}},
|
||||
{dItemNo_DROP_CONTAINER03_e, {"Vessel of Light (Lanayru)"}},
|
||||
{dItemNo_FILLED_CONTAINER_e, {"Vessel of Light (Filled)"}},
|
||||
{dItemNo_MIRROR_PIECE_2_e, {"Mirror Shard (Snowpeak Ruins)"}},
|
||||
{dItemNo_MIRROR_PIECE_3_e, {"Mirror Shard (Temple of Time)"}},
|
||||
{dItemNo_MIRROR_PIECE_4_e, {"Mirror Shard (City in the Sky)"}},
|
||||
{dItemNo_NOENTRY_168_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_169_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_170_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_171_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_172_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_173_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_174_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_175_e, {"Reserved"}},
|
||||
{dItemNo_SMELL_YELIA_POUCH_e, {"Scent of Ilia"}},
|
||||
{dItemNo_SMELL_PUMPKIN_e, {"Pumpkin Scent"}},
|
||||
{dItemNo_SMELL_POH_e, {"Poe Scent"}},
|
||||
{dItemNo_SMELL_FISH_e, {"Reekfish Scent"}},
|
||||
{dItemNo_SMELL_CHILDREN_e, {"Youth's Scent"}},
|
||||
{dItemNo_SMELL_MEDICINE_e, {"Medicine Scent"}},
|
||||
{dItemNo_NOENTRY_182_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_183_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_184_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_185_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_186_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_187_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_188_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_189_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_190_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_191_e, {"Reserved"}},
|
||||
{dItemNo_M_BEETLE_e, {"Beetle (M)"}},
|
||||
{dItemNo_F_BEETLE_e, {"Beetle (F)"}},
|
||||
{dItemNo_M_BUTTERFLY_e, {"Butterfly (M)"}},
|
||||
{dItemNo_F_BUTTERFLY_e, {"Butterfly (F)"}},
|
||||
{dItemNo_M_STAG_BEETLE_e, {"Stag Beetle (M)"}},
|
||||
{dItemNo_F_STAG_BEETLE_e, {"Stag Beetle (F)"}},
|
||||
{dItemNo_M_GRASSHOPPER_e, {"Grasshopper (M)"}},
|
||||
{dItemNo_F_GRASSHOPPER_e, {"Grasshopper (F)"}},
|
||||
{dItemNo_M_NANAFUSHI_e, {"Phasmid (M)"}},
|
||||
{dItemNo_F_NANAFUSHI_e, {"Phasmid (F)"}},
|
||||
{dItemNo_M_DANGOMUSHI_e, {"Pill Bug (M)"}},
|
||||
{dItemNo_F_DANGOMUSHI_e, {"Pill Bug (F)"}},
|
||||
{dItemNo_M_MANTIS_e, {"Mantis (M)"}},
|
||||
{dItemNo_F_MANTIS_e, {"Mantis (F)"}},
|
||||
{dItemNo_M_LADYBUG_e, {"Ladybug (M)"}},
|
||||
{dItemNo_F_LADYBUG_e, {"Ladybug (F)"}},
|
||||
{dItemNo_M_SNAIL_e, {"Snail (M)"}},
|
||||
{dItemNo_F_SNAIL_e, {"Snail (F)"}},
|
||||
{dItemNo_M_DRAGONFLY_e, {"Dragonfly (M)"}},
|
||||
{dItemNo_F_DRAGONFLY_e, {"Dragonfly (F)"}},
|
||||
{dItemNo_M_ANT_e, {"Ant (M)"}},
|
||||
{dItemNo_F_ANT_e, {"Ant (F)"}},
|
||||
{dItemNo_M_MAYFLY_e, {"Mayfly (M)"}},
|
||||
{dItemNo_F_MAYFLY_e, {"Mayfly (F)"}},
|
||||
{dItemNo_NOENTRY_216_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_217_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_218_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_219_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_220_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_221_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_222_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_223_e, {"Reserved"}},
|
||||
{dItemNo_POU_SPIRIT_e, {"Poe Soul"}},
|
||||
{dItemNo_NOENTRY_225_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_226_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_227_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_228_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_229_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_230_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_231_e, {"Reserved"}},
|
||||
{dItemNo_NOENTRY_232_e, {"Reserved"}},
|
||||
{dItemNo_ANCIENT_DOCUMENT_e, {"Ancient Sky Book", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_AIR_LETTER_e, {"Ancient Sky Book (Partial)", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_ANCIENT_DOCUMENT2_e, {"Ancient Sky Book (Filled)", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_LV7_DUNGEON_EXIT_e, {"Ooccoo Sr. (City in the Sky)"}},
|
||||
{dItemNo_LINKS_SAVINGS_e, {"Purple Rupee (Link's Savings)"}},
|
||||
{dItemNo_SMALL_KEY2_e, {"Small Key (North Faron Gate)"}},
|
||||
{dItemNo_POU_FIRE1_e, {"Poe Fire 1"}},
|
||||
{dItemNo_POU_FIRE2_e, {"Poe Fire 2"}},
|
||||
{dItemNo_POU_FIRE3_e, {"Poe Fire 3"}},
|
||||
{dItemNo_POU_FIRE4_e, {"Poe Fire 4"}},
|
||||
{dItemNo_BOSSRIDER_KEY_e, {"Hyrule Field Keys"}},
|
||||
{dItemNo_TOMATO_PUREE_e, {"Ordon Pumpkin", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_TASTE_e, {"Ordon Goat Cheese", ITEMTYPE_EQUIP_e}},
|
||||
{dItemNo_LV5_BOSS_KEY_e, {"Bedroom Key"}},
|
||||
{dItemNo_SURFBOARD_e, {"Surf Leaf"}},
|
||||
{dItemNo_KANTERA2_e, {"Lantern (Reclaimed)"}},
|
||||
{dItemNo_L2_KEY_PIECES1_e, {"Key Shard (1)"}},
|
||||
{dItemNo_L2_KEY_PIECES2_e, {"Key Shard (2)"}},
|
||||
{dItemNo_L2_KEY_PIECES3_e, {"Key Shard (3)"}},
|
||||
{dItemNo_KEY_OF_CARAVAN_e, {"Bulblin Camp Key"}},
|
||||
{dItemNo_LV2_BOSS_KEY_e, {"Goron Mines Boss Key"}},
|
||||
{dItemNo_KEY_OF_FILONE_e, {"South Faron Gate Key"}},
|
||||
{dItemNo_NONE_e, {"None"}},
|
||||
};
|
||||
|
||||
Rml::String item_label_for_slot(u8 slot) {
|
||||
if (slot == 0xFF) {
|
||||
return "None";
|
||||
}
|
||||
auto& item = dComIfGs_getSaveData()->getPlayer().getItem();
|
||||
auto itemNo = item.mItems[slot];
|
||||
return fmt::format("Slot {0} ({1})", slot, itemMap.find(itemNo)->second.m_name);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EditorWindow::EditorWindow() {
|
||||
@@ -53,60 +331,85 @@ EditorWindow::EditorWindow() {
|
||||
auto& rightPane = add_child<Pane>(content, Pane::Direction::Vertical);
|
||||
|
||||
leftPane.add_section("Player");
|
||||
leftPane.add_child<StringButton>(leftPane.root(), StringButton::Props{
|
||||
.key = "Player Name",
|
||||
.getValue = get_player_name,
|
||||
.setValue = set_player_name,
|
||||
.maxLength = 16,
|
||||
});
|
||||
leftPane.add_child<StringButton>(leftPane.root(), StringButton::Props{
|
||||
.key = "Horse Name",
|
||||
.getValue = get_horse_name,
|
||||
.setValue = set_horse_name,
|
||||
.maxLength = 16,
|
||||
});
|
||||
leftPane.add_child<NumberButton>(leftPane.root(),
|
||||
NumberButton::Props{
|
||||
leftPane
|
||||
.add_child<StringButton>(StringButton::Props{
|
||||
.key = "Player Name",
|
||||
.getValue = get_player_name,
|
||||
.setValue = set_player_name,
|
||||
.maxLength = 16,
|
||||
})
|
||||
.on_hover([&rightPane](Rml::Event&) { rightPane.clear(); });
|
||||
leftPane
|
||||
.add_child<StringButton>(StringButton::Props{
|
||||
.key = "Horse Name",
|
||||
.getValue = get_horse_name,
|
||||
.setValue = set_horse_name,
|
||||
.maxLength = 16,
|
||||
})
|
||||
.on_hover([&rightPane](Rml::Event&) { rightPane.clear(); });
|
||||
;
|
||||
leftPane
|
||||
.add_child<NumberButton>(NumberButton::Props{
|
||||
.key = "Max Health",
|
||||
.getValue = [] { return get_player_status()->getMaxLife(); },
|
||||
.setValue = [](int value) { return get_player_status()->setMaxLife(value); },
|
||||
.max = UINT16_MAX, // TODO: actual max
|
||||
});
|
||||
leftPane.add_child<NumberButton>(leftPane.root(),
|
||||
NumberButton::Props{
|
||||
})
|
||||
.on_hover([&rightPane](Rml::Event&) { rightPane.clear(); });
|
||||
leftPane
|
||||
.add_child<NumberButton>(NumberButton::Props{
|
||||
.key = "Health",
|
||||
.getValue = [] { return get_player_status()->getLife(); },
|
||||
.setValue = [](int value) { return get_player_status()->setLife(value); },
|
||||
.max = UINT16_MAX, // TODO: actual max
|
||||
});
|
||||
leftPane.add_child<NumberButton>(leftPane.root(),
|
||||
NumberButton::Props{
|
||||
})
|
||||
.on_hover([&rightPane](Rml::Event&) { rightPane.clear(); });
|
||||
leftPane
|
||||
.add_child<NumberButton>(NumberButton::Props{
|
||||
.key = "Rupees",
|
||||
.getValue = [] { return get_player_status()->getRupee(); },
|
||||
.setValue = [](int value) { return get_player_status()->setRupee(value); },
|
||||
.max = get_player_status()->getRupeeMax(),
|
||||
})
|
||||
.on_hover([&rightPane](Rml::Event&) { rightPane.clear(); });
|
||||
leftPane
|
||||
.add_child<NumberButton>(NumberButton::Props{
|
||||
.key = "Max Oil",
|
||||
.getValue = [] { return get_player_status()->getMaxOil(); },
|
||||
.setValue = [](int value) { return get_player_status()->setMaxOil(value); },
|
||||
.max = UINT16_MAX, // TODO: actual max
|
||||
});
|
||||
leftPane.add_child<NumberButton>(leftPane.root(),
|
||||
NumberButton::Props{
|
||||
})
|
||||
.on_hover([&rightPane](Rml::Event&) { rightPane.clear(); });
|
||||
leftPane
|
||||
.add_child<NumberButton>(NumberButton::Props{
|
||||
.key = "Oil",
|
||||
.getValue = [] { return get_player_status()->getOil(); },
|
||||
.setValue = [](int value) { return get_player_status()->setOil(value); },
|
||||
.max = UINT16_MAX, // TODO: actual max
|
||||
});
|
||||
})
|
||||
.on_hover([&rightPane](Rml::Event&) { rightPane.clear(); });
|
||||
|
||||
leftPane.add_section("Equipment");
|
||||
leftPane.add_select_button({
|
||||
.key = "Equip X",
|
||||
.value = "TODO",
|
||||
});
|
||||
leftPane.add_select_button({
|
||||
.key = "Equip Y",
|
||||
.value = "TODO",
|
||||
});
|
||||
|
||||
rightPane.add_button({
|
||||
.text = "Hello, world!",
|
||||
});
|
||||
const auto genSelectItemComboBox = [&leftPane, &rightPane](
|
||||
const Rml::String& label, u8& selectItemData) {
|
||||
leftPane
|
||||
.add_select_button({
|
||||
.key = label,
|
||||
.value = item_label_for_slot(selectItemData),
|
||||
})
|
||||
.on_hover([&rightPane, &selectItemData](Rml::Event&) {
|
||||
rightPane.clear();
|
||||
rightPane.add_button("None", [&selectItemData] { selectItemData = 0xFF; });
|
||||
for (int i = 0; i < 24; i++) {
|
||||
rightPane.add_button(
|
||||
item_label_for_slot(i), [i, &selectItemData] { selectItemData = i; });
|
||||
}
|
||||
});
|
||||
};
|
||||
genSelectItemComboBox("Equip X", get_player_status()->mSelectItem[0]);
|
||||
genSelectItemComboBox("Equip Y", get_player_status()->mSelectItem[1]);
|
||||
genSelectItemComboBox("Combo Equip X", get_player_status()->mMixItem[0]);
|
||||
genSelectItemComboBox("Combo Equip Y", get_player_status()->mMixItem[1]);
|
||||
});
|
||||
|
||||
add_tab("Location", [this](Rml::Element* content) {
|
||||
|
||||
+28
-43
@@ -1,8 +1,8 @@
|
||||
#include "overlay.hpp"
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <dolphin/gx/GXAurora.h>
|
||||
#include <dolphin/vi.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "dusk/config.hpp"
|
||||
#include "dusk/settings.h"
|
||||
@@ -38,23 +38,23 @@ const Rml::String kDocumentSource = R"RML(
|
||||
|
||||
int get_value(GraphicsOption option) {
|
||||
switch (option) {
|
||||
case GraphicsOption::InternalResolution:
|
||||
return getSettings().game.internalResolutionScale.getValue();
|
||||
case GraphicsOption::ShadowResolution:
|
||||
return getSettings().game.shadowResolutionMultiplier.getValue();
|
||||
case GraphicsOption::InternalResolution:
|
||||
return getSettings().game.internalResolutionScale.getValue();
|
||||
case GraphicsOption::ShadowResolution:
|
||||
return getSettings().game.shadowResolutionMultiplier.getValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_value(GraphicsOption option, int value) {
|
||||
switch (option) {
|
||||
case GraphicsOption::InternalResolution:
|
||||
getSettings().game.internalResolutionScale.setValue(value);
|
||||
VISetFrameBufferScale(static_cast<float>(value));
|
||||
break;
|
||||
case GraphicsOption::ShadowResolution:
|
||||
getSettings().game.shadowResolutionMultiplier.setValue(value);
|
||||
break;
|
||||
case GraphicsOption::InternalResolution:
|
||||
getSettings().game.internalResolutionScale.setValue(value);
|
||||
VISetFrameBufferScale(static_cast<float>(value));
|
||||
break;
|
||||
case GraphicsOption::ShadowResolution:
|
||||
getSettings().game.shadowResolutionMultiplier.setValue(value);
|
||||
break;
|
||||
}
|
||||
config::Save();
|
||||
}
|
||||
@@ -67,8 +67,8 @@ Rml::Element* create_stepped_carousel_root(Rml::Element* parent) {
|
||||
return parent->AppendChild(std::move(root));
|
||||
}
|
||||
|
||||
Rml::Element* create_stepped_carousel_arrow(Rml::Element* parent, const Rml::String& className,
|
||||
const Rml::String& label) {
|
||||
Rml::Element* create_stepped_carousel_arrow(
|
||||
Rml::Element* parent, const Rml::String& className, const Rml::String& label) {
|
||||
auto* doc = parent->GetOwnerDocument();
|
||||
auto button = doc->CreateElement("button");
|
||||
button->SetClass("stepped-carousel-arrow", true);
|
||||
@@ -86,8 +86,10 @@ SteppedCarousel::SteppedCarousel(Rml::Element* parent, Props props)
|
||||
mValueElem->SetClass("stepped-carousel-value", true);
|
||||
Rml::Element* nextElem = create_stepped_carousel_arrow(mRoot, "next", ">");
|
||||
|
||||
listen(prevElem, Rml::EventId::Click, [this](Rml::Event&) { handle_nav_command(NavCommand::Left); });
|
||||
listen(nextElem, Rml::EventId::Click, [this](Rml::Event&) { handle_nav_command(NavCommand::Right); });
|
||||
listen(prevElem, Rml::EventId::Click,
|
||||
[this](Rml::Event&) { handle_nav_command(NavCommand::Left); });
|
||||
listen(nextElem, Rml::EventId::Click,
|
||||
[this](Rml::Event&) { handle_nav_command(NavCommand::Right); });
|
||||
listen(mRoot, Rml::EventId::Keydown, [this](Rml::Event& event) {
|
||||
const auto cmd = map_nav_event(event);
|
||||
if (cmd != NavCommand::None && handle_nav_command(cmd)) {
|
||||
@@ -128,8 +130,8 @@ bool SteppedCarousel::handle_nav_command(NavCommand cmd) {
|
||||
|
||||
void SteppedCarousel::apply(int value) {
|
||||
const int nextValue = std::clamp(value, mProps.min, mProps.max);
|
||||
const int currentValue = std::clamp(mProps.getValue ? mProps.getValue()
|
||||
: 0, mProps.min, mProps.max);
|
||||
const int currentValue =
|
||||
std::clamp(mProps.getValue ? mProps.getValue() : 0, mProps.min, mProps.max);
|
||||
if (nextValue == currentValue) {
|
||||
return;
|
||||
}
|
||||
@@ -156,9 +158,7 @@ Rml::String format_graphics_setting_value(GraphicsOption option, int value) {
|
||||
}
|
||||
|
||||
Overlay::Overlay(OverlayProps props)
|
||||
: Document(kDocumentSource),
|
||||
mOption(props.option),
|
||||
mValueMin(props.valueMin),
|
||||
: Document(kDocumentSource), mOption(props.option), mValueMin(props.valueMin),
|
||||
mValueMax(props.valueMax) {
|
||||
if (mDocument == nullptr) {
|
||||
return;
|
||||
@@ -176,36 +176,21 @@ Overlay::Overlay(OverlayProps props)
|
||||
.min = mValueMin,
|
||||
.max = mValueMax,
|
||||
.step = 1,
|
||||
.getValue = [this] {
|
||||
return get_value(mOption);
|
||||
},
|
||||
.onChange = [this](int value) {
|
||||
set_value(mOption, value);
|
||||
},
|
||||
.formatValue = [this](int value) {
|
||||
return format_graphics_setting_value(mOption, value);
|
||||
},
|
||||
.getValue = [this] { return get_value(mOption); },
|
||||
.onChange = [this](int value) { set_value(mOption, value); },
|
||||
.formatValue =
|
||||
[this](int value) { return format_graphics_setting_value(mOption, value); },
|
||||
});
|
||||
}
|
||||
|
||||
if (auto* returnParent = mDocument->GetElementById("return")) {
|
||||
auto& returnButton =
|
||||
add_component<Button>(returnParent,
|
||||
Button::Props{
|
||||
.text = "Return",
|
||||
.onPressed = [this](Rml::Event&) { pop_document(); },
|
||||
}, "footer-button"
|
||||
);
|
||||
add_component<Button>(returnParent, "Return", "footer-button").on_pressed(pop_document);
|
||||
returnButton.root()->SetClass("return", true);
|
||||
}
|
||||
if (auto* resetParent = mDocument->GetElementById("reset")) {
|
||||
auto& resetButton =
|
||||
add_component<Button>(resetParent,
|
||||
Button::Props{
|
||||
.text = "Reset to default",
|
||||
.onPressed = [this](Rml::Event&) { reset_default(); },
|
||||
}, "footer-button"
|
||||
);
|
||||
auto& resetButton = add_component<Button>(resetParent, "Reset to default", "footer-button")
|
||||
.on_pressed([this] { reset_default(); });
|
||||
resetButton.root()->SetClass("reset", true);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,14 @@ public:
|
||||
void update() override;
|
||||
|
||||
Rml::Element* add_section(const Rml::String& text);
|
||||
Button& add_button(Button::Props props) { return add_child<Button>(mRoot, std::move(props)); }
|
||||
Button& add_button(Button::Props props, ButtonCallback callback) {
|
||||
return add_child<Button>(std::move(props)).on_pressed(std::move(callback));
|
||||
}
|
||||
Button& add_button(Rml::String text, ButtonCallback callback) {
|
||||
return add_child<Button>(std::move(text)).on_pressed(std::move(callback));
|
||||
}
|
||||
SelectButton& add_select_button(SelectButton::Props props) {
|
||||
return add_child<SelectButton>(mRoot, std::move(props));
|
||||
return add_child<SelectButton>(std::move(props));
|
||||
}
|
||||
Rml::Element* add_text(const Rml::String& text);
|
||||
Rml::Element* add_rml(const Rml::String& rml);
|
||||
|
||||
@@ -31,6 +31,7 @@ protected:
|
||||
Props mProps;
|
||||
Rml::Element* mKeyElem = nullptr;
|
||||
Rml::Element* mValueElem = nullptr;
|
||||
std::function<void()> mOnHover;
|
||||
};
|
||||
|
||||
class ControlledSelectButton : public SelectButton {
|
||||
|
||||
+147
-173
@@ -235,42 +235,38 @@ SettingsWindow::SettingsWindow() {
|
||||
auto& rightPane = add_child<Pane>(content, Pane::Direction::Vertical);
|
||||
|
||||
leftPane.add_section("Volume");
|
||||
leftPane.add_child<ConfigIntSelect>(leftPane.root(),
|
||||
ConfigIntSelect::Props{
|
||||
.key = "Master Volume",
|
||||
.value = &getSettings().audio.masterVolume,
|
||||
.onChange = [](int value) { audio::SetMasterVolume(value / 100.f); },
|
||||
.helpText = "Adjusts the volume of all sounds in the game.",
|
||||
.rightPane = &rightPane,
|
||||
.max = 100,
|
||||
.suffix = "%",
|
||||
});
|
||||
leftPane.add_child<ConfigIntSelect>(ConfigIntSelect::Props{
|
||||
.key = "Master Volume",
|
||||
.value = &getSettings().audio.masterVolume,
|
||||
.onChange = [](int value) { audio::SetMasterVolume(value / 100.f); },
|
||||
.helpText = "Adjusts the volume of all sounds in the game.",
|
||||
.rightPane = &rightPane,
|
||||
.max = 100,
|
||||
.suffix = "%",
|
||||
});
|
||||
|
||||
leftPane.add_section("Effects");
|
||||
leftPane.add_child<ConfigBoolSelect>(
|
||||
leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = "Enable Reverb",
|
||||
.value = &getSettings().audio.enableReverb,
|
||||
.onChange = [](bool value) { audio::SetEnableReverb(value); },
|
||||
.helpText = "Enables the reverb effect in game audio.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "Enable Reverb",
|
||||
.value = &getSettings().audio.enableReverb,
|
||||
.onChange = [](bool value) { audio::SetEnableReverb(value); },
|
||||
.helpText = "Enables the reverb effect in game audio.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
|
||||
leftPane.add_section("Tweaks");
|
||||
leftPane.add_child<ConfigBoolSelect>(
|
||||
leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = "No Low HP Sound",
|
||||
.value = &getSettings().game.noLowHpSound,
|
||||
.helpText = "Disable the beeping sound when having low health.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(leftPane.root(),
|
||||
ConfigBoolSelect::Props{
|
||||
.key = "Non-Stop Midna's Lament",
|
||||
.value = &getSettings().game.midnasLamentNonStop,
|
||||
.helpText = "Prevents enemy music while Midna's Lament is playing.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "No Low HP Sound",
|
||||
.value = &getSettings().game.noLowHpSound,
|
||||
.helpText = "Disable the beeping sound when having low health.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "Non-Stop Midna's Lament",
|
||||
.value = &getSettings().game.midnasLamentNonStop,
|
||||
.helpText = "Prevents enemy music while Midna's Lament is playing.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
});
|
||||
|
||||
add_tab("Cheats", [this](Rml::Element* content) {
|
||||
@@ -279,14 +275,13 @@ SettingsWindow::SettingsWindow() {
|
||||
|
||||
auto addCheat = [&](const Rml::String& key, ConfigVar<bool>& value,
|
||||
const Rml::String& helpText) {
|
||||
leftPane.add_child<ConfigBoolSelect>(
|
||||
leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = key,
|
||||
.value = &value,
|
||||
.isDisabled = [] { return getSettings().game.speedrunMode; },
|
||||
.helpText = helpText,
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = key,
|
||||
.value = &value,
|
||||
.isDisabled = [] { return getSettings().game.speedrunMode; },
|
||||
.helpText = helpText,
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
};
|
||||
|
||||
leftPane.add_section("Resources");
|
||||
@@ -325,24 +320,23 @@ SettingsWindow::SettingsWindow() {
|
||||
|
||||
auto addOption = [&](const Rml::String& key, ConfigVar<bool>& value,
|
||||
const Rml::String& helpText) {
|
||||
leftPane.add_child<ConfigBoolSelect>(leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = key,
|
||||
.value = &value,
|
||||
.helpText = helpText,
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = key,
|
||||
.value = &value,
|
||||
.helpText = helpText,
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
};
|
||||
|
||||
auto addSpeedrunDisabledOption = [&](const Rml::String& key, ConfigVar<bool>& value,
|
||||
const Rml::String& helpText) {
|
||||
leftPane.add_child<ConfigBoolSelect>(
|
||||
leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = key,
|
||||
.value = &value,
|
||||
.isDisabled = [] { return getSettings().game.speedrunMode; },
|
||||
.helpText = helpText,
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = key,
|
||||
.value = &value,
|
||||
.isDisabled = [] { return getSettings().game.speedrunMode; },
|
||||
.helpText = helpText,
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
};
|
||||
|
||||
leftPane.add_section("General");
|
||||
@@ -357,17 +351,16 @@ SettingsWindow::SettingsWindow() {
|
||||
"Enables rotating Link in the collection menu with the C-Stick.");
|
||||
|
||||
leftPane.add_section("Difficulty");
|
||||
leftPane.add_child<ConfigIntSelect>(
|
||||
leftPane.root(), ConfigIntSelect::Props{
|
||||
.key = "Damage Multiplier",
|
||||
.value = &getSettings().game.damageMultiplier,
|
||||
.isDisabled = [] { return getSettings().game.speedrunMode; },
|
||||
.helpText = "Multiplies incoming damage.",
|
||||
.rightPane = &rightPane,
|
||||
.min = 1,
|
||||
.max = 8,
|
||||
.prefix = "x",
|
||||
});
|
||||
leftPane.add_child<ConfigIntSelect>(ConfigIntSelect::Props{
|
||||
.key = "Damage Multiplier",
|
||||
.value = &getSettings().game.damageMultiplier,
|
||||
.isDisabled = [] { return getSettings().game.speedrunMode; },
|
||||
.helpText = "Multiplies incoming damage.",
|
||||
.rightPane = &rightPane,
|
||||
.min = 1,
|
||||
.max = 8,
|
||||
.prefix = "x",
|
||||
});
|
||||
addSpeedrunDisabledOption(
|
||||
"Instant Death", getSettings().game.instantDeath, "Any hit will instantly kill you.");
|
||||
addSpeedrunDisabledOption("No Heart Drops", getSettings().game.noHeartDrops,
|
||||
@@ -403,31 +396,29 @@ SettingsWindow::SettingsWindow() {
|
||||
"Transform instantly by pressing R and Y simultaneously.");
|
||||
|
||||
leftPane.add_section("Speedrunning");
|
||||
leftPane.add_child<ConfigBoolSelect>(leftPane.root(),
|
||||
ConfigBoolSelect::Props{
|
||||
.key = "Speedrun Mode",
|
||||
.value = &getSettings().game.speedrunMode,
|
||||
.onChange = [](bool) { reset_for_speedrun_mode(); },
|
||||
.helpText = "Enables speedrunning options while restricting certain "
|
||||
"gameplay modifiers.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(
|
||||
leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = "LiveSplit Connection",
|
||||
.value = &getSettings().game.liveSplitEnabled,
|
||||
.onChange =
|
||||
[](bool enabled) {
|
||||
if (enabled) {
|
||||
speedrun::connectLiveSplit();
|
||||
} else {
|
||||
speedrun::disconnectLiveSplit();
|
||||
}
|
||||
},
|
||||
.isDisabled = [] { return !getSettings().game.speedrunMode; },
|
||||
.helpText = "Connect to LiveSplit server on localhost:16834.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "Speedrun Mode",
|
||||
.value = &getSettings().game.speedrunMode,
|
||||
.onChange = [](bool) { reset_for_speedrun_mode(); },
|
||||
.helpText = "Enables speedrunning options while restricting certain "
|
||||
"gameplay modifiers.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "LiveSplit Connection",
|
||||
.value = &getSettings().game.liveSplitEnabled,
|
||||
.onChange =
|
||||
[](bool enabled) {
|
||||
if (enabled) {
|
||||
speedrun::connectLiveSplit();
|
||||
} else {
|
||||
speedrun::disconnectLiveSplit();
|
||||
}
|
||||
},
|
||||
.isDisabled = [] { return !getSettings().game.speedrunMode; },
|
||||
.helpText = "Connect to LiveSplit server on localhost:16834.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
});
|
||||
|
||||
add_tab("Graphics", [this](Rml::Element* content) {
|
||||
@@ -436,99 +427,82 @@ SettingsWindow::SettingsWindow() {
|
||||
|
||||
leftPane.add_section("Display");
|
||||
|
||||
leftPane.add_button({
|
||||
.text = "Toggle Fullscreen",
|
||||
.onPressed =
|
||||
[](Rml::Event&) {
|
||||
getSettings().video.enableFullscreen.setValue(
|
||||
!getSettings().video.enableFullscreen);
|
||||
VISetWindowFullscreen(getSettings().video.enableFullscreen);
|
||||
config::Save();
|
||||
},
|
||||
leftPane.add_button("Toggle Fullscreen", [] {
|
||||
getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen);
|
||||
VISetWindowFullscreen(getSettings().video.enableFullscreen);
|
||||
config::Save();
|
||||
});
|
||||
leftPane.add_button({
|
||||
.text = "Restore Default Window Size",
|
||||
.onPressed =
|
||||
[](Rml::Event&) {
|
||||
getSettings().video.enableFullscreen.setValue(false);
|
||||
VISetWindowFullscreen(false);
|
||||
VISetWindowSize(FB_WIDTH * 2, FB_HEIGHT * 2);
|
||||
VICenterWindow();
|
||||
},
|
||||
leftPane.add_button("Restore Default Window Size", [] {
|
||||
getSettings().video.enableFullscreen.setValue(false);
|
||||
VISetWindowFullscreen(false);
|
||||
VISetWindowSize(FB_WIDTH * 2, FB_HEIGHT * 2);
|
||||
VICenterWindow();
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "Enable VSync",
|
||||
.value = &getSettings().video.enableVsync,
|
||||
.onChange = [](bool value) { aurora_enable_vsync(value); },
|
||||
.helpText = "Synchronizes the frame rate to your monitor's refresh rate.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "Lock 4:3 Aspect Ratio",
|
||||
.value = &getSettings().video.lockAspectRatio,
|
||||
.onChange =
|
||||
[](bool value) {
|
||||
AuroraSetViewportPolicy(value ? AURORA_VIEWPORT_FIT : AURORA_VIEWPORT_STRETCH);
|
||||
},
|
||||
.helpText = "Lock the game's aspect ratio to the original.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(leftPane.root(),
|
||||
ConfigBoolSelect::Props{
|
||||
.key = "Enable VSync",
|
||||
.value = &getSettings().video.enableVsync,
|
||||
.onChange = [](bool value) { aurora_enable_vsync(value); },
|
||||
.helpText = "Synchronizes the frame rate to your monitor's refresh rate.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(
|
||||
leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = "Lock 4:3 Aspect Ratio",
|
||||
.value = &getSettings().video.lockAspectRatio,
|
||||
.onChange =
|
||||
[](bool value) {
|
||||
AuroraSetViewportPolicy(
|
||||
value ? AURORA_VIEWPORT_FIT : AURORA_VIEWPORT_STRETCH);
|
||||
},
|
||||
.helpText = "Lock the game's aspect ratio to the original.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
|
||||
leftPane.add_section("Resolution");
|
||||
leftPane.add_child<ConfigOverlaySelect>(leftPane.root(),
|
||||
ConfigOverlaySelect::Props{
|
||||
.key = "Internal Resolution",
|
||||
.value = &getSettings().game.internalResolutionScale,
|
||||
.option = GraphicsOption::InternalResolution,
|
||||
.title = "Internal Resolution",
|
||||
.min = 0,
|
||||
.max = 12,
|
||||
.helpText =
|
||||
"Configure the resolution used for rendering the game. Higher values are more "
|
||||
"demanding on your graphics hardware.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigOverlaySelect>(leftPane.root(),
|
||||
ConfigOverlaySelect::Props{
|
||||
.key = "Shadow Resolution",
|
||||
.value = &getSettings().game.shadowResolutionMultiplier,
|
||||
.option = GraphicsOption::ShadowResolution,
|
||||
.title = "Shadow Resolution",
|
||||
.min = 1,
|
||||
.max = 8,
|
||||
.helpText =
|
||||
"Configure the shadow-map resolution. Higher values improve shadow quality but "
|
||||
"increase GPU and memory usage.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigOverlaySelect>(ConfigOverlaySelect::Props{
|
||||
.key = "Internal Resolution",
|
||||
.value = &getSettings().game.internalResolutionScale,
|
||||
.option = GraphicsOption::InternalResolution,
|
||||
.title = "Internal Resolution",
|
||||
.min = 0,
|
||||
.max = 12,
|
||||
.helpText =
|
||||
"Configure the resolution used for rendering the game. Higher values are more "
|
||||
"demanding on your graphics hardware.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigOverlaySelect>(ConfigOverlaySelect::Props{
|
||||
.key = "Shadow Resolution",
|
||||
.value = &getSettings().game.shadowResolutionMultiplier,
|
||||
.option = GraphicsOption::ShadowResolution,
|
||||
.title = "Shadow Resolution",
|
||||
.min = 1,
|
||||
.max = 8,
|
||||
.helpText =
|
||||
"Configure the shadow-map resolution. Higher values improve shadow quality but "
|
||||
"increase GPU and memory usage.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
|
||||
leftPane.add_section("Post-Processing");
|
||||
// TODO: Bloom
|
||||
// TODO: Bloom Brightness
|
||||
|
||||
leftPane.add_section("Rendering");
|
||||
leftPane.add_child<ConfigBoolSelect>(leftPane.root(),
|
||||
ConfigBoolSelect::Props{
|
||||
.key = "Unlock Framerate",
|
||||
.value = &getSettings().game.enableFrameInterpolation,
|
||||
.helpText =
|
||||
"Uses inter-frame interpolation to enable higher frame rates.<br/><br/>Visual "
|
||||
"artifacts, animation glitches, or instability may occur.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(
|
||||
leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = "Enable Depth of Field",
|
||||
.value = &getSettings().game.enableDepthOfField,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(
|
||||
leftPane.root(), ConfigBoolSelect::Props{
|
||||
.key = "Enable Mini-Map Shadows",
|
||||
.value = &getSettings().game.enableMapBackground,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "Unlock Framerate",
|
||||
.value = &getSettings().game.enableFrameInterpolation,
|
||||
.helpText =
|
||||
"Uses inter-frame interpolation to enable higher frame rates.<br/><br/>Visual "
|
||||
"artifacts, animation glitches, or instability may occur.",
|
||||
.rightPane = &rightPane,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "Enable Depth of Field",
|
||||
.value = &getSettings().game.enableDepthOfField,
|
||||
});
|
||||
leftPane.add_child<ConfigBoolSelect>(ConfigBoolSelect::Props{
|
||||
.key = "Enable Mini-Map Shadows",
|
||||
.value = &getSettings().game.enableMapBackground,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -45,13 +45,12 @@ void TabBar::add_tab(const Rml::String& title, TabCallback callback) {
|
||||
}
|
||||
mTabs.emplace_back(Tab{
|
||||
.title = title,
|
||||
.button = add_child<Button>(mRoot,
|
||||
.button = add_child<Button>(
|
||||
Button::Props{
|
||||
.text = title,
|
||||
.onPressed = [this, index](Rml::Event&) { set_active_tab(index); },
|
||||
.selected = selected,
|
||||
},
|
||||
"tab"),
|
||||
"tab").on_pressed([this, index] { set_active_tab(index); }),
|
||||
.callback = std::move(callback),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user