summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/os/memory.cpp40
-rw-r--r--core/os/memory.h12
-rw-r--r--core/safe_refcount.cpp56
-rw-r--r--core/safe_refcount.h2
-rw-r--r--doc/base/classes.xml122
-rw-r--r--editor/editor_themes.cpp11
-rw-r--r--editor/icons/2x/icon_GUI_dropdown.pngbin183 -> 198 bytes
-rw-r--r--editor/icons/icon_GUI_dropdown.pngbin130 -> 136 bytes
-rw-r--r--editor/icons/source/icon_GUI_dropdown.svg22
-rw-r--r--editor/icons/source/icon_connect.svg46
-rw-r--r--editor/import/resource_importer_texture.cpp2
-rw-r--r--editor/import/resource_importer_wav.cpp4
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp48
-rw-r--r--editor/plugins/texture_editor_plugin.cpp16
-rw-r--r--editor/plugins/texture_editor_plugin.h1
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp38
-rw-r--r--editor/project_settings_editor.cpp18
-rw-r--r--editor/script_create_dialog.cpp31
-rw-r--r--main/performance.cpp4
-rw-r--r--platform/android/SCsub2
-rw-r--r--platform/android/detect.py28
-rw-r--r--platform/android/export/export.cpp15
-rw-r--r--platform/android/java_class_wrapper.cpp12
-rw-r--r--platform/windows/os_windows.cpp7
-rw-r--r--scene/2d/sprite.cpp1
-rw-r--r--scene/gui/patch_9_rect.cpp1
-rw-r--r--scene/resources/style_box.cpp1
-rw-r--r--scene/resources/surface_tool.cpp19
-rw-r--r--scene/resources/texture.cpp10
-rw-r--r--servers/physics/area_sw.h1
-rw-r--r--servers/physics/body_sw.cpp3
-rw-r--r--servers/physics/body_sw.h1
-rw-r--r--servers/physics/physics_server_sw.cpp30
-rw-r--r--servers/physics/space_sw.cpp6
-rw-r--r--servers/physics_2d/area_2d_sw.h1
-rw-r--r--servers/physics_2d/body_2d_sw.h1
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.cpp6
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp31
38 files changed, 467 insertions, 182 deletions
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index 069ee48fae..acc960acd9 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "memory.h"
#include "copymem.h"
+#include "core/safe_refcount.h"
#include "error_macros.h"
#include <stdio.h>
#include <stdlib.h>
@@ -43,14 +44,12 @@ void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
return p_allocfunc(p_size);
}
-#include <stdio.h>
-
#ifdef DEBUG_ENABLED
-size_t Memory::mem_usage = 0;
-size_t Memory::max_usage = 0;
+uint64_t Memory::mem_usage = 0;
+uint64_t Memory::max_usage = 0;
#endif
-size_t Memory::alloc_count = 0;
+uint64_t Memory::alloc_count = 0;
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
@@ -62,10 +61,10 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
void *mem = malloc(p_bytes + (prepad ? PAD_ALIGN : 0));
- alloc_count++;
-
ERR_FAIL_COND_V(!mem, NULL);
+ atomic_increment(&alloc_count);
+
if (prepad) {
uint64_t *s = (uint64_t *)mem;
*s = p_bytes;
@@ -73,10 +72,8 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
uint8_t *s8 = (uint8_t *)mem;
#ifdef DEBUG_ENABLED
- mem_usage += p_bytes;
- if (mem_usage > max_usage) {
- max_usage = mem_usage;
- }
+ atomic_add(&mem_usage, p_bytes);
+ atomic_exchange_if_greater(&max_usage, mem_usage);
#endif
return s8 + PAD_ALIGN;
} else {
@@ -103,8 +100,12 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
uint64_t *s = (uint64_t *)mem;
#ifdef DEBUG_ENABLED
- mem_usage -= *s;
- mem_usage += p_bytes;
+ if (p_bytes > *s) {
+ atomic_add(&mem_usage, p_bytes - *s);
+ atomic_exchange_if_greater(&max_usage, mem_usage);
+ } else {
+ atomic_sub(&mem_usage, *s - p_bytes);
+ }
#endif
if (p_bytes == 0) {
@@ -144,14 +145,14 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) {
bool prepad = p_pad_align;
#endif
- alloc_count--;
+ atomic_decrement(&alloc_count);
if (prepad) {
mem -= PAD_ALIGN;
uint64_t *s = (uint64_t *)mem;
#ifdef DEBUG_ENABLED
- mem_usage -= *s;
+ atomic_sub(&mem_usage, *s);
#endif
free(mem);
@@ -161,19 +162,20 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) {
}
}
-size_t Memory::get_mem_available() {
+uint64_t Memory::get_mem_available() {
- return 0xFFFFFFFFFFFFF;
+ return -1; // 0xFFFF...
}
-size_t Memory::get_mem_usage() {
+uint64_t Memory::get_mem_usage() {
#ifdef DEBUG_ENABLED
return mem_usage;
#else
return 0;
#endif
}
-size_t Memory::get_mem_max_usage() {
+
+uint64_t Memory::get_mem_max_usage() {
#ifdef DEBUG_ENABLED
return max_usage;
#else
diff --git a/core/os/memory.h b/core/os/memory.h
index b3eb599955..e1d7138ad5 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -45,20 +45,20 @@ class Memory {
Memory();
#ifdef DEBUG_ENABLED
- static size_t mem_usage;
- static size_t max_usage;
+ static uint64_t mem_usage;
+ static uint64_t max_usage;
#endif
- static size_t alloc_count;
+ static uint64_t alloc_count;
public:
static void *alloc_static(size_t p_bytes, bool p_pad_align = false);
static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false);
static void free_static(void *p_ptr, bool p_pad_align = false);
- static size_t get_mem_available();
- static size_t get_mem_usage();
- static size_t get_mem_max_usage();
+ static uint64_t get_mem_available();
+ static uint64_t get_mem_usage();
+ static uint64_t get_mem_max_usage();
};
class DefaultAllocator {
diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp
index d7e5297321..971e9ad1d5 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -78,6 +78,15 @@ static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) {
return *pw;
}
+template <class T>
+static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, register T val) {
+
+ if (val > *pw)
+ *pw = val;
+
+ return *pw;
+}
+
#elif defined(__GNUC__)
/* Implementation for GCC & Clang */
@@ -121,6 +130,18 @@ static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) {
return __sync_add_and_fetch(pw, val);
}
+template <class T>
+static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, register T val) {
+
+ while (true) {
+ T tmp = static_cast<T const volatile &>(*pw);
+ if (tmp >= val)
+ return tmp; // already greater, or equal
+ if (__sync_val_compare_and_swap(pw, tmp, val) == tmp)
+ return val;
+ }
+}
+
#elif defined(_MSC_VER)
/* Implementation for MSVC-Windows */
@@ -139,6 +160,15 @@ static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) {
return tmp + 1; \
}
+#define ATOMIC_EXCHANGE_IF_GREATER_BODY(m_pw, m_val, m_win_type, m_win_cmpxchg, m_cpp_type) \
+ while (true) { \
+ m_cpp_type tmp = static_cast<m_cpp_type const volatile &>(*(m_pw)); \
+ if (tmp >= m_val) \
+ return tmp; /* already greater, or equal */ \
+ if (m_win_cmpxchg((m_win_type volatile *)(m_pw), m_val, tmp) == tmp) \
+ return m_val; \
+ }
+
static _ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(register uint32_t *pw) {
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t)
@@ -156,11 +186,7 @@ static _ALWAYS_INLINE_ uint32_t _atomic_increment_impl(register uint32_t *pw) {
static _ALWAYS_INLINE_ uint32_t _atomic_sub_impl(register uint32_t *pw, register uint32_t val) {
-#if _WIN32_WINNT >= 0x0601 // Windows 7+
- return InterlockedExchangeSubtract(pw, val) - val;
-#else
return InterlockedExchangeAdd((LONG volatile *)pw, -(int32_t)val) - val;
-#endif
}
static _ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register uint32_t val) {
@@ -168,6 +194,11 @@ static _ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register
return InterlockedAdd((LONG volatile *)pw, val);
}
+static _ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(register uint32_t *pw, register uint32_t val) {
+
+ ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t)
+}
+
static _ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(register uint64_t *pw) {
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t)
@@ -185,11 +216,7 @@ static _ALWAYS_INLINE_ uint64_t _atomic_increment_impl(register uint64_t *pw) {
static _ALWAYS_INLINE_ uint64_t _atomic_sub_impl(register uint64_t *pw, register uint64_t val) {
-#if _WIN32_WINNT >= 0x0601 && !defined(UWP_ENABLED) // Windows 7+ except UWP
- return InterlockedExchangeSubtract64(pw, val) - val;
-#else
return InterlockedExchangeAdd64((LONGLONG volatile *)pw, -(int64_t)val) - val;
-#endif
}
static _ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register uint64_t val) {
@@ -197,6 +224,11 @@ static _ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register
return InterlockedAdd64((LONGLONG volatile *)pw, val);
}
+static _ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(register uint64_t *pw, register uint64_t val) {
+
+ ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t)
+}
+
#else
//no threads supported?
@@ -226,6 +258,10 @@ uint32_t atomic_add(register uint32_t *pw, register uint32_t val) {
return _atomic_add_impl(pw, val);
}
+uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val) {
+ return _atomic_exchange_if_greater_impl(pw, val);
+}
+
uint64_t atomic_conditional_increment(register uint64_t *counter) {
return _atomic_conditional_increment_impl(counter);
}
@@ -245,3 +281,7 @@ uint64_t atomic_sub(register uint64_t *pw, register uint64_t val) {
uint64_t atomic_add(register uint64_t *pw, register uint64_t val) {
return _atomic_add_impl(pw, val);
}
+
+uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val) {
+ return _atomic_exchange_if_greater_impl(pw, val);
+}
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index a2d2b5e127..ed0620c777 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -41,12 +41,14 @@ uint32_t atomic_decrement(register uint32_t *pw);
uint32_t atomic_increment(register uint32_t *pw);
uint32_t atomic_sub(register uint32_t *pw, register uint32_t val);
uint32_t atomic_add(register uint32_t *pw, register uint32_t val);
+uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val);
uint64_t atomic_conditional_increment(register uint64_t *counter);
uint64_t atomic_decrement(register uint64_t *pw);
uint64_t atomic_increment(register uint64_t *pw);
uint64_t atomic_sub(register uint64_t *pw, register uint64_t val);
uint64_t atomic_add(register uint64_t *pw, register uint64_t val);
+uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val);
struct SafeRefCount {
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 058753132e..70a7dcb651 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -10169,12 +10169,73 @@
<description>
</description>
</method>
+ <method name="create_shape_owner">
+ <return type="int">
+ </return>
+ <argument index="0" name="owner" type="Object">
+ </argument>
+ <description>
+ Creates new holder for the shapes. Argument is a [CollisionShape] node. It will return owner_id which usually you will want to save for later use.
+ </description>
+ </method>
<method name="get_rid" qualifiers="const">
<return type="RID">
</return>
<description>
</description>
</method>
+ <method name="get_shape_owners">
+ <return type="Array">
+ </return>
+ <description>
+ Shape owner is a node which is holding concrete shape resources. This method will return an array which is holding an integer numbers that are representing unique ID of each owner. You can use those ids when you are using others shape_owner methods.
+ </description>
+ </method>
+ <method name="shape_owner_clear_shapes">
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <description>
+ Will remove all the shapes associated with given owner.
+ </description>
+ </method>
+ <method name="shape_owner_get_shape">
+ <return type="Shape">
+ </return>
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <argument index="1" name="shape_id" type="int">
+ </argument>
+ <description>
+ Will return a [Shape]. First argument owner_id is an integer that can be obtained from [method get_shape_owners]. Shape_id is a position of the shape inside owner; it's a value in range from 0 to [method shape_owner_get_shape_count].
+ </description>
+ </method>
+ <method name="shape_owner_get_shape_count">
+ <return type="int">
+ </return>
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <description>
+ Returns number of shapes to which given owner is associated to.
+ </description>
+ </method>
+ <method name="shape_owner_get_transform">
+ <return type="Transform">
+ </return>
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <description>
+ Will return [Transform] of an owner node.
+ </description>
+ </method>
+ <method name="shape_owner_remove_shape">
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <argument index="1" name="shape_id" type="int">
+ </argument>
+ <description>
+ Removes related shape from the owner.
+ </description>
+ </method>
<method name="is_ray_pickable" qualifiers="const">
<return type="bool">
</return>
@@ -10245,6 +10306,15 @@
<description>
</description>
</method>
+ <method name="create_shape_owner">
+ <return type="int">
+ </return>
+ <argument index="0" name="owner" type="Object">
+ </argument>
+ <description>
+ Creates new holder for the shapes. Argument is a [CollisionShape2D] node. It will return owner_id which usually you will want to save for later use.
+ </description>
+ </method>
<method name="get_rid" qualifiers="const">
<return type="RID">
</return>
@@ -10252,6 +10322,58 @@
Return the RID of this object.
</description>
</method>
+ <method name="get_shape_owners">
+ <return type="Array">
+ </return>
+ <description>
+ Shape owner is a node which is holding concrete shape resources. This method will return an array which is holding an integer numbers that are representing unique ID of each owner. You can use those ids when you are using others shape_owner methods.
+ </description>
+ </method>
+ <method name="shape_owner_clear_shapes">
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <description>
+ Will remove all the shapes associated with given owner.
+ </description>
+ </method>
+ <method name="shape_owner_get_shape">
+ <return type="Shape2D">
+ </return>
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <argument index="1" name="shape_id" type="int">
+ </argument>
+ <description>
+ Will return a [Shape2D]. First argument owner_id is an integer that can be obtained from [method get_shape_owners]. Shape_id is a position of the shape inside owner; it's a value in range from 0 to [method shape_owner_get_shape_count].
+ </description>
+ </method>
+ <method name="shape_owner_get_shape_count">
+ <return type="int">
+ </return>
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <description>
+ Returns number of shapes to which given owner is associated to.
+ </description>
+ </method>
+ <method name="shape_owner_get_transform">
+ <return type="Transform2D">
+ </return>
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <description>
+ Will return [Transform2D] of an owner node.
+ </description>
+ </method>
+ <method name="shape_owner_remove_shape">
+ <argument index="0" name="owner_id" type="int">
+ </argument>
+ <argument index="1" name="shape_id" type="int">
+ </argument>
+ <description>
+ Removes related shape from the owner.
+ </description>
+ </method>
<method name="is_pickable" qualifiers="const">
<return type="bool">
</return>
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 6b985c7b4b..df16de947e 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -163,6 +163,13 @@ Ref<Theme> create_editor_theme() {
theme->set_color("light_color_1", "Editor", light_color_1);
theme->set_color("light_color_2", "Editor", light_color_2);
+ Color success_color = highlight_color.linear_interpolate(Color(0, 1, .8), 0.8);
+ Color warning_color = highlight_color.linear_interpolate(Color(1, 1, .2), 0.8);
+ Color error_color = highlight_color.linear_interpolate(Color(1, .2, .2), 0.8);
+ theme->set_color("success_color", "Editor", success_color);
+ theme->set_color("warning_color", "Editor", warning_color);
+ theme->set_color("error_color", "Editor", error_color);
+
// Checkbox icon
theme->set_icon("checked", "CheckBox", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("unchecked", "CheckBox", theme->get_icon("GuiUnchecked", "EditorIcons"));
@@ -307,8 +314,8 @@ Ref<Theme> create_editor_theme() {
theme->set_icon("arrow_collapsed", "Tree", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
theme->set_icon("select_arrow", "Tree", theme->get_icon("GuiDropdown", "EditorIcons"));
theme->set_stylebox("bg_focus", "Tree", focus_sbt);
- theme->set_stylebox("custom_button", "Tree", style_button_type);
- theme->set_stylebox("custom_button_pressed", "Tree", style_button_type);
+ theme->set_stylebox("custom_button", "Tree", make_empty_stylebox());
+ theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox());
theme->set_stylebox("custom_button_hover", "Tree", style_button_type);
theme->set_color("custom_button_font_highlight", "Tree", HIGHLIGHT_COLOR_LIGHT);
diff --git a/editor/icons/2x/icon_GUI_dropdown.png b/editor/icons/2x/icon_GUI_dropdown.png
index c959378430..78d3352e4e 100644
--- a/editor/icons/2x/icon_GUI_dropdown.png
+++ b/editor/icons/2x/icon_GUI_dropdown.png
Binary files differ
diff --git a/editor/icons/icon_GUI_dropdown.png b/editor/icons/icon_GUI_dropdown.png
index 4bd6544830..d21cdb634e 100644
--- a/editor/icons/icon_GUI_dropdown.png
+++ b/editor/icons/icon_GUI_dropdown.png
Binary files differ
diff --git a/editor/icons/source/icon_GUI_dropdown.svg b/editor/icons/source/icon_GUI_dropdown.svg
index f313b09983..897f63c268 100644
--- a/editor/icons/source/icon_GUI_dropdown.svg
+++ b/editor/icons/source/icon_GUI_dropdown.svg
@@ -9,9 +9,9 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="8"
+ width="14"
height="14"
- viewBox="0 0 8 14"
+ viewBox="0 0 14 14"
id="svg2"
version="1.1"
inkscape:version="0.92+devel unknown"
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="45.254834"
- inkscape:cx="1.2944669"
- inkscape:cy="5.9830116"
+ inkscape:zoom="32"
+ inkscape:cx="6.5843041"
+ inkscape:cy="6.8000184"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -72,21 +72,21 @@
id="layer1"
transform="translate(0,-1038.3622)">
<circle
- style="fill:#ffffff;fill-opacity:0.58823532;stroke-width:2;stroke-linejoin:round;stroke-opacity:0.39215686"
+ style="fill:#ffffff;fill-opacity:0.58823529;stroke-width:2;stroke-linejoin:round;stroke-opacity:0.39215686"
id="path4268"
- cx="4.5"
+ cx="7.5"
cy="1040.8622"
r="1.5" />
<circle
r="1.5"
cy="1045.8622"
- cx="4.5"
+ cx="7.5"
id="circle4271"
- style="fill:#ffffff;fill-opacity:0.58823532;stroke-width:2;stroke-linejoin:round;stroke-opacity:0.39215686" />
+ style="fill:#ffffff;fill-opacity:0.58823529;stroke-width:2;stroke-linejoin:round;stroke-opacity:0.39215686" />
<circle
- style="fill:#ffffff;fill-opacity:0.58823532;stroke-width:2;stroke-linejoin:round;stroke-opacity:0.39215686"
+ style="fill:#ffffff;fill-opacity:0.58823529;stroke-width:2;stroke-linejoin:round;stroke-opacity:0.39215686"
id="circle4273"
- cx="4.5"
+ cx="7.5"
cy="1050.8622"
r="1.5" />
</g>
diff --git a/editor/icons/source/icon_connect.svg b/editor/icons/source/icon_connect.svg
index 745d3cc436..15c8b481a1 100644
--- a/editor/icons/source/icon_connect.svg
+++ b/editor/icons/source/icon_connect.svg
@@ -14,7 +14,7 @@
viewBox="0 0 16 16"
id="svg2"
version="1.1"
- inkscape:version="0.91 r13725"
+ inkscape:version="0.92+devel unknown"
inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_add_track.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45"
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="22.627418"
- inkscape:cx="0.78663326"
- inkscape:cy="12.940707"
+ inkscape:zoom="32.000001"
+ inkscape:cx="13.864856"
+ inkscape:cy="7.2235346"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -46,7 +46,8 @@
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
- inkscape:window-maximized="1">
+ inkscape:window-maximized="1"
+ inkscape:document-rotation="0">
<inkscape:grid
type="xygrid"
id="grid3336" />
@@ -68,10 +69,37 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
+ <circle
+ style="fill:#e0e0e0;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path4266"
+ cx="4"
+ cy="1048.3622"
+ r="2" />
<path
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 7 2 A 2 2 0 0 0 5 4 L 5 7 L 1 7 L 1 9 L 5 9 L 5 12 A 2 2 0 0 0 7 14 L 11 14 L 11 12 L 14 12 L 14 10 L 11 10 L 11 6 L 14 6 L 14 4 L 11 4 L 11 2 L 7 2 z "
- transform="translate(0,1036.3622)"
- id="rect4155" />
+ id="circle4268"
+ style="fill:none;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc"
+ sodipodi:cx="4"
+ sodipodi:cy="1048.3622"
+ sodipodi:rx="5"
+ sodipodi:ry="5"
+ sodipodi:start="4.712389"
+ sodipodi:end="0"
+ sodipodi:arc-type="arc"
+ d="M 4.0000001,1043.3622 A 5,5 0 0 1 9,1048.3622"
+ sodipodi:open="true" />
+ <path
+ id="circle4270"
+ style="fill:none;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc"
+ sodipodi:cx="4"
+ sodipodi:cy="1048.3622"
+ sodipodi:rx="9"
+ sodipodi:ry="9"
+ sodipodi:start="4.712389"
+ sodipodi:end="0"
+ sodipodi:open="true"
+ sodipodi:arc-type="arc"
+ d="m 4.0000002,1039.3622 a 9,9 0 0 1 8.9999998,9" />
</g>
</svg>
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index 98020ed9b8..c0c507c2d6 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -236,7 +236,7 @@ void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String
format |= StreamTexture::FORMAT_BIT_DETECT_NORMAL;
if ((p_compress_mode == COMPRESS_LOSSLESS || p_compress_mode == COMPRESS_LOSSY) && p_image->get_format() > Image::FORMAT_RGBA8) {
- p_compress_mode == COMPRESS_UNCOMPRESSED; //these can't go as lossy
+ p_compress_mode = COMPRESS_UNCOMPRESSED; //these can't go as lossy
}
switch (p_compress_mode) {
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 18c4bed5dd..8cb712cb78 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -291,7 +291,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
bool limit_rate = p_options["force/max_rate"];
int limit_rate_hz = p_options["force/max_rate_hz"];
- if (limit_rate && rate > limit_rate_hz) {
+ if (limit_rate && rate > limit_rate_hz && rate > 0 && frames > 0) {
//resampleeee!!!
int new_data_frames = frames * limit_rate_hz / rate;
Vector<float> new_data;
@@ -356,7 +356,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
bool trim = p_options["edit/trim"];
- if (trim && !loop) {
+ if (trim && !loop && format_channels > 0) {
int first = 0;
int last = (frames * format_channels) - 1;
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index c31e11cc38..2d77bfb2c1 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -3142,7 +3142,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
xform_scale[i]->set_text("1");
}
- xform_dialog->popup_centered(Size2(200, 200));
+ xform_dialog->popup_centered(Size2(320, 240) * EDSCALE);
} break;
case MENU_VIEW_USE_1_VIEWPORT: {
@@ -3964,55 +3964,59 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
xform_dialog = memnew(ConfirmationDialog);
xform_dialog->set_title(TTR("Transform Change"));
add_child(xform_dialog);
+
+ VBoxContainer *xform_vbc = memnew(VBoxContainer);
+ xform_dialog->add_child(xform_vbc);
+
Label *l = memnew(Label);
l->set_text(TTR("Translate:"));
- l->set_position(Point2(5, 5));
- xform_dialog->add_child(l);
+ xform_vbc->add_child(l);
+
+ HBoxContainer *xform_hbc = memnew(HBoxContainer);
+ xform_vbc->add_child(xform_hbc);
for (int i = 0; i < 3; i++) {
xform_translate[i] = memnew(LineEdit);
- xform_translate[i]->set_position(Point2(15 + i * 60, 22));
- xform_translate[i]->set_size(Size2(50, 12));
- xform_dialog->add_child(xform_translate[i]);
+ xform_translate[i]->set_h_size_flags(SIZE_EXPAND_FILL);
+ xform_hbc->add_child(xform_translate[i]);
}
l = memnew(Label);
l->set_text(TTR("Rotate (deg.):"));
- l->set_position(Point2(5, 45));
- xform_dialog->add_child(l);
+ xform_vbc->add_child(l);
+
+ xform_hbc = memnew(HBoxContainer);
+ xform_vbc->add_child(xform_hbc);
for (int i = 0; i < 3; i++) {
xform_rotate[i] = memnew(LineEdit);
- xform_rotate[i]->set_position(Point2(15 + i * 60, 62));
- xform_rotate[i]->set_size(Size2(50, 22));
- xform_dialog->add_child(xform_rotate[i]);
+ xform_rotate[i]->set_h_size_flags(SIZE_EXPAND_FILL);
+ xform_hbc->add_child(xform_rotate[i]);
}
l = memnew(Label);
l->set_text(TTR("Scale (ratio):"));
- l->set_position(Point2(5, 85));
- xform_dialog->add_child(l);
+ xform_vbc->add_child(l);
+
+ xform_hbc = memnew(HBoxContainer);
+ xform_vbc->add_child(xform_hbc);
for (int i = 0; i < 3; i++) {
xform_scale[i] = memnew(LineEdit);
- xform_scale[i]->set_position(Point2(15 + i * 60, 102));
- xform_scale[i]->set_size(Size2(50, 22));
- xform_dialog->add_child(xform_scale[i]);
+ xform_scale[i]->set_h_size_flags(SIZE_EXPAND_FILL);
+ xform_hbc->add_child(xform_scale[i]);
}
l = memnew(Label);
l->set_text(TTR("Transform Type"));
- l->set_position(Point2(5, 125));
- xform_dialog->add_child(l);
+ xform_vbc->add_child(l);
xform_type = memnew(OptionButton);
- xform_type->set_anchor(MARGIN_RIGHT, ANCHOR_END);
- xform_type->set_begin(Point2(15, 142));
- xform_type->set_end(Point2(15, 75));
+ xform_type->set_h_size_flags(SIZE_EXPAND_FILL);
xform_type->add_item(TTR("Pre"));
xform_type->add_item(TTR("Post"));
- xform_dialog->add_child(xform_type);
+ xform_vbc->add_child(xform_type);
xform_dialog->connect("confirmed", this, "_xform_dialog_action");
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 125d906460..57c27a8a7e 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -102,14 +102,24 @@ void TextureEditor::_notification(int p_what) {
}
}
+void TextureEditor::_changed_callback(Object *p_changed, const char *p_prop) {
+
+ if (!is_visible())
+ return;
+ update();
+}
+
void TextureEditor::edit(Ref<Texture> p_texture) {
+ if (!texture.is_null())
+ texture->remove_change_receptor(this);
+
texture = p_texture;
- if (!texture.is_null())
+ if (!texture.is_null()) {
+ texture->add_change_receptor(this);
update();
- else {
-
+ } else {
hide();
}
}
diff --git a/editor/plugins/texture_editor_plugin.h b/editor/plugins/texture_editor_plugin.h
index 9382983538..13f8dd7fbd 100644
--- a/editor/plugins/texture_editor_plugin.h
+++ b/editor/plugins/texture_editor_plugin.h
@@ -43,6 +43,7 @@ class TextureEditor : public Control {
protected:
void _notification(int p_what);
void _gui_input(Ref<InputEvent> p_event);
+ void _changed_callback(Object *p_changed, const char *p_prop);
static void _bind_methods();
public:
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 8a7dcea393..4cd18b090a 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -617,38 +617,24 @@ void TextureRegionEditor::_bind_methods() {
}
void TextureRegionEditor::edit(Object *p_obj) {
- if (node_sprite && node_sprite->is_connected("texture_changed", this, "_edit_region"))
- node_sprite->disconnect("texture_changed", this, "_edit_region");
- if (node_patch9 && node_patch9->is_connected("texture_changed", this, "_edit_region"))
- node_patch9->disconnect("texture_changed", this, "_edit_region");
- if (obj_styleBox.is_valid() && obj_styleBox->is_connected("texture_changed", this, "_edit_region"))
- obj_styleBox->disconnect("texture_changed", this, "_edit_region");
- if (atlas_tex.is_valid() && atlas_tex->is_connected("atlas_changed", this, "_edit_region"))
- atlas_tex->disconnect("atlas_changed", this, "_edit_region");
+ if (node_sprite)
+ node_sprite->remove_change_receptor(this);
+ if (node_patch9)
+ node_patch9->remove_change_receptor(this);
+ if (obj_styleBox.is_valid())
+ obj_styleBox->remove_change_receptor(this);
+ if (atlas_tex.is_valid())
+ atlas_tex->remove_change_receptor(this);
if (p_obj) {
node_sprite = p_obj->cast_to<Sprite>();
node_patch9 = p_obj->cast_to<NinePatchRect>();
if (p_obj->cast_to<StyleBoxTexture>())
obj_styleBox = Ref<StyleBoxTexture>(p_obj->cast_to<StyleBoxTexture>());
- if (p_obj->cast_to<AtlasTexture>()) {
+ if (p_obj->cast_to<AtlasTexture>())
atlas_tex = Ref<AtlasTexture>(p_obj->cast_to<AtlasTexture>());
- atlas_tex->connect("atlas_changed", this, "_edit_region");
- } else {
- p_obj->connect("texture_changed", this, "_edit_region");
- }
p_obj->add_change_receptor(this);
- p_obj->connect("tree_exited", this, "_node_removed", varray(p_obj), CONNECT_ONESHOT);
_edit_region();
} else {
- if (node_sprite)
- node_sprite->disconnect("tree_exited", this, "_node_removed");
- else if (node_patch9)
- node_patch9->disconnect("tree_exited", this, "_node_removed");
- else if (obj_styleBox.is_valid())
- obj_styleBox->disconnect("tree_exited", this, "_node_removed");
- else if (atlas_tex.is_valid())
- atlas_tex->disconnect("tree_exited", this, "_node_removed");
-
node_sprite = NULL;
node_patch9 = NULL;
obj_styleBox = Ref<StyleBoxTexture>(NULL);
@@ -658,9 +644,11 @@ void TextureRegionEditor::edit(Object *p_obj) {
}
void TextureRegionEditor::_changed_callback(Object *p_changed, const char *p_prop) {
- if ((String)p_prop == "region_rect") {
+
+ if (!is_visible())
+ return;
+ if (p_prop == StringName("atlas") || p_prop == StringName("texture"))
_edit_region();
- }
}
void TextureRegionEditor::_edit_region() {
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 6d23e874df..6238cad14d 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -140,7 +140,7 @@ void ProjectSettingsEditor::_action_edited() {
add_at = "input/" + old_name;
message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
- message->popup_centered(Size2(300, 100));
+ message->popup_centered(Size2(300, 100) * EDSCALE);
return;
}
@@ -152,7 +152,7 @@ void ProjectSettingsEditor::_action_edited() {
add_at = "input/" + old_name;
message->set_text(vformat(TTR("Action '%s' already exists!"), new_name));
- message->popup_centered(Size2(300, 100));
+ message->popup_centered(Size2(300, 100) * EDSCALE);
return;
}
@@ -399,7 +399,7 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
device_index->add_item(TTR("Button 7"));
device_index->add_item(TTR("Button 8"));
device_index->add_item(TTR("Button 9"));
- device_input->popup_centered_minsize(Size2(350, 95));
+ device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE);
Ref<InputEventMouseButton> mb = p_exiting_event;
if (mb.is_valid()) {
@@ -420,7 +420,7 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
String desc = _axis_names[i];
device_index->add_item(TTR("Axis") + " " + itos(i / 2) + " " + (i & 1 ? "+" : "-") + desc);
}
- device_input->popup_centered_minsize(Size2(350, 95));
+ device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE);
Ref<InputEventJoypadMotion> jm = p_exiting_event;
if (jm.is_valid()) {
@@ -441,7 +441,7 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
device_index->add_item(itos(i) + ": " + String(_button_names[i]));
}
- device_input->popup_centered_minsize(Size2(350, 95));
+ device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE);
Ref<InputEventJoypadButton> jb = p_exiting_event;
if (jb.is_valid()) {
@@ -835,13 +835,13 @@ void ProjectSettingsEditor::_action_add() {
String action = action_name->get_text();
if (action.find("/") != -1 || action.find(":") != -1 || action == "") {
message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
- message->popup_centered(Size2(300, 100));
+ message->popup_centered(Size2(300, 100) * EDSCALE);
return;
}
if (ProjectSettings::get_singleton()->has("input/" + action)) {
message->set_text(vformat(TTR("Action '%s' already exists!"), action));
- message->popup_centered(Size2(300, 100));
+ message->popup_centered(Size2(300, 100) * EDSCALE);
return;
}
@@ -879,7 +879,7 @@ void ProjectSettingsEditor::_save() {
Error err = ProjectSettings::get_singleton()->save();
message->set_text(err != OK ? TTR("Error saving settings.") : TTR("Settings saved OK."));
- message->popup_centered(Size2(300, 100));
+ message->popup_centered(Size2(300, 100) * EDSCALE);
}
void ProjectSettingsEditor::_settings_prop_edited(const String &p_name) {
@@ -1554,7 +1554,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
add = memnew(Button);
hbc->add_child(add);
- add->set_custom_minimum_size(Size2(150, 0));
+ add->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
add->set_text(TTR("Add"));
add->connect("pressed", this, "_action_add");
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index d81161ae94..0748c43b5f 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "script_create_dialog.h"
+#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor_file_system.h"
#include "io/resource_saver.h"
@@ -229,7 +230,7 @@ void ScriptCreateDialog::_lang_changed(int l) {
List<String> extensions;
// get all possible extensions for script
for (int l = 0; l < language_menu->get_item_count(); l++) {
- language->get_recognized_extensions(&extensions);
+ ScriptServer::get_language(l)->get_recognized_extensions(&extensions);
}
for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
@@ -240,8 +241,11 @@ void ScriptCreateDialog::_lang_changed(int l) {
}
}
}
- file_path->set_text(path);
+ } else {
+ path = "class" + selected_ext;
+ _path_changed(path);
}
+ file_path->set_text(path);
bool use_templates = language->is_using_templates();
template_menu->set_disabled(!use_templates);
@@ -403,9 +407,9 @@ void ScriptCreateDialog::_msg_script_valid(bool valid, const String &p_msg) {
error_label->set_text(TTR(p_msg));
if (valid) {
- error_label->add_color_override("font_color", Color(0, 1.0, 0.8, 0.8));
+ error_label->add_color_override("font_color", get_color("success_color", "Editor"));
} else {
- error_label->add_color_override("font_color", Color(1, 0.2, 0.2, 0.8));
+ error_label->add_color_override("font_color", get_color("error_color", "Editor"));
}
}
@@ -413,9 +417,9 @@ void ScriptCreateDialog::_msg_path_valid(bool valid, const String &p_msg) {
path_error_label->set_text(TTR(p_msg));
if (valid) {
- path_error_label->add_color_override("font_color", Color(0, 1.0, 0.8, 0.8));
+ path_error_label->add_color_override("font_color", get_color("success_color", "Editor"));
} else {
- path_error_label->add_color_override("font_color", Color(1, 0.4, 0.0, 0.8));
+ path_error_label->add_color_override("font_color", get_color("error_color", "Editor"));
}
}
@@ -543,19 +547,6 @@ ScriptCreateDialog::ScriptCreateDialog() {
gc = memnew(GridContainer);
gc->set_columns(2);
- /* Error Stylebox Background */
-
- StyleBoxFlat *sb = memnew(StyleBoxFlat);
- sb->set_bg_color(Color(0, 0, 0, 0.05));
- sb->set_light_color(Color(1, 1, 1, 0.05));
- sb->set_dark_color(Color(1, 1, 1, 0.05));
- sb->set_border_blend(false);
- sb->set_border_size(1);
- sb->set_default_margin(MARGIN_TOP, 10.0 * EDSCALE);
- sb->set_default_margin(MARGIN_BOTTOM, 10.0 * EDSCALE);
- sb->set_default_margin(MARGIN_LEFT, 10.0 * EDSCALE);
- sb->set_default_margin(MARGIN_RIGHT, 10.0 * EDSCALE);
-
/* Error Messages Field */
vb = memnew(VBoxContainer);
@@ -582,7 +573,7 @@ ScriptCreateDialog::ScriptCreateDialog() {
pc = memnew(PanelContainer);
pc->set_h_size_flags(Control::SIZE_FILL);
- pc->add_style_override("panel", sb);
+ pc->add_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_stylebox("bg", "Tree"));
pc->add_child(vb);
/* Margins */
diff --git a/main/performance.cpp b/main/performance.cpp
index c819e15f71..3d8e21bf33 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -117,8 +117,8 @@ float Performance::get_monitor(Monitor p_monitor) const {
case TIME_FIXED_PROCESS: return _fixed_process_time;
case MEMORY_STATIC: return Memory::get_mem_usage();
case MEMORY_DYNAMIC: return MemoryPool::total_memory;
- case MEMORY_STATIC_MAX: return MemoryPool::max_memory;
- case MEMORY_DYNAMIC_MAX: return 0;
+ case MEMORY_STATIC_MAX: return Memory::get_mem_max_usage();
+ case MEMORY_DYNAMIC_MAX: return MemoryPool::max_memory;
case MEMORY_MESSAGE_BUFFER_MAX: return MessageQueue::get_singleton()->get_max_buffer_usage();
case OBJECT_COUNT: return ObjectDB::get_object_count();
case OBJECT_RESOURCE_COUNT: return ResourceCache::get_cached_resource_count();
diff --git a/platform/android/SCsub b/platform/android/SCsub
index 7fb3c876be..b124a1a5a8 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -141,6 +141,8 @@ if env['android_arch'] == 'armv6':
lib_arch_dir = 'armeabi'
elif env['android_arch'] == 'armv7':
lib_arch_dir = 'armeabi-v7a'
+elif env['android_arch'] == 'arm64v8':
+ lib_arch_dir = 'arm64-v8a'
elif env['android_arch'] == 'x86':
lib_arch_dir = 'x86'
else:
diff --git a/platform/android/detect.py b/platform/android/detect.py
index fae1df3f27..ad5bfb4949 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -22,7 +22,7 @@ def get_opts():
return [
('ANDROID_NDK_ROOT', 'Path to the Android NDK', os.environ.get("ANDROID_NDK_ROOT", 0)),
('ndk_platform', 'Target platform (android-<api>, e.g. "android-18")', "android-18"),
- ('android_arch', 'Target architecture (armv7/armv6/x86)', "armv7"),
+ ('android_arch', 'Target architecture (armv7/armv6/arm64v8/x86)', "armv7"),
('android_neon', 'Enable NEON support (armv7 only)', "yes"),
('android_stl', 'Enable Android STL support (for modules)', "no")
]
@@ -89,7 +89,7 @@ def configure(env):
## Architecture
- if env['android_arch'] not in ['armv7', 'armv6', 'x86']:
+ if env['android_arch'] not in ['armv7', 'armv6', 'arm64v8', 'x86']:
env['android_arch'] = 'armv7'
neon_text = ""
@@ -99,18 +99,21 @@ def configure(env):
can_vectorize = True
if env['android_arch'] == 'x86':
+ env['ARCH'] = 'arch-x86'
env.extra_suffix = ".x86" + env.extra_suffix
target_subpath = "x86-4.9"
abi_subpath = "i686-linux-android"
arch_subpath = "x86"
env["x86_libtheora_opt_gcc"] = True
elif env['android_arch'] == 'armv6':
+ env['ARCH'] = 'arch-arm'
env.extra_suffix = ".armv6" + env.extra_suffix
target_subpath = "arm-linux-androideabi-4.9"
abi_subpath = "arm-linux-androideabi"
arch_subpath = "armeabi"
can_vectorize = False
elif env["android_arch"] == "armv7":
+ env['ARCH'] = 'arch-arm'
target_subpath = "arm-linux-androideabi-4.9"
abi_subpath = "arm-linux-androideabi"
arch_subpath = "armeabi-v7a"
@@ -118,6 +121,12 @@ def configure(env):
env.extra_suffix = ".armv7.neon" + env.extra_suffix
else:
env.extra_suffix = ".armv7" + env.extra_suffix
+ elif env["android_arch"] == "arm64v8":
+ env['ARCH'] = 'arch-arm64'
+ target_subpath = "aarch64-linux-android-4.9"
+ abi_subpath = "aarch64-linux-android"
+ arch_subpath = "arm64-v8a"
+ env.extra_suffix = ".armv8" + env.extra_suffix
## Build type
@@ -149,6 +158,8 @@ def configure(env):
elif (sys.platform.startswith('win')):
if (platform.machine().endswith('64')):
host_subpath = "windows-x86_64"
+ if env["android_arch"] == "arm64v8":
+ mt_link = False
else:
mt_link = False
host_subpath = "windows"
@@ -166,11 +177,6 @@ def configure(env):
env['RANLIB'] = tools_path + "/ranlib"
env['AS'] = tools_path + "/as"
- if env['android_arch'] == 'x86':
- env['ARCH'] = 'arch-x86'
- else:
- env['ARCH'] = 'arch-arm'
-
sysroot = env["ANDROID_NDK_ROOT"] + "/platforms/" + env['ndk_platform'] + "/" + env['ARCH']
common_opts = ['-fno-integrated-as', '-gcc-toolchain', gcc_toolchain_path]
@@ -199,6 +205,11 @@ def configure(env):
else:
env.Append(CPPFLAGS=['-mfpu=vfpv3-d16'])
+ elif env["android_arch"] == "arm64v8":
+ target_opts = ['-target', 'aarch64-none-linux-android']
+ env.Append(CPPFLAGS=['-D__ARM_ARCH_8A__'])
+ env.Append(CPPFLAGS=['-mfix-cortex-a53-835769'])
+
env.Append(CPPFLAGS=target_opts)
env.Append(CPPFLAGS=common_opts)
@@ -213,7 +224,8 @@ def configure(env):
## Link flags
env['LINKFLAGS'] = ['-shared', '--sysroot=' + sysroot, '-Wl,--warn-shared-textrel']
- env.Append(LINKFLAGS=string.split('-Wl,--fix-cortex-a8'))
+ if env["android_arch"] == "armv7":
+ env.Append(LINKFLAGS=string.split('-Wl,--fix-cortex-a8'))
env.Append(LINKFLAGS=string.split('-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now'))
env.Append(LINKFLAGS=string.split('-Wl,-soname,libgodot_android.so -Wl,--gc-sections'))
if mt_link:
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index a722cd1b8c..3c52834d92 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -219,6 +219,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
bool use_32_fb;
bool immersive;
bool export_arm;
+ bool export_arm64;
bool export_x86;
String apk_expansion_salt;
String apk_expansion_pkey;
@@ -319,6 +320,8 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant&
_signed=p_value;
else if (n=="architecture/arm")
export_arm=p_value;
+ else if (n=="architecture/arm64")
+ export_arm64=p_value;
else if (n=="architecture/x86")
export_x86=p_value;
else if (n=="screen/use_32_bits_view")
@@ -392,6 +395,8 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret)
r_ret=_signed;
else if (n=="architecture/arm")
r_ret=export_arm;
+ else if (n=="architecture/arm64")
+ r_ret=export_arm64;
else if (n=="architecture/x86")
r_ret=export_x86;
else if (n=="screen/use_32_bits_view")
@@ -1164,6 +1169,10 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
skip=true;
}
+ if (file.match("lib/arm64*/libgodot_android.so") && !export_arm64) {
+ skip = true;
+ }
+
if (file.begins_with("META-INF") && _signed) {
skip=true;
}
@@ -1801,6 +1810,7 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
immersive=true;
export_arm=true;
+ export_arm64=false;
export_x86=false;
@@ -3176,6 +3186,7 @@ public:
bool export_x86 = p_preset->get("architecture/x86");
bool export_arm = p_preset->get("architecture/arm");
+ bool export_arm64 = p_preset->get("architecture/arm64");
bool use_32_fb = p_preset->get("screen/use_32_bits_view");
bool immersive = p_preset->get("screen/immersive_mode");
@@ -3267,6 +3278,10 @@ public:
skip = true;
}
+ if (file.match("lib/arm64*/libgodot_android.so") && !export_arm64) {
+ skip = true;
+ }
+
if (file.begins_with("META-INF") && _signed) {
skip = true;
}
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index 56a27fa0e0..52ff9cd562 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -190,7 +190,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
argv[i].i = *p_args[i];
} break;
case ARG_TYPE_LONG: {
- argv[i].j = *p_args[i];
+ argv[i].j = (int64_t)*p_args[i];
} break;
case ARG_TYPE_FLOAT: {
argv[i].f = *p_args[i];
@@ -350,7 +350,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
Array arr = *p_args[i];
jlongArray a = env->NewLongArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
- jlong val = arr[j];
+ jlong val = (int64_t)arr[j];
env->SetLongArrayRegion(a, j, 1, &val);
}
argv[i].l = a;
@@ -460,9 +460,9 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
case ARG_TYPE_LONG: {
if (method->_static) {
- ret = env->CallStaticLongMethodA(_class, method->method, argv);
+ ret = (int64_t)env->CallStaticLongMethodA(_class, method->method, argv);
} else {
- ret = env->CallLongMethodA(p_instance->instance, method->method, argv);
+ ret = (int64_t)env->CallLongMethodA(p_instance->instance, method->method, argv);
}
} break;
@@ -680,7 +680,7 @@ bool JavaClass::_convert_object_to_variant(JNIEnv *env, jobject obj, Variant &va
} break;
case ARG_TYPE_LONG | ARG_NUMBER_CLASS_BIT: {
- var = env->CallLongMethod(obj, JavaClassWrapper::singleton->Long_longValue);
+ var = (int64_t)env->CallLongMethod(obj, JavaClassWrapper::singleton->Long_longValue);
return true;
} break;
@@ -802,7 +802,7 @@ bool JavaClass::_convert_object_to_variant(JNIEnv *env, jobject obj, Variant &va
jlong val;
env->GetLongArrayRegion((jlongArray)arr, 0, 1, &val);
- ret.push_back(val);
+ ret.push_back((int64_t)val);
}
var = ret;
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index c091c7d022..da14d5c284 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -805,7 +805,12 @@ void OS_Windows::process_key_events() {
k->set_pressed(ke.uMsg == WM_KEYDOWN);
- k->set_scancode(KeyMappingWindows::get_keysym(ke.wParam));
+ if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) {
+ // Special case for Numpad Enter key
+ k->set_scancode(KEY_ENTER);
+ } else {
+ k->set_scancode(KeyMappingWindows::get_keysym(ke.wParam));
+ }
if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) {
k->set_unicode(key_event_buffer[i + 1].wParam);
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index b469013819..ad34dfd63a 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -109,6 +109,7 @@ void Sprite::set_texture(const Ref<Texture> &p_texture) {
update();
emit_signal("texture_changed");
item_rect_changed();
+ _change_notify("texture");
}
void Sprite::set_normal_map(const Ref<Texture> &p_texture) {
diff --git a/scene/gui/patch_9_rect.cpp b/scene/gui/patch_9_rect.cpp
index 16f2bb6b6f..e577000f99 100644
--- a/scene/gui/patch_9_rect.cpp
+++ b/scene/gui/patch_9_rect.cpp
@@ -99,6 +99,7 @@ void NinePatchRect::set_texture(const Ref<Texture> &p_tex) {
*/
minimum_size_changed();
emit_signal("texture_changed");
+ _change_notify("texture");
}
Ref<Texture> NinePatchRect::get_texture() const {
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index e0a9de6062..3666c18487 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -107,6 +107,7 @@ void StyleBoxTexture::set_texture(RES p_texture) {
region_rect = Rect2(Point2(), texture->get_size());
emit_signal("texture_changed");
emit_changed();
+ _change_notify("texture");
}
RES StyleBoxTexture::get_texture() const {
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index 8b747e1b43..8478432a04 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -818,6 +818,7 @@ void SurfaceTool::clear() {
void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("begin", "primitive"), &SurfaceTool::begin);
+
ClassDB::bind_method(D_METHOD("add_vertex", "vertex"), &SurfaceTool::add_vertex);
ClassDB::bind_method(D_METHOD("add_color", "color"), &SurfaceTool::add_color);
ClassDB::bind_method(D_METHOD("add_normal", "normal"), &SurfaceTool::add_normal);
@@ -827,15 +828,25 @@ void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_bones", "bones"), &SurfaceTool::add_bones);
ClassDB::bind_method(D_METHOD("add_weights", "weights"), &SurfaceTool::add_weights);
ClassDB::bind_method(D_METHOD("add_smooth_group", "smooth"), &SurfaceTool::add_smooth_group);
+
ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertexes", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>()));
- ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &SurfaceTool::set_material);
+
+ ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index);
+
ClassDB::bind_method(D_METHOD("index"), &SurfaceTool::index);
ClassDB::bind_method(D_METHOD("deindex"), &SurfaceTool::deindex);
- ///ClassDB::bind_method(D_METHOD("generate_flat_normals"),&SurfaceTool::generate_flat_normals);
ClassDB::bind_method(D_METHOD("generate_normals"), &SurfaceTool::generate_normals);
- ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index);
- ClassDB::bind_method(D_METHOD("commit:Mesh", "existing:Mesh"), &SurfaceTool::commit, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("generate_tangents"), &SurfaceTool::generate_tangents);
+
+ ClassDB::bind_method(D_METHOD("add_to_format", "flags"), &SurfaceTool::add_to_format);
+
+ ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &SurfaceTool::set_material);
+
ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear);
+
+ ClassDB::bind_method(D_METHOD("create_from", "existing:Mesh", "surface"), &SurfaceTool::create_from);
+ ClassDB::bind_method(D_METHOD("append_from", "existing:Mesh", "surface", "transform"), &SurfaceTool::append_from);
+ ClassDB::bind_method(D_METHOD("commit:Mesh", "existing:Mesh"), &SurfaceTool::commit, DEFVAL(Variant()));
}
SurfaceTool::SurfaceTool() {
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 5cd75b5a69..fe7cd0097c 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -830,7 +830,7 @@ void AtlasTexture::set_atlas(const Ref<Texture> &p_atlas) {
return;
atlas = p_atlas;
emit_changed();
- emit_signal("atlas_changed");
+ _change_notify("atlas");
}
Ref<Texture> AtlasTexture::get_atlas() const {
@@ -839,8 +839,11 @@ Ref<Texture> AtlasTexture::get_atlas() const {
void AtlasTexture::set_region(const Rect2 &p_region) {
+ if (region == p_region)
+ return;
region = p_region;
emit_changed();
+ _change_notify("region");
}
Rect2 AtlasTexture::get_region() const {
@@ -850,8 +853,11 @@ Rect2 AtlasTexture::get_region() const {
void AtlasTexture::set_margin(const Rect2 &p_margin) {
+ if (margin == p_margin)
+ return;
margin = p_margin;
emit_changed();
+ _change_notify("margin");
}
Rect2 AtlasTexture::get_margin() const {
@@ -870,8 +876,6 @@ void AtlasTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &AtlasTexture::set_margin);
ClassDB::bind_method(D_METHOD("get_margin"), &AtlasTexture::get_margin);
- ADD_SIGNAL(MethodInfo("atlas_changed"));
-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_atlas", "get_atlas");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region"), "set_region", "get_region");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "margin"), "set_margin", "get_margin");
diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h
index 06e58e3d5a..3dae1db13f 100644
--- a/servers/physics/area_sw.h
+++ b/servers/physics/area_sw.h
@@ -154,6 +154,7 @@ public:
_FORCE_INLINE_ void add_constraint(ConstraintSW *p_constraint) { constraints.insert(p_constraint); }
_FORCE_INLINE_ void remove_constraint(ConstraintSW *p_constraint) { constraints.erase(p_constraint); }
_FORCE_INLINE_ const Set<ConstraintSW *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
void set_monitorable(bool p_monitorable);
_FORCE_INLINE_ bool is_monitorable() const { return monitorable; }
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index 1f32c059a8..e065fae2be 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -757,7 +757,8 @@ BodySW::BodySW()
contact_count = 0;
gravity_scale = 1.0;
-
+ linear_damp = -1;
+ angular_damp = -1;
area_angular_damp = 0;
area_linear_damp = 0;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index c3e051c2d0..512b868570 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -194,6 +194,7 @@ public:
_FORCE_INLINE_ void add_constraint(ConstraintSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; }
_FORCE_INLINE_ void remove_constraint(ConstraintSW *p_constraint) { constraint_map.erase(p_constraint); }
const Map<ConstraintSW *, int> &get_constraint_map() const { return constraint_map; }
+ _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); }
_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; }
_FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; }
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 101bd4b185..833c77216e 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -222,12 +222,24 @@ void PhysicsServerSW::area_set_space(RID p_area, RID p_space) {
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
+
SpaceSW *space = NULL;
if (p_space.is_valid()) {
space = space_owner.get(p_space);
ERR_FAIL_COND(!space);
}
+ if (area->get_space() == space)
+ return; //pointless
+
+ for (Set<ConstraintSW *>::Element *E = area->get_constraints().front(); E; E = E->next()) {
+ RID self = E->get()->get_self();
+ if (!self.is_valid())
+ continue;
+ free(self);
+ }
+ area->clear_constraints();
+
area->set_space(space);
};
@@ -471,15 +483,23 @@ void PhysicsServerSW::body_set_space(RID p_body, RID p_space) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
- SpaceSW *space = NULL;
+ SpaceSW *space = NULL;
if (p_space.is_valid()) {
space = space_owner.get(p_space);
ERR_FAIL_COND(!space);
}
if (body->get_space() == space)
- return; //pointles
+ return; //pointless
+
+ while (body->get_constraint_map().size()) {
+ RID self = body->get_constraint_map().front()->key()->get_self();
+ if (!self.is_valid())
+ continue;
+ free(self);
+ }
+ body->clear_constraint_map();
body->set_space(space);
};
@@ -1329,12 +1349,6 @@ void PhysicsServerSW::free(RID p_rid) {
body->remove_shape(0);
}
- while (body->get_constraint_map().size()) {
- RID self = body->get_constraint_map().front()->key()->get_self();
- ERR_FAIL_COND(!self.is_valid());
- free(self);
- }
-
body_owner.free(p_rid);
memdelete(body);
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 5679fc8f60..094cfa4656 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -34,12 +34,12 @@
_FORCE_INLINE_ static bool _match_object_type_query(CollisionObjectSW *p_object, uint32_t p_collision_layer, uint32_t p_type_mask) {
- if (p_object->get_type() == CollisionObjectSW::TYPE_AREA)
- return p_type_mask & PhysicsDirectSpaceState::TYPE_MASK_AREA;
-
if ((p_object->get_collision_layer() & p_collision_layer) == 0)
return false;
+ if (p_object->get_type() == CollisionObjectSW::TYPE_AREA)
+ return p_type_mask & PhysicsDirectSpaceState::TYPE_MASK_AREA;
+
BodySW *body = static_cast<BodySW *>(p_object);
return (1 << body->get_mode()) & p_type_mask;
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h
index 68b3c61e44..6d74a4b0f6 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/area_2d_sw.h
@@ -153,6 +153,7 @@ public:
_FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint) { constraints.insert(p_constraint); }
_FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint) { constraints.erase(p_constraint); }
_FORCE_INLINE_ const Set<Constraint2DSW *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
void set_monitorable(bool p_monitorable);
_FORCE_INLINE_ bool is_monitorable() const { return monitorable; }
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index 9e5deef3f2..412f2f51cd 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -181,6 +181,7 @@ public:
_FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; }
_FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint) { constraint_map.erase(p_constraint); }
const Map<Constraint2DSW *, int> &get_constraint_map() const { return constraint_map; }
+ _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); }
_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; }
_FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; }
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
index 5b6c7e2f38..0330bfa9f3 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
@@ -203,9 +203,11 @@ void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool
if (sz.width * sz.height > large_object_min_surface) {
//unpair all elements, instead of checking all, just check what is already paired, so we at least save from checking static vs static
- for (Map<Element *, PairData *>::Element *E = p_elem->paired.front(); E; E = E->next()) {
-
+ Map<Element *, PairData *>::Element *E = p_elem->paired.front();
+ while (E) {
+ Map<Element *, PairData *>::Element *next = E->next();
_unpair_attempt(p_elem, E->key());
+ E = next;
}
if (large_elements[p_elem].dec() == 0) {
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index c20d0d14a2..add376bfb2 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -286,12 +286,24 @@ void Physics2DServerSW::area_set_space(RID p_area, RID p_space) {
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
+
Space2DSW *space = NULL;
if (p_space.is_valid()) {
space = space_owner.get(p_space);
ERR_FAIL_COND(!space);
}
+ if (area->get_space() == space)
+ return; //pointless
+
+ for (Set<Constraint2DSW *>::Element *E = area->get_constraints().front(); E; E = E->next()) {
+ RID self = E->get()->get_self();
+ if (!self.is_valid())
+ continue;
+ free(self);
+ }
+ area->clear_constraints();
+
area->set_space(space);
};
@@ -533,6 +545,17 @@ void Physics2DServerSW::body_set_space(RID p_body, RID p_space) {
ERR_FAIL_COND(!space);
}
+ if (body->get_space() == space)
+ return; //pointless
+
+ while (body->get_constraint_map().size()) {
+ RID self = body->get_constraint_map().front()->key()->get_self();
+ if (!self.is_valid())
+ continue;
+ free(self);
+ }
+ body->clear_constraint_map();
+
body->set_space(space);
};
@@ -1073,19 +1096,13 @@ void Physics2DServerSW::free(RID p_rid) {
_clear_query(body->get_direct_state_query());
*/
- body->set_space(NULL);
+ body_set_space(p_rid, RID());
while (body->get_shape_count()) {
body->remove_shape(0);
}
- while (body->get_constraint_map().size()) {
- RID self = body->get_constraint_map().front()->key()->get_self();
- ERR_FAIL_COND(!self.is_valid());
- free(self);
- }
-
body_owner.free(p_rid);
memdelete(body);