refactor(ui): 移除UI组件的链式调用方法并重构文档注释

重构所有UI组件头文件,移除链式调用构建器方法
为UI组件添加详细的文档注释,说明各方法和属性的用途
调整部分实现文件的结构,使其更加清晰易读
This commit is contained in:
ChestnutYueyue 2026-02-13 16:52:57 +08:00
parent b78c493590
commit 866fd4b1ff
15 changed files with 964 additions and 846 deletions

View File

@ -32,35 +32,6 @@ public:
static Ptr<Button> create(const std::string &text);
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(float x, float y);
Vec2 getPadding() const { return padding_; }
// ------------------------------------------------------------------------

View File

@ -18,45 +18,45 @@ public:
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);
bool isChecked() const { return checked_; }
void toggle();
// ------------------------------------------------------------------------
// 标签设置
// ------------------------------------------------------------------------
void setLabel(const std::string &label);
const std::string &getLabel() const { return label_; }
// ------------------------------------------------------------------------
// 字体设置
// ------------------------------------------------------------------------
void setFont(Ptr<FontAtlas> font);
Ptr<FontAtlas> getFont() const { return font_; }
// ------------------------------------------------------------------------
// 文字颜色
// ------------------------------------------------------------------------
void setTextColor(const Color &color);
Color getTextColor() const { return textColor_; }
// ------------------------------------------------------------------------
// 复选框尺寸
// ------------------------------------------------------------------------
void setBoxSize(float size);
float getBoxSize() const { return boxSize_; }
// ------------------------------------------------------------------------
// 间距
// ------------------------------------------------------------------------
void setSpacing(float spacing);
float getSpacing() const { return spacing_; }
// ------------------------------------------------------------------------
// 颜色设置
// ------------------------------------------------------------------------
void setCheckedColor(const Color &color);
Color getCheckedColor() const { return checkedColor_; }
@ -66,6 +66,9 @@ public:
void setCheckMarkColor(const Color &color);
Color getCheckMarkColor() const { return checkMarkColor_; }
// ------------------------------------------------------------------------
// 回调设置
// ------------------------------------------------------------------------
void setOnStateChange(Function<void(bool)> callback);
Rect getBoundingBox() const override;

View File

@ -23,27 +23,6 @@ public:
static Ptr<Label> create(const std::string &text);
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;
VerticalAlign vAlign_ = VerticalAlign::Top;
// 阴影
bool shadowEnabled_ = false;
Color shadowColor_ = Color(0.0f, 0.0f, 0.0f, 0.5f);
Vec2 shadowOffset_ = Vec2(2.0f, 2.0f);
// 描边
bool outlineEnabled_ = false;
Color outlineColor_ = Colors::Black;
float outlineWidth_ = 1.0f;
// 多行
bool multiLine_ = false;
float lineSpacing_ = 1.0f;
float maxWidth_ = 0.0f;

View File

@ -21,21 +21,6 @@ public:
static Ptr<ProgressBar> create();
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);
// ------------------------------------------------------------------------
// 数值范围
// ------------------------------------------------------------------------

View File

@ -18,40 +18,44 @@ public:
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);
bool isSelected() const { return selected_; }
// ------------------------------------------------------------------------
// 标签设置
// ------------------------------------------------------------------------
void setLabel(const std::string &label);
const std::string &getLabel() const { return label_; }
// ------------------------------------------------------------------------
// 字体设置
// ------------------------------------------------------------------------
void setFont(Ptr<FontAtlas> font);
Ptr<FontAtlas> getFont() const { return font_; }
// ------------------------------------------------------------------------
// 文字颜色
// ------------------------------------------------------------------------
void setTextColor(const Color &color);
Color getTextColor() const { return textColor_; }
// ------------------------------------------------------------------------
// 圆形尺寸
// ------------------------------------------------------------------------
void setCircleSize(float size);
float getCircleSize() const { return circleSize_; }
// ------------------------------------------------------------------------
// 间距
// ------------------------------------------------------------------------
void setSpacing(float spacing);
float getSpacing() const { return spacing_; }
// ------------------------------------------------------------------------
// 颜色设置
// ------------------------------------------------------------------------
void setSelectedColor(const Color &color);
Color getSelectedColor() const { return selectedColor_; }
@ -61,9 +65,15 @@ public:
void setDotColor(const Color &color);
Color getDotColor() const { return dotColor_; }
// ------------------------------------------------------------------------
// 分组
// ------------------------------------------------------------------------
void setGroupId(int groupId);
int getGroupId() const { return groupId_; }
// ------------------------------------------------------------------------
// 回调设置
// ------------------------------------------------------------------------
void setOnStateChange(Function<void(bool)> callback);
Rect getBoundingBox() const override;
@ -86,7 +96,7 @@ private:
Color unselectedColor_ = Color(0.3f, 0.3f, 0.3f, 1.0f);
Color dotColor_ = Colors::White;
int groupId_ = 0; // 用于分组,同组内只能选一个
int groupId_ = 0;
bool pressed_ = false;
Function<void(bool)> onStateChange_;

View File

@ -18,41 +18,45 @@ public:
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);
float getMin() const { return min_; }
float getMax() const { return max_; }
// ------------------------------------------------------------------------
// 当前值
// ------------------------------------------------------------------------
void setValue(float value);
float getValue() const { return value_; }
// ------------------------------------------------------------------------
// 步进值
// ------------------------------------------------------------------------
void setStep(float step);
float getStep() const { return step_; }
// ------------------------------------------------------------------------
// 方向
// ------------------------------------------------------------------------
void setVertical(bool vertical);
bool isVertical() const { return vertical_; }
// ------------------------------------------------------------------------
// 轨道尺寸
// ------------------------------------------------------------------------
void setTrackSize(float size);
float getTrackSize() const { return trackSize_; }
// ------------------------------------------------------------------------
// 滑块尺寸
// ------------------------------------------------------------------------
void setThumbSize(float size);
float getThumbSize() const { return thumbSize_; }
// ------------------------------------------------------------------------
// 颜色设置
// ------------------------------------------------------------------------
void setTrackColor(const Color &color);
Color getTrackColor() const { return trackColor_; }
@ -68,12 +72,18 @@ public:
void setThumbPressedColor(const Color &color);
Color getThumbPressedColor() const { return thumbPressedColor_; }
// ------------------------------------------------------------------------
// 显示设置
// ------------------------------------------------------------------------
void setShowThumb(bool show);
bool isShowThumb() const { return showThumb_; }
void setShowFill(bool show);
bool isShowFill() const { return showFill_; }
// ------------------------------------------------------------------------
// 文本显示
// ------------------------------------------------------------------------
void setTextEnabled(bool enabled);
bool isTextEnabled() const { return textEnabled_; }
@ -86,6 +96,9 @@ public:
void setTextFormat(const std::string &format);
const std::string &getTextFormat() const { return textFormat_; }
// ------------------------------------------------------------------------
// 回调设置
// ------------------------------------------------------------------------
void setOnValueChange(Function<void(float)> callback);
void setOnDragStart(Function<void()> callback);
void setOnDragEnd(Function<void()> callback);
@ -104,7 +117,7 @@ private:
float min_ = 0.0f;
float max_ = 100.0f;
float value_ = 50.0f;
float step_ = 0.0f; // 0表示无步进
float step_ = 0.0f;
bool vertical_ = false;
float trackSize_ = 6.0f;

View File

@ -41,19 +41,6 @@ public:
static Ptr<Text> createFormat(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();
}
// 链式调用的格式化方法
// 注意由于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;
// ------------------------------------------------------------------------
// 链式调用 - 坐标空间设置
// ------------------------------------------------------------------------
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:
void onDrawWidget(RenderBackend &renderer) override;

View File

@ -11,8 +11,10 @@ namespace extra2d {
// Button 实现
// ============================================================================
/**
* @brief
*/
Button::Button() {
// 按钮默认锚点为左上角这样setPosition(0, 0)会在左上角显示
setAnchor(0.0f, 0.0f);
setSpatialIndexed(false);
@ -46,133 +48,49 @@ Button::Button() {
});
}
/**
* @brief
* @param text
*/
Button::Button(const std::string &text) : Button() { text_ = text; }
// ------------------------------------------------------------------------
// 静态创建方法
// ------------------------------------------------------------------------
/**
* @brief
* @return
*/
Ptr<Button> Button::create() { return makePtr<Button>(); }
/**
* @brief
* @param text
* @return
*/
Ptr<Button> Button::create(const std::string &text) {
return makePtr<Button>(text);
}
/**
* @brief
* @param text
* @param font
* @return
*/
Ptr<Button> Button::create(const std::string &text, Ptr<FontAtlas> font) {
auto btn = makePtr<Button>(text);
btn->setFont(font);
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) {
text_ = text;
if (font_ && getSize().empty()) {
@ -181,6 +99,10 @@ void Button::setText(const std::string &text) {
}
}
/**
* @brief
* @param font
*/
void Button::setFont(Ptr<FontAtlas> font) {
font_ = font;
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) {
padding_ = padding;
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; }
/**
* @brief
* @param normal
* @param hover
* @param pressed
*/
void Button::setBackgroundColor(const Color &normal, const Color &hover,
const Color &pressed) {
bgNormal_ = normal;
@ -206,29 +151,58 @@ void Button::setBackgroundColor(const Color &normal, const Color &hover,
bgPressed_ = pressed;
}
/**
* @brief
* @param color
* @param width
*/
void Button::setBorder(const Color &color, float width) {
borderColor_ = color;
borderWidth_ = width;
}
/**
* @brief
* @param radius
*/
void Button::setCornerRadius(float radius) {
cornerRadius_ = std::max(0.0f, radius);
}
/**
* @brief
* @param enabled
*/
void Button::setRoundedCornersEnabled(bool enabled) {
roundedCornersEnabled_ = enabled;
}
/**
* @brief 使Alpha遮罩进行点击检测
* @param enabled
*/
void Button::setUseAlphaMaskForHitTest(bool enabled) {
useAlphaMaskForHitTest_ = enabled;
}
/**
* @brief
* @param callback
*/
void Button::setOnClick(Function<void()> callback) {
onClick_ = std::move(callback);
}
/**
* @brief
* @param enabled
*/
void Button::setToggleMode(bool enabled) { toggleMode_ = enabled; }
/**
* @brief
* @param on
*/
void Button::setOn(bool on) {
if (isOn_ != on) {
isOn_ = on;
@ -238,12 +212,24 @@ void Button::setOn(bool on) {
}
}
/**
* @brief
*/
void Button::toggle() { setOn(!isOn_); }
/**
* @brief
* @param callback
*/
void Button::setOnStateChange(Function<void(bool)> callback) {
onStateChange_ = std::move(callback);
}
/**
* @brief
* @param textOff
* @param textOn
*/
void Button::setStateText(const std::string &textOff,
const std::string &textOn) {
textOff_ = textOff;
@ -251,14 +237,29 @@ void Button::setStateText(const std::string &textOff,
useStateText_ = true;
}
/**
* @brief
* @param colorOff
* @param colorOn
*/
void Button::setStateTextColor(const Color &colorOff, const Color &colorOn) {
textColorOff_ = colorOff;
textColorOn_ = colorOn;
useStateTextColor_ = true;
}
/**
* @brief
* @param cursor
*/
void Button::setHoverCursor(CursorShape cursor) { hoverCursor_ = cursor; }
/**
* @brief
* @param normal
* @param hover
* @param pressed
*/
void Button::setBackgroundImage(Ptr<Texture> normal, Ptr<Texture> hover,
Ptr<Texture> pressed) {
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) {
imgNormal_ = 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(
Ptr<Texture> offNormal, Ptr<Texture> onNormal, Ptr<Texture> offHover,
Ptr<Texture> onHover, Ptr<Texture> offPressed, Ptr<Texture> onPressed) {
@ -309,6 +324,10 @@ void Button::setStateBackgroundImage(
}
}
/**
* @brief
* @param mode
*/
void Button::setBackgroundImageScaleMode(ImageScaleMode mode) {
scaleMode_ = mode;
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); }
/**
* @brief
* @param width
* @param height
*/
void Button::setCustomSize(float width, float height) {
setSize(width, height);
}
/**
* @brief
* @return
*/
Rect Button::getBoundingBox() const {
auto pos = getRenderPosition();
auto anchor = getAnchor();
@ -342,6 +374,12 @@ Rect Button::getBoundingBox() const {
return Rect(x0, y0, w, h);
}
/**
* @brief
* @param buttonSize
* @param imageSize
* @return
*/
Vec2 Button::calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize) {
switch (scaleMode_) {
case ImageScaleMode::Original:
@ -367,11 +405,15 @@ Vec2 Button::calculateImageSize(const Vec2 &buttonSize, const Vec2 &imageSize) {
return imageSize;
}
/**
* @brief
* @param renderer
* @param rect
*/
void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
Texture *texture = nullptr;
Rect srcRect;
// 如果使用状态图片,根据 isOn_ 状态选择对应的图片
if (useStateImages_) {
if (isOn_) {
if (pressed_ && imgOnPressed_) {
@ -395,7 +437,6 @@ void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
static_cast<float>(texture->getHeight()));
}
} else {
// 使用普通图片背景
if (pressed_ && imgPressed_) {
texture = imgPressed_.get();
srcRect = useTextureRect_
@ -433,6 +474,13 @@ void Button::drawBackgroundImage(RenderBackend &renderer, const Rect &rect) {
Vec2::Zero());
}
/**
* @brief
* @param renderer
* @param rect
* @param color
* @param radius
*/
void Button::drawRoundedRect(RenderBackend &renderer, const Rect &rect,
const Color &color, float radius) {
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,
const Color &color, float radius) {
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);
}
/**
* @brief
* @param renderer
*/
void Button::onDrawWidget(RenderBackend &renderer) {
Rect rect = getBoundingBox();
if (rect.empty()) {
@ -563,7 +622,6 @@ void Button::onDrawWidget(RenderBackend &renderer) {
}
if (useImageBackground_) {
// 使用图片背景时不绘制纯色背景和边框
drawBackgroundImage(renderer, rect);
} else {
renderer.endSpriteBatch();
@ -583,7 +641,6 @@ void Button::onDrawWidget(RenderBackend &renderer) {
renderer.beginSpriteBatch();
// 纯色背景模式下才绘制边框
renderer.endSpriteBatch();
if (borderWidth_ > 0.0f) {
@ -598,7 +655,6 @@ void Button::onDrawWidget(RenderBackend &renderer) {
}
if (font_) {
// 确定要显示的文字
std::string textToDraw;
if (useStateText_) {
textToDraw = isOn_ ? textOn_ : textOff_;
@ -606,7 +662,6 @@ void Button::onDrawWidget(RenderBackend &renderer) {
textToDraw = text_;
}
// 确定文字颜色
Color colorToUse;
if (useStateTextColor_) {
colorToUse = isOn_ ? textColorOn_ : textColorOff_;

View File

@ -4,92 +4,37 @@
namespace extra2d {
/**
* @brief
*/
CheckBox::CheckBox() {
setAnchor(0.0f, 0.0f);
setSize(boxSize_, boxSize_);
}
/**
* @brief
* @return
*/
Ptr<CheckBox> CheckBox::create() {
return makePtr<CheckBox>();
}
/**
* @brief
* @param label
* @return
*/
Ptr<CheckBox> CheckBox::create(const std::string &label) {
auto cb = makePtr<CheckBox>();
cb->setLabel(label);
return cb;
}
// ------------------------------------------------------------------------
// 链式调用构建器方法
// ------------------------------------------------------------------------
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;
}
/**
* @brief
* @param checked
*/
void CheckBox::setChecked(bool checked) {
if (checked_ != checked) {
checked_ = checked;
@ -99,46 +44,89 @@ void CheckBox::setChecked(bool checked) {
}
}
/**
* @brief
*/
void CheckBox::toggle() {
setChecked(!checked_);
}
/**
* @brief
* @param label
*/
void CheckBox::setLabel(const std::string &label) {
label_ = label;
}
/**
* @brief
* @param font
*/
void CheckBox::setFont(Ptr<FontAtlas> font) {
font_ = font;
}
/**
* @brief
* @param color
*/
void CheckBox::setTextColor(const Color &color) {
textColor_ = color;
}
/**
* @brief
* @param size
*/
void CheckBox::setBoxSize(float size) {
boxSize_ = size;
}
/**
* @brief
* @param spacing
*/
void CheckBox::setSpacing(float spacing) {
spacing_ = spacing;
}
/**
* @brief
* @param color
*/
void CheckBox::setCheckedColor(const Color &color) {
checkedColor_ = color;
}
/**
* @brief
* @param color
*/
void CheckBox::setUncheckedColor(const Color &color) {
uncheckedColor_ = color;
}
/**
* @brief
* @param color
*/
void CheckBox::setCheckMarkColor(const Color &color) {
checkMarkColor_ = color;
}
/**
* @brief
* @param callback
*/
void CheckBox::setOnStateChange(Function<void(bool)> callback) {
onStateChange_ = callback;
}
/**
* @brief
* @return
*/
Rect CheckBox::getBoundingBox() const {
Vec2 pos = getPosition();
float width = boxSize_;
@ -151,16 +139,18 @@ Rect CheckBox::getBoundingBox() const {
return Rect(pos.x, pos.y, width, boxSize_);
}
/**
* @brief
* @param renderer
*/
void CheckBox::onDrawWidget(RenderBackend &renderer) {
Vec2 pos = getPosition();
// 绘制复选框
Rect boxRect(pos.x, pos.y + (getSize().height - boxSize_) * 0.5f, boxSize_, boxSize_);
Color boxColor = checked_ ? checkedColor_ : uncheckedColor_;
renderer.fillRect(boxRect, boxColor);
renderer.drawRect(boxRect, Colors::White, 1.0f);
// 绘制勾选标记
if (checked_) {
float padding = boxSize_ * 0.2f;
float x1 = boxRect.origin.x + padding;
@ -170,18 +160,21 @@ void CheckBox::onDrawWidget(RenderBackend &renderer) {
float x3 = boxRect.origin.x + boxSize_ - padding;
float y3 = boxRect.origin.y + padding;
// 简化的勾选标记绘制
renderer.drawLine(Vec2(x1, y1), Vec2(x2, y2), checkMarkColor_, 2.0f);
renderer.drawLine(Vec2(x2, y2), Vec2(x3, y3), checkMarkColor_, 2.0f);
}
// 绘制标签
if (!label_.empty() && font_) {
Vec2 textPos(pos.x + boxSize_ + spacing_, pos.y);
renderer.drawText(*font_, label_, textPos, textColor_);
}
}
/**
* @brief
* @param event
* @return
*/
bool CheckBox::onMousePress(const MouseEvent &event) {
if (event.button == MouseButton::Left) {
pressed_ = true;
@ -190,6 +183,11 @@ bool CheckBox::onMousePress(const MouseEvent &event) {
return false;
}
/**
* @brief
* @param event
* @return
*/
bool CheckBox::onMouseRelease(const MouseEvent &event) {
if (event.button == MouseButton::Left && pressed_) {
pressed_ = false;

View File

@ -4,178 +4,196 @@
namespace extra2d {
/**
* @brief
*/
Label::Label() {
// 标签默认锚点为左上角
setAnchor(0.0f, 0.0f);
}
/**
* @brief
* @param text
*/
Label::Label(const std::string &text) : text_(text) {
setAnchor(0.0f, 0.0f);
sizeDirty_ = true;
}
/**
* @brief
* @return
*/
Ptr<Label> Label::create() {
return makePtr<Label>();
}
/**
* @brief
* @param text
* @return
*/
Ptr<Label> Label::create(const std::string &text) {
return makePtr<Label>(text);
}
/**
* @brief
* @param text
* @param font
* @return
*/
Ptr<Label> Label::create(const std::string &text, Ptr<FontAtlas> font) {
auto label = makePtr<Label>(text);
label->setFont(font);
return label;
}
// ------------------------------------------------------------------------
// 链式调用构建器方法
// ------------------------------------------------------------------------
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;
}
/**
* @brief
* @param text
*/
void Label::setText(const std::string &text) {
text_ = text;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @param font
*/
void Label::setFont(Ptr<FontAtlas> font) {
font_ = font;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @param color
*/
void Label::setTextColor(const Color &color) {
textColor_ = color;
}
/**
* @brief
* @param size
*/
void Label::setFontSize(int size) {
fontSize_ = size;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @param align
*/
void Label::setHorizontalAlign(HorizontalAlign align) {
hAlign_ = align;
}
/**
* @brief
* @param align
*/
void Label::setVerticalAlign(VerticalAlign align) {
vAlign_ = align;
}
/**
* @brief
* @param enabled
*/
void Label::setShadowEnabled(bool enabled) {
shadowEnabled_ = enabled;
}
/**
* @brief
* @param color
*/
void Label::setShadowColor(const Color &color) {
shadowColor_ = color;
}
/**
* @brief
* @param offset
*/
void Label::setShadowOffset(const Vec2 &offset) {
shadowOffset_ = offset;
}
/**
* @brief
* @param enabled
*/
void Label::setOutlineEnabled(bool enabled) {
outlineEnabled_ = enabled;
}
/**
* @brief
* @param color
*/
void Label::setOutlineColor(const Color &color) {
outlineColor_ = color;
}
/**
* @brief
* @param width
*/
void Label::setOutlineWidth(float width) {
outlineWidth_ = width;
}
/**
* @brief
* @param multiLine
*/
void Label::setMultiLine(bool multiLine) {
multiLine_ = multiLine;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @param spacing
*/
void Label::setLineSpacing(float spacing) {
lineSpacing_ = spacing;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @param maxWidth
*/
void Label::setMaxWidth(float maxWidth) {
maxWidth_ = maxWidth;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @return
*/
Vec2 Label::getTextSize() const {
updateCache();
return cachedSize_;
}
/**
* @brief
* @return
*/
float Label::getLineHeight() const {
if (font_) {
return font_->getLineHeight() * lineSpacing_;
@ -183,6 +201,9 @@ float Label::getLineHeight() const {
return static_cast<float>(fontSize_) * lineSpacing_;
}
/**
* @brief
*/
void Label::updateCache() const {
if (!sizeDirty_ || !font_) {
return;
@ -208,6 +229,10 @@ void Label::updateCache() const {
sizeDirty_ = false;
}
/**
* @brief
* @return
*/
std::vector<std::string> Label::splitLines() const {
std::vector<std::string> lines;
if (text_.empty()) {
@ -219,17 +244,14 @@ std::vector<std::string> Label::splitLines() const {
return lines;
}
// 按换行符分割
size_t start = 0;
size_t end = text_.find('\n');
while (end != std::string::npos) {
std::string line = text_.substr(start, end - start);
// 如果单行超过最大宽度,需要自动换行
Vec2 lineSize = font_->measureText(line);
if (lineSize.x > maxWidth_) {
// 简单实现:按字符逐个尝试
std::string currentLine;
for (size_t i = 0; i < line.length(); ++i) {
std::string testLine = currentLine + line[i];
@ -252,7 +274,6 @@ std::vector<std::string> Label::splitLines() const {
end = text_.find('\n', start);
}
// 处理最后一行
if (start < text_.length()) {
std::string line = text_.substr(start);
Vec2 lineSize = font_->measureText(line);
@ -279,16 +300,18 @@ std::vector<std::string> Label::splitLines() const {
return lines;
}
/**
* @brief
* @return
*/
Vec2 Label::calculateDrawPosition() const {
Vec2 pos = getPosition();
Vec2 size = getTextSize();
Size widgetSize = getSize();
// 如果设置了控件大小,使用控件大小作为对齐参考
float refWidth = widgetSize.empty() ? size.x : widgetSize.width;
float refHeight = widgetSize.empty() ? size.y : widgetSize.height;
// 水平对齐
switch (hAlign_) {
case HorizontalAlign::Center:
pos.x += (refWidth - size.x) * 0.5f;
@ -301,7 +324,6 @@ Vec2 Label::calculateDrawPosition() const {
break;
}
// 垂直对齐
switch (vAlign_) {
case VerticalAlign::Middle:
pos.y += (refHeight - size.y) * 0.5f;
@ -317,6 +339,12 @@ Vec2 Label::calculateDrawPosition() const {
return pos;
}
/**
* @brief
* @param renderer
* @param position
* @param color
*/
void Label::drawText(RenderBackend &renderer, const Vec2 &position, const Color &color) {
if (!font_ || text_.empty()) {
return;
@ -336,6 +364,10 @@ void Label::drawText(RenderBackend &renderer, const Vec2 &position, const Color
}
}
/**
* @brief
* @return
*/
Rect Label::getBoundingBox() const {
if (!font_ || text_.empty()) {
return Rect();
@ -351,6 +383,10 @@ Rect Label::getBoundingBox() const {
return Rect(pos.x, pos.y, size.x, size.y);
}
/**
* @brief
* @param renderer
*/
void Label::onDrawWidget(RenderBackend &renderer) {
if (!font_ || text_.empty()) {
return;
@ -358,13 +394,11 @@ void Label::onDrawWidget(RenderBackend &renderer) {
Vec2 pos = calculateDrawPosition();
// 绘制阴影
if (shadowEnabled_) {
Vec2 shadowPos = pos + shadowOffset_;
drawText(renderer, shadowPos, shadowColor_);
}
// 绘制描边简化实现向8个方向偏移绘制
if (outlineEnabled_) {
float w = outlineWidth_;
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, textColor_);
}

View File

@ -5,15 +5,29 @@
namespace extra2d {
/**
* @brief
*/
ProgressBar::ProgressBar() {
setAnchor(0.0f, 0.0f);
setSize(200.0f, 20.0f);
}
/**
* @brief
* @return
*/
Ptr<ProgressBar> ProgressBar::create() {
return makePtr<ProgressBar>();
}
/**
* @brief
* @param min
* @param max
* @param value
* @return
*/
Ptr<ProgressBar> ProgressBar::create(float min, float max, float value) {
auto bar = makePtr<ProgressBar>();
bar->setRange(min, max);
@ -21,71 +35,21 @@ Ptr<ProgressBar> ProgressBar::create(float min, float max, float value) {
return bar;
}
// ============================================================================
// 链式调用构建器方法实现
// ============================================================================
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;
}
/**
* @brief
* @param min
* @param max
*/
void ProgressBar::setRange(float min, float max) {
min_ = min;
max_ = max;
setValue(value_);
}
/**
* @brief
* @param value
*/
void ProgressBar::setValue(float value) {
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 {
if (max_ <= min_) return 0.0f;
return (displayValue_ - min_) / (max_ - min_);
}
/**
* @brief
* @param dir
*/
void ProgressBar::setDirection(Direction dir) {
direction_ = dir;
}
/**
* @brief
* @param color
*/
void ProgressBar::setBackgroundColor(const Color &color) {
bgColor_ = color;
}
/**
* @brief
* @param color
*/
void ProgressBar::setFillColor(const Color &color) {
fillColor_ = color;
}
/**
* @brief
* @param enabled
*/
void ProgressBar::setGradientFillEnabled(bool enabled) {
gradientEnabled_ = enabled;
}
/**
* @brief
* @param color
*/
void ProgressBar::setFillColorEnd(const Color &color) {
fillColorEnd_ = color;
}
/**
* @brief
* @param enabled
*/
void ProgressBar::setSegmentedColorsEnabled(bool enabled) {
segmentedColorsEnabled_ = enabled;
}
/**
* @brief
* @param percentThreshold
* @param color
*/
void ProgressBar::addColorSegment(float percentThreshold, const Color &color) {
colorSegments_.push_back({percentThreshold, color});
std::sort(colorSegments_.begin(), colorSegments_.end(),
[](const auto &a, const auto &b) { return a.first > b.first; });
}
/**
* @brief
*/
void ProgressBar::clearColorSegments() {
colorSegments_.clear();
}
/**
* @brief
* @param radius
*/
void ProgressBar::setCornerRadius(float radius) {
cornerRadius_ = radius;
}
/**
* @brief
* @param enabled
*/
void ProgressBar::setRoundedCornersEnabled(bool enabled) {
roundedCornersEnabled_ = enabled;
}
/**
* @brief
* @param enabled
*/
void ProgressBar::setBorderEnabled(bool enabled) {
borderEnabled_ = enabled;
}
/**
* @brief
* @param color
*/
void ProgressBar::setBorderColor(const Color &color) {
borderColor_ = color;
}
/**
* @brief
* @param width
*/
void ProgressBar::setBorderWidth(float width) {
borderWidth_ = width;
}
/**
* @brief
* @param padding
*/
void ProgressBar::setPadding(float padding) {
padding_ = padding;
}
/**
* @brief
* @param enabled
*/
void ProgressBar::setTextEnabled(bool enabled) {
textEnabled_ = enabled;
}
/**
* @brief
* @param font
*/
void ProgressBar::setFont(Ptr<FontAtlas> font) {
font_ = font;
}
/**
* @brief
* @param color
*/
void ProgressBar::setTextColor(const Color &color) {
textColor_ = color;
}
/**
* @brief
* @param format
*/
void ProgressBar::setTextFormat(const std::string &format) {
textFormat_ = format;
}
/**
* @brief
* @param enabled
*/
void ProgressBar::setAnimatedChangeEnabled(bool enabled) {
animatedChangeEnabled_ = enabled;
if (!enabled) {
@ -184,34 +228,66 @@ void ProgressBar::setAnimatedChangeEnabled(bool enabled) {
}
}
/**
* @brief
* @param speed
*/
void ProgressBar::setAnimationSpeed(float speed) {
animationSpeed_ = speed;
}
/**
* @brief
* @param enabled
*/
void ProgressBar::setDelayedDisplayEnabled(bool enabled) {
delayedDisplayEnabled_ = enabled;
}
/**
* @brief
* @param seconds
*/
void ProgressBar::setDelayTime(float seconds) {
delayTime_ = seconds;
}
/**
* @brief
* @param color
*/
void ProgressBar::setDelayedFillColor(const Color &color) {
delayedFillColor_ = color;
}
/**
* @brief
* @param enabled
*/
void ProgressBar::setStripedEnabled(bool enabled) {
stripedEnabled_ = enabled;
}
/**
* @brief
* @param color
*/
void ProgressBar::setStripeColor(const Color &color) {
stripeColor_ = color;
}
/**
* @brief
* @param speed
*/
void ProgressBar::setStripeSpeed(float speed) {
stripeSpeed_ = speed;
}
/**
* @brief
* @return
*/
Color ProgressBar::getCurrentFillColor() const {
if (segmentedColorsEnabled_ && !colorSegments_.empty()) {
float percent = getPercent();
@ -224,6 +300,10 @@ Color ProgressBar::getCurrentFillColor() const {
return fillColor_;
}
/**
* @brief
* @return
*/
std::string ProgressBar::formatText() const {
std::string result = textFormat_;
@ -246,10 +326,18 @@ std::string ProgressBar::formatText() const {
return result;
}
/**
* @brief
* @return
*/
Rect ProgressBar::getBoundingBox() const {
return Rect(getPosition().x, getPosition().y, getSize().width, getSize().height);
}
/**
* @brief
* @param deltaTime
*/
void ProgressBar::onUpdate(float deltaTime) {
if (animatedChangeEnabled_ && displayValue_ != value_) {
float diff = value_ - displayValue_;
@ -285,25 +373,26 @@ void ProgressBar::onUpdate(float deltaTime) {
}
}
/**
* @brief
* @param renderer
*/
void ProgressBar::onDrawWidget(RenderBackend &renderer) {
Vec2 pos = getPosition();
Size size = getSize();
// 计算实际绘制区域
float bgX = pos.x + padding_;
float bgY = pos.y + padding_;
float bgW = size.width - padding_ * 2;
float bgH = size.height - padding_ * 2;
Rect bgRect(bgX, bgY, bgW, bgH);
// 绘制背景
if (roundedCornersEnabled_) {
fillRoundedRect(renderer, bgRect, bgColor_, cornerRadius_);
} else {
renderer.fillRect(bgRect, bgColor_);
}
// 计算填充区域
float percent = getPercent();
float fillX = bgX, fillY = bgY, fillW = bgW, fillH = bgH;
@ -325,7 +414,6 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
}
Rect fillRect(fillX, fillY, fillW, fillH);
// 绘制延迟显示效果
if (delayedDisplayEnabled_ && delayedValue_ > displayValue_) {
float delayedPercent = (delayedValue_ - min_) / (max_ - min_);
float delayedX = bgX, delayedY = bgY, delayedW = bgW, delayedH = bgH;
@ -355,7 +443,6 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
}
}
// 绘制填充
if (fillW > 0 && fillH > 0) {
Color fillColor = getCurrentFillColor();
@ -370,7 +457,6 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
}
}
// 绘制边框
if (borderEnabled_) {
if (roundedCornersEnabled_) {
drawRoundedRect(renderer, bgRect, borderColor_, cornerRadius_);
@ -379,7 +465,6 @@ void ProgressBar::onDrawWidget(RenderBackend &renderer) {
}
}
// 绘制文本
if (textEnabled_ && font_) {
std::string text = formatText();
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) {
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) {
renderer.fillRect(rect, color);
}
/**
* @brief
* @param renderer
* @param rect
*/
void ProgressBar::drawStripes(RenderBackend &renderer, const Rect &rect) {
const float stripeWidth = 10.0f;
const float spacing = 20.0f;

View File

@ -4,95 +4,37 @@
namespace extra2d {
/**
* @brief
*/
RadioButton::RadioButton() {
setAnchor(0.0f, 0.0f);
setSize(circleSize_, circleSize_);
}
/**
* @brief
* @return
*/
Ptr<RadioButton> RadioButton::create() {
return makePtr<RadioButton>();
}
/**
* @brief
* @param label
* @return
*/
Ptr<RadioButton> RadioButton::create(const std::string &label) {
auto rb = makePtr<RadioButton>();
rb->setLabel(label);
return rb;
}
// ------------------------------------------------------------------------
// 链式调用构建器方法
// ------------------------------------------------------------------------
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;
}
// ------------------------------------------------------------------------
// 普通设置方法
// ------------------------------------------------------------------------
/**
* @brief
* @param selected
*/
void RadioButton::setSelected(bool selected) {
if (selected_ != selected) {
selected_ = selected;
@ -102,46 +44,90 @@ void RadioButton::setSelected(bool selected) {
}
}
/**
* @brief
* @param label
*/
void RadioButton::setLabel(const std::string &label) {
label_ = label;
}
/**
* @brief
* @param font
*/
void RadioButton::setFont(Ptr<FontAtlas> font) {
font_ = font;
}
/**
* @brief
* @param color
*/
void RadioButton::setTextColor(const Color &color) {
textColor_ = color;
}
/**
* @brief
* @param size
*/
void RadioButton::setCircleSize(float size) {
circleSize_ = size;
}
/**
* @brief
* @param spacing
*/
void RadioButton::setSpacing(float spacing) {
spacing_ = spacing;
}
/**
* @brief
* @param color
*/
void RadioButton::setSelectedColor(const Color &color) {
selectedColor_ = color;
}
/**
* @brief
* @param color
*/
void RadioButton::setUnselectedColor(const Color &color) {
unselectedColor_ = color;
}
/**
* @brief
* @param color
*/
void RadioButton::setDotColor(const Color &color) {
dotColor_ = color;
}
/**
* @brief ID
* @param groupId ID
*/
void RadioButton::setGroupId(int groupId) {
groupId_ = groupId;
}
/**
* @brief
* @param callback
*/
void RadioButton::setOnStateChange(Function<void(bool)> callback) {
onStateChange_ = callback;
}
/**
* @brief
* @return
*/
Rect RadioButton::getBoundingBox() const {
Vec2 pos = getPosition();
float width = circleSize_;
@ -154,30 +140,36 @@ Rect RadioButton::getBoundingBox() const {
return Rect(pos.x, pos.y, width, circleSize_);
}
/**
* @brief
* @param renderer
*/
void RadioButton::onDrawWidget(RenderBackend &renderer) {
Vec2 pos = getPosition();
float centerX = pos.x + circleSize_ * 0.5f;
float centerY = pos.y + getSize().height * 0.5f;
float radius = circleSize_ * 0.5f;
// 绘制外圆
Color circleColor = selected_ ? selectedColor_ : unselectedColor_;
renderer.drawCircle(Vec2(centerX, centerY), radius, circleColor, true);
renderer.drawCircle(Vec2(centerX, centerY), radius, Colors::White, false, 1.0f);
// 绘制内圆点
if (selected_) {
float dotRadius = radius * 0.4f;
renderer.drawCircle(Vec2(centerX, centerY), dotRadius, dotColor_, true);
}
// 绘制标签
if (!label_.empty() && font_) {
Vec2 textPos(pos.x + circleSize_ + spacing_, pos.y);
renderer.drawText(*font_, label_, textPos, textColor_);
}
}
/**
* @brief
* @param event
* @return
*/
bool RadioButton::onMousePress(const MouseEvent &event) {
if (event.button == MouseButton::Left) {
pressed_ = true;
@ -186,6 +178,11 @@ bool RadioButton::onMousePress(const MouseEvent &event) {
return false;
}
/**
* @brief
* @param event
* @return
*/
bool RadioButton::onMouseRelease(const MouseEvent &event) {
if (event.button == MouseButton::Left && pressed_) {
pressed_ = false;
@ -208,6 +205,10 @@ bool RadioButton::onMouseRelease(const MouseEvent &event) {
// RadioButtonGroup 实现
// ============================================================================
/**
* @brief
* @param button
*/
void RadioButtonGroup::addButton(RadioButton *button) {
if (button && std::find(buttons_.begin(), buttons_.end(), button) == buttons_.end()) {
buttons_.push_back(button);
@ -223,6 +224,10 @@ void RadioButtonGroup::addButton(RadioButton *button) {
}
}
/**
* @brief
* @param button
*/
void RadioButtonGroup::removeButton(RadioButton *button) {
auto it = std::find(buttons_.begin(), buttons_.end(), button);
if (it != buttons_.end()) {
@ -233,15 +238,17 @@ void RadioButtonGroup::removeButton(RadioButton *button) {
}
}
/**
* @brief
* @param button
*/
void RadioButtonGroup::selectButton(RadioButton *button) {
if (selectedButton_ == button) return;
// 取消之前的选择
if (selectedButton_) {
selectedButton_->setSelected(false);
}
// 选择新的按钮
selectedButton_ = button;
if (button) {
button->setSelected(true);
@ -252,6 +259,10 @@ void RadioButtonGroup::selectButton(RadioButton *button) {
}
}
/**
* @brief
* @param callback
*/
void RadioButtonGroup::setOnSelectionChange(Function<void(RadioButton*)> callback) {
onSelectionChange_ = callback;
}

View File

@ -5,15 +5,29 @@
namespace extra2d {
/**
* @brief
*/
Slider::Slider() {
setAnchor(0.0f, 0.0f);
setSize(200.0f, 20.0f);
}
/**
* @brief
* @return
*/
Ptr<Slider> Slider::create() {
return makePtr<Slider>();
}
/**
* @brief
* @param min
* @param max
* @param value
* @return
*/
Ptr<Slider> Slider::create(float min, float max, float value) {
auto slider = makePtr<Slider>();
slider->setRange(min, max);
@ -21,153 +35,21 @@ Ptr<Slider> Slider::create(float min, float max, float value) {
return slider;
}
// ============================================================================
// 链式调用构建器方法实现
// ============================================================================
/**
* @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
* @brief
* @param min
* @return this指针
*/
Slider *Slider::withMinValue(float min) {
min_ = min;
setValue(value_);
return this;
}
/**
* @brief
* @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) {
min_ = min;
max_ = max;
setValue(value_);
}
/**
* @brief
* @param value
*/
void Slider::setValue(float value) {
float newValue = std::clamp(value, min_, max_);
if (step_ > 0.0f) {
@ -182,6 +64,10 @@ void Slider::setValue(float value) {
}
}
/**
* @brief
* @param step
*/
void Slider::setStep(float step) {
step_ = step;
if (step_ > 0.0f) {
@ -189,78 +75,155 @@ void Slider::setStep(float step) {
}
}
/**
* @brief
* @param vertical
*/
void Slider::setVertical(bool vertical) {
vertical_ = vertical;
}
/**
* @brief
* @param size
*/
void Slider::setTrackSize(float size) {
trackSize_ = size;
}
/**
* @brief
* @param size
*/
void Slider::setThumbSize(float size) {
thumbSize_ = size;
}
/**
* @brief
* @param color
*/
void Slider::setTrackColor(const Color &color) {
trackColor_ = color;
}
/**
* @brief
* @param color
*/
void Slider::setFillColor(const Color &color) {
fillColor_ = color;
}
/**
* @brief
* @param color
*/
void Slider::setThumbColor(const Color &color) {
thumbColor_ = color;
}
/**
* @brief
* @param color
*/
void Slider::setThumbHoverColor(const Color &color) {
thumbHoverColor_ = color;
}
/**
* @brief
* @param color
*/
void Slider::setThumbPressedColor(const Color &color) {
thumbPressedColor_ = color;
}
/**
* @brief
* @param show
*/
void Slider::setShowThumb(bool show) {
showThumb_ = show;
}
/**
* @brief
* @param show
*/
void Slider::setShowFill(bool show) {
showFill_ = show;
}
/**
* @brief
* @param enabled
*/
void Slider::setTextEnabled(bool enabled) {
textEnabled_ = enabled;
}
/**
* @brief
* @param font
*/
void Slider::setFont(Ptr<FontAtlas> font) {
font_ = font;
}
/**
* @brief
* @param color
*/
void Slider::setTextColor(const Color &color) {
textColor_ = color;
}
/**
* @brief
* @param format
*/
void Slider::setTextFormat(const std::string &format) {
textFormat_ = format;
}
/**
* @brief
* @param callback
*/
void Slider::setOnValueChange(Function<void(float)> callback) {
onValueChange_ = callback;
}
/**
* @brief
* @param callback
*/
void Slider::setOnDragStart(Function<void()> callback) {
onDragStart_ = callback;
}
/**
* @brief
* @param callback
*/
void Slider::setOnDragEnd(Function<void()> callback) {
onDragEnd_ = callback;
}
/**
* @brief
* @return
*/
Rect Slider::getBoundingBox() const {
return Rect(getPosition().x, getPosition().y, getSize().width, getSize().height);
}
/**
* @brief
* @param value
* @return
*/
float Slider::valueToPosition(float value) const {
Vec2 pos = getPosition();
Size size = getSize();
@ -274,6 +237,11 @@ float Slider::valueToPosition(float value) const {
}
}
/**
* @brief
* @param pos
* @return
*/
float Slider::positionToValue(float pos) const {
Vec2 widgetPos = getPosition();
Size size = getSize();
@ -289,6 +257,10 @@ float Slider::positionToValue(float pos) const {
return min_ + percent * (max_ - min_);
}
/**
* @brief
* @return
*/
Rect Slider::getThumbRect() const {
Vec2 pos = getPosition();
Size size = getSize();
@ -312,6 +284,10 @@ Rect Slider::getThumbRect() const {
}
}
/**
* @brief
* @return
*/
Rect Slider::getTrackRect() const {
Vec2 pos = getPosition();
Size size = getSize();
@ -333,6 +309,10 @@ Rect Slider::getTrackRect() const {
}
}
/**
* @brief
* @return
*/
std::string Slider::formatText() const {
std::string result = textFormat_;
@ -353,18 +333,25 @@ std::string Slider::formatText() const {
return result;
}
/**
* @brief
* @param value
* @return
*/
float Slider::snapToStep(float value) const {
float steps = std::round((value - min_) / step_);
return min_ + steps * step_;
}
/**
* @brief
* @param renderer
*/
void Slider::onDrawWidget(RenderBackend &renderer) {
Rect trackRect = getTrackRect();
// 绘制轨道背景
renderer.fillRect(trackRect, trackColor_);
// 绘制填充部分
if (showFill_) {
float percent = (value_ - min_) / (max_ - min_);
float fillX = trackRect.origin.x;
@ -383,7 +370,6 @@ void Slider::onDrawWidget(RenderBackend &renderer) {
renderer.fillRect(fillRect, fillColor_);
}
// 绘制滑块
if (showThumb_) {
Rect thumbRect = getThumbRect();
Color thumbColor = thumbColor_;
@ -398,7 +384,6 @@ void Slider::onDrawWidget(RenderBackend &renderer) {
renderer.drawRect(thumbRect, Colors::White, 1.0f);
}
// 绘制文本
if (textEnabled_ && font_) {
std::string text = formatText();
Vec2 textSize = font_->measureText(text);
@ -414,6 +399,11 @@ void Slider::onDrawWidget(RenderBackend &renderer) {
}
}
/**
* @brief
* @param event
* @return
*/
bool Slider::onMousePress(const MouseEvent &event) {
if (event.button == MouseButton::Left) {
Rect thumbRect = getThumbRect();
@ -426,7 +416,6 @@ bool Slider::onMousePress(const MouseEvent &event) {
return true;
}
// 点击轨道直接跳转
Rect trackRect = getTrackRect();
if (trackRect.containsPoint(Point(event.x, event.y))) {
float newValue = positionToValue(vertical_ ? event.y : event.x);
@ -441,6 +430,11 @@ bool Slider::onMousePress(const MouseEvent &event) {
return false;
}
/**
* @brief
* @param event
* @return
*/
bool Slider::onMouseRelease(const MouseEvent &event) {
if (event.button == MouseButton::Left && dragging_) {
dragging_ = false;
@ -452,6 +446,11 @@ bool Slider::onMouseRelease(const MouseEvent &event) {
return false;
}
/**
* @brief
* @param event
* @return
*/
bool Slider::onMouseMove(const MouseEvent &event) {
if (dragging_) {
float newValue = positionToValue(vertical_ ? event.y : event.x);
@ -459,7 +458,6 @@ bool Slider::onMouseMove(const MouseEvent &event) {
return true;
}
// 检查悬停
Rect thumbRect = getThumbRect();
bool wasHovered = hovered_;
hovered_ = thumbRect.containsPoint(Point(event.x, event.y));
@ -467,10 +465,16 @@ bool Slider::onMouseMove(const MouseEvent &event) {
return hovered_ != wasHovered;
}
/**
* @brief
*/
void Slider::onMouseEnter() {
hovered_ = true;
}
/**
* @brief
*/
void Slider::onMouseLeave() {
hovered_ = false;
}

View File

@ -1,136 +1,93 @@
#include <extra2d/ui/text.h>
#include <extra2d/graphics/render_backend.h>
#include <extra2d/core/string.h>
#include <cstdarg>
#include <cstdio>
#include <extra2d/core/string.h>
#include <extra2d/graphics/render_backend.h>
#include <extra2d/ui/text.h>
namespace extra2d {
Text::Text() {
// 文字默认锚点为左上角这样setPosition(0, 0)会在左上角显示
setAnchor(0.0f, 0.0f);
}
/**
* @brief
*/
Text::Text() { setAnchor(0.0f, 0.0f); }
/**
* @brief
* @param text
*/
Text::Text(const std::string &text) : text_(text) {
sizeDirty_ = true;
// 文字默认锚点为左上角这样setPosition(0, 0)会在左上角显示
setAnchor(0.0f, 0.0f);
}
// ------------------------------------------------------------------------
// 链式调用构建器方法
// ------------------------------------------------------------------------
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;
}
// ------------------------------------------------------------------------
// 普通设置方法
// ------------------------------------------------------------------------
/**
* @brief
* @param text
*/
void Text::setText(const std::string &text) {
text_ = text;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @param font
*/
void Text::setFont(Ptr<FontAtlas> font) {
font_ = font;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @param color
*/
void Text::setTextColor(const Color &color) { color_ = color; }
/**
* @brief
* @param size
*/
void Text::setFontSize(int size) {
fontSize_ = size;
sizeDirty_ = true;
updateSpatialIndex();
}
/**
* @brief
* @param align
*/
void Text::setAlignment(Alignment align) {
alignment_ = align;
updateSpatialIndex();
}
/**
* @brief
* @param align
*/
void Text::setVerticalAlignment(VerticalAlignment align) {
verticalAlignment_ = align;
updateSpatialIndex();
}
/**
* @brief
* @return
*/
Vec2 Text::getTextSize() const {
updateCache();
return cachedSize_;
}
/**
* @brief
* @return
*/
float Text::getLineHeight() const {
if (font_) {
return font_->getLineHeight();
@ -138,6 +95,9 @@ float Text::getLineHeight() const {
return static_cast<float>(fontSize_);
}
/**
* @brief
*/
void Text::updateCache() const {
if (!sizeDirty_ || !font_) {
return;
@ -147,22 +107,22 @@ void Text::updateCache() const {
sizeDirty_ = false;
}
/**
* @brief
* @return
*/
Vec2 Text::calculateDrawPosition() const {
Vec2 pos = getPosition();
Vec2 textSize = getTextSize();
Size widgetSize = getSize();
Vec2 anchor = getAnchor();
// 如果设置了控件大小,使用控件大小作为对齐参考
float refWidth = widgetSize.empty() ? textSize.x : widgetSize.width;
float refHeight = widgetSize.empty() ? textSize.y : widgetSize.height;
// 锚点调整:锚点(0.5, 0.5)表示文本中心在pos位置
// 需要将文本向左上方偏移锚点比例 * 文本大小
pos.x -= textSize.x * anchor.x;
pos.y -= textSize.y * anchor.y;
// 水平对齐(仅在设置了控件大小时生效)
if (!widgetSize.empty()) {
switch (alignment_) {
case Alignment::Center:
@ -177,7 +137,6 @@ Vec2 Text::calculateDrawPosition() const {
}
}
// 垂直对齐(仅在设置了控件大小时生效)
if (!widgetSize.empty()) {
switch (verticalAlignment_) {
case VerticalAlignment::Middle:
@ -195,19 +154,37 @@ Vec2 Text::calculateDrawPosition() const {
return pos;
}
/**
* @brief
* @return
*/
Ptr<Text> Text::create() { return makePtr<Text>(); }
/**
* @brief
* @param text
* @return
*/
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) {
auto t = makePtr<Text>(text);
t->setFont(font);
return t;
}
// ------------------------------------------------------------------------
// 格式化创建方法
// ------------------------------------------------------------------------
/**
* @brief
* @param fmt
* @param ...
* @return
*/
Ptr<Text> Text::createFormat(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
@ -217,6 +194,13 @@ Ptr<Text> Text::createFormat(const char *fmt, ...) {
return makePtr<Text>(buffer);
}
/**
* @brief
* @param font
* @param fmt
* @param ...
* @return
*/
Ptr<Text> Text::createFormat(Ptr<FontAtlas> font, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
@ -228,6 +212,10 @@ Ptr<Text> Text::createFormat(Ptr<FontAtlas> font, const char *fmt, ...) {
return t;
}
/**
* @brief
* @return
*/
Rect Text::getBoundingBox() const {
if (!font_ || text_.empty()) {
return Rect();
@ -243,6 +231,10 @@ Rect Text::getBoundingBox() const {
return Rect(pos.x, pos.y, size.x, size.y);
}
/**
* @brief
* @param renderer
*/
void Text::onDrawWidget(RenderBackend &renderer) {
if (!font_ || text_.empty()) {
return;

View File

@ -2,7 +2,6 @@
using namespace extra2d;
// ============================================================================
// Hello World 场景
// ============================================================================
@ -33,34 +32,34 @@ public:
// 创建 "你好世界" 文本组件 - 使用屏幕空间(固定位置,不随相机移动)
auto text1 = Text::create("你好世界", font_);
text1->withCoordinateSpace(CoordinateSpace::Screen)
->withScreenPosition(640.0f, 360.0f) // 屏幕中心
->withAnchor(0.5f, 0.5f) // 中心锚点,让文字中心对准位置
->withTextColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
text1->setCoordinateSpace(CoordinateSpace::Screen);
text1->setScreenPosition(640.0f, 360.0f); // 屏幕中心
text1->setAnchor(0.5f, 0.5f); // 中心锚点,让文字中心对准位置
text1->setTextColor(Color(1.0f, 1.0f, 1.0f, 1.0f));
addChild(text1);
// 创建提示文本组件 - 使用屏幕空间,固定在屏幕底部
auto text2 = Text::create("退出按键START 按钮)", font_);
text2->withCoordinateSpace(CoordinateSpace::Screen)
->withScreenPosition(640.0f, 650.0f) // 屏幕底部
->withAnchor(0.5f, 0.5f)
->withTextColor(Color(1.0f, 1.0f, 0.0f, 1.0f));
text2->setCoordinateSpace(CoordinateSpace::Screen);
text2->setScreenPosition(640.0f, 650.0f); // 屏幕底部
text2->setAnchor(0.5f, 0.5f);
text2->setTextColor(Color(1.0f, 1.0f, 0.0f, 1.0f));
addChild(text2);
// 创建相机空间文本 - 跟随相机但保持相对偏移
auto text3 = Text::create("相机空间文本", font_);
text3->withCoordinateSpace(CoordinateSpace::Camera)
->withCameraOffset(50.0f, 50.0f) // 相机左上角偏移屏幕坐标系Y向下
->withAnchor(0.0f, 0.0f) // 左上角锚点,文字从指定位置开始显示
->withTextColor(Color(0.0f, 1.0f, 1.0f, 1.0f));
text3->setCoordinateSpace(CoordinateSpace::Camera);
text3->setCameraOffset(50.0f, 50.0f); // 相机左上角偏移屏幕坐标系Y向下
text3->setAnchor(0.0f, 0.0f); // 左上角锚点,文字从指定位置开始显示
text3->setTextColor(Color(0.0f, 1.0f, 1.0f, 1.0f));
addChild(text3);
// 创建世界空间文本 - 随相机移动(默认行为)
auto text4 = Text::create("世界空间文本", font_);
text4->withCoordinateSpace(CoordinateSpace::World)
->withPosition(100.0f, 100.0f) // 世界坐标
->withAnchor(0.0f, 0.0f) // 左上角锚点,文字从指定位置开始显示
->withTextColor(Color(1.0f, 0.5f, 0.5f, 1.0f));
text4->setCoordinateSpace(CoordinateSpace::World);
text4->setPosition(100.0f, 100.0f); // 世界坐标
text4->setAnchor(0.0f, 0.0f); // 左上角锚点,文字从指定位置开始显示
text4->setTextColor(Color(1.0f, 0.5f, 0.5f, 1.0f));
addChild(text4);
}
@ -89,8 +88,7 @@ private:
// 程序入口
// ============================================================================
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
// 初始化日志系统
Logger::init();
Logger::setLevel(LogLevel::Debug);