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 VisualShape2D node #2

Merged
merged 11 commits into from
Jul 4, 2020
1 change: 1 addition & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def get_doc_classes():
"ImageIndexed",
"ImageIndexed",
"ShapeCast2D",
"VisualShape2D",
]


Expand Down
48 changes: 48 additions & 0 deletions doc/VisualShape2D.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShape2D" inherits="Node2D" version="3.2">
<brief_description>
Draws any [Shape2D] resource. Useful for quick prototyping and debugging.
</brief_description>
<description>
This is a node with the entire purpose of rendering [Shape2D] resources just like collision shapes are drawn in the editor, yet it's also possible to override the color per each node rather than globally with this class. You may use Godot's [Polygon2D] node which is much more suitable for polygon editing and drawing with textures, as any shape can be represented with it.
</description>
<tutorials>
</tutorials>
<methods>
<method name="update_parent_shape">
<return type="bool">
</return>
<description>
Forces to update the shape from parent node. This is called automatically each [b]idle frame[/b] if [member use_parent_shape] is enabled. Updating the shape each frame may be costly, so you can disable this behavior with [code]set_process(false)[/code] on this node, and update the shape manually with this method when needed.
</description>
</method>
</methods>
<members>
<member name="color" type="Color" setter="set_color" getter="get_color" default="Color( 1, 1, 1, 1 )">
The fill color used to draw the [member shape].
</member>
<member name="debug_sync_visible_collision_shapes" type="bool" setter="set_debug_sync_visible_collision_shapes" getter="is_debug_sync_visible_collision_shapes" default="false">
If [code]true[/code], respects the "Visible Collision Shapes" option so that the shape is only drawn when the option is enabled while the game is running.
[b]Note:[/b] available in debug builds only.
</member>
<member name="debug_use_default_color" type="bool" setter="set_debug_use_default_color" getter="is_using_debug_default_color" default="false">
If [code]true[/code], this overrides the [member color] with the color used to draw the collision shapes.
[b]Note:[/b] available in debug builds only.
</member>
<member name="shape" type="Shape2D" setter="set_shape" getter="get_shape">
The shape resource used as a reference to draw. The drawing method is specific for each shape and the properties must be configured per shape.
</member>
<member name="use_parent_shape" type="bool" setter="set_use_parent_shape" getter="is_using_parent_shape" default="false">
If [code]true[/code], the shape is fetched from the parent node to draw instead of its own [member shape]. The parent node must have either [code]shape[/code] as [Shape2D] property or [code]points[/code], [code]polygon[/code] as [PoolVector2Array] property defined, else nothing is drawn.
</member>
</members>
<signals>
<signal name="shape_changed">
<description>
Emitted when the [member shape] is changed (or cleared).
</description>
</signal>
</signals>
<constants>
</constants>
</class>
4 changes: 4 additions & 0 deletions editor/2d/SCsub
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env python
Import("env_goost")

env_goost.add_source_files(env_goost.modules_sources, "*.cpp")
128 changes: 128 additions & 0 deletions editor/2d/visual_shape_2d_editor_plugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "visual_shape_2d_editor_plugin.h"

#include "editor/plugins/canvas_item_editor_plugin.h"

#include "scene/resources/concave_polygon_shape_2d.h"
#include "scene/resources/convex_polygon_shape_2d.h"

Node2D *VisualShape2DEditor::_get_node() const {
return node;
}

void VisualShape2DEditor::_set_node(Node *p_node) {
if (node) {
node->disconnect("shape_changed", this, "_update_editing");
}
node = Object::cast_to<VisualShape2D>(p_node);
if (node) {
node->connect("shape_changed", this, "_update_editing");
}
_update_editing();
}

void VisualShape2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
VisualShape2D *n = Object::cast_to<VisualShape2D>(_get_node());

const Ref<Shape2D> &shape = n->get_shape();
Ref<ConvexPolygonShape2D> convex = shape;
Ref<ConcavePolygonShape2D> concave = shape;

if (convex.is_valid()) {
convex->set("points", p_polygon);

} else if (concave.is_valid()) {
const Vector<Vector2> &polygon = p_polygon;

Vector<Vector2> segments;
segments.resize(polygon.size() * 2);
Vector2 *w = segments.ptrw();

for (int i = 0; i < polygon.size(); ++i) {
w[(i << 1) + 0] = polygon[i];
w[(i << 1) + 1] = polygon[(i + 1) % polygon.size()];
}
concave->set("segments", segments);
}
}

Variant VisualShape2DEditor::_get_polygon(int p_idx) const {
VisualShape2D *n = Object::cast_to<VisualShape2D>(_get_node());

const Ref<Shape2D> &shape = n->get_shape();
Ref<ConvexPolygonShape2D> convex = shape;
Ref<ConcavePolygonShape2D> concave = shape;

if (convex.is_valid()) {
return convex->get("points");

} else if (concave.is_valid()) {
Vector<Vector2> polygon;
const Vector<Vector2> &segments = concave->get("segments");
const Vector2 *r = segments.ptr();

for (int i = 0; i < segments.size(); i += 2) {
polygon.push_back(r[i]);
}
return polygon;
}
return Variant();
}

void VisualShape2DEditor::_update_editing() {
if (!node) {
return;
}
Ref<Shape2D> shape = node->get_shape();
Ref<ConvexPolygonShape2D> convex = shape;
Ref<ConcavePolygonShape2D> concave = shape;

const String reason = TTR("No polygon-based shape resource is set.");

if (shape.is_null()) {
disable_polygon_editing(true, reason);
} else if (convex.is_valid() || concave.is_valid()) {
disable_polygon_editing(false, "");
} else {
disable_polygon_editing(true, reason);
}
}

void VisualShape2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
undo_redo->add_do_method(this, "_set_polygon", 0, p_polygon);
undo_redo->add_undo_method(this, "_set_polygon", 0, p_previous);
}

bool VisualShape2DEditor::_has_resource() const {
if (!node) {
return false;
}
return node->get_shape().is_valid();
}

void VisualShape2DEditor::_create_resource() {
if (!node) {
return;
}
undo_redo->create_action(TTR("Create Convex Polygon Shape"));
undo_redo->add_do_method(node, "set_shape", Ref<ConvexPolygonShape2D>(memnew(ConvexPolygonShape2D)));
undo_redo->add_undo_method(node, "set_shape", Variant(REF()));
undo_redo->commit_action();

_menu_option(MODE_CREATE);

EditorNode::get_singleton()->get_inspector()->refresh();
}

void VisualShape2DEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_polygon"), &VisualShape2DEditor::_set_polygon);
ClassDB::bind_method(D_METHOD("_update_editing"), &VisualShape2DEditor::_update_editing);
}

VisualShape2DEditor::VisualShape2DEditor(EditorNode *p_editor) :
AbstractPolygon2DEditor(p_editor) {
node = nullptr;
}

VisualShape2DEditorPlugin::VisualShape2DEditorPlugin(EditorNode *p_node) :
AbstractPolygon2DEditorPlugin(p_node, memnew(VisualShape2DEditor(p_node)), "VisualShape2D") {
}
39 changes: 39 additions & 0 deletions editor/2d/visual_shape_2d_editor_plugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef GOOST_VISUAL_SHAPE_2D_EDITOR_PLUGIN_H
#define GOOST_VISUAL_SHAPE_2D_EDITOR_PLUGIN_H

#include "editor/plugins/abstract_polygon_2d_editor.h"
#include "goost/scene/2d/visual_shape_2d.h"

class VisualShape2DEditor : public AbstractPolygon2DEditor {
GDCLASS(VisualShape2DEditor, AbstractPolygon2DEditor);

VisualShape2D *node;

void _update_editing();

protected:
virtual Node2D *_get_node() const;
virtual void _set_node(Node *p_node);

virtual void _set_polygon(int p_idx, const Variant &p_polygon) const;
virtual Variant _get_polygon(int p_idx) const;

virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon);

virtual bool _has_resource() const;
virtual void _create_resource();

static void _bind_methods();

public:
VisualShape2DEditor(EditorNode *p_editor);
};

class VisualShape2DEditorPlugin : public AbstractPolygon2DEditorPlugin {
GDCLASS(VisualShape2DEditorPlugin, AbstractPolygon2DEditorPlugin);

public:
VisualShape2DEditorPlugin(EditorNode *p_node);
};

#endif // GOOST_VISUAL_SHAPE_2D_EDITOR_PLUGIN_H
3 changes: 3 additions & 0 deletions editor/3d/SCsub
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env python

# Nothing here yet!
10 changes: 9 additions & 1 deletion editor/SCsub
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
#!/usr/bin/env python
Import("env")
Import("env_goost")

# Nothing here yet!
if env_goost["goost_editor_enabled"]:
SConscript("2d/SCsub", exports="env_goost")

if not env["disable_3d"]:
SConscript("3d/SCsub", exports="env_goost")

env_goost.add_source_files(env_goost.modules_sources, "*.cpp")
2 changes: 1 addition & 1 deletion editor/icons/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

This directory contains icons for classes provided by Goost.

See official
See official Godot Engine's
[Editor icons](https://docs.godotengine.org/en/latest/development/editor/creating_icons.html)
documentation page on how to create them.
5 changes: 5 additions & 0 deletions editor/icons/icon_visual_shape_2d.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions editor/register_editor_types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "register_editor_types.h"

#include "2d/visual_shape_2d_editor_plugin.h"

namespace goost {

void register_editor_types() {
#ifdef TOOLS_ENABLED
EditorPlugins::add_by_type<VisualShape2DEditorPlugin>();
#endif
}

void unregister_editor_types() {
// Nothing to do.
}

} // namespace goost
6 changes: 6 additions & 0 deletions editor/register_editor_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace goost {

void register_editor_types();
void unregister_editor_types();

} // namespace goost
1 change: 1 addition & 0 deletions goost.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"core/image",
"core/math",
"scene/physics",
"editor",
]

def get_components():
Expand Down
4 changes: 4 additions & 0 deletions register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "core/register_core_types.h"
#include "scene/register_scene_types.h"
#include "editor/register_editor_types.h"

void register_goost_types() {
#ifdef GOOST_CORE_ENABLED
Expand All @@ -10,6 +11,9 @@ void register_goost_types() {
#ifdef GOOST_SCENE_ENABLED
goost::register_scene_types();
#endif
#ifdef GOOST_EDITOR_ENABLED
goost::register_editor_types();
#endif
}

void unregister_goost_types() {
Expand Down
4 changes: 4 additions & 0 deletions scene/2d/SCsub
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env python
Import("env_goost")

env_goost.add_source_files(env_goost.modules_sources, '*.cpp')
Loading