Refactor mask widget and renderer for improved functionality and performance
- Removed the MASK_WIDGET_DESIGN.md documentation file as it is no longer needed. - Updated the example pipeline to modify the corner radius of the rounded rectangle mask. - Enhanced the mask renderer to correctly calculate UV coordinates based on viewport size for better rendering accuracy. - Changed the get_mask_params method in circle_mask, rect_mask, and rounded_rect_mask to accept bounds by reference for efficiency. - Adjusted the mask factory function to ensure correct parameter order. - Refactored corner_radius method in rounded_rect_mask to accept a rect_corner_radius structure for more flexible corner radius settings.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,524 +0,0 @@
|
||||
# 布局工具重构设计方案
|
||||
|
||||
## 1. 概述
|
||||
|
||||
本文档描述了将 `v_stack`、`h_stack` 和 `overlay` 容器中重复的布局属性操作封装成通用工具的重构方案。
|
||||
|
||||
### 1.1 目标
|
||||
|
||||
- 消除重复代码,提高代码可维护性
|
||||
- 保持与现有代码的完全兼容性
|
||||
- 使用模板元编程保持类型安全
|
||||
- 遵循项目现有的命名规范(snake_case)
|
||||
- 最小化对现有容器代码的修改
|
||||
|
||||
### 1.2 已识别的重复模式
|
||||
|
||||
| 重复模式 | 出现位置 | 重复次数 |
|
||||
|---------|---------|---------|
|
||||
| `extract_margin()` | v_stack, h_stack, overlay | 3 |
|
||||
| `extract_stretch()` | v_stack, h_stack | 2 |
|
||||
| `has_auto_size()` | v_stack, h_stack | 2 |
|
||||
| `should_stretch()` | v_stack, h_stack | 2 |
|
||||
| `get_flex_factor()` | v_stack, h_stack | 2 |
|
||||
| `get_event_children()` 实现 | v_stack, h_stack, overlay | 3 |
|
||||
| 边距计算模式 | overlay, stack | 多处 |
|
||||
|
||||
## 2. 设计方案
|
||||
|
||||
### 2.1 新文件结构
|
||||
|
||||
```
|
||||
src/widget/
|
||||
├── layout_utils.h # 新增:通用布局工具函数
|
||||
├── slot.h # 现有:保持不变
|
||||
├── stack.h # 修改:使用 layout_utils
|
||||
├── overlay.h # 修改:使用 layout_utils
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 2.2 layout_utils.h 接口设计
|
||||
|
||||
```cpp
|
||||
#pragma once
|
||||
#include "slot.h"
|
||||
#include "event_target.h"
|
||||
#include "dynamic_list.h"
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace mirage {
|
||||
namespace layout_utils {
|
||||
|
||||
// ============================================================================
|
||||
// 参数提取工具函数
|
||||
// ============================================================================
|
||||
|
||||
/// @brief 从 slot 或普通 widget 中提取 margin 参数
|
||||
/// @tparam Child 子组件类型
|
||||
/// @param child 子组件引用
|
||||
/// @return 提取的 margin,如果不存在则返回 margin::zero()
|
||||
template <typename Child>
|
||||
constexpr margin extract_margin(const Child& child) {
|
||||
if constexpr (is_slot_v<Child>) {
|
||||
if (auto margin_p = child.template get<margin_param>()) {
|
||||
return margin_p->value;
|
||||
}
|
||||
}
|
||||
return margin::zero();
|
||||
}
|
||||
|
||||
/// @brief 从 slot 中提取 stretch 参数
|
||||
/// @tparam Child 子组件类型
|
||||
/// @param child 子组件引用
|
||||
/// @return 提取的 stretch_param(可选)
|
||||
template <typename Child>
|
||||
constexpr std::optional<stretch_param> extract_stretch(const Child& child) {
|
||||
if constexpr (is_slot_v<Child>) {
|
||||
return child.template get<stretch_param>();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/// @brief 从 slot 中提取 alignment 参数
|
||||
/// @tparam Child 子组件类型
|
||||
/// @param child 子组件引用
|
||||
/// @param default_align 默认对齐方式
|
||||
/// @return 提取的 alignment
|
||||
template <typename Child>
|
||||
constexpr alignment extract_alignment(const Child& child,
|
||||
alignment default_align = alignment::TOP_LEFT) {
|
||||
if constexpr (is_slot_v<Child>) {
|
||||
if (auto align_p = child.template get<alignment_param>()) {
|
||||
return align_p->value;
|
||||
}
|
||||
}
|
||||
return default_align;
|
||||
}
|
||||
|
||||
/// @brief 检查是否设置了 auto_size 参数
|
||||
/// @tparam Child 子组件类型
|
||||
/// @param child 子组件引用
|
||||
/// @return 如果设置了 auto_size 则返回 true
|
||||
template <typename Child>
|
||||
constexpr bool has_auto_size(const Child& child) {
|
||||
if constexpr (is_slot_v<Child>) {
|
||||
return child.template get<auto_size_param>().has_value();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief 判断子组件是否应该 stretch
|
||||
/// @tparam Child 子组件类型
|
||||
/// @param child 子组件引用
|
||||
/// @return 如果应该 stretch 则返回 true
|
||||
template <typename Child>
|
||||
constexpr bool should_stretch(const Child& child) {
|
||||
// 如果显式设置了 auto_size,不 stretch
|
||||
if (has_auto_size(child)) return false;
|
||||
// 如果设置了 stretch 参数,则 stretch
|
||||
return extract_stretch(child).has_value();
|
||||
}
|
||||
|
||||
/// @brief 获取 stretch 的 flex 因子
|
||||
/// @tparam Child 子组件类型
|
||||
/// @param child 子组件引用
|
||||
/// @return flex 因子,如果不存在则返回 0.0f
|
||||
template <typename Child>
|
||||
constexpr float get_flex_factor(const Child& child) {
|
||||
if (auto sp = extract_stretch(child)) {
|
||||
return sp->flex_factor;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 边距计算工具函数
|
||||
// ============================================================================
|
||||
|
||||
/// @brief 计算减去 padding/margin 后的内部可用空间
|
||||
/// @param available_size 可用空间
|
||||
/// @param padding 边距
|
||||
/// @return 内部可用空间(保证非负)
|
||||
inline vec2f_t calculate_inner_available(const vec2f_t& available_size,
|
||||
const margin& padding) {
|
||||
return vec2f_t(
|
||||
std::max(0.0f, available_size.x() - padding.left - padding.right),
|
||||
std::max(0.0f, available_size.y() - padding.top - padding.bottom)
|
||||
);
|
||||
}
|
||||
|
||||
/// @brief 计算水平方向的内部可用宽度
|
||||
/// @param available_width 可用宽度
|
||||
/// @param padding 边距
|
||||
/// @return 内部可用宽度(保证非负)
|
||||
inline float calculate_inner_width(float available_width, const margin& padding) {
|
||||
return std::max(0.0f, available_width - padding.left - padding.right);
|
||||
}
|
||||
|
||||
/// @brief 计算垂直方向的内部可用高度
|
||||
/// @param available_height 可用高度
|
||||
/// @param padding 边距
|
||||
/// @return 内部可用高度(保证非负)
|
||||
inline float calculate_inner_height(float available_height, const margin& padding) {
|
||||
return std::max(0.0f, available_height - padding.top - padding.bottom);
|
||||
}
|
||||
|
||||
/// @brief 计算 stretch 分配的尺寸
|
||||
/// @param flex_factor 当前组件的 flex 因子
|
||||
/// @param total_flex 总 flex 因子
|
||||
/// @param available_stretch 可用于 stretch 的空间
|
||||
/// @return 分配的尺寸
|
||||
inline float calculate_stretch_size(float flex_factor, float total_flex,
|
||||
float available_stretch) {
|
||||
if (total_flex <= 0.0f) return 0.0f;
|
||||
return (flex_factor / total_flex) * available_stretch;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 事件子组件收集工具
|
||||
// ============================================================================
|
||||
|
||||
/// @brief 从单个子组件中收集 event_target
|
||||
/// @tparam Child 子组件类型
|
||||
/// @param child 子组件引用
|
||||
/// @param event_children 输出的 event_target 列表
|
||||
template <typename Child>
|
||||
void collect_event_child(Child& child, std::vector<event_target*>& event_children) {
|
||||
using ChildType = std::remove_cvref_t<Child>;
|
||||
|
||||
// 情况 1: dynamic_list
|
||||
if constexpr (std::is_same_v<ChildType, dynamic_list>) {
|
||||
event_children.push_back(const_cast<dynamic_list*>(&child));
|
||||
}
|
||||
// 情况 2: slot 类型
|
||||
else if constexpr (is_slot_v<ChildType>) {
|
||||
using SlotChildType = slot_child_type_t<ChildType>;
|
||||
if constexpr (std::is_base_of_v<event_target, SlotChildType>) {
|
||||
event_children.push_back(const_cast<SlotChildType*>(&child.child()));
|
||||
}
|
||||
}
|
||||
// 情况 3: 继承自 event_target 的普通 widget
|
||||
else if constexpr (std::is_base_of_v<event_target, ChildType>) {
|
||||
event_children.push_back(const_cast<ChildType*>(&child));
|
||||
}
|
||||
// 情况 4: 其他 widget(不处理)
|
||||
}
|
||||
|
||||
/// @brief 从 tuple 中收集所有 event_target 子组件
|
||||
/// @tparam Tuple tuple 类型
|
||||
/// @param children 子组件 tuple
|
||||
/// @return event_target 指针列表
|
||||
template <typename Tuple>
|
||||
std::vector<event_target*> collect_event_children_from_tuple(Tuple& children) {
|
||||
std::vector<event_target*> event_children;
|
||||
|
||||
std::apply([&](auto&... child) {
|
||||
(collect_event_child(child, event_children), ...);
|
||||
}, children);
|
||||
|
||||
return event_children;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 子组件访问工具
|
||||
// ============================================================================
|
||||
|
||||
/// @brief 获取子组件的实际 widget 引用(解包 slot)
|
||||
/// @tparam Child 子组件类型
|
||||
/// @param child 子组件引用
|
||||
/// @return 实际 widget 的引用
|
||||
template <typename Child>
|
||||
decltype(auto) get_actual_child(Child& child) {
|
||||
if constexpr (is_slot_v<std::remove_cvref_t<Child>>) {
|
||||
return child.child();
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 获取子组件的实际 widget 引用(const 版本)
|
||||
template <typename Child>
|
||||
decltype(auto) get_actual_child(const Child& child) {
|
||||
if constexpr (is_slot_v<std::remove_cvref_t<Child>>) {
|
||||
return child.child();
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layout_utils
|
||||
} // namespace mirage
|
||||
```
|
||||
|
||||
## 3. 重构后的代码示例
|
||||
|
||||
### 3.1 v_stack 重构示例
|
||||
|
||||
**重构前(当前代码):**
|
||||
|
||||
```cpp
|
||||
// stack.h 中的 v_stack 类
|
||||
template <typename Child>
|
||||
margin extract_margin(const Child& child) const {
|
||||
if constexpr (is_slot_v<Child>) {
|
||||
if (auto margin_p = child.template get<margin_param>()) {
|
||||
return margin_p->value;
|
||||
}
|
||||
}
|
||||
return margin::zero();
|
||||
}
|
||||
|
||||
template <typename Child>
|
||||
std::optional<stretch_param> extract_stretch(const Child& child) const {
|
||||
if constexpr (is_slot_v<Child>) {
|
||||
return child.template get<stretch_param>();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// ... 更多重复方法
|
||||
```
|
||||
|
||||
**重构后:**
|
||||
|
||||
```cpp
|
||||
// stack.h 中的 v_stack 类
|
||||
#include "layout_utils.h"
|
||||
|
||||
template <widget... children>
|
||||
class v_stack : public event_target, public z_order_mixin<v_stack<children...>> {
|
||||
public:
|
||||
// ... 构造函数等保持不变
|
||||
|
||||
std::vector<event_target*> get_event_children() const override {
|
||||
// 使用工具函数简化实现
|
||||
return layout_utils::collect_event_children_from_tuple(
|
||||
const_cast<std::tuple<children...>&>(children_)
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
// 删除重复的私有方法,直接使用 layout_utils 命名空间中的函数
|
||||
|
||||
template <typename Child>
|
||||
void calculate_flex_info(const Child& child, const vec2f_t& available_size,
|
||||
float& fixed_height, float& total_flex) const {
|
||||
const auto child_margin = layout_utils::extract_margin(child);
|
||||
|
||||
if constexpr (std::is_same_v<std::decay_t<Child>, dynamic_list>) {
|
||||
for (const auto& sub_child : child.get_children()) {
|
||||
const auto child_size = sub_child.measure(available_size);
|
||||
fixed_height += child_size.y() + child_margin.top + child_margin.bottom;
|
||||
}
|
||||
}
|
||||
else if constexpr (is_slot_v<Child>) {
|
||||
if (layout_utils::should_stretch(child)) {
|
||||
fixed_height += child_margin.top + child_margin.bottom;
|
||||
total_flex += layout_utils::get_flex_factor(child);
|
||||
} else {
|
||||
const auto child_size = child.child().measure(available_size);
|
||||
fixed_height += child_size.y() + child_margin.top + child_margin.bottom;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const auto child_size = child.measure(available_size);
|
||||
fixed_height += child_size.y() + child_margin.top + child_margin.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
// ... 其他方法类似重构
|
||||
};
|
||||
```
|
||||
|
||||
### 3.2 overlay 重构示例
|
||||
|
||||
**重构前:**
|
||||
|
||||
```cpp
|
||||
// overlay.h
|
||||
template <typename Child>
|
||||
static margin extract_margin(const Child& child) {
|
||||
if constexpr (is_slot_v<Child>) {
|
||||
if (auto margin_p = child.template get<margin_param>()) {
|
||||
return margin_p->value;
|
||||
}
|
||||
}
|
||||
return margin::zero();
|
||||
}
|
||||
|
||||
// 边距计算
|
||||
const vec2f_t inner_available = vec2f_t(
|
||||
std::max(0.0f, available_size.x() - padding.left - padding.right),
|
||||
std::max(0.0f, available_size.y() - padding.top - padding.bottom)
|
||||
);
|
||||
```
|
||||
|
||||
**重构后:**
|
||||
|
||||
```cpp
|
||||
// overlay.h
|
||||
#include "layout_utils.h"
|
||||
|
||||
template <widget... Children>
|
||||
class overlay : public event_target, public z_order_mixin<overlay<Children...>> {
|
||||
public:
|
||||
auto measure(const vec2f_t& available_size) const -> vec2f_t {
|
||||
vec2f_t max_size = vec2f_t::Zero();
|
||||
|
||||
// 使用工具函数计算内部可用空间
|
||||
const vec2f_t inner_available = layout_utils::calculate_inner_available(
|
||||
available_size, extra_padding_
|
||||
);
|
||||
|
||||
std::apply([&](const auto&... child) {
|
||||
(process_child_measure(child, inner_available, max_size), ...);
|
||||
}, children_);
|
||||
|
||||
max_size.x() += extra_padding_.left + extra_padding_.right;
|
||||
max_size.y() += extra_padding_.top + extra_padding_.bottom;
|
||||
|
||||
return max_size;
|
||||
}
|
||||
|
||||
std::vector<event_target*> get_event_children() const override {
|
||||
return layout_utils::collect_event_children_from_tuple(
|
||||
const_cast<std::tuple<Children...>&>(children_)
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Child>
|
||||
alignment extract_alignment(const Child& child) const {
|
||||
// 使用工具函数,传入默认对齐方式
|
||||
return layout_utils::extract_alignment(child, default_alignment_);
|
||||
}
|
||||
|
||||
template <typename Child>
|
||||
void process_child_measure(const Child& child, const vec2f_t& available_size,
|
||||
vec2f_t& max_size) const {
|
||||
const auto align = extract_alignment(child);
|
||||
const auto padding = layout_utils::extract_margin(child);
|
||||
|
||||
// 使用工具函数计算内部可用空间
|
||||
const vec2f_t child_available = layout_utils::calculate_inner_available(
|
||||
available_size, padding
|
||||
);
|
||||
|
||||
// ... 其余逻辑保持不变
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 4. 重构步骤
|
||||
|
||||
### 4.1 阶段一:创建工具文件(低风险)
|
||||
|
||||
1. 创建 `src/widget/layout_utils.h`
|
||||
2. 实现所有工具函数
|
||||
3. 添加单元测试验证工具函数正确性
|
||||
|
||||
### 4.2 阶段二:逐步迁移(中等风险)
|
||||
|
||||
1. **v_stack 迁移**
|
||||
- 引入 `layout_utils.h`
|
||||
- 替换私有方法调用为工具函数
|
||||
- 删除重复的私有方法
|
||||
- 运行测试验证
|
||||
|
||||
2. **h_stack 迁移**
|
||||
- 同 v_stack 步骤
|
||||
|
||||
3. **overlay 迁移**
|
||||
- 引入 `layout_utils.h`
|
||||
- 替换 `extract_margin` 和边距计算
|
||||
- 替换 `get_event_children` 实现
|
||||
- 运行测试验证
|
||||
|
||||
### 4.3 阶段三:清理和优化(低风险)
|
||||
|
||||
1. 移除所有容器中的重复代码
|
||||
2. 更新文档
|
||||
3. 代码审查
|
||||
|
||||
## 5. 可行性评估
|
||||
|
||||
### 5.1 技术可行性:高
|
||||
|
||||
- 所有重复代码模式清晰,易于抽象
|
||||
- 模板元编程技术成熟,项目已有使用先例
|
||||
- 不涉及运行时行为变更
|
||||
|
||||
### 5.2 兼容性:完全兼容
|
||||
|
||||
- 工具函数为纯函数,无副作用
|
||||
- 不改变任何公共 API
|
||||
- 不改变任何运行时行为
|
||||
|
||||
### 5.3 风险评估
|
||||
|
||||
| 风险项 | 风险等级 | 缓解措施 |
|
||||
|-------|---------|---------|
|
||||
| 编译错误 | 低 | 逐步迁移,每步验证 |
|
||||
| 模板实例化问题 | 低 | 充分的单元测试 |
|
||||
| 性能回归 | 极低 | 内联函数,零开销抽象 |
|
||||
| 行为变更 | 极低 | 工具函数逻辑与原代码完全一致 |
|
||||
|
||||
## 6. 预期收益
|
||||
|
||||
### 6.1 代码量减少
|
||||
|
||||
| 文件 | 当前行数 | 预计减少 | 减少比例 |
|
||||
|-----|---------|---------|---------|
|
||||
| stack.h | ~564 | ~80 | ~14% |
|
||||
| overlay.h | ~356 | ~40 | ~11% |
|
||||
| **总计** | ~920 | ~120 | ~13% |
|
||||
|
||||
### 6.2 维护性提升
|
||||
|
||||
- 单一职责:布局工具函数集中管理
|
||||
- 易于测试:工具函数可独立测试
|
||||
- 易于扩展:新容器可直接复用工具函数
|
||||
|
||||
### 6.3 一致性提升
|
||||
|
||||
- 所有容器使用相同的参数提取逻辑
|
||||
- 边距计算行为统一
|
||||
- 事件子组件收集逻辑统一
|
||||
|
||||
## 7. 架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph 重构前
|
||||
VS1[v_stack] --> |重复代码| M1[extract_margin]
|
||||
VS1 --> |重复代码| S1[extract_stretch]
|
||||
VS1 --> |重复代码| E1[get_event_children]
|
||||
|
||||
HS1[h_stack] --> |重复代码| M2[extract_margin]
|
||||
HS1 --> |重复代码| S2[extract_stretch]
|
||||
HS1 --> |重复代码| E2[get_event_children]
|
||||
|
||||
OV1[overlay] --> |重复代码| M3[extract_margin]
|
||||
OV1 --> |重复代码| E3[get_event_children]
|
||||
end
|
||||
|
||||
subgraph 重构后
|
||||
LU[layout_utils.h]
|
||||
LU --> EM[extract_margin]
|
||||
LU --> ES[extract_stretch]
|
||||
LU --> SS[should_stretch]
|
||||
LU --> GF[get_flex_factor]
|
||||
LU --> CIA[calculate_inner_available]
|
||||
LU --> CEC[collect_event_children]
|
||||
|
||||
VS2[v_stack] --> LU
|
||||
HS2[h_stack] --> LU
|
||||
OV2[overlay] --> LU
|
||||
end
|
||||
```
|
||||
|
||||
## 8. 结论
|
||||
|
||||
本重构方案具有高可行性和低风险,预计可减少约 13% 的重复代码,同时提升代码的可维护性和一致性。建议按照分阶段计划执行,每个阶段完成后进行充分测试。
|
||||
File diff suppressed because it is too large
Load Diff
@@ -432,22 +432,22 @@ private:
|
||||
},
|
||||
// 使用 | 管道操作符
|
||||
mask_widget{
|
||||
rounded_rect_mask{}.corner_radius(10.f),
|
||||
rounded_rect_mask{}.corner_radius(30.f),
|
||||
overlay{
|
||||
// 使用管道语法设置图片居中对齐和边距
|
||||
imager{}
|
||||
.texture_id(texture_id_)
|
||||
.fit(image_fit::contain)
|
||||
.set_texture_size(texture_size_)
|
||||
| align(alignment::CENTER)
|
||||
| padding(10.f),
|
||||
| align(alignment::CENTER),
|
||||
// | padding(10.f),
|
||||
// 普通后效控件
|
||||
post_effect_widget{
|
||||
blur_effect{20.f},
|
||||
fill_box{}
|
||||
},
|
||||
}
|
||||
} | stretch()
|
||||
} | stretch()
|
||||
}
|
||||
};
|
||||
|
||||
layout_state state;
|
||||
|
||||
@@ -494,6 +494,13 @@ namespace mirage {
|
||||
float right = bounds.max().x();
|
||||
float bottom = bounds.max().y();
|
||||
|
||||
// 计算 UV 坐标(基于视口大小)
|
||||
// UV 坐标需要映射到离屏目标中子控件的实际位置
|
||||
float uv_left = left / viewport_size_.x();
|
||||
float uv_top = top / viewport_size_.y();
|
||||
float uv_right = right / viewport_size_.x();
|
||||
float uv_bottom = bottom / viewport_size_.y();
|
||||
|
||||
// 使用实际边界框尺寸,而不是遮罩参数中的尺寸
|
||||
// 这样着色器才能正确计算非正方形区域中的圆形遮罩
|
||||
float width = bounds.sizes().x();
|
||||
@@ -514,8 +521,8 @@ namespace mirage {
|
||||
vertices[0].color[1] = 1.0f;
|
||||
vertices[0].color[2] = 1.0f;
|
||||
vertices[0].color[3] = 1.0f;
|
||||
vertices[0].uv[0] = 0.0f;
|
||||
vertices[0].uv[1] = 0.0f;
|
||||
vertices[0].uv[0] = uv_left;
|
||||
vertices[0].uv[1] = uv_top;
|
||||
vertices[0].data_a[0] = mask_type_f;
|
||||
vertices[0].data_a[1] = params.softness;
|
||||
vertices[0].data_a[2] = width;
|
||||
@@ -532,8 +539,8 @@ namespace mirage {
|
||||
vertices[1].color[1] = 1.0f;
|
||||
vertices[1].color[2] = 1.0f;
|
||||
vertices[1].color[3] = 1.0f;
|
||||
vertices[1].uv[0] = 1.0f;
|
||||
vertices[1].uv[1] = 0.0f;
|
||||
vertices[1].uv[0] = uv_right;
|
||||
vertices[1].uv[1] = uv_top;
|
||||
vertices[1].data_a[0] = mask_type_f;
|
||||
vertices[1].data_a[1] = params.softness;
|
||||
vertices[1].data_a[2] = width;
|
||||
@@ -550,8 +557,8 @@ namespace mirage {
|
||||
vertices[2].color[1] = 1.0f;
|
||||
vertices[2].color[2] = 1.0f;
|
||||
vertices[2].color[3] = 1.0f;
|
||||
vertices[2].uv[0] = 1.0f;
|
||||
vertices[2].uv[1] = 1.0f;
|
||||
vertices[2].uv[0] = uv_right;
|
||||
vertices[2].uv[1] = uv_bottom;
|
||||
vertices[2].data_a[0] = mask_type_f;
|
||||
vertices[2].data_a[1] = params.softness;
|
||||
vertices[2].data_a[2] = width;
|
||||
@@ -568,8 +575,8 @@ namespace mirage {
|
||||
vertices[3].color[1] = 1.0f;
|
||||
vertices[3].color[2] = 1.0f;
|
||||
vertices[3].color[3] = 1.0f;
|
||||
vertices[3].uv[0] = 0.0f;
|
||||
vertices[3].uv[1] = 1.0f;
|
||||
vertices[3].uv[0] = uv_left;
|
||||
vertices[3].uv[1] = uv_bottom;
|
||||
vertices[3].data_a[0] = mask_type_f;
|
||||
vertices[3].data_a[1] = params.softness;
|
||||
vertices[3].data_a[2] = width;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace mirage {
|
||||
/// @brief 根据边界框计算遮罩参数
|
||||
/// @param bounds 边界框
|
||||
/// @return 遮罩参数
|
||||
[[nodiscard]] auto get_mask_params(aabb2d_t bounds) const -> mask_params {
|
||||
[[nodiscard]] auto get_mask_params(const aabb2d_t& bounds) const -> mask_params {
|
||||
const vec2f_t center = bounds.center();
|
||||
const vec2f_t size = bounds.sizes();
|
||||
|
||||
|
||||
@@ -136,8 +136,8 @@ namespace mirage {
|
||||
template <widget Child, mask_shape Mask>
|
||||
auto mask(Child&& child, Mask&& m) {
|
||||
return mask_widget<std::decay_t<Child>, std::decay_t<Mask>>(
|
||||
std::forward<Child>(child),
|
||||
std::forward<Mask>(m)
|
||||
std::forward<Mask>(m),
|
||||
std::forward<Child>(child)
|
||||
);
|
||||
}
|
||||
} // namespace mirage
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace mirage {
|
||||
/// @brief 根据边界框计算遮罩参数
|
||||
/// @param bounds 边界框
|
||||
/// @return 遮罩参数
|
||||
[[nodiscard]] auto get_mask_params(aabb2d_t bounds) const -> mask_params {
|
||||
[[nodiscard]] auto get_mask_params(const aabb2d_t& bounds) const -> mask_params {
|
||||
const vec2f_t center = bounds.center();
|
||||
const vec2f_t size = bounds.sizes();
|
||||
|
||||
|
||||
@@ -30,19 +30,8 @@ namespace mirage {
|
||||
/// @brief 设置统一圆角半径(四个角相同)
|
||||
/// @param r 圆角半径
|
||||
/// @return 返回自身引用,支持链式调用(包括临时对象)
|
||||
auto&& corner_radius(this auto&& self, float r) {
|
||||
self.corner_radii_ = vec4f_t(r, r, r, r);
|
||||
return std::forward<decltype(self)>(self);
|
||||
}
|
||||
|
||||
/// @brief 设置四个角分别的圆角半径
|
||||
/// @param tl 左上角半径
|
||||
/// @param tr 右上角半径
|
||||
/// @param br 右下角半径
|
||||
/// @param bl 左下角半径
|
||||
/// @return 返回自身引用,支持链式调用(包括临时对象)
|
||||
auto&& corner_radius(this auto&& self, float tl, float tr, float br, float bl) {
|
||||
self.corner_radii_ = vec4f_t(tl, tr, br, bl);
|
||||
auto&& corner_radius(this auto&& self, const rect_corner_radius r) {
|
||||
self.corner_radii_ = vec4f_t(r.top_left, r.top_right, r.bottom_right, r.bottom_left);
|
||||
return std::forward<decltype(self)>(self);
|
||||
}
|
||||
|
||||
@@ -75,7 +64,7 @@ namespace mirage {
|
||||
/// @brief 根据边界框计算遮罩参数
|
||||
/// @param bounds 边界框
|
||||
/// @return 遮罩参数
|
||||
[[nodiscard]] auto get_mask_params(aabb2d_t bounds) const -> mask_params {
|
||||
[[nodiscard]] auto get_mask_params(const aabb2d_t& bounds) const -> mask_params {
|
||||
const vec2f_t center = bounds.center();
|
||||
const vec2f_t size = bounds.sizes();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user