mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
rsx: Add support for rounded rectangles
This commit is contained in:
parent
0885884839
commit
34c1e1a9ad
@ -454,6 +454,9 @@ namespace gl
|
||||
case rsx::overlays::primitive_type::line_strip:
|
||||
primitives = GL_LINE_STRIP;
|
||||
break;
|
||||
case rsx::overlays::primitive_type::triangle_fan:
|
||||
primitives = GL_TRIANGLE_FAN;
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected primitive type %d", static_cast<s32>(type));
|
||||
}
|
||||
|
@ -25,6 +25,34 @@ namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
static std::vector<vertex> generate_unit_quadrant(int num_patch_points, const float offset[2], const float scale[2])
|
||||
{
|
||||
std::vector<vertex> result;
|
||||
result.resize(num_patch_points + 1);
|
||||
|
||||
// Set root vertex
|
||||
result[0].vec2(offset[0], offset[1]);
|
||||
|
||||
// Set the 0th and Nth outer vertices which lie flush with the axes
|
||||
result[1].vec2(offset[0] + scale[0], offset[1]);
|
||||
result[num_patch_points].vec2(offset[0], offset[1] + scale[1]);
|
||||
|
||||
constexpr float degrees_to_radians = 0.0174533f;
|
||||
for (int i = 1; i < num_patch_points - 1; i++)
|
||||
{
|
||||
// If we keep a unit circle, 2 of the 4 components of the rotation matrix become 0
|
||||
// We end up with a simple vec2(cos_theta, sin_theta) as the output
|
||||
// The final scaling and translation can then be done with fmad
|
||||
const auto angle = degrees_to_radians * ((i * 90) / (num_patch_points - 1));
|
||||
result[i + 1].vec2(
|
||||
std::fmaf(std::cosf(angle), scale[0], offset[0]),
|
||||
std::fmaf(std::sinf(angle), scale[1], offset[1])
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
image_info::image_info(const char* filename)
|
||||
{
|
||||
fs::file f(filename, fs::read + fs::isfile);
|
||||
@ -905,5 +933,89 @@ namespace rsx
|
||||
bool size_changed = old_width != new_width || old_height != new_height;
|
||||
return size_changed;
|
||||
}
|
||||
|
||||
compiled_resource& rounded_rect::get_compiled()
|
||||
{
|
||||
if (!is_compiled)
|
||||
{
|
||||
compiled_resources.clear();
|
||||
|
||||
if (radius == 0 || radius > (w / 2))
|
||||
{
|
||||
// Invalid radius
|
||||
compiled_resources = overlay_element::get_compiled();
|
||||
}
|
||||
else
|
||||
{
|
||||
compiled_resource compiled_resources_temp = {};
|
||||
compiled_resources_temp.append({}); // Bg horizontal mid
|
||||
compiled_resources_temp.append({}); // Bg horizontal top
|
||||
compiled_resources_temp.append({}); // Bg horizontal bottom
|
||||
compiled_resources_temp.append({}); // Bg upper-left
|
||||
compiled_resources_temp.append({}); // Bg lower-left
|
||||
compiled_resources_temp.append({}); // Bg upper-right
|
||||
compiled_resources_temp.append({}); // Bg lower-right
|
||||
|
||||
for (auto& draw_cmd : compiled_resources_temp.draw_commands)
|
||||
{
|
||||
auto& config = draw_cmd.config;
|
||||
config.color = back_color;
|
||||
config.pulse_glow = pulse_effect_enabled;
|
||||
config.pulse_sinus_offset = pulse_sinus_offset;
|
||||
config.pulse_speed_modifier = pulse_speed_modifier;
|
||||
}
|
||||
|
||||
auto& bg0 = compiled_resources_temp.draw_commands[0];
|
||||
auto& bg1 = compiled_resources_temp.draw_commands[1];
|
||||
auto& bg2 = compiled_resources_temp.draw_commands[2];
|
||||
|
||||
bg0.verts.emplace_back(f32(x), f32(y + radius), 0.f, 0.f);
|
||||
bg0.verts.emplace_back(f32(x + w), f32(y + radius), 0.f, 0.f);
|
||||
bg0.verts.emplace_back(f32(x), f32(y + h) - radius, 0.f, 0.f);
|
||||
bg0.verts.emplace_back(f32(x + w), f32(y + h) - radius, 0.f, 0.f);
|
||||
|
||||
bg1.verts.emplace_back(f32(x + radius), f32(y), 0.f, 0.f);
|
||||
bg1.verts.emplace_back(f32(x + w) - radius, f32(y), 0.f, 0.f);
|
||||
bg1.verts.emplace_back(f32(x + radius), f32(y + radius), 0.f, 0.f);
|
||||
bg1.verts.emplace_back(f32(x + w) - radius, f32(y + radius), 0.f, 0.f);
|
||||
|
||||
bg2.verts.emplace_back(f32(x + radius), f32(y + h) - radius, 0.f, 0.f);
|
||||
bg2.verts.emplace_back(f32(x + w) - radius, f32(y + h) - radius, 0.f, 0.f);
|
||||
bg2.verts.emplace_back(f32(x + radius), f32(y + h) + 1.f, 0.f, 0.f); // Note the +1 subpixel correction
|
||||
bg2.verts.emplace_back(f32(x + w) - radius, f32(y + h) + 1.f, 0.f, 0.f);
|
||||
|
||||
// Generate the quadrants
|
||||
const f32 corners[4][2] =
|
||||
{
|
||||
{ f32(x + radius), f32(y + radius) },
|
||||
{ f32(x + radius), f32(y + h) - radius },
|
||||
{ f32(x + w) - radius, f32(y + radius) },
|
||||
{ f32(x + w) - radius, f32(y + h) - radius }
|
||||
};
|
||||
|
||||
const f32 radius_f = static_cast<f32>(radius);
|
||||
const f32 scale[4][2] =
|
||||
{
|
||||
{ -radius_f, -radius_f },
|
||||
{ -radius_f, +radius_f },
|
||||
{ +radius_f, -radius_f },
|
||||
{ +radius_f, +radius_f }
|
||||
};
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
auto& command = compiled_resources_temp.draw_commands[i + 3];
|
||||
command.config.primitives = rsx::overlays::primitive_type::triangle_fan;
|
||||
command.verts = generate_unit_quadrant(num_control_points, corners[i], scale[i]);
|
||||
}
|
||||
|
||||
compiled_resources.add(std::move(compiled_resources_temp), margin_left, margin_top);
|
||||
}
|
||||
|
||||
is_compiled = true;
|
||||
}
|
||||
|
||||
return compiled_resources;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ namespace rsx
|
||||
quad_list = 0,
|
||||
triangle_strip = 1,
|
||||
line_list = 2,
|
||||
line_strip = 3
|
||||
line_strip = 3,
|
||||
triangle_fan = 4
|
||||
};
|
||||
|
||||
struct image_info
|
||||
@ -241,6 +242,15 @@ namespace rsx
|
||||
}
|
||||
};
|
||||
|
||||
struct rounded_rect : public overlay_element
|
||||
{
|
||||
u8 radius = 5;
|
||||
u8 num_control_points = 8; // Smoothness control
|
||||
|
||||
using overlay_element::overlay_element;
|
||||
compiled_resource& get_compiled() override;
|
||||
};
|
||||
|
||||
struct image_view : public overlay_element
|
||||
{
|
||||
private:
|
||||
|
@ -24,6 +24,7 @@ namespace rsx
|
||||
|
||||
m_text.set_font("Arial", 14);
|
||||
m_text.set_text(msg_id);
|
||||
m_text.set_padding(4, 8, 4, 8);
|
||||
m_text.auto_resize();
|
||||
m_text.back_color.a = 0.f;
|
||||
|
||||
@ -32,10 +33,18 @@ namespace rsx
|
||||
m_fade_animation.duration = 2.f;
|
||||
m_fade_animation.active = true;
|
||||
|
||||
back_color.a = 0.15;
|
||||
|
||||
if (icon)
|
||||
{
|
||||
m_icon = std::move(icon);
|
||||
m_icon->set_pos(m_text.x + m_text.w + 8, m_text.y);
|
||||
|
||||
set_size(m_margin + m_text.w + m_icon->w + m_margin, m_margin + std::max(m_text.h, m_icon->h) + m_margin);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_size(m_text.w + m_margin + m_margin, m_text.h + m_margin + m_margin);
|
||||
}
|
||||
}
|
||||
template message_item::message_item(std::string msg_id, u64, std::shared_ptr<atomic_t<u32>>, std::unique_ptr<overlay_element>);
|
||||
@ -47,15 +56,30 @@ namespace rsx
|
||||
return m_refs && *m_refs == 0 ? 0 : m_expiration_time;
|
||||
}
|
||||
|
||||
void message_item::set_pos(u16 _x, u16 _y)
|
||||
{
|
||||
rounded_rect::set_pos(_x, _y);
|
||||
m_text.set_pos(_x + m_margin, y + m_margin);
|
||||
|
||||
if (m_icon)
|
||||
{
|
||||
m_icon->set_pos(m_icon->x, m_text.y);
|
||||
}
|
||||
}
|
||||
|
||||
compiled_resource& message_item::get_compiled()
|
||||
{
|
||||
if (!m_processed)
|
||||
if (!m_processed || !m_fade_animation.active)
|
||||
{
|
||||
compiled_resources = {};
|
||||
return compiled_resources;
|
||||
}
|
||||
|
||||
compiled_resources = m_text.get_compiled();
|
||||
// Disable caching
|
||||
is_compiled = false;
|
||||
|
||||
compiled_resources = rounded_rect::get_compiled();
|
||||
compiled_resources.add(m_text.get_compiled());
|
||||
if (m_icon)
|
||||
{
|
||||
compiled_resources.add(m_icon->get_compiled());
|
||||
@ -70,18 +94,14 @@ namespace rsx
|
||||
if (m_cur_pos != index)
|
||||
{
|
||||
m_cur_pos = index;
|
||||
m_text.set_pos(10, static_cast<u16>(origin + (index * 18 * grow_direction)));
|
||||
if (m_icon)
|
||||
{
|
||||
m_icon->set_pos(m_icon->x, m_text.y);
|
||||
}
|
||||
set_pos(10, static_cast<u16>(origin + (index * 18 * grow_direction)));
|
||||
}
|
||||
|
||||
if (!m_processed)
|
||||
{
|
||||
m_expiration_time = get_expiration_time(m_visible_duration);
|
||||
}
|
||||
else if ((m_expiration_time - time) < 2'000'000)
|
||||
else if (time + 2'000'000 > m_expiration_time)
|
||||
{
|
||||
m_fade_animation.update(rsx::get_current_renderer()->vblank_count);
|
||||
}
|
||||
@ -126,7 +146,7 @@ namespace rsx
|
||||
|
||||
std::lock_guard lock(m_mutex_queue);
|
||||
|
||||
update_queue(m_vis_items_top, m_ready_queue_top, 0, 1);
|
||||
update_queue(m_vis_items_top, m_ready_queue_top, 10, 1);
|
||||
update_queue(m_vis_items_bottom, m_ready_queue_bottom, virtual_height - 18, -1);
|
||||
|
||||
visible = !m_vis_items_top.empty() || !m_vis_items_bottom.empty();
|
||||
|
@ -13,15 +13,16 @@ namespace rsx
|
||||
bottom
|
||||
};
|
||||
|
||||
class message_item : public overlay_element
|
||||
class message_item : public rounded_rect
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs, std::unique_ptr<overlay_element> icon = {});
|
||||
void update(usz index, u64 time, u16 origin, int grow_direction);
|
||||
void set_pos(u16 _x, u16 _y) override;
|
||||
|
||||
u64 get_expiration() const;
|
||||
compiled_resource& get_compiled();
|
||||
compiled_resource& get_compiled() override;
|
||||
|
||||
private:
|
||||
label m_text{};
|
||||
@ -33,6 +34,7 @@ namespace rsx
|
||||
std::shared_ptr<atomic_t<u32>> m_refs;
|
||||
bool m_processed = false;
|
||||
usz m_cur_pos = umax;
|
||||
const u16 m_margin = 6;
|
||||
};
|
||||
|
||||
class message final : public overlay
|
||||
|
@ -703,6 +703,9 @@ namespace vk
|
||||
case rsx::overlays::primitive_type::line_strip:
|
||||
renderpass_config.set_primitive_type(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP);
|
||||
break;
|
||||
case rsx::overlays::primitive_type::triangle_fan:
|
||||
renderpass_config.set_primitive_type(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN);
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected primitive type %d", static_cast<s32>(type));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user