summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/bind/core_bind.cpp75
-rw-r--r--core/bind/core_bind.h1
-rw-r--r--doc/base/classes.xml6
-rw-r--r--scene/animation/animation_tree_player.cpp9
-rw-r--r--scene/gui/control.cpp35
-rw-r--r--scene/gui/control.h4
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp20
7 files changed, 124 insertions, 26 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 9d380aa33a..d67b93603c 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -6,6 +6,15 @@
#include "core/globals.h"
#include "io/file_access_encrypted.h"
#include "os/keyboard.h"
+
+/**
+ * Time constants borrowed from loc_time.h
+ */
+#define EPOCH_YR 1970 /* EPOCH = Jan 1 1970 00:00:00 */
+#define SECS_DAY (24L * 60L * 60L)
+#define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
+#define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
+
_ResourceLoader *_ResourceLoader::singleton=NULL;
Ref<ResourceInteractiveLoader> _ResourceLoader::load_interactive(const String& p_path,const String& p_type_hint) {
@@ -479,9 +488,8 @@ Dictionary _OS::get_date(bool utc) const {
dated["weekday"]=date.weekday;
dated["dst"]=date.dst;
return dated;
-
-
}
+
Dictionary _OS::get_time(bool utc) const {
OS::Time time = OS::get_singleton()->get_time(utc);
@@ -490,7 +498,67 @@ Dictionary _OS::get_time(bool utc) const {
timed["minute"]=time.min;
timed["second"]=time.sec;
return timed;
+}
+
+/**
+ * Get a dictionary of time values when given epoc time
+ *
+ * Dictionary Time values will be a union if values from #get_time
+ * and #get_date dictionaries (with the exception of dst =
+ * day light standard time, as it cannot be determined from epoc)
+ */
+Dictionary _OS::get_time_from_unix_time( uint64_t unix_time_val) const {
+
+ OS::Date date;
+ OS::Time time;
+
+ unsigned long dayclock, dayno;
+ int year = EPOCH_YR;
+
+ dayclock = (unsigned long)unix_time_val % SECS_DAY;
+ dayno = (unsigned long)unix_time_val / SECS_DAY;
+
+ time.sec = dayclock % 60;
+ time.min = (dayclock % 3600) / 60;
+ time.hour = dayclock / 3600;
+
+ /* day 0 was a thursday */
+ date.weekday = static_cast<OS::Weekday>((dayno + 4) % 7);
+
+ while (dayno >= YEARSIZE(year)) {
+ dayno -= YEARSIZE(year);
+ year++;
+ }
+ date.year = year;
+
+ // Table of number of days in each month (for regular year and leap year)
+ const unsigned int _ytab[2][12] = {
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+ };
+
+ size_t imonth = 0;
+
+ while (dayno >= _ytab[LEAPYEAR(year)][imonth]) {
+ dayno -= _ytab[LEAPYEAR(year)][imonth];
+ imonth++;
+ }
+
+ date.month = static_cast<OS::Month>(imonth);
+
+ date.day = dayno + 1;
+
+ Dictionary timed;
+ timed["hour"]=time.hour;
+ timed["minute"]=time.min;
+ timed["second"]=time.sec;
+ timed["year"]=date.year;
+ timed["month"]=date.month;
+ timed["day"]=date.day;
+ timed["weekday"]=date.weekday;
+
+ return timed;
}
Dictionary _OS::get_time_zone_info() const {
@@ -837,6 +905,8 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_time","utc"),&_OS::get_time,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_time_zone_info"),&_OS::get_time_zone_info);
ObjectTypeDB::bind_method(_MD("get_unix_time"),&_OS::get_unix_time);
+ ObjectTypeDB::bind_method(_MD("get_time_from_unix_time", "unix_time_val"),
+ &_OS::get_time_from_unix_time);
ObjectTypeDB::bind_method(_MD("get_system_time_secs"), &_OS::get_system_time_secs);
ObjectTypeDB::bind_method(_MD("set_icon","icon"),&_OS::set_icon);
@@ -1995,7 +2065,6 @@ String _Thread::get_id() const {
return itos(thread->get_ID());
}
-
bool _Thread::is_active() const {
return active;
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 64a4e94aec..7b3494ebc1 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -208,6 +208,7 @@ public:
void set_icon(const Image& p_icon);
Dictionary get_date(bool utc) const;
Dictionary get_time(bool utc) const;
+ Dictionary get_time_from_unix_time(uint64_t unix_time_val) const;
Dictionary get_time_zone_info() const;
uint64_t get_unix_time() const;
uint64_t get_system_time_secs() const;
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index d111569a60..04e08f166e 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -8385,8 +8385,12 @@
</argument>
<argument index="1" name="anchor_mode" type="int">
</argument>
+ <argument index="2" name="keep_margin" type="bool" default="false">
+ </argument>
<description>
- Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Changing the anchor mode converts the current margin offset from the previous anchor mode to the new one, so margin offsets ([method set_margin]) must be done after setting anchors, or at the same time ([method set_anchor_and_margin]).
+ Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Changing the anchor mode converts the current margin offset from the previous anchor mode to the new one, so margin offsets ([method set_margin]) must be done after setting anchors, or at the same time ([method set_anchor_and_margin])
+
+ Additionally, [code]keep_margin[/code] controls whether margins should be left the same, or changed to keep the same position and size on-screen.
</description>
</method>
<method name="get_anchor" qualifiers="const">
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index cc9e6c71e3..9dcad8a533 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -637,10 +637,15 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
} break;
case NODE_TIMESCALE: {
TimeScaleNode *tsn = static_cast<TimeScaleNode*>(nb);
+ float rem;
if (p_seek)
- return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,true,p_filter,p_reverse_weight);
+ rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,true,p_filter,p_reverse_weight);
+ else
+ rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,switched,false,p_filter,p_reverse_weight);
+ if (tsn->scale == 0)
+ return INFINITY;
else
- return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,switched,false,p_filter,p_reverse_weight);
+ return rem / tsn->scale;
} break;
case NODE_TIMESEEK: {
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 295ec03702..0364f73275 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -39,6 +39,9 @@
#include "scene/scene_string_names.h"
#include "scene/gui/panel.h"
#include "scene/gui/label.h"
+#ifdef TOOLS_ENABLED
+#include "tools/editor/editor_settings.h"
+#endif
#include <stdio.h>
@@ -1153,20 +1156,31 @@ float Control::_a2s(float p_val, AnchorType p_anchor,float p_range) const {
}
-void Control::set_anchor(Margin p_margin,AnchorType p_anchor) {
+void Control::set_anchor(Margin p_margin,AnchorType p_anchor, bool p_keep_margin) {
if (!is_inside_tree()) {
- data.anchor[p_margin]=p_anchor;
- } else {
+ data.anchor[p_margin] = p_anchor;
+ } else if(!p_keep_margin) {
float pr = _get_parent_range(p_margin);
float s = _a2s( data.margin[p_margin], data.anchor[p_margin], pr );
- data.anchor[p_margin]=p_anchor;
+ data.anchor[p_margin] = p_anchor;
data.margin[p_margin] = _s2a( s, p_anchor, pr );
+ } else {
+ data.anchor[p_margin] = p_anchor;
+ _size_changed();
}
_change_notify();
}
+void Control::_set_anchor(Margin p_margin,AnchorType p_anchor) {
+ #ifdef TOOLS_ENABLED
+ set_anchor(p_margin, p_anchor, EDITOR_DEF("2d_editor/keep_margins_when_changing_anchors", false));
+ #else
+ set_anchor(p_margin, p_anchor);
+ #endif
+}
+
void Control::set_anchor_and_margin(Margin p_margin,AnchorType p_anchor, float p_pos) {
set_anchor(p_margin,p_anchor);
@@ -2090,7 +2104,8 @@ void Control::_bind_methods() {
ObjectTypeDB::bind_method(_MD("accept_event"),&Control::accept_event);
ObjectTypeDB::bind_method(_MD("get_minimum_size"),&Control::get_minimum_size);
ObjectTypeDB::bind_method(_MD("get_combined_minimum_size"),&Control::get_combined_minimum_size);
- ObjectTypeDB::bind_method(_MD("set_anchor","margin","anchor_mode"),&Control::set_anchor);
+ ObjectTypeDB::bind_method(_MD("set_anchor","margin","anchor_mode","keep_margin"),&Control::set_anchor,DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("_set_anchor","margin","anchor_mode"),&Control::_set_anchor);
ObjectTypeDB::bind_method(_MD("get_anchor","margin"),&Control::get_anchor);
ObjectTypeDB::bind_method(_MD("set_margin","margin","offset"),&Control::set_margin);
ObjectTypeDB::bind_method(_MD("set_anchor_and_margin","margin","anchor_mode","offset"),&Control::set_anchor_and_margin);
@@ -2184,10 +2199,10 @@ void Control::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::BOOL,"can_drop_data",PropertyInfo(Variant::VECTOR2,"pos"),PropertyInfo(Variant::NIL,"data")));
BIND_VMETHOD(MethodInfo("drop_data",PropertyInfo(Variant::VECTOR2,"pos"),PropertyInfo(Variant::NIL,"data")));
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/left", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("set_anchor"),_SCS("get_anchor"), MARGIN_LEFT );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/top", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("set_anchor"),_SCS("get_anchor"), MARGIN_TOP );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/right", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("set_anchor"),_SCS("get_anchor"), MARGIN_RIGHT );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/bottom", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("set_anchor"),_SCS("get_anchor"), MARGIN_BOTTOM );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/left", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_LEFT );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/top", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_TOP );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/right", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_RIGHT );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor/bottom", PROPERTY_HINT_ENUM, "Begin,End,Ratio,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_BOTTOM );
ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin/left", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"), MARGIN_LEFT );
ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin/top", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"), MARGIN_TOP );
@@ -2304,5 +2319,3 @@ Control::Control() {
Control::~Control()
{
}
-
-
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 851d8316fb..1e2db7a575 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -162,6 +162,8 @@ private:
Control *_get_focus_neighbour(Margin p_margin,int p_count=0);
+ void _set_anchor(Margin p_margin,AnchorType p_anchor);
+
float _get_parent_range(int p_idx) const;
float _get_range(int p_idx) const;
float _s2a(float p_val, AnchorType p_anchor,float p_range) const;
@@ -244,7 +246,7 @@ public:
/* POSITIONING */
- void set_anchor(Margin p_margin,AnchorType p_anchor);
+ void set_anchor(Margin p_margin,AnchorType p_anchor, bool p_keep_margin=false);
void set_anchor_and_margin(Margin p_margin,AnchorType p_anchor, float p_pos);
AnchorType get_anchor(Margin p_margin) const;
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index bd36f4060b..8b583dd3c6 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -968,19 +968,25 @@ void ConcavePolygonShape2DSW::set_data(const Variant& p_data) {
ERR_FAIL_COND(p_data.get_type()!=Variant::VECTOR2_ARRAY && p_data.get_type()!=Variant::REAL_ARRAY);
- segments.clear();;
- points.clear();;
- bvh.clear();;
- bvh_depth=1;
-
Rect2 aabb;
if (p_data.get_type()==Variant::VECTOR2_ARRAY) {
DVector<Vector2> p2arr = p_data;
int len = p2arr.size();
- DVector<Vector2>::Read arr = p2arr.read();
+ ERR_FAIL_COND(len%2);
+ segments.clear();
+ points.clear();
+ bvh.clear();
+ bvh_depth=1;
+
+ if (len==0) {
+ configure(aabb);
+ return;
+ }
+
+ DVector<Vector2>::Read arr = p2arr.read();
Map<Point2,int> pointmap;
for(int i=0;i<len;i+=2) {
@@ -988,8 +994,6 @@ void ConcavePolygonShape2DSW::set_data(const Variant& p_data) {
Point2 p1 =arr[i];
Point2 p2 =arr[i+1];
int idx_p1,idx_p2;
- if (p1==p2)
- continue; //don't want it
if (pointmap.has(p1)) {
idx_p1=pointmap[p1];