summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/array.cpp11
-rw-r--r--core/array.h6
-rw-r--r--core/io/logger.cpp11
-rw-r--r--doc/classes/Array.xml12
-rw-r--r--doc/classes/Tree.xml70
-rw-r--r--doc/classes/TreeItem.xml61
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp619
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h131
-rwxr-xr-x[-rw-r--r--]editor/plugins/collision_polygon_2d_editor_plugin.cpp396
-rwxr-xr-x[-rw-r--r--]editor/plugins/collision_polygon_2d_editor_plugin.h60
-rwxr-xr-x[-rw-r--r--]editor/plugins/navigation_polygon_editor_plugin.cpp500
-rwxr-xr-x[-rw-r--r--]editor/plugins/navigation_polygon_editor_plugin.h74
-rwxr-xr-x[-rw-r--r--]editor/plugins/polygon_2d_editor_plugin.cpp414
-rwxr-xr-x[-rw-r--r--]editor/plugins/polygon_2d_editor_plugin.h61
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp3
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp18
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java73
-rw-r--r--platform/android/java_glue.cpp63
18 files changed, 1048 insertions, 1535 deletions
diff --git a/core/array.cpp b/core/array.cpp
index 30184a002e..171c11776c 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -233,9 +233,10 @@ struct _ArrayVariantSort {
}
};
-void Array::sort() {
+Array &Array::sort() {
_p->array.sort_custom<_ArrayVariantSort>();
+ return *this;
}
struct _ArrayVariantSortCustom {
@@ -253,19 +254,21 @@ struct _ArrayVariantSortCustom {
return res;
}
};
-void Array::sort_custom(Object *p_obj, const StringName &p_function) {
+Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
- ERR_FAIL_NULL(p_obj);
+ ERR_FAIL_NULL_V(p_obj, *this);
SortArray<Variant, _ArrayVariantSortCustom> avs;
avs.compare.obj = p_obj;
avs.compare.func = p_function;
avs.sort(_p->array.ptr(), _p->array.size());
+ return *this;
}
-void Array::invert() {
+Array &Array::invert() {
_p->array.invert();
+ return *this;
}
void Array::push_front(const Variant &p_value) {
diff --git a/core/array.h b/core/array.h
index 8a647dd13b..2c29103108 100644
--- a/core/array.h
+++ b/core/array.h
@@ -68,9 +68,9 @@ public:
Variant front() const;
Variant back() const;
- void sort();
- void sort_custom(Object *p_obj, const StringName &p_function);
- void invert();
+ Array &sort();
+ Array &sort_custom(Object *p_obj, const StringName &p_function);
+ Array &invert();
int find(const Variant &p_value, int p_from = 0) const;
int rfind(const Variant &p_value, int p_from = -1) const;
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index b94007d316..ad6371f1e1 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -33,6 +33,17 @@
#include "os/os.h"
#include "print_string.h"
+// va_copy was defined in the C99, but not in C++ standards before C++11.
+// When you compile C++ without --std=c++<XX> option, compilers still define
+// va_copy, otherwise you have to use the internal version (__va_copy).
+#if !defined(va_copy)
+#if defined(__GNUC__)
+#define va_copy(d, s) __va_copy(d, s)
+#else
+#define va_copy(d, s) ((d) = (s))
+#endif
+#endif
+
bool Logger::should_log(bool p_err) {
return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
}
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 47100f23b8..2cfbaffe04 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -178,8 +178,10 @@
</description>
</method>
<method name="invert">
+ <return type="Array">
+ </return>
<description>
- Reverse the order of the elements in the array (so first element will now be the last).
+ Reverse the order of the elements in the array (so first element will now be the last) and return reference to the array.
</description>
</method>
<method name="pop_back">
@@ -239,17 +241,21 @@
</description>
</method>
<method name="sort">
+ <return type="Array">
+ </return>
<description>
- Sort the array using natural order.
+ Sort the array using natural order and return reference to the array.
</description>
</method>
<method name="sort_custom">
+ <return type="Array">
+ </return>
<argument index="0" name="obj" type="Object">
</argument>
<argument index="1" name="func" type="String">
</argument>
<description>
- Sort the array using a custom method. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
+ Sort the array using a custom method and return reference to the array. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
</description>
</method>
</methods>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 82e85126cc..bf9245d23a 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -4,8 +4,8 @@
Control to show a tree of items.
</brief_description>
<description>
- This shows a tree of items that can be selected, expanded and collapsed. The tree can have multiple columns with custom controls like text editing, buttons and popups. It can be useful for structural displaying and interactions.
- Trees are built via code, using [TreeItem] objects to create the structure. They have a single root but multiple root can be simulated if a dummy hidden root is added.
+ This shows a tree of items that can be selected, expanded and collapsed. The tree can have multiple columns with custom controls like text editing, buttons and popups. It can be useful for structured displays and interactions.
+ Trees are built via code, using [TreeItem] objects to create the structure. They have a single root but multiple roots can be simulated if a dummy hidden root is added.
[codeblock]
func _ready():
var tree = Tree.new()
@@ -26,14 +26,14 @@
<return type="bool">
</return>
<description>
- Get whether the column titles are being shown.
+ Returns [code]true[/code] if the column titles are being shown.
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
- Clear the tree. This erases all of the items.
+ Clears the tree. This removes all items.
</description>
</method>
<method name="create_item">
@@ -42,27 +42,28 @@
<argument index="0" name="parent" type="Object" default="null">
</argument>
<description>
- Create an item in the tree and add it as the last child of [code]parent[/code]. If parent is not given, it will be added as the last child of the root, or it'll the be the root itself if the tree is empty.
+ Create an item in the tree and add it as the last child of [code]parent[/code]. If parent is not given, it will be added as the root's last child, or it'll the be the root itself if the tree is empty.
</description>
</method>
<method name="ensure_cursor_is_visible">
<return type="void">
</return>
<description>
- Make the current selected item visible. This will scroll the tree to make sure the selected item is in sight.
+ Makes the currently selected item visible. This will scroll the tree to make sure the selected item is visible.
</description>
</method>
<method name="get_allow_reselect" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if a cell that is currently already selected may be selected again.
</description>
</method>
<method name="get_allow_rmb_select" qualifiers="const">
<return type="bool">
</return>
<description>
- Get whether a right click can select items.
+ Returns [code]true[/code] if a right click can select items.
</description>
</method>
<method name="get_column_at_position" qualifiers="const">
@@ -71,7 +72,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Get the column index under the given point.
+ Returns the column index under the given point.
</description>
</method>
<method name="get_column_title" qualifiers="const">
@@ -80,7 +81,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
- Get the title of the given column.
+ Returns the column's title.
</description>
</method>
<method name="get_column_width" qualifiers="const">
@@ -89,28 +90,28 @@
<argument index="0" name="column" type="int">
</argument>
<description>
- Get the width of the given column in pixels.
+ Returns the column's width in pixels.
</description>
</method>
<method name="get_columns" qualifiers="const">
<return type="int">
</return>
<description>
- Get the amount of columns.
+ Returns the amount of columns.
</description>
</method>
<method name="get_custom_popup_rect" qualifiers="const">
<return type="Rect2">
</return>
<description>
- Get the rectangle for custom popups. Helper to create custom cell controls that display a popup. See [method TreeItem.set_cell_mode].
+ Returns the rectangle for custom popups. Helper to create custom cell controls that display a popup. See [method TreeItem.set_cell_mode].
</description>
</method>
<method name="get_drop_mode_flags" qualifiers="const">
<return type="int">
</return>
<description>
- Get the flags of the current drop mode.
+ Returns the current drop mode's flags.
</description>
</method>
<method name="get_drop_section_at_position" qualifiers="const">
@@ -125,14 +126,14 @@
<return type="TreeItem">
</return>
<description>
- Get the current edited item. This is only available for custom cell mode.
+ Returns the currently edited item. This is only available for custom cell mode.
</description>
</method>
<method name="get_edited_column" qualifiers="const">
<return type="int">
</return>
<description>
- Get the column of the cell for the current edited icon. This is only available for custom cell mode.
+ Returns the column for the currently edited item. This is only available for custom cell mode.
</description>
</method>
<method name="get_item_area_rect" qualifiers="const">
@@ -143,7 +144,7 @@
<argument index="1" name="column" type="int" default="-1">
</argument>
<description>
- Get the rectangle area of the the specified item. If column is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
+ Returns the rectangle area for the specified item. If column is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
</description>
</method>
<method name="get_item_at_position" qualifiers="const">
@@ -152,7 +153,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Get the tree item at the specified position (relative to the tree origin position).
+ Returns the tree item at the specified position (relative to the tree origin position).
</description>
</method>
<method name="get_next_selected">
@@ -161,49 +162,49 @@
<argument index="0" name="from" type="Object">
</argument>
<description>
- Get the next selected item after the given one.
+ Returns the next selected item after the given one.
</description>
</method>
<method name="get_pressed_button" qualifiers="const">
<return type="int">
</return>
<description>
- Get the index of the last pressed button.
+ Returns the last pressed button's index.
</description>
</method>
<method name="get_root">
<return type="TreeItem">
</return>
<description>
- Get the root item of the tree.
+ Returns the tree's root item.
</description>
</method>
<method name="get_scroll" qualifiers="const">
<return type="Vector2">
</return>
<description>
- Get the current scrolling position.
+ Returns the current scrolling position.
</description>
</method>
<method name="get_selected" qualifiers="const">
<return type="TreeItem">
</return>
<description>
- Get the currently selected item.
+ Returns the currently selected item.
</description>
</method>
<method name="get_selected_column" qualifiers="const">
<return type="int">
</return>
<description>
- Get the column number of the current selection.
+ Returns the current selection's column.
</description>
</method>
<method name="is_folding_hidden" qualifiers="const">
<return type="bool">
</return>
<description>
- Get whether the folding arrow is hidden.
+ Returns [code]true[/code] if the folding arrow is hidden.
</description>
</method>
<method name="set_allow_reselect">
@@ -212,6 +213,7 @@
<argument index="0" name="allow" type="bool">
</argument>
<description>
+ If [code]true[/code] the currently selected cell may be selected again.
</description>
</method>
<method name="set_allow_rmb_select">
@@ -220,7 +222,7 @@
<argument index="0" name="allow" type="bool">
</argument>
<description>
- Set whether or not a right mouse button click can select items.
+ If [code]true[/code] a right mouse button click can select items.
</description>
</method>
<method name="set_column_expand">
@@ -231,7 +233,7 @@
<argument index="1" name="expand" type="bool">
</argument>
<description>
- Set whether a column will have the "Expand" flag of [Control].
+ If [code]true[/code] the column will have the "Expand" flag of [Control].
</description>
</method>
<method name="set_column_min_width">
@@ -262,7 +264,7 @@
<argument index="0" name="visible" type="bool">
</argument>
<description>
- Set whether the column titles visibility.
+ If [code]true[/code] column titles are visible.
</description>
</method>
<method name="set_columns">
@@ -289,7 +291,7 @@
<argument index="0" name="hide" type="bool">
</argument>
<description>
- Set whether the folding arrow should be hidden.
+ If [code]true[/code] the folding arrow is hidden.
</description>
</method>
<method name="set_hide_root">
@@ -298,7 +300,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set whether the root of the tree should be hidden.
+ If [code]true[/code] the tree's root is hidden.
</description>
</method>
<method name="set_select_mode">
@@ -307,7 +309,7 @@
<argument index="0" name="mode" type="int" enum="Tree.SelectMode">
</argument>
<description>
- Set the selection mode. Use one of the [code]SELECT_*[/code] constants.
+ Allow single or multiple selection. See the [code]SELECT_*[/code] constants.
</description>
</method>
</methods>
@@ -332,6 +334,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Emitted when a column's title is pressed.
</description>
</signal>
<signal name="custom_popup_edited">
@@ -366,15 +369,17 @@
</signal>
<signal name="item_double_clicked">
<description>
+ Emitted when an item is double clicked.
</description>
</signal>
<signal name="item_edited">
<description>
- Emitted when an item is editted.
+ Emitted when an item is edited.
</description>
</signal>
<signal name="item_rmb_edited">
<description>
+ Emitted when an item is edited using the right mouse button.
</description>
</signal>
<signal name="item_rmb_selected">
@@ -397,15 +402,18 @@
<argument index="2" name="selected" type="bool">
</argument>
<description>
+ Emitted instead of [code]item_selected[/code] when [code]select_mode[/code] is [code]SELECT_MULTI[/code].
</description>
</signal>
</signals>
<constants>
<constant name="SELECT_SINGLE" value="0">
+ Allow selection of a single item at a time.
</constant>
<constant name="SELECT_ROW" value="1">
</constant>
<constant name="SELECT_MULTI" value="2">
+ Allow selection of multiple items at the same time.
</constant>
<constant name="DROP_MODE_DISABLED" value="0">
</constant>
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index d1e45bd10f..10ebc72134 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TreeItem" inherits="Object" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Control for a single item inside a [Tree].
</brief_description>
<description>
+ Control for a single item inside a [Tree]. May have child [TreeItem]\ s and be styled as well as contain buttons.
</description>
<tutorials>
</tutorials>
@@ -23,6 +25,7 @@
<argument index="4" name="tooltip" type="String" default="&quot;&quot;">
</argument>
<description>
+ Adds a button with [Texture] [code]button[/code] at column [code]column[/code]. The [code]button_idx[/code] index is used to identify the button when calling other methods. If not specified, the next available index is used, which may be retrieved by calling [code]get_buton_count()[/code] immediately after this method. Optionally, the button can be [code]disabled[/code] and have a [code]tooltip[/code].
</description>
</method>
<method name="clear_custom_bg_color">
@@ -31,6 +34,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Resets the background color for the given column to default.
</description>
</method>
<method name="clear_custom_color">
@@ -39,6 +43,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Resets the color for the given column to default.
</description>
</method>
<method name="deselect">
@@ -47,6 +52,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Deselects the given column.
</description>
</method>
<method name="erase_button">
@@ -57,6 +63,7 @@
<argument index="1" name="button_idx" type="int">
</argument>
<description>
+ Removes the button at index [code]button_idx[/code] in column [code]column[/code].
</description>
</method>
<method name="get_button" qualifiers="const">
@@ -67,6 +74,7 @@
<argument index="1" name="button_idx" type="int">
</argument>
<description>
+ Returns the [Texture] of the button at index [code]button_idx[/code] in column [code]column[/code].
</description>
</method>
<method name="get_button_count" qualifiers="const">
@@ -75,6 +83,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the number of buttons in column [code]column[/code]. May be used to get the most recently added button's index, if no index was specified.
</description>
</method>
<method name="get_cell_mode" qualifiers="const">
@@ -83,12 +92,14 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the column's cell mode. See [code]CELL_MODE_*[/code] constants.
</description>
</method>
<method name="get_children">
<return type="TreeItem">
</return>
<description>
+ Returns the TreeItem's child items.
</description>
</method>
<method name="get_custom_bg_color" qualifiers="const">
@@ -97,12 +108,14 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the custom background color of column [code]column[/code].
</description>
</method>
<method name="get_custom_minimum_height" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the custom minimum height.
</description>
</method>
<method name="get_expand_right" qualifiers="const">
@@ -111,6 +124,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if [code]expand_right[/code] is set.
</description>
</method>
<method name="get_icon" qualifiers="const">
@@ -119,6 +133,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the given column's icon [Texture]. Error if no icon is set.
</description>
</method>
<method name="get_icon_max_width" qualifiers="const">
@@ -127,6 +142,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the column's icon's maximum width.
</description>
</method>
<method name="get_icon_region" qualifiers="const">
@@ -135,6 +151,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the icon [Texture] region as [Rect2].
</description>
</method>
<method name="get_metadata" qualifiers="const">
@@ -149,30 +166,35 @@
<return type="TreeItem">
</return>
<description>
+ Returns the next TreeItem in the tree.
</description>
</method>
<method name="get_next_visible">
<return type="TreeItem">
</return>
<description>
+ Returns the next visible TreeItem in the tree.
</description>
</method>
<method name="get_parent">
<return type="TreeItem">
</return>
<description>
+ Returns the parent TreeItem.
</description>
</method>
<method name="get_prev">
<return type="TreeItem">
</return>
<description>
+ Returns the previous TreeItem in the tree.
</description>
</method>
<method name="get_prev_visible">
<return type="TreeItem">
</return>
<description>
+ Returns the previous visible TreeItem in the tree.
</description>
</method>
<method name="get_range" qualifiers="const">
@@ -197,6 +219,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the given column's text.
</description>
</method>
<method name="get_text_align" qualifiers="const">
@@ -205,6 +228,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the given column's text alignment.
</description>
</method>
<method name="get_tooltip" qualifiers="const">
@@ -213,6 +237,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the given column's tooltip.
</description>
</method>
<method name="is_button_disabled" qualifiers="const">
@@ -223,6 +248,7 @@
<argument index="1" name="button_idx" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the button at index [code]button_idx[/code] for the given column is disabled.
</description>
</method>
<method name="is_checked" qualifiers="const">
@@ -231,12 +257,14 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the given column is checked.
</description>
</method>
<method name="is_collapsed">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if this TreeItem is collapsed.
</description>
</method>
<method name="is_custom_set_as_button" qualifiers="const">
@@ -253,12 +281,14 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if column [code]column[/code] is editable.
</description>
</method>
<method name="is_folding_disabled" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns [code]true[/code] if folding is disabled for this TreeItem.
</description>
</method>
<method name="is_selectable" qualifiers="const">
@@ -267,6 +297,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if column [code]column[/code] is selectable.
</description>
</method>
<method name="is_selected">
@@ -275,18 +306,21 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns [code]true[/code] if column [code]column[/code] is selected.
</description>
</method>
<method name="move_to_bottom">
<return type="void">
</return>
<description>
+ Moves this TreeItem to the bottom in the [Tree] hierarchy.
</description>
</method>
<method name="move_to_top">
<return type="void">
</return>
<description>
+ Moves this TreeItem to the top in the [Tree] hierarchy.
</description>
</method>
<method name="remove_child">
@@ -295,6 +329,7 @@
<argument index="0" name="child" type="Object">
</argument>
<description>
+ Removes the child TreeItem at index [code]index[/code].
</description>
</method>
<method name="select">
@@ -303,6 +338,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Selects the column [code]column[/code].
</description>
</method>
<method name="set_button">
@@ -315,6 +351,7 @@
<argument index="2" name="button" type="Texture">
</argument>
<description>
+ Sets the given column's button [Texture] at index [code]button_idx[/code] to [code]button[/code].
</description>
</method>
<method name="set_cell_mode">
@@ -325,6 +362,7 @@
<argument index="1" name="mode" type="int" enum="TreeItem.TreeCellMode">
</argument>
<description>
+ Sets the given column's cell mode to [code]mode[/code]. See [code]CELL_MODE_*[/code] constants.
</description>
</method>
<method name="set_checked">
@@ -335,6 +373,7 @@
<argument index="1" name="checked" type="bool">
</argument>
<description>
+ If [code]true[/code] the column [code]column[/code] is checked.
</description>
</method>
<method name="set_collapsed">
@@ -343,6 +382,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] the TreeItem is collapsed.
</description>
</method>
<method name="set_custom_as_button">
@@ -365,6 +405,7 @@
<argument index="2" name="just_outline" type="bool" default="false">
</argument>
<description>
+ Sets the given column's custom background color and whether to just use it as an outline.
</description>
</method>
<method name="set_custom_color">
@@ -375,6 +416,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Sets the given column's custom color.
</description>
</method>
<method name="set_custom_draw">
@@ -387,6 +429,7 @@
<argument index="2" name="callback" type="String">
</argument>
<description>
+ Sets the given column's custom draw callback to [code]callback[/code] method on [code]object[/code].
</description>
</method>
<method name="set_custom_minimum_height">
@@ -395,6 +438,7 @@
<argument index="0" name="height" type="int">
</argument>
<description>
+ Sets the custom minimum height of this TreeItem.
</description>
</method>
<method name="set_disable_folding">
@@ -403,6 +447,7 @@
<argument index="0" name="disable" type="bool">
</argument>
<description>
+ If [code]true[/code] folding is disabled for this TreeItem.
</description>
</method>
<method name="set_editable">
@@ -413,6 +458,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
+ If [code]true[/code] column [code]column[/code] is editable.
</description>
</method>
<method name="set_expand_right">
@@ -423,6 +469,7 @@
<argument index="1" name="enable" type="bool">
</argument>
<description>
+ If [code]true[/code] column [code]column[/code] is expanded to the right.
</description>
</method>
<method name="set_icon">
@@ -433,6 +480,7 @@
<argument index="1" name="texture" type="Texture">
</argument>
<description>
+ Sets the given column's icon [Texture].
</description>
</method>
<method name="set_icon_max_width">
@@ -443,6 +491,7 @@
<argument index="1" name="width" type="int">
</argument>
<description>
+ Sets the given column's icon's maximum width.
</description>
</method>
<method name="set_icon_region">
@@ -453,6 +502,7 @@
<argument index="1" name="region" type="Rect2">
</argument>
<description>
+ Sets the given column's icon's texture region.
</description>
</method>
<method name="set_metadata">
@@ -499,6 +549,7 @@
<argument index="1" name="selectable" type="bool">
</argument>
<description>
+ If [code]true[/code] the given column is selectable.
</description>
</method>
<method name="set_text">
@@ -519,6 +570,7 @@
<argument index="1" name="text_align" type="int" enum="TreeItem.TextAlign">
</argument>
<description>
+ Sets the given column's text alignment. See [code]ALIGN_*[/code] constants.
</description>
</method>
<method name="set_tooltip">
@@ -529,27 +581,36 @@
<argument index="1" name="tooltip" type="String">
</argument>
<description>
+ Sets the given column's tooltip text.
</description>
</method>
</methods>
<constants>
<constant name="CELL_MODE_STRING" value="0">
+ Cell contains a string.
</constant>
<constant name="CELL_MODE_CHECK" value="1">
+ Cell can be checked.
</constant>
<constant name="CELL_MODE_RANGE" value="2">
+ Cell contains a range.
</constant>
<constant name="CELL_MODE_RANGE_EXPRESSION" value="3">
+ Cell contains a range expression.
</constant>
<constant name="CELL_MODE_ICON" value="4">
+ Cell contains an icon.
</constant>
<constant name="CELL_MODE_CUSTOM" value="5">
</constant>
<constant name="ALIGN_LEFT" value="0">
+ Align text to the left. See [code]set_text_align()[/code].
</constant>
<constant name="ALIGN_CENTER" value="1">
+ Center text. See [code]set_text_align()[/code].
</constant>
<constant name="ALIGN_RIGHT" value="2">
+ Align text to the right. See [code]set_text_align()[/code].
</constant>
</constants>
</class>
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
new file mode 100644
index 0000000000..2fd74d529e
--- /dev/null
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -0,0 +1,619 @@
+/*************************************************************************/
+/* abstract_polygon_2d_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "abstract_polygon_2d_editor.h"
+
+#include "canvas_item_editor_plugin.h"
+
+bool AbstractPolygon2DEditor::_is_empty() const {
+
+ if (!_get_node())
+ return true;
+
+ const int n = _get_polygon_count();
+
+ for (int i = 0; i < n; i++) {
+
+ Vector<Vector2> vertices = _get_polygon(i);
+
+ if (vertices.size() != 0)
+ return false;
+ }
+
+ return true;
+}
+
+int AbstractPolygon2DEditor::_get_polygon_count() const {
+
+ return 1;
+}
+
+Variant AbstractPolygon2DEditor::_get_polygon(int p_idx) const {
+
+ return _get_node()->get("polygon");
+}
+
+void AbstractPolygon2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
+
+ _get_node()->set("polygon", p_polygon);
+}
+
+void AbstractPolygon2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
+
+ Node2D *node = _get_node();
+ undo_redo->add_do_method(node, "set_polygon", p_polygon);
+ undo_redo->add_undo_method(node, "set_polygon", p_previous);
+}
+
+Vector2 AbstractPolygon2DEditor::_get_offset(int p_idx) const {
+
+ return Vector2(0, 0);
+}
+
+void AbstractPolygon2DEditor::_commit_action() {
+
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->commit_action();
+}
+
+void AbstractPolygon2DEditor::_action_add_polygon(const Variant &p_polygon) {
+
+ _action_set_polygon(0, p_polygon);
+}
+
+void AbstractPolygon2DEditor::_action_remove_polygon(int p_idx) {
+
+ _action_set_polygon(p_idx, _get_polygon(p_idx), PoolVector<Vector2>());
+}
+
+void AbstractPolygon2DEditor::_action_set_polygon(int p_idx, const Variant &p_polygon) {
+
+ _action_set_polygon(p_idx, _get_polygon(p_idx), p_polygon);
+}
+
+bool AbstractPolygon2DEditor::_has_resource() const {
+
+ return true;
+}
+
+void AbstractPolygon2DEditor::_create_resource() {
+}
+
+void AbstractPolygon2DEditor::_menu_option(int p_option) {
+
+ switch (p_option) {
+
+ case MODE_CREATE: {
+
+ mode = MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ mode = MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ } break;
+ }
+}
+
+void AbstractPolygon2DEditor::_notification(int p_what) {
+
+ switch (p_what) {
+
+ case NOTIFICATION_READY: {
+
+ button_create->set_icon(get_icon("Edit", "EditorIcons"));
+ button_edit->set_icon(get_icon("MovePoint", "EditorIcons"));
+ button_edit->set_pressed(true);
+
+ get_tree()->connect("node_removed", this, "_node_removed");
+
+ create_resource->connect("confirmed", this, "_create_resource");
+
+ } break;
+ case NOTIFICATION_PHYSICS_PROCESS: {
+
+ } break;
+ }
+}
+
+void AbstractPolygon2DEditor::_node_removed(Node *p_node) {
+
+ if (p_node == _get_node()) {
+ edit(NULL);
+ hide();
+
+ canvas_item_editor->get_viewport_control()->update();
+ }
+}
+
+void AbstractPolygon2DEditor::_wip_close() {
+
+ if (wip.size() >= 3) {
+
+ undo_redo->create_action(TTR("Create Poly"));
+ _action_add_polygon(wip);
+ _commit_action();
+
+ mode = MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ }
+
+ wip.clear();
+ wip_active = false;
+ edited_point = -1;
+}
+
+bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
+
+ if (!_get_node())
+ return false;
+
+ Ref<InputEventMouseButton> mb = p_event;
+
+ if (!_has_resource()) {
+
+ if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
+ create_resource->set_text(String("No polygon resource on this node.\nCreate and assign one?"));
+ create_resource->popup_centered_minsize();
+ }
+ return (mb.is_valid() && mb->get_button_index() == 1);
+ }
+
+ if (mb.is_valid()) {
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
+
+ Vector2 gpoint = mb->get_position();
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint = canvas_item_editor->snap_point(cpoint);
+ cpoint = _get_node()->get_global_transform().affine_inverse().xform(cpoint);
+
+ //first check if a point is to be added (segment split)
+ real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+
+ if (mode == MODE_CREATE) {
+
+ if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back(cpoint);
+ wip_active = true;
+ edited_point_pos = cpoint;
+ edited_polygon = -1;
+ edited_point = 1;
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ } else {
+
+ if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) {
+ //wip closed
+ _wip_close();
+
+ return true;
+ } else {
+
+ wip.push_back(cpoint);
+ edited_point = wip.size();
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
+ _wip_close();
+ }
+ } else if (mode == MODE_EDIT) {
+
+ if (mb->get_button_index() == BUTTON_LEFT) {
+
+ if (mb->is_pressed()) {
+
+ if (mb->get_control()) {
+
+ const int n_polygons = _get_polygon_count();
+
+ if (n_polygons >= 1) {
+
+ Vector<Vector2> vertices = _get_polygon(n_polygons - 1);
+
+ if (vertices.size() < 3) {
+
+ vertices.push_back(cpoint);
+ undo_redo->create_action(TTR("Edit Poly"));
+ _action_set_polygon(n_polygons - 1, vertices);
+ _commit_action();
+ return true;
+ }
+ }
+
+ //search edges
+ int closest_poly = -1;
+ int closest_idx = -1;
+ Vector2 closest_pos;
+ real_t closest_dist = 1e10;
+
+ for (int j = 0; j < n_polygons; j++) {
+
+ PoolVector<Vector2> points = _get_polygon(j);
+ const Vector2 offset = _get_offset(j);
+ const int n_points = points.size();
+
+ for (int i = 0; i < n_points; i++) {
+
+ Vector2 p[2] = { xform.xform(points[i] + offset),
+ xform.xform(points[(i + 1) % n_points] + offset) };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, p);
+ if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(gpoint);
+ if (d < closest_dist && d < grab_threshold) {
+ closest_poly = j;
+ closest_dist = d;
+ closest_pos = cp;
+ closest_idx = i;
+ }
+ }
+ }
+
+ if (closest_idx >= 0) {
+
+ Vector<Vector2> vertices = _get_polygon(closest_poly);
+ pre_move_edit = vertices;
+ vertices.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
+ edited_point = closest_idx + 1;
+ edited_polygon = closest_poly;
+ edited_point_pos = xform.affine_inverse().xform(closest_pos);
+
+ undo_redo->create_action(TTR("Insert Point"));
+ _action_set_polygon(closest_poly, vertices);
+ _commit_action();
+
+ return true;
+ }
+ } else {
+
+ //look for points to move
+ int closest_poly = -1;
+ int closest_idx = -1;
+ Vector2 closest_pos;
+ real_t closest_dist = 1e10;
+
+ const int n_polygons = _get_polygon_count();
+
+ for (int j = 0; j < n_polygons; j++) {
+
+ PoolVector<Vector2> points = _get_polygon(j);
+ const Vector2 offset = _get_offset(j);
+ const int n_points = points.size();
+
+ for (int i = 0; i < n_points; i++) {
+
+ Vector2 cp = xform.xform(points[i] + offset);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d < closest_dist && d < grab_threshold) {
+ closest_poly = j;
+ closest_dist = d;
+ closest_pos = cp;
+ closest_idx = i;
+ }
+ }
+ }
+
+ if (closest_idx >= 0) {
+
+ pre_move_edit = _get_polygon(closest_poly);
+ edited_polygon = closest_poly;
+ edited_point = closest_idx;
+ edited_point_pos = xform.affine_inverse().xform(closest_pos);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point != -1) {
+
+ //apply
+
+ Vector<Vector2> vertices = _get_polygon(edited_polygon);
+ ERR_FAIL_INDEX_V(edited_point, vertices.size(), false);
+ vertices[edited_point] = edited_point_pos - _get_offset(edited_polygon);
+
+ undo_redo->create_action(TTR("Edit Poly"));
+ _action_set_polygon(edited_polygon, pre_move_edit, vertices);
+ _commit_action();
+
+ edited_point = -1;
+ return true;
+ }
+ }
+ } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
+
+ int closest_poly = -1;
+ int closest_idx = -1;
+ Vector2 closest_pos;
+ real_t closest_dist = 1e10;
+ const int n_polygons = _get_polygon_count();
+
+ for (int j = 0; j < n_polygons; j++) {
+
+ PoolVector<Vector2> points = _get_polygon(j);
+ const int n_points = points.size();
+ const Vector2 offset = _get_offset(j);
+
+ for (int i = 0; i < n_points; i++) {
+
+ Vector2 cp = xform.xform(points[i] + offset);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d < closest_dist && d < grab_threshold) {
+ closest_poly = j;
+ closest_dist = d;
+ closest_pos = cp;
+ closest_idx = i;
+ }
+ }
+ }
+
+ if (closest_idx >= 0) {
+
+ PoolVector<Vector2> vertices = _get_polygon(closest_poly);
+
+ if (vertices.size() > 3) {
+
+ vertices.remove(closest_idx);
+
+ undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+ _action_set_polygon(closest_poly, vertices);
+ _commit_action();
+ } else {
+
+ undo_redo->create_action(TTR("Remove Poly And Point"));
+ _action_remove_polygon(closest_poly);
+ _commit_action();
+ }
+
+ if (_is_empty())
+ _menu_option(MODE_CREATE);
+ return true;
+ }
+ }
+ }
+ }
+
+ Ref<InputEventMouseMotion> mm = p_event;
+
+ if (mm.is_valid()) {
+
+ if (edited_point != -1 && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) {
+
+ Vector2 gpoint = mm->get_position();
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint = canvas_item_editor->snap_point(cpoint);
+ edited_point_pos = _get_node()->get_global_transform().affine_inverse().xform(cpoint);
+
+ if (!wip_active) {
+
+ Vector<Vector2> vertices = _get_polygon(edited_polygon);
+ ERR_FAIL_INDEX_V(edited_point, vertices.size(), false);
+ vertices[edited_point] = edited_point_pos - _get_offset(edited_polygon);
+ _set_polygon(edited_polygon, vertices);
+ }
+
+ canvas_item_editor->get_viewport_control()->update();
+ }
+ }
+
+ return false;
+}
+
+void AbstractPolygon2DEditor::_canvas_draw() {
+
+ if (!_get_node())
+ return;
+
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
+ Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
+ const int n_polygons = _get_polygon_count();
+
+ for (int j = -1; j < n_polygons; j++) {
+
+ if (wip_active && wip_destructive && j != -1)
+ continue;
+
+ PoolVector<Vector2> points;
+ Vector2 offset;
+
+ if (wip_active && j == edited_polygon) {
+
+ points = Variant(wip);
+ offset = Vector2(0, 0);
+ } else {
+
+ if (j == -1)
+ continue;
+ points = _get_polygon(j);
+ offset = _get_offset(j);
+ }
+
+ if (!wip_active && j == edited_polygon && edited_point >= 0 && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) {
+
+ const Color col = Color(0.5, 0.5, 0.5); // FIXME polygon->get_outline_color();
+ const int n = pre_move_edit.size();
+ for (int i = 0; i < n; i++) {
+
+ Vector2 p, p2;
+ p = pre_move_edit[i] + offset;
+ p2 = pre_move_edit[(i + 1) % n] + offset;
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ vpc->draw_line(point, next_point, col, 2);
+ }
+ }
+
+ const int n_points = points.size();
+ const Color col = Color(1, 0.3, 0.1, 0.8);
+
+ for (int i = 0; i < n_points; i++) {
+
+ Vector2 p, p2;
+ p = (j == edited_polygon && i == edited_point) ? edited_point_pos : (points[i] + offset);
+ if (j == edited_polygon && ((wip_active && i == n_points - 1) || (((i + 1) % n_points) == edited_point)))
+ p2 = edited_point_pos;
+ else
+ p2 = points[(i + 1) % n_points] + offset;
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ vpc->draw_line(point, next_point, col, 2);
+ vpc->draw_texture(handle, point - handle->get_size() * 0.5);
+ }
+ }
+}
+
+void AbstractPolygon2DEditor::edit(Node *p_polygon) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor = CanvasItemEditor::get_singleton();
+ }
+
+ if (p_polygon) {
+
+ _set_node(p_polygon);
+
+ //Enable the pencil tool if the polygon is empty
+ if (_is_empty())
+ _menu_option(MODE_CREATE);
+
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
+
+ wip.clear();
+ wip_active = false;
+ edited_point = -1;
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ } else {
+
+ _set_node(NULL);
+
+ if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
+ }
+}
+
+void AbstractPolygon2DEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_canvas_draw"), &AbstractPolygon2DEditor::_canvas_draw);
+ ClassDB::bind_method(D_METHOD("_node_removed"), &AbstractPolygon2DEditor::_node_removed);
+ ClassDB::bind_method(D_METHOD("_menu_option"), &AbstractPolygon2DEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_create_resource"), &AbstractPolygon2DEditor::_create_resource);
+}
+
+AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive) {
+
+ canvas_item_editor = NULL;
+ editor = p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ wip_active = false;
+ edited_polygon = -1;
+ wip_destructive = p_wip_destructive;
+
+ add_child(memnew(VSeparator));
+ button_create = memnew(ToolButton);
+ add_child(button_create);
+ button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+ button_create->set_tooltip(TTR("Create a new polygon from scratch."));
+
+ button_edit = memnew(ToolButton);
+ add_child(button_edit);
+ button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+ button_edit->set_tooltip(TTR("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."));
+
+ create_resource = memnew(ConfirmationDialog);
+ add_child(create_resource);
+ create_resource->get_ok()->set_text(TTR("Create"));
+
+ mode = MODE_EDIT;
+}
+
+void AbstractPolygon2DEditorPlugin::edit(Object *p_object) {
+
+ polygon_editor->edit(Object::cast_to<Node>(p_object));
+}
+
+bool AbstractPolygon2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class(klass);
+}
+
+void AbstractPolygon2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+ polygon_editor->show();
+ } else {
+
+ polygon_editor->hide();
+ polygon_editor->edit(NULL);
+ }
+}
+
+AbstractPolygon2DEditorPlugin::AbstractPolygon2DEditorPlugin(EditorNode *p_node, AbstractPolygon2DEditor *p_polygon_editor, String p_class) {
+
+ editor = p_node;
+ polygon_editor = p_polygon_editor;
+ klass = p_class;
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(polygon_editor);
+
+ polygon_editor->hide();
+}
+
+AbstractPolygon2DEditorPlugin::~AbstractPolygon2DEditorPlugin() {
+}
diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
new file mode 100644
index 0000000000..86e14694da
--- /dev/null
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -0,0 +1,131 @@
+/*************************************************************************/
+/* abstract_polygon_2d_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef ABSTRACT_POLYGON_2D_EDITOR_H
+#define ABSTRACT_POLYGON_2D_EDITOR_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "scene/2d/polygon_2d.h"
+#include "scene/gui/tool_button.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class CanvasItemEditor;
+
+class AbstractPolygon2DEditor : public HBoxContainer {
+
+ GDCLASS(AbstractPolygon2DEditor, HBoxContainer);
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+
+ int edited_polygon;
+ int edited_point;
+ Vector2 edited_point_pos;
+ Vector<Vector2> pre_move_edit;
+ Vector<Vector2> wip;
+ bool wip_active;
+ bool wip_destructive;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ ConfirmationDialog *create_resource;
+
+protected:
+ enum {
+
+ MODE_CREATE,
+ MODE_EDIT,
+ MODE_CONT,
+
+ };
+
+ int mode;
+
+ UndoRedo *undo_redo;
+
+ virtual void _menu_option(int p_option);
+ void _wip_close();
+ void _canvas_draw();
+
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+
+ bool _is_empty() const;
+ void _commit_action();
+
+protected:
+ virtual Node2D *_get_node() const = 0;
+ virtual void _set_node(Node *p_polygon) = 0;
+
+ virtual int _get_polygon_count() const;
+ virtual Vector2 _get_offset(int p_idx) const;
+ virtual Variant _get_polygon(int p_idx) const;
+ virtual void _set_polygon(int p_idx, const Variant &p_polygon) const;
+
+ virtual void _action_add_polygon(const Variant &p_polygon);
+ virtual void _action_remove_polygon(int p_idx);
+ virtual void _action_set_polygon(int p_idx, const Variant &p_polygon);
+ 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();
+
+public:
+ bool forward_gui_input(const Ref<InputEvent> &p_event);
+ void edit(Node *p_polygon);
+ AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wip_destructive = true);
+};
+
+class AbstractPolygon2DEditorPlugin : public EditorPlugin {
+
+ GDCLASS(AbstractPolygon2DEditorPlugin, EditorPlugin);
+
+ AbstractPolygon2DEditor *polygon_editor;
+ EditorNode *editor;
+ String klass;
+
+public:
+ virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return polygon_editor->forward_gui_input(p_event); }
+
+ bool has_main_screen() const { return false; }
+ virtual String get_name() const { return klass; }
+ virtual void edit(Object *p_object);
+ virtual bool handles(Object *p_object) const;
+ virtual void make_visible(bool p_visible);
+
+ AbstractPolygon2DEditorPlugin(EditorNode *p_node, AbstractPolygon2DEditor *p_polygon_editor, String p_class);
+ ~AbstractPolygon2DEditorPlugin();
+};
+
+#endif // ABSTRACT_POLYGON_2D_EDITOR_H
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
index 4501136e19..00e6d617a1 100644..100755
--- a/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -29,400 +29,20 @@
/*************************************************************************/
#include "collision_polygon_2d_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
-#include "editor/editor_settings.h"
-#include "os/file_access.h"
+Node2D *CollisionPolygon2DEditor::_get_node() const {
-void CollisionPolygon2DEditor::_notification(int p_what) {
-
- switch (p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon(get_icon("Edit", "EditorIcons"));
- button_edit->set_icon(get_icon("MovePoint", "EditorIcons"));
- button_edit->set_pressed(true);
- get_tree()->connect("node_removed", this, "_node_removed");
-
- } break;
- case NOTIFICATION_PHYSICS_PROCESS: {
-
- } break;
- }
-}
-void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
-
- if (p_node == node) {
- node = NULL;
- hide();
- canvas_item_editor->get_viewport_control()->update();
- }
-}
-
-void CollisionPolygon2DEditor::_menu_option(int p_option) {
-
- switch (p_option) {
-
- case MODE_CREATE: {
-
- mode = MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode = MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
- }
-}
-
-void CollisionPolygon2DEditor::_wip_close() {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node, "set_polygon", node->get_polygon());
- undo_redo->add_do_method(node, "set_polygon", wip);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- wip.clear();
- wip_active = false;
- mode = MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- edited_point = -1;
-}
-
-bool CollisionPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
-
- if (!node)
- return false;
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid()) {
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Vector2 gpoint = mb->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
- Vector<Vector2> poly = node->get_polygon();
-
- //first check if a point is to be added (segment split)
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
-
- switch (mode) {
-
- case MODE_CREATE: {
-
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back(cpoint);
- wip_active = true;
- edited_point_pos = cpoint;
- canvas_item_editor->get_viewport_control()->update();
- edited_point = 1;
- return true;
- } else {
-
- if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back(cpoint);
- edited_point = wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
- _wip_close();
- }
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb->get_button_index() == BUTTON_LEFT) {
- if (mb->is_pressed()) {
-
- if (mb->get_control()) {
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node, "set_polygon", poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 points[2] = { xform.xform(poly[i]),
- xform.xform(poly[(i + 1) % poly.size()]) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
- if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = poly;
- poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
- edited_point = closest_idx + 1;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- node->set_polygon(poly);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 cp = xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = poly;
- edited_point = closest_idx;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point != -1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
- poly[edited_point] = edited_point_pos;
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_undo_method(node, "set_polygon", pre_move_edit);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
-
- edited_point = -1;
- return true;
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
-
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 cp = xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node, "set_polygon", poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- return true;
- }
- }
-
- } break;
- }
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
-
- if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = mm->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- canvas_item_editor->get_viewport_control()->update();
- }
- }
-
- return false;
+ return node;
}
-void CollisionPolygon2DEditor::_canvas_draw() {
-
- if (!node)
- return;
-
- Control *vpc = canvas_item_editor->get_viewport_control();
-
- Vector<Vector2> poly;
-
- if (wip_active)
- poly = wip;
- else
- poly = node->get_polygon();
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
+void CollisionPolygon2DEditor::_set_node(Node *p_polygon) {
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 p, p2;
- p = i == edited_point ? edited_point_pos : poly[i];
- if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point))
- p2 = edited_point_pos;
- else
- p2 = poly[(i + 1) % poly.size()];
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col = Color(1, 0.3, 0.1, 0.8);
- vpc->draw_line(point, next_point, col, 2);
- vpc->draw_texture(handle, point - handle->get_size() * 0.5);
- }
+ node = Object::cast_to<CollisionPolygon2D>(p_polygon);
}
-void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor = CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
-
- node = Object::cast_to<CollisionPolygon2D>(p_collision_polygon);
- //Enable the pencil tool if the polygon is empty
- if (node->get_polygon().size() == 0) {
- _menu_option(MODE_CREATE);
- }
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
- wip.clear();
- wip_active = false;
- edited_point = -1;
- canvas_item_editor->get_viewport_control()->update();
-
- } else {
- node = NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
- }
-}
-
-void CollisionPolygon2DEditor::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("_menu_option"), &CollisionPolygon2DEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &CollisionPolygon2DEditor::_canvas_draw);
- ClassDB::bind_method(D_METHOD("_node_removed"), &CollisionPolygon2DEditor::_node_removed);
-}
-
-CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) {
-
- node = NULL;
- canvas_item_editor = NULL;
- editor = p_editor;
- undo_redo = editor->get_undo_redo();
-
- add_child(memnew(VSeparator));
- button_create = memnew(ToolButton);
- add_child(button_create);
- button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
- button_create->set_tooltip(TTR("Create a new polygon from scratch."));
-
- button_edit = memnew(ToolButton);
- add_child(button_edit);
- button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
- button_edit->set_tooltip(TTR("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."));
-
- mode = MODE_EDIT;
- wip_active = false;
-}
-
-void CollisionPolygon2DEditorPlugin::edit(Object *p_object) {
-
- collision_polygon_editor->edit(Object::cast_to<Node>(p_object));
-}
-
-bool CollisionPolygon2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("CollisionPolygon2D");
-}
-
-void CollisionPolygon2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-}
-
-CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) {
-
- editor = p_node;
- collision_polygon_editor = memnew(CollisionPolygon2DEditor(p_node));
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
+CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor)
+ : AbstractPolygon2DEditor(p_editor) {
}
-CollisionPolygon2DEditorPlugin::~CollisionPolygon2DEditorPlugin() {
+CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node)
+ : AbstractPolygon2DEditorPlugin(p_node, memnew(CollisionPolygon2DEditor(p_node)), "CollisionPolygon2D") {
}
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.h b/editor/plugins/collision_polygon_2d_editor_plugin.h
index 4715abd2e6..edf3bbcc08 100644..100755
--- a/editor/plugins/collision_polygon_2d_editor_plugin.h
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.h
@@ -30,78 +30,32 @@
#ifndef COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
#define COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
+#include "editor/plugins/abstract_polygon_2d_editor.h"
#include "scene/2d/collision_polygon_2d.h"
-#include "scene/gui/tool_button.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-class CanvasItemEditor;
+class CollisionPolygon2DEditor : public AbstractPolygon2DEditor {
-class CollisionPolygon2DEditor : public HBoxContainer {
+ GDCLASS(CollisionPolygon2DEditor, AbstractPolygon2DEditor);
- GDCLASS(CollisionPolygon2DEditor, HBoxContainer);
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
-
- };
-
- Mode mode;
-
- ToolButton *button_create;
- ToolButton *button_edit;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
CollisionPolygon2D *node;
- MenuButton *options;
-
- int edited_point;
- Vector2 edited_point_pos;
- Vector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
- void _wip_close();
- void _canvas_draw();
- void _menu_option(int p_option);
protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
+ virtual Node2D *_get_node() const;
+ virtual void _set_node(Node *p_polygon);
public:
- bool forward_gui_input(const Ref<InputEvent> &p_event);
- void edit(Node *p_collision_polygon);
CollisionPolygon2DEditor(EditorNode *p_editor);
};
-class CollisionPolygon2DEditorPlugin : public EditorPlugin {
-
- GDCLASS(CollisionPolygon2DEditorPlugin, EditorPlugin);
+class CollisionPolygon2DEditorPlugin : public AbstractPolygon2DEditorPlugin {
- CollisionPolygon2DEditor *collision_polygon_editor;
- EditorNode *editor;
+ GDCLASS(CollisionPolygon2DEditorPlugin, AbstractPolygon2DEditorPlugin);
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "CollisionPolygon2D"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
-
CollisionPolygon2DEditorPlugin(EditorNode *p_node);
- ~CollisionPolygon2DEditorPlugin();
};
#endif // COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp
index 69e553eefb..6560a8dac7 100644..100755
--- a/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ b/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -29,485 +29,101 @@
/*************************************************************************/
#include "navigation_polygon_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
-#include "editor/editor_settings.h"
-#include "os/file_access.h"
+Ref<NavigationPolygon> NavigationPolygonEditor::_ensure_navpoly() const {
-void NavigationPolygonEditor::_notification(int p_what) {
+ Ref<NavigationPolygon> navpoly = node->get_navigation_polygon();
+ if (!navpoly.is_valid()) {
- switch (p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon(get_icon("Edit", "EditorIcons"));
- button_edit->set_icon(get_icon("MovePoint", "EditorIcons"));
- button_edit->set_pressed(true);
- get_tree()->connect("node_removed", this, "_node_removed");
- create_nav->connect("confirmed", this, "_create_nav");
-
- } break;
- case NOTIFICATION_PHYSICS_PROCESS: {
-
- } break;
+ navpoly = Ref<NavigationPolygon>(memnew(NavigationPolygon));
+ node->set_navigation_polygon(navpoly);
}
+ return navpoly;
}
-void NavigationPolygonEditor::_node_removed(Node *p_node) {
- if (p_node == node) {
- node = NULL;
- hide();
- canvas_item_editor->get_viewport_control()->update();
- }
-}
+Node2D *NavigationPolygonEditor::_get_node() const {
-void NavigationPolygonEditor::_create_nav() {
-
- if (!node)
- return;
-
- undo_redo->create_action(TTR("Create Navigation Polygon"));
- undo_redo->add_do_method(node, "set_navigation_polygon", Ref<NavigationPolygon>(memnew(NavigationPolygon)));
- undo_redo->add_undo_method(node, "set_navigation_polygon", Variant(REF()));
- undo_redo->commit_action();
- _menu_option(MODE_CREATE);
+ return node;
}
-void NavigationPolygonEditor::_menu_option(int p_option) {
+void NavigationPolygonEditor::_set_node(Node *p_polygon) {
- switch (p_option) {
-
- case MODE_CREATE: {
-
- mode = MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode = MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
- }
+ node = Object::cast_to<NavigationPolygonInstance>(p_polygon);
}
-void NavigationPolygonEditor::_wip_close() {
+int NavigationPolygonEditor::_get_polygon_count() const {
- if (wip.size() >= 3) {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "remove_outline", node->get_navigation_polygon()->get_outline_count());
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "add_outline", wip);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- mode = MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- }
-
- wip.clear();
- wip_active = false;
- edited_point = -1;
+ Ref<NavigationPolygon> navpoly = node->get_navigation_polygon();
+ if (navpoly.is_valid())
+ return navpoly->get_outline_count();
+ else
+ return 0;
}
-bool NavigationPolygonEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
-
- if (!node)
- return false;
-
- if (node->get_navigation_polygon().is_null()) {
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
- create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?");
- create_nav->popup_centered_minsize();
- }
- return (mb.is_valid() && mb->get_button_index() == 1);
- }
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid()) {
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Vector2 gpoint = mb->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
- //first check if a point is to be added (segment split)
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
-
- switch (mode) {
-
- case MODE_CREATE: {
-
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back(cpoint);
- wip_active = true;
- edited_point_pos = cpoint;
- edited_outline = -1;
- canvas_item_editor->get_viewport_control()->update();
- edited_point = 1;
- return true;
- } else {
-
- if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back(cpoint);
- edited_point = wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
- _wip_close();
- }
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb->get_button_index() == BUTTON_LEFT) {
- if (mb->is_pressed()) {
-
- if (mb->get_control()) {
-
- //search edges
- int closest_outline = -1;
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
-
- for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
-
- PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
-
- int pc = points.size();
- PoolVector<Vector2>::Read poly = points.read();
-
- for (int i = 0; i < pc; i++) {
-
- Vector2 points[2] = { xform.xform(poly[i]),
- xform.xform(poly[(i + 1) % pc]) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
- if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_outline = j;
- closest_pos = cp;
- closest_idx = i;
- }
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline);
- PoolVector<Point2> poly = pre_move_edit;
- poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos));
- edited_point = closest_idx + 1;
- edited_outline = closest_outline;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- node->get_navigation_polygon()->set_outline(closest_outline, poly);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
- int closest_outline = -1;
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
-
- for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
-
- PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
-
- int pc = points.size();
- PoolVector<Vector2>::Read poly = points.read();
+Variant NavigationPolygonEditor::_get_polygon(int p_idx) const {
- for (int i = 0; i < pc; i++) {
-
- Vector2 cp = xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_outline = j;
- closest_idx = i;
- }
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = node->get_navigation_polygon()->get_outline(closest_outline);
- edited_point = closest_idx;
- edited_outline = closest_outline;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point != -1) {
-
- //apply
-
- PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(edited_outline);
- ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
- poly.set(edited_point, edited_point_pos);
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, poly);
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", edited_outline, pre_move_edit);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
-
- edited_point = -1;
- return true;
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
-
- int closest_outline = -1;
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
-
- for (int j = 0; j < node->get_navigation_polygon()->get_outline_count(); j++) {
-
- PoolVector<Vector2> points = node->get_navigation_polygon()->get_outline(j);
-
- int pc = points.size();
- PoolVector<Vector2>::Read poly = points.read();
-
- for (int i = 0; i < pc; i++) {
-
- Vector2 cp = xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_outline = j;
- closest_idx = i;
- }
- }
- }
-
- if (closest_idx >= 0) {
-
- PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(closest_outline);
-
- if (poly.size() > 3) {
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "set_outline", closest_outline, poly);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- } else {
-
- undo_redo->create_action(TTR("Remove Poly And Point"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "add_outline_at_index", poly, closest_outline);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "remove_outline", closest_outline);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(), "make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- }
- return true;
- }
- }
-
- } break;
- }
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
-
- if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = mm->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- canvas_item_editor->get_viewport_control()->update();
- }
- }
-
- return false;
+ Ref<NavigationPolygon> navpoly = node->get_navigation_polygon();
+ if (navpoly.is_valid())
+ return navpoly->get_outline(p_idx);
+ else
+ return Variant(Vector<Vector2>());
}
-void NavigationPolygonEditor::_canvas_draw() {
- if (!node)
- return;
+void NavigationPolygonEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
- Control *vpc = canvas_item_editor->get_viewport_control();
- if (node->get_navigation_polygon().is_null())
- return;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
-
- for (int j = -1; j < node->get_navigation_polygon()->get_outline_count(); j++) {
- Vector<Vector2> poly;
-
- if (wip_active && j == edited_outline) {
- poly = wip;
- } else {
- if (j == -1)
- continue;
- poly = Variant(node->get_navigation_polygon()->get_outline(j));
- }
-
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 p, p2;
- p = (j == edited_outline && i == edited_point) ? edited_point_pos : poly[i];
- if (j == edited_outline && ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point)))
- p2 = edited_point_pos;
- else
- p2 = poly[(i + 1) % poly.size()];
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col = Color(1, 0.3, 0.1, 0.8);
- vpc->draw_line(point, next_point, col, 2);
- vpc->draw_texture(handle, point - handle->get_size() * 0.5);
- }
- }
+ Ref<NavigationPolygon> navpoly = _ensure_navpoly();
+ navpoly->set_outline(p_idx, p_polygon);
+ navpoly->make_polygons_from_outlines();
}
-void NavigationPolygonEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor = CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
+void NavigationPolygonEditor::_action_add_polygon(const Variant &p_polygon) {
- node = Object::cast_to<NavigationPolygonInstance>(p_collision_polygon);
- //Enable the pencil tool if the polygon is empty
- if (!node->get_navigation_polygon().is_null()) {
- if (node->get_navigation_polygon()->get_polygon_count() == 0)
- _menu_option(MODE_CREATE);
- }
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
- wip.clear();
- wip_active = false;
- edited_point = -1;
- canvas_item_editor->get_viewport_control()->update();
-
- } else {
- node = NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
- }
+ Ref<NavigationPolygon> navpoly = _ensure_navpoly();
+ undo_redo->add_do_method(navpoly.ptr(), "add_outline", p_polygon);
+ undo_redo->add_undo_method(navpoly.ptr(), "remove_outline", navpoly->get_outline_count());
+ undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines");
+ undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines");
}
-void NavigationPolygonEditor::_bind_methods() {
+void NavigationPolygonEditor::_action_remove_polygon(int p_idx) {
- ClassDB::bind_method(D_METHOD("_menu_option"), &NavigationPolygonEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &NavigationPolygonEditor::_canvas_draw);
- ClassDB::bind_method(D_METHOD("_node_removed"), &NavigationPolygonEditor::_node_removed);
- ClassDB::bind_method(D_METHOD("_create_nav"), &NavigationPolygonEditor::_create_nav);
+ Ref<NavigationPolygon> navpoly = _ensure_navpoly();
+ undo_redo->add_do_method(navpoly.ptr(), "remove_outline", p_idx);
+ undo_redo->add_undo_method(navpoly.ptr(), "add_outline_at_index", navpoly->get_outline(p_idx), p_idx);
+ undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines");
+ undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines");
}
-NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) {
- node = NULL;
- canvas_item_editor = NULL;
- editor = p_editor;
- undo_redo = editor->get_undo_redo();
+void NavigationPolygonEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
- add_child(memnew(VSeparator));
- button_create = memnew(ToolButton);
- add_child(button_create);
- button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
- button_create->set_tooltip(TTR("Create a new polygon from scratch."));
-
- button_edit = memnew(ToolButton);
- add_child(button_edit);
- button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
- button_edit->set_tooltip(TTR("Edit existing polygon:") + "\n" + TTR("LMB: Move Point.") + "\n" + TTR("Ctrl+LMB: Split Segment.") + "\n" + TTR("RMB: Erase Point."));
- create_nav = memnew(ConfirmationDialog);
- add_child(create_nav);
- create_nav->get_ok()->set_text(TTR("Create"));
-
- mode = MODE_EDIT;
- wip_active = false;
- edited_outline = -1;
+ Ref<NavigationPolygon> navpoly = _ensure_navpoly();
+ undo_redo->add_do_method(navpoly.ptr(), "set_outline", p_idx, p_polygon);
+ undo_redo->add_undo_method(navpoly.ptr(), "set_outline", p_idx, p_previous);
+ undo_redo->add_do_method(navpoly.ptr(), "make_polygons_from_outlines");
+ undo_redo->add_undo_method(navpoly.ptr(), "make_polygons_from_outlines");
}
-void NavigationPolygonEditorPlugin::edit(Object *p_object) {
+bool NavigationPolygonEditor::_has_resource() const {
- collision_polygon_editor->edit(Object::cast_to<Node>(p_object));
+ return node && node->get_navigation_polygon().is_valid();
}
-bool NavigationPolygonEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("NavigationPolygonInstance");
-}
+void NavigationPolygonEditor::_create_resource() {
-void NavigationPolygonEditorPlugin::make_visible(bool p_visible) {
+ if (!node)
+ return;
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
+ undo_redo->create_action(TTR("Create Navigation Polygon"));
+ undo_redo->add_do_method(node, "set_navigation_polygon", Ref<NavigationPolygon>(memnew(NavigationPolygon)));
+ undo_redo->add_undo_method(node, "set_navigation_polygon", Variant(REF()));
+ undo_redo->commit_action();
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
+ _menu_option(MODE_CREATE);
}
-NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) {
-
- editor = p_node;
- collision_polygon_editor = memnew(NavigationPolygonEditor(p_node));
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
+NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor)
+ : AbstractPolygon2DEditor(p_editor) {
}
-NavigationPolygonEditorPlugin::~NavigationPolygonEditorPlugin() {
+NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node)
+ : AbstractPolygon2DEditorPlugin(p_node, memnew(NavigationPolygonEditor(p_node)), "NavigationPolygonInstance") {
}
diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h
index 7dd555e9c9..54cc347a8c 100644..100755
--- a/editor/plugins/navigation_polygon_editor_plugin.h
+++ b/editor/plugins/navigation_polygon_editor_plugin.h
@@ -30,83 +30,45 @@
#ifndef NAVIGATIONPOLYGONEDITORPLUGIN_H
#define NAVIGATIONPOLYGONEDITORPLUGIN_H
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
+#include "editor/plugins/abstract_polygon_2d_editor.h"
#include "scene/2d/navigation_polygon.h"
-#include "scene/gui/tool_button.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-class CanvasItemEditor;
+class NavigationPolygonEditor : public AbstractPolygon2DEditor {
-class NavigationPolygonEditor : public HBoxContainer {
+ GDCLASS(NavigationPolygonEditor, AbstractPolygon2DEditor);
- GDCLASS(NavigationPolygonEditor, HBoxContainer);
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
-
- };
-
- Mode mode;
-
- ToolButton *button_create;
- ToolButton *button_edit;
-
- ConfirmationDialog *create_nav;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
NavigationPolygonInstance *node;
- MenuButton *options;
- int edited_outline;
- int edited_point;
- Vector2 edited_point_pos;
- PoolVector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
+ Ref<NavigationPolygon> _ensure_navpoly() const;
- void _wip_close();
- void _canvas_draw();
- void _create_nav();
+protected:
+ virtual Node2D *_get_node() const;
+ virtual void _set_node(Node *p_polygon);
- void _menu_option(int p_option);
+ virtual int _get_polygon_count() const;
+ virtual Variant _get_polygon(int p_idx) const;
+ virtual void _set_polygon(int p_idx, const Variant &p_polygon) const;
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
+ virtual void _action_add_polygon(const Variant &p_polygon);
+ virtual void _action_remove_polygon(int p_idx);
+ 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();
public:
- bool forward_gui_input(const Ref<InputEvent> &p_event);
- void edit(Node *p_collision_polygon);
NavigationPolygonEditor(EditorNode *p_editor);
};
-class NavigationPolygonEditorPlugin : public EditorPlugin {
+class NavigationPolygonEditorPlugin : public AbstractPolygon2DEditorPlugin {
- GDCLASS(NavigationPolygonEditorPlugin, EditorPlugin);
-
- NavigationPolygonEditor *collision_polygon_editor;
- EditorNode *editor;
+ GDCLASS(NavigationPolygonEditorPlugin, AbstractPolygon2DEditorPlugin);
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "NavigationPolygonInstance"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
-
NavigationPolygonEditorPlugin(EditorNode *p_node);
- ~NavigationPolygonEditorPlugin();
};
#endif // NAVIGATIONPOLYGONEDITORPLUGIN_H
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index af2349983d..0e8c13b067 100644..100755
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -35,15 +35,27 @@
#include "os/input.h"
#include "os/keyboard.h"
+Node2D *Polygon2DEditor::_get_node() const {
+
+ return node;
+}
+
+void Polygon2DEditor::_set_node(Node *p_polygon) {
+
+ node = Object::cast_to<Polygon2D>(p_polygon);
+}
+
+Vector2 Polygon2DEditor::_get_offset(int p_idx) const {
+
+ return node->get_offset();
+}
+
void Polygon2DEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
- button_create->set_icon(get_icon("Edit", "EditorIcons"));
- button_edit->set_icon(get_icon("MovePoint", "EditorIcons"));
- button_edit->set_pressed(true);
button_uv->set_icon(get_icon("Uv", "EditorIcons"));
uv_button[UV_MODE_EDIT_POINT]->set_icon(get_icon("ToolSelect", "EditorIcons"));
@@ -55,40 +67,17 @@ void Polygon2DEditor::_notification(int p_what) {
b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons"));
uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons"));
- get_tree()->connect("node_removed", this, "_node_removed");
-
} break;
case NOTIFICATION_PHYSICS_PROCESS: {
} break;
}
}
-void Polygon2DEditor::_node_removed(Node *p_node) {
-
- if (p_node == node) {
- edit(NULL);
- hide();
-
- canvas_item_editor->get_viewport_control()->update();
- }
-}
void Polygon2DEditor::_menu_option(int p_option) {
switch (p_option) {
- case MODE_CREATE: {
-
- mode = MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode = MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
case MODE_EDIT_UV: {
if (node->get_texture().is_null()) {
@@ -153,6 +142,9 @@ void Polygon2DEditor::_menu_option(int p_option) {
undo_redo->commit_action();
} break;
+ default: {
+ AbstractPolygon2DEditor::_menu_option(p_option);
+ } break;
}
}
@@ -185,289 +177,6 @@ void Polygon2DEditor::_set_snap_step_y(float p_val) {
uv_edit_draw->update();
}
-void Polygon2DEditor::_wip_close() {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node, "set_polygon", node->get_polygon());
- undo_redo->add_do_method(node, "set_polygon", wip);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- wip.clear();
- wip_active = false;
- mode = MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- edited_point = -1;
-}
-
-bool Polygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
-
- if (node == NULL)
- return false;
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid()) {
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Vector2 gpoint = mb->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
- Vector<Vector2> poly = Variant(node->get_polygon());
-
- //first check if a point is to be added (segment split)
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
-
- switch (mode) {
-
- case MODE_CREATE: {
-
- if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back(cpoint - node->get_offset());
- wip_active = true;
- edited_point_pos = cpoint;
- canvas_item_editor->get_viewport_control()->update();
- edited_point = 1;
- return true;
- } else {
-
- if (wip.size() > 1 && xform.xform(wip[0] + node->get_offset()).distance_to(gpoint) < grab_threshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back(cpoint - node->get_offset());
- edited_point = wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) {
- _wip_close();
- }
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb->get_button_index() == BUTTON_LEFT) {
- if (mb->is_pressed()) {
-
- if (mb->get_control()) {
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node, "set_polygon", poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 points[2] = { xform.xform(poly[i] + node->get_offset()),
- xform.xform(poly[(i + 1) % poly.size()] + node->get_offset()) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points);
- if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = poly;
- poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos) - node->get_offset());
- edited_point = closest_idx + 1;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- node->set_polygon(Variant(poly));
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 cp = xform.xform(poly[i] + node->get_offset());
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- pre_move_edit = poly;
- edited_point = closest_idx;
- edited_point_pos = xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point != -1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
- poly[edited_point] = edited_point_pos - node->get_offset();
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_undo_method(node, "set_polygon", pre_move_edit);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
-
- edited_point = -1;
- return true;
- }
- }
- } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) {
-
- int closest_idx = -1;
- Vector2 closest_pos;
- real_t closest_dist = 1e10;
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 cp = xform.xform(poly[i] + node->get_offset());
-
- real_t d = cp.distance_to(gpoint);
- if (d < closest_dist && d < grab_threshold) {
- closest_dist = d;
- closest_pos = cp;
- closest_idx = i;
- }
- }
-
- if (closest_idx >= 0) {
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node, "set_polygon", poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node, "set_polygon", poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
- undo_redo->commit_action();
- return true;
- }
- }
-
- } break;
- }
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
-
- if (edited_point != -1 && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) {
-
- Vector2 gpoint = mm->get_position();
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint = canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- if (!wip_active) {
-
- Vector<Vector2> poly = Variant(node->get_polygon());
- ERR_FAIL_INDEX_V(edited_point, poly.size(), false);
- poly[edited_point] = edited_point_pos - node->get_offset();
- node->set_polygon(Variant(poly));
- }
-
- canvas_item_editor->get_viewport_control()->update();
- }
- }
-
- return false;
-}
-void Polygon2DEditor::_canvas_draw() {
-
- if (!node)
- return;
-
- Control *vpc = canvas_item_editor->get_viewport_control();
-
- Vector<Vector2> poly;
-
- if (wip_active)
- poly = wip;
- else
- poly = Variant(node->get_polygon());
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
-
- if (!wip_active && edited_point >= 0 && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) {
-
- const Color col = node->get_color().contrasted();
- const int n = pre_move_edit.size();
- for (int i = 0; i < n; i++) {
-
- Vector2 p, p2;
- p = pre_move_edit[i] + node->get_offset();
- p2 = pre_move_edit[(i + 1) % n] + node->get_offset();
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- vpc->draw_line(point, next_point, col, 2);
- }
- }
-
- for (int i = 0; i < poly.size(); i++) {
-
- Vector2 p, p2;
- p = i == edited_point ? edited_point_pos : (poly[i] + node->get_offset());
- if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point))
- p2 = edited_point_pos;
- else
- p2 = poly[(i + 1) % poly.size()] + node->get_offset();
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col = Color(1, 0.3, 0.1, 0.8);
- vpc->draw_line(point, next_point, col, 2);
- vpc->draw_texture(handle, point - handle->get_size() * 0.5);
- }
-}
-
void Polygon2DEditor::_uv_mode(int p_mode) {
uv_mode = UVMode(p_mode);
@@ -714,44 +423,12 @@ void Polygon2DEditor::_uv_draw() {
updating_uv_scroll = false;
}
-void Polygon2DEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor = CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
-
- node = Object::cast_to<Polygon2D>(p_collision_polygon);
- //Enable the pencil tool if the polygon is empty
- if (node->get_polygon().size() == 0) {
- _menu_option(MODE_CREATE);
- }
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
-
- wip.clear();
- wip_active = false;
- edited_point = -1;
-
- } else {
-
- node = NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
- }
-}
-
void Polygon2DEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_menu_option"), &Polygon2DEditor::_menu_option);
- ClassDB::bind_method(D_METHOD("_canvas_draw"), &Polygon2DEditor::_canvas_draw);
ClassDB::bind_method(D_METHOD("_uv_mode"), &Polygon2DEditor::_uv_mode);
ClassDB::bind_method(D_METHOD("_uv_draw"), &Polygon2DEditor::_uv_draw);
ClassDB::bind_method(D_METHOD("_uv_input"), &Polygon2DEditor::_uv_input);
ClassDB::bind_method(D_METHOD("_uv_scroll_changed"), &Polygon2DEditor::_uv_scroll_changed);
- ClassDB::bind_method(D_METHOD("_node_removed"), &Polygon2DEditor::_node_removed);
ClassDB::bind_method(D_METHOD("_set_use_snap"), &Polygon2DEditor::_set_use_snap);
ClassDB::bind_method(D_METHOD("_set_show_grid"), &Polygon2DEditor::_set_show_grid);
ClassDB::bind_method(D_METHOD("_set_snap_off_x"), &Polygon2DEditor::_set_snap_off_x);
@@ -773,35 +450,17 @@ Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
return p_target;
}
-Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) {
-
- node = NULL;
- canvas_item_editor = NULL;
- editor = p_editor;
- undo_redo = editor->get_undo_redo();
+Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor)
+ : AbstractPolygon2DEditor(p_editor) {
snap_step = Vector2(10, 10);
use_snap = false;
snap_show_grid = false;
- add_child(memnew(VSeparator));
- button_create = memnew(ToolButton);
- add_child(button_create);
- button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
-
- button_edit = memnew(ToolButton);
- add_child(button_edit);
- button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
-
button_uv = memnew(ToolButton);
add_child(button_uv);
button_uv->connect("pressed", this, "_menu_option", varray(MODE_EDIT_UV));
- mode = MODE_EDIT;
- wip_active = false;
-
uv_mode = UV_MODE_EDIT_POINT;
uv_edit = memnew(AcceptDialog);
add_child(uv_edit);
@@ -941,35 +600,6 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) {
uv_edit_draw->set_clip_contents(true);
}
-void Polygon2DEditorPlugin::edit(Object *p_object) {
-
- collision_polygon_editor->edit(Object::cast_to<Node>(p_object));
-}
-
-bool Polygon2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Polygon2D");
-}
-
-void Polygon2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-}
-
-Polygon2DEditorPlugin::Polygon2DEditorPlugin(EditorNode *p_node) {
-
- editor = p_node;
- collision_polygon_editor = memnew(Polygon2DEditor(p_node));
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
-}
-
-Polygon2DEditorPlugin::~Polygon2DEditorPlugin() {
+Polygon2DEditorPlugin::Polygon2DEditorPlugin(EditorNode *p_node)
+ : AbstractPolygon2DEditorPlugin(p_node, memnew(Polygon2DEditor(p_node)), "Polygon2D") {
}
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
index f9d6a6b4b6..90da3e61c1 100644..100755
--- a/editor/plugins/polygon_2d_editor_plugin.h
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -30,26 +30,18 @@
#ifndef POLYGON_2D_EDITOR_PLUGIN_H
#define POLYGON_2D_EDITOR_PLUGIN_H
-#include "editor/editor_node.h"
-#include "editor/editor_plugin.h"
-#include "scene/2d/polygon_2d.h"
-#include "scene/gui/tool_button.h"
+#include "editor/plugins/abstract_polygon_2d_editor.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-class CanvasItemEditor;
+class Polygon2DEditor : public AbstractPolygon2DEditor {
-class Polygon2DEditor : public HBoxContainer {
+ GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor);
- GDCLASS(Polygon2DEditor, HBoxContainer);
-
- UndoRedo *undo_redo;
enum Mode {
- MODE_CREATE,
- MODE_EDIT,
- MODE_EDIT_UV,
+ MODE_EDIT_UV = MODE_CONT,
UVEDIT_POLYGON_TO_UV,
UVEDIT_UV_TO_POLYGON,
UVEDIT_UV_CLEAR
@@ -64,7 +56,7 @@ class Polygon2DEditor : public HBoxContainer {
UV_MODE_MAX
};
- Mode mode;
+ Polygon2D *node;
UVMode uv_mode;
AcceptDialog *uv_edit;
@@ -90,34 +82,19 @@ class Polygon2DEditor : public HBoxContainer {
AcceptDialog *error;
- ToolButton *button_create;
- ToolButton *button_edit;
ToolButton *button_uv;
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
- Polygon2D *node;
- MenuButton *options;
-
- int edited_point;
- Vector2 edited_point_pos;
- Vector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
bool use_snap;
bool snap_show_grid;
Vector2 snap_offset;
Vector2 snap_step;
+ virtual void _menu_option(int p_option);
+
void _uv_scroll_changed(float);
void _uv_input(const Ref<InputEvent> &p_input);
void _uv_draw();
void _uv_mode(int p_mode);
- void _wip_close();
- void _canvas_draw();
- void _menu_option(int p_option);
void _set_use_snap(bool p_use);
void _set_show_grid(bool p_show);
@@ -127,36 +104,26 @@ class Polygon2DEditor : public HBoxContainer {
void _set_snap_step_y(float p_val);
protected:
+ virtual Node2D *_get_node() const;
+ virtual void _set_node(Node *p_polygon);
+
+ virtual Vector2 _get_offset(int p_idx) const;
+
void _notification(int p_what);
- void _node_removed(Node *p_node);
static void _bind_methods();
Vector2 snap_point(Vector2 p_target) const;
public:
- bool forward_gui_input(const Ref<InputEvent> &p_event);
- void edit(Node *p_collision_polygon);
Polygon2DEditor(EditorNode *p_editor);
};
-class Polygon2DEditorPlugin : public EditorPlugin {
-
- GDCLASS(Polygon2DEditorPlugin, EditorPlugin);
+class Polygon2DEditorPlugin : public AbstractPolygon2DEditorPlugin {
- Polygon2DEditor *collision_polygon_editor;
- EditorNode *editor;
+ GDCLASS(Polygon2DEditorPlugin, AbstractPolygon2DEditorPlugin);
public:
- virtual bool forward_canvas_gui_input(const Transform2D &p_canvas_xform, const Ref<InputEvent> &p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "Polygon2D"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
-
Polygon2DEditorPlugin(EditorNode *p_node);
- ~Polygon2DEditorPlugin();
};
#endif // POLYGON_2D_EDITOR_PLUGIN_H
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 2c88832998..98b57adc50 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -285,7 +285,8 @@ bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
MonoAssembly *assembly = mono_assembly_load_full(aname, NULL, &status, false);
mono_assembly_name_free(aname);
- ERR_FAIL_NULL_V(assembly, false);
+ if (!assembly)
+ return false;
uint32_t domain_id = mono_domain_get_id(mono_domain_get());
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index b64915109f..9a6c8f0cd6 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -705,9 +705,9 @@ MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 4, i);
const Color &elem = p_array[i];
raw[0] = elem.r;
- raw[4] = elem.g;
- raw[8] = elem.b;
- raw[12] = elem.a;
+ raw[1] = elem.g;
+ raw[2] = elem.b;
+ raw[3] = elem.a;
#endif
}
@@ -719,7 +719,7 @@ PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 4, i);
MARSHALLED_IN(Color, raw_elem, elem);
ret.push_back(elem);
}
@@ -737,7 +737,7 @@ MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 2, i);
const Vector2 &elem = p_array[i];
raw[0] = elem.x;
- raw[4] = elem.y;
+ raw[1] = elem.y;
#endif
}
@@ -749,7 +749,7 @@ PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 2, i);
MARSHALLED_IN(Vector2, raw_elem, elem);
ret.push_back(elem);
}
@@ -767,8 +767,8 @@ MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 3, i);
const Vector3 &elem = p_array[i];
raw[0] = elem.x;
- raw[4] = elem.y;
- raw[8] = elem.z;
+ raw[1] = elem.y;
+ raw[2] = elem.z;
#endif
}
@@ -780,7 +780,7 @@ PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 3, i);
MARSHALLED_IN(Vector3, raw_elem, elem);
ret.push_back(elem);
}
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index 04669a3b0c..ac424ab9f8 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -88,79 +88,48 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
//Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
- for (int i=0;i<count;i++){
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
+ mView.queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < count; ++i) {
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
}
- });
- }
+ }
+ });
}
@Override
public void onTextChanged(final CharSequence pCharSequence, final int start, final int before, final int count) {
//Log.d(TAG, "onTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",before: " + before);
- for (int i=start;i<start+count;i++){
- final int ch = pCharSequence.charAt(i);
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
+ mView.queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = start; i < start + count; ++i) {
+ final int ch = pCharSequence.charAt(i);
GodotLib.key(0, ch, true);
GodotLib.key(0, ch, false);
}
- });
- }
-
+ }
+ });
}
@Override
public boolean onEditorAction(final TextView pTextView, final int pActionID, final KeyEvent pKeyEvent) {
if (this.mEdit == pTextView && this.isFullScreenEdit()) {
- // user press the action button, delete all old text and insert new text
- for (int i = this.mOriginText.length(); i > 0; i--) {
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
- GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
- }
- });
+ final String characters = pKeyEvent.getCharacters();
- /*
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "deleteBackward");
- }
- */
- }
- String text = pTextView.getText().toString();
-
- /* If user input nothing, translate "\n" to engine. */
- if (text.compareTo("") == 0) {
- text = "\n";
- }
-
- if ('\n' != text.charAt(text.length() - 1)) {
- text += '\n';
- }
-
- for(int i = 0; i < text.length(); i++) {
- final int ch = text.codePointAt(i);
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
+ mView.queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < characters.length(); i++) {
+ final int ch = characters.codePointAt(i);
GodotLib.key(0, ch, true);
GodotLib.key(0, ch, false);
}
- });
- }
- /*
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "insertText(" + insertText + ")");
- }
- */
+ }
+ });
}
if (pActionID == EditorInfo.IME_ACTION_DONE) {
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 6819a7e20f..0b193f5882 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -602,21 +602,10 @@ struct TST {
TST tst;
-struct JAndroidPointerEvent {
-
- Vector<OS_Android::TouchPos> points;
- int pointer;
- int what;
-};
-
-static List<JAndroidPointerEvent> pointer_events;
-static List<Ref<InputEvent> > key_events;
-static List<OS_Android::JoypadEvent> joy_events;
static bool initialized = false;
static int step = 0;
static bool resized = false;
static bool resized_reload = false;
-static bool go_back_request = false;
static Size2 new_size;
static Vector3 accelerometer;
static Vector3 magnetometer;
@@ -624,8 +613,6 @@ static Vector3 gyroscope;
static HashMap<String, JNISingleton *> jni_singletons;
static jobject godot_io;
-static Vector<int> joy_device_ids;
-
typedef void (*GFXInitFunc)(void *ud, bool gl2);
static jmethodID _on_video_init = 0;
@@ -998,7 +985,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *en
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj) {
- go_back_request = true;
+ os_android->main_loop_request_go_back();
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jobject obj) {
@@ -1023,36 +1010,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job
//__android_log_print(ANDROID_LOG_INFO,"godot","**STEP EVENT! - %p-%i\n",env,Thread::get_caller_id());
- while (pointer_events.size()) {
-
- JAndroidPointerEvent jpe = pointer_events.front()->get();
- os_android->process_touch(jpe.what, jpe.pointer, jpe.points);
-
- pointer_events.pop_front();
- }
-
- while (key_events.size()) {
-
- Ref<InputEvent> event = key_events.front()->get();
- os_android->process_event(event);
-
- key_events.pop_front();
- };
-
- while (joy_events.size()) {
-
- OS_Android::JoypadEvent event = joy_events.front()->get();
- os_android->process_joy_event(event);
-
- joy_events.pop_front();
- }
-
- if (go_back_request) {
-
- os_android->main_loop_request_go_back();
- go_back_request = false;
- }
-
os_android->process_accelerometer(accelerometer);
os_android->process_magnetometer(magnetometer);
@@ -1083,12 +1040,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jo
points.push_back(tp);
}
- JAndroidPointerEvent jpe;
- jpe.pointer = pointer;
- jpe.points = points;
- jpe.what = ev;
+ os_android->process_touch(ev, pointer, points);
- pointer_events.push_back(jpe);
/*
if (os_android)
os_android->process_touch(ev,pointer,points);
@@ -1358,7 +1311,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env
jevent.index = p_button;
jevent.pressed = p_pressed;
- joy_events.push_back(jevent);
+ os_android->process_joy_event(jevent);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value) {
@@ -1369,7 +1322,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env,
jevent.index = p_axis;
jevent.value = p_value;
- joy_events.push_back(jevent);
+ os_android->process_joy_event(jevent);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y) {
@@ -1390,7 +1343,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j
hat |= InputDefault::HAT_MASK_DOWN;
}
jevent.hat = hat;
- joy_events.push_back(jevent);
+
+ os_android->process_joy_event(jevent);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) {
@@ -1403,6 +1357,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
Ref<InputEventKey> ievent;
+ ievent.instance();
int val = p_unicode_char;
int scancode = android_get_keysym(p_scancode);
ievent->set_scancode(scancode);
@@ -1421,10 +1376,10 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobj
ievent->set_unicode(KEY_ENTER);
} else if (p_scancode == 4) {
- go_back_request = true;
+ os_android->main_loop_request_go_back();
}
- key_events.push_back(ievent);
+ os_android->process_event(ievent);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) {