refactor(ui): 移除UI组件的链式调用方法并重构文档注释
重构所有UI组件头文件,移除链式调用构建器方法 为UI组件添加详细的文档注释,说明各方法和属性的用途 调整部分实现文件的结构,使其更加清晰易读
This commit is contained in:
parent
b78c493590
commit
866fd4b1ff
|
|
@ -32,35 +32,6 @@ public:
|
||||||
static Ptr<Button> create(const std::string &text);
|
static Ptr<Button> create(const std::string &text);
|
||||||
static Ptr<Button> create(const std::string &text, Ptr<FontAtlas> font);
|
static Ptr<Button> create(const std::string &text, Ptr<FontAtlas> font);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用构建器方法
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Button *withPosition(float x, float y);
|
|
||||||
Button *withPosition(const Vec2 &pos);
|
|
||||||
Button *withAnchor(float x, float y);
|
|
||||||
Button *withAnchor(const Vec2 &anchor);
|
|
||||||
Button *withText(const std::string &text);
|
|
||||||
Button *withFont(Ptr<FontAtlas> font);
|
|
||||||
Button *withTextColor(const Color &color);
|
|
||||||
Button *withBackgroundColor(const Color &normal, const Color &hover,
|
|
||||||
const Color &pressed);
|
|
||||||
Button *withSize(float width, float height);
|
|
||||||
Button *withPadding(const Vec2 &padding);
|
|
||||||
Button *withPadding(float x, float y);
|
|
||||||
Button *withBorder(const Color &color, float width);
|
|
||||||
Button *withCornerRadius(float radius);
|
|
||||||
Button *withRoundedCornersEnabled(bool enabled);
|
|
||||||
Button *withHoverCursor(CursorShape cursor);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用 - 坐标空间设置
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Button *withCoordinateSpace(CoordinateSpace space);
|
|
||||||
Button *withScreenPosition(float x, float y);
|
|
||||||
Button *withScreenPosition(const Vec2 &pos);
|
|
||||||
Button *withCameraOffset(float x, float y);
|
|
||||||
Button *withCameraOffset(const Vec2 &offset);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 文字内容
|
// 文字内容
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -77,6 +48,7 @@ public:
|
||||||
// 内边距
|
// 内边距
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void setPadding(const Vec2 &padding);
|
void setPadding(const Vec2 &padding);
|
||||||
|
void setPadding(float x, float y);
|
||||||
Vec2 getPadding() const { return padding_; }
|
Vec2 getPadding() const { return padding_; }
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -18,45 +18,45 @@ public:
|
||||||
static Ptr<CheckBox> create(const std::string &label);
|
static Ptr<CheckBox> create(const std::string &label);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 链式调用构建器方法
|
// 选中状态
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
CheckBox *withPosition(float x, float y);
|
|
||||||
CheckBox *withPosition(const Vec2 &pos);
|
|
||||||
CheckBox *withAnchor(float x, float y);
|
|
||||||
CheckBox *withAnchor(const Vec2 &anchor);
|
|
||||||
CheckBox *withText(const std::string &text);
|
|
||||||
CheckBox *withFont(Ptr<FontAtlas> font);
|
|
||||||
CheckBox *withTextColor(const Color &color);
|
|
||||||
CheckBox *withSize(float width, float height);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用 - 坐标空间设置
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
CheckBox *withCoordinateSpace(CoordinateSpace space);
|
|
||||||
CheckBox *withScreenPosition(float x, float y);
|
|
||||||
CheckBox *withScreenPosition(const Vec2 &pos);
|
|
||||||
CheckBox *withCameraOffset(float x, float y);
|
|
||||||
CheckBox *withCameraOffset(const Vec2 &offset);
|
|
||||||
|
|
||||||
void setChecked(bool checked);
|
void setChecked(bool checked);
|
||||||
bool isChecked() const { return checked_; }
|
bool isChecked() const { return checked_; }
|
||||||
void toggle();
|
void toggle();
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 标签设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setLabel(const std::string &label);
|
void setLabel(const std::string &label);
|
||||||
const std::string &getLabel() const { return label_; }
|
const std::string &getLabel() const { return label_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 字体设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setFont(Ptr<FontAtlas> font);
|
void setFont(Ptr<FontAtlas> font);
|
||||||
Ptr<FontAtlas> getFont() const { return font_; }
|
Ptr<FontAtlas> getFont() const { return font_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 文字颜色
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setTextColor(const Color &color);
|
void setTextColor(const Color &color);
|
||||||
Color getTextColor() const { return textColor_; }
|
Color getTextColor() const { return textColor_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 复选框尺寸
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setBoxSize(float size);
|
void setBoxSize(float size);
|
||||||
float getBoxSize() const { return boxSize_; }
|
float getBoxSize() const { return boxSize_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 间距
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setSpacing(float spacing);
|
void setSpacing(float spacing);
|
||||||
float getSpacing() const { return spacing_; }
|
float getSpacing() const { return spacing_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 颜色设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setCheckedColor(const Color &color);
|
void setCheckedColor(const Color &color);
|
||||||
Color getCheckedColor() const { return checkedColor_; }
|
Color getCheckedColor() const { return checkedColor_; }
|
||||||
|
|
||||||
|
|
@ -66,6 +66,9 @@ public:
|
||||||
void setCheckMarkColor(const Color &color);
|
void setCheckMarkColor(const Color &color);
|
||||||
Color getCheckMarkColor() const { return checkMarkColor_; }
|
Color getCheckMarkColor() const { return checkMarkColor_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 回调设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setOnStateChange(Function<void(bool)> callback);
|
void setOnStateChange(Function<void(bool)> callback);
|
||||||
|
|
||||||
Rect getBoundingBox() const override;
|
Rect getBoundingBox() const override;
|
||||||
|
|
|
||||||
|
|
@ -23,27 +23,6 @@ public:
|
||||||
static Ptr<Label> create(const std::string &text);
|
static Ptr<Label> create(const std::string &text);
|
||||||
static Ptr<Label> create(const std::string &text, Ptr<FontAtlas> font);
|
static Ptr<Label> create(const std::string &text, Ptr<FontAtlas> font);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用构建器方法
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Label *withPosition(float x, float y);
|
|
||||||
Label *withPosition(const Vec2 &pos);
|
|
||||||
Label *withAnchor(float x, float y);
|
|
||||||
Label *withAnchor(const Vec2 &anchor);
|
|
||||||
Label *withText(const std::string &text);
|
|
||||||
Label *withFont(Ptr<FontAtlas> font);
|
|
||||||
Label *withTextColor(const Color &color);
|
|
||||||
Label *withFontSize(int size);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 坐标空间设置(链式调用)
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Label *withCoordinateSpace(CoordinateSpace space);
|
|
||||||
Label *withScreenPosition(float x, float y);
|
|
||||||
Label *withScreenPosition(const Vec2 &pos);
|
|
||||||
Label *withCameraOffset(float x, float y);
|
|
||||||
Label *withCameraOffset(const Vec2 &offset);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 文本内容
|
// 文本内容
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -143,17 +122,14 @@ private:
|
||||||
HorizontalAlign hAlign_ = HorizontalAlign::Left;
|
HorizontalAlign hAlign_ = HorizontalAlign::Left;
|
||||||
VerticalAlign vAlign_ = VerticalAlign::Top;
|
VerticalAlign vAlign_ = VerticalAlign::Top;
|
||||||
|
|
||||||
// 阴影
|
|
||||||
bool shadowEnabled_ = false;
|
bool shadowEnabled_ = false;
|
||||||
Color shadowColor_ = Color(0.0f, 0.0f, 0.0f, 0.5f);
|
Color shadowColor_ = Color(0.0f, 0.0f, 0.0f, 0.5f);
|
||||||
Vec2 shadowOffset_ = Vec2(2.0f, 2.0f);
|
Vec2 shadowOffset_ = Vec2(2.0f, 2.0f);
|
||||||
|
|
||||||
// 描边
|
|
||||||
bool outlineEnabled_ = false;
|
bool outlineEnabled_ = false;
|
||||||
Color outlineColor_ = Colors::Black;
|
Color outlineColor_ = Colors::Black;
|
||||||
float outlineWidth_ = 1.0f;
|
float outlineWidth_ = 1.0f;
|
||||||
|
|
||||||
// 多行
|
|
||||||
bool multiLine_ = false;
|
bool multiLine_ = false;
|
||||||
float lineSpacing_ = 1.0f;
|
float lineSpacing_ = 1.0f;
|
||||||
float maxWidth_ = 0.0f;
|
float maxWidth_ = 0.0f;
|
||||||
|
|
|
||||||
|
|
@ -21,21 +21,6 @@ public:
|
||||||
static Ptr<ProgressBar> create();
|
static Ptr<ProgressBar> create();
|
||||||
static Ptr<ProgressBar> create(float min, float max, float value);
|
static Ptr<ProgressBar> create(float min, float max, float value);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用构建器方法 - 坐标空间支持
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
ProgressBar *withPosition(float x, float y);
|
|
||||||
ProgressBar *withPosition(const Vec2 &pos);
|
|
||||||
ProgressBar *withAnchor(float x, float y);
|
|
||||||
ProgressBar *withAnchor(const Vec2 &anchor);
|
|
||||||
ProgressBar *withSize(float width, float height);
|
|
||||||
ProgressBar *withProgress(float progress);
|
|
||||||
ProgressBar *withCoordinateSpace(CoordinateSpace space);
|
|
||||||
ProgressBar *withScreenPosition(float x, float y);
|
|
||||||
ProgressBar *withScreenPosition(const Vec2 &pos);
|
|
||||||
ProgressBar *withCameraOffset(float x, float y);
|
|
||||||
ProgressBar *withCameraOffset(const Vec2 &offset);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 数值范围
|
// 数值范围
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -18,40 +18,44 @@ public:
|
||||||
static Ptr<RadioButton> create(const std::string &label);
|
static Ptr<RadioButton> create(const std::string &label);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 链式调用构建器方法
|
// 选择状态
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
RadioButton *withPosition(float x, float y);
|
|
||||||
RadioButton *withPosition(const Vec2 &pos);
|
|
||||||
RadioButton *withAnchor(float x, float y);
|
|
||||||
RadioButton *withAnchor(const Vec2 &anchor);
|
|
||||||
RadioButton *withText(const std::string &text);
|
|
||||||
RadioButton *withFont(Ptr<FontAtlas> font);
|
|
||||||
RadioButton *withTextColor(const Color &color);
|
|
||||||
RadioButton *withSize(float width, float height);
|
|
||||||
RadioButton *withCoordinateSpace(CoordinateSpace space);
|
|
||||||
RadioButton *withScreenPosition(float x, float y);
|
|
||||||
RadioButton *withScreenPosition(const Vec2 &pos);
|
|
||||||
RadioButton *withCameraOffset(float x, float y);
|
|
||||||
RadioButton *withCameraOffset(const Vec2 &offset);
|
|
||||||
|
|
||||||
void setSelected(bool selected);
|
void setSelected(bool selected);
|
||||||
bool isSelected() const { return selected_; }
|
bool isSelected() const { return selected_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 标签设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setLabel(const std::string &label);
|
void setLabel(const std::string &label);
|
||||||
const std::string &getLabel() const { return label_; }
|
const std::string &getLabel() const { return label_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 字体设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setFont(Ptr<FontAtlas> font);
|
void setFont(Ptr<FontAtlas> font);
|
||||||
Ptr<FontAtlas> getFont() const { return font_; }
|
Ptr<FontAtlas> getFont() const { return font_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 文字颜色
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setTextColor(const Color &color);
|
void setTextColor(const Color &color);
|
||||||
Color getTextColor() const { return textColor_; }
|
Color getTextColor() const { return textColor_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 圆形尺寸
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setCircleSize(float size);
|
void setCircleSize(float size);
|
||||||
float getCircleSize() const { return circleSize_; }
|
float getCircleSize() const { return circleSize_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 间距
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setSpacing(float spacing);
|
void setSpacing(float spacing);
|
||||||
float getSpacing() const { return spacing_; }
|
float getSpacing() const { return spacing_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 颜色设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setSelectedColor(const Color &color);
|
void setSelectedColor(const Color &color);
|
||||||
Color getSelectedColor() const { return selectedColor_; }
|
Color getSelectedColor() const { return selectedColor_; }
|
||||||
|
|
||||||
|
|
@ -61,9 +65,15 @@ public:
|
||||||
void setDotColor(const Color &color);
|
void setDotColor(const Color &color);
|
||||||
Color getDotColor() const { return dotColor_; }
|
Color getDotColor() const { return dotColor_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 分组
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setGroupId(int groupId);
|
void setGroupId(int groupId);
|
||||||
int getGroupId() const { return groupId_; }
|
int getGroupId() const { return groupId_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 回调设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setOnStateChange(Function<void(bool)> callback);
|
void setOnStateChange(Function<void(bool)> callback);
|
||||||
|
|
||||||
Rect getBoundingBox() const override;
|
Rect getBoundingBox() const override;
|
||||||
|
|
@ -86,7 +96,7 @@ private:
|
||||||
Color unselectedColor_ = Color(0.3f, 0.3f, 0.3f, 1.0f);
|
Color unselectedColor_ = Color(0.3f, 0.3f, 0.3f, 1.0f);
|
||||||
Color dotColor_ = Colors::White;
|
Color dotColor_ = Colors::White;
|
||||||
|
|
||||||
int groupId_ = 0; // 用于分组,同组内只能选一个
|
int groupId_ = 0;
|
||||||
|
|
||||||
bool pressed_ = false;
|
bool pressed_ = false;
|
||||||
Function<void(bool)> onStateChange_;
|
Function<void(bool)> onStateChange_;
|
||||||
|
|
|
||||||
|
|
@ -18,41 +18,45 @@ public:
|
||||||
static Ptr<Slider> create(float min, float max, float value);
|
static Ptr<Slider> create(float min, float max, float value);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 链式调用构建器方法
|
// 数值范围
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
Slider *withPosition(float x, float y);
|
|
||||||
Slider *withPosition(const Vec2 &pos);
|
|
||||||
Slider *withAnchor(float x, float y);
|
|
||||||
Slider *withAnchor(const Vec2 &anchor);
|
|
||||||
Slider *withSize(float width, float height);
|
|
||||||
Slider *withMinValue(float min);
|
|
||||||
Slider *withMaxValue(float max);
|
|
||||||
Slider *withValue(float value);
|
|
||||||
Slider *withCoordinateSpace(CoordinateSpace space);
|
|
||||||
Slider *withScreenPosition(float x, float y);
|
|
||||||
Slider *withScreenPosition(const Vec2 &pos);
|
|
||||||
Slider *withCameraOffset(float x, float y);
|
|
||||||
Slider *withCameraOffset(const Vec2 &offset);
|
|
||||||
|
|
||||||
void setRange(float min, float max);
|
void setRange(float min, float max);
|
||||||
float getMin() const { return min_; }
|
float getMin() const { return min_; }
|
||||||
float getMax() const { return max_; }
|
float getMax() const { return max_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 当前值
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setValue(float value);
|
void setValue(float value);
|
||||||
float getValue() const { return value_; }
|
float getValue() const { return value_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 步进值
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setStep(float step);
|
void setStep(float step);
|
||||||
float getStep() const { return step_; }
|
float getStep() const { return step_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 方向
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setVertical(bool vertical);
|
void setVertical(bool vertical);
|
||||||
bool isVertical() const { return vertical_; }
|
bool isVertical() const { return vertical_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 轨道尺寸
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setTrackSize(float size);
|
void setTrackSize(float size);
|
||||||
float getTrackSize() const { return trackSize_; }
|
float getTrackSize() const { return trackSize_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 滑块尺寸
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setThumbSize(float size);
|
void setThumbSize(float size);
|
||||||
float getThumbSize() const { return thumbSize_; }
|
float getThumbSize() const { return thumbSize_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 颜色设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setTrackColor(const Color &color);
|
void setTrackColor(const Color &color);
|
||||||
Color getTrackColor() const { return trackColor_; }
|
Color getTrackColor() const { return trackColor_; }
|
||||||
|
|
||||||
|
|
@ -68,12 +72,18 @@ public:
|
||||||
void setThumbPressedColor(const Color &color);
|
void setThumbPressedColor(const Color &color);
|
||||||
Color getThumbPressedColor() const { return thumbPressedColor_; }
|
Color getThumbPressedColor() const { return thumbPressedColor_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 显示设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setShowThumb(bool show);
|
void setShowThumb(bool show);
|
||||||
bool isShowThumb() const { return showThumb_; }
|
bool isShowThumb() const { return showThumb_; }
|
||||||
|
|
||||||
void setShowFill(bool show);
|
void setShowFill(bool show);
|
||||||
bool isShowFill() const { return showFill_; }
|
bool isShowFill() const { return showFill_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 文本显示
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setTextEnabled(bool enabled);
|
void setTextEnabled(bool enabled);
|
||||||
bool isTextEnabled() const { return textEnabled_; }
|
bool isTextEnabled() const { return textEnabled_; }
|
||||||
|
|
||||||
|
|
@ -86,6 +96,9 @@ public:
|
||||||
void setTextFormat(const std::string &format);
|
void setTextFormat(const std::string &format);
|
||||||
const std::string &getTextFormat() const { return textFormat_; }
|
const std::string &getTextFormat() const { return textFormat_; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 回调设置
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setOnValueChange(Function<void(float)> callback);
|
void setOnValueChange(Function<void(float)> callback);
|
||||||
void setOnDragStart(Function<void()> callback);
|
void setOnDragStart(Function<void()> callback);
|
||||||
void setOnDragEnd(Function<void()> callback);
|
void setOnDragEnd(Function<void()> callback);
|
||||||
|
|
@ -104,7 +117,7 @@ private:
|
||||||
float min_ = 0.0f;
|
float min_ = 0.0f;
|
||||||
float max_ = 100.0f;
|
float max_ = 100.0f;
|
||||||
float value_ = 50.0f;
|
float value_ = 50.0f;
|
||||||
float step_ = 0.0f; // 0表示无步进
|
float step_ = 0.0f;
|
||||||
|
|
||||||
bool vertical_ = false;
|
bool vertical_ = false;
|
||||||
float trackSize_ = 6.0f;
|
float trackSize_ = 6.0f;
|
||||||
|
|
|
||||||
|
|
@ -41,19 +41,6 @@ public:
|
||||||
static Ptr<Text> createFormat(const char *fmt, ...);
|
static Ptr<Text> createFormat(const char *fmt, ...);
|
||||||
static Ptr<Text> createFormat(Ptr<FontAtlas> font, const char *fmt, ...);
|
static Ptr<Text> createFormat(Ptr<FontAtlas> font, const char *fmt, ...);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用构建器方法
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Text *withPosition(float x, float y);
|
|
||||||
Text *withPosition(const Vec2 &pos);
|
|
||||||
Text *withAnchor(float x, float y);
|
|
||||||
Text *withAnchor(const Vec2 &anchor);
|
|
||||||
Text *withTextColor(const Color &color);
|
|
||||||
Text *withFont(Ptr<FontAtlas> font);
|
|
||||||
Text *withFontSize(int size);
|
|
||||||
Text *withAlignment(Alignment align);
|
|
||||||
Text *withVerticalAlignment(VerticalAlignment align);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 文字内容
|
// 文字内容
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -78,20 +65,6 @@ public:
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 链式调用的格式化方法
|
|
||||||
// 注意:由于C++可变参数的限制,链式调用需要单独设置格式和值
|
|
||||||
Text *withFormattedText(const char *fmt, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
char buffer[256];
|
|
||||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
text_ = buffer;
|
|
||||||
sizeDirty_ = true;
|
|
||||||
updateSpatialIndex();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 字体
|
// 字体
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -127,15 +100,6 @@ public:
|
||||||
|
|
||||||
Rect getBoundingBox() const override;
|
Rect getBoundingBox() const override;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用 - 坐标空间设置
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Text *withCoordinateSpace(CoordinateSpace space);
|
|
||||||
Text *withScreenPosition(float x, float y);
|
|
||||||
Text *withScreenPosition(const Vec2 &pos);
|
|
||||||
Text *withCameraOffset(float x, float y);
|
|
||||||
Text *withCameraOffset(const Vec2 &offset);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onDrawWidget(RenderBackend &renderer) override;
|
void onDrawWidget(RenderBackend &renderer) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ namespace extra2d {
|
||||||
// Button 实现
|
// Button 实现
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 默认构造函数
|
||||||
|
*/
|
||||||
Button::Button() {
|
Button::Button() {
|
||||||
// 按钮默认锚点为左上角,这样setPosition(0, 0)会在左上角显示
|
|
||||||
setAnchor(0.0f, 0.0f);
|
setAnchor(0.0f, 0.0f);
|
||||||
setSpatialIndexed(false);
|
setSpatialIndexed(false);
|
||||||
|
|
||||||
|
|
@ -46,133 +48,49 @@ Button::Button() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 带文本的构造函数
|
||||||
|
* @param text 按钮文本
|
||||||
|
*/
|
||||||
Button::Button(const std::string &text) : Button() { text_ = text; }
|
Button::Button(const std::string &text) : Button() { text_ = text; }
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 静态创建方法
|
// 静态创建方法
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief 创建空按钮对象
|
||||||
|
* @return 按钮对象指针
|
||||||
|
*/
|
||||||
Ptr<Button> Button::create() { return makePtr<Button>(); }
|
Ptr<Button> Button::create() { return makePtr<Button>(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带文本的按钮对象
|
||||||
|
* @param text 按钮文本
|
||||||
|
* @return 按钮对象指针
|
||||||
|
*/
|
||||||
Ptr<Button> Button::create(const std::string &text) {
|
Ptr<Button> Button::create(const std::string &text) {
|
||||||
return makePtr<Button>(text);
|
return makePtr<Button>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带文本和字体的按钮对象
|
||||||
|
* @param text 按钮文本
|
||||||
|
* @param font 字体图集
|
||||||
|
* @return 按钮对象指针
|
||||||
|
*/
|
||||||
Ptr<Button> Button::create(const std::string &text, Ptr<FontAtlas> font) {
|
Ptr<Button> Button::create(const std::string &text, Ptr<FontAtlas> font) {
|
||||||
auto btn = makePtr<Button>(text);
|
auto btn = makePtr<Button>(text);
|
||||||
btn->setFont(font);
|
btn->setFont(font);
|
||||||
return btn;
|
return btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用构建器方法
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Button *Button::withPosition(float x, float y) {
|
|
||||||
setPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withPosition(const Vec2 &pos) {
|
|
||||||
setPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withAnchor(float x, float y) {
|
|
||||||
setAnchor(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withAnchor(const Vec2 &anchor) {
|
|
||||||
setAnchor(anchor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withText(const std::string &text) {
|
|
||||||
setText(text);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withFont(Ptr<FontAtlas> font) {
|
|
||||||
setFont(font);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withTextColor(const Color &color) {
|
|
||||||
setTextColor(color);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withBackgroundColor(const Color &normal, const Color &hover,
|
|
||||||
const Color &pressed) {
|
|
||||||
setBackgroundColor(normal, hover, pressed);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withSize(float width, float height) {
|
|
||||||
setSize(width, height);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withPadding(const Vec2 &padding) {
|
|
||||||
setPadding(padding);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withPadding(float x, float y) {
|
|
||||||
setPadding(Vec2(x, y));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withBorder(const Color &color, float width) {
|
|
||||||
setBorder(color, width);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withCornerRadius(float radius) {
|
|
||||||
setCornerRadius(radius);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withRoundedCornersEnabled(bool enabled) {
|
|
||||||
setRoundedCornersEnabled(enabled);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withHoverCursor(CursorShape cursor) {
|
|
||||||
setHoverCursor(cursor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用 - 坐标空间设置
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Button *Button::withCoordinateSpace(CoordinateSpace space) {
|
|
||||||
setCoordinateSpace(space);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withScreenPosition(float x, float y) {
|
|
||||||
setScreenPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withScreenPosition(const Vec2 &pos) {
|
|
||||||
setScreenPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withCameraOffset(float x, float y) {
|
|
||||||
setCameraOffset(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Button *Button::withCameraOffset(const Vec2 &offset) {
|
|
||||||
setCameraOffset(offset);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// 普通设置方法
|
// 普通设置方法
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief 设置按钮文本
|
||||||
|
* @param text 文本内容
|
||||||
|
*/
|
||||||
void Button::setText(const std::string &text) {
|
void Button::setText(const std::string &text) {
|
||||||
text_ = text;
|
text_ = text;
|
||||||
if (font_ && getSize().empty()) {
|
if (font_ && getSize().empty()) {
|
||||||
|
|
@ -181,6 +99,10 @@ void Button::setText(const std::string &text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体
|
||||||
|
* @param font 字体图集指针
|
||||||
|
*/
|
||||||
void Button::setFont(Ptr<FontAtlas> font) {
|
void Button::setFont(Ptr<FontAtlas> font) {
|
||||||
font_ = font;
|
font_ = font;
|
||||||
if (font_ && getSize().empty() && !text_.empty()) {
|
if (font_ && getSize().empty() && !text_.empty()) {
|
||||||
|
|
@ -189,6 +111,10 @@ void Button::setFont(Ptr<FontAtlas> font) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置内边距(Vec2版本)
|
||||||
|
* @param padding 内边距向量
|
||||||
|
*/
|
||||||
void Button::setPadding(const Vec2 &padding) {
|
void Button::setPadding(const Vec2 &padding) {
|
||||||
padding_ = padding;
|
padding_ = padding;
|
||||||
if (font_ && getSize().empty() && !text_.empty()) {
|
if (font_ && getSize().empty() && !text_.empty()) {
|
||||||
|
|
@ -197,8 +123,27 @@ void Button::setPadding(const Vec2 &padding) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置内边距(分量版本)
|
||||||
|
* @param x X方向内边距
|
||||||
|
* @param y Y方向内边距
|
||||||
|
*/
|
||||||
|
void Button::setPadding(float x, float y) {
|
||||||
|
setPadding(Vec2(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本颜色
|
||||||
|
* @param color 文本颜色
|
||||||
|
*/
|
||||||
void Button::setTextColor(const Color &color) { textColor_ = color; }
|
void Button::setTextColor(const Color &color) { textColor_ = color; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置背景颜色
|
||||||
|
* @param normal 普通状态颜色
|
||||||
|
* @param hover 悬停状态颜色
|
||||||
|
* @param pressed 按下状态颜色
|
||||||
|
*/
|
||||||
void Button::setBackgroundColor(const Color &normal, const Color &hover,
|
void Button::setBackgroundColor(const Color &normal, const Color &hover,
|
||||||
const Color &pressed) {
|
const Color &pressed) {
|
||||||
bgNormal_ = normal;
|
bgNormal_ = normal;
|
||||||
|
|
@ -206,29 +151,58 @@ void Button::setBackgroundColor(const Color &normal, const Color &hover,
|
||||||
bgPressed_ = pressed;
|
bgPressed_ = pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置边框
|
||||||
|
* @param color 边框颜色
|
||||||
|
* @param width 边框宽度
|
||||||
|
*/
|
||||||
void Button::setBorder(const Color &color, float width) {
|
void Button::setBorder(const Color &color, float width) {
|
||||||
borderColor_ = color;
|
borderColor_ = color;
|
||||||
borderWidth_ = width;
|
borderWidth_ = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置圆角半径
|
||||||
|
* @param radius 圆角半径
|
||||||
|
*/
|
||||||
void Button::setCornerRadius(float radius) {
|
void Button::setCornerRadius(float radius) {
|
||||||
cornerRadius_ = std::max(0.0f, radius);
|
cornerRadius_ = std::max(0.0f, radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用圆角
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void Button::setRoundedCornersEnabled(bool enabled) {
|
void Button::setRoundedCornersEnabled(bool enabled) {
|
||||||
roundedCornersEnabled_ = enabled;
|
roundedCornersEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否使用Alpha遮罩进行点击检测
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void Button::setUseAlphaMaskForHitTest(bool enabled) {
|
void Button::setUseAlphaMaskForHitTest(bool enabled) {
|
||||||
useAlphaMaskForHitTest_ = enabled;
|
useAlphaMaskForHitTest_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置点击回调
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
void Button::setOnClick(Function<void()> callback) {
|
void Button::setOnClick(Function<void()> callback) {
|
||||||
onClick_ = std::move(callback);
|
onClick_ = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否为切换模式
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void Button::setToggleMode(bool enabled) { toggleMode_ = enabled; }
|
void Button::setToggleMode(bool enabled) { toggleMode_ = enabled; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置开关状态
|
||||||
|
* @param on 是否开启
|
||||||
|
*/
|
||||||
void Button::setOn(bool on) {
|
void Button::setOn(bool on) {
|
||||||
if (isOn_ != on) {
|
if (isOn_ != on) {
|
||||||
isOn_ = on;
|
isOn_ = on;
|
||||||
|
|
@ -238,12 +212,24 @@ void Button::setOn(bool on) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 切换状态
|
||||||
|
*/
|
||||||
void Button::toggle() { setOn(!isOn_); }
|
void Button::toggle() { setOn(!isOn_); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置状态改变回调
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
void Button::setOnStateChange(Function<void(bool)> callback) {
|
void Button::setOnStateChange(Function<void(bool)> callback) {
|
||||||
onStateChange_ = std::move(callback);
|
onStateChange_ = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置状态文字
|
||||||
|
* @param textOff 关闭状态文字
|
||||||
|
* @param textOn 开启状态文字
|
||||||
|
*/
|
||||||
void Button::setStateText(const std::string &textOff,
|
void Button::setStateText(const std::string &textOff,
|
||||||
const std::string &textOn) {
|
const std::string &textOn) {
|
||||||
textOff_ = textOff;
|
textOff_ = textOff;
|
||||||
|
|
@ -251,14 +237,29 @@ void Button::setStateText(const std::string &textOff,
|
||||||
useStateText_ = true;
|
useStateText_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置状态文字颜色
|
||||||
|
* @param colorOff 关闭状态颜色
|
||||||
|
* @param colorOn 开启状态颜色
|
||||||
|
*/
|
||||||
void Button::setStateTextColor(const Color &colorOff, const Color &colorOn) {
|
void Button::setStateTextColor(const Color &colorOff, const Color &colorOn) {
|
||||||
textColorOff_ = colorOff;
|
textColorOff_ = colorOff;
|
||||||
textColorOn_ = colorOn;
|
textColorOn_ = colorOn;
|
||||||
useStateTextColor_ = true;
|
useStateTextColor_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置悬停光标
|
||||||
|
* @param cursor 光标形状
|
||||||
|
*/
|
||||||
void Button::setHoverCursor(CursorShape cursor) { hoverCursor_ = cursor; }
|
void Button::setHoverCursor(CursorShape cursor) { hoverCursor_ = cursor; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置背景图片
|
||||||
|
* @param normal 普通状态图片
|
||||||
|
* @param hover 悬停状态图片
|
||||||
|
* @param pressed 按下状态图片
|
||||||
|
*/
|
||||||
void Button::setBackgroundImage(Ptr<Texture> normal, Ptr<Texture> hover,
|
void Button::setBackgroundImage(Ptr<Texture> normal, Ptr<Texture> hover,
|
||||||
Ptr<Texture> pressed) {
|
Ptr<Texture> pressed) {
|
||||||
imgNormal_ = normal;
|
imgNormal_ = normal;
|
||||||
|
|
@ -273,6 +274,11 @@ void Button::setBackgroundImage(Ptr<Texture> normal, Ptr<Texture> hover,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置背景图片(带矩形区域)
|
||||||
|
* @param texture 纹理
|
||||||
|
* @param rect 矩形区域
|
||||||
|
*/
|
||||||
void Button::setBackgroundImage(Ptr<Texture> texture, const Rect &rect) {
|
void Button::setBackgroundImage(Ptr<Texture> texture, const Rect &rect) {
|
||||||
imgNormal_ = texture;
|
imgNormal_ = texture;
|
||||||
imgHover_ = texture;
|
imgHover_ = texture;
|
||||||
|
|
@ -289,6 +295,15 @@ void Button::setBackgroundImage(Ptr<Texture> texture, const Rect &rect) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置状态背景图片
|
||||||
|
* @param offNormal 关闭状态普通图片
|
||||||
|
* @param onNormal 开启状态普通图片
|
||||||
|
* @param offHover 关闭状态悬停图片
|
||||||
|
* @param onHover 开启状态悬停图片
|
||||||
|
* @param offPressed 关闭状态按下图片
|
||||||
|
* @param onPressed 开启状态按下图片
|
||||||
|
*/
|
||||||
void Button::setStateBackgroundImage(
|
void Button::setStateBackgroundImage(
|
||||||
Ptr<Texture> offNormal, Ptr<Texture> onNormal, Ptr<Texture> offHover,
|
Ptr<Texture> offNormal, Ptr<Texture> onNormal, Ptr<Texture> offHover,
|
||||||
Ptr<Texture> onHover, Ptr<Texture> offPressed, Ptr<Texture> onPressed) {
|
Ptr<Texture> onHover, Ptr<Texture> offPressed, Ptr<Texture> onPressed) {
|
||||||
|
|
@ -309,6 +324,10 @@ void Button::setStateBackgroundImage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置背景图片缩放模式
|
||||||
|
* @param mode 缩放模式
|
||||||
|
*/
|
||||||
void Button::setBackgroundImageScaleMode(ImageScaleMode mode) {
|
void Button::setBackgroundImageScaleMode(ImageScaleMode mode) {
|
||||||
scaleMode_ = mode;
|
scaleMode_ = mode;
|
||||||
if (useImageBackground_ && scaleMode_ == ImageScaleMode::Original &&
|
if (useImageBackground_ && scaleMode_ == ImageScaleMode::Original &&
|
||||||
|
|
@ -318,12 +337,25 @@ void Button::setBackgroundImageScaleMode(ImageScaleMode mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置自定义尺寸(Vec2版本)
|
||||||
|
* @param size 尺寸向量
|
||||||
|
*/
|
||||||
void Button::setCustomSize(const Vec2 &size) { setSize(size.x, size.y); }
|
void Button::setCustomSize(const Vec2 &size) { setSize(size.x, size.y); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置自定义尺寸(分量版本)
|
||||||
|
* @param width 宽度
|
||||||
|
* @param height 高度
|
||||||
|
*/
|
||||||
void Button::setCustomSize(float width, float height) {
|
void Button::setCustomSize(float width, float height) {
|
||||||
setSize(width, height);
|
setSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取边界框
|
||||||
|
* @return 边界矩形
|
||||||
|
*/
|
||||||
Rect Button::getBoundingBox() const {
|
Rect Button::getBoundingBox() const {
|
||||||
auto pos = getRenderPosition();
|
auto pos = getRenderPosition();
|
||||||
auto anchor = getAnchor();
|
auto anchor = getAnchor();
|
||||||
|
|
@ -342,6 +374,12 @@ Rect Button::getBoundingBox() const {
|
||||||
return Rect(x0, y0, w, h);
|
return Rect(x0, y0, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 计算图片尺寸
|
||||||
|
* @param buttonSize 按钮尺寸
|
||||||
|
* @param imageSize 图片尺寸
|
||||||
|
* @return 计算后的图片尺寸
|
||||||
|
*/
|
||||||
Vec2 Button::calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize) {
|
Vec2 Button::calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize) {
|
||||||
switch (scaleMode_) {
|
switch (scaleMode_) {
|
||||||
case ImageScaleMode::Original:
|
case ImageScaleMode::Original:
|
||||||
|
|
@ -367,11 +405,15 @@ Vec2 Button::calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize) {
|
||||||
return imageSize;
|
return imageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制背景图片
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
* @param rect 绘制区域
|
||||||
|
*/
|
||||||
void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
|
void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
|
||||||
Texture *texture = nullptr;
|
Texture *texture = nullptr;
|
||||||
Rect srcRect;
|
Rect srcRect;
|
||||||
|
|
||||||
// 如果使用状态图片,根据 isOn_ 状态选择对应的图片
|
|
||||||
if (useStateImages_) {
|
if (useStateImages_) {
|
||||||
if (isOn_) {
|
if (isOn_) {
|
||||||
if (pressed_ && imgOnPressed_) {
|
if (pressed_ && imgOnPressed_) {
|
||||||
|
|
@ -395,7 +437,6 @@ void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
|
||||||
static_cast<float>(texture->getHeight()));
|
static_cast<float>(texture->getHeight()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 使用普通图片背景
|
|
||||||
if (pressed_ && imgPressed_) {
|
if (pressed_ && imgPressed_) {
|
||||||
texture = imgPressed_.get();
|
texture = imgPressed_.get();
|
||||||
srcRect = useTextureRect_
|
srcRect = useTextureRect_
|
||||||
|
|
@ -433,6 +474,13 @@ void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
|
||||||
Vec2::Zero());
|
Vec2::Zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制圆角矩形边框
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
* @param rect 矩形区域
|
||||||
|
* @param color 颜色
|
||||||
|
* @param radius 圆角半径
|
||||||
|
*/
|
||||||
void Button::drawRoundedRect(RenderBackend &renderer, const Rect &rect,
|
void Button::drawRoundedRect(RenderBackend &renderer, const Rect &rect,
|
||||||
const Color &color, float radius) {
|
const Color &color, float radius) {
|
||||||
float maxRadius = std::min(rect.size.width, rect.size.height) * 0.5f;
|
float maxRadius = std::min(rect.size.width, rect.size.height) * 0.5f;
|
||||||
|
|
@ -489,6 +537,13 @@ void Button::drawRoundedRect(RenderBackend &renderer, const Rect &rect,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 填充圆角矩形
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
* @param rect 矩形区域
|
||||||
|
* @param color 颜色
|
||||||
|
* @param radius 圆角半径
|
||||||
|
*/
|
||||||
void Button::fillRoundedRect(RenderBackend &renderer, const Rect &rect,
|
void Button::fillRoundedRect(RenderBackend &renderer, const Rect &rect,
|
||||||
const Color &color, float radius) {
|
const Color &color, float radius) {
|
||||||
float maxRadius = std::min(rect.size.width, rect.size.height) * 0.5f;
|
float maxRadius = std::min(rect.size.width, rect.size.height) * 0.5f;
|
||||||
|
|
@ -556,6 +611,10 @@ void Button::fillRoundedRect(RenderBackend &renderer, const Rect &rect,
|
||||||
renderer.fillPolygon(vertices, color);
|
renderer.fillPolygon(vertices, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制组件
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
*/
|
||||||
void Button::onDrawWidget(RenderBackend &renderer) {
|
void Button::onDrawWidget(RenderBackend &renderer) {
|
||||||
Rect rect = getBoundingBox();
|
Rect rect = getBoundingBox();
|
||||||
if (rect.empty()) {
|
if (rect.empty()) {
|
||||||
|
|
@ -563,7 +622,6 @@ void Button::onDrawWidget(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useImageBackground_) {
|
if (useImageBackground_) {
|
||||||
// 使用图片背景时不绘制纯色背景和边框
|
|
||||||
drawBackgroundImage(renderer, rect);
|
drawBackgroundImage(renderer, rect);
|
||||||
} else {
|
} else {
|
||||||
renderer.endSpriteBatch();
|
renderer.endSpriteBatch();
|
||||||
|
|
@ -583,7 +641,6 @@ void Button::onDrawWidget(RenderBackend &renderer) {
|
||||||
|
|
||||||
renderer.beginSpriteBatch();
|
renderer.beginSpriteBatch();
|
||||||
|
|
||||||
// 纯色背景模式下才绘制边框
|
|
||||||
renderer.endSpriteBatch();
|
renderer.endSpriteBatch();
|
||||||
|
|
||||||
if (borderWidth_ > 0.0f) {
|
if (borderWidth_ > 0.0f) {
|
||||||
|
|
@ -598,7 +655,6 @@ void Button::onDrawWidget(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font_) {
|
if (font_) {
|
||||||
// 确定要显示的文字
|
|
||||||
std::string textToDraw;
|
std::string textToDraw;
|
||||||
if (useStateText_) {
|
if (useStateText_) {
|
||||||
textToDraw = isOn_ ? textOn_ : textOff_;
|
textToDraw = isOn_ ? textOn_ : textOff_;
|
||||||
|
|
@ -606,7 +662,6 @@ void Button::onDrawWidget(RenderBackend &renderer) {
|
||||||
textToDraw = text_;
|
textToDraw = text_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确定文字颜色
|
|
||||||
Color colorToUse;
|
Color colorToUse;
|
||||||
if (useStateTextColor_) {
|
if (useStateTextColor_) {
|
||||||
colorToUse = isOn_ ? textColorOn_ : textColorOff_;
|
colorToUse = isOn_ ? textColorOn_ : textColorOff_;
|
||||||
|
|
|
||||||
|
|
@ -4,92 +4,37 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 默认构造函数
|
||||||
|
*/
|
||||||
CheckBox::CheckBox() {
|
CheckBox::CheckBox() {
|
||||||
setAnchor(0.0f, 0.0f);
|
setAnchor(0.0f, 0.0f);
|
||||||
setSize(boxSize_, boxSize_);
|
setSize(boxSize_, boxSize_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建复选框对象
|
||||||
|
* @return 复选框对象指针
|
||||||
|
*/
|
||||||
Ptr<CheckBox> CheckBox::create() {
|
Ptr<CheckBox> CheckBox::create() {
|
||||||
return makePtr<CheckBox>();
|
return makePtr<CheckBox>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带标签的复选框对象
|
||||||
|
* @param label 标签文本
|
||||||
|
* @return 复选框对象指针
|
||||||
|
*/
|
||||||
Ptr<CheckBox> CheckBox::create(const std::string &label) {
|
Ptr<CheckBox> CheckBox::create(const std::string &label) {
|
||||||
auto cb = makePtr<CheckBox>();
|
auto cb = makePtr<CheckBox>();
|
||||||
cb->setLabel(label);
|
cb->setLabel(label);
|
||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
/**
|
||||||
// 链式调用构建器方法
|
* @brief 设置选中状态
|
||||||
// ------------------------------------------------------------------------
|
* @param checked 是否选中
|
||||||
CheckBox *CheckBox::withPosition(float x, float y) {
|
*/
|
||||||
setPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withPosition(const Vec2 &pos) {
|
|
||||||
setPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withAnchor(float x, float y) {
|
|
||||||
setAnchor(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withAnchor(const Vec2 &anchor) {
|
|
||||||
setAnchor(anchor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withText(const std::string &text) {
|
|
||||||
setLabel(text);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withFont(Ptr<FontAtlas> font) {
|
|
||||||
setFont(font);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withTextColor(const Color &color) {
|
|
||||||
setTextColor(color);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withSize(float width, float height) {
|
|
||||||
setSize(width, height);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用 - 坐标空间设置
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
CheckBox *CheckBox::withCoordinateSpace(CoordinateSpace space) {
|
|
||||||
setCoordinateSpace(space);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withScreenPosition(float x, float y) {
|
|
||||||
setScreenPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withScreenPosition(const Vec2 &pos) {
|
|
||||||
setScreenPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withCameraOffset(float x, float y) {
|
|
||||||
setCameraOffset(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckBox *CheckBox::withCameraOffset(const Vec2 &offset) {
|
|
||||||
setCameraOffset(offset);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckBox::setChecked(bool checked) {
|
void CheckBox::setChecked(bool checked) {
|
||||||
if (checked_ != checked) {
|
if (checked_ != checked) {
|
||||||
checked_ = checked;
|
checked_ = checked;
|
||||||
|
|
@ -99,46 +44,89 @@ void CheckBox::setChecked(bool checked) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 切换选中状态
|
||||||
|
*/
|
||||||
void CheckBox::toggle() {
|
void CheckBox::toggle() {
|
||||||
setChecked(!checked_);
|
setChecked(!checked_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置标签文本
|
||||||
|
* @param label 标签文本
|
||||||
|
*/
|
||||||
void CheckBox::setLabel(const std::string &label) {
|
void CheckBox::setLabel(const std::string &label) {
|
||||||
label_ = label;
|
label_ = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体
|
||||||
|
* @param font 字体图集指针
|
||||||
|
*/
|
||||||
void CheckBox::setFont(Ptr<FontAtlas> font) {
|
void CheckBox::setFont(Ptr<FontAtlas> font) {
|
||||||
font_ = font;
|
font_ = font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本颜色
|
||||||
|
* @param color 文本颜色
|
||||||
|
*/
|
||||||
void CheckBox::setTextColor(const Color &color) {
|
void CheckBox::setTextColor(const Color &color) {
|
||||||
textColor_ = color;
|
textColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置复选框尺寸
|
||||||
|
* @param size 复选框尺寸
|
||||||
|
*/
|
||||||
void CheckBox::setBoxSize(float size) {
|
void CheckBox::setBoxSize(float size) {
|
||||||
boxSize_ = size;
|
boxSize_ = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置间距
|
||||||
|
* @param spacing 间距值
|
||||||
|
*/
|
||||||
void CheckBox::setSpacing(float spacing) {
|
void CheckBox::setSpacing(float spacing) {
|
||||||
spacing_ = spacing;
|
spacing_ = spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置选中颜色
|
||||||
|
* @param color 选中颜色
|
||||||
|
*/
|
||||||
void CheckBox::setCheckedColor(const Color &color) {
|
void CheckBox::setCheckedColor(const Color &color) {
|
||||||
checkedColor_ = color;
|
checkedColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置未选中颜色
|
||||||
|
* @param color 未选中颜色
|
||||||
|
*/
|
||||||
void CheckBox::setUncheckedColor(const Color &color) {
|
void CheckBox::setUncheckedColor(const Color &color) {
|
||||||
uncheckedColor_ = color;
|
uncheckedColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置勾选标记颜色
|
||||||
|
* @param color 勾选标记颜色
|
||||||
|
*/
|
||||||
void CheckBox::setCheckMarkColor(const Color &color) {
|
void CheckBox::setCheckMarkColor(const Color &color) {
|
||||||
checkMarkColor_ = color;
|
checkMarkColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置状态改变回调
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
void CheckBox::setOnStateChange(Function<void(bool)> callback) {
|
void CheckBox::setOnStateChange(Function<void(bool)> callback) {
|
||||||
onStateChange_ = callback;
|
onStateChange_ = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取边界框
|
||||||
|
* @return 边界矩形
|
||||||
|
*/
|
||||||
Rect CheckBox::getBoundingBox() const {
|
Rect CheckBox::getBoundingBox() const {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
float width = boxSize_;
|
float width = boxSize_;
|
||||||
|
|
@ -151,16 +139,18 @@ Rect CheckBox::getBoundingBox() const {
|
||||||
return Rect(pos.x, pos.y, width, boxSize_);
|
return Rect(pos.x, pos.y, width, boxSize_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制组件
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
*/
|
||||||
void CheckBox::onDrawWidget(RenderBackend &renderer) {
|
void CheckBox::onDrawWidget(RenderBackend &renderer) {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
|
|
||||||
// 绘制复选框
|
|
||||||
Rect boxRect(pos.x, pos.y + (getSize().height - boxSize_) * 0.5f, boxSize_, boxSize_);
|
Rect boxRect(pos.x, pos.y + (getSize().height - boxSize_) * 0.5f, boxSize_, boxSize_);
|
||||||
Color boxColor = checked_ ? checkedColor_ : uncheckedColor_;
|
Color boxColor = checked_ ? checkedColor_ : uncheckedColor_;
|
||||||
renderer.fillRect(boxRect, boxColor);
|
renderer.fillRect(boxRect, boxColor);
|
||||||
renderer.drawRect(boxRect, Colors::White, 1.0f);
|
renderer.drawRect(boxRect, Colors::White, 1.0f);
|
||||||
|
|
||||||
// 绘制勾选标记
|
|
||||||
if (checked_) {
|
if (checked_) {
|
||||||
float padding = boxSize_ * 0.2f;
|
float padding = boxSize_ * 0.2f;
|
||||||
float x1 = boxRect.origin.x + padding;
|
float x1 = boxRect.origin.x + padding;
|
||||||
|
|
@ -170,18 +160,21 @@ void CheckBox::onDrawWidget(RenderBackend &renderer) {
|
||||||
float x3 = boxRect.origin.x + boxSize_ - padding;
|
float x3 = boxRect.origin.x + boxSize_ - padding;
|
||||||
float y3 = boxRect.origin.y + padding;
|
float y3 = boxRect.origin.y + padding;
|
||||||
|
|
||||||
// 简化的勾选标记绘制
|
|
||||||
renderer.drawLine(Vec2(x1, y1), Vec2(x2, y2), checkMarkColor_, 2.0f);
|
renderer.drawLine(Vec2(x1, y1), Vec2(x2, y2), checkMarkColor_, 2.0f);
|
||||||
renderer.drawLine(Vec2(x2, y2), Vec2(x3, y3), checkMarkColor_, 2.0f);
|
renderer.drawLine(Vec2(x2, y2), Vec2(x3, y3), checkMarkColor_, 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制标签
|
|
||||||
if (!label_.empty() && font_) {
|
if (!label_.empty() && font_) {
|
||||||
Vec2 textPos(pos.x + boxSize_ + spacing_, pos.y);
|
Vec2 textPos(pos.x + boxSize_ + spacing_, pos.y);
|
||||||
renderer.drawText(*font_, label_, textPos, textColor_);
|
renderer.drawText(*font_, label_, textPos, textColor_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标按下事件处理
|
||||||
|
* @param event 鼠标事件
|
||||||
|
* @return 是否处理了事件
|
||||||
|
*/
|
||||||
bool CheckBox::onMousePress(const MouseEvent &event) {
|
bool CheckBox::onMousePress(const MouseEvent &event) {
|
||||||
if (event.button == MouseButton::Left) {
|
if (event.button == MouseButton::Left) {
|
||||||
pressed_ = true;
|
pressed_ = true;
|
||||||
|
|
@ -190,6 +183,11 @@ bool CheckBox::onMousePress(const MouseEvent &event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标释放事件处理
|
||||||
|
* @param event 鼠标事件
|
||||||
|
* @return 是否处理了事件
|
||||||
|
*/
|
||||||
bool CheckBox::onMouseRelease(const MouseEvent &event) {
|
bool CheckBox::onMouseRelease(const MouseEvent &event) {
|
||||||
if (event.button == MouseButton::Left && pressed_) {
|
if (event.button == MouseButton::Left && pressed_) {
|
||||||
pressed_ = false;
|
pressed_ = false;
|
||||||
|
|
|
||||||
|
|
@ -4,178 +4,196 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 默认构造函数
|
||||||
|
*/
|
||||||
Label::Label() {
|
Label::Label() {
|
||||||
// 标签默认锚点为左上角
|
|
||||||
setAnchor(0.0f, 0.0f);
|
setAnchor(0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 带文本的构造函数
|
||||||
|
* @param text 初始文本内容
|
||||||
|
*/
|
||||||
Label::Label(const std::string &text) : text_(text) {
|
Label::Label(const std::string &text) : text_(text) {
|
||||||
setAnchor(0.0f, 0.0f);
|
setAnchor(0.0f, 0.0f);
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建空标签对象
|
||||||
|
* @return 标签对象指针
|
||||||
|
*/
|
||||||
Ptr<Label> Label::create() {
|
Ptr<Label> Label::create() {
|
||||||
return makePtr<Label>();
|
return makePtr<Label>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带文本的标签对象
|
||||||
|
* @param text 文本内容
|
||||||
|
* @return 标签对象指针
|
||||||
|
*/
|
||||||
Ptr<Label> Label::create(const std::string &text) {
|
Ptr<Label> Label::create(const std::string &text) {
|
||||||
return makePtr<Label>(text);
|
return makePtr<Label>(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带文本和字体的标签对象
|
||||||
|
* @param text 文本内容
|
||||||
|
* @param font 字体图集
|
||||||
|
* @return 标签对象指针
|
||||||
|
*/
|
||||||
Ptr<Label> Label::create(const std::string &text, Ptr<FontAtlas> font) {
|
Ptr<Label> Label::create(const std::string &text, Ptr<FontAtlas> font) {
|
||||||
auto label = makePtr<Label>(text);
|
auto label = makePtr<Label>(text);
|
||||||
label->setFont(font);
|
label->setFont(font);
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
/**
|
||||||
// 链式调用构建器方法
|
* @brief 设置文本内容
|
||||||
// ------------------------------------------------------------------------
|
* @param text 新的文本内容
|
||||||
Label *Label::withPosition(float x, float y) {
|
*/
|
||||||
setPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withPosition(const Vec2 &pos) {
|
|
||||||
setPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withAnchor(float x, float y) {
|
|
||||||
setAnchor(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withAnchor(const Vec2 &anchor) {
|
|
||||||
setAnchor(anchor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withText(const std::string &text) {
|
|
||||||
setText(text);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withFont(Ptr<FontAtlas> font) {
|
|
||||||
setFont(font);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withTextColor(const Color &color) {
|
|
||||||
setTextColor(color);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withFontSize(int size) {
|
|
||||||
setFontSize(size);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 坐标空间设置(链式调用)
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Label *Label::withCoordinateSpace(CoordinateSpace space) {
|
|
||||||
setCoordinateSpace(space);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withScreenPosition(float x, float y) {
|
|
||||||
setScreenPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withScreenPosition(const Vec2 &pos) {
|
|
||||||
setScreenPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withCameraOffset(float x, float y) {
|
|
||||||
setCameraOffset(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *Label::withCameraOffset(const Vec2 &offset) {
|
|
||||||
setCameraOffset(offset);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Label::setText(const std::string &text) {
|
void Label::setText(const std::string &text) {
|
||||||
text_ = text;
|
text_ = text;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体
|
||||||
|
* @param font 字体图集指针
|
||||||
|
*/
|
||||||
void Label::setFont(Ptr<FontAtlas> font) {
|
void Label::setFont(Ptr<FontAtlas> font) {
|
||||||
font_ = font;
|
font_ = font;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本颜色
|
||||||
|
* @param color 文本颜色
|
||||||
|
*/
|
||||||
void Label::setTextColor(const Color &color) {
|
void Label::setTextColor(const Color &color) {
|
||||||
textColor_ = color;
|
textColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体大小
|
||||||
|
* @param size 字体大小
|
||||||
|
*/
|
||||||
void Label::setFontSize(int size) {
|
void Label::setFontSize(int size) {
|
||||||
fontSize_ = size;
|
fontSize_ = size;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置水平对齐方式
|
||||||
|
* @param align 对齐方式
|
||||||
|
*/
|
||||||
void Label::setHorizontalAlign(HorizontalAlign align) {
|
void Label::setHorizontalAlign(HorizontalAlign align) {
|
||||||
hAlign_ = align;
|
hAlign_ = align;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置垂直对齐方式
|
||||||
|
* @param align 垂直对齐方式
|
||||||
|
*/
|
||||||
void Label::setVerticalAlign(VerticalAlign align) {
|
void Label::setVerticalAlign(VerticalAlign align) {
|
||||||
vAlign_ = align;
|
vAlign_ = align;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置阴影是否启用
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void Label::setShadowEnabled(bool enabled) {
|
void Label::setShadowEnabled(bool enabled) {
|
||||||
shadowEnabled_ = enabled;
|
shadowEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置阴影颜色
|
||||||
|
* @param color 阴影颜色
|
||||||
|
*/
|
||||||
void Label::setShadowColor(const Color &color) {
|
void Label::setShadowColor(const Color &color) {
|
||||||
shadowColor_ = color;
|
shadowColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置阴影偏移
|
||||||
|
* @param offset 偏移向量
|
||||||
|
*/
|
||||||
void Label::setShadowOffset(const Vec2 &offset) {
|
void Label::setShadowOffset(const Vec2 &offset) {
|
||||||
shadowOffset_ = offset;
|
shadowOffset_ = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置描边是否启用
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void Label::setOutlineEnabled(bool enabled) {
|
void Label::setOutlineEnabled(bool enabled) {
|
||||||
outlineEnabled_ = enabled;
|
outlineEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置描边颜色
|
||||||
|
* @param color 描边颜色
|
||||||
|
*/
|
||||||
void Label::setOutlineColor(const Color &color) {
|
void Label::setOutlineColor(const Color &color) {
|
||||||
outlineColor_ = color;
|
outlineColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置描边宽度
|
||||||
|
* @param width 描边宽度
|
||||||
|
*/
|
||||||
void Label::setOutlineWidth(float width) {
|
void Label::setOutlineWidth(float width) {
|
||||||
outlineWidth_ = width;
|
outlineWidth_ = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否多行模式
|
||||||
|
* @param multiLine 是否多行
|
||||||
|
*/
|
||||||
void Label::setMultiLine(bool multiLine) {
|
void Label::setMultiLine(bool multiLine) {
|
||||||
multiLine_ = multiLine;
|
multiLine_ = multiLine;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置行间距
|
||||||
|
* @param spacing 行间距倍数
|
||||||
|
*/
|
||||||
void Label::setLineSpacing(float spacing) {
|
void Label::setLineSpacing(float spacing) {
|
||||||
lineSpacing_ = spacing;
|
lineSpacing_ = spacing;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置最大宽度
|
||||||
|
* @param maxWidth 最大宽度
|
||||||
|
*/
|
||||||
void Label::setMaxWidth(float maxWidth) {
|
void Label::setMaxWidth(float maxWidth) {
|
||||||
maxWidth_ = maxWidth;
|
maxWidth_ = maxWidth;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取文本尺寸
|
||||||
|
* @return 文本的宽度和高度
|
||||||
|
*/
|
||||||
Vec2 Label::getTextSize() const {
|
Vec2 Label::getTextSize() const {
|
||||||
updateCache();
|
updateCache();
|
||||||
return cachedSize_;
|
return cachedSize_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取行高
|
||||||
|
* @return 行高值
|
||||||
|
*/
|
||||||
float Label::getLineHeight() const {
|
float Label::getLineHeight() const {
|
||||||
if (font_) {
|
if (font_) {
|
||||||
return font_->getLineHeight() * lineSpacing_;
|
return font_->getLineHeight() * lineSpacing_;
|
||||||
|
|
@ -183,6 +201,9 @@ float Label::getLineHeight() const {
|
||||||
return static_cast<float>(fontSize_) * lineSpacing_;
|
return static_cast<float>(fontSize_) * lineSpacing_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新缓存
|
||||||
|
*/
|
||||||
void Label::updateCache() const {
|
void Label::updateCache() const {
|
||||||
if (!sizeDirty_ || !font_) {
|
if (!sizeDirty_ || !font_) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -208,6 +229,10 @@ void Label::updateCache() const {
|
||||||
sizeDirty_ = false;
|
sizeDirty_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 分割文本为多行
|
||||||
|
* @return 分割后的行列表
|
||||||
|
*/
|
||||||
std::vector<std::string> Label::splitLines() const {
|
std::vector<std::string> Label::splitLines() const {
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
if (text_.empty()) {
|
if (text_.empty()) {
|
||||||
|
|
@ -219,17 +244,14 @@ std::vector<std::string> Label::splitLines() const {
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按换行符分割
|
|
||||||
size_t start = 0;
|
size_t start = 0;
|
||||||
size_t end = text_.find('\n');
|
size_t end = text_.find('\n');
|
||||||
|
|
||||||
while (end != std::string::npos) {
|
while (end != std::string::npos) {
|
||||||
std::string line = text_.substr(start, end - start);
|
std::string line = text_.substr(start, end - start);
|
||||||
|
|
||||||
// 如果单行超过最大宽度,需要自动换行
|
|
||||||
Vec2 lineSize = font_->measureText(line);
|
Vec2 lineSize = font_->measureText(line);
|
||||||
if (lineSize.x > maxWidth_) {
|
if (lineSize.x > maxWidth_) {
|
||||||
// 简单实现:按字符逐个尝试
|
|
||||||
std::string currentLine;
|
std::string currentLine;
|
||||||
for (size_t i = 0; i < line.length(); ++i) {
|
for (size_t i = 0; i < line.length(); ++i) {
|
||||||
std::string testLine = currentLine + line[i];
|
std::string testLine = currentLine + line[i];
|
||||||
|
|
@ -252,7 +274,6 @@ std::vector<std::string> Label::splitLines() const {
|
||||||
end = text_.find('\n', start);
|
end = text_.find('\n', start);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理最后一行
|
|
||||||
if (start < text_.length()) {
|
if (start < text_.length()) {
|
||||||
std::string line = text_.substr(start);
|
std::string line = text_.substr(start);
|
||||||
Vec2 lineSize = font_->measureText(line);
|
Vec2 lineSize = font_->measureText(line);
|
||||||
|
|
@ -279,16 +300,18 @@ std::vector<std::string> Label::splitLines() const {
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 计算绘制位置
|
||||||
|
* @return 绘制位置坐标
|
||||||
|
*/
|
||||||
Vec2 Label::calculateDrawPosition() const {
|
Vec2 Label::calculateDrawPosition() const {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
Vec2 size = getTextSize();
|
Vec2 size = getTextSize();
|
||||||
Size widgetSize = getSize();
|
Size widgetSize = getSize();
|
||||||
|
|
||||||
// 如果设置了控件大小,使用控件大小作为对齐参考
|
|
||||||
float refWidth = widgetSize.empty() ? size.x : widgetSize.width;
|
float refWidth = widgetSize.empty() ? size.x : widgetSize.width;
|
||||||
float refHeight = widgetSize.empty() ? size.y : widgetSize.height;
|
float refHeight = widgetSize.empty() ? size.y : widgetSize.height;
|
||||||
|
|
||||||
// 水平对齐
|
|
||||||
switch (hAlign_) {
|
switch (hAlign_) {
|
||||||
case HorizontalAlign::Center:
|
case HorizontalAlign::Center:
|
||||||
pos.x += (refWidth - size.x) * 0.5f;
|
pos.x += (refWidth - size.x) * 0.5f;
|
||||||
|
|
@ -301,7 +324,6 @@ Vec2 Label::calculateDrawPosition() const {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 垂直对齐
|
|
||||||
switch (vAlign_) {
|
switch (vAlign_) {
|
||||||
case VerticalAlign::Middle:
|
case VerticalAlign::Middle:
|
||||||
pos.y += (refHeight - size.y) * 0.5f;
|
pos.y += (refHeight - size.y) * 0.5f;
|
||||||
|
|
@ -317,6 +339,12 @@ Vec2 Label::calculateDrawPosition() const {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制文本
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
* @param position 绘制位置
|
||||||
|
* @param color 文本颜色
|
||||||
|
*/
|
||||||
void Label::drawText(RenderBackend &renderer, const Vec2 &position, const Color &color) {
|
void Label::drawText(RenderBackend &renderer, const Vec2 &position, const Color &color) {
|
||||||
if (!font_ || text_.empty()) {
|
if (!font_ || text_.empty()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -336,6 +364,10 @@ void Label::drawText(RenderBackend &renderer, const Vec2 &position, const Color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取边界框
|
||||||
|
* @return 边界矩形
|
||||||
|
*/
|
||||||
Rect Label::getBoundingBox() const {
|
Rect Label::getBoundingBox() const {
|
||||||
if (!font_ || text_.empty()) {
|
if (!font_ || text_.empty()) {
|
||||||
return Rect();
|
return Rect();
|
||||||
|
|
@ -351,6 +383,10 @@ Rect Label::getBoundingBox() const {
|
||||||
return Rect(pos.x, pos.y, size.x, size.y);
|
return Rect(pos.x, pos.y, size.x, size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制组件
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
*/
|
||||||
void Label::onDrawWidget(RenderBackend &renderer) {
|
void Label::onDrawWidget(RenderBackend &renderer) {
|
||||||
if (!font_ || text_.empty()) {
|
if (!font_ || text_.empty()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -358,13 +394,11 @@ void Label::onDrawWidget(RenderBackend &renderer) {
|
||||||
|
|
||||||
Vec2 pos = calculateDrawPosition();
|
Vec2 pos = calculateDrawPosition();
|
||||||
|
|
||||||
// 绘制阴影
|
|
||||||
if (shadowEnabled_) {
|
if (shadowEnabled_) {
|
||||||
Vec2 shadowPos = pos + shadowOffset_;
|
Vec2 shadowPos = pos + shadowOffset_;
|
||||||
drawText(renderer, shadowPos, shadowColor_);
|
drawText(renderer, shadowPos, shadowColor_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制描边(简化实现:向8个方向偏移绘制)
|
|
||||||
if (outlineEnabled_) {
|
if (outlineEnabled_) {
|
||||||
float w = outlineWidth_;
|
float w = outlineWidth_;
|
||||||
drawText(renderer, pos + Vec2(-w, -w), outlineColor_);
|
drawText(renderer, pos + Vec2(-w, -w), outlineColor_);
|
||||||
|
|
@ -377,7 +411,6 @@ void Label::onDrawWidget(RenderBackend &renderer) {
|
||||||
drawText(renderer, pos + Vec2(w, w), outlineColor_);
|
drawText(renderer, pos + Vec2(w, w), outlineColor_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制主文本
|
|
||||||
drawText(renderer, pos, textColor_);
|
drawText(renderer, pos, textColor_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,29 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 默认构造函数
|
||||||
|
*/
|
||||||
ProgressBar::ProgressBar() {
|
ProgressBar::ProgressBar() {
|
||||||
setAnchor(0.0f, 0.0f);
|
setAnchor(0.0f, 0.0f);
|
||||||
setSize(200.0f, 20.0f);
|
setSize(200.0f, 20.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建进度条对象
|
||||||
|
* @return 进度条对象指针
|
||||||
|
*/
|
||||||
Ptr<ProgressBar> ProgressBar::create() {
|
Ptr<ProgressBar> ProgressBar::create() {
|
||||||
return makePtr<ProgressBar>();
|
return makePtr<ProgressBar>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带范围的进度条对象
|
||||||
|
* @param min 最小值
|
||||||
|
* @param max 最大值
|
||||||
|
* @param value 当前值
|
||||||
|
* @return 进度条对象指针
|
||||||
|
*/
|
||||||
Ptr<ProgressBar> ProgressBar::create(float min, float max, float value) {
|
Ptr<ProgressBar> ProgressBar::create(float min, float max, float value) {
|
||||||
auto bar = makePtr<ProgressBar>();
|
auto bar = makePtr<ProgressBar>();
|
||||||
bar->setRange(min, max);
|
bar->setRange(min, max);
|
||||||
|
|
@ -21,71 +35,21 @@ Ptr<ProgressBar> ProgressBar::create(float min, float max, float value) {
|
||||||
return bar;
|
return bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
/**
|
||||||
// 链式调用构建器方法实现
|
* @brief 设置数值范围
|
||||||
// ============================================================================
|
* @param min 最小值
|
||||||
|
* @param max 最大值
|
||||||
ProgressBar *ProgressBar::withPosition(float x, float y) {
|
*/
|
||||||
setPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withPosition(const Vec2 &pos) {
|
|
||||||
setPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withAnchor(float x, float y) {
|
|
||||||
setAnchor(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withAnchor(const Vec2 &anchor) {
|
|
||||||
setAnchor(anchor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withSize(float width, float height) {
|
|
||||||
setSize(width, height);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withProgress(float progress) {
|
|
||||||
setValue(min_ + progress * (max_ - min_));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withCoordinateSpace(CoordinateSpace space) {
|
|
||||||
setCoordinateSpace(space);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withScreenPosition(float x, float y) {
|
|
||||||
setScreenPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withScreenPosition(const Vec2 &pos) {
|
|
||||||
setScreenPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withCameraOffset(float x, float y) {
|
|
||||||
setCameraOffset(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar *ProgressBar::withCameraOffset(const Vec2 &offset) {
|
|
||||||
setCameraOffset(offset);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProgressBar::setRange(float min, float max) {
|
void ProgressBar::setRange(float min, float max) {
|
||||||
min_ = min;
|
min_ = min;
|
||||||
max_ = max;
|
max_ = max;
|
||||||
setValue(value_);
|
setValue(value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置当前值
|
||||||
|
* @param value 新值
|
||||||
|
*/
|
||||||
void ProgressBar::setValue(float value) {
|
void ProgressBar::setValue(float value) {
|
||||||
value_ = std::clamp(value, min_, max_);
|
value_ = std::clamp(value, min_, max_);
|
||||||
|
|
||||||
|
|
@ -98,85 +62,165 @@ void ProgressBar::setValue(float value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取百分比
|
||||||
|
* @return 百分比值(0.0-1.0)
|
||||||
|
*/
|
||||||
float ProgressBar::getPercent() const {
|
float ProgressBar::getPercent() const {
|
||||||
if (max_ <= min_) return 0.0f;
|
if (max_ <= min_) return 0.0f;
|
||||||
return (displayValue_ - min_) / (max_ - min_);
|
return (displayValue_ - min_) / (max_ - min_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置方向
|
||||||
|
* @param dir 方向枚举
|
||||||
|
*/
|
||||||
void ProgressBar::setDirection(Direction dir) {
|
void ProgressBar::setDirection(Direction dir) {
|
||||||
direction_ = dir;
|
direction_ = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置背景颜色
|
||||||
|
* @param color 背景颜色
|
||||||
|
*/
|
||||||
void ProgressBar::setBackgroundColor(const Color &color) {
|
void ProgressBar::setBackgroundColor(const Color &color) {
|
||||||
bgColor_ = color;
|
bgColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置填充颜色
|
||||||
|
* @param color 填充颜色
|
||||||
|
*/
|
||||||
void ProgressBar::setFillColor(const Color &color) {
|
void ProgressBar::setFillColor(const Color &color) {
|
||||||
fillColor_ = color;
|
fillColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用渐变填充
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void ProgressBar::setGradientFillEnabled(bool enabled) {
|
void ProgressBar::setGradientFillEnabled(bool enabled) {
|
||||||
gradientEnabled_ = enabled;
|
gradientEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置渐变结束颜色
|
||||||
|
* @param color 结束颜色
|
||||||
|
*/
|
||||||
void ProgressBar::setFillColorEnd(const Color &color) {
|
void ProgressBar::setFillColorEnd(const Color &color) {
|
||||||
fillColorEnd_ = color;
|
fillColorEnd_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用分段颜色
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void ProgressBar::setSegmentedColorsEnabled(bool enabled) {
|
void ProgressBar::setSegmentedColorsEnabled(bool enabled) {
|
||||||
segmentedColorsEnabled_ = enabled;
|
segmentedColorsEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 添加颜色分段
|
||||||
|
* @param percentThreshold 百分比阈值
|
||||||
|
* @param color 颜色
|
||||||
|
*/
|
||||||
void ProgressBar::addColorSegment(float percentThreshold, const Color &color) {
|
void ProgressBar::addColorSegment(float percentThreshold, const Color &color) {
|
||||||
colorSegments_.push_back({percentThreshold, color});
|
colorSegments_.push_back({percentThreshold, color});
|
||||||
std::sort(colorSegments_.begin(), colorSegments_.end(),
|
std::sort(colorSegments_.begin(), colorSegments_.end(),
|
||||||
[](const auto &a, const auto &b) { return a.first > b.first; });
|
[](const auto &a, const auto &b) { return a.first > b.first; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 清除所有颜色分段
|
||||||
|
*/
|
||||||
void ProgressBar::clearColorSegments() {
|
void ProgressBar::clearColorSegments() {
|
||||||
colorSegments_.clear();
|
colorSegments_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置圆角半径
|
||||||
|
* @param radius 圆角半径
|
||||||
|
*/
|
||||||
void ProgressBar::setCornerRadius(float radius) {
|
void ProgressBar::setCornerRadius(float radius) {
|
||||||
cornerRadius_ = radius;
|
cornerRadius_ = radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用圆角
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void ProgressBar::setRoundedCornersEnabled(bool enabled) {
|
void ProgressBar::setRoundedCornersEnabled(bool enabled) {
|
||||||
roundedCornersEnabled_ = enabled;
|
roundedCornersEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用边框
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void ProgressBar::setBorderEnabled(bool enabled) {
|
void ProgressBar::setBorderEnabled(bool enabled) {
|
||||||
borderEnabled_ = enabled;
|
borderEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置边框颜色
|
||||||
|
* @param color 边框颜色
|
||||||
|
*/
|
||||||
void ProgressBar::setBorderColor(const Color &color) {
|
void ProgressBar::setBorderColor(const Color &color) {
|
||||||
borderColor_ = color;
|
borderColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置边框宽度
|
||||||
|
* @param width 边框宽度
|
||||||
|
*/
|
||||||
void ProgressBar::setBorderWidth(float width) {
|
void ProgressBar::setBorderWidth(float width) {
|
||||||
borderWidth_ = width;
|
borderWidth_ = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置内边距
|
||||||
|
* @param padding 内边距值
|
||||||
|
*/
|
||||||
void ProgressBar::setPadding(float padding) {
|
void ProgressBar::setPadding(float padding) {
|
||||||
padding_ = padding;
|
padding_ = padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用文本显示
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void ProgressBar::setTextEnabled(bool enabled) {
|
void ProgressBar::setTextEnabled(bool enabled) {
|
||||||
textEnabled_ = enabled;
|
textEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体
|
||||||
|
* @param font 字体图集指针
|
||||||
|
*/
|
||||||
void ProgressBar::setFont(Ptr<FontAtlas> font) {
|
void ProgressBar::setFont(Ptr<FontAtlas> font) {
|
||||||
font_ = font;
|
font_ = font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本颜色
|
||||||
|
* @param color 文本颜色
|
||||||
|
*/
|
||||||
void ProgressBar::setTextColor(const Color &color) {
|
void ProgressBar::setTextColor(const Color &color) {
|
||||||
textColor_ = color;
|
textColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本格式
|
||||||
|
* @param format 格式字符串
|
||||||
|
*/
|
||||||
void ProgressBar::setTextFormat(const std::string &format) {
|
void ProgressBar::setTextFormat(const std::string &format) {
|
||||||
textFormat_ = format;
|
textFormat_ = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用动画变化
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void ProgressBar::setAnimatedChangeEnabled(bool enabled) {
|
void ProgressBar::setAnimatedChangeEnabled(bool enabled) {
|
||||||
animatedChangeEnabled_ = enabled;
|
animatedChangeEnabled_ = enabled;
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
|
|
@ -184,34 +228,66 @@ void ProgressBar::setAnimatedChangeEnabled(bool enabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置动画速度
|
||||||
|
* @param speed 每秒变化量
|
||||||
|
*/
|
||||||
void ProgressBar::setAnimationSpeed(float speed) {
|
void ProgressBar::setAnimationSpeed(float speed) {
|
||||||
animationSpeed_ = speed;
|
animationSpeed_ = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用延迟显示
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void ProgressBar::setDelayedDisplayEnabled(bool enabled) {
|
void ProgressBar::setDelayedDisplayEnabled(bool enabled) {
|
||||||
delayedDisplayEnabled_ = enabled;
|
delayedDisplayEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置延迟时间
|
||||||
|
* @param seconds 延迟秒数
|
||||||
|
*/
|
||||||
void ProgressBar::setDelayTime(float seconds) {
|
void ProgressBar::setDelayTime(float seconds) {
|
||||||
delayTime_ = seconds;
|
delayTime_ = seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置延迟显示填充颜色
|
||||||
|
* @param color 填充颜色
|
||||||
|
*/
|
||||||
void ProgressBar::setDelayedFillColor(const Color &color) {
|
void ProgressBar::setDelayedFillColor(const Color &color) {
|
||||||
delayedFillColor_ = color;
|
delayedFillColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用条纹效果
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void ProgressBar::setStripedEnabled(bool enabled) {
|
void ProgressBar::setStripedEnabled(bool enabled) {
|
||||||
stripedEnabled_ = enabled;
|
stripedEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置条纹颜色
|
||||||
|
* @param color 条纹颜色
|
||||||
|
*/
|
||||||
void ProgressBar::setStripeColor(const Color &color) {
|
void ProgressBar::setStripeColor(const Color &color) {
|
||||||
stripeColor_ = color;
|
stripeColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置条纹移动速度
|
||||||
|
* @param speed 移动速度
|
||||||
|
*/
|
||||||
void ProgressBar::setStripeSpeed(float speed) {
|
void ProgressBar::setStripeSpeed(float speed) {
|
||||||
stripeSpeed_ = speed;
|
stripeSpeed_ = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取当前填充颜色
|
||||||
|
* @return 当前填充颜色
|
||||||
|
*/
|
||||||
Color ProgressBar::getCurrentFillColor() const {
|
Color ProgressBar::getCurrentFillColor() const {
|
||||||
if (segmentedColorsEnabled_ && !colorSegments_.empty()) {
|
if (segmentedColorsEnabled_ && !colorSegments_.empty()) {
|
||||||
float percent = getPercent();
|
float percent = getPercent();
|
||||||
|
|
@ -224,6 +300,10 @@ Color ProgressBar::getCurrentFillColor() const {
|
||||||
return fillColor_;
|
return fillColor_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 格式化文本
|
||||||
|
* @return 格式化后的文本
|
||||||
|
*/
|
||||||
std::string ProgressBar::formatText() const {
|
std::string ProgressBar::formatText() const {
|
||||||
std::string result = textFormat_;
|
std::string result = textFormat_;
|
||||||
|
|
||||||
|
|
@ -246,10 +326,18 @@ std::string ProgressBar::formatText() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取边界框
|
||||||
|
* @return 边界矩形
|
||||||
|
*/
|
||||||
Rect ProgressBar::getBoundingBox() const {
|
Rect ProgressBar::getBoundingBox() const {
|
||||||
return Rect(getPosition().x, getPosition().y, getSize().width, getSize().height);
|
return Rect(getPosition().x, getPosition().y, getSize().width, getSize().height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新函数
|
||||||
|
* @param deltaTime 帧间隔时间
|
||||||
|
*/
|
||||||
void ProgressBar::onUpdate(float deltaTime) {
|
void ProgressBar::onUpdate(float deltaTime) {
|
||||||
if (animatedChangeEnabled_ && displayValue_ != value_) {
|
if (animatedChangeEnabled_ && displayValue_ != value_) {
|
||||||
float diff = value_ - displayValue_;
|
float diff = value_ - displayValue_;
|
||||||
|
|
@ -285,25 +373,26 @@ void ProgressBar::onUpdate(float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制组件
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
*/
|
||||||
void ProgressBar::onDrawWidget(RenderBackend &renderer) {
|
void ProgressBar::onDrawWidget(RenderBackend &renderer) {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
Size size = getSize();
|
Size size = getSize();
|
||||||
|
|
||||||
// 计算实际绘制区域
|
|
||||||
float bgX = pos.x + padding_;
|
float bgX = pos.x + padding_;
|
||||||
float bgY = pos.y + padding_;
|
float bgY = pos.y + padding_;
|
||||||
float bgW = size.width - padding_ * 2;
|
float bgW = size.width - padding_ * 2;
|
||||||
float bgH = size.height - padding_ * 2;
|
float bgH = size.height - padding_ * 2;
|
||||||
Rect bgRect(bgX, bgY, bgW, bgH);
|
Rect bgRect(bgX, bgY, bgW, bgH);
|
||||||
|
|
||||||
// 绘制背景
|
|
||||||
if (roundedCornersEnabled_) {
|
if (roundedCornersEnabled_) {
|
||||||
fillRoundedRect(renderer, bgRect, bgColor_, cornerRadius_);
|
fillRoundedRect(renderer, bgRect, bgColor_, cornerRadius_);
|
||||||
} else {
|
} else {
|
||||||
renderer.fillRect(bgRect, bgColor_);
|
renderer.fillRect(bgRect, bgColor_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算填充区域
|
|
||||||
float percent = getPercent();
|
float percent = getPercent();
|
||||||
float fillX = bgX, fillY = bgY, fillW = bgW, fillH = bgH;
|
float fillX = bgX, fillY = bgY, fillW = bgW, fillH = bgH;
|
||||||
|
|
||||||
|
|
@ -325,7 +414,6 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
Rect fillRect(fillX, fillY, fillW, fillH);
|
Rect fillRect(fillX, fillY, fillW, fillH);
|
||||||
|
|
||||||
// 绘制延迟显示效果
|
|
||||||
if (delayedDisplayEnabled_ && delayedValue_ > displayValue_) {
|
if (delayedDisplayEnabled_ && delayedValue_ > displayValue_) {
|
||||||
float delayedPercent = (delayedValue_ - min_) / (max_ - min_);
|
float delayedPercent = (delayedValue_ - min_) / (max_ - min_);
|
||||||
float delayedX = bgX, delayedY = bgY, delayedW = bgW, delayedH = bgH;
|
float delayedX = bgX, delayedY = bgY, delayedW = bgW, delayedH = bgH;
|
||||||
|
|
@ -355,7 +443,6 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制填充
|
|
||||||
if (fillW > 0 && fillH > 0) {
|
if (fillW > 0 && fillH > 0) {
|
||||||
Color fillColor = getCurrentFillColor();
|
Color fillColor = getCurrentFillColor();
|
||||||
|
|
||||||
|
|
@ -370,7 +457,6 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制边框
|
|
||||||
if (borderEnabled_) {
|
if (borderEnabled_) {
|
||||||
if (roundedCornersEnabled_) {
|
if (roundedCornersEnabled_) {
|
||||||
drawRoundedRect(renderer, bgRect, borderColor_, cornerRadius_);
|
drawRoundedRect(renderer, bgRect, borderColor_, cornerRadius_);
|
||||||
|
|
@ -379,7 +465,6 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制文本
|
|
||||||
if (textEnabled_ && font_) {
|
if (textEnabled_ && font_) {
|
||||||
std::string text = formatText();
|
std::string text = formatText();
|
||||||
Vec2 textSize = font_->measureText(text);
|
Vec2 textSize = font_->measureText(text);
|
||||||
|
|
@ -393,14 +478,33 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制圆角矩形边框
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
* @param rect 矩形区域
|
||||||
|
* @param color 颜色
|
||||||
|
* @param radius 圆角半径
|
||||||
|
*/
|
||||||
void ProgressBar::drawRoundedRect(RenderBackend &renderer, const Rect &rect, const Color &color, float radius) {
|
void ProgressBar::drawRoundedRect(RenderBackend &renderer, const Rect &rect, const Color &color, float radius) {
|
||||||
renderer.drawRect(rect, color, borderWidth_);
|
renderer.drawRect(rect, color, borderWidth_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 填充圆角矩形
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
* @param rect 矩形区域
|
||||||
|
* @param color 颜色
|
||||||
|
* @param radius 圆角半径
|
||||||
|
*/
|
||||||
void ProgressBar::fillRoundedRect(RenderBackend &renderer, const Rect &rect, const Color &color, float radius) {
|
void ProgressBar::fillRoundedRect(RenderBackend &renderer, const Rect &rect, const Color &color, float radius) {
|
||||||
renderer.fillRect(rect, color);
|
renderer.fillRect(rect, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制条纹效果
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
* @param rect 矩形区域
|
||||||
|
*/
|
||||||
void ProgressBar::drawStripes(RenderBackend &renderer, const Rect &rect) {
|
void ProgressBar::drawStripes(RenderBackend &renderer, const Rect &rect) {
|
||||||
const float stripeWidth = 10.0f;
|
const float stripeWidth = 10.0f;
|
||||||
const float spacing = 20.0f;
|
const float spacing = 20.0f;
|
||||||
|
|
|
||||||
|
|
@ -4,95 +4,37 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 默认构造函数
|
||||||
|
*/
|
||||||
RadioButton::RadioButton() {
|
RadioButton::RadioButton() {
|
||||||
setAnchor(0.0f, 0.0f);
|
setAnchor(0.0f, 0.0f);
|
||||||
setSize(circleSize_, circleSize_);
|
setSize(circleSize_, circleSize_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建单选按钮对象
|
||||||
|
* @return 单选按钮对象指针
|
||||||
|
*/
|
||||||
Ptr<RadioButton> RadioButton::create() {
|
Ptr<RadioButton> RadioButton::create() {
|
||||||
return makePtr<RadioButton>();
|
return makePtr<RadioButton>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带标签的单选按钮对象
|
||||||
|
* @param label 标签文本
|
||||||
|
* @return 单选按钮对象指针
|
||||||
|
*/
|
||||||
Ptr<RadioButton> RadioButton::create(const std::string &label) {
|
Ptr<RadioButton> RadioButton::create(const std::string &label) {
|
||||||
auto rb = makePtr<RadioButton>();
|
auto rb = makePtr<RadioButton>();
|
||||||
rb->setLabel(label);
|
rb->setLabel(label);
|
||||||
return rb;
|
return rb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
/**
|
||||||
// 链式调用构建器方法
|
* @brief 设置选中状态
|
||||||
// ------------------------------------------------------------------------
|
* @param selected 是否选中
|
||||||
RadioButton *RadioButton::withPosition(float x, float y) {
|
*/
|
||||||
setPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withPosition(const Vec2 &pos) {
|
|
||||||
setPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withAnchor(float x, float y) {
|
|
||||||
setAnchor(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withAnchor(const Vec2 &anchor) {
|
|
||||||
setAnchor(anchor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withText(const std::string &text) {
|
|
||||||
setLabel(text);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withFont(Ptr<FontAtlas> font) {
|
|
||||||
setFont(font);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withTextColor(const Color &color) {
|
|
||||||
setTextColor(color);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withSize(float width, float height) {
|
|
||||||
setSize(width, height);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用 - 坐标空间设置
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
RadioButton *RadioButton::withCoordinateSpace(CoordinateSpace space) {
|
|
||||||
setCoordinateSpace(space);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withScreenPosition(float x, float y) {
|
|
||||||
setScreenPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withScreenPosition(const Vec2 &pos) {
|
|
||||||
setScreenPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withCameraOffset(float x, float y) {
|
|
||||||
setCameraOffset(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioButton *RadioButton::withCameraOffset(const Vec2 &offset) {
|
|
||||||
setCameraOffset(offset);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 普通设置方法
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
void RadioButton::setSelected(bool selected) {
|
void RadioButton::setSelected(bool selected) {
|
||||||
if (selected_ != selected) {
|
if (selected_ != selected) {
|
||||||
selected_ = selected;
|
selected_ = selected;
|
||||||
|
|
@ -102,46 +44,90 @@ void RadioButton::setSelected(bool selected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置标签文本
|
||||||
|
* @param label 标签文本
|
||||||
|
*/
|
||||||
void RadioButton::setLabel(const std::string &label) {
|
void RadioButton::setLabel(const std::string &label) {
|
||||||
label_ = label;
|
label_ = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体
|
||||||
|
* @param font 字体图集指针
|
||||||
|
*/
|
||||||
void RadioButton::setFont(Ptr<FontAtlas> font) {
|
void RadioButton::setFont(Ptr<FontAtlas> font) {
|
||||||
font_ = font;
|
font_ = font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本颜色
|
||||||
|
* @param color 文本颜色
|
||||||
|
*/
|
||||||
void RadioButton::setTextColor(const Color &color) {
|
void RadioButton::setTextColor(const Color &color) {
|
||||||
textColor_ = color;
|
textColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置圆形尺寸
|
||||||
|
* @param size 圆形尺寸
|
||||||
|
*/
|
||||||
void RadioButton::setCircleSize(float size) {
|
void RadioButton::setCircleSize(float size) {
|
||||||
circleSize_ = size;
|
circleSize_ = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置间距
|
||||||
|
* @param spacing 间距值
|
||||||
|
*/
|
||||||
void RadioButton::setSpacing(float spacing) {
|
void RadioButton::setSpacing(float spacing) {
|
||||||
spacing_ = spacing;
|
spacing_ = spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置选中颜色
|
||||||
|
* @param color 选中颜色
|
||||||
|
*/
|
||||||
void RadioButton::setSelectedColor(const Color &color) {
|
void RadioButton::setSelectedColor(const Color &color) {
|
||||||
selectedColor_ = color;
|
selectedColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置未选中颜色
|
||||||
|
* @param color 未选中颜色
|
||||||
|
*/
|
||||||
void RadioButton::setUnselectedColor(const Color &color) {
|
void RadioButton::setUnselectedColor(const Color &color) {
|
||||||
unselectedColor_ = color;
|
unselectedColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置圆点颜色
|
||||||
|
* @param color 圆点颜色
|
||||||
|
*/
|
||||||
void RadioButton::setDotColor(const Color &color) {
|
void RadioButton::setDotColor(const Color &color) {
|
||||||
dotColor_ = color;
|
dotColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置分组ID
|
||||||
|
* @param groupId 分组ID
|
||||||
|
*/
|
||||||
void RadioButton::setGroupId(int groupId) {
|
void RadioButton::setGroupId(int groupId) {
|
||||||
groupId_ = groupId;
|
groupId_ = groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置状态改变回调
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
void RadioButton::setOnStateChange(Function<void(bool)> callback) {
|
void RadioButton::setOnStateChange(Function<void(bool)> callback) {
|
||||||
onStateChange_ = callback;
|
onStateChange_ = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取边界框
|
||||||
|
* @return 边界矩形
|
||||||
|
*/
|
||||||
Rect RadioButton::getBoundingBox() const {
|
Rect RadioButton::getBoundingBox() const {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
float width = circleSize_;
|
float width = circleSize_;
|
||||||
|
|
@ -154,30 +140,36 @@ Rect RadioButton::getBoundingBox() const {
|
||||||
return Rect(pos.x, pos.y, width, circleSize_);
|
return Rect(pos.x, pos.y, width, circleSize_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制组件
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
*/
|
||||||
void RadioButton::onDrawWidget(RenderBackend &renderer) {
|
void RadioButton::onDrawWidget(RenderBackend &renderer) {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
float centerX = pos.x + circleSize_ * 0.5f;
|
float centerX = pos.x + circleSize_ * 0.5f;
|
||||||
float centerY = pos.y + getSize().height * 0.5f;
|
float centerY = pos.y + getSize().height * 0.5f;
|
||||||
float radius = circleSize_ * 0.5f;
|
float radius = circleSize_ * 0.5f;
|
||||||
|
|
||||||
// 绘制外圆
|
|
||||||
Color circleColor = selected_ ? selectedColor_ : unselectedColor_;
|
Color circleColor = selected_ ? selectedColor_ : unselectedColor_;
|
||||||
renderer.drawCircle(Vec2(centerX, centerY), radius, circleColor, true);
|
renderer.drawCircle(Vec2(centerX, centerY), radius, circleColor, true);
|
||||||
renderer.drawCircle(Vec2(centerX, centerY), radius, Colors::White, false, 1.0f);
|
renderer.drawCircle(Vec2(centerX, centerY), radius, Colors::White, false, 1.0f);
|
||||||
|
|
||||||
// 绘制内圆点
|
|
||||||
if (selected_) {
|
if (selected_) {
|
||||||
float dotRadius = radius * 0.4f;
|
float dotRadius = radius * 0.4f;
|
||||||
renderer.drawCircle(Vec2(centerX, centerY), dotRadius, dotColor_, true);
|
renderer.drawCircle(Vec2(centerX, centerY), dotRadius, dotColor_, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制标签
|
|
||||||
if (!label_.empty() && font_) {
|
if (!label_.empty() && font_) {
|
||||||
Vec2 textPos(pos.x + circleSize_ + spacing_, pos.y);
|
Vec2 textPos(pos.x + circleSize_ + spacing_, pos.y);
|
||||||
renderer.drawText(*font_, label_, textPos, textColor_);
|
renderer.drawText(*font_, label_, textPos, textColor_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标按下事件处理
|
||||||
|
* @param event 鼠标事件
|
||||||
|
* @return 是否处理了事件
|
||||||
|
*/
|
||||||
bool RadioButton::onMousePress(const MouseEvent &event) {
|
bool RadioButton::onMousePress(const MouseEvent &event) {
|
||||||
if (event.button == MouseButton::Left) {
|
if (event.button == MouseButton::Left) {
|
||||||
pressed_ = true;
|
pressed_ = true;
|
||||||
|
|
@ -186,6 +178,11 @@ bool RadioButton::onMousePress(const MouseEvent &event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标释放事件处理
|
||||||
|
* @param event 鼠标事件
|
||||||
|
* @return 是否处理了事件
|
||||||
|
*/
|
||||||
bool RadioButton::onMouseRelease(const MouseEvent &event) {
|
bool RadioButton::onMouseRelease(const MouseEvent &event) {
|
||||||
if (event.button == MouseButton::Left && pressed_) {
|
if (event.button == MouseButton::Left && pressed_) {
|
||||||
pressed_ = false;
|
pressed_ = false;
|
||||||
|
|
@ -208,6 +205,10 @@ bool RadioButton::onMouseRelease(const MouseEvent &event) {
|
||||||
// RadioButtonGroup 实现
|
// RadioButtonGroup 实现
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 添加单选按钮到组
|
||||||
|
* @param button 单选按钮指针
|
||||||
|
*/
|
||||||
void RadioButtonGroup::addButton(RadioButton *button) {
|
void RadioButtonGroup::addButton(RadioButton *button) {
|
||||||
if (button && std::find(buttons_.begin(), buttons_.end(), button) == buttons_.end()) {
|
if (button && std::find(buttons_.begin(), buttons_.end(), button) == buttons_.end()) {
|
||||||
buttons_.push_back(button);
|
buttons_.push_back(button);
|
||||||
|
|
@ -223,6 +224,10 @@ void RadioButtonGroup::addButton(RadioButton *button) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从组中移除单选按钮
|
||||||
|
* @param button 单选按钮指针
|
||||||
|
*/
|
||||||
void RadioButtonGroup::removeButton(RadioButton *button) {
|
void RadioButtonGroup::removeButton(RadioButton *button) {
|
||||||
auto it = std::find(buttons_.begin(), buttons_.end(), button);
|
auto it = std::find(buttons_.begin(), buttons_.end(), button);
|
||||||
if (it != buttons_.end()) {
|
if (it != buttons_.end()) {
|
||||||
|
|
@ -233,15 +238,17 @@ void RadioButtonGroup::removeButton(RadioButton *button) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 选择指定的单选按钮
|
||||||
|
* @param button 单选按钮指针
|
||||||
|
*/
|
||||||
void RadioButtonGroup::selectButton(RadioButton *button) {
|
void RadioButtonGroup::selectButton(RadioButton *button) {
|
||||||
if (selectedButton_ == button) return;
|
if (selectedButton_ == button) return;
|
||||||
|
|
||||||
// 取消之前的选择
|
|
||||||
if (selectedButton_) {
|
if (selectedButton_) {
|
||||||
selectedButton_->setSelected(false);
|
selectedButton_->setSelected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选择新的按钮
|
|
||||||
selectedButton_ = button;
|
selectedButton_ = button;
|
||||||
if (button) {
|
if (button) {
|
||||||
button->setSelected(true);
|
button->setSelected(true);
|
||||||
|
|
@ -252,6 +259,10 @@ void RadioButtonGroup::selectButton(RadioButton *button) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置选择改变回调
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
void RadioButtonGroup::setOnSelectionChange(Function<void(RadioButton*)> callback) {
|
void RadioButtonGroup::setOnSelectionChange(Function<void(RadioButton*)> callback) {
|
||||||
onSelectionChange_ = callback;
|
onSelectionChange_ = callback;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,29 @@
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 默认构造函数
|
||||||
|
*/
|
||||||
Slider::Slider() {
|
Slider::Slider() {
|
||||||
setAnchor(0.0f, 0.0f);
|
setAnchor(0.0f, 0.0f);
|
||||||
setSize(200.0f, 20.0f);
|
setSize(200.0f, 20.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建滑动条对象
|
||||||
|
* @return 滑动条对象指针
|
||||||
|
*/
|
||||||
Ptr<Slider> Slider::create() {
|
Ptr<Slider> Slider::create() {
|
||||||
return makePtr<Slider>();
|
return makePtr<Slider>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带范围的滑动条对象
|
||||||
|
* @param min 最小值
|
||||||
|
* @param max 最大值
|
||||||
|
* @param value 当前值
|
||||||
|
* @return 滑动条对象指针
|
||||||
|
*/
|
||||||
Ptr<Slider> Slider::create(float min, float max, float value) {
|
Ptr<Slider> Slider::create(float min, float max, float value) {
|
||||||
auto slider = makePtr<Slider>();
|
auto slider = makePtr<Slider>();
|
||||||
slider->setRange(min, max);
|
slider->setRange(min, max);
|
||||||
|
|
@ -21,153 +35,21 @@ Ptr<Slider> Slider::create(float min, float max, float value) {
|
||||||
return slider;
|
return slider;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// 链式调用构建器方法实现
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置位置(浮点坐标)
|
* @brief 设置数值范围
|
||||||
* @param x X坐标
|
|
||||||
* @param y Y坐标
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withPosition(float x, float y) {
|
|
||||||
setPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置位置(Vec2坐标)
|
|
||||||
* @param pos 位置向量
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withPosition(const Vec2 &pos) {
|
|
||||||
setPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置锚点(浮点坐标)
|
|
||||||
* @param x X锚点(0-1)
|
|
||||||
* @param y Y锚点(0-1)
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withAnchor(float x, float y) {
|
|
||||||
setAnchor(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置锚点(Vec2坐标)
|
|
||||||
* @param anchor 锚点向量
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withAnchor(const Vec2 &anchor) {
|
|
||||||
setAnchor(anchor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置尺寸
|
|
||||||
* @param width 宽度
|
|
||||||
* @param height 高度
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withSize(float width, float height) {
|
|
||||||
setSize(width, height);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置最小值
|
|
||||||
* @param min 最小值
|
* @param min 最小值
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withMinValue(float min) {
|
|
||||||
min_ = min;
|
|
||||||
setValue(value_);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置最大值
|
|
||||||
* @param max 最大值
|
* @param max 最大值
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
*/
|
||||||
Slider *Slider::withMaxValue(float max) {
|
|
||||||
max_ = max;
|
|
||||||
setValue(value_);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置当前值
|
|
||||||
* @param value 当前值
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withValue(float value) {
|
|
||||||
setValue(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置坐标空间
|
|
||||||
* @param space 坐标空间类型
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withCoordinateSpace(CoordinateSpace space) {
|
|
||||||
setCoordinateSpace(space);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置屏幕位置(浮点坐标)
|
|
||||||
* @param x X屏幕坐标
|
|
||||||
* @param y Y屏幕坐标
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withScreenPosition(float x, float y) {
|
|
||||||
setScreenPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置屏幕位置(Vec2坐标)
|
|
||||||
* @param pos 屏幕位置向量
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withScreenPosition(const Vec2 &pos) {
|
|
||||||
setScreenPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置相机偏移(浮点坐标)
|
|
||||||
* @param x X偏移量
|
|
||||||
* @param y Y偏移量
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withCameraOffset(float x, float y) {
|
|
||||||
setCameraOffset(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置相机偏移(Vec2坐标)
|
|
||||||
* @param offset 偏移向量
|
|
||||||
* @return 返回this指针,支持链式调用
|
|
||||||
*/
|
|
||||||
Slider *Slider::withCameraOffset(const Vec2 &offset) {
|
|
||||||
setCameraOffset(offset);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Slider::setRange(float min, float max) {
|
void Slider::setRange(float min, float max) {
|
||||||
min_ = min;
|
min_ = min;
|
||||||
max_ = max;
|
max_ = max;
|
||||||
setValue(value_);
|
setValue(value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置当前值
|
||||||
|
* @param value 新值
|
||||||
|
*/
|
||||||
void Slider::setValue(float value) {
|
void Slider::setValue(float value) {
|
||||||
float newValue = std::clamp(value, min_, max_);
|
float newValue = std::clamp(value, min_, max_);
|
||||||
if (step_ > 0.0f) {
|
if (step_ > 0.0f) {
|
||||||
|
|
@ -182,6 +64,10 @@ void Slider::setValue(float value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置步进值
|
||||||
|
* @param step 步进值
|
||||||
|
*/
|
||||||
void Slider::setStep(float step) {
|
void Slider::setStep(float step) {
|
||||||
step_ = step;
|
step_ = step;
|
||||||
if (step_ > 0.0f) {
|
if (step_ > 0.0f) {
|
||||||
|
|
@ -189,78 +75,155 @@ void Slider::setStep(float step) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否为垂直方向
|
||||||
|
* @param vertical 是否垂直
|
||||||
|
*/
|
||||||
void Slider::setVertical(bool vertical) {
|
void Slider::setVertical(bool vertical) {
|
||||||
vertical_ = vertical;
|
vertical_ = vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置轨道尺寸
|
||||||
|
* @param size 轨道尺寸
|
||||||
|
*/
|
||||||
void Slider::setTrackSize(float size) {
|
void Slider::setTrackSize(float size) {
|
||||||
trackSize_ = size;
|
trackSize_ = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置滑块尺寸
|
||||||
|
* @param size 滑块尺寸
|
||||||
|
*/
|
||||||
void Slider::setThumbSize(float size) {
|
void Slider::setThumbSize(float size) {
|
||||||
thumbSize_ = size;
|
thumbSize_ = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置轨道颜色
|
||||||
|
* @param color 轨道颜色
|
||||||
|
*/
|
||||||
void Slider::setTrackColor(const Color &color) {
|
void Slider::setTrackColor(const Color &color) {
|
||||||
trackColor_ = color;
|
trackColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置填充颜色
|
||||||
|
* @param color 填充颜色
|
||||||
|
*/
|
||||||
void Slider::setFillColor(const Color &color) {
|
void Slider::setFillColor(const Color &color) {
|
||||||
fillColor_ = color;
|
fillColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置滑块颜色
|
||||||
|
* @param color 滑块颜色
|
||||||
|
*/
|
||||||
void Slider::setThumbColor(const Color &color) {
|
void Slider::setThumbColor(const Color &color) {
|
||||||
thumbColor_ = color;
|
thumbColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置滑块悬停颜色
|
||||||
|
* @param color 悬停颜色
|
||||||
|
*/
|
||||||
void Slider::setThumbHoverColor(const Color &color) {
|
void Slider::setThumbHoverColor(const Color &color) {
|
||||||
thumbHoverColor_ = color;
|
thumbHoverColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置滑块按下颜色
|
||||||
|
* @param color 按下颜色
|
||||||
|
*/
|
||||||
void Slider::setThumbPressedColor(const Color &color) {
|
void Slider::setThumbPressedColor(const Color &color) {
|
||||||
thumbPressedColor_ = color;
|
thumbPressedColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否显示滑块
|
||||||
|
* @param show 是否显示
|
||||||
|
*/
|
||||||
void Slider::setShowThumb(bool show) {
|
void Slider::setShowThumb(bool show) {
|
||||||
showThumb_ = show;
|
showThumb_ = show;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否显示填充
|
||||||
|
* @param show 是否显示
|
||||||
|
*/
|
||||||
void Slider::setShowFill(bool show) {
|
void Slider::setShowFill(bool show) {
|
||||||
showFill_ = show;
|
showFill_ = show;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置是否启用文本显示
|
||||||
|
* @param enabled 是否启用
|
||||||
|
*/
|
||||||
void Slider::setTextEnabled(bool enabled) {
|
void Slider::setTextEnabled(bool enabled) {
|
||||||
textEnabled_ = enabled;
|
textEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体
|
||||||
|
* @param font 字体图集指针
|
||||||
|
*/
|
||||||
void Slider::setFont(Ptr<FontAtlas> font) {
|
void Slider::setFont(Ptr<FontAtlas> font) {
|
||||||
font_ = font;
|
font_ = font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本颜色
|
||||||
|
* @param color 文本颜色
|
||||||
|
*/
|
||||||
void Slider::setTextColor(const Color &color) {
|
void Slider::setTextColor(const Color &color) {
|
||||||
textColor_ = color;
|
textColor_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本格式
|
||||||
|
* @param format 格式字符串
|
||||||
|
*/
|
||||||
void Slider::setTextFormat(const std::string &format) {
|
void Slider::setTextFormat(const std::string &format) {
|
||||||
textFormat_ = format;
|
textFormat_ = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置值改变回调
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
void Slider::setOnValueChange(Function<void(float)> callback) {
|
void Slider::setOnValueChange(Function<void(float)> callback) {
|
||||||
onValueChange_ = callback;
|
onValueChange_ = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置拖拽开始回调
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
void Slider::setOnDragStart(Function<void()> callback) {
|
void Slider::setOnDragStart(Function<void()> callback) {
|
||||||
onDragStart_ = callback;
|
onDragStart_ = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置拖拽结束回调
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
void Slider::setOnDragEnd(Function<void()> callback) {
|
void Slider::setOnDragEnd(Function<void()> callback) {
|
||||||
onDragEnd_ = callback;
|
onDragEnd_ = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取边界框
|
||||||
|
* @return 边界矩形
|
||||||
|
*/
|
||||||
Rect Slider::getBoundingBox() const {
|
Rect Slider::getBoundingBox() const {
|
||||||
return Rect(getPosition().x, getPosition().y, getSize().width, getSize().height);
|
return Rect(getPosition().x, getPosition().y, getSize().width, getSize().height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将值转换为位置
|
||||||
|
* @param value 数值
|
||||||
|
* @return 位置坐标
|
||||||
|
*/
|
||||||
float Slider::valueToPosition(float value) const {
|
float Slider::valueToPosition(float value) const {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
Size size = getSize();
|
Size size = getSize();
|
||||||
|
|
@ -274,6 +237,11 @@ float Slider::valueToPosition(float value) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将位置转换为值
|
||||||
|
* @param pos 位置坐标
|
||||||
|
* @return 数值
|
||||||
|
*/
|
||||||
float Slider::positionToValue(float pos) const {
|
float Slider::positionToValue(float pos) const {
|
||||||
Vec2 widgetPos = getPosition();
|
Vec2 widgetPos = getPosition();
|
||||||
Size size = getSize();
|
Size size = getSize();
|
||||||
|
|
@ -289,6 +257,10 @@ float Slider::positionToValue(float pos) const {
|
||||||
return min_ + percent * (max_ - min_);
|
return min_ + percent * (max_ - min_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取滑块矩形
|
||||||
|
* @return 滑块矩形
|
||||||
|
*/
|
||||||
Rect Slider::getThumbRect() const {
|
Rect Slider::getThumbRect() const {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
Size size = getSize();
|
Size size = getSize();
|
||||||
|
|
@ -312,6 +284,10 @@ Rect Slider::getThumbRect() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取轨道矩形
|
||||||
|
* @return 轨道矩形
|
||||||
|
*/
|
||||||
Rect Slider::getTrackRect() const {
|
Rect Slider::getTrackRect() const {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
Size size = getSize();
|
Size size = getSize();
|
||||||
|
|
@ -333,6 +309,10 @@ Rect Slider::getTrackRect() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 格式化文本
|
||||||
|
* @return 格式化后的文本
|
||||||
|
*/
|
||||||
std::string Slider::formatText() const {
|
std::string Slider::formatText() const {
|
||||||
std::string result = textFormat_;
|
std::string result = textFormat_;
|
||||||
|
|
||||||
|
|
@ -353,18 +333,25 @@ std::string Slider::formatText() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将值对齐到步进
|
||||||
|
* @param value 原始值
|
||||||
|
* @return 对齐后的值
|
||||||
|
*/
|
||||||
float Slider::snapToStep(float value) const {
|
float Slider::snapToStep(float value) const {
|
||||||
float steps = std::round((value - min_) / step_);
|
float steps = std::round((value - min_) / step_);
|
||||||
return min_ + steps * step_;
|
return min_ + steps * step_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制组件
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
*/
|
||||||
void Slider::onDrawWidget(RenderBackend &renderer) {
|
void Slider::onDrawWidget(RenderBackend &renderer) {
|
||||||
Rect trackRect = getTrackRect();
|
Rect trackRect = getTrackRect();
|
||||||
|
|
||||||
// 绘制轨道背景
|
|
||||||
renderer.fillRect(trackRect, trackColor_);
|
renderer.fillRect(trackRect, trackColor_);
|
||||||
|
|
||||||
// 绘制填充部分
|
|
||||||
if (showFill_) {
|
if (showFill_) {
|
||||||
float percent = (value_ - min_) / (max_ - min_);
|
float percent = (value_ - min_) / (max_ - min_);
|
||||||
float fillX = trackRect.origin.x;
|
float fillX = trackRect.origin.x;
|
||||||
|
|
@ -383,7 +370,6 @@ void Slider::onDrawWidget(RenderBackend &renderer) {
|
||||||
renderer.fillRect(fillRect, fillColor_);
|
renderer.fillRect(fillRect, fillColor_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制滑块
|
|
||||||
if (showThumb_) {
|
if (showThumb_) {
|
||||||
Rect thumbRect = getThumbRect();
|
Rect thumbRect = getThumbRect();
|
||||||
Color thumbColor = thumbColor_;
|
Color thumbColor = thumbColor_;
|
||||||
|
|
@ -398,7 +384,6 @@ void Slider::onDrawWidget(RenderBackend &renderer) {
|
||||||
renderer.drawRect(thumbRect, Colors::White, 1.0f);
|
renderer.drawRect(thumbRect, Colors::White, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制文本
|
|
||||||
if (textEnabled_ && font_) {
|
if (textEnabled_ && font_) {
|
||||||
std::string text = formatText();
|
std::string text = formatText();
|
||||||
Vec2 textSize = font_->measureText(text);
|
Vec2 textSize = font_->measureText(text);
|
||||||
|
|
@ -414,6 +399,11 @@ void Slider::onDrawWidget(RenderBackend &renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标按下事件处理
|
||||||
|
* @param event 鼠标事件
|
||||||
|
* @return 是否处理了事件
|
||||||
|
*/
|
||||||
bool Slider::onMousePress(const MouseEvent &event) {
|
bool Slider::onMousePress(const MouseEvent &event) {
|
||||||
if (event.button == MouseButton::Left) {
|
if (event.button == MouseButton::Left) {
|
||||||
Rect thumbRect = getThumbRect();
|
Rect thumbRect = getThumbRect();
|
||||||
|
|
@ -426,7 +416,6 @@ bool Slider::onMousePress(const MouseEvent &event) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击轨道直接跳转
|
|
||||||
Rect trackRect = getTrackRect();
|
Rect trackRect = getTrackRect();
|
||||||
if (trackRect.containsPoint(Point(event.x, event.y))) {
|
if (trackRect.containsPoint(Point(event.x, event.y))) {
|
||||||
float newValue = positionToValue(vertical_ ? event.y : event.x);
|
float newValue = positionToValue(vertical_ ? event.y : event.x);
|
||||||
|
|
@ -441,6 +430,11 @@ bool Slider::onMousePress(const MouseEvent &event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标释放事件处理
|
||||||
|
* @param event 鼠标事件
|
||||||
|
* @return 是否处理了事件
|
||||||
|
*/
|
||||||
bool Slider::onMouseRelease(const MouseEvent &event) {
|
bool Slider::onMouseRelease(const MouseEvent &event) {
|
||||||
if (event.button == MouseButton::Left && dragging_) {
|
if (event.button == MouseButton::Left && dragging_) {
|
||||||
dragging_ = false;
|
dragging_ = false;
|
||||||
|
|
@ -452,6 +446,11 @@ bool Slider::onMouseRelease(const MouseEvent &event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标移动事件处理
|
||||||
|
* @param event 鼠标事件
|
||||||
|
* @return 是否处理了事件
|
||||||
|
*/
|
||||||
bool Slider::onMouseMove(const MouseEvent &event) {
|
bool Slider::onMouseMove(const MouseEvent &event) {
|
||||||
if (dragging_) {
|
if (dragging_) {
|
||||||
float newValue = positionToValue(vertical_ ? event.y : event.x);
|
float newValue = positionToValue(vertical_ ? event.y : event.x);
|
||||||
|
|
@ -459,7 +458,6 @@ bool Slider::onMouseMove(const MouseEvent &event) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查悬停
|
|
||||||
Rect thumbRect = getThumbRect();
|
Rect thumbRect = getThumbRect();
|
||||||
bool wasHovered = hovered_;
|
bool wasHovered = hovered_;
|
||||||
hovered_ = thumbRect.containsPoint(Point(event.x, event.y));
|
hovered_ = thumbRect.containsPoint(Point(event.x, event.y));
|
||||||
|
|
@ -467,10 +465,16 @@ bool Slider::onMouseMove(const MouseEvent &event) {
|
||||||
return hovered_ != wasHovered;
|
return hovered_ != wasHovered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标进入事件处理
|
||||||
|
*/
|
||||||
void Slider::onMouseEnter() {
|
void Slider::onMouseEnter() {
|
||||||
hovered_ = true;
|
hovered_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 鼠标离开事件处理
|
||||||
|
*/
|
||||||
void Slider::onMouseLeave() {
|
void Slider::onMouseLeave() {
|
||||||
hovered_ = false;
|
hovered_ = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,136 +1,93 @@
|
||||||
#include <extra2d/ui/text.h>
|
|
||||||
#include <extra2d/graphics/render_backend.h>
|
|
||||||
#include <extra2d/core/string.h>
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <extra2d/core/string.h>
|
||||||
|
#include <extra2d/graphics/render_backend.h>
|
||||||
|
#include <extra2d/ui/text.h>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
Text::Text() {
|
/**
|
||||||
// 文字默认锚点为左上角,这样setPosition(0, 0)会在左上角显示
|
* @brief 默认构造函数
|
||||||
setAnchor(0.0f, 0.0f);
|
*/
|
||||||
}
|
Text::Text() { setAnchor(0.0f, 0.0f); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 带文本的构造函数
|
||||||
|
* @param text 初始文本内容
|
||||||
|
*/
|
||||||
Text::Text(const std::string &text) : text_(text) {
|
Text::Text(const std::string &text) : text_(text) {
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
// 文字默认锚点为左上角,这样setPosition(0, 0)会在左上角显示
|
|
||||||
setAnchor(0.0f, 0.0f);
|
setAnchor(0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
/**
|
||||||
// 链式调用构建器方法
|
* @brief 设置文本内容
|
||||||
// ------------------------------------------------------------------------
|
* @param text 新的文本内容
|
||||||
Text *Text::withPosition(float x, float y) {
|
*/
|
||||||
setPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withPosition(const Vec2 &pos) {
|
|
||||||
setPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withAnchor(float x, float y) {
|
|
||||||
setAnchor(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withAnchor(const Vec2 &anchor) {
|
|
||||||
setAnchor(anchor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withTextColor(const Color &color) {
|
|
||||||
setTextColor(color);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withFont(Ptr<FontAtlas> font) {
|
|
||||||
setFont(font);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withFontSize(int size) {
|
|
||||||
setFontSize(size);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withAlignment(Alignment align) {
|
|
||||||
setAlignment(align);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withVerticalAlignment(VerticalAlignment align) {
|
|
||||||
setVerticalAlignment(align);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 链式调用 - 坐标空间设置
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Text *Text::withCoordinateSpace(CoordinateSpace space) {
|
|
||||||
setCoordinateSpace(space);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withScreenPosition(float x, float y) {
|
|
||||||
setScreenPosition(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withScreenPosition(const Vec2 &pos) {
|
|
||||||
setScreenPosition(pos);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withCameraOffset(float x, float y) {
|
|
||||||
setCameraOffset(x, y);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text *Text::withCameraOffset(const Vec2 &offset) {
|
|
||||||
setCameraOffset(offset);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// 普通设置方法
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
void Text::setText(const std::string &text) {
|
void Text::setText(const std::string &text) {
|
||||||
text_ = text;
|
text_ = text;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体
|
||||||
|
* @param font 字体图集指针
|
||||||
|
*/
|
||||||
void Text::setFont(Ptr<FontAtlas> font) {
|
void Text::setFont(Ptr<FontAtlas> font) {
|
||||||
font_ = font;
|
font_ = font;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置文本颜色
|
||||||
|
* @param color 文本颜色
|
||||||
|
*/
|
||||||
void Text::setTextColor(const Color &color) { color_ = color; }
|
void Text::setTextColor(const Color &color) { color_ = color; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置字体大小
|
||||||
|
* @param size 字体大小
|
||||||
|
*/
|
||||||
void Text::setFontSize(int size) {
|
void Text::setFontSize(int size) {
|
||||||
fontSize_ = size;
|
fontSize_ = size;
|
||||||
sizeDirty_ = true;
|
sizeDirty_ = true;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置水平对齐方式
|
||||||
|
* @param align 对齐方式
|
||||||
|
*/
|
||||||
void Text::setAlignment(Alignment align) {
|
void Text::setAlignment(Alignment align) {
|
||||||
alignment_ = align;
|
alignment_ = align;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设置垂直对齐方式
|
||||||
|
* @param align 垂直对齐方式
|
||||||
|
*/
|
||||||
void Text::setVerticalAlignment(VerticalAlignment align) {
|
void Text::setVerticalAlignment(VerticalAlignment align) {
|
||||||
verticalAlignment_ = align;
|
verticalAlignment_ = align;
|
||||||
updateSpatialIndex();
|
updateSpatialIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取文本尺寸
|
||||||
|
* @return 文本的宽度和高度
|
||||||
|
*/
|
||||||
Vec2 Text::getTextSize() const {
|
Vec2 Text::getTextSize() const {
|
||||||
updateCache();
|
updateCache();
|
||||||
return cachedSize_;
|
return cachedSize_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取行高
|
||||||
|
* @return 行高值
|
||||||
|
*/
|
||||||
float Text::getLineHeight() const {
|
float Text::getLineHeight() const {
|
||||||
if (font_) {
|
if (font_) {
|
||||||
return font_->getLineHeight();
|
return font_->getLineHeight();
|
||||||
|
|
@ -138,6 +95,9 @@ float Text::getLineHeight() const {
|
||||||
return static_cast<float>(fontSize_);
|
return static_cast<float>(fontSize_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 更新缓存
|
||||||
|
*/
|
||||||
void Text::updateCache() const {
|
void Text::updateCache() const {
|
||||||
if (!sizeDirty_ || !font_) {
|
if (!sizeDirty_ || !font_) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -147,22 +107,22 @@ void Text::updateCache() const {
|
||||||
sizeDirty_ = false;
|
sizeDirty_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 计算绘制位置
|
||||||
|
* @return 绘制位置坐标
|
||||||
|
*/
|
||||||
Vec2 Text::calculateDrawPosition() const {
|
Vec2 Text::calculateDrawPosition() const {
|
||||||
Vec2 pos = getPosition();
|
Vec2 pos = getPosition();
|
||||||
Vec2 textSize = getTextSize();
|
Vec2 textSize = getTextSize();
|
||||||
Size widgetSize = getSize();
|
Size widgetSize = getSize();
|
||||||
Vec2 anchor = getAnchor();
|
Vec2 anchor = getAnchor();
|
||||||
|
|
||||||
// 如果设置了控件大小,使用控件大小作为对齐参考
|
|
||||||
float refWidth = widgetSize.empty() ? textSize.x : widgetSize.width;
|
float refWidth = widgetSize.empty() ? textSize.x : widgetSize.width;
|
||||||
float refHeight = widgetSize.empty() ? textSize.y : widgetSize.height;
|
float refHeight = widgetSize.empty() ? textSize.y : widgetSize.height;
|
||||||
|
|
||||||
// 锚点调整:锚点(0.5, 0.5)表示文本中心在pos位置
|
|
||||||
// 需要将文本向左上方偏移锚点比例 * 文本大小
|
|
||||||
pos.x -= textSize.x * anchor.x;
|
pos.x -= textSize.x * anchor.x;
|
||||||
pos.y -= textSize.y * anchor.y;
|
pos.y -= textSize.y * anchor.y;
|
||||||
|
|
||||||
// 水平对齐(仅在设置了控件大小时生效)
|
|
||||||
if (!widgetSize.empty()) {
|
if (!widgetSize.empty()) {
|
||||||
switch (alignment_) {
|
switch (alignment_) {
|
||||||
case Alignment::Center:
|
case Alignment::Center:
|
||||||
|
|
@ -177,7 +137,6 @@ Vec2 Text::calculateDrawPosition() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 垂直对齐(仅在设置了控件大小时生效)
|
|
||||||
if (!widgetSize.empty()) {
|
if (!widgetSize.empty()) {
|
||||||
switch (verticalAlignment_) {
|
switch (verticalAlignment_) {
|
||||||
case VerticalAlignment::Middle:
|
case VerticalAlignment::Middle:
|
||||||
|
|
@ -195,19 +154,37 @@ Vec2 Text::calculateDrawPosition() const {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建空文本对象
|
||||||
|
* @return 文本对象指针
|
||||||
|
*/
|
||||||
Ptr<Text> Text::create() { return makePtr<Text>(); }
|
Ptr<Text> Text::create() { return makePtr<Text>(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带文本的对象
|
||||||
|
* @param text 文本内容
|
||||||
|
* @return 文本对象指针
|
||||||
|
*/
|
||||||
Ptr<Text> Text::create(const std::string &text) { return makePtr<Text>(text); }
|
Ptr<Text> Text::create(const std::string &text) { return makePtr<Text>(text); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建带文本和字体的对象
|
||||||
|
* @param text 文本内容
|
||||||
|
* @param font 字体图集
|
||||||
|
* @return 文本对象指针
|
||||||
|
*/
|
||||||
Ptr<Text> Text::create(const std::string &text, Ptr<FontAtlas> font) {
|
Ptr<Text> Text::create(const std::string &text, Ptr<FontAtlas> font) {
|
||||||
auto t = makePtr<Text>(text);
|
auto t = makePtr<Text>(text);
|
||||||
t->setFont(font);
|
t->setFont(font);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
/**
|
||||||
// 格式化创建方法
|
* @brief 格式化创建文本
|
||||||
// ------------------------------------------------------------------------
|
* @param fmt 格式字符串
|
||||||
|
* @param ... 可变参数
|
||||||
|
* @return 文本对象指针
|
||||||
|
*/
|
||||||
Ptr<Text> Text::createFormat(const char *fmt, ...) {
|
Ptr<Text> Text::createFormat(const char *fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|
@ -217,6 +194,13 @@ Ptr<Text> Text::createFormat(const char *fmt, ...) {
|
||||||
return makePtr<Text>(buffer);
|
return makePtr<Text>(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 格式化创建文本(带字体)
|
||||||
|
* @param font 字体图集
|
||||||
|
* @param fmt 格式字符串
|
||||||
|
* @param ... 可变参数
|
||||||
|
* @return 文本对象指针
|
||||||
|
*/
|
||||||
Ptr<Text> Text::createFormat(Ptr<FontAtlas> font, const char *fmt, ...) {
|
Ptr<Text> Text::createFormat(Ptr<FontAtlas> font, const char *fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|
@ -228,6 +212,10 @@ Ptr<Text> Text::createFormat(Ptr<FontAtlas> font, const char *fmt, ...) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取边界框
|
||||||
|
* @return 边界矩形
|
||||||
|
*/
|
||||||
Rect Text::getBoundingBox() const {
|
Rect Text::getBoundingBox() const {
|
||||||
if (!font_ || text_.empty()) {
|
if (!font_ || text_.empty()) {
|
||||||
return Rect();
|
return Rect();
|
||||||
|
|
@ -243,6 +231,10 @@ Rect Text::getBoundingBox() const {
|
||||||
return Rect(pos.x, pos.y, size.x, size.y);
|
return Rect(pos.x, pos.y, size.x, size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 绘制组件
|
||||||
|
* @param renderer 渲染后端
|
||||||
|
*/
|
||||||
void Text::onDrawWidget(RenderBackend &renderer) {
|
void Text::onDrawWidget(RenderBackend &renderer) {
|
||||||
if (!font_ || text_.empty()) {
|
if (!font_ || text_.empty()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
using namespace extra2d;
|
using namespace extra2d;
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Hello World 场景
|
// Hello World 场景
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
@ -33,34 +32,34 @@ public:
|
||||||
|
|
||||||
// 创建 "你好世界" 文本组件 - 使用屏幕空间(固定位置,不随相机移动)
|
// 创建 "你好世界" 文本组件 - 使用屏幕空间(固定位置,不随相机移动)
|
||||||
auto text1 = Text::create("你好世界", font_);
|
auto text1 = Text::create("你好世界", font_);
|
||||||
text1->withCoordinateSpace(CoordinateSpace::Screen)
|
text1->setCoordinateSpace(CoordinateSpace::Screen);
|
||||||
->withScreenPosition(640.0f, 360.0f) // 屏幕中心
|
text1->setScreenPosition(640.0f, 360.0f); // 屏幕中心
|
||||||
->withAnchor(0.5f, 0.5f) // 中心锚点,让文字中心对准位置
|
text1->setAnchor(0.5f, 0.5f); // 中心锚点,让文字中心对准位置
|
||||||
->withTextColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
|
text1->setTextColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
addChild(text1);
|
addChild(text1);
|
||||||
|
|
||||||
// 创建提示文本组件 - 使用屏幕空间,固定在屏幕底部
|
// 创建提示文本组件 - 使用屏幕空间,固定在屏幕底部
|
||||||
auto text2 = Text::create("退出按键(START 按钮)", font_);
|
auto text2 = Text::create("退出按键(START 按钮)", font_);
|
||||||
text2->withCoordinateSpace(CoordinateSpace::Screen)
|
text2->setCoordinateSpace(CoordinateSpace::Screen);
|
||||||
->withScreenPosition(640.0f, 650.0f) // 屏幕底部
|
text2->setScreenPosition(640.0f, 650.0f); // 屏幕底部
|
||||||
->withAnchor(0.5f, 0.5f)
|
text2->setAnchor(0.5f, 0.5f);
|
||||||
->withTextColor(Color(1.0f, 1.0f, 0.0f, 1.0f));
|
text2->setTextColor(Color(1.0f, 1.0f, 0.0f, 1.0f));
|
||||||
addChild(text2);
|
addChild(text2);
|
||||||
|
|
||||||
// 创建相机空间文本 - 跟随相机但保持相对偏移
|
// 创建相机空间文本 - 跟随相机但保持相对偏移
|
||||||
auto text3 = Text::create("相机空间文本", font_);
|
auto text3 = Text::create("相机空间文本", font_);
|
||||||
text3->withCoordinateSpace(CoordinateSpace::Camera)
|
text3->setCoordinateSpace(CoordinateSpace::Camera);
|
||||||
->withCameraOffset(50.0f, 50.0f) // 相机左上角偏移(屏幕坐标系Y向下)
|
text3->setCameraOffset(50.0f, 50.0f); // 相机左上角偏移(屏幕坐标系Y向下)
|
||||||
->withAnchor(0.0f, 0.0f) // 左上角锚点,文字从指定位置开始显示
|
text3->setAnchor(0.0f, 0.0f); // 左上角锚点,文字从指定位置开始显示
|
||||||
->withTextColor(Color(0.0f, 1.0f, 1.0f, 1.0f));
|
text3->setTextColor(Color(0.0f, 1.0f, 1.0f, 1.0f));
|
||||||
addChild(text3);
|
addChild(text3);
|
||||||
|
|
||||||
// 创建世界空间文本 - 随相机移动(默认行为)
|
// 创建世界空间文本 - 随相机移动(默认行为)
|
||||||
auto text4 = Text::create("世界空间文本", font_);
|
auto text4 = Text::create("世界空间文本", font_);
|
||||||
text4->withCoordinateSpace(CoordinateSpace::World)
|
text4->setCoordinateSpace(CoordinateSpace::World);
|
||||||
->withPosition(100.0f, 100.0f) // 世界坐标
|
text4->setPosition(100.0f, 100.0f); // 世界坐标
|
||||||
->withAnchor(0.0f, 0.0f) // 左上角锚点,文字从指定位置开始显示
|
text4->setAnchor(0.0f, 0.0f); // 左上角锚点,文字从指定位置开始显示
|
||||||
->withTextColor(Color(1.0f, 0.5f, 0.5f, 1.0f));
|
text4->setTextColor(Color(1.0f, 0.5f, 0.5f, 1.0f));
|
||||||
addChild(text4);
|
addChild(text4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,8 +88,7 @@ private:
|
||||||
// 程序入口
|
// 程序入口
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv) {
|
||||||
{
|
|
||||||
// 初始化日志系统
|
// 初始化日志系统
|
||||||
Logger::init();
|
Logger::init();
|
||||||
Logger::setLevel(LogLevel::Debug);
|
Logger::setLevel(LogLevel::Debug);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue