summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/instance_placeholder.cpp74
-rw-r--r--scene/main/instance_placeholder.h37
-rw-r--r--scene/main/node.cpp78
-rw-r--r--scene/main/node.h37
-rw-r--r--scene/main/scene_main_loop.cpp190
-rw-r--r--scene/main/scene_main_loop.h42
-rw-r--r--scene/main/timer.cpp5
-rw-r--r--scene/main/viewport.cpp78
-rw-r--r--scene/main/viewport.h5
9 files changed, 525 insertions, 21 deletions
diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp
new file mode 100644
index 0000000000..370eb1e74a
--- /dev/null
+++ b/scene/main/instance_placeholder.cpp
@@ -0,0 +1,74 @@
+#include "instance_placeholder.h"
+
+#include "scene/resources/packed_scene.h"
+#include "io/resource_loader.h"
+
+bool InstancePlaceholder::_set(const StringName& p_name, const Variant& p_value) {
+
+ PropSet ps;
+ ps.name=p_name;
+ ps.value=p_value;
+ stored_values.push_back(ps);
+ return true;
+}
+
+bool InstancePlaceholder::_get(const StringName& p_name,Variant &r_ret) const{
+
+ return false;
+}
+void InstancePlaceholder::_get_property_list( List<PropertyInfo> *p_list) const{
+
+
+}
+
+
+void InstancePlaceholder::set_path(const String& p_name) {
+
+ path=p_name;
+}
+
+String InstancePlaceholder::get_path() const {
+
+ return path;
+}
+void InstancePlaceholder::replace_by_instance(const Ref<PackedScene> &p_custom_scene){
+
+ ERR_FAIL_COND(!is_inside_tree());
+
+ Node *base = get_parent();
+ if (!base)
+ return;
+
+ Ref<PackedScene> ps;
+ if (p_custom_scene.is_valid())
+ ps = p_custom_scene;
+ else
+ ps = ResourceLoader::load(path,"PackedScene");
+
+ if (!ps.is_valid())
+ return;
+ Node *scene = ps->instance();
+ scene->set_name(get_name());
+ int pos = get_position_in_parent();
+
+ for(List<PropSet>::Element *E=stored_values.front();E;E=E->next()) {
+ scene->set(E->get().name,E->get().value);
+ }
+
+ queue_delete();
+
+ base->remove_child(this);
+ base->add_child(scene);
+ base->move_child(scene,pos);
+
+}
+
+void InstancePlaceholder::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("replace_by_instance","custom_scene:PackedScene"),&InstancePlaceholder::replace_by_instance,DEFVAL(Variant()));
+}
+
+InstancePlaceholder::InstancePlaceholder() {
+
+
+}
diff --git a/scene/main/instance_placeholder.h b/scene/main/instance_placeholder.h
new file mode 100644
index 0000000000..e9e76e7a2d
--- /dev/null
+++ b/scene/main/instance_placeholder.h
@@ -0,0 +1,37 @@
+#ifndef INSTANCE_PLACEHOLDER_H
+#define INSTANCE_PLACEHOLDER_H
+
+#include "scene/main/node.h"
+
+class PackedScene;
+
+class InstancePlaceholder : public Node {
+
+ OBJ_TYPE(InstancePlaceholder,Node);
+
+ String path;
+ struct PropSet {
+ StringName name;
+ Variant value;
+ };
+
+ List<PropSet> stored_values;
+
+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;
+
+ static void _bind_methods();
+
+public:
+
+ void set_path(const String& p_name);
+ String get_path() const;
+
+ void replace_by_instance(const Ref<PackedScene>& p_custom_scene=Ref<PackedScene>());
+
+ InstancePlaceholder();
+};
+
+#endif // INSTANCE_PLACEHOLDER_H
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 8336ce35f6..631dc8dcc7 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -841,6 +841,20 @@ Node *Node::get_child(int p_index) const {
return data.children[p_index];
}
+
+Node *Node::_get_child_by_name(const StringName& p_name) const {
+
+ int cc=data.children.size();
+ Node* const* cd=data.children.ptr();
+
+ for(int i=0;i<cc;i++){
+ if (cd[i]->data.name==p_name)
+ return cd[i];
+ }
+
+ return NULL;
+}
+
Node *Node::_get_node(const NodePath& p_path) const {
ERR_FAIL_COND_V( !data.inside_tree && p_path.is_absolute(), NULL );
@@ -906,8 +920,10 @@ Node *Node::_get_node(const NodePath& p_path) const {
Node *Node::get_node(const NodePath& p_path) const {
Node *node = _get_node(p_path);
- ERR_EXPLAIN("Node not found: "+p_path);
- ERR_FAIL_COND_V(!node,NULL);
+ if (!node) {
+ ERR_EXPLAIN("Node not found: "+p_path);
+ ERR_FAIL_COND_V(!node,NULL);
+ }
return node;
}
@@ -1036,6 +1052,7 @@ void Node::get_owned_by(Node *p_by,List<Node*> *p_owned) {
void Node::_set_owner_nocheck(Node* p_owner) {
+ ERR_FAIL_COND(data.owner);
data.owner=p_owner;
data.owner->data.owned.push_back( this );
data.OW = data.owner->data.owned.back();
@@ -1332,7 +1349,29 @@ String Node::get_filename() const {
return data.filename;
}
+void Node::set_editable_instance(Node* p_node,bool p_editable) {
+
+ ERR_FAIL_NULL(p_node);
+ ERR_FAIL_COND(!is_a_parent_of(p_node));
+ NodePath p = get_path_to(p_node);
+ if (!p_editable)
+ data.editable_instances.erase(p);
+ else
+ data.editable_instances[p]=true;
+
+}
+
+bool Node::is_editable_instance(Node *p_node) const {
+
+ if (!p_node)
+ return false; //easier, null is never editable :)
+ ERR_FAIL_COND_V(!is_a_parent_of(p_node),false);
+ NodePath p = get_path_to(p_node);
+ return data.editable_instances.has(p);
+}
+
+#if 0
void Node::generate_instance_state() {
@@ -1383,13 +1422,36 @@ Dictionary Node::get_instance_state() const {
return data.instance_state;
}
-Vector<StringName> Node::get_instance_groups() const {
+#endif
+
+void Node::set_scene_instance_state(const Ref<SceneState>& p_state) {
+
+ data.instance_state=p_state;
+}
+
+Ref<SceneState> Node::get_scene_instance_state() const{
+
+ return data.instance_state;
+}
+
+void Node::set_scene_inherited_state(const Ref<SceneState>& p_state) {
+
+ data.inherited_state=p_state;
+}
+
+Ref<SceneState> Node::get_scene_inherited_state() const{
- return data.instance_groups;
+ return data.inherited_state;
}
-Vector<Node::Connection> Node::get_instance_connections() const{
- return data.instance_connections;
+void Node::set_scene_instance_load_placeholder(bool p_enable) {
+
+ data.use_placeholder=p_enable;
+}
+
+bool Node::get_scene_instance_load_placeholder() const{
+
+ return data.use_placeholder;
}
int Node::get_position_in_parent() const {
@@ -1931,7 +1993,7 @@ void Node::_bind_methods() {
ObjectTypeDB::bind_method(_MD("has_node","path"),&Node::has_node);
ObjectTypeDB::bind_method(_MD("get_node:Node","path"),&Node::get_node);
ObjectTypeDB::bind_method(_MD("get_parent:Parent"),&Node::get_parent);
- ObjectTypeDB::bind_method(_MD("find_node:Node","mask","recursive","owned"),&Node::get_node,DEFVAL(true),DEFVAL(true));
+ ObjectTypeDB::bind_method(_MD("find_node:Node","mask","recursive","owned"),&Node::find_node,DEFVAL(true),DEFVAL(true));
ObjectTypeDB::bind_method(_MD("has_node_and_resource","path"),&Node::has_node_and_resource);
ObjectTypeDB::bind_method(_MD("get_node_and_resource","path"),&Node::_get_node_and_resource);
@@ -2049,6 +2111,7 @@ Node::Node() {
data.parent_owned=false;
data.in_constructor=true;
data.viewport=NULL;
+ data.use_placeholder=false;
}
Node::~Node() {
@@ -2065,3 +2128,4 @@ Node::~Node() {
}
+////////////////////////////////
diff --git a/scene/main/node.h b/scene/main/node.h
index a6d5bfbd9f..87fa4dd6ca 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -38,6 +38,7 @@
class Viewport;
+class SceneState;
class Node : public Object {
OBJ_TYPE( Node, Object );
@@ -69,9 +70,10 @@ private:
struct Data {
String filename;
- Dictionary instance_state;
- Vector<StringName> instance_groups;
- Vector<Connection> instance_connections;
+ Ref<SceneState> instance_state;
+ Ref<SceneState> inherited_state;
+
+ HashMap<NodePath,int> editable_instances;
Node *parent;
Node *owner;
@@ -96,6 +98,7 @@ private:
PauseMode pause_mode;
Node *pause_owner;
// variables used to properly sort the node when processing, ignored otherwise
+ //should move all the stuff below to bits
bool fixed_process;
bool idle_process;
@@ -105,6 +108,9 @@ private:
bool parent_owned;
bool in_constructor;
+ bool use_placeholder;
+
+
} data;
@@ -112,6 +118,7 @@ private:
virtual bool _use_builtin_script() const { return true; }
Node *_get_node(const NodePath& p_path) const;
+ Node *_get_child_by_name(const StringName& p_name) const;
@@ -151,7 +158,7 @@ protected:
static void _bind_methods();
-friend class PackedScene;
+friend class SceneState;
void _add_child_nocheck(Node* p_child,const StringName& p_name);
void _set_owner_nocheck(Node* p_owner);
@@ -208,7 +215,7 @@ public:
struct GroupInfo {
- String name;
+ StringName name;
bool persistent;
};
@@ -229,7 +236,11 @@ public:
void set_filename(const String& p_filename);
String get_filename() const;
-
+
+ void set_editable_instance(Node* p_node,bool p_editable);
+ bool is_editable_instance(Node* p_node) const;
+
+
/* NOTIFICATIONS */
void propagate_notification(int p_notification);
@@ -261,10 +272,14 @@ public:
//Node *clone_tree() const;
// used by editors, to save what has changed only
- void generate_instance_state();
- Dictionary get_instance_state() const;
- Vector<StringName> get_instance_groups() const;
- Vector<Connection> get_instance_connections() const;
+ void set_scene_instance_state(const Ref<SceneState>& p_state);
+ Ref<SceneState> get_scene_instance_state() const;
+
+ void set_scene_inherited_state(const Ref<SceneState>& p_state);
+ Ref<SceneState> get_scene_inherited_state() const;
+
+ void set_scene_instance_load_placeholder(bool p_enable);
+ bool get_scene_instance_load_placeholder() const;
static Vector<Variant> make_binds(VARIANT_ARG_LIST);
@@ -307,6 +322,4 @@ public:
typedef Set<Node*,Node::Comparator> NodeSet;
-
-
#endif
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index 45e3d92ece..adf053f5c9 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -42,6 +42,8 @@
#include "io/resource_loader.h"
#include "viewport.h"
#include "scene/resources/packed_scene.h"
+#include "scene/resources/material.h"
+#include "scene/resources/mesh.h"
void SceneTree::tree_changed() {
@@ -470,7 +472,6 @@ void SceneTree::init() {
input_handled=false;
- editor_hint=false;
pause=false;
root->_set_tree(this);
@@ -624,6 +625,175 @@ bool SceneTree::is_editor_hint() const {
return editor_hint;
}
+void SceneTree::set_debug_collisions_hint(bool p_enabled) {
+
+ debug_collisions_hint=p_enabled;
+}
+
+bool SceneTree::is_debugging_collisions_hint() const {
+
+ return debug_collisions_hint;
+}
+
+void SceneTree::set_debug_navigation_hint(bool p_enabled) {
+
+ debug_navigation_hint=p_enabled;
+}
+
+bool SceneTree::is_debugging_navigation_hint() const {
+
+ return debug_navigation_hint;
+}
+
+void SceneTree::set_debug_collisions_color(const Color& p_color) {
+
+ debug_collisions_color=p_color;
+}
+
+Color SceneTree::get_debug_collisions_color() const {
+
+ return debug_collisions_color;
+}
+
+void SceneTree::set_debug_collision_contact_color(const Color& p_color) {
+
+ debug_collision_contact_color=p_color;
+}
+
+Color SceneTree::get_debug_collision_contact_color() const {
+
+ return debug_collision_contact_color;
+}
+
+void SceneTree::set_debug_navigation_color(const Color& p_color) {
+
+ debug_navigation_color=p_color;
+}
+
+Color SceneTree::get_debug_navigation_color() const {
+
+ return debug_navigation_color;
+}
+
+void SceneTree::set_debug_navigation_disabled_color(const Color& p_color) {
+
+ debug_navigation_disabled_color=p_color;
+}
+
+Color SceneTree::get_debug_navigation_disabled_color() const {
+
+ return debug_navigation_disabled_color;
+}
+
+Ref<Material> SceneTree::get_debug_navigation_material() {
+
+ if (navigation_material.is_valid())
+ return navigation_material;
+
+ Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
+ line_material->set_flag(Material::FLAG_UNSHADED, true);
+ line_material->set_line_width(3.0);
+ line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
+ line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
+ line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,get_debug_navigation_color());
+
+ navigation_material=line_material;
+
+ return navigation_material;
+
+}
+
+Ref<Material> SceneTree::get_debug_navigation_disabled_material(){
+
+ if (navigation_disabled_material.is_valid())
+ return navigation_disabled_material;
+
+ Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
+ line_material->set_flag(Material::FLAG_UNSHADED, true);
+ line_material->set_line_width(3.0);
+ line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
+ line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
+ line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,get_debug_navigation_disabled_color());
+
+ navigation_disabled_material=line_material;
+
+ return navigation_disabled_material;
+
+}
+Ref<Material> SceneTree::get_debug_collision_material() {
+
+ if (collision_material.is_valid())
+ return collision_material;
+
+
+ Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
+ line_material->set_flag(Material::FLAG_UNSHADED, true);
+ line_material->set_line_width(3.0);
+ line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
+ line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
+ line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,get_debug_collisions_color());
+
+ collision_material=line_material;
+
+ return collision_material;
+}
+
+Ref<Mesh> SceneTree::get_debug_contact_mesh() {
+
+ if (debug_contact_mesh.is_valid())
+ return debug_contact_mesh;
+
+ debug_contact_mesh = Ref<Mesh>( memnew( Mesh ) );
+
+ Ref<FixedMaterial> mat = memnew( FixedMaterial );
+ mat->set_flag(Material::FLAG_UNSHADED,true);
+ mat->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
+ mat->set_parameter(FixedMaterial::PARAM_DIFFUSE,get_debug_collision_contact_color());
+
+ Vector3 diamond[6]={
+ Vector3(-1, 0, 0),
+ Vector3( 1, 0, 0),
+ Vector3( 0, -1, 0),
+ Vector3( 0, 1, 0),
+ Vector3( 0, 0, -1),
+ Vector3( 0, 0, 1)
+ };
+
+ int diamond_faces[8*3]={
+ 0,2,4,
+ 0,3,4,
+ 1,2,4,
+ 1,3,4,
+ 0,2,5,
+ 0,3,5,
+ 1,2,5,
+ 1,3,5,
+ };
+
+ DVector<int> indices;
+ for(int i=0;i<8*3;i++)
+ indices.push_back(diamond_faces[i]);
+
+ DVector<Vector3> vertices;
+ for(int i=0;i<6;i++)
+ vertices.push_back(diamond[i]*0.1);
+
+ Array arr;
+ arr.resize(Mesh::ARRAY_MAX);
+ arr[Mesh::ARRAY_VERTEX]=vertices;
+ arr[Mesh::ARRAY_INDEX]=indices;
+
+
+ debug_contact_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,arr);
+ debug_contact_mesh->surface_set_material(0,mat);
+
+ return debug_contact_mesh;
+
+}
+
+
+
void SceneTree::set_pause(bool p_enabled) {
if (p_enabled==pause)
@@ -1424,6 +1594,11 @@ void SceneTree::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_editor_hint","enable"),&SceneTree::set_editor_hint);
ObjectTypeDB::bind_method(_MD("is_editor_hint"),&SceneTree::is_editor_hint);
+ ObjectTypeDB::bind_method(_MD("set_debug_collisions_hint","enable"),&SceneTree::set_debug_collisions_hint);
+ ObjectTypeDB::bind_method(_MD("is_debugging_collisions_hint"),&SceneTree::is_debugging_collisions_hint);
+ ObjectTypeDB::bind_method(_MD("set_debug_navigation_hint","enable"),&SceneTree::set_debug_navigation_hint);
+ ObjectTypeDB::bind_method(_MD("is_debugging_navigation_hint"),&SceneTree::is_debugging_navigation_hint);
+
#ifdef TOOLS_ENABLED
ObjectTypeDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneTree::set_edited_scene_root);
ObjectTypeDB::bind_method(_MD("get_edited_scene_root"),&SceneTree::get_edited_scene_root);
@@ -1490,10 +1665,23 @@ void SceneTree::_bind_methods() {
}
+SceneTree *SceneTree::singleton=NULL;
+
SceneTree::SceneTree() {
+ singleton=this;
_quit=false;
initialized=false;
+ editor_hint=false;
+ debug_collisions_hint=false;
+ debug_navigation_hint=false;
+ debug_collisions_color=GLOBAL_DEF("debug/collision_shape_color",Color(0.0,0.6,0.7,0.5));
+ debug_collision_contact_color=GLOBAL_DEF("debug/collision_contact_color",Color(1.0,0.2,0.1,0.8));
+ debug_navigation_color=GLOBAL_DEF("debug/navigation_geometry_color",Color(0.1,1.0,0.7,0.4));
+ debug_navigation_disabled_color=GLOBAL_DEF("debug/navigation_disabled_geometry_color",Color(1.0,0.7,0.1,0.4));
+ collision_debug_contacts=GLOBAL_DEF("debug/collision_max_contacts_displayed",10000);
+
+
tree_version=1;
fixed_process_time=1;
idle_process_time=1;
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index 1f09d9c546..8d9021d24e 100644
--- a/scene/main/scene_main_loop.h
+++ b/scene/main/scene_main_loop.h
@@ -45,6 +45,8 @@ class SceneTree;
class PackedScene;
class Node;
class Viewport;
+class Material;
+class Mesh;
class SceneTree : public MainLoop {
@@ -87,6 +89,8 @@ private:
uint32_t last_id;
bool editor_hint;
+ bool debug_collisions_hint;
+ bool debug_navigation_hint;
bool pause;
int root_lock;
@@ -138,9 +142,20 @@ private:
Node *current_scene;
+ Color debug_collisions_color;
+ Color debug_collision_contact_color;
+ Color debug_navigation_color;
+ Color debug_navigation_disabled_color;
+ Ref<Mesh> debug_contact_mesh;
+ Ref<Material> navigation_material;
+ Ref<Material> navigation_disabled_material;
+ Ref<Material> collision_material;
+ int collision_debug_contacts;
+
void _change_scene(Node* p_to);
//void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2);
+ static SceneTree *singleton;
friend class Node;
void tree_changed();
@@ -270,6 +285,32 @@ public:
void set_camera(const RID& p_camera);
RID get_camera() const;
+ void set_debug_collisions_hint(bool p_enabled);
+ bool is_debugging_collisions_hint() const;
+
+ void set_debug_navigation_hint(bool p_enabled);
+ bool is_debugging_navigation_hint() const;
+
+ void set_debug_collisions_color(const Color& p_color);
+ Color get_debug_collisions_color() const;
+
+ void set_debug_collision_contact_color(const Color& p_color);
+ Color get_debug_collision_contact_color() const;
+
+ void set_debug_navigation_color(const Color& p_color);
+ Color get_debug_navigation_color() const;
+
+ void set_debug_navigation_disabled_color(const Color& p_color);
+ Color get_debug_navigation_disabled_color() const;
+
+
+ Ref<Material> get_debug_navigation_material();
+ Ref<Material> get_debug_navigation_disabled_material();
+ Ref<Material> get_debug_collision_material();
+ Ref<Mesh> get_debug_contact_mesh();
+
+ int get_collision_debug_contact_count() { return collision_debug_contacts; }
+
int64_t get_frame() const;
int get_node_count() const;
@@ -297,6 +338,7 @@ public:
//used by Main::start, don't use otherwise
void add_current_scene(Node * p_current);
+ static SceneTree* get_singleton() { return singleton; }
SceneTree();
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index 3a80382a40..1bd22a9db1 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -182,11 +182,14 @@ void Timer::_bind_methods() {
ADD_SIGNAL( MethodInfo("timeout") );
- ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_timer_process_mode"), _SCS("get_timer_process_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_timer_process_mode"), _SCS("get_timer_process_mode") );
ADD_PROPERTY( PropertyInfo(Variant::REAL, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.01,4096,0.01" ), _SCS("set_wait_time"), _SCS("get_wait_time") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "one_shot" ), _SCS("set_one_shot"), _SCS("is_one_shot") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autostart" ), _SCS("set_autostart"), _SCS("has_autostart") );
+ BIND_CONSTANT( TIMER_PROCESS_FIXED );
+ BIND_CONSTANT( TIMER_PROCESS_IDLE );
+
}
Timer::Timer() {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 3bb64e54c6..d19b5767c2 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -37,6 +37,7 @@
#include "servers/spatial_sound_2d_server.h"
#include "scene/gui/control.h"
#include "scene/3d/camera.h"
+#include "scene/resources/mesh.h"
#include "scene/3d/spatial_indexer.h"
#include "scene/3d/collision_object.h"
@@ -319,6 +320,23 @@ void Viewport::_notification(int p_what) {
}
add_to_group("_viewports");
+ if (get_tree()->is_debugging_collisions_hint()) {
+ //2D
+ Physics2DServer::get_singleton()->space_set_debug_contacts(find_world_2d()->get_space(),get_tree()->get_collision_debug_contact_count());
+ contact_2d_debug=VisualServer::get_singleton()->canvas_item_create();
+ VisualServer::get_singleton()->canvas_item_set_parent(contact_2d_debug,find_world_2d()->get_canvas());
+ //3D
+ PhysicsServer::get_singleton()->space_set_debug_contacts(find_world()->get_space(),get_tree()->get_collision_debug_contact_count());
+ contact_3d_debug_multimesh=VisualServer::get_singleton()->multimesh_create();
+ VisualServer::get_singleton()->multimesh_set_instance_count(contact_3d_debug_multimesh,get_tree()->get_collision_debug_contact_count());
+ VisualServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh,0);
+ VisualServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh,get_tree()->get_debug_contact_mesh()->get_rid());
+ contact_3d_debug_instance=VisualServer::get_singleton()->instance_create();
+ VisualServer::get_singleton()->instance_set_base(contact_3d_debug_instance,contact_3d_debug_multimesh);
+ VisualServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance,find_world()->get_scenario());
+ VisualServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance,VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS,true);
+
+ }
} break;
case NOTIFICATION_READY: {
@@ -351,11 +369,69 @@ void Viewport::_notification(int p_what) {
VisualServer::get_singleton()->viewport_set_scenario(viewport,RID());
SpatialSoundServer::get_singleton()->listener_set_space(listener,RID());
VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas);
+ if (contact_2d_debug.is_valid()) {
+ VisualServer::get_singleton()->free(contact_2d_debug);
+ contact_2d_debug=RID();
+ }
+
+ if (contact_3d_debug_multimesh.is_valid()) {
+ VisualServer::get_singleton()->free(contact_3d_debug_multimesh);
+ VisualServer::get_singleton()->free(contact_3d_debug_instance);
+ contact_3d_debug_instance=RID();
+ contact_3d_debug_multimesh=RID();
+ }
+
remove_from_group("_viewports");
} break;
case NOTIFICATION_FIXED_PROCESS: {
+
+ if (get_tree()->is_debugging_collisions_hint() && contact_2d_debug.is_valid()) {
+
+ VisualServer::get_singleton()->canvas_item_clear(contact_2d_debug);
+ VisualServer::get_singleton()->canvas_item_raise(contact_2d_debug);
+
+ Vector<Vector2> points = Physics2DServer::get_singleton()->space_get_contacts(find_world_2d()->get_space());
+ int point_count = Physics2DServer::get_singleton()->space_get_contact_count(find_world_2d()->get_space());
+ Color ccol = get_tree()->get_debug_collision_contact_color();
+
+
+ for(int i=0;i<point_count;i++) {
+
+ VisualServer::get_singleton()->canvas_item_add_rect(contact_2d_debug,Rect2(points[i]-Vector2(2,2),Vector2(5,5)),ccol);
+ }
+ }
+
+ if (get_tree()->is_debugging_collisions_hint() && contact_3d_debug_multimesh.is_valid()) {
+
+
+ Vector<Vector3> points = PhysicsServer::get_singleton()->space_get_contacts(find_world()->get_space());
+ int point_count = PhysicsServer::get_singleton()->space_get_contact_count(find_world()->get_space());
+
+
+ VS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh,point_count);
+
+ if (point_count>0) {
+ AABB aabb;
+
+ Transform t;
+ for(int i=0;i<point_count;i++) {
+
+ if (i==0)
+ aabb.pos=points[i];
+ else
+ aabb.expand_to(points[i]);
+ t.origin=points[i];
+ VisualServer::get_singleton()->multimesh_instance_set_transform(contact_3d_debug_multimesh,i,t);
+ }
+ aabb.grow(aabb.get_longest_axis_size()*0.01);
+ VisualServer::get_singleton()->multimesh_set_aabb(contact_3d_debug_multimesh,aabb);
+ }
+ }
+
+
+
if (physics_object_picking) {
Vector2 last_pos(1e20,1e20);
@@ -1449,6 +1525,8 @@ Viewport::Viewport() {
unhandled_key_input_group = "_vp_unhandled_key_input"+id;
+
+
}
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index c3c339ac5d..843a1fd9b7 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -104,6 +104,11 @@ friend class RenderTargetTexture;
Rect2 rect;
Rect2 to_screen_rect;
+ RID contact_2d_debug;
+ RID contact_3d_debug_multimesh;
+ RID contact_3d_debug_instance;
+
+
bool size_override;
bool size_override_stretch;