summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/listener.cpp167
-rw-r--r--scene/3d/listener.h53
-rw-r--r--scene/3d/mesh_instance.cpp87
-rw-r--r--scene/3d/mesh_instance.h5
-rw-r--r--scene/3d/vehicle_body.cpp8
-rw-r--r--scene/3d/vehicle_body.h1
6 files changed, 307 insertions, 14 deletions
diff --git a/scene/3d/listener.cpp b/scene/3d/listener.cpp
new file mode 100644
index 0000000000..bf42a5c92e
--- /dev/null
+++ b/scene/3d/listener.cpp
@@ -0,0 +1,167 @@
+#include "listener.h"
+
+#include "scene/resources/mesh.h"
+
+void Listener::_update_audio_listener_state() {
+
+
+}
+
+void Listener::_request_listener_update() {
+
+ _update_listener();
+}
+
+bool Listener::_set(const StringName& p_name, const Variant& p_value) {
+
+ if (p_name == "current") {
+ if (p_value.operator bool()) {
+ make_current();
+ }
+ else {
+ clear_current();
+ }
+ }
+ else
+ return false;
+
+ return true;
+}
+bool Listener::_get(const StringName& p_name,Variant &r_ret) const {
+
+ if (p_name == "current") {
+ if (is_inside_tree() && get_tree()->is_node_being_edited(this)) {
+ r_ret = current;
+ }
+ else {
+ r_ret = is_current();
+ }
+ }
+ else
+ return false;
+
+ return true;
+}
+
+void Listener::_get_property_list( List<PropertyInfo> *p_list) const {
+
+ p_list->push_back( PropertyInfo( Variant::BOOL, "current" ) );
+}
+
+void Listener::_update_listener() {
+
+ if (is_inside_tree() && is_current()) {
+ get_viewport()->_listener_transform_changed_notify();
+
+ }
+}
+
+void Listener::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_ENTER_WORLD: {
+ bool first_listener = get_viewport()->_listener_add(this);
+ if (!get_tree()->is_node_being_edited(this) && (current || first_listener))
+ make_current();
+ } break;
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ _request_listener_update();
+ } break;
+ case NOTIFICATION_EXIT_WORLD: {
+
+ if (!get_tree()->is_node_being_edited(this)) {
+ if (is_current()) {
+ clear_current();
+ current=true; //keep it true
+
+ } else {
+ current=false;
+ }
+ }
+
+ get_viewport()->_listener_remove(this);
+
+
+ } break;
+
+
+ }
+
+}
+
+
+Transform Listener::get_listener_transform() const {
+
+ return get_global_transform().orthonormalized();
+}
+
+void Listener::make_current() {
+
+ current=true;
+
+ if (!is_inside_tree())
+ return;
+
+ get_viewport()->_listener_set(this);
+}
+
+
+
+
+void Listener::clear_current() {
+
+ current=false;
+ if (!is_inside_tree())
+ return;
+
+ if (get_viewport()->get_listener()==this) {
+ get_viewport()->_listener_set(NULL);
+ get_viewport()->_listener_make_next_current(this);
+ }
+
+}
+
+bool Listener::is_current() const {
+
+ if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
+
+ return get_viewport()->get_listener()==this;
+ } else
+ return current;
+
+ return false;
+}
+
+bool Listener::_can_gizmo_scale() const {
+
+ return false;
+}
+
+RES Listener::_get_gizmo_geometry() const {
+ Ref<Mesh> mesh = memnew(Mesh);
+
+ return mesh;
+}
+
+void Listener::_bind_methods() {
+
+ ObjectTypeDB::bind_method( _MD("make_current"),&Listener::make_current );
+ ObjectTypeDB::bind_method( _MD("clear_current"),&Listener::clear_current );
+ ObjectTypeDB::bind_method( _MD("is_current"),&Listener::is_current );
+ ObjectTypeDB::bind_method( _MD("get_listener_transform"),&Listener::get_listener_transform );
+}
+
+Listener::Listener() {
+
+ current=false;
+ force_change=false;
+ //active=false;
+}
+
+
+Listener::~Listener() {
+
+}
+
+
diff --git a/scene/3d/listener.h b/scene/3d/listener.h
new file mode 100644
index 0000000000..bf0281a8e0
--- /dev/null
+++ b/scene/3d/listener.h
@@ -0,0 +1,53 @@
+#ifndef LISTENER_H
+#define LISTENER_H
+
+
+#include "scene/3d/spatial.h"
+#include "scene/main/viewport.h"
+
+class Listener : public Spatial {
+
+ OBJ_TYPE(Listener, Spatial);
+private:
+
+ bool force_change;
+ bool current;
+
+ RID scenario_id;
+
+ virtual bool _can_gizmo_scale() const;
+ virtual RES _get_gizmo_geometry() const;
+
+friend class Viewport;
+ void _update_audio_listener_state();
+protected:
+
+ void _update_listener();
+ virtual void _request_listener_update();
+
+ 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 _notification(int p_what);
+
+ static void _bind_methods();
+
+public:
+
+ void make_current();
+ void clear_current();
+ bool is_current() const;
+
+ virtual Transform get_listener_transform() const;
+
+ void set_visible_layers(uint32_t p_layers);
+ uint32_t get_visible_layers() const;
+
+ Vector<Plane> get_frustum() const;
+
+ Listener();
+ ~Listener();
+
+};
+
+#endif
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index cfe273fa20..ef956e8ad9 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -31,8 +31,8 @@
#include "skeleton.h"
#include "physics_body.h"
#include "body_shape.h"
-
-
+#include "scene/scene_string_names.h"
+#include "core_string_names.h"
bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) {
//this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else.
@@ -43,13 +43,22 @@ bool MeshInstance::_set(const StringName& p_name, const Variant& p_value) {
Map<StringName,MorphTrack>::Element *E = morph_tracks.find(p_name);
- if (!E)
- return false;
+ if (E) {
+ E->get().value=p_value;
+ VisualServer::get_singleton()->instance_set_morph_target_weight(get_instance(),E->get().idx,E->get().value);
+ return true;
+ }
- E->get().value=p_value;
- VisualServer::get_singleton()->instance_set_morph_target_weight(get_instance(),E->get().idx,E->get().value);
+ if (p_name.operator String().begins_with("material/")) {
+ int idx = p_name.operator String().get_slicec('/',1).to_int();
+ if (idx>=materials.size() || idx<0)
+ return false;
- return true;
+ set_surface_material(idx,p_value);
+ return true;
+ }
+
+ return false;
}
bool MeshInstance::_get(const StringName& p_name,Variant &r_ret) const {
@@ -59,12 +68,19 @@ bool MeshInstance::_get(const StringName& p_name,Variant &r_ret) const {
return false;
const Map<StringName,MorphTrack>::Element *E = morph_tracks.find(p_name);
- if (!E)
- return false;
-
- r_ret = E->get().value;
+ if (E) {
+ r_ret = E->get().value;
+ return true;
+ }
- return true;
+ if (p_name.operator String().begins_with("material/")) {
+ int idx = p_name.operator String().get_slicec('/',1).to_int();
+ if (idx>=materials.size() || idx<0)
+ return false;
+ r_ret=materials[idx];
+ return true;
+ }
+ return false;
}
void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
@@ -80,6 +96,12 @@ void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
for(List<String>::Element *E=ls.front();E;E=E->next()) {
p_list->push_back( PropertyInfo(Variant::REAL,E->get(),PROPERTY_HINT_RANGE,"0,1,0.01"));
}
+
+ if (mesh.is_valid()) {
+ for(int i=0;i<mesh->get_surface_count();i++) {
+ p_list->push_back( PropertyInfo(Variant::OBJECT, "material/"+itos(i), PROPERTY_HINT_RESOURCE_TYPE, "Material"));
+ }
+ }
}
@@ -87,6 +109,14 @@ void MeshInstance::_get_property_list( List<PropertyInfo> *p_list) const {
void MeshInstance::set_mesh(const Ref<Mesh>& p_mesh) {
+ if (mesh==p_mesh)
+ return;
+
+ if (mesh.is_valid()) {
+ mesh->disconnect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_mesh_changed);
+ materials.clear();
+ }
+
mesh=p_mesh;
morph_tracks.clear();
@@ -100,13 +130,17 @@ void MeshInstance::set_mesh(const Ref<Mesh>& p_mesh) {
mt.value=0;
morph_tracks["morph/"+String(mesh->get_morph_target_name(i))]=mt;
}
+
+ mesh->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_mesh_changed);
+ materials.resize(mesh->get_surface_count());
+
set_base(mesh->get_rid());
} else {
set_base(RID());
}
- _change_notify("mesh");
+ _change_notify();
}
Ref<Mesh> MeshInstance::get_mesh() const {
@@ -232,6 +266,32 @@ void MeshInstance::_notification(int p_what) {
}
+void MeshInstance::set_surface_material(int p_surface,const Ref<Material>& p_material) {
+
+ ERR_FAIL_INDEX(p_surface,materials.size());
+
+ materials[p_surface]=p_material;
+
+ if (materials[p_surface].is_valid())
+ VS::get_singleton()->instance_set_surface_material(get_instance(),p_surface,materials[p_surface]->get_rid());
+ else
+ VS::get_singleton()->instance_set_surface_material(get_instance(),p_surface,RID());
+
+}
+
+Ref<Material> MeshInstance::get_surface_material(int p_surface) const {
+
+ ERR_FAIL_INDEX_V(p_surface,materials.size(),Ref<Material>());
+
+ return materials[p_surface];
+}
+
+
+void MeshInstance::_mesh_changed() {
+
+ materials.resize( mesh->get_surface_count() );
+}
+
void MeshInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_mesh","mesh:Mesh"),&MeshInstance::set_mesh);
@@ -243,6 +303,7 @@ void MeshInstance::_bind_methods() {
ObjectTypeDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT);
ObjectTypeDB::bind_method(_MD("create_convex_collision"),&MeshInstance::create_convex_collision);
ObjectTypeDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT);
+ ObjectTypeDB::bind_method(_MD("_mesh_changed"),&MeshInstance::_mesh_changed);
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh/mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), _SCS("set_mesh"), _SCS("get_mesh"));
ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "mesh/skeleton"), _SCS("set_skeleton_path"), _SCS("get_skeleton_path"));
}
diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h
index 7c605c2d6d..fd8faf38b4 100644
--- a/scene/3d/mesh_instance.h
+++ b/scene/3d/mesh_instance.h
@@ -50,7 +50,9 @@ class MeshInstance : public GeometryInstance {
};
Map<StringName,MorphTrack> morph_tracks;
+ Vector<Ref<Material> > materials;
+ void _mesh_changed();
void _resolve_skeleton_path();
protected:
@@ -69,6 +71,9 @@ public:
void set_skeleton_path(const NodePath& p_skeleton);
NodePath get_skeleton_path();
+ void set_surface_material(int p_surface,const Ref<Material>& p_material);
+ Ref<Material> get_surface_material(int p_surface) const;
+
Node* create_trimesh_collision_node();
void create_trimesh_collision();
diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp
index ba30c118f0..e35ba11e84 100644
--- a/scene/3d/vehicle_body.cpp
+++ b/scene/3d/vehicle_body.cpp
@@ -936,7 +936,7 @@ void VehicleBody::_direct_state_changed(Object *p_state) {
wheel.m_deltaRotation *= real_t(0.99);//damping of rotation when not in contact
}
-
+ linear_velocity = s->get_linear_velocity();
}
void VehicleBody::set_mass(real_t p_mass) {
@@ -990,6 +990,10 @@ float VehicleBody::get_steering() const{
return m_steeringValue;
}
+Vector3 VehicleBody::get_linear_velocity()
+{
+ return linear_velocity;
+}
void VehicleBody::_bind_methods(){
@@ -1008,6 +1012,8 @@ void VehicleBody::_bind_methods(){
ObjectTypeDB::bind_method(_MD("set_steering","steering"),&VehicleBody::set_steering);
ObjectTypeDB::bind_method(_MD("get_steering"),&VehicleBody::get_steering);
+ ObjectTypeDB::bind_method(_MD("get_linear_velocity"),&VehicleBody::get_linear_velocity);
+
ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed);
ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/engine_force",PROPERTY_HINT_RANGE,"0.00,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force"));
diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h
index 285cca142d..b6ad88f15e 100644
--- a/scene/3d/vehicle_body.h
+++ b/scene/3d/vehicle_body.h
@@ -178,6 +178,7 @@ public:
void set_steering(float p_steering);
float get_steering() const;
+ Vector3 get_linear_velocity();
VehicleBody();
};