#include "world.h" #include "core/config/engine.h" #include "core/core_string_names.h" #include "scene/3d/camera.h" #include "scene/3d/spatial.h" #include "scene/3d/world_environment_3d.h" #include "scene/resources/world_2d.h" #include "scene/resources/world_3d.h" #include "viewport.h" Camera *World::get_camera() const { return camera; } Ref World::get_world_2d() const { return world_2d; } void World::set_world_2d(const Ref &p_world_2d) { if (world_2d == p_world_2d) { return; } if (_parent_world && _parent_world->find_world_2d() == p_world_2d) { WARN_PRINT("Unable to use parent world as world_2d"); return; } Ref old_world; if (is_inside_tree()) { old_world = find_world_2d(); } if (p_world_2d.is_valid()) { world_2d = p_world_2d; } else { WARN_PRINT("Invalid world"); world_2d = Ref(memnew(World2D)); } _on_set_world_2d(old_world); } Ref World::get_world_3d() const { return world_3d; } void World::set_world_3d(const Ref &p_world_3d) { if (world_3d == p_world_3d) { return; } if (is_inside_tree()) { _propagate_exit_world(this); } Ref old_world = world_3d; if (own_world_3d.is_valid() && world_3d.is_valid()) { world_3d->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_3d_changed"); } world_3d = p_world_3d; if (own_world_3d.is_valid()) { if (world_3d.is_valid()) { own_world_3d = world_3d->duplicate(); world_3d->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_3d_changed"); } else { own_world_3d = Ref(memnew(World3D)); } } if (is_inside_tree()) { _propagate_enter_world(this); } _on_set_world_3d(old_world); } bool World::is_using_own_world_3d() const { return own_world_3d.is_valid(); } void World::set_use_own_world_3d(bool p_use_own_world_3d) { if (p_use_own_world_3d == own_world_3d.is_valid()) { return; } if (is_inside_tree()) { _propagate_exit_world(this); } if (p_use_own_world_3d) { if (world_3d.is_valid()) { own_world_3d = world_3d->duplicate(); world_3d->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_3d_changed"); } else { own_world_3d = Ref(memnew(World3D)); } } else { own_world_3d = Ref(); if (world_3d.is_valid()) { world_3d->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_3d_changed"); } } if (is_inside_tree()) { _propagate_enter_world(this); } _on_set_use_own_world_3d(p_use_own_world_3d); } bool World::get_override_in_parent_viewport() { return _override_in_parent_viewport; } void World::set_override_in_parent_viewport(const bool value) { if (_override_in_parent_viewport == value) { return; } if (!Engine::get_singleton()->is_editor_hint() && is_inside_tree()) { World *w = get_viewport(); if (w) { if (_override_in_parent_viewport) { if (w->get_override_world() == this) { w->set_override_world(NULL); } } else { w->set_override_world(this); } } } _override_in_parent_viewport = value; } Ref World::find_world_2d() const { if (_override_world) { return _override_world->find_world_2d(); } if (world_2d.is_valid()) { return world_2d; } else if (_parent_world) { return _parent_world->find_world_2d(); } else { return Ref(); } } Ref World::find_world_3d() const { if (_override_world) { return _override_world->find_world_3d(); } if (own_world_3d.is_valid()) { return own_world_3d; } else if (world_3d.is_valid()) { return world_3d; } else if (_parent_world) { return _parent_world->find_world_3d(); } else { return Ref(); } } Ref World::find_world_2d_no_override() const { if (world_2d.is_valid()) { return world_2d; } else if (_parent_world) { return _parent_world->find_world_2d(); } else { return Ref(); } } Ref World::find_world_3d_no_override() const { if (own_world_3d.is_valid()) { return own_world_3d; } else if (world_3d.is_valid()) { return world_3d; } else if (_parent_world) { return _parent_world->find_world_3d(); } else { return Ref(); } } World *World::get_override_world() { return _override_world; } World *World::get_override_world_or_this() { if (!_override_world) { return this; } return _override_world; } void World::set_override_world(World *p_world) { if (Engine::get_singleton()->is_editor_hint()) { return; } if (p_world == _override_world || p_world == this) { return; } _on_before_world_override_changed(); if (_overriding_world) { _overriding_world->set_override_world(NULL); _overriding_world = NULL; } _clear_override_cameras(); _override_world = p_world; if (_override_world) { _override_world->_overriding_world = this; _add_override_cameras(_override_world); } _on_after_world_override_changed(); } void World::set_override_world_bind(Node *p_world) { World *w = Object::cast_to(p_world); ERR_FAIL_COND(p_world && !w); set_override_world(w); } void World::gui_reset_canvas_sort_index() { if (_overriding_world) { _overriding_world->gui_reset_canvas_sort_index(); } } int World::gui_get_canvas_sort_index() { if (_overriding_world) { return _overriding_world->gui_get_canvas_sort_index(); } return 0; } void World::enable_canvas_transform_override(bool p_enable) { if (_overriding_world) { _overriding_world->enable_canvas_transform_override(p_enable); } } bool World::is_canvas_transform_override_enbled() const { if (_overriding_world) { return _overriding_world->is_canvas_transform_override_enbled(); } return false; } void World::set_canvas_transform_override(const Transform2D &p_transform) { if (_overriding_world) { _overriding_world->set_canvas_transform_override(p_transform); } } Transform2D World::get_canvas_transform_override() const { if (_overriding_world) { return _overriding_world->get_canvas_transform_override(); } return Transform2D(); } void World::set_canvas_transform(const Transform2D &p_transform) { if (_overriding_world) { _overriding_world->set_canvas_transform(p_transform); } } Transform2D World::get_canvas_transform() const { if (_overriding_world) { return _overriding_world->get_canvas_transform(); } return Transform2D(); } void World::set_global_canvas_transform(const Transform2D &p_transform) { if (_overriding_world) { _overriding_world->set_global_canvas_transform(p_transform); } } Transform2D World::get_global_canvas_transform() const { if (_overriding_world) { return _overriding_world->get_global_canvas_transform(); } return Transform2D(); } Transform2D World::get_final_transform() const { if (_overriding_world) { return _overriding_world->get_final_transform(); } return Transform2D(); } Rect2 World::get_visible_rect() const { if (_overriding_world) { return _overriding_world->get_visible_rect(); } return Rect2(); } RID World::get_viewport_rid() const { if (_overriding_world) { return _overriding_world->get_viewport_rid(); } return RID(); } Vector2 World::get_camera_coords(const Vector2 &p_viewport_coords) const { if (_overriding_world) { return _overriding_world->get_camera_coords(p_viewport_coords); } Transform2D xf = get_final_transform(); return xf.xform(p_viewport_coords); } Vector2 World::get_camera_rect_size() const { if (_overriding_world) { return _overriding_world->get_camera_rect_size(); } return size; } void World::update_worlds() { if (!is_inside_tree()) { return; } Rect2 abstracted_rect = Rect2(Vector2(), get_visible_rect().size); Rect2 xformed_rect = (get_global_canvas_transform() * get_canvas_transform()).affine_inverse().xform(abstracted_rect); find_world_2d()->_update_world(this, xformed_rect); find_world_2d()->_update(); find_world_3d()->_update(get_tree()->get_frame()); } void World::_world_3d_register_camera(Camera *p_camera) { if (_override_world) { _override_world->_world_3d_register_camera_as_override(p_camera); } _world_3d_register_camera_no_override(p_camera); } void World::_world_3d_remove_camera(Camera *p_camera) { if (_override_world) { _override_world->_world_3d_remove_camera_as_override(p_camera); } _world_3d_remove_camera_no_override(p_camera); } void World::_world_3d_register_camera_no_override(Camera *p_camera) { find_world_3d_no_override()->_register_camera(p_camera); } void World::_world_3d_remove_camera_no_override(Camera *p_camera) { find_world_3d_no_override()->_remove_camera(p_camera); } void World::_world_3d_register_camera_as_override(Camera *p_camera) { //find_world_3d_no_override()->_register_camera(p_camera); _override_cameras.push_back(p_camera); _camera_add(p_camera); } void World::_world_3d_remove_camera_as_override(Camera *p_camera) { //find_world_3d_no_override()->_remove_camera(p_camera); _override_cameras.erase(p_camera); _camera_remove(p_camera); } void World::_clear_override_cameras() { while (_override_cameras.size() > 0) { _world_3d_remove_camera_as_override(_override_cameras[0]); } _camera_set(_own_active_camera); _own_active_camera = NULL; } void World::_add_override_cameras(World *p_from) { _own_active_camera = camera; Ref w3d = p_from->find_world_3d_no_override(); ERR_FAIL_COND(!w3d.is_valid()); List cameras; w3d->get_camera_list(&cameras); for (List::Element *E = cameras.front(); E; E = E->next()) { Camera *cam = E->get(); _world_3d_register_camera_as_override(cam); } if (p_from->get_camera()) { _camera_set(p_from->get_camera()); } } World::World() { world_2d = Ref(memnew(World2D)); _override_world = NULL; _overriding_world = NULL; _override_in_parent_viewport = false; camera = NULL; _own_active_camera = NULL; } World::~World() { } void World::_camera_transform_changed_notify() { #ifndef _3D_DISABLED // If there is an active listener in the scene, it takes priority over the camera // if (camera && !listener) // SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, camera->get_camera_transform()); #endif } void World::_camera_set(Camera *p_camera) { #ifndef _3D_DISABLED if (camera == p_camera) { return; } if (camera) { camera->notification(Camera::NOTIFICATION_LOST_CURRENT); } camera = p_camera; /* if (!camera_override) { if (camera) { RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera()); } else { RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID()); } } */ if (camera) { camera->notification(Camera::NOTIFICATION_BECAME_CURRENT); } _update_listener(); _camera_transform_changed_notify(); #endif } bool World::_camera_add(Camera *p_camera) { cameras.insert(p_camera); return cameras.size() == 1; } void World::_camera_remove(Camera *p_camera) { cameras.erase(p_camera); if (camera == p_camera) { camera->notification(Camera::NOTIFICATION_LOST_CURRENT); camera = nullptr; } } #ifndef _3D_DISABLED void World::_camera_make_next_current(Camera *p_exclude) { for (Set::Element *E = cameras.front(); E; E = E->next()) { if (p_exclude == E->get()) { continue; } if (!E->get()->is_inside_tree()) { continue; } if (camera != nullptr) { return; } E->get()->make_current(); } } #endif void World::_update_listener() {} void World::_update_listener_2d() {} void World::_propagate_enter_world(Node *p_node) { if (p_node != this) { if (!p_node->is_inside_tree()) { //may not have entered scene yet return; } if (Object::cast_to(p_node) || Object::cast_to(p_node)) { p_node->notification(Spatial::NOTIFICATION_ENTER_WORLD); } else { World *v = Object::cast_to(p_node); if (v) { if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) { return; } } } } for (int i = 0; i < p_node->get_child_count(); i++) { _propagate_enter_world(p_node->get_child(i)); } } void World::_propagate_exit_world(Node *p_node) { if (p_node != this) { if (!p_node->is_inside_tree()) { //may have exited scene already return; } if (Object::cast_to(p_node) || Object::cast_to(p_node)) { p_node->notification(Spatial::NOTIFICATION_EXIT_WORLD); } else { World *v = Object::cast_to(p_node); if (v) { if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) { return; } } } } for (int i = 0; i < p_node->get_child_count(); i++) { _propagate_exit_world(p_node->get_child(i)); } } void World::_own_world_3d_changed() { ERR_FAIL_COND(world_3d.is_null()); ERR_FAIL_COND(own_world_3d.is_null()); if (is_inside_tree()) { _propagate_exit_world(this); } own_world_3d = world_3d->duplicate(); if (is_inside_tree()) { _propagate_enter_world(this); } } void World::_on_set_use_own_world_3d(bool p_use_own_world_3d) { } void World::_on_set_world_3d(const Ref &p_old_world) { } void World::_on_set_world_2d(const Ref &p_old_world_2d) { } void World::_on_before_world_override_changed() { } void World::_on_after_world_override_changed() { } void World::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { if (get_parent()) { _parent_world = get_parent()->get_world(); } else { _parent_world = nullptr; } } break; case NOTIFICATION_READY: { if (_override_in_parent_viewport && !Engine::get_singleton()->is_editor_hint()) { if (get_parent()) { World *w = get_parent()->get_viewport(); if (w) { w->set_override_world(this); } } } } break; case NOTIFICATION_EXIT_TREE: { if (!Engine::get_singleton()->is_editor_hint()) { set_override_world(NULL); } } break; } } void World::_bind_methods() { ClassDB::bind_method(D_METHOD("get_camera"), &World::get_camera); ClassDB::bind_method(D_METHOD("get_world_2d"), &World::get_world_2d); ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &World::set_world_2d); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d"); ClassDB::bind_method(D_METHOD("get_world_3d"), &World::get_world_3d); ClassDB::bind_method(D_METHOD("set_world_3d", "world"), &World::set_world_3d); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d"); ClassDB::bind_method(D_METHOD("is_using_own_world_3d"), &World::is_using_own_world_3d); ClassDB::bind_method(D_METHOD("set_use_own_world_3d", "enable"), &World::set_use_own_world_3d); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d"); ClassDB::bind_method(D_METHOD("get_override_in_parent_viewport"), &World::get_override_in_parent_viewport); ClassDB::bind_method(D_METHOD("set_override_in_parent_viewport", "enable"), &World::set_override_in_parent_viewport); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_in_parent_viewport"), "set_override_in_parent_viewport", "get_override_in_parent_viewport"); ClassDB::bind_method(D_METHOD("find_world_2d"), &World::find_world_2d); ClassDB::bind_method(D_METHOD("find_world_3d"), &World::find_world_3d); ClassDB::bind_method(D_METHOD("get_override_world"), &World::get_override_world); ClassDB::bind_method(D_METHOD("get_override_world_or_this"), &World::get_override_world_or_this); ClassDB::bind_method(D_METHOD("set_override_world", "world"), &World::set_override_world_bind); ClassDB::bind_method(D_METHOD("_own_world_3d_changed"), &World::_own_world_3d_changed); ClassDB::bind_method(D_METHOD("set_canvas_transform", "xform"), &World::set_canvas_transform); ClassDB::bind_method(D_METHOD("get_canvas_transform"), &World::get_canvas_transform); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_canvas_transform", "get_canvas_transform"); ClassDB::bind_method(D_METHOD("set_global_canvas_transform", "xform"), &World::set_global_canvas_transform); ClassDB::bind_method(D_METHOD("get_global_canvas_transform"), &World::get_global_canvas_transform); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_global_canvas_transform", "get_global_canvas_transform"); ClassDB::bind_method(D_METHOD("get_final_transform"), &World::get_final_transform); ClassDB::bind_method(D_METHOD("get_visible_rect"), &World::get_visible_rect); ClassDB::bind_method(D_METHOD("get_viewport_rid"), &World::get_viewport_rid); ClassDB::bind_method(D_METHOD("update_worlds"), &World::update_worlds); }