summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/canvas_item.cpp315
-rw-r--r--scene/2d/canvas_item.h65
-rw-r--r--scene/2d/canvas_modulate.cpp46
-rw-r--r--scene/2d/canvas_modulate.h23
-rw-r--r--scene/2d/light_2d.cpp300
-rw-r--r--scene/2d/light_2d.h86
-rw-r--r--scene/2d/light_occluder_2d.cpp201
-rw-r--r--scene/2d/light_occluder_2d.h73
-rw-r--r--scene/2d/navigation2d.cpp660
-rw-r--r--scene/2d/navigation2d.h138
-rw-r--r--scene/2d/navigation_polygon.cpp450
-rw-r--r--scene/2d/navigation_polygon.h84
-rw-r--r--scene/2d/node_2d.cpp14
-rw-r--r--scene/2d/node_2d.h3
-rw-r--r--scene/2d/tile_map.cpp104
-rw-r--r--scene/2d/tile_map.h14
-rw-r--r--scene/3d/camera.cpp8
-rw-r--r--scene/3d/visual_instance.cpp15
-rw-r--r--scene/3d/visual_instance.h4
-rw-r--r--scene/gui/control.cpp11
-rw-r--r--scene/gui/control.h2
-rw-r--r--scene/gui/dialogs.cpp4
-rw-r--r--scene/gui/popup.cpp4
-rw-r--r--scene/gui/popup_menu.h2
-rw-r--r--scene/gui/tree.cpp4
-rw-r--r--scene/main/viewport.cpp33
-rw-r--r--scene/main/viewport.h7
-rw-r--r--scene/register_scene_types.cpp14
-rw-r--r--scene/resources/material.cpp2
-rw-r--r--scene/resources/polygon_path_finder.cpp26
-rw-r--r--scene/resources/shader_graph.cpp388
-rw-r--r--scene/resources/shader_graph.h29
-rw-r--r--scene/resources/style_box.cpp6
-rw-r--r--scene/resources/texture.cpp95
-rw-r--r--scene/resources/texture.h25
-rw-r--r--scene/scene_string_names.cpp1
-rw-r--r--scene/scene_string_names.h1
37 files changed, 3029 insertions, 228 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index ae857bbce9..4a1842100a 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -36,6 +36,192 @@
#include "scene/resources/texture.h"
#include "scene/resources/style_box.h"
+
+bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value) {
+
+ if (p_name==SceneStringNames::get_singleton()->shader_shader) {
+ set_shader(p_value);
+ return true;
+ } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
+ set_unshaded(p_value);
+ print_line("set unshaded");
+ return true;
+ } else {
+
+ if (shader.is_valid()) {
+
+
+ StringName pr = shader->remap_param(p_name);
+ if (!pr) {
+ String n = p_name;
+ if (n.find("param/")==0) { //backwards compatibility
+ pr = n.substr(6,n.length());
+ }
+ }
+ if (pr) {
+ VisualServer::get_singleton()->canvas_item_material_set_shader_param(material,pr,p_value);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
+
+
+ if (p_name==SceneStringNames::get_singleton()->shader_shader) {
+
+ r_ret=get_shader();
+ return true;
+ } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
+
+
+ r_ret=unshaded;
+ return true;
+ } else {
+
+ if (shader.is_valid()) {
+
+ StringName pr = shader->remap_param(p_name);
+ if (pr) {
+ r_ret=VisualServer::get_singleton()->canvas_item_material_get_shader_param(material,pr);
+ return true;
+ }
+ }
+
+ }
+
+
+ return false;
+}
+
+
+void CanvasItemMaterial::_get_property_list( List<PropertyInfo> *p_list) const {
+
+ p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemShader,CanvasItemShaderGraph" ) );
+ p_list->push_back( PropertyInfo( Variant::BOOL, "shader/unshaded") );
+
+ if (!shader.is_null()) {
+
+ shader->get_param_list(p_list);
+ }
+
+}
+
+void CanvasItemMaterial::set_shader(const Ref<Shader>& p_shader) {
+
+ ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM);
+#ifdef TOOLS_ENABLED
+
+ if (shader.is_valid()) {
+ shader->disconnect("changed",this,"_shader_changed");
+ }
+#endif
+ shader=p_shader;
+
+#ifdef TOOLS_ENABLED
+
+ if (shader.is_valid()) {
+ shader->connect("changed",this,"_shader_changed");
+ }
+#endif
+
+ RID rid;
+ if (shader.is_valid())
+ rid=shader->get_rid();
+
+ VS::get_singleton()->canvas_item_material_set_shader(material,rid);
+ _change_notify(); //properties for shader exposed
+ emit_changed();
+}
+
+Ref<Shader> CanvasItemMaterial::get_shader() const{
+
+ return shader;
+}
+
+void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){
+
+ VS::get_singleton()->canvas_item_material_set_shader_param(material,p_param,p_value);
+}
+
+Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{
+
+ return VS::get_singleton()->canvas_item_material_get_shader_param(material,p_param);
+}
+
+void CanvasItemMaterial::_shader_changed() {
+
+
+}
+
+RID CanvasItemMaterial::get_rid() const {
+
+ return material;
+}
+
+void CanvasItemMaterial::set_unshaded(bool p_unshaded) {
+
+ unshaded=p_unshaded;
+ VS::get_singleton()->canvas_item_material_set_unshaded(material,p_unshaded);
+}
+
+bool CanvasItemMaterial::is_unshaded() const{
+
+ return unshaded;
+}
+
+void CanvasItemMaterial::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader);
+ ObjectTypeDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader);
+ ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param);
+ ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param);
+ ObjectTypeDB::bind_method(_MD("set_unshaded","unshaded"),&CanvasItemMaterial::set_unshaded);
+ ObjectTypeDB::bind_method(_MD("is_unshaded"),&CanvasItemMaterial::is_unshaded);
+
+}
+
+void CanvasItemMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
+
+ String f = p_function.operator String();
+ if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) {
+
+ if (shader.is_valid()) {
+ List<PropertyInfo> pl;
+ shader->get_param_list(&pl);
+ for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
+ r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
+ }
+ }
+ }
+ Resource::get_argument_options(p_function,p_idx,r_options);
+}
+
+CanvasItemMaterial::CanvasItemMaterial() {
+
+ material=VS::get_singleton()->canvas_item_material_create();
+ unshaded=false;
+}
+
+CanvasItemMaterial::~CanvasItemMaterial(){
+
+ VS::get_singleton()->free(material);
+}
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////
+
+
+
bool CanvasItem::is_visible() const {
if (!is_inside_tree())
@@ -458,6 +644,16 @@ CanvasItem::BlendMode CanvasItem::get_blend_mode() const {
return blend_mode;
}
+void CanvasItem::set_light_mask(int p_light_mask) {
+
+ light_mask=p_light_mask;
+ VS::get_singleton()->canvas_item_set_light_mask(canvas_item,p_light_mask);
+}
+
+int CanvasItem::get_light_mask() const{
+
+ return light_mask;
+}
void CanvasItem::item_rect_changed() {
@@ -511,7 +707,7 @@ void CanvasItem::draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos)
p_texture->draw(canvas_item,p_pos);
}
-void CanvasItem::draw_texture_rect(const Ref<Texture>& p_texture,const Rect2& p_rect, bool p_tile,const Color& p_modulate) {
+void CanvasItem::draw_texture_rect(const Ref<Texture>& p_texture,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) {
if (!drawing) {
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
@@ -519,17 +715,17 @@ void CanvasItem::draw_texture_rect(const Ref<Texture>& p_texture,const Rect2& p_
}
ERR_FAIL_COND(p_texture.is_null());
- p_texture->draw_rect(canvas_item,p_rect,p_tile,p_modulate);
+ p_texture->draw_rect(canvas_item,p_rect,p_tile,p_modulate,p_transpose);
}
-void CanvasItem::draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) {
+void CanvasItem::draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) {
if (!drawing) {
ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL();
}
ERR_FAIL_COND(p_texture.is_null());
- p_texture->draw_rect_region(canvas_item,p_rect,p_src_rect,p_modulate);
+ p_texture->draw_rect_region(canvas_item,p_rect,p_src_rect,p_modulate,p_transpose);
}
void CanvasItem::draw_style_box(const Ref<StyleBox>& p_style_box,const Rect2& p_rect) {
@@ -720,95 +916,36 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{
return behind;
}
-void CanvasItem::set_shader(const Ref<Shader>& p_shader) {
-
- ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM);
-
-#ifdef TOOLS_ENABLED
+void CanvasItem::set_material(const Ref<CanvasItemMaterial>& p_material) {
- if (shader.is_valid()) {
- shader->disconnect("changed",this,"_shader_changed");
- }
-#endif
- shader=p_shader;
-
-#ifdef TOOLS_ENABLED
-
- if (shader.is_valid()) {
- shader->connect("changed",this,"_shader_changed");
- }
-#endif
+ material=p_material;
RID rid;
- if (shader.is_valid())
- rid=shader->get_rid();
- VS::get_singleton()->canvas_item_set_shader(canvas_item,rid);
- _change_notify(); //properties for shader exposed
+ if (material.is_valid())
+ rid=material->get_rid();
+ VS::get_singleton()->canvas_item_set_material(canvas_item,rid);
+ _change_notify(); //properties for material exposed
}
-void CanvasItem::set_use_parent_shader(bool p_use_parent_shader) {
+void CanvasItem::set_use_parent_material(bool p_use_parent_material) {
- use_parent_shader=p_use_parent_shader;
- VS::get_singleton()->canvas_item_set_use_parent_shader(canvas_item,p_use_parent_shader);
+ use_parent_material=p_use_parent_material;
+ VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item,p_use_parent_material);
}
-bool CanvasItem::get_use_parent_shader() const{
+bool CanvasItem::get_use_parent_material() const{
- return use_parent_shader;
+ return use_parent_material;
}
-Ref<Shader> CanvasItem::get_shader() const{
+Ref<CanvasItemMaterial> CanvasItem::get_material() const{
- return shader;
-}
-
-void CanvasItem::set_shader_param(const StringName& p_param,const Variant& p_value) {
-
- VS::get_singleton()->canvas_item_set_shader_param(canvas_item,p_param,p_value);
-}
-
-Variant CanvasItem::get_shader_param(const StringName& p_param) const {
-
- return VS::get_singleton()->canvas_item_get_shader_param(canvas_item,p_param);
-}
-
-bool CanvasItem::_set(const StringName& p_name, const Variant& p_value) {
-
- if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
- if (pr) {
- set_shader_param(pr,p_value);
- return true;
- }
- }
- return false;
+ return material;
}
-bool CanvasItem::_get(const StringName& p_name,Variant &r_ret) const{
- if (shader.is_valid()) {
- StringName pr = shader->remap_param(p_name);
- if (pr) {
- r_ret=get_shader_param(pr);
- return true;
- }
- }
- return false;
-}
-void CanvasItem::_get_property_list( List<PropertyInfo> *p_list) const{
- if (shader.is_valid()) {
- shader->get_param_list(p_list);
- }
-}
-
-#ifdef TOOLS_ENABLED
-void CanvasItem::_shader_changed() {
-
- _change_notify();
-}
-#endif
void CanvasItem::_bind_methods() {
@@ -840,19 +977,19 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_blend_mode","blend_mode"),&CanvasItem::set_blend_mode);
ObjectTypeDB::bind_method(_MD("get_blend_mode"),&CanvasItem::get_blend_mode);
+ ObjectTypeDB::bind_method(_MD("set_light_mask","light_mask"),&CanvasItem::set_light_mask);
+ ObjectTypeDB::bind_method(_MD("get_light_mask"),&CanvasItem::get_light_mask);
+
ObjectTypeDB::bind_method(_MD("set_opacity","opacity"),&CanvasItem::set_opacity);
ObjectTypeDB::bind_method(_MD("get_opacity"),&CanvasItem::get_opacity);
ObjectTypeDB::bind_method(_MD("set_self_opacity","self_opacity"),&CanvasItem::set_self_opacity);
ObjectTypeDB::bind_method(_MD("get_self_opacity"),&CanvasItem::get_self_opacity);
- ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enabe"),&CanvasItem::set_draw_behind_parent);
+ ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enable"),&CanvasItem::set_draw_behind_parent);
ObjectTypeDB::bind_method(_MD("is_draw_behind_parent_enabled"),&CanvasItem::is_draw_behind_parent_enabled);
ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top);
-#ifdef TOOLS_ENABLED
- ObjectTypeDB::bind_method(_MD("_shader_changed"),&CanvasItem::_shader_changed);
-#endif
//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0));
@@ -871,16 +1008,18 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform);
ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
ObjectTypeDB::bind_method(_MD("get_global_transform"),&CanvasItem::get_global_transform);
+ ObjectTypeDB::bind_method(_MD("get_global_transform_with_canvas"),&CanvasItem::get_global_transform_with_canvas);
ObjectTypeDB::bind_method(_MD("get_viewport_transform"),&CanvasItem::get_viewport_transform);
ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
ObjectTypeDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas);
ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
//ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
- ObjectTypeDB::bind_method(_MD("set_shader","shader"),&CanvasItem::set_shader);
- ObjectTypeDB::bind_method(_MD("get_shader"),&CanvasItem::get_shader);
- ObjectTypeDB::bind_method(_MD("set_use_parent_shader","enable"),&CanvasItem::set_use_parent_shader);
- ObjectTypeDB::bind_method(_MD("get_use_parent_shader"),&CanvasItem::get_use_parent_shader);
+ ObjectTypeDB::bind_method(_MD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material);
+ ObjectTypeDB::bind_method(_MD("get_material:CanvasItemMaterial"),&CanvasItem::get_material);
+
+ ObjectTypeDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material);
+ ObjectTypeDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material);
BIND_VMETHOD(MethodInfo("_draw"));
@@ -891,8 +1030,9 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"shader/shader",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"), _SCS("set_shader"),_SCS("get_shader") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"shader/use_parent"), _SCS("set_use_parent_shader"),_SCS("get_use_parent_shader") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material/material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"material/use_parent"), _SCS("set_use_parent_material"),_SCS("get_use_parent_material") );
//exporting these two things doesn't really make much sense i think
//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") );
//ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled"));
@@ -969,8 +1109,9 @@ CanvasItem::CanvasItem() : xform_change(this) {
block_transform_notify=false;
// viewport=NULL;
canvas_layer=NULL;
- use_parent_shader;
+ use_parent_material=false;
global_invalid=true;
+ light_mask=1;
C=NULL;
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index ed3ade9df2..0c7be261ab 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -40,6 +40,41 @@ class Font;
class StyleBox;
+class CanvasItemMaterial : public Resource{
+
+ OBJ_TYPE(CanvasItemMaterial,Resource);
+ RID material;
+ Ref<Shader> shader;
+ bool unshaded;
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+ void _shader_changed();
+ static void _bind_methods();
+
+ void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
+
+public:
+
+ void set_shader(const Ref<Shader>& p_shader);
+ Ref<Shader> get_shader() const;
+
+ void set_shader_param(const StringName& p_param,const Variant& p_value);
+ Variant get_shader_param(const StringName& p_param) const;
+
+ void set_unshaded(bool p_unshaded);
+ bool is_unshaded() const;
+
+ virtual RID get_rid() const;
+ CanvasItemMaterial();
+ ~CanvasItemMaterial();
+};
+
+
class CanvasItem : public Node {
OBJ_TYPE( CanvasItem, Node );
@@ -71,6 +106,7 @@ private:
List<CanvasItem*>::Element *C;
BlendMode blend_mode;
+ int light_mask;
bool first_draw;
bool hidden;
@@ -80,9 +116,9 @@ private:
bool drawing;
bool block_transform_notify;
bool behind;
+ bool use_parent_material;
- bool use_parent_shader;
- Ref<Shader> shader;
+ Ref<CanvasItemMaterial> material;
mutable Matrix32 global_transform;
mutable bool global_invalid;
@@ -103,9 +139,6 @@ private:
void _queue_sort_children();
void _sort_children();
-#ifdef TOOLS_ENABLED
- void _shader_changed();
-#endif
void _notify_transform(CanvasItem *p_node);
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
@@ -113,11 +146,6 @@ private:
protected:
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
-
_FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); }
void item_rect_changed();
@@ -158,6 +186,9 @@ public:
void set_blend_mode(BlendMode p_blend_mode);
BlendMode get_blend_mode() const;
+ void set_light_mask(int p_light_mask);
+ int get_light_mask() const;
+
void set_opacity(float p_opacity);
float get_opacity() const;
@@ -170,8 +201,8 @@ public:
void draw_rect(const Rect2& p_rect, const Color& p_color);
void draw_circle(const Point2& p_pos, float p_radius, const Color& p_color);
void draw_texture(const Ref<Texture>& p_texture,const Point2& p_pos);
- void draw_texture_rect(const Ref<Texture>& p_texture, const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1));
- void draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1));
+ void draw_texture_rect(const Ref<Texture>& p_texture, const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false);
+ void draw_texture_rect_region(const Ref<Texture>& p_texture,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false);
void draw_style_box(const Ref<StyleBox>& p_style_box,const Rect2& p_rect);
void draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, Ref<Texture> p_texture=Ref<Texture>(),float p_width=1);
void draw_polygon(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), Ref<Texture> p_texture=Ref<Texture>());
@@ -212,14 +243,12 @@ public:
RID get_canvas() const;
Ref<World2D> get_world_2d() const;
- void set_shader(const Ref<Shader>& p_shader);
- Ref<Shader> get_shader() const;
+ void set_material(const Ref<CanvasItemMaterial>& p_material);
+ Ref<CanvasItemMaterial> get_material() const;
- void set_use_parent_shader(bool p_use_parent_shader);
- bool get_use_parent_shader() const;
+ void set_use_parent_material(bool p_use_parent_material);
+ bool get_use_parent_material() const;
- void set_shader_param(const StringName& p_param,const Variant& p_value);
- Variant get_shader_param(const StringName& p_param) const;
CanvasItem();
~CanvasItem();
diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp
new file mode 100644
index 0000000000..82dd8012a5
--- /dev/null
+++ b/scene/2d/canvas_modulate.cpp
@@ -0,0 +1,46 @@
+#include "canvas_modulate.h"
+
+
+void CanvasModulate::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_CANVAS) {
+
+ VS::get_singleton()->canvas_set_modulate(get_canvas(),color);
+ } else if (p_what==NOTIFICATION_EXIT_CANVAS) {
+
+ VS::get_singleton()->canvas_set_modulate(get_canvas(),Color(1,1,1,1));
+ }
+}
+
+void CanvasModulate::_bind_methods(){
+
+ ObjectTypeDB::bind_method(_MD("set_color","color"),&CanvasModulate::set_color);
+ ObjectTypeDB::bind_method(_MD("get_color"),&CanvasModulate::get_color);
+
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
+}
+
+
+void CanvasModulate::set_color(const Color& p_color){
+
+ color=p_color;
+ if (is_inside_tree()) {
+ VS::get_singleton()->canvas_set_modulate(get_canvas(),color);
+ }
+}
+Color CanvasModulate::get_color() const {
+
+ return color;
+}
+
+
+CanvasModulate::CanvasModulate()
+{
+ color=Color(1,1,1,1);
+}
+
+CanvasModulate::~CanvasModulate()
+{
+
+}
+
diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h
new file mode 100644
index 0000000000..a6894f29c2
--- /dev/null
+++ b/scene/2d/canvas_modulate.h
@@ -0,0 +1,23 @@
+#ifndef CANVASMODULATE_H
+#define CANVASMODULATE_H
+
+#include "scene/2d/node_2d.h"
+
+class CanvasModulate : public Node2D {
+
+ OBJ_TYPE(CanvasModulate,Node2D);
+
+ Color color;
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_color(const Color& p_color);
+ Color get_color() const;
+
+ CanvasModulate();
+ ~CanvasModulate();
+};
+
+#endif // CANVASMODULATE_H
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
new file mode 100644
index 0000000000..93be0c397f
--- /dev/null
+++ b/scene/2d/light_2d.cpp
@@ -0,0 +1,300 @@
+#include "light_2d.h"
+#include "servers/visual_server.h"
+
+void Light2D::edit_set_pivot(const Point2& p_pivot) {
+
+ set_texture_offset(p_pivot);
+
+}
+
+Point2 Light2D::edit_get_pivot() const {
+
+ return get_texture_offset();
+}
+bool Light2D::edit_has_pivot() const {
+
+ return true;
+}
+
+Rect2 Light2D::get_item_rect() const {
+
+ if (texture.is_null())
+ return Rect2(0,0,1,1);
+
+ Size2i s;
+
+ s = texture->get_size();
+ Point2i ofs=texture_offset;
+ ofs-=s/2;
+
+ if (s==Size2(0,0))
+ s=Size2(1,1);
+
+ return Rect2(ofs,s);
+}
+
+
+void Light2D::set_enabled( bool p_enabled) {
+
+ VS::get_singleton()->canvas_light_set_enabled(canvas_light,p_enabled);
+ enabled=p_enabled;
+}
+
+bool Light2D::is_enabled() const {
+
+ return enabled;
+}
+
+void Light2D::set_texture( const Ref<Texture>& p_texture) {
+
+ texture=p_texture;
+ if (texture.is_valid())
+ VS::get_singleton()->canvas_light_set_texture(canvas_light,texture->get_rid());
+ else
+ VS::get_singleton()->canvas_light_set_texture(canvas_light,RID());
+}
+
+Ref<Texture> Light2D::get_texture() const {
+
+ return texture;
+}
+
+void Light2D::set_texture_offset( const Vector2& p_offset) {
+
+ texture_offset=p_offset;
+ VS::get_singleton()->canvas_light_set_texture_offset(canvas_light,texture_offset);
+}
+
+Vector2 Light2D::get_texture_offset() const {
+
+ return texture_offset;
+}
+
+void Light2D::set_color( const Color& p_color) {
+
+ color=p_color;
+ VS::get_singleton()->canvas_light_set_color(canvas_light,color);
+
+}
+Color Light2D::get_color() const {
+
+ return color;
+}
+
+void Light2D::set_height( float p_height) {
+
+ height=p_height;
+ VS::get_singleton()->canvas_light_set_height(canvas_light,height);
+
+}
+float Light2D::get_height() const {
+
+ return height;
+}
+
+void Light2D::set_z_range_min( int p_min_z) {
+
+ z_min=p_min_z;
+ VS::get_singleton()->canvas_light_set_z_range(canvas_light,z_min,z_max);
+
+}
+int Light2D::get_z_range_min() const {
+
+ return z_min;
+}
+
+void Light2D::set_z_range_max( int p_max_z) {
+
+ z_max=p_max_z;
+ VS::get_singleton()->canvas_light_set_z_range(canvas_light,z_min,z_max);
+
+}
+int Light2D::get_z_range_max() const {
+
+ return z_max;
+}
+
+void Light2D::set_layer_range_min( int p_min_layer) {
+
+ layer_min=p_min_layer;
+ VS::get_singleton()->canvas_light_set_layer_range(canvas_light,layer_min,layer_max);
+
+}
+int Light2D::get_layer_range_min() const {
+
+ return layer_min;
+}
+
+void Light2D::set_layer_range_max( int p_max_layer) {
+
+ layer_max=p_max_layer;
+ VS::get_singleton()->canvas_light_set_layer_range(canvas_light,layer_min,layer_max);
+
+}
+int Light2D::get_layer_range_max() const {
+
+ return layer_max;
+}
+
+void Light2D::set_item_mask( int p_mask) {
+
+ item_mask=p_mask;
+ VS::get_singleton()->canvas_light_set_item_mask(canvas_light,item_mask);
+
+}
+
+int Light2D::get_item_mask() const {
+
+ return item_mask;
+}
+
+void Light2D::set_subtract_mode( bool p_enable ) {
+
+ subtract_mode=p_enable;
+ VS::get_singleton()->canvas_light_set_subtract_mode(canvas_light,p_enable);
+}
+
+bool Light2D::get_subtract_mode() const {
+
+ return subtract_mode;
+}
+
+void Light2D::set_shadow_enabled( bool p_enabled) {
+
+ shadow=p_enabled;
+ VS::get_singleton()->canvas_light_set_shadow_enabled(canvas_light,shadow);
+
+}
+bool Light2D::is_shadow_enabled() const {
+
+ return shadow;
+}
+
+void Light2D::set_shadow_buffer_size( int p_size ) {
+
+ shadow_buffer_size=p_size;
+ VS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light,shadow_buffer_size);
+}
+
+int Light2D::get_shadow_buffer_size() const {
+
+ return shadow_buffer_size;
+}
+
+void Light2D::set_shadow_esm_multiplier( float p_multiplier) {
+
+ shadow_esm_multiplier=p_multiplier;
+ VS::get_singleton()->canvas_light_set_shadow_esm_multiplier(canvas_light,p_multiplier);
+}
+
+float Light2D::get_shadow_esm_multiplier() const{
+
+ return shadow_esm_multiplier;
+}
+
+
+void Light2D::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ VS::get_singleton()->canvas_light_attach_to_canvas( canvas_light, get_canvas() );
+ }
+
+ if (p_what==NOTIFICATION_TRANSFORM_CHANGED) {
+
+ VS::get_singleton()->canvas_light_set_transform( canvas_light, get_global_transform());
+ }
+
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+ VS::get_singleton()->canvas_light_attach_to_canvas( canvas_light, RID() );
+ }
+
+}
+
+void Light2D::_bind_methods() {
+
+
+ ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&Light2D::set_enabled);
+ ObjectTypeDB::bind_method(_MD("is_enabled"),&Light2D::is_enabled);
+
+ ObjectTypeDB::bind_method(_MD("set_texture","texture"),&Light2D::set_texture);
+ ObjectTypeDB::bind_method(_MD("get_texture"),&Light2D::get_texture);
+
+ ObjectTypeDB::bind_method(_MD("set_texture_offset","texture_offset"),&Light2D::set_texture_offset);
+ ObjectTypeDB::bind_method(_MD("get_texture_offset"),&Light2D::get_texture_offset);
+
+ ObjectTypeDB::bind_method(_MD("set_color","color"),&Light2D::set_color);
+ ObjectTypeDB::bind_method(_MD("get_color"),&Light2D::get_color);
+
+ ObjectTypeDB::bind_method(_MD("set_height","height"),&Light2D::set_height);
+ ObjectTypeDB::bind_method(_MD("get_height"),&Light2D::get_height);
+
+ ObjectTypeDB::bind_method(_MD("set_z_range_min","z"),&Light2D::set_z_range_min);
+ ObjectTypeDB::bind_method(_MD("get_z_range_min"),&Light2D::get_z_range_min);
+
+ ObjectTypeDB::bind_method(_MD("set_z_range_max","z"),&Light2D::set_z_range_max);
+ ObjectTypeDB::bind_method(_MD("get_z_range_max"),&Light2D::get_z_range_max);
+
+ ObjectTypeDB::bind_method(_MD("set_layer_range_min","layer"),&Light2D::set_layer_range_min);
+ ObjectTypeDB::bind_method(_MD("get_layer_range_min"),&Light2D::get_layer_range_min);
+
+ ObjectTypeDB::bind_method(_MD("set_layer_range_max","layer"),&Light2D::set_layer_range_max);
+ ObjectTypeDB::bind_method(_MD("get_layer_range_max"),&Light2D::get_layer_range_max);
+
+
+ ObjectTypeDB::bind_method(_MD("set_item_mask","item_mask"),&Light2D::set_item_mask);
+ ObjectTypeDB::bind_method(_MD("get_item_mask"),&Light2D::get_item_mask);
+
+ ObjectTypeDB::bind_method(_MD("set_subtract_mode","enable"),&Light2D::set_subtract_mode);
+ ObjectTypeDB::bind_method(_MD("get_subtract_mode"),&Light2D::get_subtract_mode);
+
+ ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
+ ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
+
+ ObjectTypeDB::bind_method(_MD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size);
+ ObjectTypeDB::bind_method(_MD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size);
+
+ ObjectTypeDB::bind_method(_MD("set_shadow_esm_multiplier","multiplier"),&Light2D::set_shadow_esm_multiplier);
+ ObjectTypeDB::bind_method(_MD("get_shadow_esm_multiplier"),&Light2D::get_shadow_esm_multiplier);
+
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
+ ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"subtract"),_SCS("set_subtract_mode"),_SCS("get_subtract_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow/enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier"));
+
+
+}
+
+Light2D::Light2D() {
+
+ canvas_light=VisualServer::get_singleton()->canvas_light_create();
+ enabled=true;
+ shadow=false;
+ color=Color(1,1,1);
+ height=0;
+ z_min=-1024;
+ z_max=1024;
+ layer_min=0;
+ layer_max=0;
+ item_mask=1;
+ subtract_mode=false;
+ shadow_buffer_size=2048;
+ shadow_esm_multiplier=80;
+
+}
+
+Light2D::~Light2D() {
+
+ VisualServer::get_singleton()->free(canvas_light);
+}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
new file mode 100644
index 0000000000..89f351c3cd
--- /dev/null
+++ b/scene/2d/light_2d.h
@@ -0,0 +1,86 @@
+#ifndef LIGHT_2D_H
+#define LIGHT_2D_H
+
+#include "scene/2d/node_2d.h"
+
+class Light2D : public Node2D {
+
+ OBJ_TYPE(Light2D,Node2D);
+private:
+ RID canvas_light;
+ bool enabled;
+ bool shadow;
+ Color color;
+ float height;
+ int z_min;
+ int z_max;
+ int layer_min;
+ int layer_max;
+ int item_mask;
+ int shadow_buffer_size;
+ float shadow_esm_multiplier;
+ bool subtract_mode;
+ Ref<Texture> texture;
+ Vector2 texture_offset;
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+
+ virtual void edit_set_pivot(const Point2& p_pivot);
+ virtual Point2 edit_get_pivot() const;
+ virtual bool edit_has_pivot() const;
+
+ void set_enabled( bool p_enabled);
+ bool is_enabled() const;
+
+ void set_texture( const Ref<Texture>& p_texture);
+ Ref<Texture> get_texture() const;
+
+ void set_texture_offset( const Vector2& p_offset);
+ Vector2 get_texture_offset() const;
+
+ void set_color( const Color& p_color);
+ Color get_color() const;
+
+ void set_height( float p_height);
+ float get_height() const;
+
+ void set_z_range_min( int p_min_z);
+ int get_z_range_min() const;
+
+ void set_z_range_max( int p_max_z);
+ int get_z_range_max() const;
+
+ void set_layer_range_min( int p_min_layer);
+ int get_layer_range_min() const;
+
+ void set_layer_range_max( int p_max_layer);
+ int get_layer_range_max() const;
+
+ void set_item_mask( int p_mask);
+ int get_item_mask() const;
+
+ void set_subtract_mode( bool p_enable );
+ bool get_subtract_mode() const;
+
+ void set_shadow_enabled( bool p_enabled);
+ bool is_shadow_enabled() const;
+
+ void set_shadow_buffer_size( int p_size );
+ int get_shadow_buffer_size() const;
+
+ void set_shadow_esm_multiplier( float p_multiplier);
+ float get_shadow_esm_multiplier() const;
+
+ virtual Rect2 get_item_rect() const;
+
+ Light2D();
+ ~Light2D();
+};
+
+
+#endif // LIGHT_2D_H
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
new file mode 100644
index 0000000000..186ea2e248
--- /dev/null
+++ b/scene/2d/light_occluder_2d.cpp
@@ -0,0 +1,201 @@
+#include "light_occluder_2d.h"
+
+
+void OccluderPolygon2D::set_polygon(const DVector<Vector2>& p_polygon) {
+
+ polygon=p_polygon;
+ VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,p_polygon,closed);
+ emit_changed();
+}
+
+DVector<Vector2> OccluderPolygon2D::get_polygon() const{
+
+ return polygon;
+}
+
+void OccluderPolygon2D::set_closed(bool p_closed) {
+
+ if (closed==p_closed)
+ return;
+ closed=p_closed;
+ VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,polygon,closed);
+ emit_changed();
+}
+
+bool OccluderPolygon2D::is_closed() const{
+
+ return closed;
+}
+
+void OccluderPolygon2D::set_cull_mode(CullMode p_mode){
+
+ cull=p_mode;
+ VS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon,VS::CanvasOccluderPolygonCullMode(p_mode));
+}
+
+OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const{
+
+ return cull;
+}
+
+
+RID OccluderPolygon2D::get_rid() const {
+
+ return occ_polygon;
+}
+
+void OccluderPolygon2D::_bind_methods() {
+
+
+ ObjectTypeDB::bind_method(_MD("set_closed","closed"),&OccluderPolygon2D::set_closed);
+ ObjectTypeDB::bind_method(_MD("is_closed"),&OccluderPolygon2D::is_closed);
+
+ ObjectTypeDB::bind_method(_MD("set_cull_mode","cull_mode"),&OccluderPolygon2D::set_cull_mode);
+ ObjectTypeDB::bind_method(_MD("get_cull_mode"),&OccluderPolygon2D::get_cull_mode);
+
+ ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon);
+ ObjectTypeDB::bind_method(_MD("get_polygon"),&OccluderPolygon2D::get_polygon);
+
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),_SCS("set_closed"),_SCS("is_closed"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),_SCS("set_cull_mode"),_SCS("get_cull_mode"));
+
+ BIND_CONSTANT(CULL_DISABLED);
+ BIND_CONSTANT(CULL_CLOCKWISE);
+ BIND_CONSTANT(CULL_COUNTER_CLOCKWISE);
+}
+
+
+OccluderPolygon2D::OccluderPolygon2D() {
+
+ occ_polygon=VS::get_singleton()->canvas_occluder_polygon_create();
+ closed=true;
+ cull=CULL_DISABLED;
+}
+
+OccluderPolygon2D::~OccluderPolygon2D() {
+
+ VS::get_singleton()->free(occ_polygon);
+}
+
+#ifdef DEBUG_ENABLED
+void LightOccluder2D::_poly_changed() {
+
+ update();
+}
+#endif
+
+
+void LightOccluder2D::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_CANVAS) {
+
+ VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,get_canvas());
+ VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
+
+ }
+ if (p_what==NOTIFICATION_TRANSFORM_CHANGED) {
+
+ VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform());
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ if (get_tree()->is_editor_hint()) {
+
+ if (occluder_polygon.is_valid()) {
+
+ DVector<Vector2> poly = occluder_polygon->get_polygon();
+
+ if (poly.size()) {
+ if (occluder_polygon->is_closed()) {
+ Vector<Color> color;
+ color.push_back(Color(0,0,0,0.6));
+ draw_polygon(Variant(poly),color);
+ } else {
+
+ int ps=poly.size();
+ DVector<Vector2>::Read r = poly.read();
+ for(int i=0;i<ps-1;i++) {
+
+ draw_line(r[i],r[i+1],Color(0,0,0,0.6),3);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if (p_what==NOTIFICATION_EXIT_CANVAS) {
+
+ VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,RID());
+ }
+
+
+}
+
+void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon) {
+
+#ifdef DEBUG_ENABLED
+ if (occluder_polygon.is_valid())
+ occluder_polygon->disconnect("changed",this,"_poly_changed");
+#endif
+ occluder_polygon=p_polygon;
+
+ if (occluder_polygon.is_valid())
+ VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,occluder_polygon->get_rid());
+ else
+ VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,RID());
+
+#ifdef DEBUG_ENABLED
+ if (occluder_polygon.is_valid())
+ occluder_polygon->connect("changed",this,"_poly_changed");
+ update();
+#endif
+
+}
+
+Ref<OccluderPolygon2D> LightOccluder2D::get_occluder_polygon() const {
+
+ return occluder_polygon;
+}
+
+void LightOccluder2D::set_occluder_light_mask(int p_mask) {
+
+ mask=p_mask;
+ VS::get_singleton()->canvas_light_occluder_set_light_mask(occluder,mask);
+}
+
+int LightOccluder2D::get_occluder_light_mask() const{
+
+ return mask;
+}
+
+void LightOccluder2D::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_occluder_polygon","polygon:OccluderPolygon2D"),&LightOccluder2D::set_occluder_polygon);
+ ObjectTypeDB::bind_method(_MD("get_occluder_polygon:OccluderPolygon2D"),&LightOccluder2D::get_occluder_polygon);
+
+ ObjectTypeDB::bind_method(_MD("set_occluder_light_mask","mask"),&LightOccluder2D::set_occluder_light_mask);
+ ObjectTypeDB::bind_method(_MD("get_occluder_light_mask"),&LightOccluder2D::get_occluder_light_mask);
+
+#ifdef DEBUG_ENABLED
+ ObjectTypeDB::bind_method("_poly_changed",&LightOccluder2D::_poly_changed);
+#endif
+
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"),_SCS("set_occluder_polygon"),_SCS("get_occluder_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask"));
+}
+
+LightOccluder2D::LightOccluder2D() {
+
+ occluder=VS::get_singleton()->canvas_light_occluder_create();
+ mask=1;
+}
+
+LightOccluder2D::~LightOccluder2D() {
+
+ VS::get_singleton()->free(occluder);
+}
+
diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h
new file mode 100644
index 0000000000..0343e3697e
--- /dev/null
+++ b/scene/2d/light_occluder_2d.h
@@ -0,0 +1,73 @@
+#ifndef LIGHTOCCLUDER2D_H
+#define LIGHTOCCLUDER2D_H
+
+#include "scene/2d/node_2d.h"
+
+class OccluderPolygon2D : public Resource {
+
+ OBJ_TYPE(OccluderPolygon2D,Resource);
+public:
+
+ enum CullMode {
+ CULL_DISABLED,
+ CULL_CLOCKWISE,
+ CULL_COUNTER_CLOCKWISE
+ };
+private:
+
+
+ RID occ_polygon;
+ DVector<Vector2> polygon;
+ bool closed;
+ CullMode cull;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ void set_polygon(const DVector<Vector2>& p_polygon);
+ DVector<Vector2> get_polygon() const;
+
+ void set_closed(bool p_closed);
+ bool is_closed() const;
+
+ void set_cull_mode(CullMode p_mode);
+ CullMode get_cull_mode() const;
+
+ virtual RID get_rid() const;
+ OccluderPolygon2D();
+ ~OccluderPolygon2D();
+
+};
+
+VARIANT_ENUM_CAST(OccluderPolygon2D::CullMode);
+
+class LightOccluder2D : public Node2D {
+ OBJ_TYPE(LightOccluder2D,Node2D);
+
+ RID occluder;
+ bool enabled;
+ int mask;
+ Ref<OccluderPolygon2D> occluder_polygon;
+
+#ifdef DEBUG_ENABLED
+ void _poly_changed();
+#endif
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon);
+ Ref<OccluderPolygon2D> get_occluder_polygon() const;
+
+ void set_occluder_light_mask(int p_mask);
+ int get_occluder_light_mask() const;
+
+ LightOccluder2D();
+ ~LightOccluder2D();
+};
+
+#endif // LIGHTOCCLUDER2D_H
diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp
new file mode 100644
index 0000000000..46af68444a
--- /dev/null
+++ b/scene/2d/navigation2d.cpp
@@ -0,0 +1,660 @@
+#include "navigation2d.h"
+
+#define USE_ENTRY_POINT
+
+void Navigation2D::_navpoly_link(int p_id) {
+
+ ERR_FAIL_COND(!navpoly_map.has(p_id));
+ NavMesh &nm=navpoly_map[p_id];
+ ERR_FAIL_COND(nm.linked);
+
+ print_line("LINK");
+
+ DVector<Vector2> vertices=nm.navpoly->get_vertices();
+ int len = vertices.size();
+ if (len==0)
+ return;
+
+ DVector<Vector2>::Read r=vertices.read();
+
+ for(int i=0;i<nm.navpoly->get_polygon_count();i++) {
+
+ //build
+
+ List<Polygon>::Element *P=nm.polygons.push_back(Polygon());
+ Polygon &p=P->get();
+ p.owner=&nm;
+
+ Vector<int> poly = nm.navpoly->get_polygon(i);
+ int plen=poly.size();
+ const int *indices=poly.ptr();
+ bool valid=true;
+ p.edges.resize(plen);
+
+ Vector2 center;
+
+ for(int j=0;j<plen;j++) {
+
+ int idx = indices[j];
+ if (idx<0 || idx>=len) {
+ valid=false;
+ break;
+ }
+
+ Polygon::Edge e;
+ Vector2 ep=nm.xform.xform(r[idx]);
+ center+=ep;
+ e.point=_get_point(ep);
+ p.edges[j]=e;
+ }
+
+ if (!valid) {
+ nm.polygons.pop_back();
+ ERR_CONTINUE(!valid);
+ continue;
+ }
+
+ p.center=center/plen;
+
+ //connect
+
+ for(int j=0;j<plen;j++) {
+
+ int next = (j+1)%plen;
+ EdgeKey ek(p.edges[j].point,p.edges[next].point);
+
+ Map<EdgeKey,Connection>::Element *C=connections.find(ek);
+ if (!C) {
+
+ Connection c;
+ c.A=&p;
+ c.A_edge=j;
+ c.B=NULL;
+ c.B_edge=-1;
+ connections[ek]=c;
+ } else {
+
+ if (C->get().B!=NULL) {
+ print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b));
+ }
+ ERR_CONTINUE(C->get().B!=NULL); //wut
+
+ C->get().B=&p;
+ C->get().B_edge=j;
+ C->get().A->edges[C->get().A_edge].C=&p;
+ C->get().A->edges[C->get().A_edge].C_edge=j;;
+ p.edges[j].C=C->get().A;
+ p.edges[j].C_edge=C->get().A_edge;
+ //connection successful.
+ }
+ }
+ }
+
+ nm.linked=true;
+
+}
+
+
+void Navigation2D::_navpoly_unlink(int p_id) {
+
+ ERR_FAIL_COND(!navpoly_map.has(p_id));
+ NavMesh &nm=navpoly_map[p_id];
+ ERR_FAIL_COND(!nm.linked);
+
+ print_line("UNLINK");
+
+ for (List<Polygon>::Element *E=nm.polygons.front();E;E=E->next()) {
+
+
+ Polygon &p=E->get();
+
+ int ec = p.edges.size();
+ Polygon::Edge *edges=p.edges.ptr();
+
+ for(int i=0;i<ec;i++) {
+ int next = (i+1)%ec;
+
+ EdgeKey ek(edges[i].point,edges[next].point);
+ Map<EdgeKey,Connection>::Element *C=connections.find(ek);
+ ERR_CONTINUE(!C);
+ if (C->get().B) {
+ //disconnect
+
+ C->get().B->edges[C->get().B_edge].C=NULL;
+ C->get().B->edges[C->get().B_edge].C_edge=-1;
+ C->get().A->edges[C->get().A_edge].C=NULL;
+ C->get().A->edges[C->get().A_edge].C_edge=-1;
+
+ if (C->get().A==&E->get()) {
+
+ C->get().A=C->get().B;
+ C->get().A_edge=C->get().B_edge;
+ }
+ C->get().B=NULL;
+ C->get().B_edge=-1;
+
+ } else {
+ connections.erase(C);
+ //erase
+ }
+ }
+ }
+
+ nm.polygons.clear();
+
+ nm.linked=false;
+
+
+}
+
+
+int Navigation2D::navpoly_create(const Ref<NavigationPolygon>& p_mesh, const Matrix32& p_xform, Object *p_owner) {
+
+ int id = last_id++;
+ NavMesh nm;
+ nm.linked=false;
+ nm.navpoly=p_mesh;
+ nm.xform=p_xform;
+ nm.owner=p_owner;
+ navpoly_map[id]=nm;
+
+ _navpoly_link(id);
+
+ return id;
+}
+
+void Navigation2D::navpoly_set_transform(int p_id, const Matrix32& p_xform){
+
+ ERR_FAIL_COND(!navpoly_map.has(p_id));
+ NavMesh &nm=navpoly_map[p_id];
+ if (nm.xform==p_xform)
+ return; //bleh
+ _navpoly_unlink(p_id);
+ nm.xform=p_xform;
+ _navpoly_link(p_id);
+
+
+
+}
+void Navigation2D::navpoly_remove(int p_id){
+
+ ERR_FAIL_COND(!navpoly_map.has(p_id));
+ _navpoly_unlink(p_id);
+ navpoly_map.erase(p_id);
+
+}
+#if 0
+void Navigation2D::_clip_path(Vector<Vector2>& path, Polygon *from_poly, const Vector2& p_to_point, Polygon* p_to_poly) {
+
+ Vector2 from = path[path.size()-1];
+
+ if (from.distance_to(p_to_point)<CMP_EPSILON)
+ return;
+ Plane cut_plane;
+ cut_plane.normal = (from-p_to_point).cross(up);
+ if (cut_plane.normal==Vector2())
+ return;
+ cut_plane.normal.normalize();
+ cut_plane.d = cut_plane.normal.dot(from);
+
+
+ while(from_poly!=p_to_poly) {
+
+ int pe = from_poly->prev_edge;
+ Vector2 a = _get_vertex(from_poly->edges[pe].point);
+ Vector2 b = _get_vertex(from_poly->edges[(pe+1)%from_poly->edges.size()].point);
+
+ from_poly=from_poly->edges[pe].C;
+ ERR_FAIL_COND(!from_poly);
+
+ if (a.distance_to(b)>CMP_EPSILON) {
+
+ Vector2 inters;
+ if (cut_plane.intersects_segment(a,b,&inters)) {
+ if (inters.distance_to(p_to_point)>CMP_EPSILON && inters.distance_to(path[path.size()-1])>CMP_EPSILON) {
+ path.push_back(inters);
+ }
+ }
+ }
+ }
+}
+#endif
+
+Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vector2& p_end, bool p_optimize) {
+
+
+ Polygon *begin_poly=NULL;
+ Polygon *end_poly=NULL;
+ Vector2 begin_point;
+ Vector2 end_point;
+ float begin_d=1e20;
+ float end_d=1e20;
+
+ //look for point inside triangle
+
+ for (Map<int,NavMesh>::Element*E=navpoly_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+
+ Polygon &p=F->get();
+ if (begin_d || end_d) {
+ for(int i=2;i<p.edges.size();i++) {
+
+ if (begin_d>0) {
+
+ if (Geometry::is_point_in_triangle(p_start,_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point))) {
+
+ begin_poly=&p;
+ begin_point=p_start;
+ begin_d=0;
+ if (end_d==0)
+ break;
+
+ }
+ }
+
+ if (end_d>0) {
+
+ if (Geometry::is_point_in_triangle(p_end,_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point))) {
+
+ end_poly=&p;
+ end_point=p_end;
+ end_d=0;
+ if (begin_d==0)
+ break;
+ }
+ }
+
+ }
+ }
+
+ p.prev_edge=-1;
+ }
+ }
+
+ //start or end not inside triangle.. look for closest segment :|
+ if (begin_d || end_d) {
+ for (Map<int,NavMesh>::Element*E=navpoly_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+ Polygon &p=F->get();
+ int es = p.edges.size();
+ for(int i=0;i<es;i++) {
+
+ Vector2 edge[2]={
+ _get_vertex(p.edges[i].point),
+ _get_vertex(p.edges[(i+1)%es].point)
+ };
+
+
+ if (begin_d>0) {
+ Vector2 spoint=Geometry::get_closest_point_to_segment_2d(p_start,edge);
+ float d = spoint.distance_to(p_start);
+ if (d<begin_d) {
+ begin_poly=&p;
+ begin_point=spoint;
+ begin_d=d;
+ }
+ }
+
+ if (end_d>0) {
+ Vector2 spoint=Geometry::get_closest_point_to_segment_2d(p_end,edge);
+ float d = spoint.distance_to(p_end);
+ if (d<end_d) {
+ end_poly=&p;
+ end_point=spoint;
+ end_d=d;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!begin_poly || !end_poly) {
+
+ //print_line("No Path Path");
+ return Vector<Vector2>(); //no path
+ }
+
+ if (begin_poly==end_poly) {
+
+ Vector<Vector2> path;
+ path.resize(2);
+ path[0]=begin_point;
+ path[1]=end_point;
+ //print_line("Direct Path");
+ return path;
+ }
+
+
+ bool found_route=false;
+
+ List<Polygon*> open_list;
+
+ begin_poly->entry=p_start;
+
+ for(int i=0;i<begin_poly->edges.size();i++) {
+
+ if (begin_poly->edges[i].C) {
+
+ begin_poly->edges[i].C->prev_edge=begin_poly->edges[i].C_edge;
+#ifdef USE_ENTRY_POINT
+ Vector2 edge[2]={
+ _get_vertex(begin_poly->edges[i].point),
+ _get_vertex(begin_poly->edges[(i+1)%begin_poly->edges.size()].point)
+ };
+
+ Vector2 entry = Geometry::get_closest_point_to_segment_2d(begin_poly->entry,edge);
+ begin_poly->edges[i].C->distance = begin_poly->entry.distance_to(entry);
+ begin_poly->edges[i].C->entry=entry;
+#else
+ begin_poly->edges[i].C->distance=begin_poly->center.distance_to(begin_poly->edges[i].C->center);
+#endif
+ open_list.push_back(begin_poly->edges[i].C);
+
+ if (begin_poly->edges[i].C==end_poly) {
+ found_route=true;
+ }
+ }
+ }
+
+
+ while(!found_route) {
+
+ if (open_list.size()==0) {
+ // print_line("NOU OPEN LIST");
+ break;
+ }
+ //check open list
+
+ List<Polygon*>::Element *least_cost_poly=NULL;
+ float least_cost=1e30;
+
+ //this could be faster (cache previous results)
+ for (List<Polygon*>::Element *E=open_list.front();E;E=E->next()) {
+
+ Polygon *p=E->get();
+
+
+ float cost=p->distance;
+ cost+=p->center.distance_to(end_point);
+
+ if (cost<least_cost) {
+
+ least_cost_poly=E;
+ least_cost=cost;
+ }
+ }
+
+
+ Polygon *p=least_cost_poly->get();
+ //open the neighbours for search
+ int es = p->edges.size();
+
+ for(int i=0;i<es;i++) {
+
+
+ Polygon::Edge &e=p->edges[i];
+
+ if (!e.C)
+ continue;
+
+#ifdef USE_ENTRY_POINT
+ Vector2 edge[2]={
+ _get_vertex(p->edges[i].point),
+ _get_vertex(p->edges[(i+1)%es].point)
+ };
+
+ Vector2 edge_entry = Geometry::get_closest_point_to_segment_2d(p->entry,edge);
+ float distance = p->entry.distance_to(edge_entry) + p->distance;
+
+#else
+
+ float distance = p->center.distance_to(e.C->center) + p->distance;
+
+#endif
+
+
+ if (e.C->prev_edge!=-1) {
+ //oh this was visited already, can we win the cost?
+
+ if (e.C->distance>distance) {
+
+ e.C->prev_edge=e.C_edge;
+ e.C->distance=distance;
+#ifdef USE_ENTRY_POINT
+ e.C->entry=edge_entry;
+#endif
+ }
+ } else {
+ //add to open neighbours
+
+ e.C->prev_edge=e.C_edge;
+ e.C->distance=distance;
+#ifdef USE_ENTRY_POINT
+ e.C->entry=edge_entry;
+#endif
+
+ open_list.push_back(e.C);
+
+ if (e.C==end_poly) {
+ //oh my reached end! stop algorithm
+ found_route=true;
+ break;
+
+ }
+
+ }
+ }
+
+ if (found_route)
+ break;
+
+ open_list.erase(least_cost_poly);
+ }
+
+ if (found_route) {
+
+ Vector<Vector2> path;
+
+ if (p_optimize) {
+ //string pulling
+
+ Polygon *apex_poly=end_poly;
+ Vector2 apex_point=end_point;
+ Vector2 portal_left=apex_point;
+ Vector2 portal_right=apex_point;
+ Polygon *left_poly=end_poly;
+ Polygon *right_poly=end_poly;
+ Polygon *p=end_poly;
+ path.push_back(end_point);
+
+ while(p) {
+
+ Vector2 left;
+ Vector2 right;
+
+//#define CLOCK_TANGENT(m_a,m_b,m_c) ( ((m_a)-(m_c)).cross((m_a)-(m_b)) )
+#define CLOCK_TANGENT(m_a,m_b,m_c) ((((m_a).x - (m_c).x) * ((m_b).y - (m_c).y) - ((m_b).x - (m_c).x) * ((m_a).y - (m_c).y)))
+
+ if (p==begin_poly) {
+ left=begin_point;
+ right=begin_point;
+ } else {
+ int prev = p->prev_edge;
+ int prev_n = (p->prev_edge+1)%p->edges.size();
+ left = _get_vertex(p->edges[prev].point);
+ right = _get_vertex(p->edges[prev_n].point);
+
+ if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5) < 0){
+ SWAP(left,right);
+ }
+ }
+
+ bool skip=false;
+
+
+ if (CLOCK_TANGENT(apex_point,portal_left,left) >= 0){
+ //process
+ if (portal_left==apex_point || CLOCK_TANGENT(apex_point,left,portal_right) > 0) {
+ left_poly=p;
+ portal_left=left;
+ } else {
+
+ //_clip_path(path,apex_poly,portal_right,right_poly);
+
+ apex_point=portal_right;
+ p=right_poly;
+ left_poly=p;
+ apex_poly=p;
+ portal_left=apex_point;
+ portal_right=apex_point;
+ path.push_back(apex_point);
+ skip=true;
+ }
+ }
+
+ if (!skip && CLOCK_TANGENT(apex_point,portal_right,right) <= 0){
+ //process
+ if (portal_right==apex_point || CLOCK_TANGENT(apex_point,right,portal_left) < 0) {
+ right_poly=p;
+ portal_right=right;
+ } else {
+
+ //_clip_path(path,apex_poly,portal_left,left_poly);
+
+ apex_point=portal_left;
+ p=left_poly;
+ right_poly=p;
+ apex_poly=p;
+ portal_right=apex_point;
+ portal_left=apex_point;
+ path.push_back(apex_point);
+ }
+ }
+
+ if (p!=begin_poly)
+ p=p->edges[p->prev_edge].C;
+ else
+ p=NULL;
+
+ }
+
+ if (path[path.size()-1]!=begin_point)
+ path.push_back(begin_point);
+
+ path.invert();
+
+
+
+
+ } else {
+ //midpoints
+ Polygon *p=end_poly;
+
+ path.push_back(end_point);
+ while(true) {
+ int prev = p->prev_edge;
+ int prev_n = (p->prev_edge+1)%p->edges.size();
+ Vector2 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point))*0.5;
+ path.push_back(point);
+ p = p->edges[prev].C;
+ if (p==begin_poly)
+ break;
+ }
+
+ path.push_back(begin_point);
+
+
+ path.invert();;
+ }
+
+ return path;
+ }
+
+
+ return Vector<Vector2>();
+
+}
+
+
+Vector2 Navigation2D::get_closest_point(const Vector2& p_point) {
+
+ Vector2 closest_point=Vector2();
+ float closest_point_d=1e20;
+
+ for (Map<int,NavMesh>::Element*E=navpoly_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+ Polygon &p=F->get();
+ for(int i=2;i<p.edges.size();i++) {
+
+ if (Geometry::is_point_in_triangle(p_point,_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point))) {
+
+ return p_point; //inside triangle, nothing else to discuss
+ }
+
+ }
+ }
+ }
+
+ for (Map<int,NavMesh>::Element*E=navpoly_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+ Polygon &p=F->get();
+ int es = p.edges.size();
+ for(int i=0;i<es;i++) {
+
+ Vector2 edge[2]={
+ _get_vertex(p.edges[i].point),
+ _get_vertex(p.edges[(i+1)%es].point)
+ };
+
+
+ Vector2 spoint=Geometry::get_closest_point_to_segment_2d(p_point,edge);
+ float d = spoint.distance_squared_to(p_point);
+ if (d<closest_point_d) {
+
+ closest_point=spoint;
+ closest_point_d=d;
+ }
+ }
+ }
+ }
+
+ return closest_point;
+
+}
+
+
+void Navigation2D::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("navpoly_create","mesh:NavigationPolygon","xform","owner"),&Navigation2D::navpoly_create,DEFVAL(Variant()));
+ ObjectTypeDB::bind_method(_MD("navpoly_set_transform","id","xform"),&Navigation2D::navpoly_set_transform);
+ ObjectTypeDB::bind_method(_MD("navpoly_remove","id"),&Navigation2D::navpoly_remove);
+
+ ObjectTypeDB::bind_method(_MD("get_simple_path","start","end","optimize"),&Navigation2D::get_simple_path,DEFVAL(true));
+ ObjectTypeDB::bind_method(_MD("get_closest_point","to_point"),&Navigation2D::get_closest_point);
+
+}
+
+Navigation2D::Navigation2D() {
+
+ ERR_FAIL_COND( sizeof(Point)!=8 );
+ cell_size=1; // one pixel
+ last_id=1;
+
+}
diff --git a/scene/2d/navigation2d.h b/scene/2d/navigation2d.h
new file mode 100644
index 0000000000..7ff01bb442
--- /dev/null
+++ b/scene/2d/navigation2d.h
@@ -0,0 +1,138 @@
+#ifndef NAVIGATION_2D_H
+#define NAVIGATION_2D_H
+
+#include "scene/2d/node_2d.h"
+#include "scene/2d/navigation_polygon.h"
+
+class Navigation2D : public Node2D {
+
+ OBJ_TYPE( Navigation2D, Node2D);
+
+
+ union Point {
+
+ struct {
+ int64_t x:32;
+ int64_t y:32;
+ };
+
+ uint64_t key;
+ bool operator<(const Point& p_key) const { return key < p_key.key; }
+ };
+
+
+ struct EdgeKey {
+
+ Point a;
+ Point b;
+
+ bool operator<(const EdgeKey& p_key) const {
+ return (a.key==p_key.a.key)?(b.key<p_key.b.key):(a.key<p_key.a.key);
+ };
+
+ EdgeKey(const Point& p_a=Point(),const Point& p_b=Point()) {
+ a=p_a;
+ b=p_b;
+ if (a.key > b.key) {
+ SWAP(a,b);
+ }
+ }
+ };
+
+
+ struct NavMesh;
+
+
+ struct Polygon {
+
+ struct Edge {
+ Point point;
+ Polygon *C; //connection
+ int C_edge;
+ Edge() { C=NULL; C_edge=-1; }
+ };
+
+ Vector<Edge> edges;
+
+ Vector2 center;
+ Vector2 entry;
+
+ float distance;
+ int prev_edge;
+
+ NavMesh *owner;
+ };
+
+
+ struct Connection {
+
+ Polygon *A;
+ int A_edge;
+ Polygon *B;
+ int B_edge;
+ Connection() { A=NULL; B=NULL; A_edge=-1; B_edge=-1;}
+ };
+
+ Map<EdgeKey,Connection> connections;
+
+
+ struct NavMesh {
+
+ Object *owner;
+ Matrix32 xform;
+ bool linked;
+ Ref<NavigationPolygon> navpoly;
+ List<Polygon> polygons;
+
+ };
+
+
+
+ _FORCE_INLINE_ Point _get_point(const Vector2& p_pos) const {
+
+ int x = int(Math::floor(p_pos.x/cell_size));
+ int y = int(Math::floor(p_pos.y/cell_size));
+
+ Point p;
+ p.key=0;
+ p.x=x;
+ p.y=y;
+ return p;
+
+ }
+
+ _FORCE_INLINE_ Vector2 _get_vertex(const Point& p_point) const {
+
+ return Vector2(p_point.x,p_point.y)*cell_size;
+ }
+
+
+
+ void _navpoly_link(int p_id);
+ void _navpoly_unlink(int p_id);
+
+ float cell_size;
+ Map<int,NavMesh> navpoly_map;
+ int last_id;
+#if 0
+ void _clip_path(Vector<Vector2>& path,Polygon *from_poly, const Vector2& p_to_point, Polygon* p_to_poly);
+#endif
+protected:
+
+ static void _bind_methods();
+
+public:
+
+ //API should be as dynamic as possible
+ int navpoly_create(const Ref<NavigationPolygon>& p_mesh,const Matrix32& p_xform,Object* p_owner=NULL);
+ void navpoly_set_transform(int p_id, const Matrix32& p_xform);
+ void navpoly_remove(int p_id);
+
+ Vector<Vector2> get_simple_path(const Vector2& p_start, const Vector2& p_end,bool p_optimize=true);
+ Vector2 get_closest_point(const Vector2& p_point);
+
+ Navigation2D();
+};
+
+
+#endif // Navigation2D2D_H
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
new file mode 100644
index 0000000000..fc69ea8a0d
--- /dev/null
+++ b/scene/2d/navigation_polygon.cpp
@@ -0,0 +1,450 @@
+#include "navigation_polygon.h"
+#include "navigation2d.h"
+#include "triangulator.h"
+#include "core_string_names.h"
+
+void NavigationPolygon::set_vertices(const DVector<Vector2>& p_vertices) {
+
+ vertices=p_vertices;
+}
+
+DVector<Vector2> NavigationPolygon::get_vertices() const{
+
+ return vertices;
+}
+
+
+void NavigationPolygon::_set_polygons(const Array& p_array) {
+
+ polygons.resize(p_array.size());
+ for(int i=0;i<p_array.size();i++) {
+ polygons[i].indices=p_array[i];
+ }
+}
+
+Array NavigationPolygon::_get_polygons() const {
+
+ Array ret;
+ ret.resize(polygons.size());
+ for(int i=0;i<ret.size();i++) {
+ ret[i]=polygons[i].indices;
+ }
+
+ return ret;
+}
+
+void NavigationPolygon::_set_outlines(const Array& p_array) {
+
+ outlines.resize(p_array.size());
+ for(int i=0;i<p_array.size();i++) {
+ outlines[i]=p_array[i];
+ }
+}
+
+Array NavigationPolygon::_get_outlines() const {
+
+ Array ret;
+ ret.resize(outlines.size());
+ for(int i=0;i<ret.size();i++) {
+ ret[i]=outlines[i];
+ }
+
+ return ret;
+}
+
+
+void NavigationPolygon::add_polygon(const Vector<int>& p_polygon){
+
+ Polygon polygon;
+ polygon.indices=p_polygon;
+ polygons.push_back(polygon);
+
+}
+
+void NavigationPolygon::add_outline_at_index(const DVector<Vector2>& p_outline,int p_index) {
+
+ outlines.insert(p_index,p_outline);
+}
+
+int NavigationPolygon::get_polygon_count() const{
+
+ return polygons.size();
+}
+Vector<int> NavigationPolygon::get_polygon(int p_idx){
+
+ ERR_FAIL_INDEX_V(p_idx,polygons.size(),Vector<int>());
+ return polygons[p_idx].indices;
+}
+void NavigationPolygon::clear_polygons(){
+
+ polygons.clear();
+}
+
+void NavigationPolygon::add_outline(const DVector<Vector2>& p_outline) {
+
+ outlines.push_back(p_outline);
+}
+
+int NavigationPolygon::get_outline_count() const{
+
+ return outlines.size();
+}
+
+void NavigationPolygon::set_outline(int p_idx,const DVector<Vector2>& p_outline) {
+ ERR_FAIL_INDEX(p_idx,outlines.size());
+ outlines[p_idx]=p_outline;
+}
+
+void NavigationPolygon::remove_outline(int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx,outlines.size());
+ outlines.remove(p_idx);
+
+}
+
+DVector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx,outlines.size(),DVector<Vector2>());
+ return outlines[p_idx];
+}
+
+void NavigationPolygon::clear_outlines(){
+
+ outlines.clear();;
+}
+void NavigationPolygon::make_polygons_from_outlines(){
+
+ List<TriangulatorPoly> in_poly,out_poly;
+
+ Vector2 outside_point(-1e10,-1e10);
+
+ for(int i=0;i<outlines.size();i++) {
+
+ DVector<Vector2> ol = outlines[i];
+ int olsize = ol.size();
+ if (olsize<3)
+ continue;
+ DVector<Vector2>::Read r=ol.read();
+ for(int j=0;j<olsize;j++) {
+ outside_point.x = MAX( r[j].x, outside_point.x );
+ outside_point.y = MAX( r[j].y, outside_point.y );
+ }
+
+ }
+
+ outside_point+=Vector2(0.7239784,0.819238); //avoid precision issues
+
+
+
+ for(int i=0;i<outlines.size();i++) {
+
+ DVector<Vector2> ol = outlines[i];
+ int olsize = ol.size();
+ if (olsize<3)
+ continue;
+ DVector<Vector2>::Read r=ol.read();
+
+ int interscount=0;
+ //test if this is an outer outline
+ for(int k=0;k<outlines.size();k++) {
+
+ if (i==k)
+ continue; //no self intersect
+
+ DVector<Vector2> ol2 = outlines[k];
+ int olsize2 = ol2.size();
+ if (olsize2<3)
+ continue;
+ DVector<Vector2>::Read r2=ol2.read();
+
+ for(int l=0;l<olsize2;l++) {
+
+ if (Geometry::segment_intersects_segment_2d(r[0],outside_point,r2[l],r2[(l+1)%olsize2],NULL)) {
+ interscount++;
+ }
+ }
+
+ }
+
+ bool outer = (interscount%2)==0;
+
+ TriangulatorPoly tp;
+ tp.Init(olsize);
+ for(int j=0;j<olsize;j++) {
+ tp[j]=r[j];
+ }
+
+ if (outer)
+ tp.SetOrientation(TRIANGULATOR_CCW);
+ else {
+ tp.SetOrientation(TRIANGULATOR_CW);
+ tp.SetHole(true);
+ }
+
+ in_poly.push_back(tp);
+ }
+
+
+ TriangulatorPartition tpart;
+ if (tpart.ConvexPartition_HM(&in_poly,&out_poly)==0) { //failed!
+ print_line("convex partition failed!");
+ return;
+ }
+
+ polygons.clear();
+ vertices.resize(0);
+
+ Map<Vector2,int> points;
+ for(List<TriangulatorPoly>::Element*I = out_poly.front();I;I=I->next()) {
+
+ TriangulatorPoly& tp = I->get();
+
+ struct Polygon p;
+
+ for(int i=0;i<tp.GetNumPoints();i++) {
+
+ Map<Vector2,int>::Element *E=points.find(tp[i]);
+ if (!E) {
+ E=points.insert(tp[i],vertices.size());
+ vertices.push_back(tp[i]);
+ }
+ p.indices.push_back(E->get());
+ }
+
+ polygons.push_back(p);
+ }
+
+ emit_signal(CoreStringNames::get_singleton()->changed);
+}
+
+
+void NavigationPolygon::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_vertices","vertices"),&NavigationPolygon::set_vertices);
+ ObjectTypeDB::bind_method(_MD("get_vertices"),&NavigationPolygon::get_vertices);
+
+ ObjectTypeDB::bind_method(_MD("add_polygon","polygon"),&NavigationPolygon::add_polygon);
+ ObjectTypeDB::bind_method(_MD("get_polygon_count"),&NavigationPolygon::get_polygon_count);
+ ObjectTypeDB::bind_method(_MD("get_polygon","idx"),&NavigationPolygon::get_polygon);
+ ObjectTypeDB::bind_method(_MD("clear_polygons"),&NavigationPolygon::clear_polygons);
+
+ ObjectTypeDB::bind_method(_MD("add_outline","outline"),&NavigationPolygon::add_outline);
+ ObjectTypeDB::bind_method(_MD("add_outline_at_index","outline","index"),&NavigationPolygon::add_outline_at_index);
+ ObjectTypeDB::bind_method(_MD("get_outline_count"),&NavigationPolygon::get_outline_count);
+ ObjectTypeDB::bind_method(_MD("set_outline","idx","outline"),&NavigationPolygon::set_outline);
+ ObjectTypeDB::bind_method(_MD("get_outline","idx"),&NavigationPolygon::get_outline);
+ ObjectTypeDB::bind_method(_MD("remove_outline","idx"),&NavigationPolygon::remove_outline);
+ ObjectTypeDB::bind_method(_MD("clear_outlines"),&NavigationPolygon::clear_outlines);
+ ObjectTypeDB::bind_method(_MD("make_polygons_from_outlines"),&NavigationPolygon::make_polygons_from_outlines);
+
+ ObjectTypeDB::bind_method(_MD("_set_polygons","polygons"),&NavigationPolygon::_set_polygons);
+ ObjectTypeDB::bind_method(_MD("_get_polygons"),&NavigationPolygon::_get_polygons);
+
+ ObjectTypeDB::bind_method(_MD("_set_outlines","outlines"),&NavigationPolygon::_set_outlines);
+ ObjectTypeDB::bind_method(_MD("_get_outlines"),&NavigationPolygon::_get_outlines);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_vertices"),_SCS("get_vertices"));
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_polygons"),_SCS("_get_polygons"));
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"outlines",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_outlines"),_SCS("_get_outlines"));
+}
+
+NavigationPolygon::NavigationPolygon() {
+
+
+}
+
+void NavigationPolygonInstance::set_enabled(bool p_enabled) {
+
+ if (enabled==p_enabled)
+ return;
+ enabled=p_enabled;
+
+ if (!is_inside_tree())
+ return;
+
+ if (!enabled) {
+
+ if (nav_id!=-1) {
+ navigation->navpoly_remove(nav_id);
+ nav_id=-1;
+ }
+ } else {
+
+ if (navigation) {
+
+ if (navpoly.is_valid()) {
+
+ nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this);
+ }
+ }
+
+ }
+
+ if (get_tree()->is_editor_hint())
+ update();
+
+// update_gizmo();
+}
+
+bool NavigationPolygonInstance::is_enabled() const {
+
+
+ return enabled;
+}
+
+
+/////////////////////////////
+
+
+void NavigationPolygonInstance::_notification(int p_what) {
+
+
+ switch(p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+
+ Node2D *c=this;
+ while(c) {
+
+ navigation=c->cast_to<Navigation2D>();
+ if (navigation) {
+
+ if (enabled && navpoly.is_valid()) {
+
+ nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this);
+ }
+ break;
+ }
+
+ c=c->get_parent()->cast_to<Node2D>();
+ }
+
+ } break;
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+
+ if (navigation && nav_id!=-1) {
+ navigation->navpoly_set_transform(nav_id,get_relative_transform(navigation));
+ }
+
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+
+ if (navigation) {
+
+ if (nav_id!=-1) {
+ navigation->navpoly_remove(nav_id);
+ nav_id=-1;
+ }
+ }
+ navigation=NULL;
+ } break;
+ case NOTIFICATION_DRAW: {
+
+ if (is_inside_tree() && get_tree()->is_editor_hint() && navpoly.is_valid()) {
+
+ DVector<Vector2> verts=navpoly->get_vertices();
+ int vsize = verts.size();
+ if (vsize<3)
+ return;
+
+
+ Color color;
+ if (enabled) {
+ color=Color(0.1,0.8,1.0,0.4);
+ } else {
+ color=Color(1.0,0.8,0.1,0.4);
+ }
+ Vector<Color> colors;
+ Vector<Vector2> vertices;
+ vertices.resize(vsize);
+ colors.resize(vsize);
+ {
+ DVector<Vector2>::Read vr = verts.read();
+ for(int i=0;i<vsize;i++) {
+ vertices[i]=vr[i];
+ colors[i]=color;
+ }
+ }
+
+ Vector<int> indices;
+
+
+ for(int i=0;i<navpoly->get_polygon_count();i++) {
+ Vector<int> polygon = navpoly->get_polygon(i);
+
+ for(int j=2;j<polygon.size();j++) {
+
+ int kofs[3]={0,j-1,j};
+ for(int k=0;k<3;k++) {
+
+ int idx = polygon[ kofs[k] ];
+ ERR_FAIL_INDEX(idx,vsize);
+ indices.push_back(idx);
+ }
+ }
+ }
+ VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(),indices,vertices,colors);
+
+ }
+ } break;
+
+ }
+}
+
+
+void NavigationPolygonInstance::set_navigation_polygon(const Ref<NavigationPolygon>& p_navpoly) {
+
+ if (p_navpoly==navpoly)
+ return;
+
+ if (navigation && nav_id!=-1) {
+ navigation->navpoly_remove(nav_id);
+ nav_id=-1;
+ }
+ if (navpoly.is_valid()) {
+ navpoly->disconnect(CoreStringNames::get_singleton()->changed,this,"_navpoly_changed");
+ }
+ navpoly=p_navpoly;
+
+ if (navpoly.is_valid()) {
+ navpoly->connect(CoreStringNames::get_singleton()->changed,this,"_navpoly_changed");
+ }
+
+ if (navigation && navpoly.is_valid() && enabled) {
+ nav_id = navigation->navpoly_create(navpoly,get_relative_transform(navigation),this);
+ }
+ //update_gizmo();
+ _change_notify("navpoly");
+
+}
+
+Ref<NavigationPolygon> NavigationPolygonInstance::get_navigation_polygon() const{
+
+ return navpoly;
+}
+
+void NavigationPolygonInstance::_navpoly_changed() {
+
+ if (is_inside_tree() && get_tree()->is_editor_hint())
+ update();
+}
+
+void NavigationPolygonInstance::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("set_navigation_polygon","navpoly"),&NavigationPolygonInstance::set_navigation_polygon);
+ ObjectTypeDB::bind_method(_MD("get_navigation_polygon"),&NavigationPolygonInstance::get_navigation_polygon);
+
+ ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&NavigationPolygonInstance::set_enabled);
+ ObjectTypeDB::bind_method(_MD("is_enabled"),&NavigationPolygonInstance::is_enabled);
+
+ ObjectTypeDB::bind_method(_MD("_navpoly_changed"),&NavigationPolygonInstance::_navpoly_changed);
+
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navpoly",PROPERTY_HINT_RESOURCE_TYPE,"NavigationPolygon"),_SCS("set_navigation_polygon"),_SCS("get_navigation_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
+}
+
+NavigationPolygonInstance::NavigationPolygonInstance() {
+
+ navigation=NULL;
+ nav_id=-1;
+ enabled=true;
+
+}
diff --git a/scene/2d/navigation_polygon.h b/scene/2d/navigation_polygon.h
new file mode 100644
index 0000000000..01307a170b
--- /dev/null
+++ b/scene/2d/navigation_polygon.h
@@ -0,0 +1,84 @@
+#ifndef NAVIGATION_POLYGON_H
+#define NAVIGATION_POLYGON_H
+
+#include "scene/2d/node_2d.h"
+
+
+class NavigationPolygon : public Resource {
+
+ OBJ_TYPE( NavigationPolygon, Resource );
+
+ DVector<Vector2> vertices;
+ struct Polygon {
+ Vector<int> indices;
+ };
+ Vector<Polygon> polygons;
+ Vector< DVector<Vector2> > outlines;
+
+protected:
+
+ static void _bind_methods();
+
+ void _set_polygons(const Array& p_array);
+ Array _get_polygons() const;
+
+ void _set_outlines(const Array& p_array);
+ Array _get_outlines() const;
+
+public:
+
+
+
+ void set_vertices(const DVector<Vector2>& p_vertices);
+ DVector<Vector2> get_vertices() const;
+
+ void add_polygon(const Vector<int>& p_polygon);
+ int get_polygon_count() const;
+
+ void add_outline(const DVector<Vector2>& p_outline);
+ void add_outline_at_index(const DVector<Vector2>& p_outline,int p_index);
+ void set_outline(int p_idx,const DVector<Vector2>& p_outline);
+ DVector<Vector2> get_outline(int p_idx) const;
+ void remove_outline(int p_idx);
+ int get_outline_count() const;
+
+ void clear_outlines();
+ void make_polygons_from_outlines();
+
+ Vector<int> get_polygon(int p_idx);
+ void clear_polygons();
+
+ NavigationPolygon();
+};
+
+
+class Navigation2D;
+
+class NavigationPolygonInstance : public Node2D {
+
+ OBJ_TYPE(NavigationPolygonInstance,Node2D);
+
+ bool enabled;
+ int nav_id;
+ Navigation2D *navigation;
+ Ref<NavigationPolygon> navpoly;
+
+ void _navpoly_changed();
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_enabled(bool p_enabled);
+ bool is_enabled() const;
+
+ void set_navigation_polygon(const Ref<NavigationPolygon>& p_navpoly);
+ Ref<NavigationPolygon> get_navigation_polygon() const;
+
+ NavigationPolygonInstance();
+};
+
+
+#endif // NAVIGATIONPOLYGON_H
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 8b4196ee7f..36b6b220b3 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -317,6 +317,18 @@ int Node2D::get_z() const{
return z;
}
+Matrix32 Node2D::get_relative_transform(const Node *p_parent) const {
+
+ if (p_parent==this)
+ return Matrix32();
+
+ Node2D *parent_2d = get_parent()->cast_to<Node2D>();
+ ERR_FAIL_COND_V(!parent_2d,Matrix32());
+ if (p_parent==parent_2d)
+ return get_transform();
+ else
+ return parent_2d->get_relative_transform(p_parent) * get_transform();
+}
void Node2D::_bind_methods() {
@@ -351,6 +363,8 @@ void Node2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("edit_set_pivot"),&Node2D::edit_set_pivot);
+ ObjectTypeDB::bind_method(_MD("get_relative_transform"),&Node2D::get_relative_transform);
+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos"));
ADD_PROPERTY(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd"));
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/scale"),_SCS("set_scale"),_SCS("get_scale"));
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 61b8c829d6..7b059008c2 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -93,6 +93,9 @@ public:
void set_z_as_relative(bool p_enabled);
bool is_z_relative() const;
+ Matrix32 get_relative_transform(const Node *p_parent) const;
+
+
Matrix32 get_transform() const;
Node2D();
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 9fcf34cee6..75e7957cb8 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -29,6 +29,7 @@
#include "tile_map.h"
#include "io/marshalls.h"
#include "servers/physics_2d_server.h"
+#include "method_bind_ext.inc"
void TileMap::_notification(int p_what) {
switch(p_what) {
@@ -62,7 +63,7 @@ void TileMap::_update_quadrant_space(const RID& p_space) {
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
Quadrant &q=E->get();
- Physics2DServer::get_singleton()->body_set_space(q.static_body,p_space);
+ Physics2DServer::get_singleton()->body_set_space(q.body,p_space);
}
}
@@ -79,7 +80,7 @@ void TileMap::_update_quadrant_transform() {
Matrix32 xform;
xform.set_origin( q.pos );
xform = global_transform * xform;
- Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
+ Physics2DServer::get_singleton()->body_set_state(q.body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
}
}
@@ -178,7 +179,7 @@ void TileMap::_update_dirty_quadrants() {
Quadrant &q = *dirty_quadrant_list.first()->self();
vs->canvas_item_clear(q.canvas_item);
- ps->body_clear_shapes(q.static_body);
+ ps->body_clear_shapes(q.body);
int shape_idx=0;
for(int i=0;i<q.cells.size();i++) {
@@ -225,11 +226,9 @@ void TileMap::_update_dirty_quadrants() {
rect.pos+=tile_ofs;
if (r==Rect2()) {
-
- tex->draw_rect(q.canvas_item,rect);
+ tex->draw_rect(q.canvas_item,rect,false,Color(1,1,1),c.transpose);
} else {
-
- tex->draw_rect_region(q.canvas_item,rect,r);
+ tex->draw_rect_region(q.canvas_item,rect,r,Color(1,1,1),c.transpose);
}
Vector< Ref<Shape2D> > shapes = tile_set->tile_get_shapes(c.id);
@@ -243,24 +242,29 @@ void TileMap::_update_dirty_quadrants() {
Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id);
Matrix32 xform;
xform.set_origin(offset.floor());
+ if (c.transpose) {
+ SWAP(xform.elements[0].x, xform.elements[0].y);
+ SWAP(xform.elements[1].x, xform.elements[1].y);
+ SWAP(shape_ofs.x, shape_ofs.y);
+ SWAP(s.x, s.y);
+ }
if (c.flip_h) {
- xform.elements[0]=-xform.elements[0];
- xform.elements[2].x+=s.x-shape_ofs.x;
- } else {
-
- xform.elements[2].x+=shape_ofs.x;
+ xform.elements[0].x=-xform.elements[0].x;
+ xform.elements[1].x=-xform.elements[1].x;
+ shape_ofs.x=s.x-shape_ofs.x;
}
if (c.flip_v) {
- xform.elements[1]=-xform.elements[1];
- xform.elements[2].y+=s.y-shape_ofs.y;
- } else {
-
- xform.elements[2].y+=shape_ofs.y;
+ xform.elements[0].y=-xform.elements[0].y;
+ xform.elements[1].y=-xform.elements[1].y;
+ shape_ofs.y=s.y-shape_ofs.y;
}
+ xform.elements[2].x+=shape_ofs.x;
+ xform.elements[2].y+=shape_ofs.y;
+
- ps->body_add_shape(q.static_body,shape->get_rid(),xform);
- ps->body_set_shape_metadata(q.static_body,shape_idx++,Vector2(E->key().x,E->key().y));
+ ps->body_add_shape(q.body,shape->get_rid(),xform);
+ ps->body_set_shape_metadata(q.body,shape_idx++,Vector2(E->key().x,E->key().y));
}
}
@@ -339,19 +343,19 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const
q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() );
VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform );
- q.static_body=Physics2DServer::get_singleton()->body_create(Physics2DServer::BODY_MODE_STATIC);
- Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.static_body,get_instance_ID());
- Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer);
- Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_FRICTION,friction);
- Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_BOUNCE,bounce);
+ q.body=Physics2DServer::get_singleton()->body_create(use_kinematic?Physics2DServer::BODY_MODE_KINEMATIC:Physics2DServer::BODY_MODE_STATIC);
+ Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.body,get_instance_ID());
+ Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer);
+ Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_FRICTION,friction);
+ Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_BOUNCE,bounce);
if (is_inside_tree()) {
xform = get_global_transform() * xform;
RID space = get_world_2d()->get_space();
- Physics2DServer::get_singleton()->body_set_space(q.static_body,space);
+ Physics2DServer::get_singleton()->body_set_space(q.body,space);
}
- Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
+ Physics2DServer::get_singleton()->body_set_state(q.body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
rect_cache_dirty=true;
quadrant_order_dirty=true;
@@ -361,7 +365,7 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const
void TileMap::_erase_quadrant(Map<PosKey,Quadrant>::Element *Q) {
Quadrant &q=Q->get();
- Physics2DServer::get_singleton()->free(q.static_body);
+ Physics2DServer::get_singleton()->free(q.body);
VisualServer::get_singleton()->free(q.canvas_item);
if (q.dirty_list.in_list())
dirty_quadrant_list.remove(&q.dirty_list);
@@ -385,7 +389,7 @@ void TileMap::_make_quadrant_dirty(Map<PosKey,Quadrant>::Element *Q) {
}
-void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) {
+void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bool p_transpose) {
PosKey pk(p_x,p_y);
@@ -421,7 +425,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) {
} else {
ERR_FAIL_COND(!Q); // quadrant should exist...
- if (E->get().id==p_tile && E->get().flip_h==p_flip_x && E->get().flip_v==p_flip_y)
+ if (E->get().id==p_tile && E->get().flip_h==p_flip_x && E->get().flip_v==p_flip_y && E->get().transpose==p_transpose)
return; //nothing changed
}
@@ -432,6 +436,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y) {
c.id=p_tile;
c.flip_h=p_flip_x;
c.flip_v=p_flip_y;
+ c.transpose=p_transpose;
_make_quadrant_dirty(Q);
@@ -471,6 +476,17 @@ bool TileMap::is_cell_y_flipped(int p_x,int p_y) const {
return E->get().flip_v;
}
+bool TileMap::is_cell_transposed(int p_x,int p_y) const {
+
+ PosKey pk(p_x,p_y);
+
+ const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
+
+ if (!E)
+ return false;
+
+ return E->get().transpose;
+}
void TileMap::_recreate_quadrants() {
@@ -535,11 +551,12 @@ void TileMap::_set_tile_data(const DVector<int>& p_data) {
uint32_t v = decode_uint32(&local[4]);
bool flip_h = v&(1<<29);
bool flip_v = v&(1<<30);
+ bool transpose = v&(1<<31);
v&=(1<<29)-1;
// if (x<-20 || y <-20 || x>4000 || y>4000)
// continue;
- set_cell(x,y,v,flip_h,flip_v);
+ set_cell(x,y,v,flip_h,flip_v,transpose);
}
@@ -562,6 +579,8 @@ DVector<int> TileMap::_get_tile_data() const {
val|=(1<<29);
if (E->get().flip_v)
val|=(1<<30);
+ if (E->get().transpose)
+ val|=(1<<31);
encode_uint32(val,&ptr[4]);
idx+=2;
@@ -586,17 +605,29 @@ void TileMap::set_collision_layer_mask(uint32_t p_layer) {
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
Quadrant &q=E->get();
- Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer);
+ Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer);
}
}
+bool TileMap::get_collision_use_kinematic() const{
+
+ return use_kinematic;
+}
+
+void TileMap::set_collision_use_kinematic(bool p_use_kinematic) {
+
+ _clear_quadrants();
+ use_kinematic=p_use_kinematic;
+ _recreate_quadrants();
+}
+
void TileMap::set_collision_friction(float p_friction) {
friction=p_friction;
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
Quadrant &q=E->get();
- Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_FRICTION,p_friction);
+ Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_FRICTION,p_friction);
}
}
@@ -612,7 +643,7 @@ void TileMap::set_collision_bounce(float p_bounce){
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
Quadrant &q=E->get();
- Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_BOUNCE,p_bounce);
+ Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_BOUNCE,p_bounce);
}
}
@@ -804,6 +835,9 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_center_y","enable"),&TileMap::set_center_y);
ObjectTypeDB::bind_method(_MD("get_center_y"),&TileMap::get_center_y);
+ ObjectTypeDB::bind_method(_MD("set_collision_use_kinematic","use_kinematic"),&TileMap::set_collision_use_kinematic);
+ ObjectTypeDB::bind_method(_MD("get_collision_use_kinematic"),&TileMap::get_collision_use_kinematic);
+
ObjectTypeDB::bind_method(_MD("set_collision_layer_mask","mask"),&TileMap::set_collision_layer_mask);
ObjectTypeDB::bind_method(_MD("get_collision_layer_mask"),&TileMap::get_collision_layer_mask);
@@ -813,7 +847,7 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_collision_bounce","value"),&TileMap::set_collision_bounce);
ObjectTypeDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce);
- ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell);
ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);
@@ -837,6 +871,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collision/use_kinematic",PROPERTY_HINT_NONE,""),_SCS("set_collision_use_kinematic"),_SCS("get_collision_use_kinematic"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask"));
@@ -870,6 +905,7 @@ TileMap::TileMap() {
bounce=0;
mode=MODE_SQUARE;
half_offset=HALF_OFFSET_DISABLED;
+ use_kinematic=false;
fp_adjust=0.01;
fp_adjust=0.01;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 4e9e2e7e97..fe1067fc1d 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -60,6 +60,7 @@ private:
Mode mode;
Matrix32 custom_transform;
HalfOffset half_offset;
+ bool use_kinematic;
union PosKey {
@@ -85,6 +86,7 @@ private:
int32_t id:24;
bool flip_h:1;
bool flip_v:1;
+ bool transpose:1;
};
uint32_t _u32t;
@@ -97,14 +99,14 @@ private:
Vector2 pos;
RID canvas_item;
- RID static_body;
+ RID body;
SelfList<Quadrant> dirty_list;
VSet<PosKey> cells;
- void operator=(const Quadrant& q) { pos=q.pos; canvas_item=q.canvas_item; static_body=q.static_body; cells=q.cells; }
- Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_item=q.canvas_item; static_body=q.static_body; cells=q.cells;}
+ void operator=(const Quadrant& q) { pos=q.pos; canvas_item=q.canvas_item; body=q.body; cells=q.cells; }
+ Quadrant(const Quadrant& q) : dirty_list(this) { pos=q.pos; canvas_item=q.canvas_item; body=q.body; cells=q.cells;}
Quadrant() : dirty_list(this) {}
};
@@ -167,16 +169,20 @@ public:
void set_center_y(bool p_enable);
bool get_center_y() const;
- void set_cell(int p_x,int p_y,int p_tile,bool p_flip_x=false,bool p_flip_y=false);
+ void set_cell(int p_x,int p_y,int p_tile,bool p_flip_x=false,bool p_flip_y=false,bool p_transpose=false);
int get_cell(int p_x,int p_y) const;
bool is_cell_x_flipped(int p_x,int p_y) const;
bool is_cell_y_flipped(int p_x,int p_y) const;
+ bool is_cell_transposed(int p_x,int p_y) const;
Rect2 get_item_rect() const;
void set_collision_layer_mask(uint32_t p_layer);
uint32_t get_collision_layer_mask() const;
+ void set_collision_use_kinematic(bool p_use_kinematic);
+ bool get_collision_use_kinematic() const;
+
void set_collision_friction(float p_friction);
float get_collision_friction() const;
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 27420f8002..1109139180 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -152,11 +152,11 @@ void Camera::_get_property_list( List<PropertyInfo> *p_list) const {
case PROJECTION_PERSPECTIVE: {
- p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_NOEDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fov" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_NOEDITOR) );
if (keep_aspect==KEEP_WIDTH)
- p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fovx" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) );
else
- p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,89,0.1",PROPERTY_USAGE_EDITOR) );
+ p_list->push_back( PropertyInfo( Variant::REAL, "fovy" , PROPERTY_HINT_RANGE, "1,179,0.1",PROPERTY_USAGE_EDITOR) );
} break;
@@ -604,7 +604,7 @@ Vector3 Camera::project_position(const Point2& p_point) const {
Vector2 point;
point.x = (p_point.x/viewport_size.x) * 2.0 - 1.0;
- point.y = (p_point.y/viewport_size.y) * 2.0 - 1.0;
+ point.y = (1.0-(p_point.y/viewport_size.y)) * 2.0 - 1.0;
point*=vp_size;
Vector3 p(point.x,point.y,-near);
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index a82c69e67f..45c7fa912c 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -310,6 +310,17 @@ int GeometryInstance::get_baked_light_texture_id() const{
return baked_light_texture_id;
}
+void GeometryInstance::set_extra_cull_margin(float p_margin) {
+
+ ERR_FAIL_COND(p_margin<0);
+ extra_cull_margin=p_margin;
+ VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(),extra_cull_margin);
+}
+
+float GeometryInstance::get_extra_cull_margin() const{
+
+ return extra_cull_margin;
+}
void GeometryInstance::_bind_methods() {
@@ -328,6 +339,9 @@ void GeometryInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_baked_light_texture_id","id"), &GeometryInstance::set_baked_light_texture_id);
ObjectTypeDB::bind_method(_MD("get_baked_light_texture_id"), &GeometryInstance::get_baked_light_texture_id);
+ ObjectTypeDB::bind_method(_MD("set_extra_cull_margin","margin"), &GeometryInstance::set_extra_cull_margin);
+ ObjectTypeDB::bind_method(_MD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
+
ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE);
@@ -336,6 +350,7 @@ void GeometryInstance::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/receive_shadows"), _SCS("set_flag"), _SCS("get_flag"),FLAG_RECEIVE_SHADOWS);
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_begin",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_begin"), _SCS("get_draw_range_begin"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/range_end",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_draw_range_end"), _SCS("get_draw_range_end"));
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "geometry/extra_cull_margin",PROPERTY_HINT_RANGE,"0,16384,0"), _SCS("set_extra_cull_margin"), _SCS("get_extra_cull_margin"));
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard_y"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD_FIX_Y);
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE);
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index e9fefe1ba0..e08acbe9a2 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -108,6 +108,7 @@ private:
void _find_baked_light();
BakedLightInstance *baked_light_instance;
int baked_light_texture_id;
+ float extra_cull_margin;
void _baked_light_changed();
void _update_visibility();
@@ -132,6 +133,9 @@ public:
void set_baked_light_texture_id(int p_id);
int get_baked_light_texture_id() const;
+ void set_extra_cull_margin(float p_margin);
+ float get_extra_cull_margin() const;
+
GeometryInstance();
};
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index ce268843b1..a8070be91d 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2267,8 +2267,10 @@ void Control::_window_sort_subwindows() {
if (!window->subwindow_order_dirty)
return;
+
window->modal_stack.sort_custom<CComparator>();
window->subwindows.sort_custom<CComparator>();
+
window->subwindow_order_dirty=false;
}
@@ -2688,6 +2690,12 @@ Control *Control::get_focus_owner() const {
return data.window->window->key_focus;
}
+
+void Control::warp_mouse(const Point2& p_to_pos) {
+ ERR_FAIL_COND(!is_inside_tree());
+ get_viewport()->warp_mouse(get_global_transform().xform(p_to_pos));
+}
+
void Control::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_window_input_event"),&Control::_window_input_event);
@@ -2784,6 +2792,9 @@ void Control::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_drag_preview","control:Control"),&Control::set_drag_preview);
+ ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse);
+
+
BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size"));
BIND_VMETHOD(MethodInfo(Variant::OBJECT,"get_drag_data",PropertyInfo(Variant::VECTOR2,"pos")));
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 64b5a9b661..7e14bff098 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -380,7 +380,7 @@ public:
void grab_click_focus();
-
+ void warp_mouse(const Point2& p_to_pos);
Control();
~Control();
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index a82cfc7ea6..30e0241f23 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -328,8 +328,8 @@ AcceptDialog::AcceptDialog() {
label->set_anchor(MARGIN_RIGHT,ANCHOR_END);
label->set_anchor(MARGIN_BOTTOM,ANCHOR_END);
label->set_begin( Point2( margin, margin) );
- label->set_end( Point2( margin, button_margin) );
- label->set_autowrap(true);
+ label->set_end( Point2( margin, button_margin+10) );
+ //label->set_autowrap(true);
add_child(label);
hbc = memnew( HBoxContainer );
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index bccd05d4fe..d58cb3da79 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -94,6 +94,8 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) {
Control *c=get_child(i)->cast_to<Control>();
if (!c)
continue;
+ if (c->is_hidden())
+ continue;
Size2 minsize = c->get_combined_minimum_size();
@@ -114,6 +116,8 @@ void Popup::popup_centered_minsize(const Size2& p_minsize) {
}
+ print_line(String(c->get_type())+": "+minsize);
+
total_minsize.width = MAX( total_minsize.width, minsize.width );
total_minsize.height = MAX( total_minsize.height, minsize.height );
}
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index c2e988de95..d825ea2b68 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -90,7 +90,7 @@ public:
void add_icon_check_item(const Ref<Texture>& p_icon,const String& p_label,int p_ID=-1,uint32_t p_accel=0);
void add_check_item(const String& p_label,int p_ID=-1,uint32_t p_accel=0);
void add_submenu_item(const String& p_label,const String& p_submenu, int p_ID=-1);
-
+
void set_item_text(int p_idx,const String& p_text);
void set_item_icon(int p_idx,const Ref<Texture>& p_icon);
void set_item_checked(int p_idx,bool p_checked);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index b7b52a39dc..035dbb8cc4 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2472,6 +2472,10 @@ void Tree::_notification(int p_what) {
}
}
+ if (p_what==NOTIFICATION_THEME_CHANGED) {
+ update_cache();
+ }
+
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index e6c787cf9e..02e009866f 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -29,6 +29,8 @@
#include "viewport.h"
#include "os/os.h"
#include "scene/3d/spatial.h"
+#include "os/input.h"
+
//#include "scene/3d/camera.h"
#include "servers/spatial_sound_server.h"
@@ -970,6 +972,22 @@ bool Viewport::get_render_target_vflip() const{
return render_target_vflip;
}
+void Viewport::set_render_target_clear_on_new_frame(bool p_enable) {
+
+ render_target_clear_on_new_frame=p_enable;
+ VisualServer::get_singleton()->viewport_set_render_target_clear_on_new_frame(viewport,p_enable);
+}
+
+bool Viewport::get_render_target_clear_on_new_frame() const{
+
+ return render_target_clear_on_new_frame;
+}
+
+void Viewport::render_target_clear() {
+
+ //render_target_clear=true;
+ VisualServer::get_singleton()->viewport_render_target_clear(viewport);
+}
void Viewport::set_render_target_filter(bool p_enable) {
@@ -1100,6 +1118,12 @@ void Viewport::_vp_unhandled_input(const InputEvent& p_ev) {
}
+void Viewport::warp_mouse(const Vector2& p_pos) {
+
+ Vector2 gpos = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse().xform(p_pos);
+ Input::get_singleton()->warp_mouse_pos(gpos);
+}
+
void Viewport::input(const InputEvent& p_event) {
ERR_FAIL_COND(!is_inside_tree());
@@ -1256,6 +1280,11 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_render_target_vflip","enable"), &Viewport::set_render_target_vflip);
ObjectTypeDB::bind_method(_MD("get_render_target_vflip"), &Viewport::get_render_target_vflip);
+
+ ObjectTypeDB::bind_method(_MD("set_render_target_clear_on_new_frame","enable"), &Viewport::set_render_target_clear_on_new_frame);
+ ObjectTypeDB::bind_method(_MD("get_render_target_clear_on_new_frame"), &Viewport::get_render_target_clear_on_new_frame);
+
+ ObjectTypeDB::bind_method(_MD("render_target_clear"), &Viewport::render_target_clear);
ObjectTypeDB::bind_method(_MD("set_render_target_filter","enable"), &Viewport::set_render_target_filter);
ObjectTypeDB::bind_method(_MD("get_render_target_filter"), &Viewport::get_render_target_filter);
@@ -1289,6 +1318,7 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d);
ObjectTypeDB::bind_method(_MD("set_render_target_to_screen_rect"), &Viewport::set_render_target_to_screen_rect);
+ ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"), &Viewport::warp_mouse);
ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") );
@@ -1297,6 +1327,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/enabled"), _SCS("set_as_render_target"), _SCS("is_set_as_render_target") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/v_flip"), _SCS("set_render_target_vflip"), _SCS("get_render_target_vflip") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/clear_on_new_frame"), _SCS("set_render_target_clear_on_new_frame"), _SCS("get_render_target_clear_on_new_frame") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/filter"), _SCS("set_render_target_filter"), _SCS("get_render_target_filter") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/gen_mipmaps"), _SCS("set_render_target_gen_mipmaps"), _SCS("get_render_target_gen_mipmaps") );
ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_render_target_update_mode"), _SCS("get_render_target_update_mode") );
@@ -1335,6 +1366,8 @@ Viewport::Viewport() {
render_target_gen_mipmaps=false;
render_target=false;
render_target_vflip=false;
+ render_target_clear_on_new_frame=true;
+ //render_target_clear=true;
render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE;
render_target_texture = Ref<RenderTargetTexture>( memnew( RenderTargetTexture(this) ) );
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 4bb5735731..d2a22401bd 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -114,6 +114,7 @@ friend class RenderTargetTexture;
bool transparent_bg;
bool render_target_vflip;
+ bool render_target_clear_on_new_frame;
bool render_target_filter;
bool render_target_gen_mipmaps;
@@ -220,6 +221,10 @@ public:
void set_render_target_vflip(bool p_enable);
bool get_render_target_vflip() const;
+ void set_render_target_clear_on_new_frame(bool p_enable);
+ bool get_render_target_clear_on_new_frame() const;
+ void render_target_clear();
+
void set_render_target_filter(bool p_enable);
bool get_render_target_filter() const;
@@ -246,6 +251,8 @@ public:
void set_render_target_to_screen_rect(const Rect2& p_rect);
Rect2 get_render_target_to_screen_rect() const;
+ void warp_mouse(const Vector2& p_pos);
+
void set_physics_object_picking(bool p_enable);
bool get_physics_object_picking();
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 998e0b2044..f90db42614 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -79,6 +79,8 @@
#include "scene/resources/video_stream.h"
#include "scene/2d/particles_2d.h"
#include "scene/2d/path_2d.h"
+#include "scene/2d/light_2d.h"
+#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/canvas_item.h"
#include "scene/2d/sprite.h"
@@ -102,6 +104,8 @@
#include "scene/2d/screen_button.h"
#include "scene/2d/remote_transform_2d.h"
#include "scene/2d/y_sort.h"
+#include "scene/2d/navigation2d.h"
+#include "scene/2d/canvas_modulate.h"
#include "scene/2d/position_2d.h"
#include "scene/2d/tile_map.h"
@@ -262,6 +266,7 @@ void register_scene_types() {
ObjectTypeDB::register_virtual_type<RenderTargetTexture>();
ObjectTypeDB::register_type<Timer>();
ObjectTypeDB::register_type<CanvasLayer>();
+ ObjectTypeDB::register_type<CanvasModulate>();
ObjectTypeDB::register_type<ResourcePreloader>();
/* REGISTER GUI */
@@ -450,6 +455,7 @@ void register_scene_types() {
//ObjectTypeDB::set_type_enabled("BodyVolumeCylinder",false);
//ObjectTypeDB::set_type_enabled("BodyVolumeConvexPolygon",false);
+ ObjectTypeDB::register_type<CanvasItemMaterial>();
ObjectTypeDB::register_virtual_type<CanvasItem>();
ObjectTypeDB::register_type<Node2D>();
ObjectTypeDB::register_type<Particles2D>();
@@ -471,6 +477,9 @@ void register_scene_types() {
ObjectTypeDB::register_type<VisibilityNotifier2D>();
ObjectTypeDB::register_type<VisibilityEnabler2D>();
ObjectTypeDB::register_type<Polygon2D>();
+ ObjectTypeDB::register_type<Light2D>();
+ ObjectTypeDB::register_type<LightOccluder2D>();
+ ObjectTypeDB::register_type<OccluderPolygon2D>();
ObjectTypeDB::register_type<YSort>();
ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
@@ -499,6 +508,7 @@ void register_scene_types() {
ObjectTypeDB::register_virtual_type<Shader>();
ObjectTypeDB::register_virtual_type<ShaderGraph>();
ObjectTypeDB::register_type<CanvasItemShader>();
+ ObjectTypeDB::register_type<CanvasItemShaderGraph>();
#ifndef _3D_DISABLED
ObjectTypeDB::register_type<Mesh>();
@@ -574,6 +584,10 @@ void register_scene_types() {
ObjectTypeDB::register_type<Path2D>();
ObjectTypeDB::register_type<PathFollow2D>();
+ ObjectTypeDB::register_type<Navigation2D>();
+ ObjectTypeDB::register_type<NavigationPolygon>();
+ ObjectTypeDB::register_type<NavigationPolygonInstance>();
+
OS::get_singleton()->yield(); //may take time to init
ObjectTypeDB::register_type<PackedScene>();
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 08c752cff9..633dd72ce3 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -582,7 +582,7 @@ void ShaderMaterial::get_argument_options(const StringName& p_function,int p_idx
List<PropertyInfo> pl;
shader->get_param_list(&pl);
for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
- r_options->push_back("\""+E->get().name.replace("shader_param/","")+"\"");
+ r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\"");
}
}
}
diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp
index 9f691d6ad3..e8cdec66df 100644
--- a/scene/resources/polygon_path_finder.cpp
+++ b/scene/resources/polygon_path_finder.cpp
@@ -525,24 +525,32 @@ bool PolygonPathFinder::is_point_inside(const Vector2& p_point) const {
Vector2 PolygonPathFinder::get_closest_point(const Vector2& p_point) const {
- int closest_idx=-1;
float closest_dist=1e20;
- for(int i=0;i<points.size()-2;i++) {
+ Vector2 closest_point;
+
+ for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
+
+ const Edge& e=E->get();
+ Vector2 seg[2]={
+ points[e.points[0]].pos,
+ points[e.points[1]].pos
+ };
+
+
+ Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point,seg);
+ float d = p_point.distance_squared_to(closest);
- float d = p_point.distance_squared_to(points[i].pos);
if (d<closest_dist) {
closest_dist=d;
- closest_idx=i;
+ closest_point=closest;
}
-
}
+
+ ERR_FAIL_COND_V(closest_dist==1e20,Vector2());
- ERR_FAIL_COND_V(closest_idx==-1,Vector2());
-
- return points[closest_idx].pos;
+ return closest_point;
}
-
Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2& p_from, const Vector2& p_to) const {
Vector<Vector2> inters;
diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp
index 9703799a48..b0d9ceee0e 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -221,6 +221,13 @@ void ShaderGraph::_bind_methods() {
ObjectTypeDB::bind_method(_MD("comment_node_set_text","shader_type","id","text"),&ShaderGraph::comment_node_set_text);
ObjectTypeDB::bind_method(_MD("comment_node_get_text","shader_type","id"),&ShaderGraph::comment_node_get_text);
+ ObjectTypeDB::bind_method(_MD("color_ramp_node_set_ramp","shader_type","id","colors","offsets"),&ShaderGraph::color_ramp_node_set_ramp);
+ ObjectTypeDB::bind_method(_MD("color_ramp_node_get_colors","shader_type","id"),&ShaderGraph::color_ramp_node_get_colors);
+ ObjectTypeDB::bind_method(_MD("color_ramp_node_get_offsets","shader_type","id"),&ShaderGraph::color_ramp_node_get_offsets);
+
+ ObjectTypeDB::bind_method(_MD("curve_map_node_set_points","shader_type","id","points"),&ShaderGraph::curve_map_node_set_points);
+ ObjectTypeDB::bind_method(_MD("curve_map_node_get_points","shader_type","id"),&ShaderGraph::curve_map_node_get_points);
+
ObjectTypeDB::bind_method(_MD("connect_node:Error","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::connect_node);
ObjectTypeDB::bind_method(_MD("is_node_connected","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::is_node_connected);
ObjectTypeDB::bind_method(_MD("disconnect_node","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::disconnect_node);
@@ -263,12 +270,15 @@ void ShaderGraph::_bind_methods() {
BIND_CONSTANT( NODE_XFORM_TO_VEC ); // 3 vec input ); 1 xform output
BIND_CONSTANT( NODE_SCALAR_INTERP ); // scalar interpolation (with optional curve)
BIND_CONSTANT( NODE_VEC_INTERP ); // vec3 interpolation (with optional curve)
+ BIND_CONSTANT( NODE_COLOR_RAMP );
+ BIND_CONSTANT( NODE_CURVE_MAP );
BIND_CONSTANT( NODE_SCALAR_INPUT ); // scalar uniform (assignable in material)
BIND_CONSTANT( NODE_VEC_INPUT ); // vec3 uniform (assignable in material)
BIND_CONSTANT( NODE_RGB_INPUT ); // color uniform (assignable in material)
BIND_CONSTANT( NODE_XFORM_INPUT ); // mat4 uniform (assignable in material)
BIND_CONSTANT( NODE_TEXTURE_INPUT ); // texture input (assignable in material)
BIND_CONSTANT( NODE_CUBEMAP_INPUT ); // cubemap input (assignable in material)
+ BIND_CONSTANT( NODE_DEFAULT_TEXTURE );
BIND_CONSTANT( NODE_OUTPUT ); // output (shader type dependent)
BIND_CONSTANT( NODE_COMMENT ); // comment
BIND_CONSTANT( NODE_TYPE_MAX );
@@ -519,12 +529,15 @@ void ShaderGraph::node_add(ShaderType p_type, NodeType p_node_type,int p_id) {
case NODE_XFORM_TO_VEC: {} break; // 3 scalar input: {} break; 1 vec3 output
case NODE_SCALAR_INTERP: {} break; // scalar interpolation (with optional curve)
case NODE_VEC_INTERP: {} break; // vec3 interpolation (with optional curve)
+ case NODE_COLOR_RAMP: { node.param1=DVector<Color>(); node.param2=DVector<real_t>();} break; // vec3 interpolation (with optional curve)
+ case NODE_CURVE_MAP: { node.param1=DVector<Vector2>();} break; // vec3 interpolation (with optional curve)
case NODE_SCALAR_INPUT: {node.param1=_find_unique_name("Scalar"); node.param2=0;} break; // scalar uniform (assignable in material)
case NODE_VEC_INPUT: {node.param1=_find_unique_name("Vec3");node.param2=Vector3();} break; // vec3 uniform (assignable in material)
case NODE_RGB_INPUT: {node.param1=_find_unique_name("Color");node.param2=Color();} break; // color uniform (assignable in material)
case NODE_XFORM_INPUT: {node.param1=_find_unique_name("XForm"); node.param2=Transform();} break; // mat4 uniform (assignable in material)
case NODE_TEXTURE_INPUT: {node.param1=_find_unique_name("Tex"); } break; // texture input (assignable in material)
- case NODE_CUBEMAP_INPUT: {node.param1=_find_unique_name("Cube"); } break; // cubemap input (assignable in material)
+ case NODE_CUBEMAP_INPUT: {node.param1=_find_unique_name("Cube"); } break; // cubemap input (assignable in material)
+ case NODE_DEFAULT_TEXTURE: {}; break;
case NODE_OUTPUT: {} break; // output (shader type dependent)
case NODE_COMMENT: {} break; // comment
case NODE_TYPE_MAX: {};
@@ -964,6 +977,59 @@ ShaderGraph::VecFunc ShaderGraph::vec_func_node_get_function(ShaderType p_type,
return VecFunc(func);
}
+void ShaderGraph::color_ramp_node_set_ramp(ShaderType p_type,int p_id,const DVector<Color>& p_colors, const DVector<real_t>& p_offsets){
+
+ ERR_FAIL_INDEX(p_type,3);
+ ERR_FAIL_COND(!shader[p_type].node_map.has(p_id));
+ ERR_FAIL_COND(p_colors.size()!=p_offsets.size());
+ Node& n = shader[p_type].node_map[p_id];
+ n.param1=p_colors;
+ n.param2=p_offsets;
+ _request_update();
+
+}
+
+DVector<Color> ShaderGraph::color_ramp_node_get_colors(ShaderType p_type,int p_id) const{
+
+ ERR_FAIL_INDEX_V(p_type,3,DVector<Color>());
+ ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<Color>());
+ const Node& n = shader[p_type].node_map[p_id];
+ return n.param1;
+
+
+}
+
+DVector<real_t> ShaderGraph::color_ramp_node_get_offsets(ShaderType p_type,int p_id) const{
+
+ ERR_FAIL_INDEX_V(p_type,3,DVector<real_t>());
+ ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<real_t>());
+ const Node& n = shader[p_type].node_map[p_id];
+ return n.param2;
+
+}
+
+
+void ShaderGraph::curve_map_node_set_points(ShaderType p_type,int p_id,const DVector<Vector2>& p_points) {
+
+ ERR_FAIL_INDEX(p_type,3);
+ ERR_FAIL_COND(!shader[p_type].node_map.has(p_id));
+ Node& n = shader[p_type].node_map[p_id];
+ n.param1=p_points;
+ _request_update();
+
+}
+
+DVector<Vector2> ShaderGraph::curve_map_node_get_points(ShaderType p_type,int p_id) const{
+
+ ERR_FAIL_INDEX_V(p_type,3,DVector<Vector2>());
+ ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<Vector2>());
+ const Node& n = shader[p_type].node_map[p_id];
+ return n.param1;
+
+}
+
+
+
void ShaderGraph::input_node_set_name(ShaderType p_type,int p_id,const String& p_name){
ERR_FAIL_INDEX(p_type,3);
@@ -1223,7 +1289,7 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Binormal","BINORMAL","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UV","vec3(UV,0);","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UV2","UV2","",SLOT_TYPE_VEC,SLOT_IN},
- {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UVScreen","SCREEN_UV","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UVScreen","vec3(SCREEN_UV,0)","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN},
@@ -1254,6 +1320,43 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={
{MODE_MATERIAL,SHADER_TYPE_LIGHT,"ShadeParam","SHADE_PARAM","",SLOT_TYPE_SCALAR,SLOT_IN},
//light out
{MODE_MATERIAL,SHADER_TYPE_LIGHT,"Light","LIGHT","",SLOT_TYPE_VEC,SLOT_OUT},
+ //canvas item vertex in
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Vertex","vec3(SRC_VERTEX,0)","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"UV","SRC_UV","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Color","SRC_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Alpha","SRC_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"WorldMatrix","WORLD_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"ExtraMatrix","EXTRA_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"ProjectionMatrix","PROJECTION_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN},
+ //canvas item vertex out
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Vertex","VERTEX",".xy",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"UV","UV",".xy",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"PointSize","POINT_SIZE","",SLOT_TYPE_SCALAR,SLOT_OUT},
+ //canvas item fragment in
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Color","SRC_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Alpha","SRC_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"UV","vec3(UV,0)","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"UVScreen","vec3(SCREEN_UV,0)","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"TexPixelSize","vec3(TEXTURE_PIXEL_SIZE,0)","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN},
+ //canvas item fragment out
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_OUT},
+ //canvas item light in
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightDist","LIGHT_DISTANCE","",SLOT_TYPE_SCALAR,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightDir","vec3(LIGHT_DIR,0)","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN},
+ //canvas item light out
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Light","LIGHT","",SLOT_TYPE_VEC,SLOT_OUT},
//end
{MODE_MATERIAL,SHADER_TYPE_FRAGMENT,NULL,NULL,NULL,SLOT_TYPE_SCALAR,SLOT_OUT},
@@ -1299,12 +1402,15 @@ const ShaderGraph::NodeSlotInfo ShaderGraph::node_slot_info[]= {
{NODE_SCALAR_TO_VEC,{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR},{SLOT_TYPE_VEC,SLOT_MAX}}, // 3 scalar input,{SLOT_MAX},{SLOT_MAX}}, 1 vec3 output
{NODE_SCALAR_INTERP,{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar interpolation (with optional curve)
{NODE_VEC_INTERP,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_TYPE_SCALAR},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 interpolation (with optional curve)
+ {NODE_COLOR_RAMP,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 interpolation (with optional curve)
+ {NODE_CURVE_MAP,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 interpolation (with optional curve)
{NODE_SCALAR_INPUT,{SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar uniform (assignable in material)
{NODE_VEC_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 uniform (assignable in material)
{NODE_RGB_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // color uniform (assignable in material)
{NODE_XFORM_INPUT,{SLOT_MAX},{SLOT_TYPE_XFORM,SLOT_MAX}}, // mat4 uniform (assignable in material)
{NODE_TEXTURE_INPUT,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // texture input (assignable in material)
{NODE_CUBEMAP_INPUT,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // cubemap input (assignable in material)
+ {NODE_DEFAULT_TEXTURE,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // cubemap input (assignable in material)
{NODE_COMMENT,{SLOT_MAX},{SLOT_MAX}}, // comment
{NODE_TYPE_MAX,{SLOT_MAX},{SLOT_MAX}}
};
@@ -1663,6 +1769,11 @@ void ShaderGraph::_update_shader() {
} else if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL) {
if (name==("IN_NORMAL"))
code[i]="vec3 IN_NORMAL=NORMAL;\n"+code[i];
+ } else if (i==SHADER_TYPE_VERTEX && get_mode()==MODE_CANVAS_ITEM) {
+ if (name==("SRC_COLOR"))
+ code[i]="vec3 SRC_COLOR=COLOR.rgb;\n"+code[i];
+ if (name==("SRC_UV"))
+ code[i]="vec3 SRC_UV=vec3(UV,0);\n"+code[i];
}
}
@@ -1679,6 +1790,10 @@ void ShaderGraph::_update_shader() {
all_ok=false;
}
+ /*print_line("VERTEX: \n"+code[0]);
+ print_line("FRAGMENT: \n"+code[1]);
+ print_line("LIGHT: \n"+code[2]);*/
+
if (all_ok) {
set_code(code[0],code[1],code[2]);
}
@@ -1688,6 +1803,134 @@ void ShaderGraph::_update_shader() {
emit_signal(SceneStringNames::get_singleton()->updated);
}
+void ShaderGraph::_plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d,uint8_t* p_heights,bool *p_useds) {
+
+ float geometry[4][4];
+ float tmp1[4][4];
+ float tmp2[4][4];
+ float deltas[4][4];
+ double x, dx, dx2, dx3;
+ double y, dy, dy2, dy3;
+ double d, d2, d3;
+ int lastx, lasty;
+ int newx, newy;
+ int ntimes;
+ int i,j;
+
+ int xmax=255;
+ int ymax=255;
+
+ /* construct the geometry matrix from the segment */
+ for (i = 0; i < 4; i++) {
+ geometry[i][2] = 0;
+ geometry[i][3] = 0;
+ }
+
+ geometry[0][0] = (p_a[0] * xmax);
+ geometry[1][0] = (p_b[0] * xmax);
+ geometry[2][0] = (p_c[0] * xmax);
+ geometry[3][0] = (p_d[0] * xmax);
+
+ geometry[0][1] = (p_a[1] * ymax);
+ geometry[1][1] = (p_b[1] * ymax);
+ geometry[2][1] = (p_c[1] * ymax);
+ geometry[3][1] = (p_d[1] * ymax);
+
+ /* subdivide the curve ntimes (1000) times */
+ ntimes = 4 * xmax;
+ /* ntimes can be adjusted to give a finer or coarser curve */
+ d = 1.0 / ntimes;
+ d2 = d * d;
+ d3 = d * d * d;
+
+ /* construct a temporary matrix for determining the forward differencing deltas */
+ tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1;
+ tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0;
+ tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0;
+ tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0;
+
+ /* compose the basis and geometry matrices */
+
+ static const float CR_basis[4][4] =
+ {
+ { -0.5, 1.5, -1.5, 0.5 },
+ { 1.0, -2.5, 2.0, -0.5 },
+ { -0.5, 0.0, 0.5, 0.0 },
+ { 0.0, 1.0, 0.0, 0.0 },
+ };
+
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] +
+ CR_basis[i][1] * geometry[1][j] +
+ CR_basis[i][2] * geometry[2][j] +
+ CR_basis[i][3] * geometry[3][j]);
+ }
+ }
+ /* compose the above results to get the deltas matrix */
+
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ deltas[i][j] = (tmp2[i][0] * tmp1[0][j] +
+ tmp2[i][1] * tmp1[1][j] +
+ tmp2[i][2] * tmp1[2][j] +
+ tmp2[i][3] * tmp1[3][j]);
+ }
+ }
+
+
+ /* extract the x deltas */
+ x = deltas[0][0];
+ dx = deltas[1][0];
+ dx2 = deltas[2][0];
+ dx3 = deltas[3][0];
+
+ /* extract the y deltas */
+ y = deltas[0][1];
+ dy = deltas[1][1];
+ dy2 = deltas[2][1];
+ dy3 = deltas[3][1];
+
+
+ lastx = CLAMP (x, 0, xmax);
+ lasty = CLAMP (y, 0, ymax);
+
+ p_heights[lastx] = lasty;
+ p_useds[lastx] = true;
+
+ /* loop over the curve */
+ for (i = 0; i < ntimes; i++)
+ {
+ /* increment the x values */
+ x += dx;
+ dx += dx2;
+ dx2 += dx3;
+
+ /* increment the y values */
+ y += dy;
+ dy += dy2;
+ dy2 += dy3;
+
+ newx = CLAMP ((Math::round (x)), 0, xmax);
+ newy = CLAMP ((Math::round (y)), 0, ymax);
+
+ /* if this point is different than the last one...then draw it */
+ if ((lastx != newx) || (lasty != newy))
+ {
+ p_useds[newx]=true;
+ p_heights[newx]=newy;
+ }
+
+ lastx = newx;
+ lasty = newy;
+ }
+}
+
+
void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<String>& p_inputs,String& code) {
@@ -1730,7 +1973,7 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str
code+=OUTNAME(p_node->id,0)+"=TIME;\n";
}break;
case NODE_SCREEN_TEX: {
- code+=OUTNAME(p_node->id,0)+"=texscreen("+p_inputs[0]+");\n";
+ code+=OUTNAME(p_node->id,0)+"=texscreen("+p_inputs[0]+".xy);\n";
}break;
case NODE_SCALAR_OP: {
int op = p_node->param1;
@@ -1988,6 +2231,129 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str
code += OUTNAME(p_node->id,0)+"=mix("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+");\n";
}break;
+ case NODE_COLOR_RAMP: {
+
+ static const int color_ramp_len=512;
+ DVector<uint8_t> cramp;
+ cramp.resize(color_ramp_len*4);
+ {
+
+ DVector<Color> colors=p_node->param1;
+ DVector<real_t> offsets=p_node->param2;
+ int cc =colors.size();
+ DVector<uint8_t>::Write crw = cramp.write();
+ DVector<Color>::Read cr = colors.read();
+ DVector<real_t>::Read ofr = offsets.read();
+
+ int at=0;
+ Color color_at(0,0,0,1);
+ for(int i=0;i<=cc;i++) {
+
+ int pos;
+ Color to;
+ if (i==cc) {
+ if (at==color_ramp_len)
+ break;
+ pos=color_ramp_len;
+ to=Color(1,1,1,1);
+ } else {
+ to=cr[i];
+ pos= MIN(ofr[i]*color_ramp_len,color_ramp_len);
+ }
+ for(int j=at;j<pos;j++) {
+ float t = (j-at)/float(pos-at);
+ Color c = color_at.linear_interpolate(to,t);
+ crw[j*4+0]=Math::fast_ftoi( CLAMP(c.r*255.0,0,255) );
+ crw[j*4+1]=Math::fast_ftoi( CLAMP(c.g*255.0,0,255) );
+ crw[j*4+2]=Math::fast_ftoi( CLAMP(c.b*255.0,0,255) );
+ crw[j*4+3]=Math::fast_ftoi( CLAMP(c.a*255.0,0,255) );
+ }
+
+ at=pos;
+ color_at=to;
+ }
+ }
+
+ Image gradient(color_ramp_len,1,0,Image::FORMAT_RGBA,cramp);
+ Ref<ImageTexture> it = memnew( ImageTexture );
+ it->create_from_image(gradient,Texture::FLAG_FILTER|Texture::FLAG_MIPMAPS);
+
+ String crampname= "cramp_"+itos(p_node->id);
+ set_default_texture_param(crampname,it);
+
+ code +="uniform texture "+crampname+";\n";
+ code +="vec4 "+crampname+"_r=tex("+crampname+",vec2("+p_inputs[0]+",0));\n";
+ code += OUTNAME(p_node->id,0)+"="+crampname+"_r.rgb;\n";
+ code += OUTNAME(p_node->id,1)+"="+crampname+"_r.a;\n";
+
+ }break;
+ case NODE_CURVE_MAP: {
+ static const int curve_map_len=256;
+ bool mapped[256];
+ zeromem(mapped,sizeof(mapped));
+ DVector<uint8_t> cmap;
+ cmap.resize(curve_map_len);
+ {
+
+ DVector<Point2> points=p_node->param1;
+ int pc =points.size();
+ DVector<uint8_t>::Write cmw = cmap.write();
+ DVector<Point2>::Read pr = points.read();
+
+ Vector2 prev=Vector2(0,0);
+ Vector2 prev2=Vector2(0,0);
+
+ for(int i=-1;i<pc;i++) {
+
+ Vector2 next;
+ Vector2 next2;
+ if (i+1>=pc) {
+ next=Vector2(1,1);
+ } else {
+ next=Vector2(pr[i+1].x,pr[i+1].y);
+ }
+
+ if (i+2>=pc) {
+ next2=Vector2(1,1);
+ } else {
+ next2=Vector2(pr[i+2].x,pr[i+2].y);
+ }
+
+ /*if (i==-1 && prev.offset==next.offset) {
+ prev=next;
+ continue;
+ }*/
+
+ _plot_curve(prev2,prev,next,next2,cmw.ptr(),mapped);
+
+ prev2=prev;
+ prev=next;
+ }
+
+ uint8_t pp=0;
+ for(int i=0;i<curve_map_len;i++) {
+
+ if (!mapped[i]) {
+ cmw[i]=pp;
+ } else {
+ pp=cmw[i];
+ }
+ }
+ }
+
+
+
+ Image gradient(curve_map_len,1,0,Image::FORMAT_GRAYSCALE,cmap);
+ Ref<ImageTexture> it = memnew( ImageTexture );
+ it->create_from_image(gradient,Texture::FLAG_FILTER|Texture::FLAG_MIPMAPS);
+
+ String cmapname= "cmap_"+itos(p_node->id);
+ set_default_texture_param(cmapname,it);
+
+ code +="uniform texture "+cmapname+";\n";
+ code += OUTNAME(p_node->id,0)+"=tex("+cmapname+",vec2("+p_inputs[0]+",0)).r;\n";
+
+ }break;
case NODE_SCALAR_INPUT: {
String name = p_node->param1;
float dv=p_node->param2;
@@ -2043,6 +2409,22 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str
code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n";
code += OUTNAME(p_node->id,1)+"="+rname+".a;\n";
}break;
+ case NODE_DEFAULT_TEXTURE: {
+
+ if (get_mode()==MODE_CANVAS_ITEM && p_type==SHADER_TYPE_FRAGMENT) {
+
+ String rname="rt_default_tex"+itos(p_node->id);
+ code +="vec4 "+rname+"=tex(TEXTURE,"+p_inputs[0]+".xy);\n";
+ code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n";
+ code += OUTNAME(p_node->id,1)+"="+rname+".a;\n";
+
+ } else {
+ //not supported
+ code += OUTNAME(p_node->id,0)+"=vec3(0,0,0);\n";
+ code += OUTNAME(p_node->id,1)+"=1.0;\n";
+
+ }
+ } break;
case NODE_OUTPUT: {
diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h
index c515f6e101..5c34bedadd 100644
--- a/scene/resources/shader_graph.h
+++ b/scene/resources/shader_graph.h
@@ -66,14 +66,15 @@ public:
NODE_VEC_TO_XFORM, // 3 vec input, 1 xform output
NODE_SCALAR_INTERP, // scalar interpolation (with optional curve)
NODE_VEC_INTERP, // vec3 interpolation (with optional curve)
- /*NODE_SCALAR_CURVE_REMAP,
- NODE_VEC_CURVE_REMAP,*/
- NODE_SCALAR_INPUT, // scalar uniform (assignable in material)
+ NODE_COLOR_RAMP, //take scalar, output vec3
+ NODE_CURVE_MAP, //take scalar, otput scalar
+ NODE_SCALAR_INPUT, // scalar uniform (assignable in material)
NODE_VEC_INPUT, // vec3 uniform (assignable in material)
NODE_RGB_INPUT, // color uniform (assignable in material)
NODE_XFORM_INPUT, // mat4 uniform (assignable in material)
NODE_TEXTURE_INPUT, // texture input (assignable in material)
NODE_CUBEMAP_INPUT, // cubemap input (assignable in material)
+ NODE_DEFAULT_TEXTURE,
NODE_OUTPUT, // output (shader type dependent)
NODE_COMMENT, // comment
NODE_TYPE_MAX
@@ -174,6 +175,7 @@ private:
void _update_shader();
void _request_update();
+ void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d,uint8_t* p_heights,bool *p_useds);
void _add_node_code(ShaderType p_type,Node *p_node,const Vector<String>& p_inputs,String& code);
Array _get_node_list(ShaderType p_type) const;
@@ -315,6 +317,13 @@ public:
void vec_func_node_set_function(ShaderType p_which,int p_id,VecFunc p_func);
VecFunc vec_func_node_get_function(ShaderType p_which,int p_id) const;
+ void color_ramp_node_set_ramp(ShaderType p_which,int p_id,const DVector<Color>& p_colors, const DVector<real_t>& p_offsets);
+ DVector<Color> color_ramp_node_get_colors(ShaderType p_which,int p_id) const;
+ DVector<real_t> color_ramp_node_get_offsets(ShaderType p_which,int p_id) const;
+
+ void curve_map_node_set_points(ShaderType p_which, int p_id, const DVector<Vector2>& p_points);
+ DVector<Vector2> curve_map_node_get_points(ShaderType p_which,int p_id) const;
+
void input_node_set_name(ShaderType p_which,int p_id,const String& p_name);
String input_node_get_name(ShaderType p_which,int p_id);
@@ -397,7 +406,6 @@ VARIANT_ENUM_CAST( ShaderGraph::GraphError );
class MaterialShaderGraph : public ShaderGraph {
OBJ_TYPE( MaterialShaderGraph, ShaderGraph );
- RES_BASE_EXTENSION("sgp");
public:
@@ -407,4 +415,17 @@ public:
}
};
+class CanvasItemShaderGraph : public ShaderGraph {
+
+ OBJ_TYPE( CanvasItemShaderGraph, ShaderGraph );
+
+public:
+
+
+ CanvasItemShaderGraph() : ShaderGraph(MODE_CANVAS_ITEM) {
+
+ }
+};
+
+
#endif // SHADER_GRAPH_H
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 316b5e91eb..ca4bd3d253 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -85,6 +85,12 @@ void StyleBox::_bind_methods() {
ObjectTypeDB::bind_method(_MD("draw"),&StyleBox::draw);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/left", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_LEFT );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/right", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_RIGHT );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/top", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_TOP);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin/bottom", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_BOTTOM );
+
+
}
StyleBox::StyleBox() {
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index dae055890b..2c1502288b 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -38,19 +38,19 @@ Size2 Texture::get_size() const {
}
-void Texture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate) const {
+void Texture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const {
- VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, get_size()),get_rid(),false,p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, get_size()),get_rid(),false,p_modulate,p_transpose);
}
-void Texture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate) const {
+void Texture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const {
- VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,get_rid(),p_tile,p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,get_rid(),p_tile,p_modulate,p_transpose);
}
-void Texture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) const{
+void Texture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const{
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,get_rid(),p_src_rect,p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,get_rid(),p_src_rect,p_modulate,p_transpose);
}
bool Texture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const {
@@ -70,9 +70,9 @@ void Texture::_bind_methods() {
ObjectTypeDB::bind_method(_MD("has_alpha"),&Texture::has_alpha);
ObjectTypeDB::bind_method(_MD("set_flags","flags"),&Texture::set_flags);
ObjectTypeDB::bind_method(_MD("get_flags"),&Texture::get_flags);
- ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","modulate"),&Texture::draw,DEFVAL(Color(1,1,1)));
- ObjectTypeDB::bind_method(_MD("draw_rect","canvas_item","rect","tile","modulate"),&Texture::draw_rect,DEFVAL(Color(1,1,1)));
- ObjectTypeDB::bind_method(_MD("draw_rect_region","canvas_item","rect","src_rect","modulate"),&Texture::draw_rect_region,DEFVAL(Color(1,1,1)));
+ ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","modulate"),&Texture::draw,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("draw_rect","canvas_item","rect","tile","modulate"),&Texture::draw_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ObjectTypeDB::bind_method(_MD("draw_rect_region","canvas_item","rect","src_rect","modulate"),&Texture::draw_rect_region,DEFVAL(Color(1,1,1)),DEFVAL(false));
BIND_CONSTANT( FLAG_MIPMAPS );
BIND_CONSTANT( FLAG_REPEAT );
@@ -327,28 +327,27 @@ bool ImageTexture::has_alpha() const {
}
-void ImageTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate) const {
+void ImageTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const {
if ((w|h)==0)
return;
- VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, Size2(w,h)),texture,false,p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, Size2(w,h)),texture,false,p_modulate,p_transpose);
}
-void ImageTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate) const {
+void ImageTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const {
if ((w|h)==0)
return;
- VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,texture,p_tile,p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,texture,p_tile,p_modulate,p_transpose);
}
-void ImageTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) const{
+void ImageTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const{
if ((w|h)==0)
return;
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,texture,p_src_rect,p_modulate);
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,texture,p_src_rect,p_modulate,p_transpose);
}
-
void ImageTexture::set_size_override(const Size2& p_size) {
Size2 s=p_size;
@@ -546,7 +545,7 @@ void AtlasTexture::_bind_methods() {
-void AtlasTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate) const {
+void AtlasTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const {
Rect2 rc=region;
@@ -561,10 +560,10 @@ void AtlasTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_m
rc.size.height=atlas->get_height();
}
- VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,Rect2(p_pos+margin.pos,rc.size),atlas->get_rid(),rc,p_modulate);
+ VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,Rect2(p_pos+margin.pos,rc.size),atlas->get_rid(),rc,p_modulate,p_transpose);
}
-void AtlasTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate) const {
+void AtlasTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const {
Rect2 rc=region;
@@ -582,10 +581,10 @@ void AtlasTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,
Vector2 scale = p_rect.size / (region.size+margin.size);
Rect2 dr( p_rect.pos+margin.pos*scale,rc.size*scale );
- VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),rc,p_modulate);
+ VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),rc,p_modulate,p_transpose);
}
-void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) const {
+void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const {
//this might not necesarily work well if using a rect, needs to be fixed properly
Rect2 rc=region;
@@ -615,7 +614,7 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const
}
Rect2 dr( p_rect.pos+ofs*scale,src_c.size*scale );
- VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),src_c,p_modulate);
+ VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),src_c,p_modulate,p_transpose);
}
bool AtlasTexture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const {
@@ -801,15 +800,16 @@ void LargeTexture::_bind_methods() {
-void LargeTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate) const {
+void LargeTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const {
for(int i=0;i<pieces.size();i++) {
- pieces[i].texture->draw(p_canvas_item,pieces[i].offset+p_pos,p_modulate);
+ // TODO
+ pieces[i].texture->draw(p_canvas_item,pieces[i].offset+p_pos,p_modulate,p_transpose);
}
}
-void LargeTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate) const {
+void LargeTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const {
//tiling not supported for this
if (size.x==0 || size.y==0)
@@ -819,11 +819,11 @@ void LargeTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,
for(int i=0;i<pieces.size();i++) {
- pieces[i].texture->draw_rect(p_canvas_item,Rect2(pieces[i].offset*scale+p_rect.pos,pieces[i].texture->get_size()*scale),false,p_modulate);
+ // TODO
+ pieces[i].texture->draw_rect(p_canvas_item,Rect2(pieces[i].offset*scale+p_rect.pos,pieces[i].texture->get_size()*scale),false,p_modulate,p_transpose);
}
-
}
-void LargeTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate) const {
+void LargeTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate, bool p_transpose) const {
//tiling not supported for this
@@ -834,6 +834,7 @@ void LargeTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const
for(int i=0;i<pieces.size();i++) {
+ // TODO
Rect2 rect( pieces[i].offset, pieces[i].texture->get_size());
if (!p_src_rect.intersects(rect))
continue;
@@ -842,7 +843,7 @@ void LargeTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const
target.size*=scale;
target.pos=p_rect.pos+(p_src_rect.pos+rect.pos)*scale;
local.pos-=rect.pos;
- pieces[i].texture->draw_rect_region(p_canvas_item,target,local,p_modulate);
+ pieces[i].texture->draw_rect_region(p_canvas_item,target,local,p_modulate,p_transpose);
}
}
@@ -935,21 +936,21 @@ float CubeMap::get_lossy_storage_quality() const {
bool CubeMap::_set(const StringName& p_name, const Variant& p_value) {
- if (p_name=="side/left")
+ if (p_name=="side/left") {
set_side(SIDE_LEFT,p_value);
- if (p_name=="side/right")
+ } else if (p_name=="side/right") {
set_side(SIDE_RIGHT,p_value);
- if (p_name=="side/bottom")
+ } else if (p_name=="side/bottom") {
set_side(SIDE_BOTTOM,p_value);
- if (p_name=="side/top")
+ } else if (p_name=="side/top") {
set_side(SIDE_TOP,p_value);
- if (p_name=="side/front")
+ } else if (p_name=="side/front") {
set_side(SIDE_FRONT,p_value);
- if (p_name=="side/back")
+ } else if (p_name=="side/back") {
set_side(SIDE_BACK,p_value);
- else if (p_name=="flags")
+ } else if (p_name=="flags") {
set_flags(p_value);
- else if (p_name=="storage") {
+ } else if (p_name=="storage") {
storage=Storage(p_value.operator int());
} else if (p_name=="lossy_quality") {
lossy_storage_quality=p_value;
@@ -962,25 +963,25 @@ bool CubeMap::_set(const StringName& p_name, const Variant& p_value) {
bool CubeMap::_get(const StringName& p_name,Variant &r_ret) const {
- if (p_name=="side/left")
+ if (p_name=="side/left") {
r_ret=get_side(SIDE_LEFT);
- if (p_name=="side/right")
+ } else if (p_name=="side/right") {
r_ret=get_side(SIDE_RIGHT);
- if (p_name=="side/bottom")
+ } else if (p_name=="side/bottom") {
r_ret=get_side(SIDE_BOTTOM);
- if (p_name=="side/top")
+ } else if (p_name=="side/top") {
r_ret=get_side(SIDE_TOP);
- if (p_name=="side/front")
+ } else if (p_name=="side/front") {
r_ret=get_side(SIDE_FRONT);
- if (p_name=="side/back")
+ } else if (p_name=="side/back") {
r_ret=get_side(SIDE_BACK);
- else if (p_name=="flags")
+ } else if (p_name=="flags") {
r_ret= flags;
- else if (p_name=="storage")
+ } else if (p_name=="storage") {
r_ret= storage;
- else if (p_name=="lossy_quality")
+ } else if (p_name=="lossy_quality") {
r_ret= lossy_storage_quality;
- else
+ } else
return false;
return true;
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 4bb2f6d979..c1122b005d 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -69,9 +69,9 @@ public:
virtual void set_flags(uint32_t p_flags)=0;
virtual uint32_t get_flags() const=0;
- virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const;
- virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const;
- virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const;
+ virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
+ virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
+ virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const;
@@ -135,10 +135,9 @@ public:
virtual RID get_rid() const;
bool has_alpha() const;
- virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const;
- virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const;
- virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const;
-
+ virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
+ virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
+ virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
void set_storage(Storage p_storage);
Storage get_storage() const;
@@ -191,9 +190,9 @@ public:
void set_margin(const Rect2& p_margin);
Rect2 get_margin() const ;
- virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const;
- virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const;
- virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const;
+ virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
+ virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
+ virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const;
@@ -241,9 +240,9 @@ public:
Vector2 get_piece_offset(int p_idx) const;
Ref<Texture> get_piece_texture(int p_idx) const;
- virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const;
- virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const;
- virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const;
+ virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
+ virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
+ virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
LargeTexture();
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index af5e6d4165..c30ff0044e 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -41,6 +41,7 @@ SceneStringNames::SceneStringNames() {
visibility_changed=StaticCString::create("visibility_changed");
input_event=StaticCString::create("input_event");
shader_shader=StaticCString::create("shader/shader");
+ shader_unshaded=StaticCString::create("shader/unshaded");
enter_tree=StaticCString::create("enter_tree");
exit_tree=StaticCString::create("exit_tree");
item_rect_changed=StaticCString::create("item_rect_changed");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 14e5e83b8d..184cbe347b 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -56,6 +56,7 @@ public:
StringName _input_event;
StringName item_rect_changed;
StringName shader_shader;
+ StringName shader_unshaded;
StringName enter_tree;
StringName exit_tree;
StringName size_flags_changed;