diff options
Diffstat (limited to 'servers')
61 files changed, 1447 insertions, 529 deletions
diff --git a/servers/arvr/arvr_interface.cpp b/servers/arvr/arvr_interface.cpp index 0705df17b1..55707def7c 100644 --- a/servers/arvr/arvr_interface.cpp +++ b/servers/arvr/arvr_interface.cpp @@ -31,29 +31,49 @@ void ARVRInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_name"), &ARVRInterface::get_name); + ClassDB::bind_method(D_METHOD("get_capabilities"), &ARVRInterface::get_capabilities); ClassDB::bind_method(D_METHOD("is_primary"), &ARVRInterface::is_primary); ClassDB::bind_method(D_METHOD("set_is_primary", "enable"), &ARVRInterface::set_is_primary); - ClassDB::bind_method(D_METHOD("is_installed"), &ARVRInterface::is_installed); - ClassDB::bind_method(D_METHOD("hmd_is_present"), &ARVRInterface::hmd_is_present); - ClassDB::bind_method(D_METHOD("supports_hmd"), &ARVRInterface::supports_hmd); ClassDB::bind_method(D_METHOD("is_initialized"), &ARVRInterface::is_initialized); + ClassDB::bind_method(D_METHOD("set_is_initialized", "initialized"), &ARVRInterface::set_is_initialized); ClassDB::bind_method(D_METHOD("initialize"), &ARVRInterface::initialize); ClassDB::bind_method(D_METHOD("uninitialize"), &ARVRInterface::uninitialize); + ClassDB::bind_method(D_METHOD("get_tracking_status"), &ARVRInterface::get_tracking_status); + ClassDB::bind_method(D_METHOD("get_recommended_render_targetsize"), &ARVRInterface::get_recommended_render_targetsize); + ClassDB::bind_method(D_METHOD("is_stereo"), &ARVRInterface::is_stereo); + + ADD_GROUP("Interface", "interface_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_is_primary", "is_primary"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_initialized"), "set_is_initialized", "is_initialized"); + + // we don't have any properties specific to VR yet.... - // These are now purely used internally, we may expose them again if we expose CameraMatrix through Variant but reduz is not a fan for good reasons :) - // ClassDB::bind_method(D_METHOD("get_transform_for_eye", "eye", "cam_transform"), &ARVRInterface::get_transform_for_eye); - // ClassDB::bind_method(D_METHOD("get_projection_for_eye", "eye"), &ARVRInterface::get_projection_for_eye); - // ClassDB::bind_method(D_METHOD("commit_for_eye", "node:viewport"), &ARVRInterface::commit_for_eye); + // but we do have properties specific to AR.... + ClassDB::bind_method(D_METHOD("get_anchor_detection_is_enabled"), &ARVRInterface::get_anchor_detection_is_enabled); + ClassDB::bind_method(D_METHOD("set_anchor_detection_is_enabled", "enable"), &ARVRInterface::set_anchor_detection_is_enabled); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "primary"), "set_is_primary", "is_primary"); + ADD_GROUP("AR", "ar_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ar_is_anchor_detection_enabled"), "set_anchor_detection_is_enabled", "get_anchor_detection_is_enabled"); + + BIND_ENUM_CONSTANT(ARVR_NONE); + BIND_ENUM_CONSTANT(ARVR_MONO); + BIND_ENUM_CONSTANT(ARVR_STEREO); + BIND_ENUM_CONSTANT(ARVR_AR); + BIND_ENUM_CONSTANT(ARVR_EXTERNAL); BIND_ENUM_CONSTANT(EYE_MONO); BIND_ENUM_CONSTANT(EYE_LEFT); BIND_ENUM_CONSTANT(EYE_RIGHT); + + BIND_ENUM_CONSTANT(ARVR_NORMAL_TRACKING); + BIND_ENUM_CONSTANT(ARVR_EXCESSIVE_MOTION); + BIND_ENUM_CONSTANT(ARVR_INSUFFICIENT_FEATURES); + BIND_ENUM_CONSTANT(ARVR_UNKNOWN_TRACKING); + BIND_ENUM_CONSTANT(ARVR_NOT_TRACKING); }; StringName ARVRInterface::get_name() const { @@ -73,10 +93,40 @@ void ARVRInterface::set_is_primary(bool p_is_primary) { if (p_is_primary) { ERR_FAIL_COND(!is_initialized()); - ERR_FAIL_COND(!supports_hmd()); arvr_server->set_primary_interface(this); } else { arvr_server->clear_primary_interface_if(this); }; }; + +void ARVRInterface::set_is_initialized(bool p_initialized) { + if (p_initialized) { + if (!is_initialized()) { + initialize(); + }; + } else { + if (is_initialized()) { + uninitialize(); + }; + }; +}; + +ARVRInterface::Tracking_status ARVRInterface::get_tracking_status() const { + return tracking_state; +}; + +ARVRInterface::ARVRInterface() { + tracking_state = ARVR_UNKNOWN_TRACKING; +}; + +ARVRInterface::~ARVRInterface(){}; + +/** these will only be implemented on AR interfaces, so we want dummies for VR **/ +bool ARVRInterface::get_anchor_detection_is_enabled() const { + return false; +}; + +void ARVRInterface::set_anchor_detection_is_enabled(bool p_enable){ + // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc. +}; diff --git a/servers/arvr/arvr_interface.h b/servers/arvr/arvr_interface.h index d4fb383bbc..880f6e4595 100644 --- a/servers/arvr/arvr_interface.h +++ b/servers/arvr/arvr_interface.h @@ -50,31 +50,59 @@ class ARVRInterface : public Reference { GDCLASS(ARVRInterface, Reference); -protected: - _THREAD_SAFE_CLASS_ - - static void _bind_methods(); - public: + enum Capabilities { /* purely meta data, provides some info about what this interface supports */ + ARVR_NONE = 0, /* no capabilities */ + ARVR_MONO = 1, /* can be used with mono output */ + ARVR_STEREO = 2, /* can be used with stereo output */ + ARVR_AR = 4, /* offers a camera feed for AR */ + ARVR_EXTERNAL = 8 /* renders to external device */ + }; + enum Eyes { EYE_MONO, /* my son says we should call this EYE_CYCLOPS */ EYE_LEFT, EYE_RIGHT }; + enum Tracking_status { /* tracking status currently based on AR but we can start doing more with this for VR as well */ + ARVR_NORMAL_TRACKING, + ARVR_EXCESSIVE_MOTION, + ARVR_INSUFFICIENT_FEATURES, + ARVR_UNKNOWN_TRACKING, + ARVR_NOT_TRACKING + }; + +protected: + _THREAD_SAFE_CLASS_ + + Tracking_status tracking_state; + static void _bind_methods(); + +public: + /** general interface information **/ virtual StringName get_name() const; + virtual int get_capabilities() const = 0; bool is_primary(); void set_is_primary(bool p_is_primary); - virtual bool is_installed() = 0; /* returns true if the middle ware related to this interface has been installed */ - virtual bool hmd_is_present() = 0; /* returns true if our HMD is connected */ - virtual bool supports_hmd() = 0; /* returns true is this interface handles output to an HMD or only handles positioning */ - virtual bool is_initialized() = 0; /* returns true if we've initialized this interface */ + void set_is_initialized(bool p_initialized); /* helper function, will call initialize or uninitialize */ virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */ virtual void uninitialize() = 0; /* deinitialize this interface */ + Tracking_status get_tracking_status() const; /* get the status of our current tracking */ + + /** specific to VR **/ + // nothing yet + + /** specific to AR **/ + virtual bool get_anchor_detection_is_enabled() const; + virtual void set_anchor_detection_is_enabled(bool p_enable); + + /** rendering and internal **/ + virtual Size2 get_recommended_render_targetsize() = 0; /* returns the recommended render target size per eye for this device */ virtual bool is_stereo() = 0; /* returns true if this interface requires stereo rendering (for VR HMDs) or mono rendering (for mobile AR) */ virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) = 0; /* get each eyes camera transform, also implement EYE_MONO */ @@ -82,8 +110,13 @@ public: virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */ virtual void process() = 0; + + ARVRInterface(); + ~ARVRInterface(); }; +VARIANT_ENUM_CAST(ARVRInterface::Capabilities); VARIANT_ENUM_CAST(ARVRInterface::Eyes); +VARIANT_ENUM_CAST(ARVRInterface::Tracking_status); #endif diff --git a/servers/arvr/arvr_positional_tracker.cpp b/servers/arvr/arvr_positional_tracker.cpp index 539bac6703..4ecd7a3898 100644 --- a/servers/arvr/arvr_positional_tracker.cpp +++ b/servers/arvr/arvr_positional_tracker.cpp @@ -31,6 +31,10 @@ #include "core/os/input.h" void ARVRPositionalTracker::_bind_methods() { + BIND_ENUM_CONSTANT(TRACKER_HAND_UNKNOWN); + BIND_ENUM_CONSTANT(TRACKER_LEFT_HAND); + BIND_ENUM_CONSTANT(TRACKER_RIGHT_HAND); + // this class is read only from GDScript, so we only have access to getters.. ClassDB::bind_method(D_METHOD("get_type"), &ARVRPositionalTracker::get_type); ClassDB::bind_method(D_METHOD("get_name"), &ARVRPositionalTracker::get_name); @@ -39,6 +43,7 @@ void ARVRPositionalTracker::_bind_methods() { ClassDB::bind_method(D_METHOD("get_orientation"), &ARVRPositionalTracker::get_orientation); ClassDB::bind_method(D_METHOD("get_tracks_position"), &ARVRPositionalTracker::get_tracks_position); ClassDB::bind_method(D_METHOD("get_position"), &ARVRPositionalTracker::get_position); + ClassDB::bind_method(D_METHOD("get_hand"), &ARVRPositionalTracker::get_hand); ClassDB::bind_method(D_METHOD("get_transform", "adjust_by_reference_frame"), &ARVRPositionalTracker::get_transform); // these functions we don't want to expose to normal users but do need to be callable from GDNative @@ -141,6 +146,14 @@ Vector3 ARVRPositionalTracker::get_rw_position() const { return rw_position; }; +ARVRPositionalTracker::TrackerHand ARVRPositionalTracker::get_hand() const { + return hand; +}; + +void ARVRPositionalTracker::set_hand(const ARVRPositionalTracker::TrackerHand p_hand) { + hand = p_hand; +}; + Transform ARVRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const { Transform new_transform; @@ -164,6 +177,7 @@ ARVRPositionalTracker::ARVRPositionalTracker() { tracker_id = 0; tracks_orientation = false; tracks_position = false; + hand = TRACKER_HAND_UNKNOWN; }; ARVRPositionalTracker::~ARVRPositionalTracker(){ diff --git a/servers/arvr/arvr_positional_tracker.h b/servers/arvr/arvr_positional_tracker.h index f91f862ba3..ff0c150f89 100644 --- a/servers/arvr/arvr_positional_tracker.h +++ b/servers/arvr/arvr_positional_tracker.h @@ -48,6 +48,13 @@ class ARVRPositionalTracker : public Object { GDCLASS(ARVRPositionalTracker, Object); _THREAD_SAFE_CLASS_ +public: + enum TrackerHand { + TRACKER_HAND_UNKNOWN, /* unknown or not applicable */ + TRACKER_LEFT_HAND, /* controller is the left hand controller */ + TRACKER_RIGHT_HAND /* controller is the right hand controller */ + }; + private: ARVRServer::TrackerType type; // type of tracker StringName name; // (unique) name of the tracker @@ -57,6 +64,7 @@ private: Basis orientation; // our orientation bool tracks_position; // do we track position? Vector3 rw_position; // our position "in the real world, so without world_scale applied" + TrackerHand hand; // if known, the hand this tracker is held in protected: static void _bind_methods(); @@ -77,6 +85,8 @@ public: Vector3 get_position() const; // get position with world_scale applied void set_rw_position(const Vector3 &p_rw_position); Vector3 get_rw_position() const; + ARVRPositionalTracker::TrackerHand get_hand() const; + void set_hand(const ARVRPositionalTracker::TrackerHand p_hand); Transform get_transform(bool p_adjust_by_reference_frame) const; @@ -84,4 +94,6 @@ public: ~ARVRPositionalTracker(); }; +VARIANT_ENUM_CAST(ARVRPositionalTracker::TrackerHand); + #endif diff --git a/servers/arvr/arvr_script_interface.cpp b/servers/arvr/arvr_script_interface.cpp deleted file mode 100644 index 16e607920e..0000000000 --- a/servers/arvr/arvr_script_interface.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include "arvr_script_interface.h" - -ARVRScriptInterface::ARVRScriptInterface() { - // testing - printf("Construct script interface"); -} - -ARVRScriptInterface::~ARVRScriptInterface() { - if (is_initialized()) { - uninitialize(); - }; - - // testing - printf("Destruct script interface"); -} - -StringName ARVRScriptInterface::get_name() const { - if (get_script_instance() && get_script_instance()->has_method("get_name")) { - return get_script_instance()->call("get_name"); - } else { - // just return something for now - return "ARVR Script interface"; - } -} - -bool ARVRScriptInterface::is_installed() { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("is_installed")), false); - return get_script_instance()->call("is_installed"); -} - -bool ARVRScriptInterface::hmd_is_present() { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("hmd_is_present")), false); - return get_script_instance()->call("hmd_is_present"); -} - -bool ARVRScriptInterface::supports_hmd() { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("supports_hmd")), false); - return get_script_instance()->call("supports_hmd"); -} - -bool ARVRScriptInterface::is_stereo() { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("is_stereo")), false); - return get_script_instance()->call("is_stereo"); -} - -bool ARVRScriptInterface::is_initialized() { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("is_initialized")), false); - return get_script_instance()->call("is_initialized"); -} - -bool ARVRScriptInterface::initialize() { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("initialize")), false); - return get_script_instance()->call("initialize"); -} - -void ARVRScriptInterface::uninitialize() { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - if (arvr_server != NULL) { - // Whatever happens, make sure this is no longer our primary interface - arvr_server->clear_primary_interface_if(this); - } - - ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("uninitialize"))); - get_script_instance()->call("uninitialize"); -} - -Size2 ARVRScriptInterface::get_recommended_render_targetsize() { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_recommended_render_targetsize")), Size2()); - return get_script_instance()->call("get_recommended_render_targetsize"); -} - -Transform ARVRScriptInterface::get_transform_for_eye(Eyes p_eye, const Transform &p_cam_transform) { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_transform_for_eye")), Transform()); - return get_script_instance()->call("get_transform_for_eye", p_eye, p_cam_transform); -} - -// Suggestion from Reduz, as we can't return a CameraMatrix, return a PoolVector with our 16 floats -PoolVector<float> ARVRScriptInterface::_get_projection_for_eye(Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_projection_for_eye")), PoolVector<float>()); - return get_script_instance()->call("_get_projection_for_eye", p_eye, p_aspect, p_z_near, p_z_far); -} - -CameraMatrix ARVRScriptInterface::get_projection_for_eye(Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { - CameraMatrix cm; - int i = 0; - int j = 0; - - PoolVector<float> cm_as_floats = _get_projection_for_eye(p_eye, p_aspect, p_z_near, p_z_far); - - for (int k = 0; k < cm_as_floats.size() && i < 4; k++) { - cm.matrix[i][j] = cm_as_floats[k]; - j++; - if (j == 4) { - j = 0; - i++; - }; - }; - - return cm; -} - -void ARVRScriptInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { - ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("commit_for_eye"))); - get_script_instance()->call("commit_for_eye"); -} - -void ARVRScriptInterface::process() { - ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("process"))); - get_script_instance()->call("process"); -} - -void ARVRScriptInterface::_bind_methods() { - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "is_installed")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "hmd_is_present")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "supports_hmd")); - - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "is_initialized")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "initialize")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo("uninitialize")); - - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "is_stereo")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::VECTOR2, "get_recommended_render_targetsize")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::TRANSFORM, "get_transform_for_eye", PropertyInfo(Variant::INT, "eye"), PropertyInfo(Variant::TRANSFORM, "cam_transform"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo("_get_projection_for_eye")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo("commit_for_eye", PropertyInfo(Variant::INT, "eye"), PropertyInfo(Variant::_RID, "render_target"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo("process")); -} diff --git a/servers/arvr/arvr_script_interface.h b/servers/arvr/arvr_script_interface.h deleted file mode 100644 index 04ca33901a..0000000000 --- a/servers/arvr/arvr_script_interface.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SCRIPT_INTERFACE_H -#define SCRIPT_INTERFACE_H - -#include "arvr_interface.h" - -/** - @authors Hinsbart & Karroffel - - This subclass of our AR/VR interface forms a bridge to GDNative. -*/ - -class ARVRScriptInterface : public ARVRInterface { - GDCLASS(ARVRScriptInterface, ARVRInterface); - -protected: - static void _bind_methods(); - -public: - ARVRScriptInterface(); - ~ARVRScriptInterface(); - - virtual StringName get_name() const; - - virtual bool is_installed(); - virtual bool hmd_is_present(); - virtual bool supports_hmd(); - - virtual bool is_initialized(); - virtual bool initialize(); - virtual void uninitialize(); - - virtual Size2 get_recommended_render_targetsize(); - virtual bool is_stereo(); - virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform); - - // we expose a PoolVector<float> version of this function to GDNative - PoolVector<float> _get_projection_for_eye(Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far); - - // and a CameraMatrix version to ARVRServer - virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far); - - virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect); - - virtual void process(); -}; - -#endif // SCRIPT_INTERFACE_H diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp index bac24f6438..ede080b424 100644 --- a/servers/arvr_server.cpp +++ b/servers/arvr_server.cpp @@ -43,7 +43,7 @@ void ARVRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_world_scale"), &ARVRServer::get_world_scale); ClassDB::bind_method(D_METHOD("set_world_scale"), &ARVRServer::set_world_scale); ClassDB::bind_method(D_METHOD("get_reference_frame"), &ARVRServer::get_reference_frame); - ClassDB::bind_method(D_METHOD("request_reference_frame", "ignore_tilt", "keep_height"), &ARVRServer::request_reference_frame); + ClassDB::bind_method(D_METHOD("center_on_hmd", "ignore_tilt", "keep_height"), &ARVRServer::center_on_hmd); ADD_PROPERTY(PropertyInfo(Variant::REAL, "world_scale"), "set_world_scale", "get_world_scale"); @@ -53,23 +53,23 @@ void ARVRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tracker_count"), &ARVRServer::get_tracker_count); ClassDB::bind_method(D_METHOD("get_tracker", "idx"), &ARVRServer::get_tracker); - ClassDB::bind_method(D_METHOD("set_primary_interface"), &ARVRServer::set_primary_interface); + ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &ARVRServer::set_primary_interface); - ClassDB::bind_method(D_METHOD("add_interface"), &ARVRServer::add_interface); - ClassDB::bind_method(D_METHOD("remove_interface"), &ARVRServer::remove_interface); + ClassDB::bind_method(D_METHOD("add_interface", "interface"), &ARVRServer::add_interface); + ClassDB::bind_method(D_METHOD("remove_interface", "interface"), &ARVRServer::remove_interface); BIND_ENUM_CONSTANT(TRACKER_CONTROLLER); BIND_ENUM_CONSTANT(TRACKER_BASESTATION); BIND_ENUM_CONSTANT(TRACKER_ANCHOR); - BIND_ENUM_CONSTANT(TRACKER_UNKNOWN); BIND_ENUM_CONSTANT(TRACKER_ANY_KNOWN); + BIND_ENUM_CONSTANT(TRACKER_UNKNOWN); BIND_ENUM_CONSTANT(TRACKER_ANY); ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING, "name"))); ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING, "name"))); - ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "type"))); - ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING, "name"))); + ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id"))); + ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id"))); }; real_t ARVRServer::get_world_scale() const { @@ -98,7 +98,7 @@ Transform ARVRServer::get_reference_frame() const { return reference_frame; }; -void ARVRServer::request_reference_frame(bool p_ignore_tilt, bool p_keep_height) { +void ARVRServer::center_on_hmd(bool p_ignore_tilt, bool p_keep_height) { if (primary_interface != NULL) { // clear our current reference frame or we'll end up double adjusting it reference_frame = Transform(); @@ -130,7 +130,6 @@ void ARVRServer::request_reference_frame(bool p_ignore_tilt, bool p_keep_height) void ARVRServer::add_interface(const Ref<ARVRInterface> &p_interface) { ERR_FAIL_COND(p_interface.is_null()); - int idx = -1; for (int i = 0; i < interfaces.size(); i++) { if (interfaces[i] == p_interface) { @@ -139,7 +138,7 @@ void ARVRServer::add_interface(const Ref<ARVRInterface> &p_interface) { }; }; - print_line("Registered interface " + p_interface->get_name()); + print_line("ARVR: Registered interface: " + p_interface->get_name()); interfaces.push_back(p_interface); emit_signal("interface_added", p_interface->get_name()); @@ -232,7 +231,7 @@ void ARVRServer::add_tracker(ARVRPositionalTracker *p_tracker) { ERR_FAIL_NULL(p_tracker); trackers.push_back(p_tracker); - emit_signal("tracker_added", p_tracker->get_name(), p_tracker->get_type()); + emit_signal("tracker_added", p_tracker->get_name(), p_tracker->get_type(), p_tracker->get_tracker_id()); }; void ARVRServer::remove_tracker(ARVRPositionalTracker *p_tracker) { @@ -250,7 +249,7 @@ void ARVRServer::remove_tracker(ARVRPositionalTracker *p_tracker) { ERR_FAIL_COND(idx == -1); - emit_signal("tracker_removed", p_tracker->get_name()); + emit_signal("tracker_removed", p_tracker->get_name(), p_tracker->get_type(), p_tracker->get_tracker_id()); trackers.remove(idx); }; diff --git a/servers/arvr_server.h b/servers/arvr_server.h index 2645637ad5..948895cb27 100644 --- a/servers/arvr_server.h +++ b/servers/arvr_server.h @@ -117,14 +117,17 @@ public: void set_world_origin(const Transform p_world_origin); /* - Requesting a reference frame results in a matrix being calculated that ensures the HMD is positioned to 0,0,0 facing 0,0,-1 (need to verify this direction) + center_on_hmd calculates a new reference frame. This ensures the HMD is positioned to 0,0,0 facing 0,0,-1 (need to verify this direction) in the virtual world. + You can ignore the tilt of the device ensuring you're looking straight forward even if the player is looking down or sideways. + You can chose to keep the height the tracking provides which is important for room scale capable tracking. + Note: this should not be used in AR and should be ignored by an AR based interface as it would throw what you're looking at in the real world and in the virtual world out of sync */ Transform get_reference_frame() const; - void request_reference_frame(bool p_ignore_tilt, bool p_keep_height); + void center_on_hmd(bool p_ignore_tilt, bool p_keep_height); /* Interfaces are objects that 'glue' Godot to an AR or VR SDK such as the Oculus SDK, OpenVR, OpenHMD, etc. diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 992fece85f..1ae0e7b96b 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -37,17 +37,16 @@ Error AudioDriverDummy::init() { active = false; thread_exited = false; exit_thread = false; - pcm_open = false; samples_in = NULL; - mix_rate = 44100; + mix_rate = DEFAULT_MIX_RATE; speaker_mode = SPEAKER_MODE_STEREO; channels = 2; - int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = next_power_of_2(latency * mix_rate / 1000); + int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY); + buffer_frames = closest_power_of_2(latency * mix_rate / 1000); - samples_in = memnew_arr(int32_t, buffer_size * channels); + samples_in = memnew_arr(int32_t, buffer_frames * channels); mutex = Mutex::create(); thread = Thread::create(AudioDriverDummy::thread_func, this); @@ -59,17 +58,15 @@ void AudioDriverDummy::thread_func(void *p_udata) { AudioDriverDummy *ad = (AudioDriverDummy *)p_udata; - uint64_t usdelay = (ad->buffer_size / float(ad->mix_rate)) * 1000000; + uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000; while (!ad->exit_thread) { - if (!ad->active) { - - } else { + if (ad->active) { ad->lock(); - ad->audio_server_process(ad->buffer_size, ad->samples_in); + ad->audio_server_process(ad->buffer_frames, ad->samples_in); ad->unlock(); }; diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index b3fea59389..90af1961b7 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -43,8 +43,8 @@ class AudioDriverDummy : public AudioDriver { int32_t *samples_in; static void thread_func(void *p_udata); - int buffer_size; + unsigned int buffer_frames; unsigned int mix_rate; SpeakerMode speaker_mode; @@ -53,7 +53,6 @@ class AudioDriverDummy : public AudioDriver { bool active; bool thread_exited; mutable bool exit_thread; - bool pcm_open; public: const char *get_name() const { diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp index 2f160fd7cd..113e356612 100644 --- a/servers/audio/audio_rb_resampler.cpp +++ b/servers/audio/audio_rb_resampler.cpp @@ -176,7 +176,7 @@ bool AudioRBResampler::mix(int32_t *p_dest, int p_frames) { { - uint32_t read = 0; + int read = 0; switch (channels) { case 1: read = _resample<1>(p_dest, todo, increment); break; case 2: read = _resample<2>(p_dest, todo, increment); break; @@ -189,7 +189,7 @@ bool AudioRBResampler::mix(int32_t *p_dest, int p_frames) { if (remaining && todo > 0) { //print_line("fadeout"); - for (int c = 0; c < channels; c++) { + for (uint32_t c = 0; c < channels; c++) { for (int i = 0; i < todo; i++) { @@ -202,7 +202,7 @@ bool AudioRBResampler::mix(int32_t *p_dest, int p_frames) { } //zero out what remains there to avoid glitches - for (int i = todo * channels; i < int(p_frames) * channels; i++) { + for (uint32_t i = todo * channels; i < int(p_frames) * channels; i++) { p_dest[i] = 0; } @@ -250,7 +250,7 @@ Error AudioRBResampler::setup(int p_channels, int p_src_mix_rate, int p_target_m rb_write_pos = 0; //avoid maybe strange noises upon load - for (int i = 0; i < (rb_len * channels); i++) { + for (unsigned int i = 0; i < (rb_len * channels); i++) { rb[i] = 0; read_buf[i] = 0; diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index dd4240f028..d7b2c2c5e0 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -178,25 +178,25 @@ int AudioStreamPlaybackRandomPitch::get_loop_count() const { return 0; } -float AudioStreamPlaybackRandomPitch::get_pos() const { +float AudioStreamPlaybackRandomPitch::get_playback_position() const { if (playing.is_valid()) { - return playing->get_pos(); + return playing->get_playback_position(); } return 0; } -void AudioStreamPlaybackRandomPitch::seek_pos(float p_time) { +void AudioStreamPlaybackRandomPitch::seek(float p_time) { if (playing.is_valid()) { - playing->seek_pos(p_time); + playing->seek(p_time); } } -void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames) { +void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { if (playing.is_valid()) { - playing->mix(p_bufer, p_rate_scale * pitch_scale, p_frames); + playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames); } else { for (int i = 0; i < p_frames; i++) { - p_bufer[i] = AudioFrame(0, 0); + p_buffer[i] = AudioFrame(0, 0); } } } diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index c7cb63ef2c..dc931502b4 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -45,10 +45,10 @@ public: virtual int get_loop_count() const = 0; //times it looped - virtual float get_pos() const = 0; - virtual void seek_pos(float p_time) = 0; + virtual float get_playback_position() const = 0; + virtual void seek(float p_time) = 0; - virtual void mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames) = 0; + virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) = 0; virtual float get_length() const = 0; //if supported, otherwise return 0 }; @@ -70,7 +70,7 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback { protected: void _begin_resample(); - virtual void _mix_internal(AudioFrame *p_bufer, int p_frames) = 0; + virtual void _mix_internal(AudioFrame *p_buffer, int p_frames) = 0; virtual float get_stream_sampling_rate() = 0; public: @@ -133,10 +133,10 @@ public: virtual int get_loop_count() const; //times it looped - virtual float get_pos() const; - virtual void seek_pos(float p_time); + virtual float get_playback_position() const; + virtual void seek(float p_time); - virtual void mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames); + virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); virtual float get_length() const; //if supported, otherwise return 0 diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp index 4075bc3e63..32631beb2c 100644 --- a/servers/audio/effects/audio_effect_chorus.cpp +++ b/servers/audio/effects/audio_effect_chorus.cpp @@ -78,7 +78,7 @@ void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames, A uint64_t increment = llrint(cycles_to_mix / (double)p_frame_count * (double)(1 << AudioEffectChorus::CYCLES_FRAC)); //check the LFO doesn't read ahead of the write pos - if ((((int)max_depth_frames) + 10) > delay_frames) { //10 as some threshold to avoid precision stuff + if ((((unsigned int)max_depth_frames) + 10) > delay_frames) { //10 as some threshold to avoid precision stuff delay_frames += (int)max_depth_frames - delay_frames; delay_frames += 10; //threshold to avoid precision stuff } @@ -182,9 +182,8 @@ Ref<AudioEffectInstance> AudioEffectChorus::instance() { void AudioEffectChorus::set_voice_count(int p_voices) { - ERR_FAIL_COND(p_voices < 1 || p_voices >= MAX_VOICES); + ERR_FAIL_COND(p_voices < 1 || p_voices > MAX_VOICES); voice_count = p_voices; - _change_notify(); } int AudioEffectChorus::get_voice_count() const { diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp index f2bcabc3cb..3e6280f033 100644 --- a/servers/audio/effects/audio_effect_distortion.cpp +++ b/servers/audio/effects/audio_effect_distortion.cpp @@ -175,6 +175,12 @@ void AudioEffectDistortion::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20000,1"), "set_keep_hf_hz", "get_keep_hf_hz"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "post_gain", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_post_gain", "get_post_gain"); + + BIND_ENUM_CONSTANT(MODE_CLIP); + BIND_ENUM_CONSTANT(MODE_ATAN); + BIND_ENUM_CONSTANT(MODE_LOFI); + BIND_ENUM_CONSTANT(MODE_OVERDRIVE); + BIND_ENUM_CONSTANT(MODE_WAVESHAPE); } AudioEffectDistortion::AudioEffectDistortion() { diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp index 64a9db51a5..95354230c6 100644 --- a/servers/audio/effects/audio_effect_filter.cpp +++ b/servers/audio/effects/audio_effect_filter.cpp @@ -158,7 +158,12 @@ void AudioEffectFilter::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "cutoff_hz", PROPERTY_HINT_RANGE, "1,40000,0.1"), "set_cutoff", "get_cutoff"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "resonance", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_resonance", "get_resonance"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "gain", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_gain", "get_gain"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "dB", PROPERTY_HINT_ENUM, "6db,12db,18db,24db"), "set_db", "get_db"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "db", PROPERTY_HINT_ENUM, "6 dB,12 dB,18 dB,24 dB"), "set_db", "get_db"); + + BIND_ENUM_CONSTANT(FILTER_6DB); + BIND_ENUM_CONSTANT(FILTER_12DB); + BIND_ENUM_CONSTANT(FILTER_18DB); + BIND_ENUM_CONSTANT(FILTER_24DB); } AudioEffectFilter::AudioEffectFilter(AudioFilterSW::Mode p_mode) { diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp index 391e5db639..c50dd804f2 100644 --- a/servers/audio/effects/audio_effect_limiter.cpp +++ b/servers/audio/effects/audio_effect_limiter.cpp @@ -31,18 +31,13 @@ void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { - float thresh = Math::db2linear(base->threshold); float threshdb = base->threshold; float ceiling = Math::db2linear(base->ceiling); float ceildb = base->ceiling; float makeup = Math::db2linear(ceildb - threshdb); - float makeupdb = ceildb - threshdb; float sc = -base->soft_clip; float scv = Math::db2linear(sc); - float sccomp = Math::db2linear(-sc); float peakdb = ceildb + 25; - float peaklvl = Math::db2linear(peakdb); - float scratio = base->soft_clip_ratio; float scmult = Math::abs((ceildb - sc) / (peakdb - sc)); for (int i = 0; i < p_frame_count; i++) { @@ -115,7 +110,7 @@ void AudioEffectLimiter::set_soft_clip_ratio(float p_soft_clip) { } float AudioEffectLimiter::get_soft_clip_ratio() const { - return soft_clip; + return soft_clip_ratio; } void AudioEffectLimiter::_bind_methods() { diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index c0343399c3..18b7014595 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -32,6 +32,7 @@ #include "os/file_access.h" #include "os/os.h" #include "project_settings.h" +#include "servers/audio/audio_driver_dummy.h" #include "servers/audio/effects/audio_effect_compressor.h" #ifdef TOOLS_ENABLED @@ -77,6 +78,28 @@ double AudioDriver::get_mix_time() const { return total; } +AudioDriver::SpeakerMode AudioDriver::get_speaker_mode_by_total_channels(int p_channels) const { + switch (p_channels) { + case 4: return SPEAKER_SURROUND_31; + case 6: return SPEAKER_SURROUND_51; + case 8: return SPEAKER_SURROUND_71; + } + + // Default to STEREO + return SPEAKER_MODE_STEREO; +} + +int AudioDriver::get_total_channels_by_speaker_mode(AudioDriver::SpeakerMode p_mode) const { + switch (p_mode) { + case SPEAKER_MODE_STEREO: return 2; + case SPEAKER_SURROUND_31: return 4; + case SPEAKER_SURROUND_51: return 6; + case SPEAKER_SURROUND_71: return 8; + } + + ERR_FAIL_V(2); +} + AudioDriver::AudioDriver() { _last_mix_time = 0; @@ -85,6 +108,7 @@ AudioDriver::AudioDriver() { AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS]; int AudioDriverManager::driver_count = 0; +AudioDriverDummy AudioDriverManager::dummy_driver; void AudioDriverManager::add_driver(AudioDriver *p_driver) { @@ -96,6 +120,43 @@ int AudioDriverManager::get_driver_count() { return driver_count; } + +void AudioDriverManager::initialize(int p_driver) { + AudioDriver *driver; + int failed_driver = -1; + + // Check if there is a selected driver + if (p_driver >= 0 && p_driver < driver_count) { + if (drivers[p_driver]->init() == OK) { + drivers[p_driver]->set_singleton(); + return; + } else { + failed_driver = p_driver; + } + } + + // No selected driver, try them all in order + for (int i = 0; i < driver_count; i++) { + // Don't re-init the driver if it failed above + if (i == failed_driver) { + continue; + } + + if (drivers[i]->init() == OK) { + drivers[i]->set_singleton(); + return; + } + } + + // Fallback to our dummy driver + if (dummy_driver.init() == OK) { + ERR_PRINT("AudioDriverManager: all drivers failed, falling back to dummy driver"); + dummy_driver.set_singleton(); + } else { + ERR_PRINT("AudioDriverManager: dummy driver faild to init()"); + } +} + AudioDriver *AudioDriverManager::get_driver(int p_driver) { ERR_FAIL_INDEX_V(p_driver, driver_count, NULL); @@ -155,6 +216,29 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { todo -= to_copy; to_mix -= to_copy; } + +#ifdef DEBUG_ENABLED + if (OS::get_singleton() && OS::get_singleton()->is_stdout_verbose()) { + static uint64_t first_ticks = 0; + static uint64_t last_ticks = 0; + static uint64_t ticks = 0; + static int count = 0; + static int total = 0; + + ticks = OS::get_singleton()->get_ticks_msec(); + if ((ticks - first_ticks) > 10 * 1000) { + print_line("Audio Driver " + String(AudioDriver::get_singleton()->get_name()) + " average latency: " + itos(total / count) + "ms (frame=" + itos(p_frames) + ")"); + first_ticks = ticks; + total = 0; + count = 0; + } + + total += ticks - last_ticks; + count++; + + last_ticks = ticks; + } +#endif } void AudioServer::_mix_step() { @@ -180,8 +264,9 @@ void AudioServer::_mix_step() { if (!bus_map.has(bus->send)) { bus = buses[0]; //send to master } else { + int prev_index_cache = bus->index_cache; bus = bus_map[bus->send]; - if (bus->index_cache >= bus->index_cache) { //invalid, send to master + if (prev_index_cache >= bus->index_cache) { //invalid, send to master bus = buses[0]; } } @@ -400,8 +485,8 @@ void AudioServer::set_bus_count(int p_count) { } buses[i] = memnew(Bus); - buses[i]->channels.resize(_get_channel_count()); - for (int j = 0; j < _get_channel_count(); j++) { + buses[i]->channels.resize(get_channel_count()); + for (int j = 0; j < get_channel_count(); j++) { buses[i]->channels[j].buffer.resize(buffer_size); } buses[i]->name = attempt; @@ -470,8 +555,8 @@ void AudioServer::add_bus(int p_at_pos) { } Bus *bus = memnew(Bus); - bus->channels.resize(_get_channel_count()); - for (int j = 0; j < _get_channel_count(); j++) { + bus->channels.resize(get_channel_count()); + for (int j = 0; j < get_channel_count(); j++) { bus->channels[j].buffer.resize(buffer_size); } bus->name = attempt; @@ -774,17 +859,8 @@ void AudioServer::init() { channel_disable_threshold_db = GLOBAL_DEF("audio/channel_disable_threshold_db", -60.0); channel_disable_frames = float(GLOBAL_DEF("audio/channel_disable_time", 2.0)) * get_mix_rate(); buffer_size = 1024; //harcoded for now - switch (get_speaker_mode()) { - case SPEAKER_MODE_STEREO: { - temp_buffer.resize(1); - } break; - case SPEAKER_SURROUND_51: { - temp_buffer.resize(3); - } break; - case SPEAKER_SURROUND_71: { - temp_buffer.resize(4); - } break; - } + + temp_buffer.resize(get_channel_count()); for (int i = 0; i < temp_buffer.size(); i++) { temp_buffer[i].resize(buffer_size); @@ -792,11 +868,11 @@ void AudioServer::init() { mix_count = 0; set_bus_count(1); - ; set_bus_name(0, "Master"); if (AudioDriver::get_singleton()) AudioDriver::get_singleton()->start(); + #ifdef TOOLS_ENABLED set_edited(false); //avoid editors from thinking this was edited #endif @@ -968,8 +1044,8 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) { bus_map[bus->name] = bus; buses[i] = bus; - buses[i]->channels.resize(_get_channel_count()); - for (int j = 0; j < _get_channel_count(); j++) { + buses[i]->channels.resize(get_channel_count()); + for (int j = 0; j < get_channel_count(); j++) { buses[i]->channels[j].buffer.resize(buffer_size); } _update_bus_effects(i); @@ -1012,7 +1088,7 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bus_count"), &AudioServer::get_bus_count); ClassDB::bind_method(D_METHOD("remove_bus", "index"), &AudioServer::remove_bus); - ClassDB::bind_method(D_METHOD("add_bus", "at_pos"), &AudioServer::add_bus, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("add_bus", "at_position"), &AudioServer::add_bus, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("move_bus", "index", "to_index"), &AudioServer::move_bus); ClassDB::bind_method(D_METHOD("set_bus_name", "bus_idx", "name"), &AudioServer::set_bus_name); @@ -1034,7 +1110,7 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bus_bypass_effects", "bus_idx", "enable"), &AudioServer::set_bus_bypass_effects); ClassDB::bind_method(D_METHOD("is_bus_bypassing_effects", "bus_idx"), &AudioServer::is_bus_bypassing_effects); - ClassDB::bind_method(D_METHOD("add_bus_effect", "bus_idx", "effect", "at_pos"), &AudioServer::add_bus_effect, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("add_bus_effect", "bus_idx", "effect", "at_position"), &AudioServer::add_bus_effect, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("remove_bus_effect", "bus_idx", "effect_idx"), &AudioServer::remove_bus_effect); ClassDB::bind_method(D_METHOD("get_bus_effect_count", "bus_idx"), &AudioServer::get_bus_effect_count); @@ -1057,6 +1133,10 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout); ADD_SIGNAL(MethodInfo("bus_layout_changed")); + + BIND_ENUM_CONSTANT(SPEAKER_MODE_STEREO); + BIND_ENUM_CONSTANT(SPEAKER_SURROUND_51); + BIND_ENUM_CONSTANT(SPEAKER_SURROUND_71); } AudioServer::AudioServer() { diff --git a/servers/audio_server.h b/servers/audio_server.h index 05e92ceaf0..55e9367308 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -35,6 +35,8 @@ #include "servers/audio/audio_effect.h" #include "variant.h" +class AudioDriverDummy; + class AudioDriver { static AudioDriver *singleton; @@ -50,10 +52,14 @@ public: enum SpeakerMode { SPEAKER_MODE_STEREO, + SPEAKER_SURROUND_31, SPEAKER_SURROUND_51, SPEAKER_SURROUND_71, }; + static const int DEFAULT_MIX_RATE = 44100; + static const int DEFAULT_OUTPUT_LATENCY = 15; + static AudioDriver *get_singleton(); void set_singleton(); @@ -69,6 +75,9 @@ public: virtual float get_latency() { return 0; } + SpeakerMode get_speaker_mode_by_total_channels(int p_channels) const; + int get_total_channels_by_speaker_mode(SpeakerMode) const; + AudioDriver(); virtual ~AudioDriver() {} }; @@ -83,8 +92,11 @@ class AudioDriverManager { static AudioDriver *drivers[MAX_DRIVERS]; static int driver_count; + static AudioDriverDummy dummy_driver; + public: static void add_driver(AudioDriver *p_driver); + static void initialize(int p_driver); static int get_driver_count(); static AudioDriver *get_driver(int p_driver); }; @@ -98,6 +110,7 @@ public: //re-expose this her, as AudioDriver is not exposed to script enum SpeakerMode { SPEAKER_MODE_STEREO, + SPEAKER_SURROUND_31, SPEAKER_SURROUND_51, SPEAKER_SURROUND_71, }; @@ -160,15 +173,6 @@ private: Vector<Bus *> buses; Map<StringName, Bus *> bus_map; - _FORCE_INLINE_ int _get_channel_count() const { - switch (AudioDriver::get_singleton()->get_speaker_mode()) { - case AudioDriver::SPEAKER_MODE_STEREO: return 1; - case AudioDriver::SPEAKER_SURROUND_51: return 3; - case AudioDriver::SPEAKER_SURROUND_71: return 4; - } - ERR_FAIL_V(1); - } - void _update_bus_effects(int p_bus); static AudioServer *singleton; @@ -202,6 +206,16 @@ protected: static void _bind_methods(); public: + _FORCE_INLINE_ int get_channel_count() const { + switch (get_speaker_mode()) { + case SPEAKER_MODE_STEREO: return 1; + case SPEAKER_SURROUND_31: return 2; + case SPEAKER_SURROUND_51: return 3; + case SPEAKER_SURROUND_71: return 4; + } + ERR_FAIL_V(1); + } + //do not use from outside audio thread AudioFrame *thread_get_channel_mix_buffer(int p_bus, int p_buffer); int thread_get_mix_buffer_size() const; diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index 7e8d31f8eb..782bf14a4b 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -399,7 +399,7 @@ public: virtual int get_contact_count() const { return body->contact_count; } - virtual Vector3 get_contact_local_pos(int p_contact_idx) const { + virtual Vector3 get_contact_local_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); return body->contacts[p_contact_idx].local_pos; } @@ -416,7 +416,7 @@ public: ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID()); return body->contacts[p_contact_idx].collider; } - virtual Vector3 get_contact_collider_pos(int p_contact_idx) const { + virtual Vector3 get_contact_collider_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); return body->contacts[p_contact_idx].collider_pos; } @@ -428,7 +428,7 @@ public: ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0); return body->contacts[p_contact_idx].collider_shape; } - virtual Vector3 get_contact_collider_velocity_at_pos(int p_contact_idx) const { + virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); return body->contacts[p_contact_idx].collider_velocity_at_pos; } diff --git a/servers/physics/broad_phase_basic.cpp b/servers/physics/broad_phase_basic.cpp index 959718a252..c6565ac2e9 100644 --- a/servers/physics/broad_phase_basic.cpp +++ b/servers/physics/broad_phase_basic.cpp @@ -30,9 +30,10 @@ #include "broad_phase_basic.h" #include "list.h" #include "print_string.h" + BroadPhaseSW::ID BroadPhaseBasic::create(CollisionObjectSW *p_object, int p_subindex) { - ERR_FAIL_COND_V(p_object == NULL, NULL); + ERR_FAIL_COND_V(p_object == NULL, 0); current++; diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h index 51a24f4678..5c124c1792 100644 --- a/servers/physics/broad_phase_basic.h +++ b/servers/physics/broad_phase_basic.h @@ -82,7 +82,7 @@ class BroadPhaseBasic : public BroadPhaseSW { public: // 0 is an invalid ID - virtual ID create(CollisionObjectSW *p_object_, int p_subindex = 0); + virtual ID create(CollisionObjectSW *p_object, int p_subindex = 0); virtual void move(ID p_id, const Rect3 &p_aabb); virtual void set_static(ID p_id, bool p_static); virtual void remove(ID p_id); diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp index ab716a8f6e..3af8b542fa 100644 --- a/servers/physics/collision_object_sw.cpp +++ b/servers/physics/collision_object_sw.cpp @@ -28,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "collision_object_sw.h" +#include "servers/physics/physics_server_sw.h" #include "space_sw.h" void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform) { @@ -39,8 +40,12 @@ void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform s.bpid = 0; //needs update shapes.push_back(s); p_shape->add_owner(this); - _update_shapes(); - _shapes_changed(); + + if (!pending_shape_update_list.in_list()) { + PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); } void CollisionObjectSW::set_shape(int p_index, ShapeSW *p_shape) { @@ -50,8 +55,11 @@ void CollisionObjectSW::set_shape(int p_index, ShapeSW *p_shape) { shapes[p_index].shape = p_shape; p_shape->add_owner(this); - _update_shapes(); - _shapes_changed(); + if (!pending_shape_update_list.in_list()) { + PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); } void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_transform) { @@ -59,8 +67,11 @@ void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_tran shapes[p_index].xform = p_transform; shapes[p_index].xform_inv = p_transform.affine_inverse(); - _update_shapes(); - _shapes_changed(); + if (!pending_shape_update_list.in_list()) { + PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); } void CollisionObjectSW::remove_shape(ShapeSW *p_shape) { @@ -90,7 +101,11 @@ void CollisionObjectSW::remove_shape(int p_index) { shapes[p_index].shape->remove_owner(this); shapes.remove(p_index); - _shapes_changed(); + if (!pending_shape_update_list.in_list()) { + PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); } void CollisionObjectSW::_set_static(bool p_static) { @@ -202,7 +217,8 @@ void CollisionObjectSW::_shape_changed() { _shapes_changed(); } -CollisionObjectSW::CollisionObjectSW(Type p_type) { +CollisionObjectSW::CollisionObjectSW(Type p_type) + : pending_shape_update_list(this) { _static = true; type = p_type; diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h index dc988aae86..67a8a44944 100644 --- a/servers/physics/collision_object_sw.h +++ b/servers/physics/collision_object_sw.h @@ -75,6 +75,8 @@ private: Transform inv_transform; bool _static; + SelfList<CollisionObjectSW> pending_shape_update_list; + void _update_shapes(); protected: diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index c7f66cb7fc..7bef208237 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -271,7 +271,7 @@ bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A, const Tra bool collided = false; Vector3 closest; - real_t closest_d; + real_t closest_d = 0; for (int i = 0; i < support_count; i++) { diff --git a/servers/physics/gjk_epa.cpp b/servers/physics/gjk_epa.cpp index 6cea5b003d..0f03bd917a 100644 --- a/servers/physics/gjk_epa.cpp +++ b/servers/physics/gjk_epa.cpp @@ -410,8 +410,8 @@ struct GJK if(l>GJK_SIMPLEX3_EPS) { real_t mindist=-1; - real_t subw[2]; - U subm; + real_t subw[2] = { 0 , 0}; + U subm = 0; for(U i=0;i<3;++i) { if(vec3_dot(*vt[i],vec3_cross(dl[i],n))>0) @@ -458,7 +458,7 @@ struct GJK { real_t mindist=-1; real_t subw[3]; - U subm; + U subm=0; for(U i=0;i<3;++i) { const U j=imd3[i]; diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h index 670c1ab61f..f6c11c49b0 100644 --- a/servers/physics/joints/pin_joint_sw.h +++ b/servers/physics/joints/pin_joint_sw.h @@ -86,8 +86,8 @@ public: void set_pos_a(const Vector3 &p_pos) { m_pivotInA = p_pos; } void set_pos_b(const Vector3 &p_pos) { m_pivotInB = p_pos; } - Vector3 get_pos_a() { return m_pivotInB; } - Vector3 get_pos_b() { return m_pivotInA; } + Vector3 get_position_a() { return m_pivotInA; } + Vector3 get_position_b() { return m_pivotInB; } PinJointSW(BodySW *p_body_a, const Vector3 &p_pos_a, BodySW *p_body_b, const Vector3 &p_pos_b); ~PinJointSW(); diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 432d20105b..5ba935d47c 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -183,7 +183,7 @@ PhysicsDirectSpaceState *PhysicsServerSW::space_get_direct_state(RID p_space) { ERR_FAIL_COND_V(!space, NULL); if (!doing_sync || space->is_locked()) { - ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or fixed process notification."); + ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or physics process notification."); ERR_FAIL_V(NULL); } @@ -749,6 +749,8 @@ void PhysicsServerSW::body_apply_impulse(RID p_body, const Vector3 &p_pos, const BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + _update_shapes(); + body->apply_impulse(p_pos, p_impulse); body->wakeup(); }; @@ -758,6 +760,8 @@ void PhysicsServerSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_imp BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + _update_shapes(); + body->apply_torque_impulse(p_impulse); body->wakeup(); }; @@ -767,6 +771,8 @@ void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_v BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + _update_shapes(); + Vector3 v = body->get_linear_velocity(); Vector3 axis = p_axis_velocity.normalized(); v -= axis * axis.dot(v); @@ -779,6 +785,7 @@ void PhysicsServerSW::body_set_axis_lock(RID p_body, BodyAxisLock p_lock) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); + body->set_axis_lock(p_lock); body->wakeup(); } @@ -888,9 +895,26 @@ bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, cons ERR_FAIL_COND_V(!body->get_space(), false); ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + _update_shapes(); + return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result); } +PhysicsDirectBodyState *PhysicsServerSW::body_get_direct_state(RID p_body) { + + BodySW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body, NULL); + + if (!doing_sync || body->get_space()->is_locked()) { + + ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification."); + ERR_FAIL_V(NULL); + } + + direct_state->body = body; + return direct_state; +} + /* JOINT API */ RID PhysicsServerSW::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { @@ -945,7 +969,7 @@ Vector3 PhysicsServerSW::pin_joint_get_local_a(RID p_joint) const { ERR_FAIL_COND_V(!joint, Vector3()); ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); PinJointSW *pin_joint = static_cast<PinJointSW *>(joint); - return pin_joint->get_pos_a(); + return pin_joint->get_position_a(); } void PhysicsServerSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { @@ -962,7 +986,7 @@ Vector3 PhysicsServerSW::pin_joint_get_local_b(RID p_joint) const { ERR_FAIL_COND_V(!joint, Vector3()); ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); PinJointSW *pin_joint = static_cast<PinJointSW *>(joint); - return pin_joint->get_pos_b(); + return pin_joint->get_position_b(); } RID PhysicsServerSW::joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) { @@ -1195,6 +1219,8 @@ bool PhysicsServerSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_a void PhysicsServerSW::free(RID p_rid) { + _update_shapes(); //just in case + if (shape_owner.owns(p_rid)) { ShapeSW *shape = shape_owner.get(p_rid); @@ -1298,6 +1324,8 @@ void PhysicsServerSW::step(real_t p_step) { if (!active) return; + _update_shapes(); + doing_sync = false; last_step = p_step; @@ -1395,6 +1423,14 @@ int PhysicsServerSW::get_process_info(ProcessInfo p_info) { return 0; } +void PhysicsServerSW::_update_shapes() { + + while (pending_shape_update_list.first()) { + pending_shape_update_list.first()->self()->_shape_changed(); + pending_shape_update_list.remove(pending_shape_update_list.first()); + } +} + void PhysicsServerSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { CollCbkData *cbk = (CollCbkData *)p_userdata; diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 2e1fa7065a..f9eb8fa454 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -62,6 +62,10 @@ class PhysicsServerSW : public PhysicsServer { mutable RID_Owner<JointSW> joint_owner; //void _clear_query(QuerySW *p_query); + friend class CollisionObjectSW; + SelfList<CollisionObjectSW>::List pending_shape_update_list; + void _update_shapes(); + public: static PhysicsServerSW *singleton; @@ -91,7 +95,7 @@ public: virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value); virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const; - // this function only works on fixed process, errors and returns null otherwise + // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space); virtual void space_set_debug_contacts(RID p_space, int p_max_contacts); @@ -219,6 +223,9 @@ public: virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, float p_margin = 0.001, MotionResult *r_result = NULL); + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); + /* JOINT API */ virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B); diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp index f02ff03fcf..6dafaac115 100644 --- a/servers/physics/shape_sw.cpp +++ b/servers/physics/shape_sw.cpp @@ -734,7 +734,7 @@ Vector3 ConvexPolygonShapeSW::get_support(const Vector3 &p_normal) const { Vector3 n = p_normal; int vert_support_idx = -1; - real_t support_max; + real_t support_max = 0; int vertex_count = mesh.vertices.size(); if (vertex_count == 0) @@ -767,8 +767,8 @@ void ConvexPolygonShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vect int vc = mesh.vertices.size(); //find vertex first - real_t max; - int vtx; + real_t max = 0; + int vtx = 0; for (int i = 0; i < vc; i++) { @@ -954,6 +954,9 @@ Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(real_t p_mass) const { void ConvexPolygonShapeSW::_setup(const Vector<Vector3> &p_vertices) { Error err = QuickHull::build(p_vertices, mesh); + if (err != OK) + ERR_PRINT("Failed to build QuickHull"); + Rect3 _aabb; for (int i = 0; i < mesh.vertices.size(); i++) { @@ -1000,7 +1003,7 @@ void FaceShapeSW::project_range(const Vector3 &p_normal, const Transform &p_tran Vector3 FaceShapeSW::get_support(const Vector3 &p_normal) const { int vert_support_idx = -1; - real_t support_max; + real_t support_max = 0; for (int i = 0; i < 3; i++) { @@ -1154,7 +1157,7 @@ Vector3 ConcavePolygonShapeSW::get_support(const Vector3 &p_normal) const { Vector3 n = p_normal; int vert_support_idx = -1; - real_t support_max; + real_t support_max = 0; for (int i = 0; i < count; i++) { @@ -1208,8 +1211,6 @@ void ConcavePolygonShapeSW::_cull_segment(int p_idx, _SegmentCullParams *p_param p_params->min_d = d; p_params->result = res; p_params->normal = Plane(vertices[0], vertices[1], vertices[2]).normal; - if (p_params->normal.dot(p_params->dir) > 0) - p_params->normal = -p_params->normal; p_params->collisions++; } } diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 17e2df6c9e..7e68d54bfa 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -33,9 +33,9 @@ #include "physics_server_sw.h" #include "project_settings.h" -_FORCE_INLINE_ static bool _match_object_type_query(CollisionObjectSW *p_object, uint32_t p_collision_layer, uint32_t p_type_mask) { +_FORCE_INLINE_ static bool _match_object_type_query(CollisionObjectSW *p_object, uint32_t p_collision_mask, uint32_t p_type_mask) { - if ((p_object->get_collision_layer() & p_collision_layer) == 0) + if ((p_object->get_collision_layer() & p_collision_mask) == 0) return false; if (p_object->get_type() == CollisionObjectSW::TYPE_AREA) @@ -46,7 +46,7 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObjectSW *p_object, return (1 << body->get_mode()) & p_type_mask; } -int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { ERR_FAIL_COND_V(space->locked, false); int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -59,7 +59,7 @@ int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResu if (cc >= p_result_max) break; - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; //area can't be picked by ray (default) @@ -90,7 +90,7 @@ int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResu return cc; } -bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask, bool p_pick_ray) { +bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask, bool p_pick_ray) { ERR_FAIL_COND_V(space->locked, false); @@ -112,7 +112,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; if (p_pick_ray && !(static_cast<CollisionObjectSW *>(space->intersection_query_results[i])->is_ray_pickable())) @@ -168,7 +168,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vecto return true; } -int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { if (p_result_max <= 0) return 0; @@ -189,7 +189,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transfo if (cc >= p_result_max) break; - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; //area can't be picked by ray (default) @@ -219,7 +219,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transfo return cc; } -bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask, ShapeRestInfo *r_info) { +bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask, ShapeRestInfo *r_info) { ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape, false); @@ -249,7 +249,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -333,7 +333,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform return true; } -bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { if (p_result_max <= 0) return 0; @@ -363,7 +363,7 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_sh for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; const CollisionObjectSW *col_obj = space->intersection_query_results[i]; @@ -412,7 +412,7 @@ static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, rd->best_object = rd->object; rd->best_shape = rd->shape; } -bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape, 0); @@ -429,7 +429,7 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_ for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; const CollisionObjectSW *col_obj = space->intersection_query_results[i]; diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h index 56f4d2f10d..270e4ef1bd 100644 --- a/servers/physics/space_sw.h +++ b/servers/physics/space_sw.h @@ -47,12 +47,12 @@ class PhysicsDirectSpaceStateSW : public PhysicsDirectSpaceState { public: SpaceSW *space; - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_ray = false); - virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); - virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, ShapeRestInfo *r_info = NULL); - virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); - virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_ray = false); + virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, ShapeRestInfo *r_info = NULL); + virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const; PhysicsDirectSpaceStateSW(); diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp index 79a55e0af1..76b097dda6 100644 --- a/servers/physics/step_sw.cpp +++ b/servers/physics/step_sw.cpp @@ -62,7 +62,7 @@ void StepSW::_setup_island(ConstraintSW *p_island, real_t p_delta) { ConstraintSW *ci = p_island; while (ci) { - bool process = ci->setup(p_delta); + ci->setup(p_delta); //todo remove from island if process fails ci = ci->get_island_next(); } diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 0ffad62f45..f7c717a5c6 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -353,7 +353,7 @@ public: virtual int get_contact_count() const { return body->contact_count; } - virtual Vector2 get_contact_local_pos(int p_contact_idx) const { + virtual Vector2 get_contact_local_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2()); return body->contacts[p_contact_idx].local_pos; } @@ -370,7 +370,7 @@ public: ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID()); return body->contacts[p_contact_idx].collider; } - virtual Vector2 get_contact_collider_pos(int p_contact_idx) const { + virtual Vector2 get_contact_collider_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2()); return body->contacts[p_contact_idx].collider_pos; } @@ -384,7 +384,7 @@ public: } virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const; - virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const { + virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2()); return body->contacts[p_contact_idx].collider_velocity_at_pos; } diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp index 6c800a4b49..db18995bee 100644 --- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp +++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp @@ -640,7 +640,7 @@ BroadPhase2DHashGrid::BroadPhase2DHashGrid() { cell_size = GLOBAL_DEF("physics/2d/cell_size", 128); large_object_min_surface = GLOBAL_DEF("physics/2d/large_object_surface_threshold_in_cells", 512); - for (int i = 0; i < hash_table_size; i++) + for (uint32_t i = 0; i < hash_table_size; i++) hash_table[i] = NULL; pass = 1; @@ -649,7 +649,7 @@ BroadPhase2DHashGrid::BroadPhase2DHashGrid() { BroadPhase2DHashGrid::~BroadPhase2DHashGrid() { - for (int i = 0; i < hash_table_size; i++) { + for (uint32_t i = 0; i < hash_table_size; i++) { while (hash_table[i]) { PosBin *pb = hash_table[i]; hash_table[i] = pb->next; diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index db1270633f..627ba8ea15 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -110,21 +110,48 @@ public: void set_shape_metadata(int p_index, const Variant &p_metadata); _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } - _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { return shapes[p_index].shape; } - _FORCE_INLINE_ const Transform2D &get_shape_transform(int p_index) const { return shapes[p_index].xform; } - _FORCE_INLINE_ const Transform2D &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } - _FORCE_INLINE_ const Rect2 &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } - _FORCE_INLINE_ const Variant &get_shape_metadata(int p_index) const { return shapes[p_index].metadata; } + _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { + ERR_FAIL_INDEX_V(p_index, shapes.size(), NULL); + return shapes[p_index].shape; + } + _FORCE_INLINE_ const Transform2D &get_shape_transform(int p_index) const { + ERR_FAIL_INDEX_V(p_index, shapes.size(), Transform2D()); + return shapes[p_index].xform; + } + _FORCE_INLINE_ const Transform2D &get_shape_inv_transform(int p_index) const { + ERR_FAIL_INDEX_V(p_index, shapes.size(), Transform2D()); + return shapes[p_index].xform_inv; + } + _FORCE_INLINE_ const Rect2 &get_shape_aabb(int p_index) const { + ERR_FAIL_INDEX_V(p_index, shapes.size(), Rect2()); + return shapes[p_index].aabb_cache; + } + _FORCE_INLINE_ const Variant &get_shape_metadata(int p_index) const { + ERR_FAIL_INDEX_V(p_index, shapes.size(), Variant()); + return shapes[p_index].metadata; + } _FORCE_INLINE_ Transform2D get_transform() const { return transform; } _FORCE_INLINE_ Transform2D get_inv_transform() const { return inv_transform; } _FORCE_INLINE_ Space2DSW *get_space() const { return space; } - _FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_disabled) { shapes[p_idx].disabled = p_disabled; } - _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const { return shapes[p_idx].disabled; } + _FORCE_INLINE_ void set_shape_as_disabled(int p_idx, bool p_disabled) { + ERR_FAIL_INDEX(p_idx, shapes.size()); + shapes[p_idx].disabled = p_disabled; + } + _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, shapes.size(), false); + return shapes[p_idx].disabled; + } - _FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision) { shapes[p_idx].one_way_collision = p_one_way_collision; } - _FORCE_INLINE_ bool is_shape_set_as_one_way_collision(int p_idx) const { return shapes[p_idx].one_way_collision; } + _FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision) { + ERR_FAIL_INDEX(p_idx, shapes.size()); + shapes[p_idx].one_way_collision = p_one_way_collision; + } + _FORCE_INLINE_ bool is_shape_set_as_one_way_collision(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, shapes.size(), false); + return shapes[p_idx].one_way_collision; + } void set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; } _FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; } diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 773ee374c3..5d3305c82d 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -130,9 +130,12 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 & if (cbk->valid_dir != Vector2()) { if (p_point_A.distance_squared_to(p_point_B) > cbk->valid_depth * cbk->valid_depth) { + cbk->invalid_by_dir++; return; } if (cbk->valid_dir.dot((p_point_A - p_point_B).normalized()) < 0.7071) { + cbk->invalid_by_dir++; + ; /* print_line("A: "+p_point_A); print_line("B: "+p_point_B); print_line("discard too angled "+rtos(cbk->valid_dir.dot((p_point_A-p_point_B)))); @@ -267,7 +270,7 @@ Physics2DDirectSpaceState *Physics2DServerSW::space_get_direct_state(RID p_space ERR_FAIL_COND_V(!space, NULL); if ((using_threads && !doing_sync) || space->is_locked()) { - ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or fixed process notification."); + ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or physics process notification."); ERR_FAIL_V(NULL); } @@ -937,6 +940,21 @@ bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result); } +Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) { + + Body2DSW *body = body_owner.get(p_body); + ERR_FAIL_COND_V(!body, NULL); + + if ((using_threads && !doing_sync) || body->get_space()->is_locked()) { + + ERR_EXPLAIN("Body state is inaccessible right now, wait for iteration or physics process notification."); + ERR_FAIL_V(NULL); + } + + direct_state->body = body; + return direct_state; +} + /* JOINT API */ void Physics2DServerSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) { diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 7d3c589fa9..c40cf0e3e0 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -74,6 +74,7 @@ public: real_t valid_depth; int max; int amount; + int invalid_by_dir; Vector2 *ptr; }; @@ -102,7 +103,7 @@ public: virtual Vector<Vector2> space_get_contacts(RID p_space) const; virtual int space_get_contact_count(RID p_space) const; - // this function only works on fixed process, errors and returns null otherwise + // this function only works on physics process, errors and returns null otherwise virtual Physics2DDirectSpaceState *space_get_direct_state(RID p_space); /* AREA API */ @@ -221,6 +222,9 @@ public: virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = NULL); + // this function only works on physics process, errors and returns null otherwise + virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body); + /* JOINT API */ virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp index a4e6abfd45..f8f3b620d4 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp +++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp @@ -109,16 +109,13 @@ void Physics2DServerWrapMT::init() { if (create_thread) { step_sem = Semaphore::create(); - print_line("CREATING PHYSICS 2D THREAD"); //OS::get_singleton()->release_rendering_thread(); if (create_thread) { thread = Thread::create(_thread_callback, this); - print_line("STARTING PHYISICS 2D THREAD"); } while (!step_thread_up) { OS::get_singleton()->delay_usec(1000); } - print_line("DONE PHYSICS 2D THREAD"); } else { physics_2d_server->init(); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 189419e8e4..50e9ab1005 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -111,7 +111,7 @@ public: FUNC3(space_set_param, RID, SpaceParameter, real_t); FUNC2RC(real_t, space_get_param, RID, SpaceParameter); - // this function only works on fixed process, errors and returns null otherwise + // this function only works on physics process, errors and returns null otherwise Physics2DDirectSpaceState *space_get_direct_state(RID p_space) { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), NULL); @@ -253,6 +253,13 @@ public: return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result); } + // this function only works on physics process, errors and returns null otherwise + Physics2DDirectBodyState *body_get_direct_state(RID p_body) { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), NULL); + return physics_2d_server->body_get_direct_state(p_body); + } + /* JOINT API */ FUNC3(joint_set_param, RID, JointParam, real_t); diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 9b2e586993..6eaaaa777b 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -30,11 +30,11 @@ #include "space_2d_sw.h" #include "collision_solver_2d_sw.h" +#include "pair.h" #include "physics_2d_server_sw.h" +_FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_object, uint32_t p_collision_mask, uint32_t p_type_mask) { -_FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_object, uint32_t p_collision_layer, uint32_t p_type_mask) { - - if ((p_object->get_collision_layer() & p_collision_layer) == 0) + if ((p_object->get_collision_layer() & p_collision_mask) == 0) return false; if (p_object->get_type() == CollisionObject2DSW::TYPE_AREA) @@ -45,7 +45,7 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_objec return (1 << body->get_mode()) & p_type_mask; } -int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask, bool p_pick_point) { +int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask, bool p_pick_point) { if (p_result_max <= 0) return 0; @@ -60,7 +60,7 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -96,7 +96,7 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe return cc; } -bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { ERR_FAIL_COND_V(space->locked, false); @@ -118,7 +118,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vec for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -176,7 +176,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vec return true; } -int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { if (p_result_max <= 0) return 0; @@ -193,7 +193,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -218,7 +218,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans return cc; } -bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape, false); @@ -239,7 +239,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; if (p_exclude.has(space->intersection_query_results[i]->get_self())) @@ -302,7 +302,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transfor return true; } -bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { if (p_result_max <= 0) return 0; @@ -333,7 +333,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D & for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; @@ -391,7 +391,7 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, rd->best_shape = rd->shape; } -bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_layer, uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, uint32_t p_object_type_mask) { Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape, 0); @@ -409,7 +409,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh for (int i = 0; i < amount; i++) { - if (!_match_object_type_query(space->intersection_query_results[i], p_collision_layer, p_object_type_mask)) + if (!_match_object_type_query(space->intersection_query_results[i], p_collision_mask, p_object_type_mask)) continue; const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; @@ -517,6 +517,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb)); body_aabb = body_aabb.grow(p_margin); + static const int max_excluded_shape_pairs = 32; + ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs]; + int excluded_shape_pair_count = 0; + Transform2D body_transform = p_from; { @@ -532,6 +536,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.max = max_results; cbk.amount = 0; cbk.ptr = sr; + cbk.invalid_by_dir = 0; + excluded_shape_pair_count = 0; //last step is the one valid Physics2DServerSW::CollCbkData *cbkptr = &cbk; CollisionSolver2DSW::CallbackResult cbkres = Physics2DServerSW::_shape_col_cbk; @@ -555,14 +561,29 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.valid_dir = body_shape_xform.get_axis(1).normalized(); cbk.valid_depth = p_margin; //only valid depth is the collision margin + cbk.invalid_by_dir = 0; + } else { cbk.valid_dir = Vector2(); cbk.valid_depth = 0; + cbk.invalid_by_dir = 0; } - if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) { + Shape2DSW *against_shape = col_obj->get_shape(shape_idx); + if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) { collided = cbk.amount > 0; } + + if (!collided && cbk.invalid_by_dir > 0) { + //this shape must be excluded + if (excluded_shape_pair_count < max_excluded_shape_pairs) { + ExcludedShapeSW esp; + esp.local_shape = body_shape; + esp.against_object = col_obj; + esp.against_shape_index = shape_idx; + excluded_shape_pairs[excluded_shape_pair_count++] = esp; + } + } } } @@ -622,15 +643,31 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co const CollisionObject2DSW *col_obj = intersection_query_results[i]; int shape_idx = intersection_query_subindex_results[i]; + Shape2DSW *against_shape = col_obj->get_shape(shape_idx); + + bool excluded = false; + + for (int k = 0; k < excluded_shape_pair_count; k++) { + + if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) { + excluded = true; + break; + } + } + + if (excluded) { + + continue; + } Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? - if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) { + if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) { continue; } //test initial overlap - if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) { + if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) { if (col_obj->is_shape_set_as_one_way_collision(j)) { continue; @@ -650,7 +687,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co real_t ofs = (low + hi) * 0.5; Vector2 sep = mnormal; //important optimization for this to work fast enough - bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), NULL, NULL, &sep, 0); + bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_xform, Vector2(), NULL, NULL, &sep, 0); if (collided) { @@ -669,7 +706,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.amount = 0; cbk.ptr = cd; cbk.valid_dir = body_shape_xform.get_axis(1).normalized(); - ; + cbk.valid_depth = 10e20; Vector2 sep = mnormal; //important optimization for this to work fast enough @@ -738,6 +775,19 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co const CollisionObject2DSW *col_obj = intersection_query_results[i]; int shape_idx = intersection_query_subindex_results[i]; + Shape2DSW *against_shape = col_obj->get_shape(shape_idx); + + bool excluded = false; + for (int k = 0; k < excluded_shape_pair_count; k++) { + + if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) { + excluded = true; + break; + } + } + if (excluded) + continue; + if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) { rcd.valid_dir = body_shape_xform.get_axis(1).normalized(); @@ -749,7 +799,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co rcd.object = col_obj; rcd.shape = shape_idx; - bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, NULL, p_margin); + bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, NULL, p_margin); if (!sc) continue; } diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index ed6136e372..bf0796fb22 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -47,12 +47,12 @@ class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState { public: Space2DSW *space; - virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_point = false); - virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); - virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); - virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); - virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); - virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION, bool p_pick_point = false); + virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); + virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, uint32_t p_object_type_mask = TYPE_MASK_COLLISION); Physics2DDirectSpaceStateSW(); }; @@ -71,6 +71,12 @@ public: }; private: + struct ExcludedShapeSW { + Shape2DSW *local_shape; + const CollisionObject2DSW *against_object; + int against_shape_index; + }; + uint64_t elapsed_time[ELAPSED_TIME_MAX]; Physics2DDirectSpaceStateSW *direct_access; diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 06966e2452..b2e1d541ab 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -92,16 +92,16 @@ void Physics2DDirectBodyState::_bind_methods() { ClassDB::bind_method(D_METHOD("get_contact_count"), &Physics2DDirectBodyState::get_contact_count); - ClassDB::bind_method(D_METHOD("get_contact_local_pos", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_pos); + ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_position); ClassDB::bind_method(D_METHOD("get_contact_local_normal", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_normal); ClassDB::bind_method(D_METHOD("get_contact_local_shape", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_shape); ClassDB::bind_method(D_METHOD("get_contact_collider", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider); - ClassDB::bind_method(D_METHOD("get_contact_collider_pos", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_pos); + ClassDB::bind_method(D_METHOD("get_contact_collider_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_position); ClassDB::bind_method(D_METHOD("get_contact_collider_id", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_id); ClassDB::bind_method(D_METHOD("get_contact_collider_object", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_object); ClassDB::bind_method(D_METHOD("get_contact_collider_shape", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_shape); ClassDB::bind_method(D_METHOD("get_contact_collider_shape_metadata", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_shape_metadata); - ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_pos", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_velocity_at_pos); + ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_velocity_at_position); ClassDB::bind_method(D_METHOD("get_step"), &Physics2DDirectBodyState::get_step); ClassDB::bind_method(D_METHOD("integrate_forces"), &Physics2DDirectBodyState::integrate_forces); ClassDB::bind_method(D_METHOD("get_space_state"), &Physics2DDirectBodyState::get_space_state); @@ -358,8 +358,8 @@ void Physics2DDirectSpaceState::_bind_methods() { BIND_ENUM_CONSTANT(TYPE_MASK_KINEMATIC_BODY); BIND_ENUM_CONSTANT(TYPE_MASK_RIGID_BODY); BIND_ENUM_CONSTANT(TYPE_MASK_CHARACTER_BODY); - BIND_ENUM_CONSTANT(TYPE_MASK_AREA); BIND_ENUM_CONSTANT(TYPE_MASK_COLLISION); + BIND_ENUM_CONSTANT(TYPE_MASK_AREA); } int Physics2DShapeQueryResult::get_result_count() const { @@ -561,7 +561,7 @@ void Physics2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &Physics2DServer::body_set_state); ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &Physics2DServer::body_get_state); - ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "pos", "impulse"), &Physics2DServer::body_apply_impulse); + ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &Physics2DServer::body_apply_impulse); ClassDB::bind_method(D_METHOD("body_add_force", "body", "offset", "force"), &Physics2DServer::body_add_force); ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &Physics2DServer::body_set_axis_velocity); @@ -579,6 +579,8 @@ void Physics2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result"), &Physics2DServer::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &Physics2DServer::body_get_direct_state); + /* JOINT API */ ClassDB::bind_method(D_METHOD("joint_set_param", "joint", "param", "value"), &Physics2DServer::joint_set_param); @@ -613,6 +615,7 @@ void Physics2DServer::_bind_methods() { BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); BIND_ENUM_CONSTANT(SHAPE_LINE); + BIND_ENUM_CONSTANT(SHAPE_RAY); BIND_ENUM_CONSTANT(SHAPE_SEGMENT); BIND_ENUM_CONSTANT(SHAPE_CIRCLE); BIND_ENUM_CONSTANT(SHAPE_RECTANGLE); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index cd6a20e6b8..18f4f460b6 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -65,17 +65,17 @@ public: virtual int get_contact_count() const = 0; - virtual Vector2 get_contact_local_pos(int p_contact_idx) const = 0; + virtual Vector2 get_contact_local_position(int p_contact_idx) const = 0; virtual Vector2 get_contact_local_normal(int p_contact_idx) const = 0; virtual int get_contact_local_shape(int p_contact_idx) const = 0; virtual RID get_contact_collider(int p_contact_idx) const = 0; - virtual Vector2 get_contact_collider_pos(int p_contact_idx) const = 0; + virtual Vector2 get_contact_collider_position(int p_contact_idx) const = 0; virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0; virtual Object *get_contact_collider_object(int p_contact_idx) const; virtual int get_contact_collider_shape(int p_contact_idx) const = 0; virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const = 0; - virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const = 0; + virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0; virtual real_t get_step() const = 0; virtual void integrate_forces(); @@ -283,7 +283,7 @@ public: virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0; virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const = 0; - // this function only works on fixed process, errors and returns null otherwise + // this function only works on physics process, errors and returns null otherwise virtual Physics2DDirectSpaceState *space_get_direct_state(RID p_space) = 0; virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) = 0; @@ -468,6 +468,9 @@ public: virtual void body_set_pickable(RID p_body, bool p_pickable) = 0; + // this function only works on physics process, errors and returns null otherwise + virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body) = 0; + struct MotionResult { Vector2 motion; diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index 5097e0a5d2..360808ce8c 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -75,7 +75,7 @@ void PhysicsDirectBodyState::_bind_methods() { ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState::get_total_angular_damp); ClassDB::bind_method(D_METHOD("get_center_of_mass"), &PhysicsDirectBodyState::get_center_of_mass); - ClassDB::bind_method(D_METHOD("get_principal_inetria_axes"), &PhysicsDirectBodyState::get_principal_inertia_axes); + ClassDB::bind_method(D_METHOD("get_principal_inertia_axes"), &PhysicsDirectBodyState::get_principal_inertia_axes); ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState::get_inverse_mass); ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &PhysicsDirectBodyState::get_inverse_inertia); @@ -89,8 +89,8 @@ void PhysicsDirectBodyState::_bind_methods() { ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState::set_transform); ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState::get_transform); - ClassDB::bind_method(D_METHOD("add_force", "force", "pos"), &PhysicsDirectBodyState::add_force); - ClassDB::bind_method(D_METHOD("apply_impulse", "pos", "j"), &PhysicsDirectBodyState::apply_impulse); + ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState::add_force); + ClassDB::bind_method(D_METHOD("apply_impulse", "position", "j"), &PhysicsDirectBodyState::apply_impulse); ClassDB::bind_method(D_METHOD("apply_torqe_impulse", "j"), &PhysicsDirectBodyState::apply_torque_impulse); ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState::set_sleep_state); @@ -98,15 +98,15 @@ void PhysicsDirectBodyState::_bind_methods() { ClassDB::bind_method(D_METHOD("get_contact_count"), &PhysicsDirectBodyState::get_contact_count); - ClassDB::bind_method(D_METHOD("get_contact_local_pos", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_pos); + ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_position); ClassDB::bind_method(D_METHOD("get_contact_local_normal", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_normal); ClassDB::bind_method(D_METHOD("get_contact_local_shape", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_shape); ClassDB::bind_method(D_METHOD("get_contact_collider", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider); - ClassDB::bind_method(D_METHOD("get_contact_collider_pos", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_pos); + ClassDB::bind_method(D_METHOD("get_contact_collider_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_position); ClassDB::bind_method(D_METHOD("get_contact_collider_id", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_id); ClassDB::bind_method(D_METHOD("get_contact_collider_object", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_object); ClassDB::bind_method(D_METHOD("get_contact_collider_shape", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_shape); - ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_pos", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_velocity_at_pos); + ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_velocity_at_position); ClassDB::bind_method(D_METHOD("get_step"), &PhysicsDirectBodyState::get_step); ClassDB::bind_method(D_METHOD("integrate_forces"), &PhysicsDirectBodyState::integrate_forces); ClassDB::bind_method(D_METHOD("get_space_state"), &PhysicsDirectBodyState::get_space_state); @@ -353,8 +353,8 @@ void PhysicsDirectSpaceState::_bind_methods() { BIND_ENUM_CONSTANT(TYPE_MASK_KINEMATIC_BODY); BIND_ENUM_CONSTANT(TYPE_MASK_RIGID_BODY); BIND_ENUM_CONSTANT(TYPE_MASK_CHARACTER_BODY); - BIND_ENUM_CONSTANT(TYPE_MASK_AREA); BIND_ENUM_CONSTANT(TYPE_MASK_COLLISION); + BIND_ENUM_CONSTANT(TYPE_MASK_AREA); } int PhysicsShapeQueryResult::get_result_count() const { @@ -482,7 +482,7 @@ void PhysicsServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer::body_set_state); ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer::body_get_state); - ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "pos", "impulse"), &PhysicsServer::body_apply_impulse); + ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &PhysicsServer::body_apply_impulse); ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer::body_apply_torque_impulse); ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer::body_set_axis_velocity); @@ -504,6 +504,8 @@ void PhysicsServer::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer::body_set_ray_pickable); ClassDB::bind_method(D_METHOD("body_is_ray_pickable", "body"), &PhysicsServer::body_is_ray_pickable); + ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer::body_get_direct_state); + /* JOINT API */ BIND_ENUM_CONSTANT(JOINT_PIN); @@ -677,8 +679,8 @@ void PhysicsServer::_bind_methods() { BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); BIND_ENUM_CONSTANT(BODY_PARAM_MASS); BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE); - BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP); BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP); BIND_ENUM_CONSTANT(BODY_PARAM_MAX); BIND_ENUM_CONSTANT(BODY_STATE_TRANSFORM); @@ -704,6 +706,20 @@ void PhysicsServer::_bind_methods() { BIND_ENUM_CONSTANT(INFO_ACTIVE_OBJECTS); BIND_ENUM_CONSTANT(INFO_COLLISION_PAIRS); BIND_ENUM_CONSTANT(INFO_ISLAND_COUNT); + + BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS); + BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_SEPARATION); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO); + BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); + + BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_DISABLED); + BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_X); + BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_Y); + BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_Z); } PhysicsServer::PhysicsServer() { diff --git a/servers/physics_server.h b/servers/physics_server.h index c6d312e0fe..8cec125646 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -71,16 +71,16 @@ public: virtual int get_contact_count() const = 0; - virtual Vector3 get_contact_local_pos(int p_contact_idx) const = 0; + virtual Vector3 get_contact_local_position(int p_contact_idx) const = 0; virtual Vector3 get_contact_local_normal(int p_contact_idx) const = 0; virtual int get_contact_local_shape(int p_contact_idx) const = 0; virtual RID get_contact_collider(int p_contact_idx) const = 0; - virtual Vector3 get_contact_collider_pos(int p_contact_idx) const = 0; + virtual Vector3 get_contact_collider_position(int p_contact_idx) const = 0; virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0; virtual Object *get_contact_collider_object(int p_contact_idx) const; virtual int get_contact_collider_shape(int p_contact_idx) const = 0; - virtual Vector3 get_contact_collider_velocity_at_pos(int p_contact_idx) const = 0; + virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0; virtual real_t get_step() const = 0; virtual void integrate_forces(); @@ -276,7 +276,7 @@ public: virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0; virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const = 0; - // this function only works on fixed process, errors and returns null otherwise + // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space) = 0; virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) = 0; @@ -464,6 +464,9 @@ public: virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0; virtual bool body_is_ray_pickable(RID p_body) const = 0; + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body) = 0; + struct MotionResult { Vector3 motion; diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 845a3443b7..7a9328e30f 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -32,7 +32,6 @@ #include "arvr/arvr_interface.h" #include "arvr/arvr_positional_tracker.h" -#include "arvr/arvr_script_interface.h" #include "arvr_server.h" #include "audio/audio_effect.h" #include "audio/audio_stream.h" @@ -74,10 +73,14 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag } ShaderTypes *shader_types = NULL; -ARVRServer *arvr_server = NULL; void register_server_types() { - arvr_server = memnew(ARVRServer); + + ClassDB::register_virtual_class<VisualServer>(); + ClassDB::register_class<AudioServer>(); + ClassDB::register_virtual_class<PhysicsServer>(); + ClassDB::register_virtual_class<Physics2DServer>(); + ClassDB::register_class<ARVRServer>(); ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("VisualServer", VisualServer::get_singleton())); ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("AudioServer", AudioServer::get_singleton())); @@ -89,12 +92,13 @@ void register_server_types() { ClassDB::register_virtual_class<ARVRInterface>(); ClassDB::register_class<ARVRPositionalTracker>(); - ClassDB::register_class<ARVRScriptInterface>(); ClassDB::register_virtual_class<AudioStream>(); ClassDB::register_virtual_class<AudioStreamPlayback>(); ClassDB::register_class<AudioStreamRandomPitch>(); ClassDB::register_virtual_class<AudioEffect>(); + ClassDB::register_class<AudioEffectEQ>(); + ClassDB::register_class<AudioEffectFilter>(); ClassDB::register_class<AudioBusLayout>(); { @@ -144,9 +148,5 @@ void register_server_types() { void unregister_server_types() { - //@TODO move this into iPhone/Android implementation? just have this here for testing... - // mobile_interface = NULL; - memdelete(shader_types); - memdelete(arvr_server); } diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h index 267e5c63b9..51e7f446ea 100644 --- a/servers/server_wrap_mt_common.h +++ b/servers/server_wrap_mt_common.h @@ -775,3 +775,12 @@ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \ } \ } + +#define FUNC12(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12) \ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10, m_arg11 p11, m_arg12 p12) { \ + if (Thread::get_caller_id() != server_thread) { \ + command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \ + } else { \ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \ + } \ + } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 9e4acac25d..cd4b465d79 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -53,7 +53,7 @@ public: virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg) = 0; virtual void environment_set_sky(RID p_env, RID p_sky) = 0; - virtual void environment_set_sky_scale(RID p_env, float p_scale) = 0; + virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; @@ -65,7 +65,7 @@ public: virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0; virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, bool p_blur) = 0; + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; @@ -213,6 +213,7 @@ public: virtual RID material_create() = 0; + virtual void material_set_render_priority(RID p_material, int priority) = 0; virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; virtual RID material_get_shader(RID p_shader_material) const = 0; @@ -334,6 +335,8 @@ public: virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) = 0; virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; virtual bool light_directional_get_blend_splits(RID p_light) const = 0; + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0; + virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0; virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0; virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index bc59acead5..8fee6050a0 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -79,7 +79,11 @@ String ShaderLanguage::get_operator_text(Operator p_op) { "|", "^", "~", - "++" + "++", + "--", + "?", + ":", + "++", "--", "()", "construct", @@ -263,6 +267,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_CF_BREAK, "break" }, { TK_CF_CONTINUE, "continue" }, { TK_CF_RETURN, "return" }, + { TK_CF_DISCARD, "discard" }, { TK_UNIFORM, "uniform" }, { TK_VARYING, "varying" }, { TK_ARG_IN, "in" }, @@ -1042,12 +1047,6 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type } } break; case OP_ASSIGN: { - - if (p_op->arguments[0]->type != Node::TYPE_MEMBER && p_op->arguments[0]->type != Node::TYPE_VARIABLE) { - valid = false; - break; - } - DataType na = p_op->arguments[0]->get_datatype(); DataType nb = p_op->arguments[1]->get_datatype(); valid = na == nb; @@ -1379,6 +1378,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, + { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, + { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, + { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, + { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } }, //builtins - common { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, @@ -1742,8 +1745,6 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, - { "textureScreen", TYPE_VEC4, { TYPE_VEC2, TYPE_VOID } }, - { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } }, { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } }, @@ -2585,6 +2586,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else if (tk.type == TK_BRACKET_OPEN) { Node *index = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!index) + return NULL; if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) { _set_error("Only integer datatypes are allowed for indexing"); @@ -2592,7 +2595,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } bool index_valid = false; - DataType member_type; + DataType member_type = TYPE_VOID; switch (expr->get_datatype()) { case TYPE_BVEC2: @@ -2959,7 +2962,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (expression[next_op + 1].is_op) { // this is not invalid and can really appear // but it becomes invalid anyway because no binary op - // can be followed by an unary op in a valid combination, + // can be followed by a unary op in a valid combination, // due to how precedence works, unaries will always disappear first _set_error("Parser bug.."); @@ -3002,8 +3005,6 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha if (op->op == OP_CONSTRUCT) { ERR_FAIL_COND_V(op->arguments[0]->type != Node::TYPE_VARIABLE, p_node); - VariableNode *vn = static_cast<VariableNode *>(op->arguments[0]); - //StringName name=vn->name; DataType base = get_scalar_type(op->get_datatype()); @@ -3122,6 +3123,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat tk = _get_token(); + VariableDeclarationNode *vardecl = alloc_node<VariableDeclarationNode>(); + vardecl->datatype = type; + vardecl->precision = precision; + + p_block->statements.push_back(vardecl); + while (true) { if (tk.type != TK_IDENTIFIER) { @@ -3139,8 +3146,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat var.type = type; var.precision = precision; var.line = tk_line; + p_block->variables[name] = var; + VariableDeclarationNode::Declaration decl; + + decl.name = name; + decl.initializer = NULL; + tk = _get_token(); if (tk.type == TK_OP_ASSIGN) { @@ -3149,22 +3162,17 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat if (!n) return ERR_PARSE_ERROR; - OperatorNode *assign = alloc_node<OperatorNode>(); - VariableNode *vnode = alloc_node<VariableNode>(); - vnode->name = name; - vnode->datatype_cache = type; - assign->arguments.push_back(vnode); - assign->arguments.push_back(n); - assign->op = OP_ASSIGN; - p_block->statements.push_back(assign); - tk = _get_token(); + decl.initializer = n; - if (!_validate_operator(assign)) { - _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(type) + "'"); + if (var.type != n->get_datatype()) { + _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'"); return ERR_PARSE_ERROR; } + tk = _get_token(); } + vardecl->declarations.push_back(decl); + if (tk.type == TK_COMMA) { tk = _get_token(); //another variable @@ -3227,7 +3235,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat //if () {} tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after if"); + _set_error("Expected '(' after while"); return ERR_PARSE_ERROR; } @@ -3249,7 +3257,63 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat cf->blocks.push_back(block); p_block->statements.push_back(cf); - Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue); + Error err = _parse_block(block, p_builtin_types, true, true, true); + if (err) + return err; + } else if (tk.type == TK_CF_FOR) { + //if () {} + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after for"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op = FLOW_OP_FOR; + + BlockNode *init_block = alloc_node<BlockNode>(); + init_block->parent_block = p_block; + init_block->single_statement = true; + cf->blocks.push_back(init_block); + if (_parse_block(init_block, p_builtin_types, true, false, false) != OK) { + return ERR_PARSE_ERROR; + } + + Node *n = _parse_and_reduce_expression(init_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + if (n->get_datatype() != TYPE_BOOL) { + _set_error("Middle expression is expected to be boolean."); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';' after middle expression"); + return ERR_PARSE_ERROR; + } + + cf->expressions.push_back(n); + + n = _parse_and_reduce_expression(init_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + cf->expressions.push_back(n); + + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' after third expression"); + return ERR_PARSE_ERROR; + } + + BlockNode *block = alloc_node<BlockNode>(); + block->parent_block = p_block; + cf->blocks.push_back(block); + p_block->statements.push_back(cf); + + Error err = _parse_block(block, p_builtin_types, true, true, true); if (err) return err; @@ -3326,6 +3390,42 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat } p_block->statements.push_back(flow); + } else if (tk.type == TK_CF_BREAK) { + + if (!p_can_break) { + //all is good + _set_error("Breaking is not allowed here"); + } + + ControlFlowNode *flow = alloc_node<ControlFlowNode>(); + flow->flow_op = FLOW_OP_BREAK; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + //all is good + _set_error("Expected ';' after break"); + } + + p_block->statements.push_back(flow); + } else if (tk.type == TK_CF_CONTINUE) { + + if (!p_can_break) { + //all is good + _set_error("Contiuning is not allowed here"); + } + + ControlFlowNode *flow = alloc_node<ControlFlowNode>(); + flow->flow_op = FLOW_OP_CONTINUE; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + //all is good + _set_error("Expected ';' after continue"); + } + + p_block->statements.push_back(flow); } else { @@ -3355,7 +3455,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct Token tk = _get_token(); if (tk.type != TK_SHADER_TYPE) { - _set_error("Expected 'shader_type' at the begining of shader."); + _set_error("Expected 'shader_type' at the beginning of shader."); return ERR_PARSE_ERROR; } @@ -3705,6 +3805,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct func_node->return_type = type; func_node->return_precision = precision; + if (p_functions.has(name)) { + func_node->can_discard = p_functions[name].can_discard; + } + func_node->body = alloc_node<BlockNode>(); func_node->body->parent_function = func_node; @@ -3878,6 +3982,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct shader = alloc_node<ShaderNode>(); Error err = _parse_shader(p_functions, p_render_modes, p_shader_types); + if (err != OK) + ERR_PRINT("Failed to parse shader"); switch (completion_type) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index f00b4c5a97..7a7f6dd71c 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -266,6 +266,7 @@ public: TYPE_FUNCTION, TYPE_BLOCK, TYPE_VARIABLE, + TYPE_VARIABLE_DECLARATION, TYPE_CONSTANT, TYPE_OPERATOR, TYPE_CONTROL_FLOW, @@ -315,6 +316,25 @@ public: } }; + struct VariableDeclarationNode : public Node { + + DataPrecision precision; + DataType datatype; + + struct Declaration { + + StringName name; + Node *initializer; + }; + + Vector<Declaration> declarations; + virtual DataType get_datatype() const { return datatype; } + + VariableDeclarationNode() { + type = TYPE_VARIABLE_DECLARATION; + } + }; + struct ConstantNode : public Node { DataType datatype; @@ -346,10 +366,12 @@ public: Map<StringName, Variable> variables; List<Node *> statements; + bool single_statement; BlockNode() { type = TYPE_BLOCK; parent_block = NULL; parent_function = NULL; + single_statement = false; } }; diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index d8d1b1c1b1..7489ca7e3e 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -50,12 +50,6 @@ ShaderTypes::ShaderTypes() { /*************** SPATIAL ***********************/ - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["SRC_VERTEX"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["SRC_NORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["SRC_BONES"] = ShaderLanguage::TYPE_IVEC4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["SRC_WEIGHTS"] = ShaderLanguage::TYPE_VEC4; - - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3; @@ -75,6 +69,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2; @@ -89,7 +84,6 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT; @@ -102,7 +96,9 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; @@ -114,10 +110,31 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].can_discard = true; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2; + + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3; + + shader_modes[VS::SHADER_SPATIAL].functions["light"].can_discard = true; + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix"); shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add"); shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub"); @@ -128,15 +145,16 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_never"); shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_alpha_prepass"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_test_disable"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_front"); shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_back"); shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_disabled"); shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("ontop"); shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_half_lambert"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_lambert_wrap"); shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_oren_nayar"); shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_burley"); shader_modes[VS::SHADER_SPATIAL].modes.insert("diffuse_toon"); @@ -154,21 +172,19 @@ ShaderTypes::ShaderTypes() { /************ CANVAS ITEM **************************/ - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SRC_VERTEX"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX_COLOR"] = ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["EXTRA_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PARTICLE_CUSTOM"] = ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SRC_COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; @@ -177,13 +193,13 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC2; diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 68ca586caf..69e2d1c162 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -90,17 +90,10 @@ void VisualServerRaster::request_frame_drawn_callback(Object *p_where, const Str fdc.param = p_userdata; frame_drawn_callbacks.push_back(fdc); - - print_line("added callback to draw"); } void VisualServerRaster::draw() { - /* - if (changes) - print_line("changes: "+itos(changes)); - */ - changes = 0; VSG::rasterizer->begin_frame(); @@ -109,9 +102,8 @@ void VisualServerRaster::draw() { VSG::viewport->draw_viewports(); VSG::scene->render_probes(); - //_draw_cursors_and_margins(); + _draw_margins(); VSG::rasterizer->end_frame(); - //draw_extra_frame=VS:rasterizer->needs_to_draw_next_frame(); while (frame_drawn_callbacks.front()) { @@ -128,8 +120,6 @@ void VisualServerRaster::draw() { frame_drawn_callbacks.pop_front(); } - - _draw_margins(); } void VisualServerRaster::sync() { } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 774b692a22..425381550e 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -281,7 +281,7 @@ class VisualServerRaster : public VisualServer { Set<Instance*> owned_instances; BakedLightSampler *sampler; int resolution; - Vector<Color> light_bufer; + Vector<Color> light_buffer; RID sampled_light; uint64_t last_pass; Transform xform; // viewspace normal to lightspace, might not use one. @@ -589,11 +589,29 @@ class VisualServerRaster : public VisualServer { #endif void _draw_margins(); + static void _changes_changed() {} public: +//if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed() +//#define DEBUG_CHANGES + +#ifdef DEBUG_CHANGES + _FORCE_INLINE_ static void redraw_request() { + changes++; + _changes_changed(); + } + +#define DISPLAY_CHANGED \ + changes++; \ + _changes_changed(); + +#else _FORCE_INLINE_ static void redraw_request() { changes++; } -#define DISPLAY_CHANGED changes++; +#define DISPLAY_CHANGED \ + changes++; +#endif +// print_line(String("CHANGED: ") + __FUNCTION__); #define BIND0R(m_r, m_name) \ m_r m_name() { return BINDBASE->m_name(); } @@ -634,6 +652,8 @@ public: void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } #define BIND11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \ void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); } +#define BIND12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); } //from now on, calls forwarded to this singleton #define BINDBASE VSG::storage @@ -690,6 +710,7 @@ public: BIND3(material_set_param, RID, const StringName &, const Variant &) BIND2RC(Variant, material_get_param, RID, const StringName &) + BIND2(material_set_render_priority, RID, int) BIND2(material_set_line_width, RID, float) BIND2(material_set_next_pass, RID, RID) @@ -794,6 +815,7 @@ public: BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) BIND2(light_directional_set_blend_splits, RID, bool) + BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) /* PROBE API */ @@ -948,13 +970,13 @@ public: BIND2(environment_set_background, RID, EnvironmentBG) BIND2(environment_set_sky, RID, RID) - BIND2(environment_set_sky_scale, RID, float) + BIND2(environment_set_sky_custom_fov, RID, float) BIND2(environment_set_bg_color, RID, const Color &) BIND2(environment_set_bg_energy, RID, float) BIND2(environment_set_canvas_max_layer, RID, int) BIND4(environment_set_ambient_light, RID, const Color &, float, float) BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool) - BIND10(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, bool) + BIND12(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float) BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality) BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index cd68c14de8..e49baf0763 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -101,7 +101,7 @@ void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance SWAP(A, B); //lesser always first } - if (B->base_type == VS::INSTANCE_LIGHT && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + if (B->base_type == VS::INSTANCE_LIGHT && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -119,7 +119,7 @@ void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance geom->lighting_dirty = true; return E; //this element should make freeing faster - } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -133,7 +133,7 @@ void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance geom->reflection_dirty = true; return E; //this element should make freeing faster - } else if (B->base_type == VS::INSTANCE_GI_PROBE && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -151,8 +151,6 @@ void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance } else if (B->base_type == VS::INSTANCE_GI_PROBE && A->base_type == VS::INSTANCE_LIGHT) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); - InstanceLightData *light = static_cast<InstanceLightData *>(A->base_data); - return gi_probe->lights.insert(A); } @@ -169,7 +167,7 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance SWAP(A, B); //lesser always first } - if (B->base_type == VS::INSTANCE_LIGHT && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + if (B->base_type == VS::INSTANCE_LIGHT && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -184,7 +182,7 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance } geom->lighting_dirty = true; - } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -196,7 +194,7 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance geom->reflection_dirty = true; - } else if (B->base_type == VS::INSTANCE_GI_PROBE && (1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); @@ -211,8 +209,6 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance } else if (B->base_type == VS::INSTANCE_GI_PROBE && A->base_type == VS::INSTANCE_LIGHT) { InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); - InstanceLightData *light = static_cast<InstanceLightData *>(A->base_data); - Set<Instance *>::Element *E = reinterpret_cast<Set<Instance *>::Element *>(udata); gi_probe->lights.erase(E); @@ -886,12 +882,53 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons float max_distance = p_cam_projection.get_z_far(); float shadow_max = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE); - if (shadow_max > 0) { + if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera max_distance = MIN(shadow_max, max_distance); } max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001); + float min_distance = MIN(p_cam_projection.get_z_near(), max_distance); + + VS::LightDirectionalShadowDepthRangeMode depth_range_mode = VSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base); + + if (depth_range_mode == VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) { + //optimize min/max + Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform); + int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); + Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2)); + //check distance max and min + + bool found_items = false; + float z_max = -1e20; + float z_min = 1e20; + + for (int i = 0; i < cull_count; i++) { + + Instance *instance = instance_shadow_cull_result[i]; + if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { + continue; + } + + float max, min; + instance->transformed_aabb.project_range_in_plane(base, min, max); + + if (max > z_max) { + z_max = max; + } + + if (min < z_min) { + z_min = min; + } - float range = max_distance - p_cam_projection.get_z_near(); + found_items = true; + } + + if (found_items) { + min_distance = MAX(min_distance, z_min); + max_distance = MIN(max_distance, z_max); + } + } + + float range = max_distance - min_distance; int splits = 0; switch (VSG::storage->light_directional_get_shadow_mode(p_instance->base)) { @@ -902,9 +939,9 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons float distances[5]; - distances[0] = p_cam_projection.get_z_near(); + distances[0] = min_distance; for (int i = 0; i < splits; i++) { - distances[i + 1] = p_cam_projection.get_z_near() + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range; + distances[i + 1] = min_distance + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range; }; distances[splits] = max_distance; @@ -948,13 +985,13 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized(); //z_vec points agsint the camera, like in default opengl - float x_min, x_max; - float y_min, y_max; - float z_min, z_max; + float x_min = 0.f, x_max = 0.f; + float y_min = 0.f, y_max = 0.f; + float z_min = 0.f, z_max = 0.f; - float x_min_cam, x_max_cam; - float y_min_cam, y_max_cam; - float z_min_cam, z_max_cam; + float x_min_cam = 0.f, x_max_cam = 0.f; + float y_min_cam = 0.f, y_max_cam = 0.f; + float z_min_cam = 0.f, z_max_cam = 0.f; float bias_scale = 1.0; @@ -984,8 +1021,6 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons { //camera viewport stuff - //this trick here is what stabilizes the shadow (make potential jaggies to not move) - //at the cost of some wasted resolution. Still the quality increase is very well worth it Vector3 center; @@ -1006,7 +1041,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons radius = d; } - radius *= texture_size / (texture_size - 2.0); //add a texel by each side, so stepified texture will always fit + radius *= texture_size / (texture_size - 2.0); //add a texel by each side if (i == 0) { first_radius = radius; @@ -1021,12 +1056,17 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons z_max_cam = z_vec.dot(center) + radius; z_min_cam = z_vec.dot(center) - radius; - float unit = radius * 2.0 / texture_size; + if (depth_range_mode == VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) { + //this trick here is what stabilizes the shadow (make potential jaggies to not move) + //at the cost of some wasted resolution. Still the quality increase is very well worth it + + float unit = radius * 2.0 / texture_size; - x_max_cam = Math::stepify(x_max_cam, unit); - x_min_cam = Math::stepify(x_min_cam, unit); - y_max_cam = Math::stepify(y_max_cam, unit); - y_min_cam = Math::stepify(y_min_cam, unit); + x_max_cam = Math::stepify(x_max_cam, unit); + x_min_cam = Math::stepify(x_min_cam, unit); + y_max_cam = Math::stepify(y_max_cam, unit); + y_min_cam = Math::stepify(y_min_cam, unit); + } } //now that we now all ranges, we can proceed to make the light frustum planes, for culling octree @@ -1069,6 +1109,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons } { + CameraMatrix ortho_camera; real_t half_x = (x_max_cam - x_min_cam) * 0.5; real_t half_y = (y_max_cam - y_min_cam) * 0.5; @@ -1375,7 +1416,7 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform, const Cam gi_probe_update_list.add(&gi_probe->update_element); } - } else if ((1 << ins->base_type) & VS::INSTANCE_GEOMETRY_MASK && ins->visible && ins->cast_shadows != VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + } else if (((1 << ins->base_type) & VS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { keep = true; @@ -1434,7 +1475,7 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform, const Cam } ins->depth = near_plane.distance_to(ins->transform.origin); - ins->depth_layer = CLAMP(int(ins->depth * 8 / z_far), 0, 7); + ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15); } if (!keep) { @@ -1503,7 +1544,7 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform, const Cam InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data); - float coverage; + float coverage = 0.f; { //compute coverage @@ -1687,7 +1728,7 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int void VisualServerScene::_gi_probe_fill_local_data(int p_idx, int p_level, int p_x, int p_y, int p_z, const GIProbeDataCell *p_cell, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, Vector<uint32_t> *prev_cell) { - if (p_level == p_header->cell_subdiv - 1) { + if ((uint32_t)p_level == p_header->cell_subdiv - 1) { Vector3 emission; emission.x = (p_cell[p_idx].emission >> 24) / 255.0; @@ -1798,9 +1839,9 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) { } for (int i = 0; i < (int)header->cell_subdiv; i++) { - uint32_t x = header->width >> i; - uint32_t y = header->height >> i; - uint32_t z = header->depth >> i; + int x = header->width >> i; + int y = header->height >> i; + int z = header->depth >> i; //create and clear mipmap PoolVector<uint8_t> mipmap; @@ -1896,7 +1937,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) { uint8_t alpha_block[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; - for (int j = 0; j < k.source_count; j++) { + for (uint32_t j = 0; j < k.source_count; j++) { int alpha = (cells[k.sources[j]].level_alpha >> 8) & 0xFF; if (alpha < min_alpha) @@ -2085,7 +2126,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co int success_count = 0; - uint64_t us = OS::get_singleton()->get_ticks_usec(); + // uint64_t us = OS::get_singleton()->get_ticks_usec(); for (int i = 0; i < p_leaf_count; i++) { @@ -2138,14 +2179,15 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co success_count++; } } - //print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); - //print_line("valid cells: " + itos(success_count)); + + // print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); + // print_line("valid cells: " + itos(success_count)); } break; case VS::LIGHT_OMNI: case VS::LIGHT_SPOT: { - uint64_t us = OS::get_singleton()->get_ticks_usec(); + // uint64_t us = OS::get_singleton()->get_ticks_usec(); Vector3 light_pos = light_cache.transform.origin; Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized(); @@ -2244,8 +2286,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, co light->energy[2] += int32_t(light_b * att * ((cell->albedo) & 0xFF) / 255.0); } } - //print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); - + // print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); } break; } } @@ -2307,7 +2348,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { RID rid = E->key(); const InstanceGIProbeData::LightCache &lc = E->get(); - if (!probe_data->dynamic.light_cache_changes.has(rid) || !(probe_data->dynamic.light_cache_changes[rid] == lc)) { + if ((!probe_data->dynamic.light_cache_changes.has(rid) || !(probe_data->dynamic.light_cache_changes[rid] == lc)) && lc.visible) { //erase light data _bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, -1); @@ -2320,7 +2361,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { RID rid = E->key(); const InstanceGIProbeData::LightCache &lc = E->get(); - if (!probe_data->dynamic.light_cache.has(rid) || !(probe_data->dynamic.light_cache[rid] == lc)) { + if ((!probe_data->dynamic.light_cache.has(rid) || !(probe_data->dynamic.light_cache[rid] == lc)) && lc.visible) { //add light data _bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, 1); @@ -2389,7 +2430,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { Vector3 colors[16]; - for (int j = 0; j < b.source_count; j++) { + for (uint32_t j = 0; j < b.source_count; j++) { colors[j].x = (local_data[b.sources[j]].energy[0] / float(probe_data->dynamic.bake_dynamic_range)) / 1024.0; colors[j].y = (local_data[b.sources[j]].energy[1] / float(probe_data->dynamic.bake_dynamic_range)) / 1024.0; @@ -2403,8 +2444,8 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { if (b.source_count == 16) { //all cells are used so, find minmax between them int further_apart[2] = { 0, 0 }; - for (int j = 0; j < b.source_count; j++) { - for (int k = j + 1; k < b.source_count; k++) { + for (uint32_t j = 0; j < b.source_count; j++) { + for (uint32_t k = j + 1; k < b.source_count; k++) { float d = colors[j].distance_squared_to(colors[k]); if (d > distance) { distance = d; @@ -2424,12 +2465,12 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { //average all colors first Vector3 average; - for (int j = 0; j < b.source_count; j++) { + for (uint32_t j = 0; j < b.source_count; j++) { average += colors[j]; } average.normalize(); //find max distance in normal from average - for (int j = 0; j < b.source_count; j++) { + for (uint32_t j = 0; j < b.source_count; j++) { float d = average.dot(colors[j]); distance = MAX(d, distance); } @@ -2459,7 +2500,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { Vector3 dir = (to - from).normalized(); - for (int j = 0; j < b.source_count; j++) { + for (uint32_t j = 0; j < b.source_count; j++) { float d = (colors[j] - from).dot(dir) / distance; indices[j] = int(d * 3 + 0.5); @@ -2469,7 +2510,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { indices[j] = index_swap[CLAMP(indices[j], 0, 3)]; } } else { - for (int j = 0; j < b.source_count; j++) { + for (uint32_t j = 0; j < b.source_count; j++) { indices[j] = 0; } } @@ -2478,7 +2519,7 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { uint32_t index_block[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - for (int j = 0; j < b.source_count; j++) { + for (uint32_t j = 0; j < b.source_count; j++) { int x = local_data[b.sources[j]].pos[0] % 4; int y = local_data[b.sources[j]].pos[1] % 4; @@ -2527,6 +2568,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { lc.spot_angle = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ANGLE); lc.spot_attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ATTENUATION); lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; + lc.visible = E->get()->visible; if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self] == lc)) { all_equal = false; @@ -2546,6 +2588,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { lc.spot_angle = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ANGLE); lc.spot_attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ATTENUATION); lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; + lc.visible = E->get()->visible; if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self] == lc)) { all_equal = false; @@ -2657,18 +2700,17 @@ void VisualServerScene::render_probes() { } break; case GI_UPDATE_STAGE_UPLOADING: { - uint64_t us = OS::get_singleton()->get_ticks_usec(); + // uint64_t us = OS::get_singleton()->get_ticks_usec(); for (int i = 0; i < (int)probe->dynamic.mipmaps_3d.size(); i++) { - int mmsize = probe->dynamic.mipmaps_3d[i].size(); PoolVector<uint8_t>::Read r = probe->dynamic.mipmaps_3d[i].read(); VSG::storage->gi_probe_dynamic_data_update(probe->dynamic.probe_data, 0, probe->dynamic.grid_size[2] >> i, i, r.ptr()); } probe->dynamic.updating_stage = GI_UPDATE_STAGE_CHECK; - //print_line("UPLOAD TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + // print_line("UPLOAD TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); } break; } } diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index ac771030cf..d30a2108a5 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -359,6 +359,7 @@ public: float attenuation; float spot_angle; float spot_attenuation; + bool visible; bool operator==(const LightCache &p_cache) { @@ -369,7 +370,8 @@ public: radius == p_cache.radius && attenuation == p_cache.attenuation && spot_angle == p_cache.spot_angle && - spot_attenuation == p_cache.spot_attenuation); + spot_attenuation == p_cache.spot_attenuation && + visible == p_cache.visible); } LightCache() { @@ -380,6 +382,7 @@ public: attenuation = 1.0; spot_angle = 1.0; spot_attenuation = 1.0; + visible = true; } }; diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 0dca09a5bf..92c431e393 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -54,7 +54,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E bool can_draw_3d = !p_viewport->disable_3d && !p_viewport->disable_3d_by_usage && VSG::scene->camera_owner.owns(p_viewport->camera); if (p_viewport->clear_mode != VS::VIEWPORT_CLEAR_NEVER) { - VSG::rasterizer->clear_render_target(clear_color); + VSG::rasterizer->clear_render_target(p_viewport->transparent_bg ? Color(0, 0, 0, 0) : clear_color); if (p_viewport->clear_mode == VS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) { p_viewport->clear_mode = VS::VIEWPORT_CLEAR_NEVER; } @@ -504,6 +504,7 @@ void VisualServerViewport::viewport_set_transparent_background(RID p_viewport, b ERR_FAIL_COND(!viewport); VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_TRANSPARENT, p_enabled); + viewport->transparent_bg = true; } void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) { diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h index 8a294a9129..8db6eda133 100644 --- a/servers/visual/visual_server_viewport.h +++ b/servers/visual/visual_server_viewport.h @@ -72,6 +72,8 @@ public: VS::ViewportClearMode clear_mode; + bool transparent_bg; + struct CanvasKey { int layer; @@ -101,6 +103,7 @@ public: Viewport() { update_mode = VS::VIEWPORT_UPDATE_WHEN_VISIBLE; clear_mode = VS::VIEWPORT_CLEAR_ALWAYS; + transparent_bg = false; disable_environment = false; viewport_to_screen = 0; shadow_atlas_size = 0; diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 7143178b04..67d503dfca 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -128,6 +128,7 @@ public: FUNC3(material_set_param, RID, const StringName &, const Variant &) FUNC2RC(Variant, material_get_param, RID, const StringName &) + FUNC2(material_set_render_priority, RID, int) FUNC2(material_set_line_width, RID, float) FUNC2(material_set_next_pass, RID, RID) @@ -232,6 +233,7 @@ public: FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) FUNC2(light_directional_set_blend_splits, RID, bool) + FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) /* PROBE API */ @@ -379,13 +381,13 @@ public: FUNC2(environment_set_background, RID, EnvironmentBG) FUNC2(environment_set_sky, RID, RID) - FUNC2(environment_set_sky_scale, RID, float) + FUNC2(environment_set_sky_custom_fov, RID, float) FUNC2(environment_set_bg_color, RID, const Color &) FUNC2(environment_set_bg_energy, RID, float) FUNC2(environment_set_canvas_max_layer, RID, int) FUNC4(environment_set_ambient_light, RID, const Color &, float, float) FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool) - FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, bool) + FUNC12(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, EnvironmentSSAOQuality, EnvironmentSSAOBlur, float) FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality) FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 777feffb06..2234ddda0d 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -62,6 +62,31 @@ RID VisualServer::texture_create_from_image(const Ref<Image> &p_image, uint32_t return texture; } +Array VisualServer::_texture_debug_usage_bind() { + + List<TextureInfo> list; + texture_debug_usage(&list); + Array arr; + for (const List<TextureInfo>::Element *E = list.front(); E; E = E->next()) { + + Dictionary dict; + dict["texture"] = E->get().texture; + dict["size"] = E->get().size; + dict["format"] = E->get().format; + dict["bytes"] = E->get().bytes; + dict["path"] = E->get().path; + arr.push_back(dict); + } + return arr; +} + +Array VisualServer::_shader_get_param_list_bind(RID p_shader) const { + + List<PropertyInfo> l; + shader_get_param_list(p_shader, &l); + return convert_property_list(&l); +} + RID VisualServer::get_test_texture() { if (test_texture.is_valid()) { @@ -1420,19 +1445,417 @@ Array VisualServer::mesh_surface_get_arrays(RID p_mesh, int p_surface) const { return _get_array_from_surface(format, vertex_data, vertex_len, index_data, index_len); } +Array VisualServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const { + + Vector<PoolVector<uint8_t> > blend_shape_data = mesh_surface_get_blend_shapes(p_mesh, p_surface); + if (blend_shape_data.size() > 0) { + int vertex_len = mesh_surface_get_array_len(p_mesh, p_surface); + + PoolVector<uint8_t> index_data = mesh_surface_get_index_array(p_mesh, p_surface); + int index_len = mesh_surface_get_array_index_len(p_mesh, p_surface); + + uint32_t format = mesh_surface_get_format(p_mesh, p_surface); + + Array blend_shape_array; + blend_shape_array.resize(blend_shape_data.size()); + for (int i = 0; i < blend_shape_data.size(); i++) { + blend_shape_array.set(i, _get_array_from_surface(format, blend_shape_data[i], vertex_len, index_data, index_len)); + } + + return blend_shape_array; + } else { + return Array(); + } +} + +Array VisualServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const { + + Vector<Rect3> vec = VS::get_singleton()->mesh_surface_get_skeleton_aabb(p_mesh, p_surface); + Array arr; + for (int i = 0; i < vec.size(); i++) { + arr[i] = vec[i]; + } + return arr; +} + void VisualServer::_bind_methods() { + ClassDB::bind_method(D_METHOD("force_sync"), &VisualServer::sync); + ClassDB::bind_method(D_METHOD("force_draw"), &VisualServer::draw); + ClassDB::bind_method(D_METHOD("texture_create"), &VisualServer::texture_create); ClassDB::bind_method(D_METHOD("texture_create_from_image", "image", "flags"), &VisualServer::texture_create_from_image, DEFVAL(TEXTURE_FLAGS_DEFAULT)); - //ClassDB::bind_method(D_METHOD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) ); - //ClassDB::bind_method(D_METHOD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) ); - //ClassDB::bind_method(D_METHOD("texture_get_rect"),&VisualServer::texture_get_rect ); + ClassDB::bind_method(D_METHOD("texture_allocate", "texture", "width", "height", "format", "flags"), &VisualServer::texture_allocate, DEFVAL(TEXTURE_FLAGS_DEFAULT)); + ClassDB::bind_method(D_METHOD("texture_set_data", "texture", "image", "cube_side"), &VisualServer::texture_set_data, DEFVAL(CUBEMAP_LEFT)); + ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "cube_side"), &VisualServer::texture_get_data, DEFVAL(CUBEMAP_LEFT)); ClassDB::bind_method(D_METHOD("texture_set_flags", "texture", "flags"), &VisualServer::texture_set_flags); ClassDB::bind_method(D_METHOD("texture_get_flags", "texture"), &VisualServer::texture_get_flags); + ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &VisualServer::texture_get_format); + ClassDB::bind_method(D_METHOD("texture_get_texid", "texture"), &VisualServer::texture_get_texid); ClassDB::bind_method(D_METHOD("texture_get_width", "texture"), &VisualServer::texture_get_width); ClassDB::bind_method(D_METHOD("texture_get_height", "texture"), &VisualServer::texture_get_height); - + ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height"), &VisualServer::texture_set_size_override); + ClassDB::bind_method(D_METHOD("texture_set_path", "texture", "path"), &VisualServer::texture_set_path); + ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &VisualServer::texture_get_path); ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data", "shrink"), &VisualServer::texture_set_shrink_all_x2_on_set_data); + + ClassDB::bind_method(D_METHOD("texture_debug_usage"), &VisualServer::_texture_debug_usage_bind); + ClassDB::bind_method(D_METHOD("textures_keep_original", "enable"), &VisualServer::textures_keep_original); + + ClassDB::bind_method(D_METHOD("sky_create"), &VisualServer::sky_create); + ClassDB::bind_method(D_METHOD("sky_set_texture", "sky", "cube_map", "radiance_size"), &VisualServer::sky_set_texture); + + ClassDB::bind_method(D_METHOD("shader_create"), &VisualServer::shader_create); + ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &VisualServer::shader_set_code); + ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &VisualServer::shader_get_code); + ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &VisualServer::_shader_get_param_list_bind); + ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "name", "texture"), &VisualServer::shader_set_default_texture_param); + ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "name"), &VisualServer::shader_get_default_texture_param); + + ClassDB::bind_method(D_METHOD("material_create"), &VisualServer::material_create); + ClassDB::bind_method(D_METHOD("material_set_shader", "shader_material", "shader"), &VisualServer::material_set_shader); + ClassDB::bind_method(D_METHOD("material_get_shader", "shader_material"), &VisualServer::material_get_shader); + ClassDB::bind_method(D_METHOD("material_set_param", "material", "parameter", "value"), &VisualServer::material_set_param); + ClassDB::bind_method(D_METHOD("material_get_param", "material", "parameter"), &VisualServer::material_get_param); + ClassDB::bind_method(D_METHOD("material_set_render_priority", "material", "priority"), &VisualServer::material_set_render_priority); + ClassDB::bind_method(D_METHOD("material_set_line_width", "material", "width"), &VisualServer::material_set_line_width); + ClassDB::bind_method(D_METHOD("material_set_next_pass", "material", "next_material"), &VisualServer::material_set_next_pass); + + ClassDB::bind_method(D_METHOD("mesh_create"), &VisualServer::mesh_create); + ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primtive", "arrays", "blend_shapes", "compress_format"), &VisualServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); + ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_count", "mesh", "amount"), &VisualServer::mesh_set_blend_shape_count); + ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &VisualServer::mesh_get_blend_shape_count); + ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &VisualServer::mesh_set_blend_shape_mode); + ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &VisualServer::mesh_get_blend_shape_mode); + ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &VisualServer::mesh_surface_set_material); + ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &VisualServer::mesh_surface_get_material); + ClassDB::bind_method(D_METHOD("mesh_surface_get_array_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_len); + ClassDB::bind_method(D_METHOD("mesh_surface_get_array_index_len", "mesh", "surface"), &VisualServer::mesh_surface_get_array_index_len); + ClassDB::bind_method(D_METHOD("mesh_surface_get_array", "mesh", "surface"), &VisualServer::mesh_surface_get_array); + ClassDB::bind_method(D_METHOD("mesh_surface_get_index_array", "mesh", "surface"), &VisualServer::mesh_surface_get_index_array); + ClassDB::bind_method(D_METHOD("mesh_surface_get_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_arrays); + ClassDB::bind_method(D_METHOD("mesh_surface_get_blend_shape_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_blend_shape_arrays); + ClassDB::bind_method(D_METHOD("mesh_surface_get_format", "mesh", "surface"), &VisualServer::mesh_surface_get_format); + ClassDB::bind_method(D_METHOD("mesh_surface_get_primitive_type", "mesh", "surface"), &VisualServer::mesh_surface_get_primitive_type); + ClassDB::bind_method(D_METHOD("mesh_surface_get_aabb", "mesh", "surface"), &VisualServer::mesh_surface_get_aabb); + ClassDB::bind_method(D_METHOD("mesh_surface_get_skeleton_aabb", "mesh", "surface"), &VisualServer::_mesh_surface_get_skeleton_aabb_bind); + ClassDB::bind_method(D_METHOD("mesh_remove_surface", "mesh", "index"), &VisualServer::mesh_remove_surface); + ClassDB::bind_method(D_METHOD("mesh_get_surface_count", "mesh"), &VisualServer::mesh_get_surface_count); + ClassDB::bind_method(D_METHOD("mesh_set_custom_aabb", "mesh", "aabb"), &VisualServer::mesh_set_custom_aabb); + ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb); + ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear); + + // TODO: multimesh_*, immediate_*, skeleton_*, light_*, reflection_probe_*, gi_probe_*, particles_*, camera_* + + ClassDB::bind_method(D_METHOD("viewport_create"), &VisualServer::viewport_create); + ClassDB::bind_method(D_METHOD("viewport_set_use_arvr", "viewport", "use_arvr"), &VisualServer::viewport_set_use_arvr); + ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &VisualServer::viewport_set_size); + ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &VisualServer::viewport_set_active); + ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &VisualServer::viewport_set_parent_viewport); + ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("viewport_detach", "viewport"), &VisualServer::viewport_detach); + ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode); + ClassDB::bind_method(D_METHOD("viewport_set_vflip", "viewport", "enabled"), &VisualServer::viewport_set_vflip); + ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &VisualServer::viewport_set_clear_mode); + ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &VisualServer::viewport_get_texture); + ClassDB::bind_method(D_METHOD("viewport_set_hide_scenario", "viewport", "hidden"), &VisualServer::viewport_set_hide_scenario); + ClassDB::bind_method(D_METHOD("viewport_set_hide_canvas", "viewport", "hidden"), &VisualServer::viewport_set_hide_canvas); + ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &VisualServer::viewport_set_disable_environment); + ClassDB::bind_method(D_METHOD("viewport_set_disable_3d", "viewport", "disabled"), &VisualServer::viewport_set_disable_3d); + ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &VisualServer::viewport_attach_camera); + ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &VisualServer::viewport_set_scenario); + ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &VisualServer::viewport_attach_canvas); + ClassDB::bind_method(D_METHOD("viewport_remove_canvas", "viewport", "canvas"), &VisualServer::viewport_remove_canvas); + ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform); + ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background); + ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform); + ClassDB::bind_method(D_METHOD("viewport_set_canvas_layer", "viewport", "canvas", "layer"), &VisualServer::viewport_set_canvas_layer); + ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size); + ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision); + ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa); + ClassDB::bind_method(D_METHOD("viewport_set_hdr", "viewport", "enabled"), &VisualServer::viewport_set_hdr); + ClassDB::bind_method(D_METHOD("viewport_set_usage", "viewport", "usage"), &VisualServer::viewport_set_usage); + ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &VisualServer::viewport_get_render_info); + ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &VisualServer::viewport_set_debug_draw); + + // TODO: environment_*, scenario_*, instance_* + + ClassDB::bind_method(D_METHOD("canvas_create"), &VisualServer::canvas_create); + ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &VisualServer::canvas_set_item_mirroring); + ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &VisualServer::canvas_set_modulate); + + ClassDB::bind_method(D_METHOD("canvas_item_create"), &VisualServer::canvas_item_create); + ClassDB::bind_method(D_METHOD("canvas_item_set_parent", "item", "parent"), &VisualServer::canvas_item_set_parent); + ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &VisualServer::canvas_item_set_visible); + ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &VisualServer::canvas_item_set_light_mask); + ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &VisualServer::canvas_item_set_transform); + ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &VisualServer::canvas_item_set_clip); + ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &VisualServer::canvas_item_set_distance_field_mode); + ClassDB::bind_method(D_METHOD("canvas_item_set_custom_rect", "item", "use_custom_rect", "rect"), &VisualServer::canvas_item_set_custom_rect, DEFVAL(Rect2())); + ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &VisualServer::canvas_item_set_modulate); + ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &VisualServer::canvas_item_set_self_modulate); + ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &VisualServer::canvas_item_set_draw_behind_parent); + ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &VisualServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &VisualServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &VisualServer::canvas_item_add_rect); + ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &VisualServer::canvas_item_add_circle); + ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose", "normal_map"), &VisualServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID()), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate", "normal_map"), &VisualServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &VisualServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &VisualServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "texture", "count", "normal_map"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "skeleton"), &VisualServer::canvas_item_add_mesh, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "skeleton"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map", "h_frames", "v_frames"), &VisualServer::canvas_item_add_particles); + ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &VisualServer::canvas_item_add_set_transform); + ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &VisualServer::canvas_item_add_clip_ignore); + ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &VisualServer::canvas_item_set_sort_children_by_y); + ClassDB::bind_method(D_METHOD("canvas_item_set_z", "item", "z"), &VisualServer::canvas_item_set_z); + ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &VisualServer::canvas_item_set_z_as_relative_to_parent); + ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &VisualServer::canvas_item_set_copy_to_backbuffer); + ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &VisualServer::canvas_item_clear); + ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &VisualServer::canvas_item_set_draw_index); + ClassDB::bind_method(D_METHOD("canvas_item_set_material", "item", "material"), &VisualServer::canvas_item_set_material); + ClassDB::bind_method(D_METHOD("canvas_item_set_use_parent_material", "item", "enabled"), &VisualServer::canvas_item_set_use_parent_material); + ClassDB::bind_method(D_METHOD("canvas_light_create"), &VisualServer::canvas_light_create); + ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &VisualServer::canvas_light_attach_to_canvas); + ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &VisualServer::canvas_light_set_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_set_scale", "light", "scale"), &VisualServer::canvas_light_set_scale); + ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &VisualServer::canvas_light_set_transform); + ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &VisualServer::canvas_light_set_texture); + ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &VisualServer::canvas_light_set_texture_offset); + ClassDB::bind_method(D_METHOD("canvas_light_set_color", "light", "color"), &VisualServer::canvas_light_set_color); + ClassDB::bind_method(D_METHOD("canvas_light_set_height", "light", "height"), &VisualServer::canvas_light_set_height); + ClassDB::bind_method(D_METHOD("canvas_light_set_energy", "light", "energy"), &VisualServer::canvas_light_set_energy); + ClassDB::bind_method(D_METHOD("canvas_light_set_z_range", "light", "min_z", "max_z"), &VisualServer::canvas_light_set_z_range); + ClassDB::bind_method(D_METHOD("canvas_light_set_layer_range", "light", "min_layer", "max_layer"), &VisualServer::canvas_light_set_layer_range); + ClassDB::bind_method(D_METHOD("canvas_light_set_item_cull_mask", "light", "mask"), &VisualServer::canvas_light_set_item_cull_mask); + ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &VisualServer::canvas_light_set_item_shadow_cull_mask); + ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &VisualServer::canvas_light_set_mode); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &VisualServer::canvas_light_set_shadow_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_buffer_size", "light", "size"), &VisualServer::canvas_light_set_shadow_buffer_size); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_gradient_length", "light", "length"), &VisualServer::canvas_light_set_shadow_gradient_length); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &VisualServer::canvas_light_set_shadow_filter); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &VisualServer::canvas_light_set_shadow_color); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &VisualServer::canvas_light_set_shadow_smooth); + + ClassDB::bind_method(D_METHOD("canvas_light_occluder_create"), &VisualServer::canvas_light_occluder_create); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_attach_to_canvas", "occluder", "canvas"), &VisualServer::canvas_light_occluder_attach_to_canvas); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_enabled", "occluder", "enabled"), &VisualServer::canvas_light_occluder_set_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_polygon", "occluder", "polygon"), &VisualServer::canvas_light_occluder_set_polygon); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &VisualServer::canvas_light_occluder_set_transform); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &VisualServer::canvas_light_occluder_set_light_mask); + + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &VisualServer::canvas_occluder_polygon_create); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &VisualServer::canvas_occluder_polygon_set_shape); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &VisualServer::canvas_occluder_polygon_set_shape_as_lines); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &VisualServer::canvas_occluder_polygon_set_cull_mode); + + ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_margins); + ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_images); + + ClassDB::bind_method(D_METHOD("free", "rid"), &VisualServer::free); + + ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &VisualServer::request_frame_drawn_callback); + ClassDB::bind_method(D_METHOD("draw"), &VisualServer::draw); + ClassDB::bind_method(D_METHOD("sync"), &VisualServer::sync); + ClassDB::bind_method(D_METHOD("has_changed"), &VisualServer::has_changed); + ClassDB::bind_method(D_METHOD("init"), &VisualServer::init); + ClassDB::bind_method(D_METHOD("finish"), &VisualServer::finish); + ClassDB::bind_method(D_METHOD("get_render_info", "info"), &VisualServer::get_render_info); + + ClassDB::bind_method(D_METHOD("get_test_cube"), &VisualServer::get_test_cube); + ClassDB::bind_method(D_METHOD("get_test_texture"), &VisualServer::get_test_texture); + ClassDB::bind_method(D_METHOD("get_white_texture"), &VisualServer::get_white_texture); + + ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &VisualServer::make_sphere_mesh); + + ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale"), &VisualServer::set_boot_image); + ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &VisualServer::set_default_clear_color); + + ClassDB::bind_method(D_METHOD("has_feature", "feature"), &VisualServer::has_feature); + ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &VisualServer::has_os_feature); + ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &VisualServer::set_debug_generate_wireframes); + + BIND_CONSTANT(NO_INDEX_ARRAY); + BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); + BIND_CONSTANT(CANVAS_ITEM_Z_MIN); + BIND_CONSTANT(CANVAS_ITEM_Z_MAX); + BIND_CONSTANT(MAX_GLOW_LEVELS); + BIND_CONSTANT(MAX_CURSORS); + BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MIN); + BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MAX); + + BIND_ENUM_CONSTANT(CUBEMAP_LEFT); + BIND_ENUM_CONSTANT(CUBEMAP_RIGHT); + BIND_ENUM_CONSTANT(CUBEMAP_BOTTOM); + BIND_ENUM_CONSTANT(CUBEMAP_TOP); + BIND_ENUM_CONSTANT(CUBEMAP_FRONT); + BIND_ENUM_CONSTANT(CUBEMAP_BACK); + + BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIPMAPS); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_REPEAT); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_FILTER); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_ANISOTROPIC_FILTER); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_CONVERT_TO_LINEAR); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIRRORED_REPEAT); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_CUBEMAP); + BIND_ENUM_CONSTANT(TEXTURE_FLAG_USED_FOR_STREAMING); + BIND_ENUM_CONSTANT(TEXTURE_FLAGS_DEFAULT); + + BIND_ENUM_CONSTANT(SHADER_SPATIAL); + BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); + BIND_ENUM_CONSTANT(SHADER_PARTICLES); + BIND_ENUM_CONSTANT(SHADER_MAX); + + BIND_ENUM_CONSTANT(ARRAY_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_COLOR); + BIND_ENUM_CONSTANT(ARRAY_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_BONES); + BIND_ENUM_CONSTANT(ARRAY_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_INDEX); + BIND_ENUM_CONSTANT(ARRAY_MAX); + + BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BONES); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX); + BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES); + BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_16_BIT_BONES); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT); + + BIND_ENUM_CONSTANT(PRIMITIVE_POINTS); + BIND_ENUM_CONSTANT(PRIMITIVE_LINES); + BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP); + BIND_ENUM_CONSTANT(PRIMITIVE_LINE_LOOP); + BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES); + BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); + BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_FAN); + BIND_ENUM_CONSTANT(PRIMITIVE_MAX); + + BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED); + BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE); + + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL); + BIND_ENUM_CONSTANT(LIGHT_OMNI); + BIND_ENUM_CONSTANT(LIGHT_SPOT); + + BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR); + BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION); + BIND_ENUM_CONSTANT(LIGHT_PARAM_CONTACT_SHADOW_SIZE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX); + + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS); + + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ALWAYS); + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_NEVER); + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ONLY_NEXT_FRAME); + + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_2X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_8X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_16X); + + BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D); + BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D_NO_SAMPLING); + BIND_ENUM_CONSTANT(VIEWPORT_USAGE_3D); + BIND_ENUM_CONSTANT(VIEWPORT_USAGE_3D_NO_EFFECTS); + + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MAX); + + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_UNSHADED); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OVERDRAW); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_WIREFRAME); + + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_DISABLED); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_WIREFRAME); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_OVERDRAW); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_SHADELESS); + + BIND_ENUM_CONSTANT(INSTANCE_NONE); + BIND_ENUM_CONSTANT(INSTANCE_MESH); + BIND_ENUM_CONSTANT(INSTANCE_MULTIMESH); + BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE); + BIND_ENUM_CONSTANT(INSTANCE_PARTICLES); + BIND_ENUM_CONSTANT(INSTANCE_LIGHT); + BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE); + BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE); + BIND_ENUM_CONSTANT(INSTANCE_MAX); + BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK); + + BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH); + BIND_ENUM_CONSTANT(NINE_PATCH_TILE); + BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT); + + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_ADD); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_SUB); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MIX); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK); + + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF3); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF7); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF9); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13); + + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED); + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE); + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE); + + BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_USAGE_VIDEO_MEM_TOTAL); + BIND_ENUM_CONSTANT(INFO_VIDEO_MEM_USED); + BIND_ENUM_CONSTANT(INFO_TEXTURE_MEM_USED); + BIND_ENUM_CONSTANT(INFO_VERTEX_MEM_USED); + + BIND_ENUM_CONSTANT(FEATURE_SHADERS); + BIND_ENUM_CONSTANT(FEATURE_MULTITHREADED); } void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector<float> &p_margins, const Color &p_modulate) { diff --git a/servers/visual_server.h b/servers/visual_server.h index 9f2d685531..64ed540501 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -85,7 +85,7 @@ public: enum TextureFlags { TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping - TEXTURE_FLAG_FILTER = 4, /// Create texure with linear (or available) filter + TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter TEXTURE_FLAG_ANISOTROPIC_FILTER = 8, TEXTURE_FLAG_CONVERT_TO_LINEAR = 16, TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored @@ -137,6 +137,7 @@ public: }; virtual void texture_debug_usage(List<TextureInfo> *r_info) = 0; + Array _texture_debug_usage_bind(); virtual void textures_keep_original(bool p_enable) = 0; @@ -160,12 +161,18 @@ public: virtual void shader_set_code(RID p_shader, const String &p_code) = 0; virtual String shader_get_code(RID p_shader) const = 0; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + Array _shader_get_param_list_bind(RID p_shader) const; virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; /* COMMON MATERIAL API */ + enum { + MATERIAL_RENDER_PRIORITY_MIN = -128, + MATERIAL_RENDER_PRIORITY_MAX = 127, + + }; virtual RID material_create() = 0; virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; @@ -174,6 +181,8 @@ public: virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; + virtual void material_set_render_priority(RID p_material, int priority) = 0; + virtual void material_set_line_width(RID p_material, float p_width) = 0; virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; @@ -260,6 +269,7 @@ public: virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const = 0; virtual Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const; + virtual Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const; virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const = 0; virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const = 0; @@ -267,6 +277,7 @@ public: virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const = 0; virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const = 0; virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const = 0; + Array _mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const; virtual void mesh_remove_surface(RID p_mesh, int p_index) = 0; virtual int mesh_get_surface_count(RID p_mesh) const = 0; @@ -358,6 +369,7 @@ public: LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, LIGHT_PARAM_SHADOW_NORMAL_BIAS, LIGHT_PARAM_SHADOW_BIAS, + LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, LIGHT_PARAM_MAX }; @@ -398,6 +410,14 @@ public: virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0; virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; + enum LightDirectionalShadowDepthRangeMode { + LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, + LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, + + }; + + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, LightDirectionalShadowDepthRangeMode p_range_mode) = 0; + /* PROBE API */ virtual RID reflection_probe_create() = 0; @@ -612,6 +632,7 @@ public: ENV_BG_CLEAR_COLOR, ENV_BG_COLOR, ENV_BG_SKY, + ENV_BG_COLOR_SKY, ENV_BG_CANVAS, ENV_BG_KEEP, ENV_BG_MAX @@ -619,7 +640,7 @@ public: virtual void environment_set_background(RID p_env, EnvironmentBG p_bg) = 0; virtual void environment_set_sky(RID p_env, RID p_sky) = 0; - virtual void environment_set_sky_scale(RID p_env, float p_scale) = 0; + virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; @@ -657,7 +678,21 @@ public: virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, bool p_blur) = 0; + + enum EnvironmentSSAOQuality { + ENV_SSAO_QUALITY_LOW, + ENV_SSAO_QUALITY_MEDIUM, + ENV_SSAO_QUALITY_HIGH, + }; + + enum EnvironmentSSAOBlur { + ENV_SSAO_BLUR_DISABLED, + ENV_SSAO_BLUR_1x1, + ENV_SSAO_BLUR_2x2, + ENV_SSAO_BLUR_3x3, + }; + + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, const Color &p_color, EnvironmentSSAOQuality p_quality, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0; virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; @@ -823,6 +858,7 @@ public: CANVAS_LIGHT_FILTER_NONE, CANVAS_LIGHT_FILTER_PCF3, CANVAS_LIGHT_FILTER_PCF5, + CANVAS_LIGHT_FILTER_PCF7, CANVAS_LIGHT_FILTER_PCF9, CANVAS_LIGHT_FILTER_PCF13, }; @@ -922,18 +958,29 @@ public: }; // make variant understand the enums - VARIANT_ENUM_CAST(VisualServer::CubeMapSide); VARIANT_ENUM_CAST(VisualServer::TextureFlags); VARIANT_ENUM_CAST(VisualServer::ShaderMode); VARIANT_ENUM_CAST(VisualServer::ArrayType); VARIANT_ENUM_CAST(VisualServer::ArrayFormat); VARIANT_ENUM_CAST(VisualServer::PrimitiveType); +VARIANT_ENUM_CAST(VisualServer::BlendShapeMode); VARIANT_ENUM_CAST(VisualServer::LightType); VARIANT_ENUM_CAST(VisualServer::LightParam); +VARIANT_ENUM_CAST(VisualServer::ViewportUpdateMode); +VARIANT_ENUM_CAST(VisualServer::ViewportClearMode); +VARIANT_ENUM_CAST(VisualServer::ViewportMSAA); +VARIANT_ENUM_CAST(VisualServer::ViewportUsage); +VARIANT_ENUM_CAST(VisualServer::ViewportRenderInfo); +VARIANT_ENUM_CAST(VisualServer::ViewportDebugDraw); VARIANT_ENUM_CAST(VisualServer::ScenarioDebugMode); VARIANT_ENUM_CAST(VisualServer::InstanceType); +VARIANT_ENUM_CAST(VisualServer::NinePatchAxisMode); +VARIANT_ENUM_CAST(VisualServer::CanvasLightMode); +VARIANT_ENUM_CAST(VisualServer::CanvasLightShadowFilter); +VARIANT_ENUM_CAST(VisualServer::CanvasOccluderPolygonCullMode); VARIANT_ENUM_CAST(VisualServer::RenderInfo); +VARIANT_ENUM_CAST(VisualServer::Features); //typedef VisualServer VS; // makes it easier to use #define VS VisualServer |