button press anims & temp reassignment state when opening assignment modal

This commit is contained in:
thecozies
2025-07-22 08:20:38 -05:00
parent b887dd99e7
commit 447d282eed
5 changed files with 243 additions and 52 deletions
+135 -29
View File
@@ -1,11 +1,84 @@
#include "ui_assign_players_modal.h"
#include "elements/ui_label.h"
#include "elements/ui_container.h"
#include "recomp_ui.h"
namespace recompui {
recompui::ContextId assign_players_modal_context;
static constexpr float assign_player_card_size = 128.0f;
static constexpr float assign_player_card_icon_size = 64.0f;
AssignPlayerCard::AssignPlayerCard(Element *parent) : Element(parent, 0, "div", false) {
set_display(Display::Flex);
set_flex_direction(FlexDirection::Column);
set_align_items(AlignItems::Center);
set_justify_content(JustifyContent::Center);
set_width(assign_player_card_size);
set_height(assign_player_card_size);
set_border_color(theme::color::BorderSoft);
set_border_width(theme::border::width, Unit::Dp);
set_border_radius(theme::border::radius_sm, Unit::Dp);
set_background_color(theme::color::Transparent);
recompui::ContextId context = get_current_context();
icon = context.create_element<Svg>(this, "assets/icons/RecordBorder.svg");
icon->set_width(assign_player_card_icon_size, Unit::Dp);
icon->set_height(assign_player_card_icon_size, Unit::Dp);
icon->set_color(theme::color::TextDim);
}
AssignPlayerCard::~AssignPlayerCard() {
}
void AssignPlayerCard::update_player_card(int player_index) {
static const float scale_anim_duration = 0.25f;
bool is_assigned = recompinput::get_player_is_assigned(player_index);
if (!is_assigned) {
icon->set_scale_2D(1.0f, 1.0f);
set_background_color(theme::color::Transparent);
icon->set_color(theme::color::TextDim);
icon->set_src("assets/icons/RecordBorder.svg");
return;
}
set_background_color(theme::color::PrimaryA20);
bool has_controller =recompinput::does_player_have_controller(player_index);
std::chrono::steady_clock::duration time_since_last_button_press = recompinput::get_player_time_since_last_button_press(player_index);
auto millis = static_cast<float>(std::chrono::duration_cast<std::chrono::milliseconds>(time_since_last_button_press).count());
float seconds = millis / 1000.0f;
if (seconds > 0 && seconds < scale_anim_duration) {
float t = 1.0f - (seconds / scale_anim_duration);
float scale = 1.0f + t * 0.15f;
icon->set_scale_2D(scale, scale);
icon->set_color(theme::color::Text, 200 + static_cast<int>(t * 55.0f));
} else {
icon->set_scale_2D(1.0f, 1.0f);
icon->set_color(theme::color::Text, 200);
}
if (has_controller) {
icon->set_src("assets/icons/Cont.svg");
} else {
icon->set_src("assets/icons/Keyboard.svg");
}
}
static const float assignPlayersHFPaddingVert = 20.0f;
static const float assignPlayersHFPaddingHorz = 20.0f;
static void set_button_side_styles(Element *el) {
el->set_align_items(AlignItems::Center);
el->set_width_auto();
el->set_height_auto();
el->set_flex_basis_auto();
el->set_gap(8.0f);
}
AssignPlayersModal::AssignPlayersModal(Element *parent) : Element(parent, 0, "div", false) {
recompui::ContextId context = get_current_context();
@@ -47,6 +120,12 @@ AssignPlayersModal::AssignPlayersModal(Element *parent) : Element(parent, 0, "di
modal->set_border_color(theme::color::WhiteA20);
modal->set_background_color(theme::color::ModalOverlay);
fake_focus_button = context.create_element<Element>(modal, 0, "button", false);
fake_focus_button->set_position(Position::Absolute);
fake_focus_button->set_width(0, Unit::Dp);
fake_focus_button->set_height(0, Unit::Dp);
fake_focus_button->set_opacity(0);
context.create_element<Label>(modal, "Assign Players", LabelStyle::Large);
player_elements_wrapper = context.create_element<Element>(modal, 0, "div", false);
@@ -56,38 +135,76 @@ AssignPlayersModal::AssignPlayersModal(Element *parent) : Element(parent, 0, "di
player_elements_wrapper->set_align_items(AlignItems::Center);
player_elements_wrapper->set_width(100, Unit::Percent);
player_elements_wrapper->set_padding(24, Unit::Dp);
Element* footer = context.create_element<Element>(modal, 0, "div", false);
footer->set_display(Display::Flex);
footer->set_position(Position::Relative);
footer->set_flex_direction(FlexDirection::Row);
footer->set_align_items(AlignItems::Center);
footer->set_justify_content(JustifyContent::SpaceBetween);
footer->set_width(100.0f, Unit::Percent);
footer->set_height_auto();
footer->set_padding_top(assignPlayersHFPaddingVert);
footer->set_padding_bottom(assignPlayersHFPaddingVert);
footer->set_padding_left(assignPlayersHFPaddingHorz);
footer->set_padding_right(assignPlayersHFPaddingHorz);
auto left = context.create_element<Container>(footer, FlexDirection::Row, JustifyContent::FlexStart, 0);
set_button_side_styles(left);
close_button = context.create_element<Button>(left, "Cancel", ButtonStyle::Tertiary);
close_button->add_pressed_callback(recompinput::stop_player_assignment_and_close_modal);
auto right = context.create_element<Container>(footer, FlexDirection::Row, JustifyContent::FlexEnd, 0);
retry_button = context.create_element<Button>(right, "Retry", ButtonStyle::Warning);
retry_button->set_enabled(false);
retry_button->add_pressed_callback(recompinput::start_player_assignment);
confirm_button = context.create_element<Button>(right, "Confirm", ButtonStyle::Primary);
confirm_button->set_enabled(false);
confirm_button->add_pressed_callback(recompinput::commit_player_assignment);
set_button_side_styles(right);
}
AssignPlayersModal::~AssignPlayersModal() {
}
static void set_player_element_assigned(Element* player_element, bool assigned, bool as_controller) {
if (assigned) {
if (as_controller) {
player_element->set_background_color(theme::color::PrimaryA50);
} else {
player_element->set_background_color(theme::color::SecondaryA50);
}
} else {
player_element->set_background_color(theme::color::Transparent);
}
}
void AssignPlayersModal::process_event(const Event &e) {
if (!is_open) {
return;
}
if (e.type == EventType::Update) {
if (!recompinput::is_player_assignment_active()) {
return;
}
if (player_elements.empty() || player_elements.size() != recompinput::get_num_players()) {
create_player_elements();
}
for (int i = 0; i < recompinput::get_num_players(); i++) {
set_player_element_assigned(player_elements[i], recompinput::get_player_is_assigned(i), recompinput::does_player_have_controller(i));
player_elements[i]->update_player_card(i);
}
if (!recompinput::is_player_assignment_active()) {
if (recompinput::get_player_is_assigned(0)) {
confirm_button->set_enabled(true);
retry_button->set_enabled(true);
if (was_assigning) {
confirm_button->focus();
}
}
was_assigning = false;
} else {
fake_focus_button->focus();
was_assigning = true;
}
if (recompinput::get_player_is_assigned(0)) {
confirm_button->set_enabled(true);
retry_button->set_enabled(true);
} else {
confirm_button->set_enabled(false);
retry_button->set_enabled(false);
}
queue_update();
}
}
@@ -98,18 +215,7 @@ void AssignPlayersModal::create_player_elements() {
recompui::ContextId context = get_current_context();
for (int i = 0; i < recompinput::get_num_players(); i++) {
Element* player_element = context.create_element<Element>(player_elements_wrapper, 0, "div", false);
player_element->set_display(Display::Flex);
player_element->set_flex_direction(FlexDirection::Column);
player_element->set_align_items(AlignItems::Center);
player_element->set_justify_content(JustifyContent::Center);
player_element->set_width(100);
player_element->set_height(100);
player_element->set_border_color(theme::color::BorderSoft);
player_element->set_border_width(theme::border::width, Unit::Dp);
player_element->set_border_radius(theme::border::radius_sm, Unit::Dp);
player_element->set_background_color(theme::color::Transparent);
AssignPlayerCard* player_element = context.create_element<AssignPlayerCard>(player_elements_wrapper);
player_elements.push_back(player_element);
}
}