Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add StyleBoxMulti that draws other style boxes #79046

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions doc/classes/StyleBoxMulti.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="StyleBoxMulti" inherits="StyleBox" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Style box that can draw multiple style boxes.
</brief_description>
<description>
StyleBoxMulti is a style box that draws other style boxes. It can be used to combine multiple style boxes into one.
</description>
<tutorials>
</tutorials>
<members>
<member name="style_boxes" type="StyleBox[]" setter="set_style_boxes" getter="get_style_boxes" default="[]">
The style boxes to draw. Each must be a [StyleBox] or a derived class (including custom style boxes defined in GDScript).
</member>
</members>
</class>
1 change: 1 addition & 0 deletions editor/icons/StyleBoxMulti.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions scene/register_scene_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ void register_scene_types() {

GDREGISTER_VIRTUAL_CLASS(StyleBox);
GDREGISTER_CLASS(StyleBoxEmpty);
GDREGISTER_CLASS(StyleBoxMulti);
GDREGISTER_CLASS(StyleBoxTexture);
GDREGISTER_CLASS(StyleBoxFlat);
GDREGISTER_CLASS(StyleBoxLine);
Expand Down
49 changes: 49 additions & 0 deletions scene/resources/style_box.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,55 @@ StyleBox::StyleBox() {
}
}

void StyleBoxMulti::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_style_boxes"), &StyleBoxMulti::get_style_boxes);
ClassDB::bind_method(D_METHOD("set_style_boxes", "style_boxes"), &StyleBoxMulti::set_style_boxes);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "style_boxes", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("StyleBox")), "set_style_boxes", "get_style_boxes");
}

TypedArray<StyleBox> StyleBoxMulti::get_style_boxes() const {
return style_boxes;
}

#ifdef DEBUG_ENABLED
bool _check_for_recursive_style_box_multi_reference(StyleBoxMulti *start, StyleBoxMulti *current) {
if (start == current) {
return true;
}
TypedArray<StyleBox> style_boxes = current->get_style_boxes();
for (int i = 0; i < style_boxes.size(); i++) {
StyleBoxMulti *style_box_multi = Object::cast_to<StyleBoxMulti>(style_boxes[i]);
if (style_box_multi != nullptr) {
if (_check_for_recursive_style_box_multi_reference(start, style_box_multi)) {
return true;
}
}
}
return false;
}
#endif // DEBUG_ENABLED

void StyleBoxMulti::set_style_boxes(const TypedArray<StyleBox> &p_styleboxes) {
#ifdef DEBUG_ENABLED
for (int i = 0; i < p_styleboxes.size(); i++) {
StyleBoxMulti *style_box_multi = Object::cast_to<StyleBoxMulti>(p_styleboxes[i]);
if (style_box_multi != nullptr) {
ERR_FAIL_COND_MSG(_check_for_recursive_style_box_multi_reference(this, style_box_multi), "StyleBoxMulti: Recursive StyleBoxMulti reference detected. Ensure that the StyleBoxMulti does not contain itself.");
}
}
#endif // DEBUG_ENABLED
style_boxes = p_styleboxes;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setter probably should have a cyclic reference check to make sure one of the items is not this or another StyleBoxMulti with this as a child style, or it can get stuck it the infinite draw loop.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a check for that in debug mode https://github.com/aaronfranke/godot/blob/style-box-multi/scene/resources/style_box.cpp#L159-L185

GitHub isn't showing the change on the PR for some reason. I could push again to see if that works but I will need to push again anyway for the docs after the version bump to 4.2 so I'll just wait.

emit_changed();
}

void StyleBoxMulti::draw(RID p_canvas_item, const Rect2 &p_rect) const {
for (int i = 0; i < style_boxes.size(); i++) {
StyleBox *style_box = Object::cast_to<StyleBox>(style_boxes[i]);
ERR_CONTINUE_MSG(style_box == nullptr, "StyleBoxMulti: An item the in style box array is not a valid StyleBox. Ensure it is set to a valid non-null StyleBox.");
style_box->draw(p_canvas_item, p_rect);
}
}

void StyleBoxTexture::set_texture(Ref<Texture2D> p_texture) {
if (texture == p_texture) {
return;
Expand Down
15 changes: 15 additions & 0 deletions scene/resources/style_box.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ class StyleBoxEmpty : public StyleBox {
StyleBoxEmpty() {}
};

class StyleBoxMulti : public StyleBox {
GDCLASS(StyleBoxMulti, StyleBox);
TypedArray<StyleBox> style_boxes;

protected:
static void _bind_methods();

public:
TypedArray<StyleBox> get_style_boxes() const;
void set_style_boxes(const TypedArray<StyleBox> &p_styleboxes);

virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const override;
StyleBoxMulti() {}
};

class StyleBoxTexture : public StyleBox {
GDCLASS(StyleBoxTexture, StyleBox);

Expand Down