diff options
Diffstat (limited to 'modules')
624 files changed, 22085 insertions, 15080 deletions
diff --git a/modules/SCsub b/modules/SCsub index 5b39b18334..fb46c5f877 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -1,16 +1,17 @@ #!/usr/bin/env python -Import('env') +Import("env") import modules_builders env_modules = env.Clone() -Export('env_modules') +Export("env_modules") # Header with MODULE_*_ENABLED defines. env.CommandNoCache("modules_enabled.gen.h", Value(env.module_list), modules_builders.generate_modules_enabled) +vs_sources = [] # libmodule_<name>.a for each active module. for module in env.module_list: env.modules_sources = [] @@ -23,6 +24,8 @@ for module in env.module_list: lib = env_modules.add_library("module_%s" % module, env.modules_sources) env.Prepend(LIBS=[lib]) + if env["vsproj"]: + vs_sources += env.modules_sources # libmodules.a with only register_module_types. # Must be last so that all libmodule_<name>.a libraries are on the right side @@ -31,3 +34,5 @@ env.modules_sources = [] env_modules.add_source_files(env.modules_sources, "register_module_types.gen.cpp") lib = env_modules.add_library("modules", env.modules_sources) env.Prepend(LIBS=[lib]) +if env["vsproj"]: + env.modules_sources += vs_sources diff --git a/modules/arkit/SCsub b/modules/arkit/SCsub index c05595ea2a..61c0a8248c 100644 --- a/modules/arkit/SCsub +++ b/modules/arkit/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_arkit = env_modules.Clone() @@ -9,4 +9,4 @@ env_arkit = env_modules.Clone() modules_sources = [] env_arkit.add_source_files(modules_sources, "*.cpp") env_arkit.add_source_files(modules_sources, "*.mm") -mod_lib = env_modules.add_library('#bin/libgodot_arkit_module' + env['LIBSUFFIX'], modules_sources) +mod_lib = env_modules.add_library("#bin/libgodot_arkit_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/arkit/arkit_interface.h b/modules/arkit/arkit_interface.h index 4f8f726816..1044f3cf6f 100644 --- a/modules/arkit/arkit_interface.h +++ b/modules/arkit/arkit_interface.h @@ -31,9 +31,9 @@ #ifndef ARKIT_INTERFACE_H #define ARKIT_INTERFACE_H -#include "servers/arvr/arvr_interface.h" -#include "servers/arvr/arvr_positional_tracker.h" #include "servers/camera/camera_feed.h" +#include "servers/xr/xr_interface.h" +#include "servers/xr/xr_positional_tracker.h" /** @author Bastiaan Olij <mux213@gmail.com> @@ -44,8 +44,8 @@ // forward declaration for some needed objects class ARKitShader; -class ARKitInterface : public ARVRInterface { - GDCLASS(ARKitInterface, ARVRInterface); +class ARKitInterface : public XRInterface { + GDCLASS(ARKitInterface, XRInterface); private: bool initialized; @@ -65,7 +65,7 @@ private: Vector<uint8_t> img_data[2]; struct anchor_map { - ARVRPositionalTracker *tracker; + XRPositionalTracker *tracker; unsigned char uuid[16]; }; @@ -73,7 +73,7 @@ private: unsigned int num_anchors; unsigned int max_anchors; anchor_map *anchors; - ARVRPositionalTracker *get_anchor_for_uuid(const unsigned char *p_uuid); + XRPositionalTracker *get_anchor_for_uuid(const unsigned char *p_uuid); void remove_anchor_for_uuid(const unsigned char *p_uuid); void remove_all_anchors(); @@ -108,9 +108,9 @@ public: virtual Size2 get_render_targetsize(); virtual bool is_stereo(); - virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform); - 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 Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform); + virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far); + virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect); virtual void process(); diff --git a/modules/arkit/arkit_interface.mm b/modules/arkit/arkit_interface.mm index 39447e8dab..7de824815a 100644 --- a/modules/arkit/arkit_interface.mm +++ b/modules/arkit/arkit_interface.mm @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "core/os/input.h" +#include "core/input/input.h" #include "core/os/os.h" #include "scene/resources/surface_tool.h" -#include "servers/visual/visual_server_globals.h" +#include "servers/rendering/rendering_server_globals.h" #import <ARKit/ARKit.h> #import <UIKit/UIKit.h> @@ -158,7 +158,7 @@ StringName ARKitInterface::get_name() const { } int ARKitInterface::get_capabilities() const { - return ARKitInterface::ARVR_MONO + ARKitInterface::ARVR_AR; + return ARKitInterface::XR_MONO + ARKitInterface::XR_AR; } Array ARKitInterface::raycast(Vector2 p_screen_coord) { @@ -218,8 +218,8 @@ bool ARKitInterface::is_initialized() const { } bool ARKitInterface::initialize() { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, false); + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, false); if (!initialized) { print_line("initializing ARKit"); @@ -244,7 +244,7 @@ bool ARKitInterface::initialize() { transform = Transform(); // make this our primary interface - arvr_server->set_primary_interface(this); + xr_server->set_primary_interface(this); // make sure we have our feed setup if (feed.is_null()) { @@ -270,10 +270,10 @@ bool ARKitInterface::initialize() { void ARKitInterface::uninitialize() { if (initialized) { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - if (arvr_server != NULL) { + XRServer *xr_server = XRServer::get_singleton(); + if (xr_server != NULL) { // no longer our primary interface - arvr_server->clear_primary_interface_if(this); + xr_server->clear_primary_interface_if(this); } if (feed.is_valid()) { @@ -303,22 +303,22 @@ Size2 ARKitInterface::get_render_targetsize() { return target_size; } -Transform ARKitInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) { +Transform ARKitInterface::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) { _THREAD_SAFE_METHOD_ Transform transform_for_eye; - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, transform_for_eye); + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, transform_for_eye); if (initialized) { - float world_scale = arvr_server->get_world_scale(); + float world_scale = xr_server->get_world_scale(); // just scale our origin point of our transform, note that we really shouldn't be using world_scale in ARKit but.... transform_for_eye = transform; transform_for_eye.origin *= world_scale; - transform_for_eye = p_cam_transform * arvr_server->get_reference_frame() * transform_for_eye; + transform_for_eye = p_cam_transform * xr_server->get_reference_frame() * transform_for_eye; } else { // huh? well just return what we got.... transform_for_eye = p_cam_transform; @@ -327,7 +327,7 @@ Transform ARKitInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, const return transform_for_eye; } -CameraMatrix ARKitInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { +CameraMatrix ARKitInterface::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { // Remember our near and far, it will be used in process when we obtain our projection from our ARKit session. z_near = p_z_near; z_far = p_z_far; @@ -335,7 +335,7 @@ CameraMatrix ARKitInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, r return projection; } -void ARKitInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { +void ARKitInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { _THREAD_SAFE_METHOD_ // We must have a valid render target @@ -356,7 +356,7 @@ void ARKitInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_targ VSG::rasterizer->blit_render_target_to_screen(p_render_target, screen_rect, 0); } -ARVRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *p_uuid) { +XRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *p_uuid) { if (anchors == NULL) { num_anchors = 0; max_anchors = 10; @@ -377,8 +377,8 @@ ARVRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char * ERR_FAIL_NULL_V(anchors, NULL); } - ARVRPositionalTracker *new_tracker = memnew(ARVRPositionalTracker); - new_tracker->set_type(ARVRServer::TRACKER_ANCHOR); + XRPositionalTracker *new_tracker = memnew(XRPositionalTracker); + new_tracker->set_type(XRServer::TRACKER_ANCHOR); char tracker_name[256]; sprintf(tracker_name, "Anchor %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", p_uuid[0], p_uuid[1], p_uuid[2], p_uuid[3], p_uuid[4], p_uuid[5], p_uuid[6], p_uuid[7], p_uuid[8], p_uuid[9], p_uuid[10], p_uuid[11], p_uuid[12], p_uuid[13], p_uuid[14], p_uuid[15]); @@ -388,7 +388,7 @@ ARVRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char * new_tracker->set_name(name); // add our tracker - ARVRServer::get_singleton()->add_tracker(new_tracker); + XRServer::get_singleton()->add_tracker(new_tracker); anchors[num_anchors].tracker = new_tracker; memcpy(anchors[num_anchors].uuid, p_uuid, 16); num_anchors++; @@ -401,7 +401,7 @@ void ARKitInterface::remove_anchor_for_uuid(const unsigned char *p_uuid) { for (unsigned int i = 0; i < num_anchors; i++) { if (memcmp(anchors[i].uuid, p_uuid, 16) == 0) { // remove our tracker - ARVRServer::get_singleton()->remove_tracker(anchors[i].tracker); + XRServer::get_singleton()->remove_tracker(anchors[i].tracker); memdelete(anchors[i].tracker); // bring remaining forward @@ -421,7 +421,7 @@ void ARKitInterface::remove_all_anchors() { if (anchors != NULL) { for (unsigned int i = 0; i < num_anchors; i++) { // remove our tracker - ARVRServer::get_singleton()->remove_tracker(anchors[i].tracker); + XRServer::get_singleton()->remove_tracker(anchors[i].tracker); memdelete(anchors[i].tracker); }; @@ -582,16 +582,16 @@ void ARKitInterface::process() { // strangely enough we have to states, rolling them up into one if (camera.trackingState == ARTrackingStateNotAvailable) { // no tracking, would be good if we black out the screen or something... - tracking_state = ARVRInterface::ARVR_NOT_TRACKING; + tracking_state = XRInterface::XR_NOT_TRACKING; } else { if (camera.trackingState == ARTrackingStateNormal) { - tracking_state = ARVRInterface::ARVR_NORMAL_TRACKING; + tracking_state = XRInterface::XR_NORMAL_TRACKING; } else if (camera.trackingStateReason == ARTrackingStateReasonExcessiveMotion) { - tracking_state = ARVRInterface::ARVR_EXCESSIVE_MOTION; + tracking_state = XRInterface::XR_EXCESSIVE_MOTION; } else if (camera.trackingStateReason == ARTrackingStateReasonInsufficientFeatures) { - tracking_state = ARVRInterface::ARVR_INSUFFICIENT_FEATURES; + tracking_state = XRInterface::XR_INSUFFICIENT_FEATURES; } else { - tracking_state = ARVRInterface::ARVR_UNKNOWN_TRACKING; + tracking_state = XRInterface::XR_UNKNOWN_TRACKING; } // copy our current frame transform @@ -665,7 +665,7 @@ void ARKitInterface::_add_or_update_anchor(void *p_anchor) { unsigned char uuid[16]; [anchor.identifier getUUIDBytes:uuid]; - ARVRPositionalTracker *tracker = get_anchor_for_uuid(uuid); + XRPositionalTracker *tracker = get_anchor_for_uuid(uuid); if (tracker != NULL) { // lets update our mesh! (using Arjens code as is for now) // we should also probably limit how often we do this... @@ -695,7 +695,7 @@ void ARKitInterface::_add_or_update_anchor(void *p_anchor) { } // Note, this also contains a scale factor which gives us an idea of the size of the anchor - // We may extract that in our ARVRAnchor class + // We may extract that in our XRAnchor class Basis b; matrix_float4x4 m44 = anchor.transform; b.elements[0].x = m44.columns[0][0]; diff --git a/modules/arkit/config.py b/modules/arkit/config.py index 96e41826c5..e68603fc93 100644 --- a/modules/arkit/config.py +++ b/modules/arkit/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return platform == 'iphone' + return platform == "iphone" + def configure(env): pass diff --git a/modules/arkit/register_types.cpp b/modules/arkit/register_types.cpp index c78b35529b..91069ab364 100644 --- a/modules/arkit/register_types.cpp +++ b/modules/arkit/register_types.cpp @@ -37,7 +37,7 @@ void register_arkit_types() { Ref<ARKitInterface> arkit_interface; arkit_interface.instance(); - ARVRServer::get_singleton()->add_interface(arkit_interface); + XRServer::get_singleton()->add_interface(arkit_interface); } void unregister_arkit_types() { diff --git a/modules/assimp/SCsub b/modules/assimp/SCsub index 90cdd7f5fc..f1d0c742b4 100644 --- a/modules/assimp/SCsub +++ b/modules/assimp/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_assimp = env_modules.Clone() @@ -10,85 +10,85 @@ env_assimp = env_modules.Clone() if True: # env['builtin_assimp']: thirdparty_dir = "#thirdparty/assimp" - env_assimp.Prepend(CPPPATH=['#thirdparty/assimp']) - env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/code']) - env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/include']) + env_assimp.Prepend(CPPPATH=["#thirdparty/assimp"]) + env_assimp.Prepend(CPPPATH=["#thirdparty/assimp/code"]) + env_assimp.Prepend(CPPPATH=["#thirdparty/assimp/include"]) - #env_assimp.Append(CPPDEFINES=['ASSIMP_DOUBLE_PRECISION']) # TODO default to what godot is compiled with for future double support - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_SINGLETHREADED']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_BOOST_WORKAROUND']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_OWN_ZLIB']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_EXPORT']) + # env_assimp.Append(CPPDEFINES=['ASSIMP_DOUBLE_PRECISION']) # TODO default to what godot is compiled with for future double support + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_SINGLETHREADED"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_BOOST_WORKAROUND"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OWN_ZLIB"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_EXPORT"]) # Importers we don't need - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_3D_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_3DS_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_3MF_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_AC_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_AMF_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_ASE_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_ASSBIN_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_B3D_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_BLEND_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_BVH_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_C4D_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_COB_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_COLLADA_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_CSM_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_DXF_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_GLTF2_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_GLTF_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_HMP_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_IFC_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_IRR_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_IRRMESH_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_LWO_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_LWS_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_M3D_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_MD2_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_MD3_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_MD5_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_MD5_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_MDC_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_MDL_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_MMD_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_MS3D_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_NDO_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_NFF_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_OBJ_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_OFF_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_OGRE_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_OPENGEX_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_PLY_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_Q3BSP_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_Q3D_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_RAW_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_SIB_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_SMD_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_STEP_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_STL_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_TERRAGEN_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_X3D_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_XGL_IMPORTER']) - env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_X_IMPORTER']) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3D_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3DS_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3MF_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_AC_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_AMF_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_ASE_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_ASSBIN_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_B3D_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_BLEND_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_BVH_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_C4D_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_COB_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_COLLADA_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_CSM_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_DXF_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_GLTF2_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_GLTF_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_HMP_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IFC_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IRR_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IRRMESH_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_LWO_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_LWS_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_M3D_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD2_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD3_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD5_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD5_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MDC_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MDL_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MMD_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MS3D_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_NDO_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_NFF_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OBJ_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OFF_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OGRE_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OPENGEX_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_PLY_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_Q3BSP_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_Q3D_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_RAW_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_SIB_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_SMD_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_STEP_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_STL_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_TERRAGEN_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_X3D_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_XGL_IMPORTER"]) + env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_X_IMPORTER"]) + + if env["platform"] == "windows": + env_assimp.Append(CPPDEFINES=["PLATFORM_WINDOWS"]) + env_assimp.Append(CPPDEFINES=[("PLATFORM", "WINDOWS")]) + elif env["platform"] == "linuxbsd": + env_assimp.Append(CPPDEFINES=["PLATFORM_LINUX"]) + env_assimp.Append(CPPDEFINES=[("PLATFORM", "LINUX")]) + elif env["platform"] == "osx": + env_assimp.Append(CPPDEFINES=["PLATFORM_DARWIN"]) + env_assimp.Append(CPPDEFINES=[("PLATFORM", "DARWIN")]) - if(env['platform'] == 'windows'): - env_assimp.Append(CPPDEFINES=['PLATFORM_WINDOWS']) - env_assimp.Append(CPPDEFINES=[('PLATFORM', 'WINDOWS')]) - elif(env['platform'] == 'x11'): - env_assimp.Append(CPPDEFINES=['PLATFORM_LINUX']) - env_assimp.Append(CPPDEFINES=[('PLATFORM', 'LINUX')]) - elif(env['platform'] == 'osx'): - env_assimp.Append(CPPDEFINES=['PLATFORM_DARWIN']) - env_assimp.Append(CPPDEFINES=[('PLATFORM', 'DARWIN')]) - env_thirdparty = env_assimp.Clone() env_thirdparty.disable_warnings() - env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/CApi/*.cpp')) - env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/Common/*.cpp')) - env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/PostProcessing/*.cpp')) - env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/Material/*.cpp')) - env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/FBX/*.cpp')) + env_thirdparty.add_source_files(env.modules_sources, Glob("#thirdparty/assimp/code/CApi/*.cpp")) + env_thirdparty.add_source_files(env.modules_sources, Glob("#thirdparty/assimp/code/Common/*.cpp")) + env_thirdparty.add_source_files(env.modules_sources, Glob("#thirdparty/assimp/code/PostProcessing/*.cpp")) + env_thirdparty.add_source_files(env.modules_sources, Glob("#thirdparty/assimp/code/Material/*.cpp")) + env_thirdparty.add_source_files(env.modules_sources, Glob("#thirdparty/assimp/code/FBX/*.cpp")) # Godot's own source files env_assimp.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/assimp/config.py b/modules/assimp/config.py index 098f1eafa9..53b8f2f2e3 100644 --- a/modules/assimp/config.py +++ b/modules/assimp/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return env['tools'] + return env["tools"] + def configure(env): pass diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp index 682a7e33c8..9c90faf66b 100644 --- a/modules/assimp/editor_scene_importer_assimp.cpp +++ b/modules/assimp/editor_scene_importer_assimp.cpp @@ -32,9 +32,9 @@ #include "core/io/image_loader.h" #include "editor/import/resource_importer_scene.h" #include "import_utils.h" -#include "scene/3d/camera.h" -#include "scene/3d/light.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/main/node.h" #include "scene/resources/material.h" #include "scene/resources/surface_tool.h" @@ -53,7 +53,6 @@ aiBone *get_bone_by_name(const aiScene *scene, aiString bone_name) { // iterate over all the bones on the mesh for this node only! for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) { - aiBone *bone = mesh->mBones[boneIndex]; if (bone->mName == bone_name) { printf("matched bone by name: %s\n", bone->mName.C_Str()); @@ -62,11 +61,10 @@ aiBone *get_bone_by_name(const aiScene *scene, aiString bone_name) { } } - return NULL; + return nullptr; } void EditorSceneImporterAssimp::get_extensions(List<String> *r_extensions) const { - const String import_setting_string = "filesystem/import/open_asset_import/"; Map<String, ImportFormat> import_format; @@ -149,21 +147,18 @@ Node *EditorSceneImporterAssimp::import_scene(const String &p_path, uint32_t p_f 0; aiScene *scene = (aiScene *)importer.ReadFile(s_path.c_str(), post_process_Steps); - ERR_FAIL_COND_V_MSG(scene == NULL, NULL, String("Open Asset Import failed to open: ") + String(importer.GetErrorString())); + ERR_FAIL_COND_V_MSG(scene == nullptr, nullptr, String("Open Asset Import failed to open: ") + String(importer.GetErrorString())); return _generate_scene(p_path, scene, p_flags, p_bake_fps, max_bone_weights); } template <class T> struct EditorSceneImporterAssetImportInterpolate { - T lerp(const T &a, const T &b, float c) const { - return a + (b - a) * c; } T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) { - float t2 = t * t; float t3 = t2 * t; @@ -185,7 +180,6 @@ struct EditorSceneImporterAssetImportInterpolate { //thank you for existing, partial specialization template <> struct EditorSceneImporterAssetImportInterpolate<Quat> { - Quat lerp(const Quat &a, const Quat &b, float c) const { ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quat(), "The quaternion \"a\" must be normalized."); ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quat(), "The quaternion \"b\" must be normalized."); @@ -214,8 +208,9 @@ T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, co //could use binary search, worth it? int idx = -1; for (int i = 0; i < p_times.size(); i++) { - if (p_times[i] > p_time) + if (p_times[i] > p_time) { break; + } idx++; } @@ -223,7 +218,6 @@ T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, co switch (p_interp) { case AssetImportAnimation::INTERP_LINEAR: { - if (idx == -1) { return p_values[0]; } else if (idx >= p_times.size() - 1) { @@ -236,7 +230,6 @@ T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, co } break; case AssetImportAnimation::INTERP_STEP: { - if (idx == -1) { return p_values[0]; } else if (idx >= p_times.size() - 1) { @@ -247,7 +240,6 @@ T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, co } break; case AssetImportAnimation::INTERP_CATMULLROMSPLINE: { - if (idx == -1) { return p_values[1]; } else if (idx >= p_times.size() - 1) { @@ -260,7 +252,6 @@ T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, co } break; case AssetImportAnimation::INTERP_CUBIC_SPLINE: { - if (idx == -1) { return p_values[1]; } else if (idx >= p_times.size() - 1) { @@ -284,7 +275,7 @@ T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, co aiBone *EditorSceneImporterAssimp::get_bone_from_stack(ImportState &state, aiString name) { List<aiBone *>::Element *iter; - aiBone *bone = NULL; + aiBone *bone = nullptr; for (iter = state.bone_stack.front(); iter; iter = iter->next()) { bone = (aiBone *)iter->get(); @@ -294,32 +285,31 @@ aiBone *EditorSceneImporterAssimp::get_bone_from_stack(ImportState &state, aiStr } } - return NULL; + return nullptr; } -Spatial * +Node3D * EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights) { - ERR_FAIL_COND_V(scene == NULL, NULL); + ERR_FAIL_COND_V(scene == nullptr, nullptr); ImportState state; state.path = p_path; state.assimp_scene = scene; state.max_bone_weights = p_max_bone_weights; - state.animation_player = NULL; + state.animation_player = nullptr; // populate light map for (unsigned int l = 0; l < scene->mNumLights; l++) { - aiLight *ai_light = scene->mLights[l]; - ERR_CONTINUE(ai_light == NULL); + ERR_CONTINUE(ai_light == nullptr); state.light_cache[AssimpUtils::get_assimp_string(ai_light->mName)] = l; } // fill camera cache for (unsigned int c = 0; c < scene->mNumCameras; c++) { aiCamera *ai_camera = scene->mCameras[c]; - ERR_CONTINUE(ai_camera == NULL); + ERR_CONTINUE(ai_camera == nullptr); state.camera_cache[AssimpUtils::get_assimp_string(ai_camera->mName)] = c; } @@ -333,7 +323,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, RegenerateBoneStack(state); - Node *last_valid_parent = NULL; + Node *last_valid_parent = nullptr; List<const aiNode *>::Element *iter; for (iter = state.nodes.front(); iter; iter = iter->next()) { @@ -343,7 +333,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, String node_name = AssimpUtils::get_assimp_string(element_assimp_node->mName); //print_verbose("node: " + node_name); - Spatial *spatial = NULL; + Node3D *spatial = nullptr; Transform transform = AssimpUtils::assimp_matrix_transform(element_assimp_node->mTransformation); // retrieve this node bone @@ -356,18 +346,18 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, } else if (state.armature_nodes.find(element_assimp_node)) { // create skeleton print_verbose("Making skeleton: " + node_name); - Skeleton *skeleton = memnew(Skeleton); + Skeleton3D *skeleton = memnew(Skeleton3D); spatial = skeleton; if (!state.armature_skeletons.has(element_assimp_node)) { state.armature_skeletons.insert(element_assimp_node, skeleton); } - } else if (bone != NULL) { + } else if (bone != nullptr) { continue; } else { - spatial = memnew(Spatial); + spatial = memnew(Node3D); } - ERR_CONTINUE_MSG(spatial == NULL, "FBX Import - are we out of ram?"); + ERR_CONTINUE_MSG(spatial == nullptr, "FBX Import - are we out of ram?"); // we on purpose set the transform and name after creating the node. spatial->set_name(node_name); @@ -381,13 +371,13 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, // flat node map parent lookup tool state.flat_node_map.insert(element_assimp_node, spatial); - Map<const aiNode *, Spatial *>::Element *parent_lookup = state.flat_node_map.find(parent_assimp_node); + Map<const aiNode *, Node3D *>::Element *parent_lookup = state.flat_node_map.find(parent_assimp_node); // note: this always fails on the root node :) keep that in mind this is by design if (parent_lookup) { - Spatial *parent_node = parent_lookup->value(); + Node3D *parent_node = parent_lookup->value(); - ERR_FAIL_COND_V_MSG(parent_node == NULL, state.root, + ERR_FAIL_COND_V_MSG(parent_node == nullptr, state.root, "Parent node invalid even though lookup successful, out of ram?"); if (spatial != state.root) { @@ -434,8 +424,8 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, aiNode *parent_node = bone_node->mParent; String bone_name = AssimpUtils::get_anim_string_from_assimp(bone->mName); - ERR_CONTINUE_MSG(armature_for_bone == NULL, "Armature for bone invalid: " + bone_name); - Skeleton *skeleton = state.armature_skeletons[armature_for_bone]; + ERR_CONTINUE_MSG(armature_for_bone == nullptr, "Armature for bone invalid: " + bone_name); + Skeleton3D *skeleton = state.armature_skeletons[armature_for_bone]; state.skeleton_bone_map[bone] = skeleton; @@ -454,7 +444,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, skeleton->set_bone_rest(boneIdx, pform); skeleton->set_bone_pose(boneIdx, pform); - if (parent_node != NULL) { + if (parent_node != nullptr) { int parent_bone_id = skeleton->find_bone(AssimpUtils::get_anim_string_from_assimp(parent_node->mName)); int current_bone_id = boneIdx; skeleton->set_bone_parent(current_bone_id, parent_bone_id); @@ -464,14 +454,14 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, print_verbose("generating mesh phase from skeletal mesh"); - List<Spatial *> cleanup_template_nodes; + List<Node3D *> cleanup_template_nodes; - for (Map<const aiNode *, Spatial *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { + for (Map<const aiNode *, Node3D *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { const aiNode *assimp_node = key_value_pair->key(); - Spatial *mesh_template = key_value_pair->value(); + Node3D *mesh_template = key_value_pair->value(); - ERR_CONTINUE(assimp_node == NULL); - ERR_CONTINUE(mesh_template == NULL); + ERR_CONTINUE(assimp_node == nullptr); + ERR_CONTINUE(mesh_template == nullptr); Node *parent_node = mesh_template->get_parent(); @@ -479,7 +469,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, continue; } - if (parent_node == NULL) { + if (parent_node == nullptr) { print_error("Found invalid parent node!"); continue; // root node } @@ -488,9 +478,8 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, Transform node_transform = AssimpUtils::assimp_matrix_transform(assimp_node->mTransformation); if (assimp_node->mNumMeshes > 0) { - MeshInstance *mesh = create_mesh(state, assimp_node, node_name, parent_node, node_transform); + MeshInstance3D *mesh = create_mesh(state, assimp_node, node_name, parent_node, node_transform); if (mesh) { - parent_node->remove_child(mesh_template); // re-parent children @@ -522,7 +511,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, } } - for (List<Spatial *>::Element *element = cleanup_template_nodes.front(); element; element = element->next()) { + for (List<Node3D *>::Element *element = cleanup_template_nodes.front(); element; element = element->next()) { if (element->get()) { memdelete(element->get()); } @@ -530,7 +519,6 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, } if (p_flags & IMPORT_ANIMATION && scene->mNumAnimations) { - state.animation_player = memnew(AnimationPlayer); state.root->add_child(state.animation_player); state.animation_player->set_owner(state.root); @@ -559,7 +547,7 @@ EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, void EditorSceneImporterAssimp::_insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id, int anim_fps, Ref<Animation> animation, float ticks_per_second, - Skeleton *skeleton, const NodePath &node_path, + Skeleton3D *skeleton, const NodePath &node_path, const String &node_name, aiBone *track_bone) { const aiNodeAnim *assimp_track = assimp_anim->mChannels[track_id]; //make transform track @@ -621,7 +609,6 @@ void EditorSceneImporterAssimp::_insert_animation_track(ImportState &scene, cons int skeleton_bone = skeleton->find_bone(node_name); if (skeleton_bone >= 0 && track_bone) { - Transform xform; xform.basis.set_quat_scale(rot, scale); xform.origin = pos; @@ -652,21 +639,20 @@ void EditorSceneImporterAssimp::_insert_animation_track(ImportState &scene, cons // I really do not like this but need to figure out a better way of removing it later. Node *EditorSceneImporterAssimp::get_node_by_name(ImportState &state, String name) { - for (Map<const aiNode *, Spatial *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { + for (Map<const aiNode *, Node3D *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) { const aiNode *assimp_node = key_value_pair->key(); - Spatial *node = key_value_pair->value(); + Node3D *node = key_value_pair->value(); String node_name = AssimpUtils::get_assimp_string(assimp_node->mName); if (name == node_name && node) { return node; } } - return NULL; + return nullptr; } /* Bone stack is a fifo handler for multiple armatures since armatures aren't a thing in assimp (yet) */ void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state) { - state.bone_stack.clear(); // build bone stack list for (unsigned int mesh_id = 0; mesh_id < state.assimp_scene->mNumMeshes; ++mesh_id) { @@ -691,7 +677,7 @@ void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state, aiMesh * // iterate over all the bones on the mesh for this node only! for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) { aiBone *bone = mesh->mBones[boneIndex]; - if (state.bone_stack.find(bone) == NULL) { + if (state.bone_stack.find(bone) == nullptr) { state.bone_stack.push_back(bone); } } @@ -700,7 +686,6 @@ void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state, aiMesh * // animation tracks are per bone void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_animation_index, int p_bake_fps) { - ERR_FAIL_INDEX(p_animation_index, (int)state.assimp_scene->mNumAnimations); const aiAnimation *anim = state.assimp_scene->mAnimations[p_animation_index]; @@ -711,7 +696,7 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim print_verbose("import animation: " + name); float ticks_per_second = anim->mTicksPerSecond; - if (state.assimp_scene->mMetaData != NULL && Math::is_equal_approx(ticks_per_second, 0.0f)) { + if (state.assimp_scene->mMetaData != nullptr && Math::is_equal_approx(ticks_per_second, 0.0f)) { int32_t time_mode = 0; state.assimp_scene->mMetaData->Get("TimeMode", time_mode); ticks_per_second = AssimpUtils::get_fbx_fps(time_mode, state.assimp_scene); @@ -747,9 +732,9 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim continue; //do not bother } - Skeleton *skeleton = NULL; + Skeleton3D *skeleton = nullptr; NodePath node_path; - aiBone *bone = NULL; + aiBone *bone = nullptr; // Import skeleton bone animation for this track // Any bone will do, no point in processing more than just what is in the skeleton @@ -795,7 +780,6 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim //blend shape tracks for (size_t i = 0; i < anim->mNumMorphMeshChannels; i++) { - const aiMeshMorphAnim *anim_mesh = anim->mMorphMeshChannels[i]; const String prop_name = AssimpUtils::get_assimp_string(anim_mesh->mName); @@ -805,8 +789,8 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim Node *item = get_node_by_name(state, mesh_name); ERR_CONTINUE_MSG(!item, "failed to look up node by name"); - const MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(item); - ERR_CONTINUE(mesh_instance == NULL); + const MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(item); + ERR_CONTINUE(mesh_instance == nullptr); String base_path = state.root->get_path_to(mesh_instance); @@ -816,14 +800,12 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim //add the tracks for this mesh int base_track = animation->get_track_count(); for (int j = 0; j < mesh->get_blend_shape_count(); j++) { - animation->add_track(Animation::TYPE_VALUE); animation->track_set_path(base_track + j, base_path + ":blend_shapes/" + mesh->get_blend_shape_name(j)); } for (size_t k = 0; k < anim_mesh->mNumKeys; k++) { for (size_t j = 0; j < anim_mesh->mKeys[k].mNumValuesAndWeights; j++) { - float t = anim_mesh->mKeys[k].mTime / ticks_per_second; float w = anim_mesh->mKeys[k].mWeights[j]; @@ -836,14 +818,14 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim state.animation_player->add_animation(name, animation); } } + // // Mesh Generation from indices ? why do we need so much mesh code // [debt needs looked into] Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &state, const Vector<int> &p_surface_indices, const aiNode *assimp_node, Ref<Skin> &skin, - Skeleton *&skeleton_assigned) { - + Skeleton3D *&skeleton_assigned) { Ref<ArrayMesh> mesh; mesh.instance(); bool has_uvs = false; @@ -894,7 +876,6 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat int bone_index = skeleton_assigned->find_bone(bone_name); ERR_CONTINUE(bone_index == -1); for (size_t w = 0; w < bone->mNumWeights; w++) { - aiVertexWeight ai_weights = bone->mWeights[w]; BoneInfo bi; @@ -920,7 +901,6 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat st->begin(Mesh::PRIMITIVE_TRIANGLES); for (size_t j = 0; j < ai_mesh->mNumVertices; j++) { - // Get the texture coordinates if they exist if (ai_mesh->HasTextureCoords(0)) { has_uvs = true; @@ -940,7 +920,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat } // Work out normal calculations? - this needs work it doesn't work properly on huestos - if (ai_mesh->mNormals != NULL) { + if (ai_mesh->mNormals != nullptr) { const aiVector3D normals = ai_mesh->mNormals[j]; const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z); st->add_normal(godot_normal); @@ -956,7 +936,6 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat // We have vertex weights right? if (vertex_weights.has(j)) { - Vector<BoneInfo> bone_info = vertex_weights[j]; Vector<int> bones; bones.resize(bone_info.size()); @@ -1200,7 +1179,6 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES; for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) { - String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName); if (ai_anim_mesh_name.empty()) { @@ -1208,9 +1186,9 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat } Array array_copy; - array_copy.resize(VisualServer::ARRAY_MAX); + array_copy.resize(RenderingServer::ARRAY_MAX); - for (int l = 0; l < VisualServer::ARRAY_MAX; l++) { + for (int l = 0; l < RenderingServer::ARRAY_MAX; l++) { array_copy[l] = array_mesh[l].duplicate(true); } @@ -1224,13 +1202,13 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat Vector3 position = Vector3(ai_pos.x, ai_pos.y, ai_pos.z); vertices.ptrw()[l] = position; } - PackedVector3Array new_vertices = array_copy[VisualServer::ARRAY_VERTEX].duplicate(true); + PackedVector3Array new_vertices = array_copy[RenderingServer::ARRAY_VERTEX].duplicate(true); ERR_CONTINUE(vertices.size() != new_vertices.size()); for (int32_t l = 0; l < new_vertices.size(); l++) { Vector3 *w = new_vertices.ptrw(); w[l] = vertices[l]; } - array_copy[VisualServer::ARRAY_VERTEX] = new_vertices; + array_copy[RenderingServer::ARRAY_VERTEX] = new_vertices; } int32_t color_set = 0; @@ -1242,13 +1220,13 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat Color color = Color(ai_color.r, ai_color.g, ai_color.b, ai_color.a); colors.ptrw()[l] = color; } - PackedColorArray new_colors = array_copy[VisualServer::ARRAY_COLOR].duplicate(true); + PackedColorArray new_colors = array_copy[RenderingServer::ARRAY_COLOR].duplicate(true); ERR_CONTINUE(colors.size() != new_colors.size()); for (int32_t l = 0; l < colors.size(); l++) { Color *w = new_colors.ptrw(); w[l] = colors[l]; } - array_copy[VisualServer::ARRAY_COLOR] = new_colors; + array_copy[RenderingServer::ARRAY_COLOR] = new_colors; } if (ai_mesh->mAnimMeshes[j]->HasNormals()) { @@ -1259,13 +1237,13 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat Vector3 normal = Vector3(ai_normal.x, ai_normal.y, ai_normal.z); normals.ptrw()[l] = normal; } - PackedVector3Array new_normals = array_copy[VisualServer::ARRAY_NORMAL].duplicate(true); + PackedVector3Array new_normals = array_copy[RenderingServer::ARRAY_NORMAL].duplicate(true); ERR_CONTINUE(normals.size() != new_normals.size()); for (int l = 0; l < normals.size(); l++) { Vector3 *w = new_normals.ptrw(); w[l] = normals[l]; } - array_copy[VisualServer::ARRAY_NORMAL] = new_normals; + array_copy[RenderingServer::ARRAY_NORMAL] = new_normals; } if (ai_mesh->mAnimMeshes[j]->HasTangentsAndBitangents()) { @@ -1275,7 +1253,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat for (size_t l = 0; l < num_vertices; l++) { AssimpUtils::calc_tangent_from_mesh(ai_mesh, j, l, l, w); } - PackedFloat32Array new_tangents = array_copy[VisualServer::ARRAY_TANGENT].duplicate(true); + PackedFloat32Array new_tangents = array_copy[RenderingServer::ARRAY_TANGENT].duplicate(true); ERR_CONTINUE(new_tangents.size() != tangents.size() * 4); for (int32_t l = 0; l < tangents.size(); l++) { new_tangents.ptrw()[l + 0] = tangents[l].r; @@ -1283,7 +1261,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat new_tangents.ptrw()[l + 2] = tangents[l].b; new_tangents.ptrw()[l + 3] = tangents[l].a; } - array_copy[VisualServer::ARRAY_TANGENT] = new_tangents; + array_copy[RenderingServer::ARRAY_TANGENT] = new_tangents; } morphs[j] = array_copy; @@ -1299,7 +1277,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat /** * Create a new mesh for the node supplied */ -MeshInstance * +MeshInstance3D * EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform) { /* MESH NODE */ Ref<Mesh> mesh; @@ -1325,15 +1303,15 @@ EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_ mesh_key += itos(surface_indices[i]); } - Skeleton *skeleton = NULL; - aiNode *armature = NULL; + Skeleton3D *skeleton = nullptr; + aiNode *armature = nullptr; if (!state.mesh_cache.has(mesh_key)) { mesh = _generate_mesh_from_surface_indices(state, surface_indices, assimp_node, skin, skeleton); state.mesh_cache[mesh_key] = mesh; } - MeshInstance *mesh_node = memnew(MeshInstance); + MeshInstance3D *mesh_node = memnew(MeshInstance3D); mesh = state.mesh_cache[mesh_key]; mesh_node->set_mesh(mesh); @@ -1407,22 +1385,22 @@ EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_ * Create a light for the scene * Automatically caches lights for lookup later */ -Spatial *EditorSceneImporterAssimp::create_light( +Node3D *EditorSceneImporterAssimp::create_light( ImportState &state, const String &node_name, Transform &look_at_transform) { - Light *light = NULL; + Light3D *light = nullptr; aiLight *assimp_light = state.assimp_scene->mLights[state.light_cache[node_name]]; - ERR_FAIL_COND_V(!assimp_light, NULL); + ERR_FAIL_COND_V(!assimp_light, nullptr); if (assimp_light->mType == aiLightSource_DIRECTIONAL) { - light = memnew(DirectionalLight); + light = memnew(DirectionalLight3D); } else if (assimp_light->mType == aiLightSource_POINT) { - light = memnew(OmniLight); + light = memnew(OmniLight3D); } else if (assimp_light->mType == aiLightSource_SPOT) { - light = memnew(SpotLight); + light = memnew(SpotLight3D); } - ERR_FAIL_COND_V(light == NULL, NULL); + ERR_FAIL_COND_V(light == nullptr, nullptr); if (assimp_light->mType != aiLightSource_POINT) { Vector3 pos = Vector3( @@ -1453,15 +1431,15 @@ Spatial *EditorSceneImporterAssimp::create_light( /** * Create camera for the scene */ -Spatial *EditorSceneImporterAssimp::create_camera( +Node3D *EditorSceneImporterAssimp::create_camera( ImportState &state, const String &node_name, Transform &look_at_transform) { aiCamera *camera = state.assimp_scene->mCameras[state.camera_cache[node_name]]; - ERR_FAIL_COND_V(!camera, NULL); + ERR_FAIL_COND_V(!camera, nullptr); - Camera *camera_node = memnew(Camera); - ERR_FAIL_COND_V(!camera_node, NULL); + Camera3D *camera_node = memnew(Camera3D); + ERR_FAIL_COND_V(!camera_node, nullptr); float near = camera->mClipPlaneNear; if (Math::is_equal_approx(near, 0.0f)) { near = 0.1f; @@ -1482,8 +1460,7 @@ Spatial *EditorSceneImporterAssimp::create_camera( void EditorSceneImporterAssimp::_generate_node( ImportState &state, const aiNode *assimp_node) { - - ERR_FAIL_COND(assimp_node == NULL); + ERR_FAIL_COND(assimp_node == nullptr); state.nodes.push_back(assimp_node); String parent_name = AssimpUtils::get_assimp_string(assimp_node->mParent->mName); @@ -1498,7 +1475,7 @@ void EditorSceneImporterAssimp::_generate_node( // is this an armature // parent null // and this is the first bone :) - if (parent_bone == NULL && current_bone) { + if (parent_bone == nullptr && current_bone) { state.armature_nodes.push_back(assimp_node->mParent); print_verbose("found valid armature: " + parent_name); } diff --git a/modules/assimp/editor_scene_importer_assimp.h b/modules/assimp/editor_scene_importer_assimp.h index 4cd50e7681..ab00a6c3aa 100644 --- a/modules/assimp/editor_scene_importer_assimp.h +++ b/modules/assimp/editor_scene_importer_assimp.h @@ -37,9 +37,9 @@ #include "core/vector.h" #include "editor/import/resource_importer_scene.h" #include "editor/project_settings_editor.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" #include "scene/resources/surface_tool.h" @@ -90,29 +90,29 @@ private: Ref<Mesh> _generate_mesh_from_surface_indices(ImportState &state, const Vector<int> &p_surface_indices, const aiNode *assimp_node, Ref<Skin> &skin, - Skeleton *&skeleton_assigned); + Skeleton3D *&skeleton_assigned); // simple object creation functions - Spatial *create_light(ImportState &state, + Node3D *create_light(ImportState &state, const String &node_name, Transform &look_at_transform); - Spatial *create_camera( + Node3D *create_camera( ImportState &state, const String &node_name, Transform &look_at_transform); // non recursive - linear so must not use recursive arguments - MeshInstance *create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform); + MeshInstance3D *create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform); // recursive node generator void _generate_node(ImportState &state, const aiNode *assimp_node); void _insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id, int anim_fps, Ref<Animation> animation, float ticks_per_second, - Skeleton *skeleton, const NodePath &node_path, + Skeleton3D *skeleton, const NodePath &node_path, const String &node_name, aiBone *track_bone); void _import_animation(ImportState &state, int p_animation_index, int p_bake_fps); Node *get_node_by_name(ImportState &state, String name); aiBone *get_bone_from_stack(ImportState &state, aiString name); - Spatial *_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights); + Node3D *_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights); template <class T> T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, AssetImportAnimation::Interpolation p_interp); @@ -138,7 +138,7 @@ public: virtual void get_extensions(List<String> *r_extensions) const; virtual uint32_t get_import_flags() const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); Ref<Image> load_image(ImportState &state, const aiScene *p_scene, String p_path); static void RegenerateBoneStack(ImportState &state); diff --git a/modules/assimp/import_state.h b/modules/assimp/import_state.h index fbbbe23399..4a3bd17acb 100644 --- a/modules/assimp/import_state.h +++ b/modules/assimp/import_state.h @@ -36,9 +36,9 @@ #include "core/vector.h" #include "editor/import/resource_importer_scene.h" #include "editor/project_settings_editor.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" #include "scene/resources/surface_tool.h" @@ -55,9 +55,8 @@ namespace AssimpImporter { * This makes the code simpler and contains useful lookups. */ struct ImportState { - String path; - Spatial *root; + Node3D *root; const aiScene *assimp_scene; uint32_t max_bone_weights; @@ -74,15 +73,15 @@ struct ImportState { // Generation 3 - determinisitic iteration // to lower potential recursion errors List<const aiNode *> nodes; - Map<const aiNode *, Spatial *> flat_node_map; + Map<const aiNode *, Node3D *> flat_node_map; AnimationPlayer *animation_player; // Generation 3 - deterministic armatures // list of armature nodes - flat and simple to parse // assimp node, node in godot List<aiNode *> armature_nodes; - Map<const aiNode *, Skeleton *> armature_skeletons; - Map<aiBone *, Skeleton *> skeleton_bone_map; + Map<const aiNode *, Skeleton3D *> armature_skeletons; + Map<aiBone *, Skeleton3D *> skeleton_bone_map; // Generation 3 - deterministic bone handling // bones from the stack are popped when found // this means we can detect @@ -103,8 +102,8 @@ struct RecursiveState { RecursiveState() {} // do not construct :) RecursiveState( Transform &_node_transform, - Skeleton *_skeleton, - Spatial *_new_node, + Skeleton3D *_skeleton, + Node3D *_new_node, String &_node_name, aiNode *_assimp_node, Node *_parent_node, @@ -118,12 +117,12 @@ struct RecursiveState { bone(_bone) {} Transform node_transform; - Skeleton *skeleton = NULL; - Spatial *new_node = NULL; + Skeleton3D *skeleton = nullptr; + Node3D *new_node = nullptr; String node_name; - aiNode *assimp_node = NULL; - Node *parent_node = NULL; - aiBone *bone = NULL; + aiNode *assimp_node = nullptr; + Node *parent_node = nullptr; + aiBone *bone = nullptr; }; } // namespace AssimpImporter diff --git a/modules/assimp/import_utils.h b/modules/assimp/import_utils.h index 30c00f8765..dc85d06fed 100644 --- a/modules/assimp/import_utils.h +++ b/modules/assimp/import_utils.h @@ -162,7 +162,6 @@ public: } static String get_anim_string_from_assimp(const aiString &p_string) { - String name; name.parse_utf8(p_string.C_Str() /*,p_string.length*/); if (name.find(":") != -1) { @@ -202,20 +201,34 @@ public: */ static float get_fbx_fps(int32_t time_mode, const aiScene *p_scene) { switch (time_mode) { - case AssetImportFbx::TIME_MODE_DEFAULT: return 24; //hack - case AssetImportFbx::TIME_MODE_120: return 120; - case AssetImportFbx::TIME_MODE_100: return 100; - case AssetImportFbx::TIME_MODE_60: return 60; - case AssetImportFbx::TIME_MODE_50: return 50; - case AssetImportFbx::TIME_MODE_48: return 48; - case AssetImportFbx::TIME_MODE_30: return 30; - case AssetImportFbx::TIME_MODE_30_DROP: return 30; - case AssetImportFbx::TIME_MODE_NTSC_DROP_FRAME: return 29.9700262f; - case AssetImportFbx::TIME_MODE_NTSC_FULL_FRAME: return 29.9700262f; - case AssetImportFbx::TIME_MODE_PAL: return 25; - case AssetImportFbx::TIME_MODE_CINEMA: return 24; - case AssetImportFbx::TIME_MODE_1000: return 1000; - case AssetImportFbx::TIME_MODE_CINEMA_ND: return 23.976f; + case AssetImportFbx::TIME_MODE_DEFAULT: + return 24; //hack + case AssetImportFbx::TIME_MODE_120: + return 120; + case AssetImportFbx::TIME_MODE_100: + return 100; + case AssetImportFbx::TIME_MODE_60: + return 60; + case AssetImportFbx::TIME_MODE_50: + return 50; + case AssetImportFbx::TIME_MODE_48: + return 48; + case AssetImportFbx::TIME_MODE_30: + return 30; + case AssetImportFbx::TIME_MODE_30_DROP: + return 30; + case AssetImportFbx::TIME_MODE_NTSC_DROP_FRAME: + return 29.9700262f; + case AssetImportFbx::TIME_MODE_NTSC_FULL_FRAME: + return 29.9700262f; + case AssetImportFbx::TIME_MODE_PAL: + return 25; + case AssetImportFbx::TIME_MODE_CINEMA: + return 24; + case AssetImportFbx::TIME_MODE_1000: + return 1000; + case AssetImportFbx::TIME_MODE_CINEMA_ND: + return 23.976f; case AssetImportFbx::TIME_MODE_CUSTOM: int32_t frame_rate = -1; p_scene->mMetaData->Get("FrameRate", frame_rate); @@ -233,7 +246,7 @@ public: static Transform _get_global_assimp_node_transform(const aiNode *p_current_node) { aiNode const *current_node = p_current_node; Transform xform; - while (current_node != NULL) { + while (current_node != nullptr) { xform = assimp_matrix_transform(current_node->mTransformation) * xform; current_node = current_node->mParent; } @@ -319,7 +332,7 @@ public: */ static void set_texture_mapping_mode(aiTextureMapMode *map_mode, Ref<ImageTexture> texture) { ERR_FAIL_COND(texture.is_null()); - ERR_FAIL_COND(map_mode == NULL); + ERR_FAIL_COND(map_mode == nullptr); // FIXME: Commented out during Vulkan port. /* aiTextureMapMode tex_mode = map_mode[0]; @@ -340,7 +353,6 @@ public: * Load or load from cache image :) */ static Ref<Image> load_image(ImportState &state, const aiScene *p_scene, String p_path) { - Map<String, Ref<Image>>::Element *match = state.path_to_image_cache.find(p_path); // if our cache contains this image then don't bother @@ -358,13 +370,13 @@ public: print_verbose("Open Asset Import: Loading embedded texture " + filename); if (tex->mHeight == 0) { if (tex->CheckFormat("png")) { - ERR_FAIL_COND_V(Image::_png_mem_loader_func == NULL, Ref<Image>()); + ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, Ref<Image>()); Ref<Image> img = Image::_png_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth); ERR_FAIL_COND_V(img.is_null(), Ref<Image>()); state.path_to_image_cache.insert(p_path, img); return img; } else if (tex->CheckFormat("jpg")) { - ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == NULL, Ref<Image>()); + ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, Ref<Image>()); Ref<Image> img = Image::_jpg_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth); ERR_FAIL_COND_V(img.is_null(), Ref<Image>()); state.path_to_image_cache.insert(p_path, img); @@ -440,7 +452,7 @@ public: String &path, AssimpImageData &image_state) { aiString ai_filename = aiString(); - if (AI_SUCCESS == ai_material->GetTexture(texture_type, 0, &ai_filename, NULL, NULL, NULL, NULL, image_state.map_mode)) { + if (AI_SUCCESS == ai_material->GetTexture(texture_type, 0, &ai_filename, nullptr, nullptr, nullptr, nullptr, image_state.map_mode)) { return CreateAssimpTexture(state, ai_filename, filename, path, image_state); } diff --git a/modules/assimp/register_types.cpp b/modules/assimp/register_types.cpp index 3af8827bf9..6cb0fc982f 100644 --- a/modules/assimp/register_types.cpp +++ b/modules/assimp/register_types.cpp @@ -42,7 +42,6 @@ static void _editor_init() { #endif void register_assimp_types() { - #ifdef TOOLS_ENABLED ClassDB::APIType prev_api = ClassDB::get_current_api(); ClassDB::set_current_api(ClassDB::API_EDITOR); diff --git a/modules/assimp/register_types.h b/modules/assimp/register_types.h index f363744c0a..f399a7acc6 100644 --- a/modules/assimp/register_types.h +++ b/modules/assimp/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef ASSIMP_REGISTER_TYPES_H +#define ASSIMP_REGISTER_TYPES_H + void register_assimp_types(); void unregister_assimp_types(); + +#endif // ASSIMP_REGISTER_TYPES_H diff --git a/modules/basis_universal/SCsub b/modules/basis_universal/SCsub index 63324e920b..dc7b176d24 100644 --- a/modules/basis_universal/SCsub +++ b/modules/basis_universal/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_basisu = env_modules.Clone() @@ -9,36 +9,38 @@ env_basisu = env_modules.Clone() # Not unbundled so far since not widespread as shared library thirdparty_dir = "#thirdparty/basis_universal/" tool_sources = [ - "basisu_astc_decomp.cpp", - "basisu_backend.cpp", - "basisu_basis_file.cpp", - "basisu_comp.cpp", - "basisu_enc.cpp", - "basisu_etc.cpp", - "basisu_frontend.cpp", - "basisu_global_selector_palette_helpers.cpp", - "basisu_gpu_texture.cpp", - "basisu_pvrtc1_4.cpp", - "basisu_resample_filters.cpp", - "basisu_resampler.cpp", - "basisu_ssim.cpp", - "lodepng.cpp", + "basisu_astc_decomp.cpp", + "basisu_backend.cpp", + "basisu_basis_file.cpp", + "basisu_comp.cpp", + "basisu_enc.cpp", + "basisu_etc.cpp", + "basisu_frontend.cpp", + "basisu_global_selector_palette_helpers.cpp", + "basisu_gpu_texture.cpp", + "basisu_pvrtc1_4.cpp", + "basisu_resample_filters.cpp", + "basisu_resampler.cpp", + "basisu_ssim.cpp", + "lodepng.cpp", ] tool_sources = [thirdparty_dir + file for file in tool_sources] transcoder_sources = [thirdparty_dir + "transcoder/basisu_transcoder.cpp"] # Treat Basis headers as system headers to avoid raising warnings. Not supported on MSVC. if not env.msvc: - env_basisu.Append(CPPFLAGS=['-isystem', Dir(thirdparty_dir).path, '-isystem', Dir(thirdparty_dir + "transcoder").path]) + env_basisu.Append( + CPPFLAGS=["-isystem", Dir(thirdparty_dir).path, "-isystem", Dir(thirdparty_dir + "transcoder").path] + ) else: env_basisu.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "transcoder"]) -if env['target'] == "debug": - env_basisu.Append(CPPFLAGS=["-DBASISU_DEVEL_MESSAGES=1", "-DBASISD_ENABLE_DEBUG_FLAGS=1"]) +if env["target"] == "debug": + env_basisu.Append(CPPFLAGS=["-DBASISU_DEVEL_MESSAGES=1", "-DBASISD_ENABLE_DEBUG_FLAGS=1"]) env_thirdparty = env_basisu.Clone() env_thirdparty.disable_warnings() -if env['tools']: +if env["tools"]: env_thirdparty.add_source_files(env.modules_sources, tool_sources) env_thirdparty.add_source_files(env.modules_sources, transcoder_sources) diff --git a/modules/basis_universal/config.py b/modules/basis_universal/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/basis_universal/config.py +++ b/modules/basis_universal/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/basis_universal/register_types.cpp b/modules/basis_universal/register_types.cpp index 062b5b59f8..27b299a65d 100644 --- a/modules/basis_universal/register_types.cpp +++ b/modules/basis_universal/register_types.cpp @@ -31,7 +31,7 @@ #include "register_types.h" #include "core/os/os.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #include "texture_basisu.h" #ifdef TOOLS_ENABLED @@ -54,7 +54,6 @@ basist::etc1_global_selector_codebook *sel_codebook = nullptr; #ifdef TOOLS_ENABLED static Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedChannels p_channels) { - Vector<uint8_t> budata; { @@ -98,7 +97,7 @@ static Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image:: params.m_mip_gen = false; //sorry, please some day support provided mipmaps. params.m_source_images.push_back(buimg); - BasisDecompressFormat decompress_format; + BasisDecompressFormat decompress_format = BASIS_DECOMPRESS_RG; params.m_check_for_alpha = false; switch (p_channels) { @@ -158,34 +157,33 @@ static Ref<Image> basis_universal_unpacker(const Vector<uint8_t> &p_buffer) { const uint8_t *ptr = r; int size = p_buffer.size(); - basist::transcoder_texture_format format; - Image::Format imgfmt; + basist::transcoder_texture_format format = basist::transcoder_texture_format::cTFTotalTextureFormats; + Image::Format imgfmt = Image::FORMAT_MAX; switch (*(uint32_t *)(ptr)) { case BASIS_DECOMPRESS_RG: { - - if (VS::get_singleton()->has_os_feature("rgtc")) { + if (RS::get_singleton()->has_os_feature("rgtc")) { format = basist::transcoder_texture_format::cTFBC5; // get this from renderer imgfmt = Image::FORMAT_RGTC_RG; - } else if (VS::get_singleton()->has_os_feature("etc2")) { + } else if (RS::get_singleton()->has_os_feature("etc2")) { //unfortunately, basis universal does not support // ERR_FAIL_V(image); //unimplemented here //format = basist::transcoder_texture_format::cTFETC1; // get this from renderer //imgfmt = Image::FORMAT_RGTC_RG; } else { - //decompress + // FIXME: There wasn't anything here, but then imgformat is used uninitialized. + ERR_FAIL_V(image); } } break; case BASIS_DECOMPRESS_RGB: { - if (VS::get_singleton()->has_os_feature("bptc")) { + if (RS::get_singleton()->has_os_feature("bptc")) { format = basist::transcoder_texture_format::cTFBC7_M6_OPAQUE_ONLY; // get this from renderer imgfmt = Image::FORMAT_BPTC_RGBA; - } else if (VS::get_singleton()->has_os_feature("s3tc")) { + } else if (RS::get_singleton()->has_os_feature("s3tc")) { format = basist::transcoder_texture_format::cTFBC1; // get this from renderer imgfmt = Image::FORMAT_DXT1; - } else if (VS::get_singleton()->has_os_feature("etc")) { - + } else if (RS::get_singleton()->has_os_feature("etc")) { format = basist::transcoder_texture_format::cTFETC1; // get this from renderer imgfmt = Image::FORMAT_ETC; } else { @@ -195,13 +193,13 @@ static Ref<Image> basis_universal_unpacker(const Vector<uint8_t> &p_buffer) { } break; case BASIS_DECOMPRESS_RGBA: { - if (VS::get_singleton()->has_os_feature("bptc")) { + if (RS::get_singleton()->has_os_feature("bptc")) { format = basist::transcoder_texture_format::cTFBC7_M5; // get this from renderer imgfmt = Image::FORMAT_BPTC_RGBA; - } else if (VS::get_singleton()->has_os_feature("s3tc")) { + } else if (RS::get_singleton()->has_os_feature("s3tc")) { format = basist::transcoder_texture_format::cTFBC3; // get this from renderer imgfmt = Image::FORMAT_DXT5; - } else if (VS::get_singleton()->has_os_feature("etc2")) { + } else if (RS::get_singleton()->has_os_feature("etc2")) { format = basist::transcoder_texture_format::cTFETC2; // get this from renderer imgfmt = Image::FORMAT_ETC2_RGBA8; } else { @@ -211,10 +209,10 @@ static Ref<Image> basis_universal_unpacker(const Vector<uint8_t> &p_buffer) { } } break; case BASIS_DECOMPRESS_RG_AS_RA: { - if (VS::get_singleton()->has_os_feature("s3tc")) { + if (RS::get_singleton()->has_os_feature("s3tc")) { format = basist::transcoder_texture_format::cTFBC3; // get this from renderer imgfmt = Image::FORMAT_DXT5_RA_AS_RG; - } else if (VS::get_singleton()->has_os_feature("etc2")) { + } else if (RS::get_singleton()->has_os_feature("etc2")) { format = basist::transcoder_texture_format::cTFETC2; // get this from renderer imgfmt = Image::FORMAT_ETC2_RGBA8; } else { @@ -228,7 +226,7 @@ static Ref<Image> basis_universal_unpacker(const Vector<uint8_t> &p_buffer) { ptr += 4; size -= 4; - basist::basisu_transcoder tr(NULL); + basist::basisu_transcoder tr(nullptr); ERR_FAIL_COND_V(!tr.validate_header(ptr, size), image); @@ -242,13 +240,13 @@ static Ref<Image> basis_universal_unpacker(const Vector<uint8_t> &p_buffer) { { uint8_t *w = gpudata.ptrw(); uint8_t *dst = w; - for (int i = 0; i < gpudata.size(); i++) + for (int i = 0; i < gpudata.size(); i++) { dst[i] = 0x00; + } int ofs = 0; tr.start_transcoding(ptr, size); for (uint32_t i = 0; i < info.m_total_levels; i++) { - basist::basisu_image_level_info level; tr.get_image_level_info(ptr, size, level, 0, i); @@ -278,10 +276,9 @@ void register_basis_universal_types() { } void unregister_basis_universal_types() { - #ifdef TOOLS_ENABLED delete sel_codebook; - Image::basis_universal_packer = NULL; + Image::basis_universal_packer = nullptr; #endif - Image::basis_universal_unpacker = NULL; + Image::basis_universal_unpacker = nullptr; } diff --git a/modules/basis_universal/register_types.h b/modules/basis_universal/register_types.h index 977374fbfc..5053dc27ce 100644 --- a/modules/basis_universal/register_types.h +++ b/modules/basis_universal/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef BASIS_UNIVERSAL_REGISTER_TYPES_H +#define BASIS_UNIVERSAL_REGISTER_TYPES_H + void register_basis_universal_types(); void unregister_basis_universal_types(); + +#endif // BASIS_UNIVERSAL_REGISTER_TYPES_H diff --git a/modules/basis_universal/texture_basisu.cpp b/modules/basis_universal/texture_basisu.cpp index 12f3241c98..2ed0340927 100644 --- a/modules/basis_universal/texture_basisu.cpp +++ b/modules/basis_universal/texture_basisu.cpp @@ -72,7 +72,7 @@ bool TextureBasisU::has_alpha() const { void TextureBasisU::set_flags(uint32_t p_flags) { flags = p_flags; - VisualServer::get_singleton()->texture_set_flags(texture, p_flags); + RenderingServer::get_singleton()->texture_set_flags(texture, p_flags); }; uint32_t TextureBasisU::get_flags() const { @@ -105,7 +105,7 @@ void TextureBasisU::set_basisu_data(const Vector<uint8_t>& p_data) { imgfmt = Image::FORMAT_ETC2_RGBA8; }; - basist::basisu_transcoder tr(NULL); + basist::basisu_transcoder tr(nullptr); ERR_FAIL_COND(!tr.validate_header(ptr, size)); @@ -144,8 +144,8 @@ void TextureBasisU::set_basisu_data(const Vector<uint8_t>& p_data) { img.instance(); img->create(info.m_width, info.m_height, info.m_total_levels > 1, imgfmt, gpudata); - VisualServer::get_singleton()->texture_allocate(texture, tex_size.x, tex_size.y, 0, img->get_format(), VS::TEXTURE_TYPE_2D, flags); - VisualServer::get_singleton()->texture_set_data(texture, img); + RenderingServer::get_singleton()->texture_allocate(texture, tex_size.x, tex_size.y, 0, img->get_format(), RS::TEXTURE_TYPE_2D, flags); + RenderingServer::get_singleton()->texture_set_data(texture, img); }; Error TextureBasisU::import(const Ref<Image>& p_img) { @@ -221,13 +221,13 @@ Vector<uint8_t> TextureBasisU::get_basisu_data() const { TextureBasisU::TextureBasisU() { flags = FLAGS_DEFAULT; - texture = VisualServer::get_singleton()->texture_create(); + texture = RenderingServer::get_singleton()->texture_create(); }; TextureBasisU::~TextureBasisU() { - VisualServer::get_singleton()->free(texture); + RenderingServer::get_singleton()->free(texture); }; #endif diff --git a/modules/bmp/SCsub b/modules/bmp/SCsub index e7da7cf108..4f3405ff28 100644 --- a/modules/bmp/SCsub +++ b/modules/bmp/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_bmp = env_modules.Clone() diff --git a/modules/bmp/config.py b/modules/bmp/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/bmp/config.py +++ b/modules/bmp/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp index 71e5076e78..ac4e534983 100644 --- a/modules/bmp/image_loader_bmp.cpp +++ b/modules/bmp/image_loader_bmp.cpp @@ -35,11 +35,11 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, const uint8_t *p_color_buffer, const uint32_t color_table_size, const bmp_header_s &p_header) { - Error err = OK; - if (p_buffer == NULL) + if (p_buffer == nullptr) { err = FAILED; + } if (err == OK) { size_t index = 0; @@ -60,7 +60,6 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, ERR_FAIL_COND_V(height % 2 != 0, ERR_UNAVAILABLE); } else if (bits_per_pixel == 16) { - ERR_FAIL_V(ERR_UNAVAILABLE); } @@ -151,9 +150,9 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, line -= line_width; } - if (p_color_buffer == NULL || color_table_size == 0) { // regular pixels + if (p_color_buffer == nullptr || color_table_size == 0) { // regular pixels - p_image->create(width, height, 0, Image::FORMAT_RGBA8, data); + p_image->create(width, height, false, Image::FORMAT_RGBA8, data); } else { // data is in indexed format, extend it @@ -193,7 +192,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, dest += 4; } - p_image->create(width, height, 0, Image::FORMAT_RGBA8, extended_data); + p_image->create(width, height, false, Image::FORMAT_RGBA8, extended_data); } } return err; @@ -201,7 +200,6 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image, Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - bmp_header_s bmp_header; Error err = ERR_INVALID_DATA; @@ -290,7 +288,6 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f, void ImageLoaderBMP::get_recognized_extensions( List<String> *p_extensions) const { - p_extensions->push_back("bmp"); } diff --git a/modules/bmp/register_types.cpp b/modules/bmp/register_types.cpp index d5cc6c5eb3..6220e956d6 100644 --- a/modules/bmp/register_types.cpp +++ b/modules/bmp/register_types.cpp @@ -32,7 +32,7 @@ #include "image_loader_bmp.h" -static ImageLoaderBMP *image_loader_bmp = NULL; +static ImageLoaderBMP *image_loader_bmp = nullptr; void register_bmp_types() { image_loader_bmp = memnew(ImageLoaderBMP); diff --git a/modules/bmp/register_types.h b/modules/bmp/register_types.h index 398716eaa1..e7561dc32d 100644 --- a/modules/bmp/register_types.h +++ b/modules/bmp/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef BMP_REGISTER_TYPES_H +#define BMP_REGISTER_TYPES_H + void register_bmp_types(); void unregister_bmp_types(); + +#endif // BMP_REGISTER_TYPES_H diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub index 02d0a31a69..b853ebfc63 100644 --- a/modules/bullet/SCsub +++ b/modules/bullet/SCsub @@ -1,213 +1,211 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_bullet = env_modules.Clone() # Thirdparty source files -if env['builtin_bullet']: +if env["builtin_bullet"]: # Build only version 2 for now (as of 2.89) # Sync file list with relevant upstream CMakeLists.txt for each folder. thirdparty_dir = "#thirdparty/bullet/" bullet2_src = [ # BulletCollision - "BulletCollision/BroadphaseCollision/btAxisSweep3.cpp" - , "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp" - , "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp" - , "BulletCollision/BroadphaseCollision/btDbvt.cpp" - , "BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp" - , "BulletCollision/BroadphaseCollision/btDispatcher.cpp" - , "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp" - , "BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp" - , "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp" - , "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp" - , "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp" - , "BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp" - , "BulletCollision/CollisionDispatch/btCollisionObject.cpp" - , "BulletCollision/CollisionDispatch/btCollisionWorld.cpp" - , "BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp" - , "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp" - , "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btGhostObject.cpp" - , "BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp" - , "BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp" - , "BulletCollision/CollisionDispatch/btManifoldResult.cpp" - , "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp" - , "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp" - , "BulletCollision/CollisionDispatch/btUnionFind.cpp" - , "BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp" - , "BulletCollision/CollisionShapes/btBoxShape.cpp" - , "BulletCollision/CollisionShapes/btBox2dShape.cpp" - , "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp" - , "BulletCollision/CollisionShapes/btCapsuleShape.cpp" - , "BulletCollision/CollisionShapes/btCollisionShape.cpp" - , "BulletCollision/CollisionShapes/btCompoundShape.cpp" - , "BulletCollision/CollisionShapes/btConcaveShape.cpp" - , "BulletCollision/CollisionShapes/btConeShape.cpp" - , "BulletCollision/CollisionShapes/btConvexHullShape.cpp" - , "BulletCollision/CollisionShapes/btConvexInternalShape.cpp" - , "BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp" - , "BulletCollision/CollisionShapes/btConvexPolyhedron.cpp" - , "BulletCollision/CollisionShapes/btConvexShape.cpp" - , "BulletCollision/CollisionShapes/btConvex2dShape.cpp" - , "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp" - , "BulletCollision/CollisionShapes/btCylinderShape.cpp" - , "BulletCollision/CollisionShapes/btEmptyShape.cpp" - , "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp" - , "BulletCollision/CollisionShapes/btMiniSDF.cpp" - , "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp" - , "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp" - , "BulletCollision/CollisionShapes/btMultiSphereShape.cpp" - , "BulletCollision/CollisionShapes/btOptimizedBvh.cpp" - , "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp" - , "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp" - , "BulletCollision/CollisionShapes/btSdfCollisionShape.cpp" - , "BulletCollision/CollisionShapes/btShapeHull.cpp" - , "BulletCollision/CollisionShapes/btSphereShape.cpp" - , "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp" - , "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp" - , "BulletCollision/CollisionShapes/btTetrahedronShape.cpp" - , "BulletCollision/CollisionShapes/btTriangleBuffer.cpp" - , "BulletCollision/CollisionShapes/btTriangleCallback.cpp" - , "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp" - , "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp" - , "BulletCollision/CollisionShapes/btTriangleMesh.cpp" - , "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp" - , "BulletCollision/CollisionShapes/btUniformScalingShape.cpp" - , "BulletCollision/Gimpact/btContactProcessing.cpp" - , "BulletCollision/Gimpact/btGenericPoolAllocator.cpp" - , "BulletCollision/Gimpact/btGImpactBvh.cpp" - , "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp" - , "BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp" - , "BulletCollision/Gimpact/btGImpactShape.cpp" - , "BulletCollision/Gimpact/btTriangleShapeEx.cpp" - , "BulletCollision/Gimpact/gim_box_set.cpp" - , "BulletCollision/Gimpact/gim_contact.cpp" - , "BulletCollision/Gimpact/gim_memory.cpp" - , "BulletCollision/Gimpact/gim_tri_collision.cpp" - , "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp" - , "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp" - , "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp" - , "BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp" - , "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp" - , "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp" - , "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp" - , "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp" - , "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp" - , "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp" - , "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp" - , "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp" - + "BulletCollision/BroadphaseCollision/btAxisSweep3.cpp", + "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", + "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp", + "BulletCollision/BroadphaseCollision/btDbvt.cpp", + "BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp", + "BulletCollision/BroadphaseCollision/btDispatcher.cpp", + "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", + "BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp", + "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", + "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp", + "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp", + "BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp", + "BulletCollision/CollisionDispatch/btCollisionObject.cpp", + "BulletCollision/CollisionDispatch/btCollisionWorld.cpp", + "BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp", + "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp", + "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btGhostObject.cpp", + "BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp", + "BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp", + "BulletCollision/CollisionDispatch/btManifoldResult.cpp", + "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp", + "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btUnionFind.cpp", + "BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp", + "BulletCollision/CollisionShapes/btBoxShape.cpp", + "BulletCollision/CollisionShapes/btBox2dShape.cpp", + "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btCapsuleShape.cpp", + "BulletCollision/CollisionShapes/btCollisionShape.cpp", + "BulletCollision/CollisionShapes/btCompoundShape.cpp", + "BulletCollision/CollisionShapes/btConcaveShape.cpp", + "BulletCollision/CollisionShapes/btConeShape.cpp", + "BulletCollision/CollisionShapes/btConvexHullShape.cpp", + "BulletCollision/CollisionShapes/btConvexInternalShape.cpp", + "BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp", + "BulletCollision/CollisionShapes/btConvexPolyhedron.cpp", + "BulletCollision/CollisionShapes/btConvexShape.cpp", + "BulletCollision/CollisionShapes/btConvex2dShape.cpp", + "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btCylinderShape.cpp", + "BulletCollision/CollisionShapes/btEmptyShape.cpp", + "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp", + "BulletCollision/CollisionShapes/btMiniSDF.cpp", + "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp", + "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btMultiSphereShape.cpp", + "BulletCollision/CollisionShapes/btOptimizedBvh.cpp", + "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp", + "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btSdfCollisionShape.cpp", + "BulletCollision/CollisionShapes/btShapeHull.cpp", + "BulletCollision/CollisionShapes/btSphereShape.cpp", + "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp", + "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp", + "BulletCollision/CollisionShapes/btTetrahedronShape.cpp", + "BulletCollision/CollisionShapes/btTriangleBuffer.cpp", + "BulletCollision/CollisionShapes/btTriangleCallback.cpp", + "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp", + "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp", + "BulletCollision/CollisionShapes/btTriangleMesh.cpp", + "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btUniformScalingShape.cpp", + "BulletCollision/Gimpact/btContactProcessing.cpp", + "BulletCollision/Gimpact/btGenericPoolAllocator.cpp", + "BulletCollision/Gimpact/btGImpactBvh.cpp", + "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp", + "BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp", + "BulletCollision/Gimpact/btGImpactShape.cpp", + "BulletCollision/Gimpact/btTriangleShapeEx.cpp", + "BulletCollision/Gimpact/gim_box_set.cpp", + "BulletCollision/Gimpact/gim_contact.cpp", + "BulletCollision/Gimpact/gim_memory.cpp", + "BulletCollision/Gimpact/gim_tri_collision.cpp", + "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp", + "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp", + "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp", + "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp", + "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp", + "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp", + "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp", # BulletDynamics - , "BulletDynamics/Character/btKinematicCharacterController.cpp" - , "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btContactConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btFixedConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btGearConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp" - , "BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp" - , "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp" - , "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp" - , "BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp" - , "BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp" - , "BulletDynamics/ConstraintSolver/btSliderConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp" - , "BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp" - , "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp" - , "BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp" - , "BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp" - , "BulletDynamics/Dynamics/btRigidBody.cpp" - , "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp" - #, "BulletDynamics/Dynamics/Bullet-C-API.cpp" - , "BulletDynamics/Vehicle/btRaycastVehicle.cpp" - , "BulletDynamics/Vehicle/btWheelInfo.cpp" - , "BulletDynamics/Featherstone/btMultiBody.cpp" - , "BulletDynamics/Featherstone/btMultiBodyConstraint.cpp" - , "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp" - , "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp" - , "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp" - , "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp" - , "BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp" - , "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp" - , "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp" - , "BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp" - , "BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp" - , "BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp" - , "BulletDynamics/MLCPSolvers/btDantzigLCP.cpp" - , "BulletDynamics/MLCPSolvers/btMLCPSolver.cpp" - , "BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp" - + "BulletDynamics/Character/btKinematicCharacterController.cpp", + "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp", + "BulletDynamics/ConstraintSolver/btContactConstraint.cpp", + "BulletDynamics/ConstraintSolver/btFixedConstraint.cpp", + "BulletDynamics/ConstraintSolver/btGearConstraint.cpp", + "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp", + "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp", + "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp", + "BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp", + "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp", + "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp", + "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp", + "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp", + "BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp", + "BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp", + "BulletDynamics/ConstraintSolver/btSliderConstraint.cpp", + "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp", + "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp", + "BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp", + "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp", + "BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp", + "BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp", + "BulletDynamics/Dynamics/btRigidBody.cpp", + "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp", + # "BulletDynamics/Dynamics/Bullet-C-API.cpp", + "BulletDynamics/Vehicle/btRaycastVehicle.cpp", + "BulletDynamics/Vehicle/btWheelInfo.cpp", + "BulletDynamics/Featherstone/btMultiBody.cpp", + "BulletDynamics/Featherstone/btMultiBodyConstraint.cpp", + "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp", + "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp", + "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp", + "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp", + "BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp", + "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp", + "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp", + "BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp", + "BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp", + "BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp", + "BulletDynamics/MLCPSolvers/btDantzigLCP.cpp", + "BulletDynamics/MLCPSolvers/btMLCPSolver.cpp", + "BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp", # BulletInverseDynamics - , "BulletInverseDynamics/IDMath.cpp" - , "BulletInverseDynamics/MultiBodyTree.cpp" - , "BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp" - , "BulletInverseDynamics/details/MultiBodyTreeImpl.cpp" - + "BulletInverseDynamics/IDMath.cpp", + "BulletInverseDynamics/MultiBodyTree.cpp", + "BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp", + "BulletInverseDynamics/details/MultiBodyTreeImpl.cpp", # BulletSoftBody - , "BulletSoftBody/btSoftBody.cpp" - , "BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp" - , "BulletSoftBody/btSoftBodyHelpers.cpp" - , "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp" - , "BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp" - , "BulletSoftBody/btSoftRigidDynamicsWorld.cpp" - , "BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp" - , "BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp" - , "BulletSoftBody/btDefaultSoftBodySolver.cpp" - , "BulletSoftBody/btDeformableBackwardEulerObjective.cpp" - , "BulletSoftBody/btDeformableBodySolver.cpp" - , "BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp" - , "BulletSoftBody/btDeformableContactProjection.cpp" - , "BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp" - , "BulletSoftBody/btDeformableContactConstraint.cpp" - + "BulletSoftBody/btSoftBody.cpp", + "BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp", + "BulletSoftBody/btSoftBodyHelpers.cpp", + "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp", + "BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp", + "BulletSoftBody/btSoftRigidDynamicsWorld.cpp", + "BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp", + "BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp", + "BulletSoftBody/btDefaultSoftBodySolver.cpp", + "BulletSoftBody/btDeformableBackwardEulerObjective.cpp", + "BulletSoftBody/btDeformableBodySolver.cpp", + "BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp", + "BulletSoftBody/btDeformableContactProjection.cpp", + "BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp", + "BulletSoftBody/btDeformableContactConstraint.cpp", + "BulletSoftBody/poly34.cpp", # clew - , "clew/clew.c" - + "clew/clew.c", # LinearMath - , "LinearMath/btAlignedAllocator.cpp" - , "LinearMath/btConvexHull.cpp" - , "LinearMath/btConvexHullComputer.cpp" - , "LinearMath/btGeometryUtil.cpp" - , "LinearMath/btPolarDecomposition.cpp" - , "LinearMath/btQuickprof.cpp" - , "LinearMath/btSerializer.cpp" - , "LinearMath/btSerializer64.cpp" - , "LinearMath/btThreads.cpp" - , "LinearMath/btVector3.cpp" - , "LinearMath/TaskScheduler/btTaskScheduler.cpp" - , "LinearMath/TaskScheduler/btThreadSupportPosix.cpp" - , "LinearMath/TaskScheduler/btThreadSupportWin32.cpp" + "LinearMath/btAlignedAllocator.cpp", + "LinearMath/btConvexHull.cpp", + "LinearMath/btConvexHullComputer.cpp", + "LinearMath/btGeometryUtil.cpp", + "LinearMath/btPolarDecomposition.cpp", + "LinearMath/btQuickprof.cpp", + "LinearMath/btSerializer.cpp", + "LinearMath/btSerializer64.cpp", + "LinearMath/btThreads.cpp", + "LinearMath/btVector3.cpp", + "LinearMath/TaskScheduler/btTaskScheduler.cpp", + "LinearMath/TaskScheduler/btThreadSupportPosix.cpp", + "LinearMath/TaskScheduler/btThreadSupportWin32.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in bullet2_src] # Treat Bullet headers as system headers to avoid raising warnings. Not supported on MSVC. if not env.msvc: - env_bullet.Append(CPPFLAGS=['-isystem', Dir(thirdparty_dir).path]) + env_bullet.Append(CPPFLAGS=["-isystem", Dir(thirdparty_dir).path]) else: env_bullet.Prepend(CPPPATH=[thirdparty_dir]) # if env['target'] == "debug" or env['target'] == "release_debug": # env_bullet.Append(CPPDEFINES=['BT_DEBUG']) + env_bullet.Append(CPPDEFINES=["BT_USE_OLD_DAMPING_METHOD"]) + env_thirdparty = env_bullet.Clone() env_thirdparty.disable_warnings() env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources) diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp index e8a5c1475a..79d8e252f0 100644 --- a/modules/bullet/area_bullet.cpp +++ b/modules/bullet/area_bullet.cpp @@ -44,19 +44,7 @@ */ AreaBullet::AreaBullet() : - RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_AREA), - monitorable(true), - spOv_mode(PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED), - spOv_gravityPoint(false), - spOv_gravityPointDistanceScale(0), - spOv_gravityPointAttenuation(1), - spOv_gravityVec(0, -1, 0), - spOv_gravityMag(10), - spOv_linearDump(0.1), - spOv_angularDump(1), - spOv_priority(0), - isScratched(false) { - + RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_AREA) { btGhost = bulletnew(btGhostObject); reload_shapes(); setupBulletCollisionObject(btGhost); @@ -64,19 +52,22 @@ AreaBullet::AreaBullet() : /// In order to use collision objects as trigger, you have to disable the collision response. set_collision_enabled(false); - for (int i = 0; i < 5; ++i) + for (int i = 0; i < 5; ++i) { call_event_res_ptr[i] = &call_event_res[i]; + } } AreaBullet::~AreaBullet() { // signal are handled by godot, so just clear without notify - for (int i = overlappingObjects.size() - 1; 0 <= i; --i) + for (int i = overlappingObjects.size() - 1; 0 <= i; --i) { overlappingObjects[i].object->on_exit_area(this); + } } void AreaBullet::dispatch_callbacks() { - if (!isScratched) + if (!isScratched) { return; + } isScratched = false; // Reverse order because I've to remove EXIT objects @@ -86,11 +77,11 @@ void AreaBullet::dispatch_callbacks() { switch (otherObj.state) { case OVERLAP_STATE_ENTER: otherObj.state = OVERLAP_STATE_INSIDE; - call_event(otherObj.object, PhysicsServer::AREA_BODY_ADDED); + call_event(otherObj.object, PhysicsServer3D::AREA_BODY_ADDED); otherObj.object->on_enter_area(this); break; case OVERLAP_STATE_EXIT: - call_event(otherObj.object, PhysicsServer::AREA_BODY_REMOVED); + call_event(otherObj.object, PhysicsServer3D::AREA_BODY_REMOVED); otherObj.object->on_exit_area(this); overlappingObjects.remove(i); // Remove after callback break; @@ -101,8 +92,7 @@ void AreaBullet::dispatch_callbacks() { } } -void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer::AreaBodyStatus p_status) { - +void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status) { InOutEventCallback &event = eventsCallbacks[static_cast<int>(p_otherObject->getType())]; Object *areaGodoObject = ObjectDB::get_instance(event.event_callback_id); @@ -122,15 +112,17 @@ void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer: } void AreaBullet::scratch() { - if (isScratched) + if (isScratched) { return; + } isScratched = true; } void AreaBullet::clear_overlaps(bool p_notify) { for (int i = overlappingObjects.size() - 1; 0 <= i; --i) { - if (p_notify) - call_event(overlappingObjects[i].object, PhysicsServer::AREA_BODY_REMOVED); + if (p_notify) { + call_event(overlappingObjects[i].object, PhysicsServer3D::AREA_BODY_REMOVED); + } overlappingObjects[i].object->on_exit_area(this); } overlappingObjects.clear(); @@ -139,8 +131,9 @@ void AreaBullet::clear_overlaps(bool p_notify) { void AreaBullet::remove_overlap(CollisionObjectBullet *p_object, bool p_notify) { for (int i = overlappingObjects.size() - 1; 0 <= i; --i) { if (overlappingObjects[i].object == p_object) { - if (p_notify) - call_event(overlappingObjects[i].object, PhysicsServer::AREA_BODY_REMOVED); + if (p_notify) { + call_event(overlappingObjects[i].object, PhysicsServer3D::AREA_BODY_REMOVED); + } overlappingObjects[i].object->on_exit_area(this); overlappingObjects.remove(i); break; @@ -218,30 +211,30 @@ void AreaBullet::put_overlap_as_inside(int p_index) { } } -void AreaBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value) { +void AreaBullet::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: + case PhysicsServer3D::AREA_PARAM_GRAVITY: set_spOv_gravityMag(p_value); break; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: set_spOv_gravityVec(p_value); break; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: set_spOv_linearDump(p_value); break; - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: set_spOv_angularDump(p_value); break; - case PhysicsServer::AREA_PARAM_PRIORITY: + case PhysicsServer3D::AREA_PARAM_PRIORITY: set_spOv_priority(p_value); break; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: set_spOv_gravityPoint(p_value); break; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: set_spOv_gravityPointDistanceScale(p_value); break; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: set_spOv_gravityPointAttenuation(p_value); break; default: @@ -249,23 +242,23 @@ void AreaBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant & } } -Variant AreaBullet::get_param(PhysicsServer::AreaParameter p_param) const { +Variant AreaBullet::get_param(PhysicsServer3D::AreaParameter p_param) const { switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: + case PhysicsServer3D::AREA_PARAM_GRAVITY: return spOv_gravityMag; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: return spOv_gravityVec; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: return spOv_linearDump; - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: return spOv_angularDump; - case PhysicsServer::AREA_PARAM_PRIORITY: + case PhysicsServer3D::AREA_PARAM_PRIORITY: return spOv_priority; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: return spOv_gravityPoint; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return spOv_gravityPointDistanceScale; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return spOv_gravityPointAttenuation; default: WARN_PRINT("Area doesn't support this parameter in the Bullet backend: " + itos(p_param)); diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h index 18888c6725..cde889c1ba 100644 --- a/modules/bullet/area_bullet.h +++ b/modules/bullet/area_bullet.h @@ -33,7 +33,7 @@ #include "collision_object_bullet.h" #include "core/vector.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include "space_bullet.h" /** @@ -61,12 +61,10 @@ public: }; struct OverlappingObjectData { - CollisionObjectBullet *object; - OverlapState state; + CollisionObjectBullet *object = nullptr; + OverlapState state = OVERLAP_STATE_ENTER; - OverlappingObjectData() : - object(NULL), - state(OVERLAP_STATE_ENTER) {} + OverlappingObjectData() {} OverlappingObjectData(CollisionObjectBullet *p_object, OverlapState p_state) : object(p_object), state(p_state) {} @@ -86,19 +84,19 @@ private: btGhostObject *btGhost; Vector<OverlappingObjectData> overlappingObjects; - bool monitorable; + bool monitorable = true; - PhysicsServer::AreaSpaceOverrideMode spOv_mode; - bool spOv_gravityPoint; - real_t spOv_gravityPointDistanceScale; - real_t spOv_gravityPointAttenuation; - Vector3 spOv_gravityVec; - real_t spOv_gravityMag; - real_t spOv_linearDump; - real_t spOv_angularDump; - int spOv_priority; + PhysicsServer3D::AreaSpaceOverrideMode spOv_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + bool spOv_gravityPoint = false; + real_t spOv_gravityPointDistanceScale = 0; + real_t spOv_gravityPointAttenuation = 1; + Vector3 spOv_gravityVec = Vector3(0, -1, 0); + real_t spOv_gravityMag = 10; + real_t spOv_linearDump = 0.1; + real_t spOv_angularDump = 1; + int spOv_priority = 0; - bool isScratched; + bool isScratched = false; InOutEventCallback eventsCallbacks[2]; @@ -114,8 +112,8 @@ public: bool is_monitoring() const; - _FORCE_INLINE_ void set_spOv_mode(PhysicsServer::AreaSpaceOverrideMode p_mode) { spOv_mode = p_mode; } - _FORCE_INLINE_ PhysicsServer::AreaSpaceOverrideMode get_spOv_mode() { return spOv_mode; } + _FORCE_INLINE_ void set_spOv_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) { spOv_mode = p_mode; } + _FORCE_INLINE_ PhysicsServer3D::AreaSpaceOverrideMode get_spOv_mode() { return spOv_mode; } _FORCE_INLINE_ void set_spOv_gravityPoint(bool p_isGP) { spOv_gravityPoint = p_isGP; } _FORCE_INLINE_ bool is_spOv_gravityPoint() { return spOv_gravityPoint; } @@ -146,7 +144,7 @@ public: virtual void set_space(SpaceBullet *p_space); virtual void dispatch_callbacks(); - void call_event(CollisionObjectBullet *p_otherObject, PhysicsServer::AreaBodyStatus p_status); + void call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status); void set_on_state_change(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); void scratch(); @@ -162,8 +160,8 @@ public: void put_overlap_as_exit(int p_index); void put_overlap_as_inside(int p_index); - void set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value); - Variant get_param(PhysicsServer::AreaParameter p_param) const; + void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); + Variant get_param(PhysicsServer3D::AreaParameter p_param) const; void set_event_callback(Type p_callbackObjectType, ObjectID p_id, const StringName &p_method); bool has_event_callback(Type p_callbackObjectType); diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp index 4071723a3e..a754ca6a89 100644 --- a/modules/bullet/btRayShape.cpp +++ b/modules/bullet/btRayShape.cpp @@ -43,13 +43,13 @@ btRayShape::btRayShape(btScalar length) : m_shapeAxis(0, 0, 1) { m_shapeType = CUSTOM_CONVEX_SHAPE_TYPE; setLength(length); + slipsOnSlope = false; } btRayShape::~btRayShape() { } void btRayShape::setLength(btScalar p_length) { - m_length = p_length; reload_cache(); } @@ -60,7 +60,6 @@ void btRayShape::setMargin(btScalar margin) { } void btRayShape::setSlipsOnSlope(bool p_slipsOnSlope) { - slipsOnSlope = p_slipsOnSlope; } @@ -69,10 +68,11 @@ btVector3 btRayShape::localGetSupportingVertex(const btVector3 &vec) const { } btVector3 btRayShape::localGetSupportingVertexWithoutMargin(const btVector3 &vec) const { - if (vec.z() > 0) + if (vec.z() > 0) { return m_shapeAxis * m_cacheScaledLength; - else + } else { return btVector3(0, 0, 0); + } } void btRayShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3 *vectors, btVector3 *supportVerticesOut, int numVectors) const { @@ -100,7 +100,6 @@ void btRayShape::getPreferredPenetrationDirection(int index, btVector3 &penetrat } void btRayShape::reload_cache() { - m_cacheScaledLength = m_length * m_localScaling[2]; m_cacheSupportPoint.setIdentity(); diff --git a/modules/bullet/btRayShape.h b/modules/bullet/btRayShape.h index df6dd93d57..d9ecde81e6 100644 --- a/modules/bullet/btRayShape.h +++ b/modules/bullet/btRayShape.h @@ -42,7 +42,6 @@ /// Ray shape around z axis ATTRIBUTE_ALIGNED16(class) btRayShape : public btConvexInternalShape { - btScalar m_length; bool slipsOnSlope; /// The default axis is the z diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 89868babc6..55686543f3 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -74,51 +74,41 @@ body->get_space()->add_constraint(joint, joint->is_disabled_collisions_between_bodies()); // <--------------- Joint creation asserts -void BulletPhysicsServer::_bind_methods() { - //ClassDB::bind_method(D_METHOD("DoTest"), &BulletPhysicsServer::DoTest); +void BulletPhysicsServer3D::_bind_methods() { + //ClassDB::bind_method(D_METHOD("DoTest"), &BulletPhysicsServer3D::DoTest); } -BulletPhysicsServer::BulletPhysicsServer() : - PhysicsServer(), - active(true), - active_spaces_count(0) {} +BulletPhysicsServer3D::BulletPhysicsServer3D() : + PhysicsServer3D() {} -BulletPhysicsServer::~BulletPhysicsServer() {} +BulletPhysicsServer3D::~BulletPhysicsServer3D() {} -RID BulletPhysicsServer::shape_create(ShapeType p_shape) { - ShapeBullet *shape = NULL; +RID BulletPhysicsServer3D::shape_create(ShapeType p_shape) { + ShapeBullet *shape = nullptr; switch (p_shape) { case SHAPE_PLANE: { - shape = bulletnew(PlaneShapeBullet); } break; case SHAPE_SPHERE: { - shape = bulletnew(SphereShapeBullet); } break; case SHAPE_BOX: { - shape = bulletnew(BoxShapeBullet); } break; case SHAPE_CAPSULE: { - shape = bulletnew(CapsuleShapeBullet); } break; case SHAPE_CYLINDER: { - shape = bulletnew(CylinderShapeBullet); } break; case SHAPE_CONVEX_POLYGON: { - shape = bulletnew(ConvexPolygonShapeBullet); } break; case SHAPE_CONCAVE_POLYGON: { - shape = bulletnew(ConcavePolygonShapeBullet); } break; case SHAPE_HEIGHTMAP: { - shape = bulletnew(HeightMapShapeBullet); } break; case SHAPE_RAY: { @@ -133,52 +123,51 @@ RID BulletPhysicsServer::shape_create(ShapeType p_shape) { CreateThenReturnRID(shape_owner, shape) } -void BulletPhysicsServer::shape_set_data(RID p_shape, const Variant &p_data) { +void BulletPhysicsServer3D::shape_set_data(RID p_shape, const Variant &p_data) { ShapeBullet *shape = shape_owner.getornull(p_shape); ERR_FAIL_COND(!shape); shape->set_data(p_data); } -void BulletPhysicsServer::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { +void BulletPhysicsServer3D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { //WARN_PRINT("Bias not supported by Bullet physics engine"); } -PhysicsServer::ShapeType BulletPhysicsServer::shape_get_type(RID p_shape) const { +PhysicsServer3D::ShapeType BulletPhysicsServer3D::shape_get_type(RID p_shape) const { ShapeBullet *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, PhysicsServer::SHAPE_CUSTOM); + ERR_FAIL_COND_V(!shape, PhysicsServer3D::SHAPE_CUSTOM); return shape->get_type(); } -Variant BulletPhysicsServer::shape_get_data(RID p_shape) const { +Variant BulletPhysicsServer3D::shape_get_data(RID p_shape) const { ShapeBullet *shape = shape_owner.getornull(p_shape); ERR_FAIL_COND_V(!shape, Variant()); return shape->get_data(); } -void BulletPhysicsServer::shape_set_margin(RID p_shape, real_t p_margin) { +void BulletPhysicsServer3D::shape_set_margin(RID p_shape, real_t p_margin) { ShapeBullet *shape = shape_owner.getornull(p_shape); ERR_FAIL_COND(!shape); shape->set_margin(p_margin); } -real_t BulletPhysicsServer::shape_get_margin(RID p_shape) const { +real_t BulletPhysicsServer3D::shape_get_margin(RID p_shape) const { ShapeBullet *shape = shape_owner.getornull(p_shape); ERR_FAIL_COND_V(!shape, 0.0); return shape->get_margin(); } -real_t BulletPhysicsServer::shape_get_custom_solver_bias(RID p_shape) const { +real_t BulletPhysicsServer3D::shape_get_custom_solver_bias(RID p_shape) const { //WARN_PRINT("Bias not supported by Bullet physics engine"); return 0.; } -RID BulletPhysicsServer::space_create() { +RID BulletPhysicsServer3D::space_create() { SpaceBullet *space = bulletnew(SpaceBullet); CreateThenReturnRID(space_owner, space); } -void BulletPhysicsServer::space_set_active(RID p_space, bool p_active) { - +void BulletPhysicsServer3D::space_set_active(RID p_space, bool p_active) { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); @@ -195,64 +184,64 @@ void BulletPhysicsServer::space_set_active(RID p_space, bool p_active) { } } -bool BulletPhysicsServer::space_is_active(RID p_space) const { +bool BulletPhysicsServer3D::space_is_active(RID p_space) const { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, false); return -1 != active_spaces.find(space); } -void BulletPhysicsServer::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { +void BulletPhysicsServer3D::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); space->set_param(p_param, p_value); } -real_t BulletPhysicsServer::space_get_param(RID p_space, SpaceParameter p_param) const { +real_t BulletPhysicsServer3D::space_get_param(RID p_space, SpaceParameter p_param) const { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, 0); return space->get_param(p_param); } -PhysicsDirectSpaceState *BulletPhysicsServer::space_get_direct_state(RID p_space) { +PhysicsDirectSpaceState3D *BulletPhysicsServer3D::space_get_direct_state(RID p_space) { SpaceBullet *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, NULL); + ERR_FAIL_COND_V(!space, nullptr); return space->get_direct_state(); } -void BulletPhysicsServer::space_set_debug_contacts(RID p_space, int p_max_contacts) { +void BulletPhysicsServer3D::space_set_debug_contacts(RID p_space, int p_max_contacts) { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); space->set_debug_contacts(p_max_contacts); } -Vector<Vector3> BulletPhysicsServer::space_get_contacts(RID p_space) const { +Vector<Vector3> BulletPhysicsServer3D::space_get_contacts(RID p_space) const { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, Vector<Vector3>()); return space->get_debug_contacts(); } -int BulletPhysicsServer::space_get_contact_count(RID p_space) const { +int BulletPhysicsServer3D::space_get_contact_count(RID p_space) const { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, 0); return space->get_debug_contact_count(); } -RID BulletPhysicsServer::area_create() { +RID BulletPhysicsServer3D::area_create() { AreaBullet *area = bulletnew(AreaBullet); area->set_collision_layer(1); area->set_collision_mask(1); CreateThenReturnRID(area_owner, area) } -void BulletPhysicsServer::area_set_space(RID p_area, RID p_space) { +void BulletPhysicsServer3D::area_set_space(RID p_area, RID p_space) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); - SpaceBullet *space = NULL; + SpaceBullet *space = nullptr; if (p_space.is_valid()) { space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); @@ -260,26 +249,26 @@ void BulletPhysicsServer::area_set_space(RID p_area, RID p_space) { area->set_space(space); } -RID BulletPhysicsServer::area_get_space(RID p_area) const { +RID BulletPhysicsServer3D::area_get_space(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); return area->get_space()->get_self(); } -void BulletPhysicsServer::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { +void BulletPhysicsServer3D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_spOv_mode(p_mode); } -PhysicsServer::AreaSpaceOverrideMode BulletPhysicsServer::area_get_space_override_mode(RID p_area) const { +PhysicsServer3D::AreaSpaceOverrideMode BulletPhysicsServer3D::area_get_space_override_mode(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED); + ERR_FAIL_COND_V(!area, PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED); return area->get_spOv_mode(); } -void BulletPhysicsServer::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) { +void BulletPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); @@ -289,7 +278,7 @@ void BulletPhysicsServer::area_add_shape(RID p_area, RID p_shape, const Transfor area->add_shape(shape, p_transform, p_disabled); } -void BulletPhysicsServer::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { +void BulletPhysicsServer3D::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); @@ -299,56 +288,57 @@ void BulletPhysicsServer::area_set_shape(RID p_area, int p_shape_idx, RID p_shap area->set_shape(p_shape_idx, shape); } -void BulletPhysicsServer::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) { +void BulletPhysicsServer3D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_shape_transform(p_shape_idx, p_transform); } -int BulletPhysicsServer::area_get_shape_count(RID p_area) const { +int BulletPhysicsServer3D::area_get_shape_count(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, 0); return area->get_shape_count(); } -RID BulletPhysicsServer::area_get_shape(RID p_area, int p_shape_idx) const { +RID BulletPhysicsServer3D::area_get_shape(RID p_area, int p_shape_idx) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, RID()); return area->get_shape(p_shape_idx)->get_self(); } -Transform BulletPhysicsServer::area_get_shape_transform(RID p_area, int p_shape_idx) const { +Transform BulletPhysicsServer3D::area_get_shape_transform(RID p_area, int p_shape_idx) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, Transform()); return area->get_shape_transform(p_shape_idx); } -void BulletPhysicsServer::area_remove_shape(RID p_area, int p_shape_idx) { +void BulletPhysicsServer3D::area_remove_shape(RID p_area, int p_shape_idx) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); return area->remove_shape_full(p_shape_idx); } -void BulletPhysicsServer::area_clear_shapes(RID p_area) { +void BulletPhysicsServer3D::area_clear_shapes(RID p_area) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); - for (int i = area->get_shape_count(); 0 < i; --i) + for (int i = area->get_shape_count(); 0 < i; --i) { area->remove_shape_full(0); + } } -void BulletPhysicsServer::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { +void BulletPhysicsServer3D::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_shape_disabled(p_shape_idx, p_disabled); } -void BulletPhysicsServer::area_attach_object_instance_id(RID p_area, ObjectID p_id) { +void BulletPhysicsServer3D::area_attach_object_instance_id(RID p_area, ObjectID p_id) { if (space_owner.owns(p_area)) { return; } @@ -357,7 +347,7 @@ void BulletPhysicsServer::area_attach_object_instance_id(RID p_area, ObjectID p_ area->set_instance_id(p_id); } -ObjectID BulletPhysicsServer::area_get_object_instance_id(RID p_area) const { +ObjectID BulletPhysicsServer3D::area_get_object_instance_id(RID p_area) const { if (space_owner.owns(p_area)) { return ObjectID(); } @@ -366,14 +356,13 @@ ObjectID BulletPhysicsServer::area_get_object_instance_id(RID p_area) const { return area->get_instance_id(); } -void BulletPhysicsServer::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { +void BulletPhysicsServer3D::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { if (space_owner.owns(p_area)) { SpaceBullet *space = space_owner.getornull(p_area); if (space) { space->set_param(p_param, p_value); } } else { - AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); @@ -381,7 +370,7 @@ void BulletPhysicsServer::area_set_param(RID p_area, AreaParameter p_param, cons } } -Variant BulletPhysicsServer::area_get_param(RID p_area, AreaParameter p_param) const { +Variant BulletPhysicsServer3D::area_get_param(RID p_area, AreaParameter p_param) const { if (space_owner.owns(p_area)) { SpaceBullet *space = space_owner.getornull(p_area); return space->get_param(p_param); @@ -393,113 +382,115 @@ Variant BulletPhysicsServer::area_get_param(RID p_area, AreaParameter p_param) c } } -void BulletPhysicsServer::area_set_transform(RID p_area, const Transform &p_transform) { +void BulletPhysicsServer3D::area_set_transform(RID p_area, const Transform &p_transform) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_transform(p_transform); } -Transform BulletPhysicsServer::area_get_transform(RID p_area) const { +Transform BulletPhysicsServer3D::area_get_transform(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, Transform()); return area->get_transform(); } -void BulletPhysicsServer::area_set_collision_mask(RID p_area, uint32_t p_mask) { +void BulletPhysicsServer3D::area_set_collision_mask(RID p_area, uint32_t p_mask) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_collision_mask(p_mask); } -void BulletPhysicsServer::area_set_collision_layer(RID p_area, uint32_t p_layer) { +void BulletPhysicsServer3D::area_set_collision_layer(RID p_area, uint32_t p_layer) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_collision_layer(p_layer); } -void BulletPhysicsServer::area_set_monitorable(RID p_area, bool p_monitorable) { +void BulletPhysicsServer3D::area_set_monitorable(RID p_area, bool p_monitorable) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_monitorable(p_monitorable); } -void BulletPhysicsServer::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { +void BulletPhysicsServer3D::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_event_callback(CollisionObjectBullet::TYPE_RIGID_BODY, p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } -void BulletPhysicsServer::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { +void BulletPhysicsServer3D::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_event_callback(CollisionObjectBullet::TYPE_AREA, p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } -void BulletPhysicsServer::area_set_ray_pickable(RID p_area, bool p_enable) { +void BulletPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_ray_pickable(p_enable); } -bool BulletPhysicsServer::area_is_ray_pickable(RID p_area) const { +bool BulletPhysicsServer3D::area_is_ray_pickable(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, false); return area->is_ray_pickable(); } -RID BulletPhysicsServer::body_create(BodyMode p_mode, bool p_init_sleeping) { +RID BulletPhysicsServer3D::body_create(BodyMode p_mode, bool p_init_sleeping) { RigidBodyBullet *body = bulletnew(RigidBodyBullet); body->set_mode(p_mode); body->set_collision_layer(1); body->set_collision_mask(1); - if (p_init_sleeping) + if (p_init_sleeping) { body->set_state(BODY_STATE_SLEEPING, p_init_sleeping); + } CreateThenReturnRID(rigid_body_owner, body); } -void BulletPhysicsServer::body_set_space(RID p_body, RID p_space) { +void BulletPhysicsServer3D::body_set_space(RID p_body, RID p_space) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); - SpaceBullet *space = NULL; + SpaceBullet *space = nullptr; if (p_space.is_valid()) { space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); } - if (body->get_space() == space) + if (body->get_space() == space) { return; //pointles + } body->set_space(space); } -RID BulletPhysicsServer::body_get_space(RID p_body) const { +RID BulletPhysicsServer3D::body_get_space(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, RID()); SpaceBullet *space = body->get_space(); - if (!space) + if (!space) { return RID(); + } return space->get_self(); } -void BulletPhysicsServer::body_set_mode(RID p_body, PhysicsServer::BodyMode p_mode) { +void BulletPhysicsServer3D::body_set_mode(RID p_body, PhysicsServer3D::BodyMode p_mode) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_mode(p_mode); } -PhysicsServer::BodyMode BulletPhysicsServer::body_get_mode(RID p_body) const { +PhysicsServer3D::BodyMode BulletPhysicsServer3D::body_get_mode(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); return body->get_mode(); } -void BulletPhysicsServer::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) { - +void BulletPhysicsServer3D::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -509,7 +500,7 @@ void BulletPhysicsServer::body_add_shape(RID p_body, RID p_shape, const Transfor body->add_shape(shape, p_transform, p_disabled); } -void BulletPhysicsServer::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { +void BulletPhysicsServer3D::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -519,20 +510,20 @@ void BulletPhysicsServer::body_set_shape(RID p_body, int p_shape_idx, RID p_shap body->set_shape(p_shape_idx, shape); } -void BulletPhysicsServer::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) { +void BulletPhysicsServer3D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_shape_transform(p_shape_idx, p_transform); } -int BulletPhysicsServer::body_get_shape_count(RID p_body) const { +int BulletPhysicsServer3D::body_get_shape_count(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_shape_count(); } -RID BulletPhysicsServer::body_get_shape(RID p_body, int p_shape_idx) const { +RID BulletPhysicsServer3D::body_get_shape(RID p_body, int p_shape_idx) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, RID()); @@ -542,218 +533,216 @@ RID BulletPhysicsServer::body_get_shape(RID p_body, int p_shape_idx) const { return shape->get_self(); } -Transform BulletPhysicsServer::body_get_shape_transform(RID p_body, int p_shape_idx) const { +Transform BulletPhysicsServer3D::body_get_shape_transform(RID p_body, int p_shape_idx) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Transform()); return body->get_shape_transform(p_shape_idx); } -void BulletPhysicsServer::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { +void BulletPhysicsServer3D::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_shape_disabled(p_shape_idx, p_disabled); } -void BulletPhysicsServer::body_remove_shape(RID p_body, int p_shape_idx) { +void BulletPhysicsServer3D::body_remove_shape(RID p_body, int p_shape_idx) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->remove_shape_full(p_shape_idx); } -void BulletPhysicsServer::body_clear_shapes(RID p_body) { +void BulletPhysicsServer3D::body_clear_shapes(RID p_body) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->remove_all_shapes(); } -void BulletPhysicsServer::body_attach_object_instance_id(RID p_body, ObjectID p_id) { +void BulletPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p_id) { CollisionObjectBullet *body = get_collisin_object(p_body); ERR_FAIL_COND(!body); body->set_instance_id(p_id); } -ObjectID BulletPhysicsServer::body_get_object_instance_id(RID p_body) const { +ObjectID BulletPhysicsServer3D::body_get_object_instance_id(RID p_body) const { CollisionObjectBullet *body = get_collisin_object(p_body); ERR_FAIL_COND_V(!body, ObjectID()); return body->get_instance_id(); } -void BulletPhysicsServer::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { +void BulletPhysicsServer3D::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_continuous_collision_detection(p_enable); } -bool BulletPhysicsServer::body_is_continuous_collision_detection_enabled(RID p_body) const { +bool BulletPhysicsServer3D::body_is_continuous_collision_detection_enabled(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); return body->is_continuous_collision_detection_enabled(); } -void BulletPhysicsServer::body_set_collision_layer(RID p_body, uint32_t p_layer) { +void BulletPhysicsServer3D::body_set_collision_layer(RID p_body, uint32_t p_layer) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_collision_layer(p_layer); } -uint32_t BulletPhysicsServer::body_get_collision_layer(RID p_body) const { +uint32_t BulletPhysicsServer3D::body_get_collision_layer(RID p_body) const { const RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_collision_layer(); } -void BulletPhysicsServer::body_set_collision_mask(RID p_body, uint32_t p_mask) { +void BulletPhysicsServer3D::body_set_collision_mask(RID p_body, uint32_t p_mask) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_collision_mask(p_mask); } -uint32_t BulletPhysicsServer::body_get_collision_mask(RID p_body) const { +uint32_t BulletPhysicsServer3D::body_get_collision_mask(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_collision_mask(); } -void BulletPhysicsServer::body_set_user_flags(RID p_body, uint32_t p_flags) { +void BulletPhysicsServer3D::body_set_user_flags(RID p_body, uint32_t p_flags) { // This function si not currently supported } -uint32_t BulletPhysicsServer::body_get_user_flags(RID p_body) const { +uint32_t BulletPhysicsServer3D::body_get_user_flags(RID p_body) const { // This function si not currently supported return 0; } -void BulletPhysicsServer::body_set_param(RID p_body, BodyParameter p_param, float p_value) { +void BulletPhysicsServer3D::body_set_param(RID p_body, BodyParameter p_param, float p_value) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_param(p_param, p_value); } -float BulletPhysicsServer::body_get_param(RID p_body, BodyParameter p_param) const { +float BulletPhysicsServer3D::body_get_param(RID p_body, BodyParameter p_param) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_param(p_param); } -void BulletPhysicsServer::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) { +void BulletPhysicsServer3D::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); if (body->get_kinematic_utilities()) { - body->get_kinematic_utilities()->setSafeMargin(p_margin); } } -real_t BulletPhysicsServer::body_get_kinematic_safe_margin(RID p_body) const { +real_t BulletPhysicsServer3D::body_get_kinematic_safe_margin(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); if (body->get_kinematic_utilities()) { - return body->get_kinematic_utilities()->safe_margin; } return 0; } -void BulletPhysicsServer::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { +void BulletPhysicsServer3D::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_state(p_state, p_variant); } -Variant BulletPhysicsServer::body_get_state(RID p_body, BodyState p_state) const { +Variant BulletPhysicsServer3D::body_get_state(RID p_body, BodyState p_state) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Variant()); return body->get_state(p_state); } -void BulletPhysicsServer::body_set_applied_force(RID p_body, const Vector3 &p_force) { +void BulletPhysicsServer3D::body_set_applied_force(RID p_body, const Vector3 &p_force) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_applied_force(p_force); } -Vector3 BulletPhysicsServer::body_get_applied_force(RID p_body) const { +Vector3 BulletPhysicsServer3D::body_get_applied_force(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3()); return body->get_applied_force(); } -void BulletPhysicsServer::body_set_applied_torque(RID p_body, const Vector3 &p_torque) { +void BulletPhysicsServer3D::body_set_applied_torque(RID p_body, const Vector3 &p_torque) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_applied_torque(p_torque); } -Vector3 BulletPhysicsServer::body_get_applied_torque(RID p_body) const { +Vector3 BulletPhysicsServer3D::body_get_applied_torque(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3()); return body->get_applied_torque(); } -void BulletPhysicsServer::body_add_central_force(RID p_body, const Vector3 &p_force) { +void BulletPhysicsServer3D::body_add_central_force(RID p_body, const Vector3 &p_force) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_central_force(p_force); } -void BulletPhysicsServer::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) { +void BulletPhysicsServer3D::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_force(p_force, p_pos); } -void BulletPhysicsServer::body_add_torque(RID p_body, const Vector3 &p_torque) { +void BulletPhysicsServer3D::body_add_torque(RID p_body, const Vector3 &p_torque) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_torque(p_torque); } -void BulletPhysicsServer::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { +void BulletPhysicsServer3D::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_central_impulse(p_impulse); } -void BulletPhysicsServer::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) { +void BulletPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_impulse(p_pos, p_impulse); } -void BulletPhysicsServer::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { +void BulletPhysicsServer3D::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_torque_impulse(p_impulse); } -void BulletPhysicsServer::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { +void BulletPhysicsServer3D::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -764,19 +753,19 @@ void BulletPhysicsServer::body_set_axis_velocity(RID p_body, const Vector3 &p_ax body->set_linear_velocity(v); } -void BulletPhysicsServer::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { +void BulletPhysicsServer3D::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_axis_lock(p_axis, p_lock); } -bool BulletPhysicsServer::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { +bool BulletPhysicsServer3D::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { const RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->is_axis_locked(p_axis); } -void BulletPhysicsServer::body_add_collision_exception(RID p_body, RID p_body_b) { +void BulletPhysicsServer3D::body_add_collision_exception(RID p_body, RID p_body_b) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -786,7 +775,7 @@ void BulletPhysicsServer::body_add_collision_exception(RID p_body, RID p_body_b) body->add_collision_exception(other_body); } -void BulletPhysicsServer::body_remove_collision_exception(RID p_body, RID p_body_b) { +void BulletPhysicsServer3D::body_remove_collision_exception(RID p_body, RID p_body_b) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -796,7 +785,7 @@ void BulletPhysicsServer::body_remove_collision_exception(RID p_body, RID p_body body->remove_collision_exception(other_body); } -void BulletPhysicsServer::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { +void BulletPhysicsServer3D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); for (int i = 0; i < body->get_exceptions().size(); i++) { @@ -804,68 +793,68 @@ void BulletPhysicsServer::body_get_collision_exceptions(RID p_body, List<RID> *p } } -void BulletPhysicsServer::body_set_max_contacts_reported(RID p_body, int p_contacts) { +void BulletPhysicsServer3D::body_set_max_contacts_reported(RID p_body, int p_contacts) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_max_collisions_detection(p_contacts); } -int BulletPhysicsServer::body_get_max_contacts_reported(RID p_body) const { +int BulletPhysicsServer3D::body_get_max_contacts_reported(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_max_collisions_detection(); } -void BulletPhysicsServer::body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) { +void BulletPhysicsServer3D::body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) { // Not supported by bullet and even Godot } -float BulletPhysicsServer::body_get_contacts_reported_depth_threshold(RID p_body) const { +float BulletPhysicsServer3D::body_get_contacts_reported_depth_threshold(RID p_body) const { // Not supported by bullet and even Godot return 0.; } -void BulletPhysicsServer::body_set_omit_force_integration(RID p_body, bool p_omit) { +void BulletPhysicsServer3D::body_set_omit_force_integration(RID p_body, bool p_omit) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_omit_forces_integration(p_omit); } -bool BulletPhysicsServer::body_is_omitting_force_integration(RID p_body) const { +bool BulletPhysicsServer3D::body_is_omitting_force_integration(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); return body->get_omit_forces_integration(); } -void BulletPhysicsServer::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { +void BulletPhysicsServer3D::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); } -void BulletPhysicsServer::body_set_ray_pickable(RID p_body, bool p_enable) { +void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_ray_pickable(p_enable); } -bool BulletPhysicsServer::body_is_ray_pickable(RID p_body) const { +bool BulletPhysicsServer3D::body_is_ray_pickable(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); return body->is_ray_pickable(); } -PhysicsDirectBodyState *BulletPhysicsServer::body_get_direct_state(RID p_body) { +PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_body) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, NULL); - return BulletPhysicsDirectBodyState::get_singleton(body); + ERR_FAIL_COND_V(!body, nullptr); + return BulletPhysicsDirectBodyState3D::get_singleton(body); } -bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) { +bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); @@ -873,7 +862,7 @@ bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes); } -int BulletPhysicsServer::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { +int BulletPhysicsServer3D::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); ERR_FAIL_COND_V(!body->get_space(), 0); @@ -881,84 +870,87 @@ int BulletPhysicsServer::body_test_ray_separation(RID p_body, const Transform &p return body->get_space()->test_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); } -RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) { +RID BulletPhysicsServer3D::soft_body_create(bool p_init_sleeping) { SoftBodyBullet *body = bulletnew(SoftBodyBullet); body->set_collision_layer(1); body->set_collision_mask(1); - if (p_init_sleeping) + if (p_init_sleeping) { body->set_activation_state(false); + } CreateThenReturnRID(soft_body_owner, body); } -void BulletPhysicsServer::soft_body_update_visual_server(RID p_body, class SoftBodyVisualServerHandler *p_visual_server_handler) { +void BulletPhysicsServer3D::soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->update_visual_server(p_visual_server_handler); + body->update_rendering_server(p_rendering_server_handler); } -void BulletPhysicsServer::soft_body_set_space(RID p_body, RID p_space) { +void BulletPhysicsServer3D::soft_body_set_space(RID p_body, RID p_space) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); - SpaceBullet *space = NULL; + SpaceBullet *space = nullptr; if (p_space.is_valid()) { space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); } - if (body->get_space() == space) + if (body->get_space() == space) { return; //pointles + } body->set_space(space); } -RID BulletPhysicsServer::soft_body_get_space(RID p_body) const { +RID BulletPhysicsServer3D::soft_body_get_space(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, RID()); SpaceBullet *space = body->get_space(); - if (!space) + if (!space) { return RID(); + } return space->get_self(); } -void BulletPhysicsServer::soft_body_set_mesh(RID p_body, const REF &p_mesh) { +void BulletPhysicsServer3D::soft_body_set_mesh(RID p_body, const REF &p_mesh) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_soft_mesh(p_mesh); } -void BulletPhysicsServer::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { +void BulletPhysicsServer3D::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_collision_layer(p_layer); } -uint32_t BulletPhysicsServer::soft_body_get_collision_layer(RID p_body) const { +uint32_t BulletPhysicsServer3D::soft_body_get_collision_layer(RID p_body) const { const SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_collision_layer(); } -void BulletPhysicsServer::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) { +void BulletPhysicsServer3D::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_collision_mask(p_mask); } -uint32_t BulletPhysicsServer::soft_body_get_collision_mask(RID p_body) const { +uint32_t BulletPhysicsServer3D::soft_body_get_collision_mask(RID p_body) const { const SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_collision_mask(); } -void BulletPhysicsServer::soft_body_add_collision_exception(RID p_body, RID p_body_b) { +void BulletPhysicsServer3D::soft_body_add_collision_exception(RID p_body, RID p_body_b) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -971,7 +963,7 @@ void BulletPhysicsServer::soft_body_add_collision_exception(RID p_body, RID p_bo body->add_collision_exception(other_body); } -void BulletPhysicsServer::soft_body_remove_collision_exception(RID p_body, RID p_body_b) { +void BulletPhysicsServer3D::soft_body_remove_collision_exception(RID p_body, RID p_body_b) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -984,7 +976,7 @@ void BulletPhysicsServer::soft_body_remove_collision_exception(RID p_body, RID p body->remove_collision_exception(other_body); } -void BulletPhysicsServer::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { +void BulletPhysicsServer3D::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); for (int i = 0; i < body->get_exceptions().size(); i++) { @@ -992,25 +984,25 @@ void BulletPhysicsServer::soft_body_get_collision_exceptions(RID p_body, List<RI } } -void BulletPhysicsServer::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { +void BulletPhysicsServer3D::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { // FIXME: Must be implemented. WARN_PRINT("soft_body_state is not implemented yet in Bullet backend."); } -Variant BulletPhysicsServer::soft_body_get_state(RID p_body, BodyState p_state) const { +Variant BulletPhysicsServer3D::soft_body_get_state(RID p_body, BodyState p_state) const { // FIXME: Must be implemented. WARN_PRINT("soft_body_state is not implemented yet in Bullet backend."); return Variant(); } -void BulletPhysicsServer::soft_body_set_transform(RID p_body, const Transform &p_transform) { +void BulletPhysicsServer3D::soft_body_set_transform(RID p_body, const Transform &p_transform) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_soft_transform(p_transform); } -Vector3 BulletPhysicsServer::soft_body_get_vertex_position(RID p_body, int vertex_index) const { +Vector3 BulletPhysicsServer3D::soft_body_get_vertex_position(RID p_body, int vertex_index) const { const SoftBodyBullet *body = soft_body_owner.getornull(p_body); Vector3 pos; ERR_FAIL_COND_V(!body, pos); @@ -1019,133 +1011,133 @@ Vector3 BulletPhysicsServer::soft_body_get_vertex_position(RID p_body, int verte return pos; } -void BulletPhysicsServer::soft_body_set_ray_pickable(RID p_body, bool p_enable) { +void BulletPhysicsServer3D::soft_body_set_ray_pickable(RID p_body, bool p_enable) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_ray_pickable(p_enable); } -bool BulletPhysicsServer::soft_body_is_ray_pickable(RID p_body) const { +bool BulletPhysicsServer3D::soft_body_is_ray_pickable(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); return body->is_ray_pickable(); } -void BulletPhysicsServer::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { +void BulletPhysicsServer3D::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_simulation_precision(p_simulation_precision); } -int BulletPhysicsServer::soft_body_get_simulation_precision(RID p_body) { +int BulletPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_simulation_precision(); } -void BulletPhysicsServer::soft_body_set_total_mass(RID p_body, real_t p_total_mass) { +void BulletPhysicsServer3D::soft_body_set_total_mass(RID p_body, real_t p_total_mass) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_total_mass(p_total_mass); } -real_t BulletPhysicsServer::soft_body_get_total_mass(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_total_mass(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_total_mass(); } -void BulletPhysicsServer::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { +void BulletPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_linear_stiffness(p_stiffness); } -real_t BulletPhysicsServer::soft_body_get_linear_stiffness(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_linear_stiffness(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_linear_stiffness(); } -void BulletPhysicsServer::soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) { +void BulletPhysicsServer3D::soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_areaAngular_stiffness(p_stiffness); } -real_t BulletPhysicsServer::soft_body_get_areaAngular_stiffness(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_areaAngular_stiffness(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_areaAngular_stiffness(); } -void BulletPhysicsServer::soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) { +void BulletPhysicsServer3D::soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_volume_stiffness(p_stiffness); } -real_t BulletPhysicsServer::soft_body_get_volume_stiffness(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_volume_stiffness(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_volume_stiffness(); } -void BulletPhysicsServer::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { +void BulletPhysicsServer3D::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_pressure_coefficient(p_pressure_coefficient); } -real_t BulletPhysicsServer::soft_body_get_pressure_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_pressure_coefficient(); } -void BulletPhysicsServer::soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) { +void BulletPhysicsServer3D::soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); return body->set_pose_matching_coefficient(p_pose_matching_coefficient); } -real_t BulletPhysicsServer::soft_body_get_pose_matching_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_pose_matching_coefficient(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_pose_matching_coefficient(); } -void BulletPhysicsServer::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { +void BulletPhysicsServer3D::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_damping_coefficient(p_damping_coefficient); } -real_t BulletPhysicsServer::soft_body_get_damping_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_damping_coefficient(); } -void BulletPhysicsServer::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) { +void BulletPhysicsServer3D::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_drag_coefficient(p_drag_coefficient); } -real_t BulletPhysicsServer::soft_body_get_drag_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_drag_coefficient(); } -void BulletPhysicsServer::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) { +void BulletPhysicsServer3D::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_node_position(p_point_index, p_global_position); } -Vector3 BulletPhysicsServer::soft_body_get_point_global_position(RID p_body, int p_point_index) { +Vector3 BulletPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3(0., 0., 0.)); Vector3 pos; @@ -1153,7 +1145,7 @@ Vector3 BulletPhysicsServer::soft_body_get_point_global_position(RID p_body, int return pos; } -Vector3 BulletPhysicsServer::soft_body_get_point_offset(RID p_body, int p_point_index) const { +Vector3 BulletPhysicsServer3D::soft_body_get_point_offset(RID p_body, int p_point_index) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3()); Vector3 res; @@ -1161,60 +1153,60 @@ Vector3 BulletPhysicsServer::soft_body_get_point_offset(RID p_body, int p_point_ return res; } -void BulletPhysicsServer::soft_body_remove_all_pinned_points(RID p_body) { +void BulletPhysicsServer3D::soft_body_remove_all_pinned_points(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->reset_all_node_mass(); } -void BulletPhysicsServer::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) { +void BulletPhysicsServer3D::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_node_mass(p_point_index, p_pin ? 0 : 1); } -bool BulletPhysicsServer::soft_body_is_point_pinned(RID p_body, int p_point_index) { +bool BulletPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_node_mass(p_point_index); } -PhysicsServer::JointType BulletPhysicsServer::joint_get_type(RID p_joint) const { +PhysicsServer3D::JointType BulletPhysicsServer3D::joint_get_type(RID p_joint) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, JOINT_PIN); return joint->get_type(); } -void BulletPhysicsServer::joint_set_solver_priority(RID p_joint, int p_priority) { +void BulletPhysicsServer3D::joint_set_solver_priority(RID p_joint, int p_priority) { // Joint priority not supported by bullet } -int BulletPhysicsServer::joint_get_solver_priority(RID p_joint) const { +int BulletPhysicsServer3D::joint_get_solver_priority(RID p_joint) const { // Joint priority not supported by bullet return 0; } -void BulletPhysicsServer::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { +void BulletPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); joint->disable_collisions_between_bodies(p_disable); } -bool BulletPhysicsServer::joint_is_disabled_collisions_between_bodies(RID p_joint) const { +bool BulletPhysicsServer3D::joint_is_disabled_collisions_between_bodies(RID p_joint) const { JointBullet *joint(joint_owner.getornull(p_joint)); ERR_FAIL_COND_V(!joint, false); return joint->is_disabled_collisions_between_bodies(); } -RID BulletPhysicsServer::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { +RID BulletPhysicsServer3D::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); - RigidBodyBullet *body_B = NULL; + RigidBodyBullet *body_B = nullptr; if (p_body_B.is_valid()) { body_B = rigid_body_owner.getornull(p_body_B); JointAssertSpace(body_B, "B", RID()); @@ -1229,7 +1221,7 @@ RID BulletPhysicsServer::joint_create_pin(RID p_body_A, const Vector3 &p_local_A CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) { +void BulletPhysicsServer3D::pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_PIN); @@ -1237,7 +1229,7 @@ void BulletPhysicsServer::pin_joint_set_param(RID p_joint, PinJointParam p_param pin_joint->set_param(p_param, p_value); } -float BulletPhysicsServer::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { +float BulletPhysicsServer3D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, 0); @@ -1245,7 +1237,7 @@ float BulletPhysicsServer::pin_joint_get_param(RID p_joint, PinJointParam p_para return pin_joint->get_param(p_param); } -void BulletPhysicsServer::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { +void BulletPhysicsServer3D::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_PIN); @@ -1253,7 +1245,7 @@ void BulletPhysicsServer::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) pin_joint->setPivotInA(p_A); } -Vector3 BulletPhysicsServer::pin_joint_get_local_a(RID p_joint) const { +Vector3 BulletPhysicsServer3D::pin_joint_get_local_a(RID p_joint) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, Vector3()); ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); @@ -1261,7 +1253,7 @@ Vector3 BulletPhysicsServer::pin_joint_get_local_a(RID p_joint) const { return pin_joint->getPivotInA(); } -void BulletPhysicsServer::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { +void BulletPhysicsServer3D::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_PIN); @@ -1269,7 +1261,7 @@ void BulletPhysicsServer::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) pin_joint->setPivotInB(p_B); } -Vector3 BulletPhysicsServer::pin_joint_get_local_b(RID p_joint) const { +Vector3 BulletPhysicsServer3D::pin_joint_get_local_b(RID p_joint) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, Vector3()); ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); @@ -1277,12 +1269,12 @@ Vector3 BulletPhysicsServer::pin_joint_get_local_b(RID p_joint) const { return pin_joint->getPivotInB(); } -RID BulletPhysicsServer::joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) { +RID BulletPhysicsServer3D::joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); - RigidBodyBullet *body_B = NULL; + RigidBodyBullet *body_B = nullptr; if (p_body_B.is_valid()) { body_B = rigid_body_owner.getornull(p_body_B); JointAssertSpace(body_B, "B", RID()); @@ -1297,12 +1289,12 @@ RID BulletPhysicsServer::joint_create_hinge(RID p_body_A, const Transform &p_hin CreateThenReturnRID(joint_owner, joint); } -RID BulletPhysicsServer::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { +RID BulletPhysicsServer3D::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); - RigidBodyBullet *body_B = NULL; + RigidBodyBullet *body_B = nullptr; if (p_body_B.is_valid()) { body_B = rigid_body_owner.getornull(p_body_B); JointAssertSpace(body_B, "B", RID()); @@ -1317,7 +1309,7 @@ RID BulletPhysicsServer::joint_create_hinge_simple(RID p_body_A, const Vector3 & CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) { +void BulletPhysicsServer3D::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_HINGE); @@ -1325,7 +1317,7 @@ void BulletPhysicsServer::hinge_joint_set_param(RID p_joint, HingeJointParam p_p hinge_joint->set_param(p_param, p_value); } -float BulletPhysicsServer::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { +float BulletPhysicsServer3D::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, 0); @@ -1333,7 +1325,7 @@ float BulletPhysicsServer::hinge_joint_get_param(RID p_joint, HingeJointParam p_ return hinge_joint->get_param(p_param); } -void BulletPhysicsServer::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { +void BulletPhysicsServer3D::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_HINGE); @@ -1341,7 +1333,7 @@ void BulletPhysicsServer::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_fla hinge_joint->set_flag(p_flag, p_value); } -bool BulletPhysicsServer::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { +bool BulletPhysicsServer3D::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, false); ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, false); @@ -1349,12 +1341,12 @@ bool BulletPhysicsServer::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_fla return hinge_joint->get_flag(p_flag); } -RID BulletPhysicsServer::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { +RID BulletPhysicsServer3D::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); - RigidBodyBullet *body_B = NULL; + RigidBodyBullet *body_B = nullptr; if (p_body_B.is_valid()) { body_B = rigid_body_owner.getornull(p_body_B); JointAssertSpace(body_B, "B", RID()); @@ -1369,7 +1361,7 @@ RID BulletPhysicsServer::joint_create_slider(RID p_body_A, const Transform &p_lo CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) { +void BulletPhysicsServer3D::slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_SLIDER); @@ -1377,7 +1369,7 @@ void BulletPhysicsServer::slider_joint_set_param(RID p_joint, SliderJointParam p slider_joint->set_param(p_param, p_value); } -float BulletPhysicsServer::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { +float BulletPhysicsServer3D::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_SLIDER, 0); @@ -1385,12 +1377,12 @@ float BulletPhysicsServer::slider_joint_get_param(RID p_joint, SliderJointParam return slider_joint->get_param(p_param); } -RID BulletPhysicsServer::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { +RID BulletPhysicsServer3D::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); - RigidBodyBullet *body_B = NULL; + RigidBodyBullet *body_B = nullptr; if (p_body_B.is_valid()) { body_B = rigid_body_owner.getornull(p_body_B); JointAssertSpace(body_B, "B", RID()); @@ -1403,7 +1395,7 @@ RID BulletPhysicsServer::joint_create_cone_twist(RID p_body_A, const Transform & CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) { +void BulletPhysicsServer3D::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_CONE_TWIST); @@ -1411,7 +1403,7 @@ void BulletPhysicsServer::cone_twist_joint_set_param(RID p_joint, ConeTwistJoint coneTwist_joint->set_param(p_param, p_value); } -float BulletPhysicsServer::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { +float BulletPhysicsServer3D::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0.); ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0.); @@ -1419,12 +1411,12 @@ float BulletPhysicsServer::cone_twist_joint_get_param(RID p_joint, ConeTwistJoin return coneTwist_joint->get_param(p_param); } -RID BulletPhysicsServer::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { +RID BulletPhysicsServer3D::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); - RigidBodyBullet *body_B = NULL; + RigidBodyBullet *body_B = nullptr; if (p_body_B.is_valid()) { body_B = rigid_body_owner.getornull(p_body_B); JointAssertSpace(body_B, "B", RID()); @@ -1439,7 +1431,7 @@ RID BulletPhysicsServer::joint_create_generic_6dof(RID p_body_A, const Transform CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, float p_value) { +void BulletPhysicsServer3D::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); @@ -1447,7 +1439,7 @@ void BulletPhysicsServer::generic_6dof_joint_set_param(RID p_joint, Vector3::Axi generic_6dof_joint->set_param(p_axis, p_param, p_value); } -float BulletPhysicsServer::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) { +float BulletPhysicsServer3D::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0); @@ -1455,7 +1447,7 @@ float BulletPhysicsServer::generic_6dof_joint_get_param(RID p_joint, Vector3::Ax return generic_6dof_joint->get_param(p_axis, p_param); } -void BulletPhysicsServer::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { +void BulletPhysicsServer3D::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); @@ -1463,7 +1455,7 @@ void BulletPhysicsServer::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis generic_6dof_joint->set_flag(p_axis, p_flag, p_enable); } -bool BulletPhysicsServer::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) { +bool BulletPhysicsServer3D::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, false); ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, false); @@ -1471,7 +1463,7 @@ bool BulletPhysicsServer::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis return generic_6dof_joint->get_flag(p_axis, p_flag); } -void BulletPhysicsServer::generic_6dof_joint_set_precision(RID p_joint, int p_precision) { +void BulletPhysicsServer3D::generic_6dof_joint_set_precision(RID p_joint, int p_precision) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); @@ -1479,7 +1471,7 @@ void BulletPhysicsServer::generic_6dof_joint_set_precision(RID p_joint, int p_pr generic_6dof_joint->set_precision(p_precision); } -int BulletPhysicsServer::generic_6dof_joint_get_precision(RID p_joint) { +int BulletPhysicsServer3D::generic_6dof_joint_get_precision(RID p_joint) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0); @@ -1487,9 +1479,8 @@ int BulletPhysicsServer::generic_6dof_joint_get_precision(RID p_joint) { return generic_6dof_joint->get_precision(); } -void BulletPhysicsServer::free(RID p_rid) { +void BulletPhysicsServer3D::free(RID p_rid) { if (shape_owner.owns(p_rid)) { - ShapeBullet *shape = shape_owner.getornull(p_rid); // Notify the shape is configured @@ -1500,10 +1491,9 @@ void BulletPhysicsServer::free(RID p_rid) { shape_owner.free(p_rid); bulletdelete(shape); } else if (rigid_body_owner.owns(p_rid)) { - RigidBodyBullet *body = rigid_body_owner.getornull(p_rid); - body->set_space(NULL); + body->set_space(nullptr); body->remove_all_shapes(true, true); @@ -1511,19 +1501,17 @@ void BulletPhysicsServer::free(RID p_rid) { bulletdelete(body); } else if (soft_body_owner.owns(p_rid)) { - SoftBodyBullet *body = soft_body_owner.getornull(p_rid); - body->set_space(NULL); + body->set_space(nullptr); soft_body_owner.free(p_rid); bulletdelete(body); } else if (area_owner.owns(p_rid)) { - AreaBullet *area = area_owner.getornull(p_rid); - area->set_space(NULL); + area->set_space(nullptr); area->remove_all_shapes(true, true); @@ -1531,14 +1519,12 @@ void BulletPhysicsServer::free(RID p_rid) { bulletdelete(area); } else if (joint_owner.owns(p_rid)) { - JointBullet *joint = joint_owner.getornull(p_rid); joint->destroy_internal_constraint(); joint_owner.free(p_rid); bulletdelete(joint); } else if (space_owner.owns(p_rid)) { - SpaceBullet *space = space_owner.getornull(p_rid); space->remove_all_collision_objects(); @@ -1547,42 +1533,41 @@ void BulletPhysicsServer::free(RID p_rid) { space_owner.free(p_rid); bulletdelete(space); } else { - ERR_FAIL_MSG("Invalid ID."); } } -void BulletPhysicsServer::init() { - BulletPhysicsDirectBodyState::initSingleton(); +void BulletPhysicsServer3D::init() { + BulletPhysicsDirectBodyState3D::initSingleton(); } -void BulletPhysicsServer::step(float p_deltaTime) { - if (!active) +void BulletPhysicsServer3D::step(float p_deltaTime) { + if (!active) { return; + } - BulletPhysicsDirectBodyState::singleton_setDeltaTime(p_deltaTime); + BulletPhysicsDirectBodyState3D::singleton_setDeltaTime(p_deltaTime); for (int i = 0; i < active_spaces_count; ++i) { - active_spaces[i]->step(p_deltaTime); } } -void BulletPhysicsServer::sync() { +void BulletPhysicsServer3D::sync() { } -void BulletPhysicsServer::flush_queries() { +void BulletPhysicsServer3D::flush_queries() { } -void BulletPhysicsServer::finish() { - BulletPhysicsDirectBodyState::destroySingleton(); +void BulletPhysicsServer3D::finish() { + BulletPhysicsDirectBodyState3D::destroySingleton(); } -int BulletPhysicsServer::get_process_info(ProcessInfo p_info) { +int BulletPhysicsServer3D::get_process_info(ProcessInfo p_info) { return 0; } -CollisionObjectBullet *BulletPhysicsServer::get_collisin_object(RID p_object) const { +CollisionObjectBullet *BulletPhysicsServer3D::get_collisin_object(RID p_object) const { if (rigid_body_owner.owns(p_object)) { return rigid_body_owner.getornull(p_object); } @@ -1592,15 +1577,15 @@ CollisionObjectBullet *BulletPhysicsServer::get_collisin_object(RID p_object) co if (soft_body_owner.owns(p_object)) { return soft_body_owner.getornull(p_object); } - return NULL; + return nullptr; } -RigidCollisionObjectBullet *BulletPhysicsServer::get_rigid_collisin_object(RID p_object) const { +RigidCollisionObjectBullet *BulletPhysicsServer3D::get_rigid_collisin_object(RID p_object) const { if (rigid_body_owner.owns(p_object)) { return rigid_body_owner.getornull(p_object); } if (area_owner.owns(p_object)) { return area_owner.getornull(p_object); } - return NULL; + return nullptr; } diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 6ea9a7a974..558d1ce5f7 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -36,21 +36,22 @@ #include "core/rid_owner.h" #include "joint_bullet.h" #include "rigid_body_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include "shape_bullet.h" #include "soft_body_bullet.h" #include "space_bullet.h" + /** @author AndreaCatania */ -class BulletPhysicsServer : public PhysicsServer { - GDCLASS(BulletPhysicsServer, PhysicsServer); +class BulletPhysicsServer3D : public PhysicsServer3D { + GDCLASS(BulletPhysicsServer3D, PhysicsServer3D); friend class BulletPhysicsDirectSpaceState; - bool active; - char active_spaces_count; + bool active = true; + char active_spaces_count = 0; Vector<SpaceBullet *> active_spaces; mutable RID_PtrOwner<SpaceBullet> space_owner; @@ -64,8 +65,8 @@ protected: static void _bind_methods(); public: - BulletPhysicsServer(); - ~BulletPhysicsServer(); + BulletPhysicsServer3D(); + ~BulletPhysicsServer3D(); _FORCE_INLINE_ RID_PtrOwner<SpaceBullet> *get_space_owner() { return &space_owner; @@ -111,7 +112,7 @@ public: /// Not supported virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const; - virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space); + virtual PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space); virtual void space_set_debug_contacts(RID p_space, int p_max_contacts); virtual Vector<Vector3> space_get_contacts(RID p_space) const; @@ -252,16 +253,16 @@ public: virtual bool body_is_ray_pickable(RID p_body) const; // this function only works on physics process, errors and returns null otherwise - virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); + virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body); - virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true); + virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true); virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001); /* SOFT BODY API */ virtual RID soft_body_create(bool p_init_sleeping = false); - virtual void soft_body_update_visual_server(RID p_body, class SoftBodyVisualServerHandler *p_visual_server_handler); + virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler); virtual void soft_body_set_space(RID p_body, RID p_space); virtual RID soft_body_get_space(RID p_body) const; @@ -387,7 +388,7 @@ public: } static bool singleton_isActive() { - return static_cast<BulletPhysicsServer *>(get_singleton())->active; + return static_cast<BulletPhysicsServer3D *>(get_singleton())->active; } bool isActive() { diff --git a/modules/bullet/bullet_utilities.h b/modules/bullet/bullet_utilities.h index 968cb38ba2..a5e33d9829 100644 --- a/modules/bullet/bullet_utilities.h +++ b/modules/bullet/bullet_utilities.h @@ -41,6 +41,6 @@ #define bulletdelete(cl) \ { \ delete cl; \ - cl = NULL; \ + cl = nullptr; \ } #endif diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 5b7e7281e4..a3158a15e5 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -60,7 +60,7 @@ void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_tra } btTransform CollisionObjectBullet::ShapeWrapper::get_adjusted_transform() const { - if (shape->get_type() == PhysicsServer::SHAPE_HEIGHTMAP) { + if (shape->get_type() == PhysicsServer3D::SHAPE_HEIGHTMAP) { const HeightMapShapeBullet *hm_shape = (const HeightMapShapeBullet *)shape; // should be safe to cast now btTransform adjusted_transform; @@ -80,27 +80,17 @@ btTransform CollisionObjectBullet::ShapeWrapper::get_adjusted_transform() const void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_scale) { if (!bt_shape) { - if (active) + if (active) { bt_shape = shape->create_bt_shape(scale * body_scale); - else + } else { bt_shape = ShapeBullet::create_shape_empty(); + } } } CollisionObjectBullet::CollisionObjectBullet(Type p_type) : RIDBullet(), - type(p_type), - instance_id(ObjectID()), - collisionLayer(0), - collisionMask(0), - collisionsEnabled(true), - m_isStatic(false), - ray_pickable(false), - bt_collision_object(NULL), - body_scale(1., 1., 1.), - force_shape_reset(false), - space(NULL), - isTransformChanged(false) {} + type(p_type) {} CollisionObjectBullet::~CollisionObjectBullet() { // Remove all overlapping, notify is not required since godot take care of it @@ -147,18 +137,21 @@ void CollisionObjectBullet::setupBulletCollisionObject(btCollisionObject *p_coll void CollisionObjectBullet::add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) { exceptions.insert(p_ignoreCollisionObject->get_self()); - if (!bt_collision_object) + if (!bt_collision_object) { return; + } bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, true); - if (space) + if (space) { space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher()); + } } void CollisionObjectBullet::remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) { exceptions.erase(p_ignoreCollisionObject->get_self()); bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, false); - if (space) + if (space) { space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher()); + } } bool CollisionObjectBullet::has_collision_exception(const CollisionObjectBullet *p_otherCollisionObject) const { @@ -195,7 +188,6 @@ int CollisionObjectBullet::get_godot_object_flags() const { } void CollisionObjectBullet::set_transform(const Transform &p_global_transform) { - set_body_scale(p_global_transform.basis.get_scale_abs()); btTransform bt_transform; @@ -225,11 +217,6 @@ void CollisionObjectBullet::notify_transform_changed() { isTransformChanged = true; } -RigidCollisionObjectBullet::RigidCollisionObjectBullet(Type p_type) : - CollisionObjectBullet(p_type), - mainShape(NULL) { -} - RigidCollisionObjectBullet::~RigidCollisionObjectBullet() { remove_all_shapes(true, true); if (mainShape && mainShape->isCompound()) { @@ -266,8 +253,9 @@ btCollisionShape *RigidCollisionObjectBullet::get_bt_shape(int p_index) const { int RigidCollisionObjectBullet::find_shape(ShapeBullet *p_shape) const { const int size = shapes.size(); for (int i = 0; i < size; ++i) { - if (shapes[i].shape == p_shape) + if (shapes[i].shape == p_shape) { return i; + } } return -1; } @@ -297,8 +285,9 @@ void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBod internal_shape_destroy(i, p_permanentlyFromThisBody); } shapes.clear(); - if (!p_force_not_reload) + if (!p_force_not_reload) { reload_shapes(); + } } void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) { @@ -319,8 +308,9 @@ Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const { } void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) { - if (shapes[p_index].active != p_disabled) + if (shapes[p_index].active != p_disabled) { return; + } shapes.write[p_index].active = !p_disabled; shape_changed(p_index); } @@ -332,20 +322,19 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) { void RigidCollisionObjectBullet::shape_changed(int p_shape_index) { ShapeWrapper &shp = shapes.write[p_shape_index]; if (shp.bt_shape == mainShape) { - mainShape = NULL; + mainShape = nullptr; } bulletdelete(shp.bt_shape); reload_shapes(); } void RigidCollisionObjectBullet::reload_shapes() { - if (mainShape && mainShape->isCompound()) { // Destroy compound bulletdelete(mainShape); } - mainShape = NULL; + mainShape = nullptr; ShapeWrapper *shpWrapper; const int shape_count = shapes.size(); @@ -398,7 +387,7 @@ void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_perm ShapeWrapper &shp = shapes.write[p_index]; shp.shape->remove_owner(this, p_permanentlyFromThisBody); if (shp.bt_shape == mainShape) { - mainShape = NULL; + mainShape = nullptr; } bulletdelete(shp.bt_shape); } diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h index 42ba4aa907..f1423a69e4 100644 --- a/modules/bullet/collision_object_bullet.h +++ b/modules/bullet/collision_object_bullet.h @@ -69,27 +69,22 @@ public: }; struct ShapeWrapper { - ShapeBullet *shape; - btCollisionShape *bt_shape; + ShapeBullet *shape = nullptr; + btCollisionShape *bt_shape = nullptr; btTransform transform; btVector3 scale; - bool active; + bool active = true; - ShapeWrapper() : - shape(NULL), - bt_shape(NULL), - active(true) {} + ShapeWrapper() {} ShapeWrapper(ShapeBullet *p_shape, const btTransform &p_transform, bool p_active) : shape(p_shape), - bt_shape(NULL), active(p_active) { set_transform(p_transform); } ShapeWrapper(ShapeBullet *p_shape, const Transform &p_transform, bool p_active) : shape(p_shape), - bt_shape(NULL), active(p_active) { set_transform(p_transform); } @@ -117,15 +112,15 @@ public: protected: Type type; ObjectID instance_id; - uint32_t collisionLayer; - uint32_t collisionMask; - bool collisionsEnabled; - bool m_isStatic; - bool ray_pickable; - btCollisionObject *bt_collision_object; - Vector3 body_scale; - bool force_shape_reset; - SpaceBullet *space; + uint32_t collisionLayer = 0; + uint32_t collisionMask = 0; + bool collisionsEnabled = true; + bool m_isStatic = false; + bool ray_pickable = false; + btCollisionObject *bt_collision_object = nullptr; + Vector3 body_scale = Vector3(1, 1, 1); + bool force_shape_reset = false; + SpaceBullet *space = nullptr; VSet<RID> exceptions; @@ -133,7 +128,7 @@ protected: /// New area is added when overlap with new area (AreaBullet::addOverlap), then is removed when it exit (CollisionObjectBullet::onExitArea) /// This array is used mainly to know which area hold the pointer of this object Vector<AreaBullet *> areasOverlapped; - bool isTransformChanged; + bool isTransformChanged = false; public: CollisionObjectBullet(Type p_type); @@ -218,11 +213,12 @@ public: class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet { protected: - btCollisionShape *mainShape; + btCollisionShape *mainShape = nullptr; Vector<ShapeWrapper> shapes; public: - RigidCollisionObjectBullet(Type p_type); + RigidCollisionObjectBullet(Type p_type) : + CollisionObjectBullet(p_type) {} ~RigidCollisionObjectBullet(); _FORCE_INLINE_ const Vector<ShapeWrapper> &get_shapes_wrappers() const { return shapes; } diff --git a/modules/bullet/cone_twist_joint_bullet.cpp b/modules/bullet/cone_twist_joint_bullet.cpp index 23eb39fe7e..b4735fa9e9 100644 --- a/modules/bullet/cone_twist_joint_bullet.cpp +++ b/modules/bullet/cone_twist_joint_bullet.cpp @@ -42,7 +42,6 @@ ConeTwistJointBullet::ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &rbAFrame, const Transform &rbBFrame) : JointBullet() { - Transform scaled_AFrame(rbAFrame.scaled(rbA->get_body_scale())); scaled_AFrame.basis.rotref_posscale_decomposition(scaled_AFrame.basis); @@ -50,7 +49,6 @@ ConeTwistJointBullet::ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet G_TO_B(scaled_AFrame, btFrameA); if (rbB) { - Transform scaled_BFrame(rbBFrame.scaled(rbB->get_body_scale())); scaled_BFrame.basis.rotref_posscale_decomposition(scaled_BFrame.basis); @@ -64,43 +62,43 @@ ConeTwistJointBullet::ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet setup(coneConstraint); } -void ConeTwistJointBullet::set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value) { +void ConeTwistJointBullet::set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: + case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: coneConstraint->setLimit(5, p_value); coneConstraint->setLimit(4, p_value); break; - case PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN: + case PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN: coneConstraint->setLimit(3, p_value); break; - case PhysicsServer::CONE_TWIST_JOINT_BIAS: + case PhysicsServer3D::CONE_TWIST_JOINT_BIAS: coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), p_value, coneConstraint->getRelaxationFactor()); break; - case PhysicsServer::CONE_TWIST_JOINT_SOFTNESS: + case PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS: coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), p_value, coneConstraint->getBiasFactor(), coneConstraint->getRelaxationFactor()); break; - case PhysicsServer::CONE_TWIST_JOINT_RELAXATION: + case PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION: coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), coneConstraint->getBiasFactor(), p_value); break; - case PhysicsServer::CONE_TWIST_MAX: + case PhysicsServer3D::CONE_TWIST_MAX: // Internal size value, nothing to do. break; } } -real_t ConeTwistJointBullet::get_param(PhysicsServer::ConeTwistJointParam p_param) const { +real_t ConeTwistJointBullet::get_param(PhysicsServer3D::ConeTwistJointParam p_param) const { switch (p_param) { - case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: + case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: return coneConstraint->getSwingSpan1(); - case PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN: + case PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN: return coneConstraint->getTwistSpan(); - case PhysicsServer::CONE_TWIST_JOINT_BIAS: + case PhysicsServer3D::CONE_TWIST_JOINT_BIAS: return coneConstraint->getBiasFactor(); - case PhysicsServer::CONE_TWIST_JOINT_SOFTNESS: + case PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS: return coneConstraint->getLimitSoftness(); - case PhysicsServer::CONE_TWIST_JOINT_RELAXATION: + case PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION: return coneConstraint->getRelaxationFactor(); - case PhysicsServer::CONE_TWIST_MAX: + case PhysicsServer3D::CONE_TWIST_MAX: // Internal size value, nothing to do. return 0; } diff --git a/modules/bullet/cone_twist_joint_bullet.h b/modules/bullet/cone_twist_joint_bullet.h index 134706f8bb..ed4baa9d1b 100644 --- a/modules/bullet/cone_twist_joint_bullet.h +++ b/modules/bullet/cone_twist_joint_bullet.h @@ -45,9 +45,9 @@ class ConeTwistJointBullet : public JointBullet { public: ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &rbAFrame, const Transform &rbBFrame); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_CONE_TWIST; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_CONE_TWIST; } - void set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::ConeTwistJointParam p_param) const; + void set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::ConeTwistJointParam p_param) const; }; #endif diff --git a/modules/bullet/config.py b/modules/bullet/config.py index 92dbcf5cb0..d22f9454ed 100644 --- a/modules/bullet/config.py +++ b/modules/bullet/config.py @@ -1,14 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass - -def get_doc_classes(): - return [ - "BulletPhysicsDirectBodyState", - "BulletPhysicsServer", - ] - -def get_doc_path(): - return "doc_classes" diff --git a/modules/bullet/constraint_bullet.cpp b/modules/bullet/constraint_bullet.cpp index 7e90e2b488..c47a23e75f 100644 --- a/modules/bullet/constraint_bullet.cpp +++ b/modules/bullet/constraint_bullet.cpp @@ -37,10 +37,7 @@ @author AndreaCatania */ -ConstraintBullet::ConstraintBullet() : - space(NULL), - constraint(NULL), - disabled_collisions_between_bodies(true) {} +ConstraintBullet::ConstraintBullet() {} void ConstraintBullet::setup(btTypedConstraint *p_constraint) { constraint = p_constraint; diff --git a/modules/bullet/constraint_bullet.h b/modules/bullet/constraint_bullet.h index 89ad150257..538808be51 100644 --- a/modules/bullet/constraint_bullet.h +++ b/modules/bullet/constraint_bullet.h @@ -45,11 +45,10 @@ class SpaceBullet; class btTypedConstraint; class ConstraintBullet : public RIDBullet { - protected: - SpaceBullet *space; - btTypedConstraint *constraint; - bool disabled_collisions_between_bodies; + SpaceBullet *space = nullptr; + btTypedConstraint *constraint = nullptr; + bool disabled_collisions_between_bodies = true; public: ConstraintBullet(); @@ -64,7 +63,7 @@ public: public: virtual ~ConstraintBullet() { bulletdelete(constraint); - constraint = NULL; + constraint = nullptr; } _FORCE_INLINE_ btTypedConstraint *get_bt_constraint() { return constraint; } diff --git a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml deleted file mode 100644 index 5ea1b810a1..0000000000 --- a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" version="4.0"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> - <methods> - </methods> - <constants> - </constants> -</class> diff --git a/modules/bullet/doc_classes/BulletPhysicsServer.xml b/modules/bullet/doc_classes/BulletPhysicsServer.xml deleted file mode 100644 index af8fb3c02c..0000000000 --- a/modules/bullet/doc_classes/BulletPhysicsServer.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="BulletPhysicsServer" inherits="PhysicsServer" version="4.0"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> - <methods> - </methods> - <constants> - </constants> -</class> diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp index 45ab3d3bb2..56a66dba45 100644 --- a/modules/bullet/generic_6dof_joint_bullet.cpp +++ b/modules/bullet/generic_6dof_joint_bullet.cpp @@ -42,6 +42,11 @@ Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB) : JointBullet() { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < PhysicsServer3D::G6DOF_JOINT_FLAG_MAX; j++) { + flags[i][j] = false; + } + } Transform scaled_AFrame(frameInA.scaled(rbA->get_body_scale())); @@ -118,62 +123,62 @@ void Generic6DOFJointBullet::set_angular_upper_limit(const Vector3 &angularUpper sixDOFConstraint->setAngularUpperLimit(btVec); } -void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value) { +void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value) { ERR_FAIL_INDEX(p_axis, 3); switch (p_param) { - case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: limits_lower[0][p_axis] = p_value; - set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter + set_flag(p_axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter break; - case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: limits_upper[0][p_axis] = p_value; - set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter + set_flag(p_axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter break; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: limits_lower[1][p_axis] = p_value; - set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter + set_flag(p_axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: limits_upper[1][p_axis] = p_value; - set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter + set_flag(p_axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint = p_value; break; - case PhysicsServer::G6DOF_JOINT_MAX: + case PhysicsServer3D::G6DOF_JOINT_MAX: // Internal size value, nothing to do. break; default: @@ -182,42 +187,42 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO } } -real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param) const { +real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const { ERR_FAIL_INDEX_V(p_axis, 3, 0.); switch (p_param) { - case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: return limits_lower[0][p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: return limits_upper[0][p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: return sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: return sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: return sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: return sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: return limits_lower[1][p_axis]; - case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: return limits_upper[1][p_axis]; - case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce; - case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint; - case PhysicsServer::G6DOF_JOINT_MAX: + case PhysicsServer3D::G6DOF_JOINT_MAX: // Internal size value, nothing to do. return 0; default: @@ -226,45 +231,45 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6 } } -void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value) { +void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value) { ERR_FAIL_INDEX(p_axis, 3); flags[p_axis][p_flag] = p_value; switch (p_flag) { - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: if (flags[p_axis][p_flag]) { sixDOFConstraint->setLimit(p_axis, limits_lower[0][p_axis], limits_upper[0][p_axis]); } else { sixDOFConstraint->setLimit(p_axis, 0, -1); // Free } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: if (flags[p_axis][p_flag]) { sixDOFConstraint->setLimit(p_axis + 3, limits_lower[1][p_axis], limits_upper[1][p_axis]); } else { sixDOFConstraint->setLimit(p_axis + 3, 0, -1); // Free } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableSpring = p_value; break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: sixDOFConstraint->getTranslationalLimitMotor()->m_enableSpring[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableMotor = flags[p_axis][p_flag]; break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag]; break; - case PhysicsServer::G6DOF_JOINT_FLAG_MAX: + case PhysicsServer3D::G6DOF_JOINT_FLAG_MAX: // Internal size value, nothing to do. break; } } -bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const { +bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const { ERR_FAIL_INDEX_V(p_axis, 3, false); return flags[p_axis][p_flag]; } diff --git a/modules/bullet/generic_6dof_joint_bullet.h b/modules/bullet/generic_6dof_joint_bullet.h index 75c8005811..316708bb11 100644 --- a/modules/bullet/generic_6dof_joint_bullet.h +++ b/modules/bullet/generic_6dof_joint_bullet.h @@ -45,12 +45,12 @@ class Generic6DOFJointBullet : public JointBullet { // First is linear second is angular Vector3 limits_lower[2]; Vector3 limits_upper[2]; - bool flags[3][PhysicsServer::G6DOF_JOINT_FLAG_MAX]; + bool flags[3][PhysicsServer3D::G6DOF_JOINT_FLAG_MAX]; public: Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_6DOF; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_6DOF; } Transform getFrameOffsetA() const; Transform getFrameOffsetB() const; @@ -63,11 +63,11 @@ public: void set_angular_lower_limit(const Vector3 &angularLower); void set_angular_upper_limit(const Vector3 &angularUpper); - void set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value); - real_t get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param) const; + void set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value); + real_t get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const; - void set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value); - bool get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const; + void set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value); + bool get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const; void set_precision(int p_precision); int get_precision() const; diff --git a/modules/bullet/godot_collision_configuration.cpp b/modules/bullet/godot_collision_configuration.cpp index f3e3a01a52..ec7a1dbd9a 100644 --- a/modules/bullet/godot_collision_configuration.cpp +++ b/modules/bullet/godot_collision_configuration.cpp @@ -41,8 +41,7 @@ GodotCollisionConfiguration::GodotCollisionConfiguration(const btDiscreteDynamicsWorld *world, const btDefaultCollisionConstructionInfo &constructionInfo) : btDefaultCollisionConfiguration(constructionInfo) { - - void *mem = NULL; + void *mem = nullptr; mem = btAlignedAlloc(sizeof(GodotRayWorldAlgorithm::CreateFunc), 16); m_rayWorldCF = new (mem) GodotRayWorldAlgorithm::CreateFunc(world); @@ -60,45 +59,34 @@ GodotCollisionConfiguration::~GodotCollisionConfiguration() { } btCollisionAlgorithmCreateFunc *GodotCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) { - if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0 && CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) { - // This collision is not supported return m_emptyCreateFunc; } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0) { - return m_rayWorldCF; } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) { - return m_swappedRayWorldCF; } else { - return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0, proxyType1); } } btCollisionAlgorithmCreateFunc *GodotCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) { - if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0 && CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) { - // This collision is not supported return m_emptyCreateFunc; } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0) { - return m_rayWorldCF; } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) { - return m_swappedRayWorldCF; } else { - return btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(proxyType0, proxyType1); } } GodotSoftCollisionConfiguration::GodotSoftCollisionConfiguration(const btDiscreteDynamicsWorld *world, const btDefaultCollisionConstructionInfo &constructionInfo) : btSoftBodyRigidBodyCollisionConfiguration(constructionInfo) { - - void *mem = NULL; + void *mem = nullptr; mem = btAlignedAlloc(sizeof(GodotRayWorldAlgorithm::CreateFunc), 16); m_rayWorldCF = new (mem) GodotRayWorldAlgorithm::CreateFunc(world); @@ -116,37 +104,27 @@ GodotSoftCollisionConfiguration::~GodotSoftCollisionConfiguration() { } btCollisionAlgorithmCreateFunc *GodotSoftCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) { - if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0 && CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) { - // This collision is not supported return m_emptyCreateFunc; } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0) { - return m_rayWorldCF; } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) { - return m_swappedRayWorldCF; } else { - return btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0, proxyType1); } } btCollisionAlgorithmCreateFunc *GodotSoftCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) { - if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0 && CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) { - // This collision is not supported return m_emptyCreateFunc; } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0) { - return m_rayWorldCF; } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) { - return m_swappedRayWorldCF; } else { - return btSoftBodyRigidBodyCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(proxyType0, proxyType1); } } diff --git a/modules/bullet/godot_motion_state.h b/modules/bullet/godot_motion_state.h index e2c1b10e94..90d1614a77 100644 --- a/modules/bullet/godot_motion_state.h +++ b/modules/bullet/godot_motion_state.h @@ -46,7 +46,6 @@ class RigidBodyBullet; /// DOC: /// http://www.bulletphysics.org/mediawiki-1.5.8/index.php/MotionStates#What.27s_a_MotionState.3F class GodotMotionState : public btMotionState { - /// This data is used to store the new world position for kinematic body btTransform bodyKinematicWorldTransf; /// This data is used to store last world position diff --git a/modules/bullet/godot_ray_world_algorithm.cpp b/modules/bullet/godot_ray_world_algorithm.cpp index 2ef277cf5b..a84f3511ba 100644 --- a/modules/bullet/godot_ray_world_algorithm.cpp +++ b/modules/bullet/godot_ray_world_algorithm.cpp @@ -52,7 +52,6 @@ GodotRayWorldAlgorithm::GodotRayWorldAlgorithm(const btDiscreteDynamicsWorld *wo btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap), m_world(world), m_manifoldPtr(mf), - m_ownManifold(false), m_isSwapped(isSwapped) {} GodotRayWorldAlgorithm::~GodotRayWorldAlgorithm() { @@ -62,7 +61,6 @@ GodotRayWorldAlgorithm::~GodotRayWorldAlgorithm() { } void GodotRayWorldAlgorithm::processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut) { - if (!m_manifoldPtr) { if (m_isSwapped) { m_manifoldPtr = m_dispatcher->getNewManifold(body1Wrap->getCollisionObject(), body0Wrap->getCollisionObject()); @@ -80,13 +78,11 @@ void GodotRayWorldAlgorithm::processCollision(const btCollisionObjectWrapper *bo const btCollisionObjectWrapper *other_co_wrapper; if (m_isSwapped) { - ray_shape = static_cast<const btRayShape *>(body1Wrap->getCollisionShape()); ray_transform = body1Wrap->getWorldTransform(); other_co_wrapper = body0Wrap; } else { - ray_shape = static_cast<const btRayShape *>(body0Wrap->getCollisionShape()); ray_transform = body0Wrap->getWorldTransform(); @@ -100,15 +96,15 @@ void GodotRayWorldAlgorithm::processCollision(const btCollisionObjectWrapper *bo m_world->rayTestSingleInternal(ray_transform, to, other_co_wrapper, btResult); if (btResult.hasHit()) { - btScalar depth(ray_shape->getScaledLength() * (btResult.m_closestHitFraction - 1)); - if (depth > -RAY_PENETRATION_DEPTH_EPSILON) + if (depth > -RAY_PENETRATION_DEPTH_EPSILON) { depth = 0.0; + } - if (ray_shape->getSlipsOnSlope()) + if (ray_shape->getSlipsOnSlope()) { resultOut->addContactPoint(btResult.m_hitNormalWorld, btResult.m_hitPointWorld, depth); - else { + } else { resultOut->addContactPoint((ray_transform.getOrigin() - to.getOrigin()).normalize(), btResult.m_hitPointWorld, depth); } } diff --git a/modules/bullet/godot_ray_world_algorithm.h b/modules/bullet/godot_ray_world_algorithm.h index 2cdea6c133..9786732d40 100644 --- a/modules/bullet/godot_ray_world_algorithm.h +++ b/modules/bullet/godot_ray_world_algorithm.h @@ -42,10 +42,9 @@ class btDiscreteDynamicsWorld; class GodotRayWorldAlgorithm : public btActivatingCollisionAlgorithm { - const btDiscreteDynamicsWorld *m_world; btPersistentManifold *m_manifoldPtr; - bool m_ownManifold; + bool m_ownManifold = false; bool m_isSwapped; public: @@ -57,11 +56,11 @@ public: virtual void getAllContactManifolds(btManifoldArray &manifoldArray) { ///should we use m_ownManifold to avoid adding duplicates? - if (m_manifoldPtr && m_ownManifold) + if (m_manifoldPtr && m_ownManifold) { manifoldArray.push_back(m_manifoldPtr); + } } struct CreateFunc : public btCollisionAlgorithmCreateFunc { - const btDiscreteDynamicsWorld *m_world; CreateFunc(const btDiscreteDynamicsWorld *world); @@ -72,7 +71,6 @@ public: }; struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc { - const btDiscreteDynamicsWorld *m_world; SwappedCreateFunc(const btDiscreteDynamicsWorld *world); diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 20467e3ef3..f82648d6ff 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -62,11 +62,13 @@ bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) co CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { - if (!collide_with_areas) + if (!collide_with_areas) { return false; + } } else { - if (!collide_with_bodies) + if (!collide_with_bodies) { return false; + } } if (m_pickRay && !gObj->is_ray_pickable()) { @@ -84,8 +86,9 @@ bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) co } bool GodotAllConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { - if (count >= m_resultMax) + if (count >= m_resultMax) { return false; + } const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask); if (needs) { @@ -102,17 +105,18 @@ bool GodotAllConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) con } btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) { - if (count >= m_resultMax) + if (count >= m_resultMax) { return 1; // not used by bullet + } CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(convexResult.m_hitCollisionObject->getUserPointer()); - PhysicsDirectSpaceState::ShapeResult &result = m_results[count]; + PhysicsDirectSpaceState3D::ShapeResult &result = m_results[count]; result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID result.rid = gObj->get_self(); result.collider_id = gObj->get_instance_id(); - result.collider = result.collider_id.is_null() ? NULL : ObjectDB::get_instance(result.collider_id); + result.collider = result.collider_id.is_null() ? nullptr : ObjectDB::get_instance(result.collider_id); ++count; return 1; // not used by bullet @@ -126,16 +130,18 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox if (gObj == m_self_object) { return false; } else { - // A kinematic body can't be stopped by a rigid body since the mass of kinematic body is infinite - if (m_infinite_inertia && !btObj->isStaticOrKinematicObject()) + if (m_infinite_inertia && !btObj->isStaticOrKinematicObject()) { return false; + } - if (gObj->getType() == CollisionObjectBullet::TYPE_AREA) + if (gObj->getType() == CollisionObjectBullet::TYPE_AREA) { return false; + } - if (m_self_object->has_collision_exception(gObj) || gObj->has_collision_exception(m_self_object)) + if (m_self_object->has_collision_exception(gObj) || gObj->has_collision_exception(m_self_object)) { return false; + } } return true; } else { @@ -150,11 +156,13 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { - if (!collide_with_areas) + if (!collide_with_areas) { return false; + } } else { - if (!collide_with_bodies) + if (!collide_with_bodies) { return false; + } } if (m_exclude->has(gObj->get_self())) { @@ -167,16 +175,18 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) } btScalar GodotClosestConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) { - if (convexResult.m_localShapeInfo) + if (convexResult.m_localShapeInfo) { m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID - else + } else { m_shapeId = 0; + } return btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace); } bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { - if (m_count >= m_resultMax) + if (m_count >= m_resultMax) { return false; + } const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask); if (needs) { @@ -184,11 +194,13 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { - if (!collide_with_areas) + if (!collide_with_areas) { return false; + } } else { - if (!collide_with_bodies) + if (!collide_with_bodies) { return false; + } } if (m_exclude->has(gObj->get_self())) { @@ -201,13 +213,12 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co } btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) { - - if (m_count >= m_resultMax) + if (m_count >= m_resultMax) { return cp.getDistance(); + } if (cp.getDistance() <= 0) { - - PhysicsDirectSpaceState::ShapeResult &result = m_results[m_count]; + PhysicsDirectSpaceState3D::ShapeResult &result = m_results[m_count]; // Penetrated CollisionObjectBullet *colObj; @@ -220,7 +231,7 @@ btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, con } result.collider_id = colObj->get_instance_id(); - result.collider = result.collider_id.is_null() ? NULL : ObjectDB::get_instance(result.collider_id); + result.collider = result.collider_id.is_null() ? nullptr : ObjectDB::get_instance(result.collider_id); result.rid = colObj->get_self(); ++m_count; } @@ -229,8 +240,9 @@ btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, con } bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { - if (m_count >= m_resultMax) + if (m_count >= m_resultMax) { return false; + } const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask); if (needs) { @@ -238,11 +250,13 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { - if (!collide_with_areas) + if (!collide_with_areas) { return false; + } } else { - if (!collide_with_bodies) + if (!collide_with_bodies) { return false; + } } if (m_exclude->has(gObj->get_self())) { @@ -255,8 +269,9 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr } btScalar GodotContactPairContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) { - if (m_count >= m_resultMax) + if (m_count >= m_resultMax) { return 1; // not used by bullet + } if (m_self_object == colObj0Wrap->getCollisionObject()) { B_TO_G(cp.m_localPointA, m_results[m_count * 2 + 0]); // Local contact @@ -278,11 +293,13 @@ bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) { - if (!collide_with_areas) + if (!collide_with_areas) { return false; + } } else { - if (!collide_with_bodies) + if (!collide_with_bodies) { return false; + } } if (m_exclude->has(gObj->get_self())) { @@ -295,7 +312,6 @@ bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy } btScalar GodotRestInfoContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) { - if (cp.getDistance() <= m_min_distance) { m_min_distance = cp.getDistance(); @@ -325,7 +341,6 @@ btScalar GodotRestInfoContactResultCallback::addSingleResult(btManifoldPoint &cp } void GodotDeepPenetrationContactResultCallback::addContactPoint(const btVector3 &normalOnBInWorld, const btVector3 &pointInWorldOnB, btScalar depth) { - if (m_penetration_distance > depth) { // Has penetration? const bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h index 4f634ed6f0..1325542973 100644 --- a/modules/bullet/godot_result_callbacks.h +++ b/modules/bullet/godot_result_callbacks.h @@ -31,7 +31,7 @@ #ifndef GODOT_RESULT_CALLBACKS_H #define GODOT_RESULT_CALLBACKS_H -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include <BulletCollision/BroadphaseCollision/btBroadphaseProxy.h> #include <btBulletDynamicsCommon.h> @@ -56,8 +56,8 @@ struct GodotFilterCallback : public btOverlapFilterCallback { /// It performs an additional check allow exclusions. struct GodotClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback { const Set<RID> *m_exclude; - bool m_pickRay; - int m_shapeId; + bool m_pickRay = false; + int m_shapeId = 0; bool collide_with_bodies; bool collide_with_areas; @@ -66,18 +66,17 @@ public: GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld), m_exclude(p_exclude), - m_pickRay(false), - m_shapeId(0), collide_with_bodies(p_collide_with_bodies), collide_with_areas(p_collide_with_areas) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace) { - if (rayResult.m_localShapeInfo) + if (rayResult.m_localShapeInfo) { m_shapeId = rayResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID - else + } else { m_shapeId = 0; + } return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); } }; @@ -85,16 +84,15 @@ public: // store all colliding object struct GodotAllConvexResultCallback : public btCollisionWorld::ConvexResultCallback { public: - PhysicsDirectSpaceState::ShapeResult *m_results; + PhysicsDirectSpaceState3D::ShapeResult *m_results; int m_resultMax; const Set<RID> *m_exclude; - int count; + int count = 0; - GodotAllConvexResultCallback(PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude) : + GodotAllConvexResultCallback(PhysicsDirectSpaceState3D::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude) : m_results(p_results), m_resultMax(p_resultMax), - m_exclude(p_exclude), - count(0) {} + m_exclude(p_exclude) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; @@ -117,7 +115,7 @@ public: struct GodotClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { public: const Set<RID> *m_exclude; - int m_shapeId; + int m_shapeId = 0; bool collide_with_bodies; bool collide_with_areas; @@ -125,7 +123,6 @@ public: GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld), m_exclude(p_exclude), - m_shapeId(0), collide_with_bodies(p_collide_with_bodies), collide_with_areas(p_collide_with_areas) {} @@ -137,20 +134,19 @@ public: struct GodotAllContactResultCallback : public btCollisionWorld::ContactResultCallback { public: const btCollisionObject *m_self_object; - PhysicsDirectSpaceState::ShapeResult *m_results; + PhysicsDirectSpaceState3D::ShapeResult *m_results; int m_resultMax; const Set<RID> *m_exclude; - int m_count; + int m_count = 0; bool collide_with_bodies; bool collide_with_areas; - GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : + GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState3D::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : m_self_object(p_self_object), m_results(p_results), m_resultMax(p_resultMax), m_exclude(p_exclude), - m_count(0), collide_with_bodies(p_collide_with_bodies), collide_with_areas(p_collide_with_areas) {} @@ -166,7 +162,7 @@ public: Vector3 *m_results; int m_resultMax; const Set<RID> *m_exclude; - int m_count; + int m_count = 0; bool collide_with_bodies; bool collide_with_areas; @@ -176,7 +172,6 @@ public: m_results(p_results), m_resultMax(p_resultMax), m_exclude(p_exclude), - m_count(0), collide_with_bodies(p_collide_with_bodies), collide_with_areas(p_collide_with_areas) {} @@ -188,21 +183,19 @@ public: struct GodotRestInfoContactResultCallback : public btCollisionWorld::ContactResultCallback { public: const btCollisionObject *m_self_object; - PhysicsDirectSpaceState::ShapeRestInfo *m_result; + PhysicsDirectSpaceState3D::ShapeRestInfo *m_result; const Set<RID> *m_exclude; - bool m_collided; - real_t m_min_distance; + bool m_collided = false; + real_t m_min_distance = 0; const btCollisionObject *m_rest_info_collision_object; btVector3 m_rest_info_bt_point; bool collide_with_bodies; bool collide_with_areas; - GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : + GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState3D::ShapeRestInfo *p_result, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : m_self_object(p_self_object), m_result(p_result), m_exclude(p_exclude), - m_collided(false), - m_min_distance(0), collide_with_bodies(p_collide_with_bodies), collide_with_areas(p_collide_with_areas) {} @@ -214,13 +207,11 @@ public: struct GodotDeepPenetrationContactResultCallback : public btManifoldResult { btVector3 m_pointNormalWorld; btVector3 m_pointWorld; - btScalar m_penetration_distance; - int m_other_compound_shape_index; + btScalar m_penetration_distance = 0; + int m_other_compound_shape_index = 0; GodotDeepPenetrationContactResultCallback(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap) : - btManifoldResult(body0Wrap, body1Wrap), - m_penetration_distance(0), - m_other_compound_shape_index(0) {} + btManifoldResult(body0Wrap, body1Wrap) {} void reset() { m_penetration_distance = 0; diff --git a/modules/bullet/hinge_joint_bullet.cpp b/modules/bullet/hinge_joint_bullet.cpp index 970732688a..2338277565 100644 --- a/modules/bullet/hinge_joint_bullet.cpp +++ b/modules/bullet/hinge_joint_bullet.cpp @@ -42,7 +42,6 @@ HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameA, const Transform &frameB) : JointBullet() { - Transform scaled_AFrame(frameA.scaled(rbA->get_body_scale())); scaled_AFrame.basis.rotref_posscale_decomposition(scaled_AFrame.basis); @@ -50,7 +49,6 @@ HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, c G_TO_B(scaled_AFrame, btFrameA); if (rbB) { - Transform scaled_BFrame(frameB.scaled(rbB->get_body_scale())); scaled_BFrame.basis.rotref_posscale_decomposition(scaled_BFrame.basis); @@ -59,7 +57,6 @@ HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, c hingeConstraint = bulletnew(btHingeConstraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btFrameA, btFrameB)); } else { - hingeConstraint = bulletnew(btHingeConstraint(*rbA->get_bt_rigid_body(), btFrameA)); } @@ -68,7 +65,6 @@ HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, c HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB) : JointBullet() { - btVector3 btPivotA; btVector3 btAxisA; G_TO_B(pivotInA * rbA->get_body_scale(), btPivotA); @@ -82,7 +78,6 @@ HingeJointBullet::HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, c hingeConstraint = bulletnew(btHingeConstraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btPivotA, btPivotB, btAxisA, btAxisB)); } else { - hingeConstraint = bulletnew(btHingeConstraint(*rbA->get_bt_rigid_body(), btPivotA, btAxisA)); } @@ -93,58 +88,58 @@ real_t HingeJointBullet::get_hinge_angle() { return hingeConstraint->getHingeAngle(); } -void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) { +void HingeJointBullet::set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::HINGE_JOINT_BIAS: - WARN_DEPRECATED_MSG("The HingeJoint parameter \"bias\" is deprecated."); + case PhysicsServer3D::HINGE_JOINT_BIAS: + WARN_DEPRECATED_MSG("The HingeJoint3D parameter \"bias\" is deprecated."); break; - case PhysicsServer::HINGE_JOINT_LIMIT_UPPER: + case PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), p_value, hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; - case PhysicsServer::HINGE_JOINT_LIMIT_LOWER: + case PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER: hingeConstraint->setLimit(p_value, hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; - case PhysicsServer::HINGE_JOINT_LIMIT_BIAS: + case PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), p_value, hingeConstraint->getLimitRelaxationFactor()); break; - case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS: + case PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), p_value, hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; - case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: + case PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), p_value); break; - case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY: hingeConstraint->setMotorTargetVelocity(p_value); break; - case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: + case PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE: hingeConstraint->setMaxMotorImpulse(p_value); break; - case PhysicsServer::HINGE_JOINT_MAX: + case PhysicsServer3D::HINGE_JOINT_MAX: // Internal size value, nothing to do. break; } } -real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const { +real_t HingeJointBullet::get_param(PhysicsServer3D::HingeJointParam p_param) const { switch (p_param) { - case PhysicsServer::HINGE_JOINT_BIAS: - WARN_DEPRECATED_MSG("The HingeJoint parameter \"bias\" is deprecated."); + case PhysicsServer3D::HINGE_JOINT_BIAS: + WARN_DEPRECATED_MSG("The HingeJoint3D parameter \"bias\" is deprecated."); return 0; - case PhysicsServer::HINGE_JOINT_LIMIT_UPPER: + case PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER: return hingeConstraint->getUpperLimit(); - case PhysicsServer::HINGE_JOINT_LIMIT_LOWER: + case PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER: return hingeConstraint->getLowerLimit(); - case PhysicsServer::HINGE_JOINT_LIMIT_BIAS: + case PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS: return hingeConstraint->getLimitBiasFactor(); - case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS: + case PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS: return hingeConstraint->getLimitSoftness(); - case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: + case PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION: return hingeConstraint->getLimitRelaxationFactor(); - case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY: return hingeConstraint->getMotorTargetVelocity(); - case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: + case PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE: return hingeConstraint->getMaxMotorImpulse(); - case PhysicsServer::HINGE_JOINT_MAX: + case PhysicsServer3D::HINGE_JOINT_MAX: // Internal size value, nothing to do. return 0; } @@ -152,25 +147,26 @@ real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const return 0; } -void HingeJointBullet::set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value) { +void HingeJointBullet::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value) { switch (p_flag) { - case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT: + case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT: if (!p_value) { hingeConstraint->setLimit(-Math_PI, Math_PI); } break; - case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR: + case PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR: hingeConstraint->enableMotor(p_value); break; - case PhysicsServer::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning + case PhysicsServer3D::HINGE_JOINT_FLAG_MAX: + break; // Can't happen, but silences warning } } -bool HingeJointBullet::get_flag(PhysicsServer::HingeJointFlag p_flag) const { +bool HingeJointBullet::get_flag(PhysicsServer3D::HingeJointFlag p_flag) const { switch (p_flag) { - case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT: + case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT: return true; - case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR: + case PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR: return hingeConstraint->getEnableAngularMotor(); default: return false; diff --git a/modules/bullet/hinge_joint_bullet.h b/modules/bullet/hinge_joint_bullet.h index d1061fe52f..120c40e5c0 100644 --- a/modules/bullet/hinge_joint_bullet.h +++ b/modules/bullet/hinge_joint_bullet.h @@ -44,14 +44,14 @@ public: HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameA, const Transform &frameB); HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_HINGE; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_HINGE; } real_t get_hinge_angle(); - void set_param(PhysicsServer::HingeJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::HingeJointParam p_param) const; + void set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::HingeJointParam p_param) const; - void set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value); - bool get_flag(PhysicsServer::HingeJointFlag p_flag) const; + void set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value); + bool get_flag(PhysicsServer3D::HingeJointFlag p_flag) const; }; #endif diff --git a/modules/bullet/joint_bullet.h b/modules/bullet/joint_bullet.h index c840eb8f14..c70cea817e 100644 --- a/modules/bullet/joint_bullet.h +++ b/modules/bullet/joint_bullet.h @@ -32,7 +32,7 @@ #define JOINT_BULLET_H #include "constraint_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" /** @author AndreaCatania @@ -42,11 +42,10 @@ class RigidBodyBullet; class btTypedConstraint; class JointBullet : public ConstraintBullet { - public: JointBullet(); virtual ~JointBullet(); - virtual PhysicsServer::JointType get_type() const = 0; + virtual PhysicsServer3D::JointType get_type() const = 0; }; #endif diff --git a/modules/bullet/pin_joint_bullet.cpp b/modules/bullet/pin_joint_bullet.cpp index 8d109f1866..1cfbc65c78 100644 --- a/modules/bullet/pin_joint_bullet.cpp +++ b/modules/bullet/pin_joint_bullet.cpp @@ -42,7 +42,6 @@ PinJointBullet::PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b) : JointBullet() { if (p_body_b) { - btVector3 btPivotA; btVector3 btPivotB; G_TO_B(p_pos_a * p_body_a->get_body_scale(), btPivotA); @@ -62,27 +61,27 @@ PinJointBullet::PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a PinJointBullet::~PinJointBullet() {} -void PinJointBullet::set_param(PhysicsServer::PinJointParam p_param, real_t p_value) { +void PinJointBullet::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::PIN_JOINT_BIAS: + case PhysicsServer3D::PIN_JOINT_BIAS: p2pConstraint->m_setting.m_tau = p_value; break; - case PhysicsServer::PIN_JOINT_DAMPING: + case PhysicsServer3D::PIN_JOINT_DAMPING: p2pConstraint->m_setting.m_damping = p_value; break; - case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: + case PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP: p2pConstraint->m_setting.m_impulseClamp = p_value; break; } } -real_t PinJointBullet::get_param(PhysicsServer::PinJointParam p_param) const { +real_t PinJointBullet::get_param(PhysicsServer3D::PinJointParam p_param) const { switch (p_param) { - case PhysicsServer::PIN_JOINT_BIAS: + case PhysicsServer3D::PIN_JOINT_BIAS: return p2pConstraint->m_setting.m_tau; - case PhysicsServer::PIN_JOINT_DAMPING: + case PhysicsServer3D::PIN_JOINT_DAMPING: return p2pConstraint->m_setting.m_damping; - case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: + case PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP: return p2pConstraint->m_setting.m_impulseClamp; } // Compiler doesn't seem to notice that all code paths are fulfilled... diff --git a/modules/bullet/pin_joint_bullet.h b/modules/bullet/pin_joint_bullet.h index d6e7a945b5..e7d05f34d4 100644 --- a/modules/bullet/pin_joint_bullet.h +++ b/modules/bullet/pin_joint_bullet.h @@ -46,10 +46,10 @@ public: PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b); ~PinJointBullet(); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_PIN; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_PIN; } - void set_param(PhysicsServer::PinJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::PinJointParam p_param) const; + void set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::PinJointParam p_param) const; void setPivotInA(const Vector3 &p_pos); void setPivotInB(const Vector3 &p_pos); diff --git a/modules/bullet/register_types.cpp b/modules/bullet/register_types.cpp index 7819b67cad..009d0dff63 100644 --- a/modules/bullet/register_types.cpp +++ b/modules/bullet/register_types.cpp @@ -39,15 +39,15 @@ */ #ifndef _3D_DISABLED -PhysicsServer *_createBulletPhysicsCallback() { - return memnew(BulletPhysicsServer); +PhysicsServer3D *_createBulletPhysicsCallback() { + return memnew(BulletPhysicsServer3D); } #endif void register_bullet_types() { #ifndef _3D_DISABLED - PhysicsServerManager::register_server("Bullet", &_createBulletPhysicsCallback); - PhysicsServerManager::set_default_server("Bullet", 1); + PhysicsServer3DManager::register_server("Bullet", &_createBulletPhysicsCallback); + PhysicsServer3DManager::set_default_server("Bullet", 1); GLOBAL_DEF("physics/3d/active_soft_world", true); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/active_soft_world", PropertyInfo(Variant::BOOL, "physics/3d/active_soft_world")); diff --git a/modules/bullet/rid_bullet.h b/modules/bullet/rid_bullet.h index b76641ca54..3551ca05f9 100644 --- a/modules/bullet/rid_bullet.h +++ b/modules/bullet/rid_bullet.h @@ -37,17 +37,17 @@ @author AndreaCatania */ -class BulletPhysicsServer; +class BulletPhysicsServer3D; class RIDBullet { RID self; - BulletPhysicsServer *physicsServer; + BulletPhysicsServer3D *physicsServer; public: _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } _FORCE_INLINE_ RID get_self() const { return self; } - _FORCE_INLINE_ void _set_physics_server(BulletPhysicsServer *p_physicsServer) { physicsServer = p_physicsServer; } - _FORCE_INLINE_ BulletPhysicsServer *get_physics_server() const { return physicsServer; } + _FORCE_INLINE_ void _set_physics_server(BulletPhysicsServer3D *p_physicsServer) { physicsServer = p_physicsServer; } + _FORCE_INLINE_ BulletPhysicsServer3D *get_physics_server() const { return physicsServer; } }; #endif diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 80f42c8441..9aac7ba9e4 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -48,141 +48,141 @@ @author AndreaCatania */ -BulletPhysicsDirectBodyState *BulletPhysicsDirectBodyState::singleton = NULL; +BulletPhysicsDirectBodyState3D *BulletPhysicsDirectBodyState3D::singleton = nullptr; -Vector3 BulletPhysicsDirectBodyState::get_total_gravity() const { +Vector3 BulletPhysicsDirectBodyState3D::get_total_gravity() const { Vector3 gVec; B_TO_G(body->btBody->getGravity(), gVec); return gVec; } -float BulletPhysicsDirectBodyState::get_total_angular_damp() const { +float BulletPhysicsDirectBodyState3D::get_total_angular_damp() const { return body->btBody->getAngularDamping(); } -float BulletPhysicsDirectBodyState::get_total_linear_damp() const { +float BulletPhysicsDirectBodyState3D::get_total_linear_damp() const { return body->btBody->getLinearDamping(); } -Vector3 BulletPhysicsDirectBodyState::get_center_of_mass() const { +Vector3 BulletPhysicsDirectBodyState3D::get_center_of_mass() const { Vector3 gVec; B_TO_G(body->btBody->getCenterOfMassPosition(), gVec); return gVec; } -Basis BulletPhysicsDirectBodyState::get_principal_inertia_axes() const { +Basis BulletPhysicsDirectBodyState3D::get_principal_inertia_axes() const { return Basis(); } -float BulletPhysicsDirectBodyState::get_inverse_mass() const { +float BulletPhysicsDirectBodyState3D::get_inverse_mass() const { return body->btBody->getInvMass(); } -Vector3 BulletPhysicsDirectBodyState::get_inverse_inertia() const { +Vector3 BulletPhysicsDirectBodyState3D::get_inverse_inertia() const { Vector3 gVec; B_TO_G(body->btBody->getInvInertiaDiagLocal(), gVec); return gVec; } -Basis BulletPhysicsDirectBodyState::get_inverse_inertia_tensor() const { +Basis BulletPhysicsDirectBodyState3D::get_inverse_inertia_tensor() const { Basis gInertia; B_TO_G(body->btBody->getInvInertiaTensorWorld(), gInertia); return gInertia; } -void BulletPhysicsDirectBodyState::set_linear_velocity(const Vector3 &p_velocity) { +void BulletPhysicsDirectBodyState3D::set_linear_velocity(const Vector3 &p_velocity) { body->set_linear_velocity(p_velocity); } -Vector3 BulletPhysicsDirectBodyState::get_linear_velocity() const { +Vector3 BulletPhysicsDirectBodyState3D::get_linear_velocity() const { return body->get_linear_velocity(); } -void BulletPhysicsDirectBodyState::set_angular_velocity(const Vector3 &p_velocity) { +void BulletPhysicsDirectBodyState3D::set_angular_velocity(const Vector3 &p_velocity) { body->set_angular_velocity(p_velocity); } -Vector3 BulletPhysicsDirectBodyState::get_angular_velocity() const { +Vector3 BulletPhysicsDirectBodyState3D::get_angular_velocity() const { return body->get_angular_velocity(); } -void BulletPhysicsDirectBodyState::set_transform(const Transform &p_transform) { +void BulletPhysicsDirectBodyState3D::set_transform(const Transform &p_transform) { body->set_transform(p_transform); } -Transform BulletPhysicsDirectBodyState::get_transform() const { +Transform BulletPhysicsDirectBodyState3D::get_transform() const { return body->get_transform(); } -void BulletPhysicsDirectBodyState::add_central_force(const Vector3 &p_force) { +void BulletPhysicsDirectBodyState3D::add_central_force(const Vector3 &p_force) { body->apply_central_force(p_force); } -void BulletPhysicsDirectBodyState::add_force(const Vector3 &p_force, const Vector3 &p_pos) { +void BulletPhysicsDirectBodyState3D::add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->apply_force(p_force, p_pos); } -void BulletPhysicsDirectBodyState::add_torque(const Vector3 &p_torque) { +void BulletPhysicsDirectBodyState3D::add_torque(const Vector3 &p_torque) { body->apply_torque(p_torque); } -void BulletPhysicsDirectBodyState::apply_central_impulse(const Vector3 &p_impulse) { +void BulletPhysicsDirectBodyState3D::apply_central_impulse(const Vector3 &p_impulse) { body->apply_central_impulse(p_impulse); } -void BulletPhysicsDirectBodyState::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { +void BulletPhysicsDirectBodyState3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { body->apply_impulse(p_pos, p_impulse); } -void BulletPhysicsDirectBodyState::apply_torque_impulse(const Vector3 &p_impulse) { +void BulletPhysicsDirectBodyState3D::apply_torque_impulse(const Vector3 &p_impulse) { body->apply_torque_impulse(p_impulse); } -void BulletPhysicsDirectBodyState::set_sleep_state(bool p_enable) { - body->set_activation_state(p_enable); +void BulletPhysicsDirectBodyState3D::set_sleep_state(bool p_sleep) { + body->set_activation_state(!p_sleep); } -bool BulletPhysicsDirectBodyState::is_sleeping() const { +bool BulletPhysicsDirectBodyState3D::is_sleeping() const { return !body->is_active(); } -int BulletPhysicsDirectBodyState::get_contact_count() const { +int BulletPhysicsDirectBodyState3D::get_contact_count() const { return body->collisionsCount; } -Vector3 BulletPhysicsDirectBodyState::get_contact_local_position(int p_contact_idx) const { +Vector3 BulletPhysicsDirectBodyState3D::get_contact_local_position(int p_contact_idx) const { return body->collisions[p_contact_idx].hitLocalLocation; } -Vector3 BulletPhysicsDirectBodyState::get_contact_local_normal(int p_contact_idx) const { +Vector3 BulletPhysicsDirectBodyState3D::get_contact_local_normal(int p_contact_idx) const { return body->collisions[p_contact_idx].hitNormal; } -float BulletPhysicsDirectBodyState::get_contact_impulse(int p_contact_idx) const { +float BulletPhysicsDirectBodyState3D::get_contact_impulse(int p_contact_idx) const { return body->collisions[p_contact_idx].appliedImpulse; } -int BulletPhysicsDirectBodyState::get_contact_local_shape(int p_contact_idx) const { +int BulletPhysicsDirectBodyState3D::get_contact_local_shape(int p_contact_idx) const { return body->collisions[p_contact_idx].local_shape; } -RID BulletPhysicsDirectBodyState::get_contact_collider(int p_contact_idx) const { +RID BulletPhysicsDirectBodyState3D::get_contact_collider(int p_contact_idx) const { return body->collisions[p_contact_idx].otherObject->get_self(); } -Vector3 BulletPhysicsDirectBodyState::get_contact_collider_position(int p_contact_idx) const { +Vector3 BulletPhysicsDirectBodyState3D::get_contact_collider_position(int p_contact_idx) const { return body->collisions[p_contact_idx].hitWorldLocation; } -ObjectID BulletPhysicsDirectBodyState::get_contact_collider_id(int p_contact_idx) const { +ObjectID BulletPhysicsDirectBodyState3D::get_contact_collider_id(int p_contact_idx) const { return body->collisions[p_contact_idx].otherObject->get_instance_id(); } -int BulletPhysicsDirectBodyState::get_contact_collider_shape(int p_contact_idx) const { +int BulletPhysicsDirectBodyState3D::get_contact_collider_shape(int p_contact_idx) const { return body->collisions[p_contact_idx].other_object_shape; } -Vector3 BulletPhysicsDirectBodyState::get_contact_collider_velocity_at_position(int p_contact_idx) const { +Vector3 BulletPhysicsDirectBodyState3D::get_contact_collider_velocity_at_position(int p_contact_idx) const { RigidBodyBullet::CollisionData &colDat = body->collisions.write[p_contact_idx]; btVector3 hitLocation; @@ -194,7 +194,7 @@ Vector3 BulletPhysicsDirectBodyState::get_contact_collider_velocity_at_position( return velocityAtPoint; } -PhysicsDirectSpaceState *BulletPhysicsDirectBodyState::get_space_state() { +PhysicsDirectSpaceState3D *BulletPhysicsDirectBodyState3D::get_space_state() { return body->get_space()->get_direct_state(); } @@ -231,17 +231,17 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() { shapes.write[i].transform = shape_wrapper->transform; shapes.write[i].transform.getOrigin() *= owner_scale; switch (shape_wrapper->shape->get_type()) { - case PhysicsServer::SHAPE_SPHERE: - case PhysicsServer::SHAPE_BOX: - case PhysicsServer::SHAPE_CAPSULE: - case PhysicsServer::SHAPE_CYLINDER: - case PhysicsServer::SHAPE_CONVEX_POLYGON: - case PhysicsServer::SHAPE_RAY: { + case PhysicsServer3D::SHAPE_SPHERE: + case PhysicsServer3D::SHAPE_BOX: + case PhysicsServer3D::SHAPE_CAPSULE: + case PhysicsServer3D::SHAPE_CYLINDER: + case PhysicsServer3D::SHAPE_CONVEX_POLYGON: + case PhysicsServer3D::SHAPE_RAY: { shapes.write[i].shape = static_cast<btConvexShape *>(shape_wrapper->shape->create_bt_shape(owner_scale * shape_wrapper->scale, safe_margin)); } break; default: WARN_PRINT("This shape is not supported for kinematic collision."); - shapes.write[i].shape = NULL; + shapes.write[i].shape = nullptr; } } } @@ -256,42 +256,23 @@ void RigidBodyBullet::KinematicUtilities::just_delete_shapes(int new_size) { } RigidBodyBullet::RigidBodyBullet() : - RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_RIGID_BODY), - kinematic_utilities(NULL), - locked_axis(0), - mass(1), - gravity_scale(1), - linearDamp(0), - angularDamp(0), - can_sleep(true), - omit_forces_integration(false), - can_integrate_forces(false), - maxCollisionsDetection(0), - collisionsCount(0), - prev_collision_count(0), - maxAreasWhereIam(10), - areaWhereIamCount(0), - countGravityPointSpaces(0), - isScratchedSpaceOverrideModificator(false), - previousActiveState(true), - force_integration_callback(NULL) { - + RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_RIGID_BODY) { godotMotionState = bulletnew(GodotMotionState(this)); // Initial properties const btVector3 localInertia(0, 0, 0); - btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, NULL, localInertia); + btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, nullptr, localInertia); btBody = bulletnew(btRigidBody(cInfo)); reload_shapes(); setupBulletCollisionObject(btBody); - set_mode(PhysicsServer::BODY_MODE_RIGID); + set_mode(PhysicsServer3D::BODY_MODE_RIGID); reload_axis_lock(); areasWhereIam.resize(maxAreasWhereIam); for (int i = areasWhereIam.size() - 1; 0 <= i; --i) { - areasWhereIam.write[i] = NULL; + areasWhereIam.write[i] = nullptr; } btBody->setSleepingThresholds(0.2, 0.2); @@ -302,8 +283,9 @@ RigidBodyBullet::RigidBodyBullet() : RigidBodyBullet::~RigidBodyBullet() { bulletdelete(godotMotionState); - if (force_integration_callback) + if (force_integration_callback) { memdelete(force_integration_callback); + } destroy_kinematic_utilities(); } @@ -315,7 +297,7 @@ void RigidBodyBullet::init_kinematic_utilities() { void RigidBodyBullet::destroy_kinematic_utilities() { if (kinematic_utilities) { memdelete(kinematic_utilities); - kinematic_utilities = NULL; + kinematic_utilities = nullptr; } } @@ -328,8 +310,9 @@ void RigidBodyBullet::main_shape_changed() { void RigidBodyBullet::reload_body() { if (space) { space->remove_rigid_body(this); - if (get_main_shape()) + if (get_main_shape()) { space->add_rigid_body(this); + } } } @@ -355,11 +338,11 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) { void RigidBodyBullet::dispatch_callbacks() { /// The check isFirstTransformChanged is necessary in order to call integrated forces only when the first transform is sent if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && can_integrate_forces) { - - if (omit_forces_integration) + if (omit_forces_integration) { btBody->clearForces(); + } - BulletPhysicsDirectBodyState *bodyDirect = BulletPhysicsDirectBodyState::get_singleton(this); + BulletPhysicsDirectBodyState3D *bodyDirect = BulletPhysicsDirectBodyState3D::get_singleton(this); Variant variantBodyDirect = bodyDirect; @@ -389,10 +372,9 @@ void RigidBodyBullet::dispatch_callbacks() { } void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { - if (force_integration_callback) { memdelete(force_integration_callback); - force_integration_callback = NULL; + force_integration_callback = nullptr; } if (p_id.is_valid()) { @@ -416,7 +398,6 @@ void RigidBodyBullet::on_collision_filters_change() { } void RigidBodyBullet::on_collision_checker_start() { - prev_collision_count = collisionsCount; collisionsCount = 0; @@ -432,7 +413,6 @@ void RigidBodyBullet::on_collision_checker_end() { } bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) { - if (collisionsCount >= maxCollisionsDetection) { return false; } @@ -454,8 +434,9 @@ bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const bool RigidBodyBullet::was_colliding(RigidBodyBullet *p_other_object) { for (int i = prev_collision_count - 1; 0 <= i; --i) { - if ((*prev_collision_traces)[i] == p_other_object) + if ((*prev_collision_traces)[i] == p_other_object) { return true; + } } return false; } @@ -464,11 +445,6 @@ void RigidBodyBullet::assert_no_constraints() { if (btBody->getNumConstraintRefs()) { WARN_PRINT("A body with a joints is destroyed. Please check the implementation in order to destroy the joint before the body."); } - /*for(int i = btBody->getNumConstraintRefs()-1; 0<=i; --i){ - btTypedConstraint* btConst = btBody->getConstraintRef(i); - JointBullet* joint = static_cast<JointBullet*>( btConst->getUserConstraintPtr() ); - space->removeConstraint(joint); - }*/ } void RigidBodyBullet::set_activation_state(bool p_active) { @@ -487,31 +463,34 @@ void RigidBodyBullet::set_omit_forces_integration(bool p_omit) { omit_forces_integration = p_omit; } -void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { +void RigidBodyBullet::set_param(PhysicsServer3D::BodyParameter p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::BODY_PARAM_BOUNCE: + case PhysicsServer3D::BODY_PARAM_BOUNCE: btBody->setRestitution(p_value); break; - case PhysicsServer::BODY_PARAM_FRICTION: + case PhysicsServer3D::BODY_PARAM_FRICTION: btBody->setFriction(p_value); break; - case PhysicsServer::BODY_PARAM_MASS: { + case PhysicsServer3D::BODY_PARAM_MASS: { ERR_FAIL_COND(p_value < 0); mass = p_value; _internal_set_mass(p_value); break; } - case PhysicsServer::BODY_PARAM_LINEAR_DAMP: + case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP: linearDamp = p_value; - btBody->setDamping(linearDamp, angularDamp); + // Mark for updating total linear damping. + scratch_space_override_modificator(); break; - case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP: angularDamp = p_value; - btBody->setDamping(linearDamp, angularDamp); + // Mark for updating total angular damping. + scratch_space_override_modificator(); break; - case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: + case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: gravity_scale = p_value; - /// The Bullet gravity will be is set by reload_space_override_modificator + // The Bullet gravity will be is set by reload_space_override_modificator. + // Mark for updating total gravity scale. scratch_space_override_modificator(); break; default: @@ -519,21 +498,21 @@ void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_v } } -real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const { +real_t RigidBodyBullet::get_param(PhysicsServer3D::BodyParameter p_param) const { switch (p_param) { - case PhysicsServer::BODY_PARAM_BOUNCE: + case PhysicsServer3D::BODY_PARAM_BOUNCE: return btBody->getRestitution(); - case PhysicsServer::BODY_PARAM_FRICTION: + case PhysicsServer3D::BODY_PARAM_FRICTION: return btBody->getFriction(); - case PhysicsServer::BODY_PARAM_MASS: { + case PhysicsServer3D::BODY_PARAM_MASS: { const btScalar invMass = btBody->getInvMass(); return 0 == invMass ? 0 : 1 / invMass; } - case PhysicsServer::BODY_PARAM_LINEAR_DAMP: + case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP: return linearDamp; - case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP: return angularDamp; - case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: + case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: return gravity_scale; default: WARN_PRINT("Parameter " + itos(p_param) + " not supported by bullet"); @@ -541,31 +520,31 @@ real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const { } } -void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) { +void RigidBodyBullet::set_mode(PhysicsServer3D::BodyMode p_mode) { // This is necessary to block force_integration untile next move can_integrate_forces = false; destroy_kinematic_utilities(); // The mode change is relevant to its mass switch (p_mode) { - case PhysicsServer::BODY_MODE_KINEMATIC: - mode = PhysicsServer::BODY_MODE_KINEMATIC; + case PhysicsServer3D::BODY_MODE_KINEMATIC: + mode = PhysicsServer3D::BODY_MODE_KINEMATIC; reload_axis_lock(); _internal_set_mass(0); init_kinematic_utilities(); break; - case PhysicsServer::BODY_MODE_STATIC: - mode = PhysicsServer::BODY_MODE_STATIC; + case PhysicsServer3D::BODY_MODE_STATIC: + mode = PhysicsServer3D::BODY_MODE_STATIC; reload_axis_lock(); _internal_set_mass(0); break; - case PhysicsServer::BODY_MODE_RIGID: - mode = PhysicsServer::BODY_MODE_RIGID; + case PhysicsServer3D::BODY_MODE_RIGID: + mode = PhysicsServer3D::BODY_MODE_RIGID; reload_axis_lock(); _internal_set_mass(0 == mass ? 1 : mass); scratch_space_override_modificator(); break; - case PhysicsServer::BODY_MODE_CHARACTER: - mode = PhysicsServer::BODY_MODE_CHARACTER; + case PhysicsServer3D::BODY_MODE_CHARACTER: + mode = PhysicsServer3D::BODY_MODE_CHARACTER; reload_axis_lock(); _internal_set_mass(0 == mass ? 1 : mass); scratch_space_override_modificator(); @@ -575,26 +554,26 @@ void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) { btBody->setAngularVelocity(btVector3(0, 0, 0)); btBody->setLinearVelocity(btVector3(0, 0, 0)); } -PhysicsServer::BodyMode RigidBodyBullet::get_mode() const { + +PhysicsServer3D::BodyMode RigidBodyBullet::get_mode() const { return mode; } -void RigidBodyBullet::set_state(PhysicsServer::BodyState p_state, const Variant &p_variant) { - +void RigidBodyBullet::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) { switch (p_state) { - case PhysicsServer::BODY_STATE_TRANSFORM: + case PhysicsServer3D::BODY_STATE_TRANSFORM: set_transform(p_variant); break; - case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: + case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: set_linear_velocity(p_variant); break; - case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: + case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: set_angular_velocity(p_variant); break; - case PhysicsServer::BODY_STATE_SLEEPING: + case PhysicsServer3D::BODY_STATE_SLEEPING: set_activation_state(!bool(p_variant)); break; - case PhysicsServer::BODY_STATE_CAN_SLEEP: + case PhysicsServer3D::BODY_STATE_CAN_SLEEP: can_sleep = bool(p_variant); if (!can_sleep) { // Can't sleep @@ -606,17 +585,17 @@ void RigidBodyBullet::set_state(PhysicsServer::BodyState p_state, const Variant } } -Variant RigidBodyBullet::get_state(PhysicsServer::BodyState p_state) const { +Variant RigidBodyBullet::get_state(PhysicsServer3D::BodyState p_state) const { switch (p_state) { - case PhysicsServer::BODY_STATE_TRANSFORM: + case PhysicsServer3D::BODY_STATE_TRANSFORM: return get_transform(); - case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: + case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: return get_linear_velocity(); - case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: + case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: return get_angular_velocity(); - case PhysicsServer::BODY_STATE_SLEEPING: + case PhysicsServer3D::BODY_STATE_SLEEPING: return !is_active(); - case PhysicsServer::BODY_STATE_CAN_SLEEP: + case PhysicsServer3D::BODY_STATE_CAN_SLEEP: return can_sleep; default: WARN_PRINT("This state " + itos(p_state) + " is not supported by Bullet"); @@ -627,8 +606,9 @@ Variant RigidBodyBullet::get_state(PhysicsServer::BodyState p_state) const { void RigidBodyBullet::apply_central_impulse(const Vector3 &p_impulse) { btVector3 btImpu; G_TO_B(p_impulse, btImpu); - if (Vector3() != p_impulse) + if (Vector3() != p_impulse) { btBody->activate(); + } btBody->applyCentralImpulse(btImpu); } @@ -637,16 +617,18 @@ void RigidBodyBullet::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impul btVector3 btPos; G_TO_B(p_impulse, btImpu); G_TO_B(p_pos, btPos); - if (Vector3() != p_impulse) + if (Vector3() != p_impulse) { btBody->activate(); + } btBody->applyImpulse(btImpu, btPos); } void RigidBodyBullet::apply_torque_impulse(const Vector3 &p_impulse) { btVector3 btImp; G_TO_B(p_impulse, btImp); - if (Vector3() != p_impulse) + if (Vector3() != p_impulse) { btBody->activate(); + } btBody->applyTorqueImpulse(btImp); } @@ -655,32 +637,36 @@ void RigidBodyBullet::apply_force(const Vector3 &p_force, const Vector3 &p_pos) btVector3 btPos; G_TO_B(p_force, btForce); G_TO_B(p_pos, btPos); - if (Vector3() != p_force) + if (Vector3() != p_force) { btBody->activate(); + } btBody->applyForce(btForce, btPos); } void RigidBodyBullet::apply_central_force(const Vector3 &p_force) { btVector3 btForce; G_TO_B(p_force, btForce); - if (Vector3() != p_force) + if (Vector3() != p_force) { btBody->activate(); + } btBody->applyCentralForce(btForce); } void RigidBodyBullet::apply_torque(const Vector3 &p_torque) { btVector3 btTorq; G_TO_B(p_torque, btTorq); - if (Vector3() != p_torque) + if (Vector3() != p_torque) { btBody->activate(); + } btBody->applyTorque(btTorq); } void RigidBodyBullet::set_applied_force(const Vector3 &p_force) { btVector3 btVec = btBody->getTotalTorque(); - if (Vector3() != p_force) + if (Vector3() != p_force) { btBody->activate(); + } btBody->clearForces(); btBody->applyTorque(btVec); @@ -698,8 +684,9 @@ Vector3 RigidBodyBullet::get_applied_force() const { void RigidBodyBullet::set_applied_torque(const Vector3 &p_torque) { btVector3 btVec = btBody->getTotalForce(); - if (Vector3() != p_torque) + if (Vector3() != p_torque) { btBody->activate(); + } btBody->clearForces(); btBody->applyCentralForce(btVec); @@ -714,7 +701,7 @@ Vector3 RigidBodyBullet::get_applied_torque() const { return gTotTorq; } -void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) { +void RigidBodyBullet::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) { if (lock) { locked_axis |= p_axis; } else { @@ -724,18 +711,17 @@ void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) { reload_axis_lock(); } -bool RigidBodyBullet::is_axis_locked(PhysicsServer::BodyAxis p_axis) const { +bool RigidBodyBullet::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const { return locked_axis & p_axis; } void RigidBodyBullet::reload_axis_lock() { - - btBody->setLinearFactor(btVector3(float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_X)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Y)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Z)))); - if (PhysicsServer::BODY_MODE_CHARACTER == mode) { + btBody->setLinearFactor(btVector3(float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_X)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Y)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Z)))); + if (PhysicsServer3D::BODY_MODE_CHARACTER == mode) { /// When character angular is always locked btBody->setAngularFactor(btVector3(0., 0., 0.)); } else { - btBody->setAngularFactor(btVector3(float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_X)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Y)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Z)))); + btBody->setAngularFactor(btVector3(float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_X)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_Y)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_Z)))); } } @@ -768,8 +754,9 @@ bool RigidBodyBullet::is_continuous_collision_detection_enabled() const { void RigidBodyBullet::set_linear_velocity(const Vector3 &p_velocity) { btVector3 btVec; G_TO_B(p_velocity, btVec); - if (Vector3() != p_velocity) + if (Vector3() != p_velocity) { btBody->activate(); + } btBody->setLinearVelocity(btVec); } @@ -782,8 +769,9 @@ Vector3 RigidBodyBullet::get_linear_velocity() const { void RigidBodyBullet::set_angular_velocity(const Vector3 &p_velocity) { btVector3 btVec; G_TO_B(p_velocity, btVec); - if (Vector3() != p_velocity) + if (Vector3() != p_velocity) { btBody->activate(); + } btBody->setAngularVelocity(btVec); } @@ -794,9 +782,10 @@ Vector3 RigidBodyBullet::get_angular_velocity() const { } void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transform) { - if (mode == PhysicsServer::BODY_MODE_KINEMATIC) { - if (space && space->get_delta_time() != 0) + if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) { + if (space && space->get_delta_time() != 0) { btBody->setLinearVelocity((p_global_transform.getOrigin() - btBody->getWorldTransform().getOrigin()) / space->get_delta_time()); + } // The kinematic use MotionState class godotMotionState->moveBody(p_global_transform); } else { @@ -808,10 +797,8 @@ void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transfor const btTransform &RigidBodyBullet::get_transform__bullet() const { if (is_static()) { - return RigidCollisionObjectBullet::get_transform__bullet(); } else { - return godotMotionState->getCurrentWorldTransform(); } } @@ -827,8 +814,9 @@ void RigidBodyBullet::reload_shapes() { // shapes incorrectly do not set the vector in calculateLocalIntertia. // Arbitrary zero is preferable to undefined behaviour. btVector3 inertia(0, 0, 0); - if (EMPTY_SHAPE_PROXYTYPE != mainShape->getShapeType()) // Necessary to avoid assertion of the empty shape + if (EMPTY_SHAPE_PROXYTYPE != mainShape->getShapeType()) { // Necessary to avoid assertion of the empty shape mainShape->calculateLocalInertia(mass, inertia); + } btBody->setMassProps(mass, inertia); } btBody->updateInertiaTensor(); @@ -846,8 +834,7 @@ void RigidBodyBullet::on_enter_area(AreaBullet *p_area) { return; } for (int i = 0; i < areaWhereIamCount; ++i) { - - if (NULL == areasWhereIam[i]) { + if (nullptr == areasWhereIam[i]) { // This area has the highest priority areasWhereIam.write[i] = p_area; break; @@ -862,7 +849,7 @@ void RigidBodyBullet::on_enter_area(AreaBullet *p_area) { } } } - if (PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { + if (PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { scratch_space_override_modificator(); } @@ -894,39 +881,37 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) { } --areaWhereIamCount; - areasWhereIam.write[areaWhereIamCount] = NULL; // Even if this is not required, I clear the last element to be safe - if (PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { + areasWhereIam.write[areaWhereIamCount] = nullptr; // Even if this is not required, I clear the last element to be safe + if (PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { scratch_space_override_modificator(); } } } void RigidBodyBullet::reload_space_override_modificator() { - // Make sure that kinematic bodies have their total gravity calculated - if (!is_active() && PhysicsServer::BODY_MODE_KINEMATIC != mode) + if (!is_active() && PhysicsServer3D::BODY_MODE_KINEMATIC != mode) { return; + } - Vector3 newGravity(space->get_gravity_direction() * space->get_gravity_magnitude()); - real_t newLinearDamp(linearDamp); - real_t newAngularDamp(angularDamp); + Vector3 newGravity(0.0, 0.0, 0.0); + real_t newLinearDamp = MAX(0.0, linearDamp); + real_t newAngularDamp = MAX(0.0, angularDamp); AreaBullet *currentArea; // Variable used to calculate new gravity for gravity point areas, it is pointed by currentGravity pointer Vector3 support_gravity(0, 0, 0); - int countCombined(0); - for (int i = areaWhereIamCount - 1; 0 <= i; --i) { - + bool stopped = false; + for (int i = areaWhereIamCount - 1; (0 <= i) && !stopped; --i) { currentArea = areasWhereIam[i]; - if (!currentArea || PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED == currentArea->get_spOv_mode()) { + if (!currentArea || PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED == currentArea->get_spOv_mode()) { continue; } /// Here is calculated the gravity if (currentArea->is_spOv_gravityPoint()) { - /// It calculates the direction of new gravity support_gravity = currentArea->get_transform().xform(currentArea->get_spOv_gravityVec()) - get_transform().get_origin(); real_t distanceMag = support_gravity.length(); @@ -954,52 +939,50 @@ void RigidBodyBullet::reload_space_override_modificator() { } switch (currentArea->get_spOv_mode()) { - case PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED: /// This area does not affect gravity/damp. These are generally areas /// that exist only to detect collisions, and objects entering or exiting them. break; - case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: /// This area adds its gravity/damp values to whatever has been /// calculated so far. This way, many overlapping areas can combine /// their physics to make interesting newGravity += support_gravity; newLinearDamp += currentArea->get_spOv_linearDamp(); newAngularDamp += currentArea->get_spOv_angularDamp(); - ++countCombined; break; - case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: /// This area adds its gravity/damp values to whatever has been calculated /// so far. Then stops taking into account the rest of the areas, even the /// default one. newGravity += support_gravity; newLinearDamp += currentArea->get_spOv_linearDamp(); newAngularDamp += currentArea->get_spOv_angularDamp(); - ++countCombined; - goto endAreasCycle; - case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE: + stopped = true; + break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: /// This area replaces any gravity/damp, even the default one, and /// stops taking into account the rest of the areas. newGravity = support_gravity; newLinearDamp = currentArea->get_spOv_linearDamp(); newAngularDamp = currentArea->get_spOv_angularDamp(); - countCombined = 1; - goto endAreasCycle; - case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: + stopped = true; + break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: /// This area replaces any gravity/damp calculated so far, but keeps /// calculating the rest of the areas, down to the default one. newGravity = support_gravity; newLinearDamp = currentArea->get_spOv_linearDamp(); newAngularDamp = currentArea->get_spOv_angularDamp(); - countCombined = 1; break; } } -endAreasCycle: - if (1 < countCombined) { - newGravity /= countCombined; - newLinearDamp /= countCombined; - newAngularDamp /= countCombined; + // Add default gravity and damping from space. + if (!stopped) { + newGravity += space->get_gravity_direction() * space->get_gravity_magnitude(); + newLinearDamp += space->get_linear_damp(); + newAngularDamp += space->get_angular_damp(); } btVector3 newBtGravity; @@ -1022,7 +1005,6 @@ void RigidBodyBullet::notify_transform_changed() { } void RigidBodyBullet::_internal_set_mass(real_t p_mass) { - btVector3 localInertia(0, 0, 0); int clearedCurrentFlags = btBody->getCollisionFlags(); @@ -1031,19 +1013,18 @@ void RigidBodyBullet::_internal_set_mass(real_t p_mass) { // Rigidbody is dynamic if and only if mass is non Zero, otherwise static const bool isDynamic = p_mass != 0.f; if (isDynamic) { - - if (PhysicsServer::BODY_MODE_RIGID != mode && PhysicsServer::BODY_MODE_CHARACTER != mode) + if (PhysicsServer3D::BODY_MODE_RIGID != mode && PhysicsServer3D::BODY_MODE_CHARACTER != mode) { return; + } m_isStatic = false; - if (mainShape) + if (mainShape) { mainShape->calculateLocalInertia(p_mass, localInertia); + } - if (PhysicsServer::BODY_MODE_RIGID == mode) { - + if (PhysicsServer3D::BODY_MODE_RIGID == mode) { btBody->setCollisionFlags(clearedCurrentFlags); // Just set the flags without Kin and Static } else { - btBody->setCollisionFlags(clearedCurrentFlags | btCollisionObject::CF_CHARACTER_OBJECT); } @@ -1053,16 +1034,14 @@ void RigidBodyBullet::_internal_set_mass(real_t p_mass) { btBody->forceActivationState(DISABLE_DEACTIVATION); // DISABLE_DEACTIVATION 4 } } else { - - if (PhysicsServer::BODY_MODE_STATIC != mode && PhysicsServer::BODY_MODE_KINEMATIC != mode) + if (PhysicsServer3D::BODY_MODE_STATIC != mode && PhysicsServer3D::BODY_MODE_KINEMATIC != mode) { return; + } m_isStatic = true; - if (PhysicsServer::BODY_MODE_STATIC == mode) { - + if (PhysicsServer3D::BODY_MODE_STATIC == mode) { btBody->setCollisionFlags(clearedCurrentFlags | btCollisionObject::CF_STATIC_OBJECT); } else { - btBody->setCollisionFlags(clearedCurrentFlags | btCollisionObject::CF_KINEMATIC_OBJECT); set_transform__bullet(btBody->getWorldTransform()); // Set current Transform using kinematic method } diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index ca599f7a77..6d159504b8 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -45,37 +45,37 @@ class AreaBullet; class SpaceBullet; class btRigidBody; class GodotMotionState; -class BulletPhysicsDirectBodyState; +class BulletPhysicsDirectBodyState3D; /// This class could be used in multi thread with few changes but currently /// is set to be only in one single thread. /// /// In the system there is only one object at a time that manage all bodies and is -/// created by BulletPhysicsServer and is held by the "singleton" variable of this class +/// created by BulletPhysicsServer3D and is held by the "singleton" variable of this class /// Each time something require it, the body must be set again. -class BulletPhysicsDirectBodyState : public PhysicsDirectBodyState { - GDCLASS(BulletPhysicsDirectBodyState, PhysicsDirectBodyState); +class BulletPhysicsDirectBodyState3D : public PhysicsDirectBodyState3D { + GDCLASS(BulletPhysicsDirectBodyState3D, PhysicsDirectBodyState3D); - static BulletPhysicsDirectBodyState *singleton; + static BulletPhysicsDirectBodyState3D *singleton; public: /// This class avoid the creation of more object of this class static void initSingleton() { if (!singleton) { - singleton = memnew(BulletPhysicsDirectBodyState); + singleton = memnew(BulletPhysicsDirectBodyState3D); } } static void destroySingleton() { memdelete(singleton); - singleton = NULL; + singleton = nullptr; } static void singleton_setDeltaTime(real_t p_deltaTime) { singleton->deltaTime = p_deltaTime; } - static BulletPhysicsDirectBodyState *get_singleton(RigidBodyBullet *p_body) { + static BulletPhysicsDirectBodyState3D *get_singleton(RigidBodyBullet *p_body) { singleton->body = p_body; return singleton; } @@ -85,7 +85,7 @@ public: real_t deltaTime; private: - BulletPhysicsDirectBodyState() {} + BulletPhysicsDirectBodyState3D() {} public: virtual Vector3 get_total_gravity() const; @@ -117,7 +117,7 @@ public: virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); virtual void apply_torque_impulse(const Vector3 &p_impulse); - virtual void set_sleep_state(bool p_enable); + virtual void set_sleep_state(bool p_sleep); virtual bool is_sleeping() const; virtual int get_contact_count() const; @@ -138,11 +138,10 @@ public: // Skip the execution of this function } - virtual PhysicsDirectSpaceState *get_space_state(); + virtual PhysicsDirectSpaceState3D *get_space_state(); }; class RigidBodyBullet : public RigidCollisionObjectBullet { - public: struct CollisionData { RigidBodyBullet *otherObject; @@ -162,11 +161,10 @@ public: /// Used to hold shapes struct KinematicShape { - class btConvexShape *shape; + class btConvexShape *shape = nullptr; btTransform transform; - KinematicShape() : - shape(NULL) {} + KinematicShape() {} bool is_active() const { return shape; } }; @@ -187,22 +185,22 @@ public: }; private: - friend class BulletPhysicsDirectBodyState; + friend class BulletPhysicsDirectBodyState3D; // This is required only for Kinematic movement - KinematicUtilities *kinematic_utilities; + KinematicUtilities *kinematic_utilities = nullptr; - PhysicsServer::BodyMode mode; + PhysicsServer3D::BodyMode mode; GodotMotionState *godotMotionState; btRigidBody *btBody; - uint16_t locked_axis; - real_t mass; - real_t gravity_scale; - real_t linearDamp; - real_t angularDamp; - bool can_sleep; - bool omit_forces_integration; - bool can_integrate_forces; + uint16_t locked_axis = 0; + real_t mass = 1; + real_t gravity_scale = 1; + real_t linearDamp = 0; + real_t angularDamp = 0; + bool can_sleep = true; + bool omit_forces_integration = false; + bool can_integrate_forces = false; Vector<CollisionData> collisions; Vector<RigidBodyBullet *> collision_traces_1; @@ -211,21 +209,21 @@ private: Vector<RigidBodyBullet *> *curr_collision_traces; // these parameters are used to avoid vector resize - int maxCollisionsDetection; - int collisionsCount; - int prev_collision_count; + int maxCollisionsDetection = 0; + int collisionsCount = 0; + int prev_collision_count = 0; Vector<AreaBullet *> areasWhereIam; // these parameters are used to avoid vector resize - int maxAreasWhereIam; - int areaWhereIamCount; + int maxAreasWhereIam = 10; + int areaWhereIamCount = 0; // Used to know if the area is used as gravity point - int countGravityPointSpaces; - bool isScratchedSpaceOverrideModificator; + int countGravityPointSpaces = 0; + bool isScratchedSpaceOverrideModificator = false; - bool previousActiveState; // Last check state + bool previousActiveState = true; // Last check state - ForceIntegrationCallback *force_integration_callback; + ForceIntegrationCallback *force_integration_callback = nullptr; public: RigidBodyBullet(); @@ -250,7 +248,6 @@ public: virtual void on_collision_checker_end(); void set_max_collisions_detection(int p_maxCollisionsDetection) { - ERR_FAIL_COND(0 > p_maxCollisionsDetection); maxCollisionsDetection = p_maxCollisionsDetection; @@ -278,14 +275,14 @@ public: void set_omit_forces_integration(bool p_omit); _FORCE_INLINE_ bool get_omit_forces_integration() const { return omit_forces_integration; } - void set_param(PhysicsServer::BodyParameter p_param, real_t); - real_t get_param(PhysicsServer::BodyParameter p_param) const; + void set_param(PhysicsServer3D::BodyParameter p_param, real_t); + real_t get_param(PhysicsServer3D::BodyParameter p_param) const; - void set_mode(PhysicsServer::BodyMode p_mode); - PhysicsServer::BodyMode get_mode() const; + void set_mode(PhysicsServer3D::BodyMode p_mode); + PhysicsServer3D::BodyMode get_mode() const; - void set_state(PhysicsServer::BodyState p_state, const Variant &p_variant); - Variant get_state(PhysicsServer::BodyState p_state) const; + void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant); + Variant get_state(PhysicsServer3D::BodyState p_state) const; void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); void apply_central_impulse(const Vector3 &p_impulse); @@ -300,8 +297,8 @@ public: void set_applied_torque(const Vector3 &p_torque); Vector3 get_applied_torque() const; - void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock); - bool is_axis_locked(PhysicsServer::BodyAxis p_axis) const; + void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock); + bool is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const; void reload_axis_lock(); /// Doc: diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index 6780f89d9e..d53f1e7d17 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -46,8 +46,7 @@ @author AndreaCatania */ -ShapeBullet::ShapeBullet() : - margin(0.04) {} +ShapeBullet::ShapeBullet() {} ShapeBullet::~ShapeBullet() {} @@ -81,7 +80,9 @@ void ShapeBullet::add_owner(ShapeOwnerBullet *p_owner) { void ShapeBullet::remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody) { Map<ShapeOwnerBullet *, int>::Element *E = owners.find(p_owner); - if (!E) return; + if (!E) { + return; + } E->get()--; if (p_permanentlyFromThisBody || 0 >= E->get()) { owners.erase(E); @@ -89,7 +90,6 @@ void ShapeBullet::remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFrom } bool ShapeBullet::is_owner(ShapeOwnerBullet *p_owner) const { - return owners.has(p_owner); } @@ -138,7 +138,7 @@ btScaledBvhTriangleMeshShape *ShapeBullet::create_shape_concave(btBvhTriangleMes if (p_mesh_shape) { return bulletnew(btScaledBvhTriangleMeshShape(p_mesh_shape, p_local_scaling)); } else { - return NULL; + return nullptr; } } @@ -150,9 +150,10 @@ btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(Vector<real_t> btHeightfieldTerrainShape *heightfield = bulletnew(btHeightfieldTerrainShape(p_width, p_depth, heightsPtr, ignoredHeightScale, p_min_height, p_max_height, YAxis, PHY_FLOAT, flipQuadEdges)); - // The shape can be created without params when you do PhysicsServer.shape_create(PhysicsServer.SHAPE_HEIGHTMAP) - if (heightsPtr) + // The shape can be created without params when you do PhysicsServer3D.shape_create(PhysicsServer3D.SHAPE_HEIGHTMAP) + if (heightsPtr) { heightfield->buildAccelerator(16); + } return heightfield; } @@ -176,8 +177,8 @@ Variant PlaneShapeBullet::get_data() const { return plane; } -PhysicsServer::ShapeType PlaneShapeBullet::get_type() const { - return PhysicsServer::SHAPE_PLANE; +PhysicsServer3D::ShapeType PlaneShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_PLANE; } void PlaneShapeBullet::setup(const Plane &p_plane) { @@ -204,8 +205,8 @@ Variant SphereShapeBullet::get_data() const { return radius; } -PhysicsServer::ShapeType SphereShapeBullet::get_type() const { - return PhysicsServer::SHAPE_SPHERE; +PhysicsServer3D::ShapeType SphereShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_SPHERE; } void SphereShapeBullet::setup(real_t p_radius) { @@ -231,8 +232,8 @@ Variant BoxShapeBullet::get_data() const { return g_half_extents; } -PhysicsServer::ShapeType BoxShapeBullet::get_type() const { - return PhysicsServer::SHAPE_BOX; +PhysicsServer3D::ShapeType BoxShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_BOX; } void BoxShapeBullet::setup(const Vector3 &p_half_extents) { @@ -263,8 +264,8 @@ Variant CapsuleShapeBullet::get_data() const { return d; } -PhysicsServer::ShapeType CapsuleShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CAPSULE; +PhysicsServer3D::ShapeType CapsuleShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CAPSULE; } void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) { @@ -296,8 +297,8 @@ Variant CylinderShapeBullet::get_data() const { return d; } -PhysicsServer::ShapeType CylinderShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CYLINDER; +PhysicsServer3D::ShapeType CylinderShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CYLINDER; } void CylinderShapeBullet::setup(real_t p_height, real_t p_radius) { @@ -334,8 +335,8 @@ Variant ConvexPolygonShapeBullet::get_data() const { return out_vertices; } -PhysicsServer::ShapeType ConvexPolygonShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CONVEX_POLYGON; +PhysicsServer3D::ShapeType ConvexPolygonShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CONVEX_POLYGON; } void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) { @@ -349,9 +350,10 @@ void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) { } btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { - if (!vertices.size()) + if (!vertices.size()) { // This is necessary since 0 vertices return prepare(ShapeBullet::create_shape_empty()); + } btCollisionShape *cs(ShapeBullet::create_shape_convex(vertices)); cs->setLocalScaling(p_implicit_scale); prepare(cs); @@ -361,8 +363,7 @@ btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_i /* Concave polygon */ ConcavePolygonShapeBullet::ConcavePolygonShapeBullet() : - ShapeBullet(), - meshShape(NULL) {} + ShapeBullet() {} ConcavePolygonShapeBullet::~ConcavePolygonShapeBullet() { if (meshShape) { @@ -381,8 +382,8 @@ Variant ConcavePolygonShapeBullet::get_data() const { return faces; } -PhysicsServer::ShapeType ConcavePolygonShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CONCAVE_POLYGON; +PhysicsServer3D::ShapeType ConcavePolygonShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; } void ConcavePolygonShapeBullet::setup(Vector<Vector3> p_faces) { @@ -395,7 +396,6 @@ void ConcavePolygonShapeBullet::setup(Vector<Vector3> p_faces) { } int src_face_count = faces.size(); if (0 < src_face_count) { - // It counts the faces and assert the array contains the correct number of vertices. ERR_FAIL_COND(src_face_count % 3); @@ -425,7 +425,7 @@ void ConcavePolygonShapeBullet::setup(Vector<Vector3> p_faces) { btGenerateInternalEdgeInfo(meshShape, triangleInfoMap); } } else { - meshShape = NULL; + meshShape = nullptr; ERR_PRINT("The faces count are 0, the mesh shape cannot be created"); } notifyShapeChanged(); @@ -433,9 +433,10 @@ void ConcavePolygonShapeBullet::setup(Vector<Vector3> p_faces) { btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { btCollisionShape *cs = ShapeBullet::create_shape_concave(meshShape); - if (!cs) - // This is necessary since if 0 faces the creation of concave return NULL + if (!cs) { + // This is necessary since if 0 faces the creation of concave return null cs = ShapeBullet::create_shape_empty(); + } cs->setLocalScaling(p_implicit_scale); prepare(cs); cs->setMargin(0); @@ -458,10 +459,12 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) { real_t l_max_height = 0.0; // If specified, min and max height will be used as precomputed values - if (d.has("min_height")) + if (d.has("min_height")) { l_min_height = d["min_height"]; - if (d.has("max_height")) + } + if (d.has("max_height")) { l_max_height = d["max_height"]; + } ERR_FAIL_COND(l_min_height > l_max_height); @@ -514,7 +517,6 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) { // Compute min and max heights if not specified. if (!d.has("min_height") && !d.has("max_height")) { - const real_t *r = l_heights.ptr(); int heights_size = l_heights.size(); @@ -536,8 +538,8 @@ Variant HeightMapShapeBullet::get_data() const { ERR_FAIL_V(Variant()); } -PhysicsServer::ShapeType HeightMapShapeBullet::get_type() const { - return PhysicsServer::SHAPE_HEIGHTMAP; +PhysicsServer3D::ShapeType HeightMapShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_HEIGHTMAP; } void HeightMapShapeBullet::setup(Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) { @@ -562,26 +564,22 @@ btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_impli /* Ray shape */ RayShapeBullet::RayShapeBullet() : - ShapeBullet(), - length(1), - slips_on_slope(false) {} + ShapeBullet() {} void RayShapeBullet::set_data(const Variant &p_data) { - Dictionary d = p_data; setup(d["length"], d["slips_on_slope"]); } Variant RayShapeBullet::get_data() const { - Dictionary d; d["length"] = length; d["slips_on_slope"] = slips_on_slope; return d; } -PhysicsServer::ShapeType RayShapeBullet::get_type() const { - return PhysicsServer::SHAPE_RAY; +PhysicsServer3D::ShapeType RayShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_RAY; } void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) { diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index c8b5ca102a..b24ded574f 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -34,7 +34,7 @@ #include "core/math/geometry.h" #include "core/variant.h" #include "rid_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include <LinearMath/btAlignedObjectArray.h> #include <LinearMath/btScalar.h> @@ -50,9 +50,8 @@ class ShapeOwnerBullet; class btBvhTriangleMeshShape; class ShapeBullet : public RIDBullet { - Map<ShapeOwnerBullet *, int> owners; - real_t margin; + real_t margin = 0.04; protected: /// return self @@ -78,7 +77,7 @@ public: virtual void set_data(const Variant &p_data) = 0; virtual Variant get_data() const = 0; - virtual PhysicsServer::ShapeType get_type() const = 0; + virtual PhysicsServer3D::ShapeType get_type() const = 0; public: static class btEmptyShape *create_shape_empty(); @@ -95,7 +94,6 @@ public: }; class PlaneShapeBullet : public ShapeBullet { - Plane plane; public: @@ -103,7 +101,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -111,7 +109,6 @@ private: }; class SphereShapeBullet : public ShapeBullet { - real_t radius; public: @@ -120,7 +117,7 @@ public: _FORCE_INLINE_ real_t get_radius() { return radius; } virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -128,7 +125,6 @@ private: }; class BoxShapeBullet : public ShapeBullet { - btVector3 half_extents; public: @@ -137,7 +133,7 @@ public: _FORCE_INLINE_ const btVector3 &get_half_extents() { return half_extents; } virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -145,7 +141,6 @@ private: }; class CapsuleShapeBullet : public ShapeBullet { - real_t height; real_t radius; @@ -156,7 +151,7 @@ public: _FORCE_INLINE_ real_t get_radius() { return radius; } virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -164,7 +159,6 @@ private: }; class CylinderShapeBullet : public ShapeBullet { - real_t height; real_t radius; @@ -175,7 +169,7 @@ public: _FORCE_INLINE_ real_t get_radius() { return radius; } virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); private: @@ -183,7 +177,6 @@ private: }; class ConvexPolygonShapeBullet : public ShapeBullet { - public: btAlignedObjectArray<btVector3> vertices; @@ -192,7 +185,7 @@ public: virtual void set_data(const Variant &p_data); void get_vertices(Vector<Vector3> &out_vertices); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -200,7 +193,7 @@ private: }; class ConcavePolygonShapeBullet : public ShapeBullet { - class btBvhTriangleMeshShape *meshShape; + class btBvhTriangleMeshShape *meshShape = nullptr; public: Vector<Vector3> faces; @@ -210,7 +203,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -218,7 +211,6 @@ private: }; class HeightMapShapeBullet : public ShapeBullet { - public: Vector<real_t> heights; int width; @@ -230,7 +222,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -238,16 +230,15 @@ private: }; class RayShapeBullet : public ShapeBullet { - public: - real_t length; - bool slips_on_slope; + real_t length = 1; + bool slips_on_slope = false; RayShapeBullet(); virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: diff --git a/modules/bullet/slider_joint_bullet.cpp b/modules/bullet/slider_joint_bullet.cpp index d9ebb9d580..6d5d95d07a 100644 --- a/modules/bullet/slider_joint_bullet.cpp +++ b/modules/bullet/slider_joint_bullet.cpp @@ -42,7 +42,6 @@ SliderJointBullet::SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB) : JointBullet() { - Transform scaled_AFrame(frameInA.scaled(rbA->get_body_scale())); scaled_AFrame.basis.rotref_posscale_decomposition(scaled_AFrame.basis); @@ -50,7 +49,6 @@ SliderJointBullet::SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, G_TO_B(scaled_AFrame, btFrameA); if (rbB) { - Transform scaled_BFrame(frameInB.scaled(rbB->get_body_scale())); scaled_BFrame.basis.rotref_posscale_decomposition(scaled_BFrame.basis); @@ -121,6 +119,7 @@ real_t SliderJointBullet::getLowerLinLimit() const { void SliderJointBullet::setLowerLinLimit(real_t lowerLimit) { sliderConstraint->setLowerLinLimit(lowerLimit); } + real_t SliderJointBullet::getUpperLinLimit() const { return sliderConstraint->getUpperLinLimit(); } @@ -342,58 +341,125 @@ real_t SliderJointBullet::getLinearPos() { ; } -void SliderJointBullet::set_param(PhysicsServer::SliderJointParam p_param, real_t p_value) { +void SliderJointBullet::set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: setUpperLinLimit(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER: setLowerLinLimit(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: setSoftnessLimLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: setRestitutionLimLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: setDampingLimLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: setSoftnessDirLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: setRestitutionDirLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING: setDampingDirLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: setDampingOrthoLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: setUpperAngLimit(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: setLowerAngLimit(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: setSoftnessLimAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: setRestitutionLimAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: setDampingLimAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: setSoftnessDirAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: setRestitutionDirAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: setDampingDirAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: setDampingOrthoAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER: + setUpperLinLimit(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER: + setLowerLinLimit(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: + setSoftnessLimLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: + setRestitutionLimLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: + setDampingLimLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: + setSoftnessDirLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: + setRestitutionDirLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING: + setDampingDirLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: + setSoftnessOrthoLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: + setRestitutionOrthoLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: + setDampingOrthoLin(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: + setUpperAngLimit(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: + setLowerAngLimit(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: + setSoftnessLimAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: + setRestitutionLimAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: + setDampingLimAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: + setSoftnessDirAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: + setRestitutionDirAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: + setDampingDirAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: + setSoftnessOrthoAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: + setRestitutionOrthoAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: + setDampingOrthoAng(p_value); + break; + case PhysicsServer3D::SLIDER_JOINT_MAX: + break; // Can't happen, but silences warning } } -real_t SliderJointBullet::get_param(PhysicsServer::SliderJointParam p_param) const { +real_t SliderJointBullet::get_param(PhysicsServer3D::SliderJointParam p_param) const { switch (p_param) { - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return getUpperLinLimit(); - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER: return getLowerLinLimit(); - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: return getSoftnessLimLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: return getRestitutionLimLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: return getDampingLimLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: return getSoftnessDirLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: return getRestitutionDirLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING: return getDampingDirLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: return getSoftnessOrthoLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: return getRestitutionOrthoLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: return getDampingOrthoLin(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: return getUpperAngLimit(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: return getLowerAngLimit(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: return getSoftnessLimAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: return getRestitutionLimAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: return getDampingLimAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: return getSoftnessDirAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: return getRestitutionDirAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: return getDampingDirAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: return getSoftnessOrthoAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: return getRestitutionOrthoAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: return getDampingOrthoAng(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER: + return getUpperLinLimit(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER: + return getLowerLinLimit(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: + return getSoftnessLimLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: + return getRestitutionLimLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: + return getDampingLimLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: + return getSoftnessDirLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: + return getRestitutionDirLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING: + return getDampingDirLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: + return getSoftnessOrthoLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: + return getRestitutionOrthoLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: + return getDampingOrthoLin(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: + return getUpperAngLimit(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: + return getLowerAngLimit(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: + return getSoftnessLimAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: + return getRestitutionLimAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: + return getDampingLimAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: + return getSoftnessDirAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: + return getRestitutionDirAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: + return getDampingDirAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: + return getSoftnessOrthoAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: + return getRestitutionOrthoAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: + return getDampingOrthoAng(); default: return 0; } diff --git a/modules/bullet/slider_joint_bullet.h b/modules/bullet/slider_joint_bullet.h index d98a1b8c95..6410b952ed 100644 --- a/modules/bullet/slider_joint_bullet.h +++ b/modules/bullet/slider_joint_bullet.h @@ -46,7 +46,7 @@ public: /// Reference frame is A SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_SLIDER; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_SLIDER; } const RigidBodyBullet *getRigidBodyA() const; const RigidBodyBullet *getRigidBodyB() const; @@ -115,7 +115,7 @@ public: real_t getMaxAngMotorForce(); real_t getLinearPos(); - void set_param(PhysicsServer::SliderJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::SliderJointParam p_param) const; + void set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::SliderJointParam p_param) const; }; #endif diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index f21206dd0d..6794d6c313 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -32,22 +32,11 @@ #include "bullet_types_converter.h" #include "bullet_utilities.h" -#include "scene/3d/soft_body.h" +#include "scene/3d/soft_body_3d.h" #include "space_bullet.h" SoftBodyBullet::SoftBodyBullet() : - CollisionObjectBullet(CollisionObjectBullet::TYPE_SOFT_BODY), - bt_soft_body(NULL), - isScratched(false), - simulation_precision(5), - total_mass(1.), - linear_stiffness(0.5), - areaAngular_stiffness(0.5), - volume_stiffness(0.5), - pressure_coefficient(0.), - pose_matching_coefficient(0.), - damping_coefficient(0.01), - drag_coefficient(0.) {} + CollisionObjectBullet(CollisionObjectBullet::TYPE_SOFT_BODY) {} SoftBodyBullet::~SoftBodyBullet() { } @@ -76,9 +65,10 @@ void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {} void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {} -void SoftBodyBullet::update_visual_server(SoftBodyVisualServerHandler *p_visual_server_handler) { - if (!bt_soft_body) +void SoftBodyBullet::update_rendering_server(SoftBodyRenderingServerHandler *p_rendering_server_handler) { + if (!bt_soft_body) { return; + } /// Update visual server vertices const btSoftBody::tNodeArray &nodes(bt_soft_body->m_nodes); @@ -96,8 +86,8 @@ void SoftBodyBullet::update_visual_server(SoftBodyVisualServerHandler *p_visual_ const int vs_indices_size(vs_indices->size()); for (int x = 0; x < vs_indices_size; ++x) { - p_visual_server_handler->set_vertex((*vs_indices)[x], vertex_position); - p_visual_server_handler->set_normal((*vs_indices)[x], vertex_normal); + p_rendering_server_handler->set_vertex((*vs_indices)[x], vertex_position); + p_rendering_server_handler->set_normal((*vs_indices)[x], vertex_normal); } } @@ -112,31 +102,30 @@ void SoftBodyBullet::update_visual_server(SoftBodyVisualServerHandler *p_visual_ B_TO_G(aabb_min, aabb.position); B_TO_G(size, aabb.size); - p_visual_server_handler->set_aabb(aabb); + p_rendering_server_handler->set_aabb(aabb); } void SoftBodyBullet::set_soft_mesh(const Ref<Mesh> &p_mesh) { - - if (p_mesh.is_null()) + if (p_mesh.is_null()) { soft_mesh.unref(); - else + } else { soft_mesh = p_mesh; + } if (soft_mesh.is_null()) { - destroy_soft_body(); return; } Array arrays = soft_mesh->surface_get_arrays(0); - ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & VS::ARRAY_FORMAT_INDEX)); - set_trimesh_body_shape(arrays[VS::ARRAY_INDEX], arrays[VS::ARRAY_VERTEX]); + ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & RS::ARRAY_FORMAT_INDEX)); + set_trimesh_body_shape(arrays[RS::ARRAY_INDEX], arrays[RS::ARRAY_VERTEX]); } void SoftBodyBullet::destroy_soft_body() { - - if (!bt_soft_body) + if (!bt_soft_body) { return; + } if (space) { /// Remove from world before deletion @@ -144,7 +133,7 @@ void SoftBodyBullet::destroy_soft_body() { } destroyBulletCollisionObject(); - bt_soft_body = NULL; + bt_soft_body = nullptr; } void SoftBodyBullet::set_soft_transform(const Transform &p_transform) { @@ -153,8 +142,9 @@ void SoftBodyBullet::set_soft_transform(const Transform &p_transform) { } void SoftBodyBullet::move_all_nodes(const Transform &p_transform) { - if (!bt_soft_body) + if (!bt_soft_body) { return; + } btTransform bt_transf; G_TO_B(p_transform, bt_transf); bt_soft_body->transform(bt_transf); @@ -180,11 +170,12 @@ void SoftBodyBullet::get_node_position(int p_node_index, Vector3 &r_position) co } void SoftBodyBullet::get_node_offset(int p_node_index, Vector3 &r_offset) const { - if (soft_mesh.is_null()) + if (soft_mesh.is_null()) { return; + } Array arrays = soft_mesh->surface_get_arrays(0); - Vector<Vector3> vertices(arrays[VS::ARRAY_VERTEX]); + Vector<Vector3> vertices(arrays[RS::ARRAY_VERTEX]); if (0 <= p_node_index && vertices.size() > p_node_index) { r_offset = vertices[p_node_index]; @@ -226,15 +217,15 @@ void SoftBodyBullet::reset_all_node_mass() { } void SoftBodyBullet::reset_all_node_positions() { - if (soft_mesh.is_null()) + if (soft_mesh.is_null()) { return; + } Array arrays = soft_mesh->surface_get_arrays(0); - Vector<Vector3> vs_vertices(arrays[VS::ARRAY_VERTEX]); + Vector<Vector3> vs_vertices(arrays[RS::ARRAY_VERTEX]); const Vector3 *vs_vertices_read = vs_vertices.ptr(); for (int vertex_index = bt_soft_body->m_nodes.size() - 1; 0 <= vertex_index; --vertex_index) { - G_TO_B(vs_vertices_read[indices_table[vertex_index][0]], bt_soft_body->m_nodes[vertex_index].m_x); bt_soft_body->m_nodes[vertex_index].m_q = bt_soft_body->m_nodes[vertex_index].m_x; @@ -342,7 +333,6 @@ void SoftBodyBullet::set_trimesh_body_shape(Vector<int> p_indices, Vector<Vector const Vector3 *p_vertices_read = p_vertices.ptr(); for (int vs_vertex_index = 0; vs_vertex_index < vs_vertices_size; ++vs_vertex_index) { - Map<Vector3, int>::Element *e = unique_vertices.find(p_vertices_read[vs_vertex_index]); int vertex_id; if (e) { @@ -398,13 +388,13 @@ void SoftBodyBullet::set_trimesh_body_shape(Vector<int> p_indices, Vector<Vector } void SoftBodyBullet::setup_soft_body() { - - if (!bt_soft_body) + if (!bt_soft_body) { return; + } // Soft body setup setupBulletCollisionObject(bt_soft_body); - bt_soft_body->m_worldInfo = NULL; // Remove fake world info + bt_soft_body->m_worldInfo = nullptr; // Remove fake world info bt_soft_body->getCollisionShape()->setMargin(0.01); bt_soft_body->setCollisionFlags(bt_soft_body->getCollisionFlags() & (~(btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT))); diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h index 05d7e6ce3f..da8a2412ed 100644 --- a/modules/bullet/soft_body_bullet.h +++ b/modules/bullet/soft_body_bullet.h @@ -43,7 +43,7 @@ #include "BulletSoftBody/btSoftBodyHelpers.h" #include "collision_object_bullet.h" #include "scene/resources/mesh.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #ifdef x11_None /// This is required to re add the macro None defined by x11 compiler @@ -56,24 +56,23 @@ */ class SoftBodyBullet : public CollisionObjectBullet { - private: - btSoftBody *bt_soft_body; + btSoftBody *bt_soft_body = nullptr; Vector<Vector<int>> indices_table; btSoftBody::Material *mat0; // This is just a copy of pointer managed by btSoftBody - bool isScratched; + bool isScratched = false; Ref<Mesh> soft_mesh; - int simulation_precision; - real_t total_mass; - real_t linear_stiffness; // [0,1] - real_t areaAngular_stiffness; // [0,1] - real_t volume_stiffness; // [0,1] - real_t pressure_coefficient; // [-inf,+inf] - real_t pose_matching_coefficient; // [0,1] - real_t damping_coefficient; // [0,1] - real_t drag_coefficient; // [0,1] + int simulation_precision = 5; + real_t total_mass = 1.; + real_t linear_stiffness = 0.5; // [0,1] + real_t areaAngular_stiffness = 0.5; // [0,1] + real_t volume_stiffness = 0.5; // [0,1] + real_t pressure_coefficient = 0.; // [-inf,+inf] + real_t pose_matching_coefficient = 0.; // [0,1] + real_t damping_coefficient = 0.01; // [0,1] + real_t drag_coefficient = 0.; // [0,1] Vector<int> pinned_nodes; // Other property to add @@ -100,7 +99,7 @@ public: _FORCE_INLINE_ btSoftBody *get_bt_soft_body() const { return bt_soft_body; } - void update_visual_server(class SoftBodyVisualServerHandler *p_visual_server_handler); + void update_rendering_server(class SoftBodyRenderingServerHandler *p_rendering_server_handler); void set_soft_mesh(const Ref<Mesh> &p_mesh); void destroy_soft_body(); diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index f6df97f11d..99f58e7059 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -39,7 +39,7 @@ #include "godot_collision_configuration.h" #include "godot_collision_dispatcher.h" #include "rigid_body_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include "soft_body_bullet.h" #include <BulletCollision/BroadphaseCollision/btBroadphaseProxy.h> @@ -59,13 +59,13 @@ */ BulletPhysicsDirectSpaceState::BulletPhysicsDirectSpaceState(SpaceBullet *p_space) : - PhysicsDirectSpaceState(), + PhysicsDirectSpaceState3D(), space(p_space) {} int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - - if (p_result_max <= 0) + if (p_result_max <= 0) { return 0; + } btVector3 bt_point; G_TO_B(p_point, bt_point); @@ -86,7 +86,6 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape } bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { - btVector3 btVec_from; btVector3 btVec_to; @@ -108,7 +107,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V r_result.shape = btResult.m_shapeId; r_result.rid = gObj->get_self(); r_result.collider_id = gObj->get_instance_id(); - r_result.collider = r_result.collider_id.is_null() ? NULL : ObjectDB::get_instance(r_result.collider_id); + r_result.collider = r_result.collider_id.is_null() ? nullptr : ObjectDB::get_instance(r_result.collider_id); } else { WARN_PRINT("The raycast performed has hit a collision object that is not part of Godot scene, please check it."); } @@ -119,8 +118,9 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V } int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - if (p_result_max <= 0) + if (p_result_max <= 0) { return 0; + } ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); @@ -204,8 +204,9 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf /// Returns the list of contacts pairs in this order: Local contact, other body contact bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - if (p_result_max <= 0) - return 0; + if (p_result_max <= 0) { + return false; + } ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); @@ -213,7 +214,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINT("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); - return 0; + return false; } btConvexShape *btConvex = static_cast<btConvexShape *>(btShape); @@ -238,14 +239,13 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & } bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINT("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); - return 0; + return false; } btConvexShape *btConvex = static_cast<btConvexShape *>(btShape); @@ -276,7 +276,6 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh } Vector3 BulletPhysicsDirectSpaceState::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const { - RigidCollisionObjectBullet *rigid_object = space->get_physics_server()->get_rigid_collisin_object(p_object); ERR_FAIL_COND_V(!rigid_object, Vector3()); @@ -309,7 +308,7 @@ Vector3 BulletPhysicsDirectSpaceState::get_closest_point_to_object_volume(RID p_ btPointCollector result; btGjkPairDetector gjk_pair_detector(&point_shape, convex_shape, space->gjk_simplex_solver, space->gjk_epa_pen_solver); - gjk_pair_detector.getClosestPoints(input, result, 0); + gjk_pair_detector.getClosestPoints(input, result, nullptr); if (out_distance > result.m_distance) { out_distance = result.m_distance; @@ -320,31 +319,16 @@ Vector3 BulletPhysicsDirectSpaceState::get_closest_point_to_object_volume(RID p_ } if (shapes_found) { - Vector3 out; B_TO_G(out_closest_point, out); return out; } else { - // no shapes found, use distance to origin. return rigid_object->get_transform().get_origin(); } } -SpaceBullet::SpaceBullet() : - broadphase(NULL), - collisionConfiguration(NULL), - dispatcher(NULL), - solver(NULL), - dynamicsWorld(NULL), - soft_body_world_info(NULL), - ghostPairCallback(NULL), - godotFilterCallback(NULL), - gravityDirection(0, -1, 0), - gravityMagnitude(10), - contactDebugCount(0), - delta_time(0.) { - +SpaceBullet::SpaceBullet() { create_empty_world(GLOBAL_DEF("physics/3d/active_soft_world", true)); direct_access = memnew(BulletPhysicsDirectSpaceState(this)); } @@ -366,27 +350,30 @@ void SpaceBullet::step(real_t p_delta_time) { dynamicsWorld->stepSimulation(p_delta_time, 0, 0); } -void SpaceBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value) { +void SpaceBullet::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { assert(dynamicsWorld); switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: + case PhysicsServer3D::AREA_PARAM_GRAVITY: gravityMagnitude = p_value; update_gravity(); break; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: gravityDirection = p_value; update_gravity(); break; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: - break; // No damp - case PhysicsServer::AREA_PARAM_PRIORITY: + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: + linear_damp = p_value; + break; + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: + angular_damp = p_value; + break; + case PhysicsServer3D::AREA_PARAM_PRIORITY: // Priority is always 0, the lower break; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: break; default: WARN_PRINT("This set parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it."); @@ -394,22 +381,23 @@ void SpaceBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant } } -Variant SpaceBullet::get_param(PhysicsServer::AreaParameter p_param) { +Variant SpaceBullet::get_param(PhysicsServer3D::AreaParameter p_param) { switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: + case PhysicsServer3D::AREA_PARAM_GRAVITY: return gravityMagnitude; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: return gravityDirection; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: - return 0; // No damp - case PhysicsServer::AREA_PARAM_PRIORITY: + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: + return linear_damp; + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: + return angular_damp; + case PhysicsServer3D::AREA_PARAM_PRIORITY: return 0; // Priority is always 0, the lower - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: return false; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return 0; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return 0; default: WARN_PRINT("This get parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it."); @@ -417,32 +405,32 @@ Variant SpaceBullet::get_param(PhysicsServer::AreaParameter p_param) { } } -void SpaceBullet::set_param(PhysicsServer::SpaceParameter p_param, real_t p_value) { +void SpaceBullet::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: - case PhysicsServer::SPACE_PARAM_CONTACT_MAX_SEPARATION: - case PhysicsServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: - case PhysicsServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: - case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: - case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: + case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: + case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_SEPARATION: + case PhysicsServer3D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: + case PhysicsServer3D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: + case PhysicsServer3D::SPACE_PARAM_BODY_TIME_TO_SLEEP: + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: + case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: default: WARN_PRINT("This set parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it."); break; } } -real_t SpaceBullet::get_param(PhysicsServer::SpaceParameter p_param) { +real_t SpaceBullet::get_param(PhysicsServer3D::SpaceParameter p_param) { switch (p_param) { - case PhysicsServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: - case PhysicsServer::SPACE_PARAM_CONTACT_MAX_SEPARATION: - case PhysicsServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: - case PhysicsServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: - case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: - case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: + case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: + case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_SEPARATION: + case PhysicsServer3D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: + case PhysicsServer3D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: + case PhysicsServer3D::SPACE_PARAM_BODY_TIME_TO_SLEEP: + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: + case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: default: WARN_PRINT("The SpaceBullet doesn't support this get parameter (" + itos(p_param) + "), 0 is returned."); return 0.f; @@ -511,7 +499,7 @@ void SpaceBullet::remove_soft_body(SoftBodyBullet *p_body) { if (is_using_soft_world()) { if (p_body->get_bt_soft_body()) { static_cast<btSoftRigidDynamicsWorld *>(dynamicsWorld)->removeSoftBody(p_body->get_bt_soft_body()); - p_body->get_bt_soft_body()->m_worldInfo = NULL; + p_body->get_bt_soft_body()->m_worldInfo = nullptr; } } } @@ -539,7 +527,7 @@ void SpaceBullet::remove_all_collision_objects() { for (int i = dynamicsWorld->getNumCollisionObjects() - 1; 0 <= i; --i) { btCollisionObject *btObj = dynamicsWorld->getCollisionObjectArray()[i]; CollisionObjectBullet *colObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); - colObj->set_space(NULL); + colObj->set_space(nullptr); } } @@ -548,7 +536,6 @@ void onBulletPreTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep } void onBulletTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) { - const btCollisionObjectArray &colObjArray = p_dynamicsWorld->getCollisionObjectArray(); // Notify all Collision objects the collision checker is started @@ -570,17 +557,14 @@ BulletPhysicsDirectSpaceState *SpaceBullet::get_direct_state() { } btScalar calculateGodotCombinedRestitution(const btCollisionObject *body0, const btCollisionObject *body1) { - return CLAMP(body0->getRestitution() + body1->getRestitution(), 0, 1); } btScalar calculateGodotCombinedFriction(const btCollisionObject *body0, const btCollisionObject *body1) { - return ABS(MIN(body0->getFriction(), body1->getFriction())); } void SpaceBullet::create_empty_world(bool p_create_soft_world) { - gjk_epa_pen_solver = bulletnew(btGjkEpaPenetrationDepthSolver); gjk_simplex_solver = bulletnew(btVoronoiSimplexSolver); @@ -633,11 +617,10 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) { } void SpaceBullet::destroy_world() { - /// The world elements (like: Collision Objects, Constraints, Shapes) are managed by godot - dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(NULL); - dynamicsWorld->getPairCache()->setOverlapFilterCallback(NULL); + dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(nullptr); + dynamicsWorld->getPairCache()->setOverlapFilterCallback(nullptr); bulletdelete(ghostPairCallback); bulletdelete(godotFilterCallback); @@ -645,7 +628,7 @@ void SpaceBullet::destroy_world() { // Deallocate world dynamicsWorld->~btDiscreteDynamicsWorld(); free(dynamicsWorld); - dynamicsWorld = NULL; + dynamicsWorld = nullptr; bulletdelete(solver); bulletdelete(broadphase); @@ -657,7 +640,6 @@ void SpaceBullet::destroy_world() { } void SpaceBullet::check_ghost_overlaps() { - /// Algorithm support variables btCollisionShape *other_body_shape; btConvexShape *area_shape; @@ -671,8 +653,9 @@ void SpaceBullet::check_ghost_overlaps() { btVector3 area_scale(area->get_bt_body_scale()); - if (!area->is_monitoring()) + if (!area->is_monitoring()) { continue; + } /// 1. Reset all states for (i = area->overlappingObjects.size() - 1; 0 <= i; --i) { @@ -690,7 +673,6 @@ void SpaceBullet::check_ghost_overlaps() { // For each overlapping for (i = ghostOverlaps.size() - 1; 0 <= i; --i) { - bool hasOverlap = false; btCollisionObject *overlapped_bt_co = ghostOverlaps[i]; RigidCollisionObjectBullet *otherObject = static_cast<RigidCollisionObjectBullet *>(overlapped_bt_co->getUserPointer()); @@ -702,15 +684,18 @@ void SpaceBullet::check_ghost_overlaps() { } if (overlapped_bt_co->getUserIndex() == CollisionObjectBullet::TYPE_AREA) { - if (!static_cast<AreaBullet *>(overlapped_bt_co->getUserPointer())->is_monitorable()) + if (!static_cast<AreaBullet *>(overlapped_bt_co->getUserPointer())->is_monitorable()) { continue; - } else if (overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY) + } + } else if (overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY) { continue; + } // For each area shape for (y = area->get_shape_count() - 1; 0 <= y; --y) { - if (!area->get_bt_shape(y)->isConvex()) + if (!area->get_bt_shape(y)->isConvex()) { continue; + } btTransform area_shape_treansform(area->get_bt_shape_transform(y)); area_shape_treansform.getOrigin() *= area_scale; @@ -723,7 +708,6 @@ void SpaceBullet::check_ghost_overlaps() { // For each other object shape for (z = otherObject->get_shape_count() - 1; 0 <= z; --z) { - other_body_shape = static_cast<btCollisionShape *>(otherObject->get_bt_shape(z)); btTransform other_shape_transform(otherObject->get_bt_shape_transform(z)); @@ -734,14 +718,13 @@ void SpaceBullet::check_ghost_overlaps() { other_shape_transform; if (other_body_shape->isConvex()) { - btPointCollector result; btGjkPairDetector gjk_pair_detector( area_shape, static_cast<btConvexShape *>(other_body_shape), gjk_simplex_solver, gjk_epa_pen_solver); - gjk_pair_detector.getClosestPoints(gjk_input, result, 0); + gjk_pair_detector.getClosestPoints(gjk_input, result, nullptr); if (0 >= result.m_distance) { hasOverlap = true; @@ -749,14 +732,14 @@ void SpaceBullet::check_ghost_overlaps() { } } else { + btCollisionObjectWrapper obA(nullptr, area_shape, area->get_bt_ghost(), gjk_input.m_transformA, -1, y); + btCollisionObjectWrapper obB(nullptr, other_body_shape, otherObject->get_bt_collision_object(), gjk_input.m_transformB, -1, z); - btCollisionObjectWrapper obA(NULL, area_shape, area->get_bt_ghost(), gjk_input.m_transformA, -1, y); - btCollisionObjectWrapper obB(NULL, other_body_shape, otherObject->get_bt_collision_object(), gjk_input.m_transformB, -1, z); + btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, nullptr, BT_CONTACT_POINT_ALGORITHMS); - btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CONTACT_POINT_ALGORITHMS); - - if (!algorithm) + if (!algorithm) { continue; + } GodotDeepPenetrationContactResultCallback contactPointResult(&obA, &obB); algorithm->processCollision(&obA, &obB, dynamicsWorld->getDispatchInfo(), &contactPointResult); @@ -774,8 +757,9 @@ void SpaceBullet::check_ghost_overlaps() { } // ~For each area shape collision_found: - if (!hasOverlap) + if (!hasOverlap) { continue; + } indexOverlap = area->find_overlapping_object(otherObject); if (-1 == indexOverlap) { @@ -832,7 +816,6 @@ void SpaceBullet::check_body_collision() { pt.getDistance() <= 0.0 || bodyA->was_colliding(bodyB) || bodyB->was_colliding(bodyA)) { - Vector3 collisionWorldPosition; Vector3 collisionLocalPosition; Vector3 normalOnB; @@ -885,20 +868,19 @@ void SpaceBullet::update_gravity() { #include "scene/3d/immediate_geometry.h" -static ImmediateGeometry *motionVec(NULL); -static ImmediateGeometry *normalLine(NULL); +static ImmediateGeometry3D *motionVec(nullptr); +static ImmediateGeometry3D *normalLine(nullptr); static Ref<StandardMaterial3D> red_mat; static Ref<StandardMaterial3D> blue_mat; #endif -bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes) { - +bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) { #if debug_test_motion /// Yes I know this is not good, but I've used it as fast debugging hack. /// I'm leaving it here just for speedup the other eventual debugs if (!normalLine) { - motionVec = memnew(ImmediateGeometry); - normalLine = memnew(ImmediateGeometry); + motionVec = memnew(ImmediateGeometry3D); + normalLine = memnew(ImmediateGeometry3D); SceneTree::get_singleton()->get_current_scene()->add_child(motionVec); SceneTree::get_singleton()->get_current_scene()->add_child(normalLine); @@ -951,7 +933,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f Vector3 sup_line; B_TO_G(body_safe_position.getOrigin(), sup_line); motionVec->clear(); - motionVec->begin(Mesh::PRIMITIVE_LINES, NULL); + motionVec->begin(Mesh::PRIMITIVE_LINES, nullptr); motionVec->add_vertex(sup_line); motionVec->add_vertex(sup_line + p_motion * 10); motionVec->end(); @@ -1009,7 +991,6 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f B_TO_G(motion + initial_recover_motion + __rec, r_result->motion); if (has_penetration) { - const btRigidBody *btRigid = static_cast<const btRigidBody *>(r_recover_result.other_collision_object); CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(btRigid->getUserPointer()); @@ -1028,7 +1009,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f Vector3 sup_line2; B_TO_G(motion, sup_line2); normalLine->clear(); - normalLine->begin(Mesh::PRIMITIVE_LINES, NULL); + normalLine->begin(Mesh::PRIMITIVE_LINES, nullptr); normalLine->add_vertex(r_result->collision_point); normalLine->add_vertex(r_result->collision_point + r_result->collision_normal * 10); normalLine->end(); @@ -1042,8 +1023,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f return has_penetration; } -int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin) { - +int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, float p_margin) { btTransform body_transform; G_TO_B(p_transform, body_transform); UNSCALE_BT_BASIS(body_transform); @@ -1054,7 +1034,7 @@ int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p int rays_found_this_round = 0; for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - PhysicsServer::SeparationResult *next_results = &r_results[rays_found]; + PhysicsServer3D::SeparationResult *next_results = &r_results[rays_found]; rays_found_this_round = recover_from_penetration_ray(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, p_result_max - rays_found, recover_motion, next_results); rays_found += rays_found_this_round; @@ -1108,14 +1088,12 @@ public: self_collision_object(p_self_collision_object), collision_layer(p_collision_layer), collision_mask(p_collision_mask) { - bounds = btDbvtVolume::FromMM(p_aabb_min, p_aabb_max); } virtual ~RecoverPenetrationBroadPhaseCallback() {} virtual bool process(const btBroadphaseProxy *proxy) { - btCollisionObject *co = static_cast<btCollisionObject *>(proxy->m_clientObject); if (co->getInternalType() <= btCollisionObject::CO_RIGID_BODY) { if (self_collision_object != proxy->m_clientObject && GodotFilterCallback::test_collision_filters(collision_layer, collision_mask, proxy->m_collisionFilterGroup, proxy->m_collisionFilterMask)) { @@ -1124,7 +1102,7 @@ public: if (cs->getNumChildShapes() > 1) { const btDbvt *tree = cs->getDynamicAabbTree(); - ERR_FAIL_COND_V(tree == NULL, true); + ERR_FAIL_COND_V(tree == nullptr, true); // Transform bounds into compound shape local space const btTransform other_in_compound_space = co->getWorldTransform().inverse(); @@ -1159,13 +1137,11 @@ public: }; bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) { - // Calculate the cumulative AABB of all shapes of the kinematic body btVector3 aabb_min, aabb_max; bool shapes_found = false; for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { - const RigidBodyBullet::KinematicShape &kin_shape(p_body->get_kinematic_utilities()->shapes[kinIndex]); if (!kin_shape.is_active()) { continue; @@ -1210,7 +1186,6 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran // Perform narrowphase per shape for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { - const RigidBodyBullet::KinematicShape &kin_shape(p_body->get_kinematic_utilities()->shapes[kinIndex]); if (!kin_shape.is_active()) { continue; @@ -1229,8 +1204,9 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran if (p_infinite_inertia && !otherObject->isStaticOrKinematicObject()) { otherObject->activate(); // Force activation of hitten rigid, soft body continue; - } else if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object())) + } else if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object())) { continue; + } if (otherObject->getCollisionShape()->isCompound()) { const btCompoundShape *cs = static_cast<const btCompoundShape *>(otherObject->getCollisionShape()); @@ -1239,23 +1215,19 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran if (cs->getChildShape(shape_idx)->isConvex()) { if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(shape_idx)), otherObject, kinIndex, shape_idx, shape_transform, otherObject->getWorldTransform() * cs->getChildTransform(shape_idx), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { - penetration = true; } } else { if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(shape_idx), p_body->get_bt_collision_object(), otherObject, kinIndex, shape_idx, shape_transform, otherObject->getWorldTransform() * cs->getChildTransform(shape_idx), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { - penetration = true; } } } else if (otherObject->getCollisionShape()->isConvex()) { /// Execute GJK test against object shape if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, kinIndex, 0, shape_transform, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { - penetration = true; } } else { if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, shape_transform, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { - penetration = true; } } @@ -1266,7 +1238,6 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran } bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) { - // Initialize GJK input btGjkPairDetector::ClosestPointInput gjk_input; gjk_input.m_transformA = p_transformA; @@ -1275,7 +1246,7 @@ bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const bt // Perform GJK test btPointCollector result; btGjkPairDetector gjk_pair_detector(p_shapeA, p_shapeB, gjk_simplex_solver, gjk_epa_pen_solver); - gjk_pair_detector.getClosestPoints(gjk_input, result, 0); + gjk_pair_detector.getClosestPoints(gjk_input, result, nullptr); if (0 > result.m_distance) { // Has penetration r_delta_recover_movement += result.m_normalOnBInWorld * (result.m_distance * -1 * p_recover_movement_scale); @@ -1297,15 +1268,14 @@ bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const bt } bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) { - /// Contact test btTransform tA(p_transformA); - btCollisionObjectWrapper obA(NULL, p_shapeA, p_objectA, tA, -1, p_shapeId_A); - btCollisionObjectWrapper obB(NULL, p_shapeB, p_objectB, p_transformB, -1, p_shapeId_B); + btCollisionObjectWrapper obA(nullptr, p_shapeA, p_objectA, tA, -1, p_shapeId_A); + btCollisionObjectWrapper obB(nullptr, p_shapeB, p_objectB, p_transformB, -1, p_shapeId_B); - btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CONTACT_POINT_ALGORITHMS); + btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, nullptr, BT_CONTACT_POINT_ALGORITHMS); if (algorithm) { GodotDeepPenetrationContactResultCallback contactPointResult(&obA, &obB); //discrete collision detection query @@ -1333,8 +1303,7 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC return false; } -int SpaceBullet::add_separation_result(PhysicsServer::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const { - +int SpaceBullet::add_separation_result(PhysicsServer3D::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const { // optimize results (ignore non-colliding) if (p_recover_result.penetration_distance < 0.0) { const btRigidBody *btRigid = static_cast<const btRigidBody *>(p_other_object); @@ -1355,14 +1324,12 @@ int SpaceBullet::add_separation_result(PhysicsServer::SeparationResult *r_result } } -int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results) { - +int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer3D::SeparationResult *r_results) { // Calculate the cumulative AABB of all shapes of the kinematic body btVector3 aabb_min, aabb_max; bool shapes_found = false; for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { - const RigidBodyBullet::KinematicShape &kin_shape(p_body->get_kinematic_utilities()->shapes[kinIndex]); if (!kin_shape.is_active()) { continue; @@ -1406,7 +1373,6 @@ int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btT // Perform narrowphase per shape for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { - if (ray_count >= p_result_max) { break; } @@ -1428,8 +1394,9 @@ int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btT if (p_infinite_inertia && !otherObject->isStaticOrKinematicObject()) { otherObject->activate(); // Force activation of hitten rigid, soft body continue; - } else if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object())) + } else if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object())) { continue; + } if (otherObject->getCollisionShape()->isCompound()) { const btCompoundShape *cs = static_cast<const btCompoundShape *>(otherObject->getCollisionShape()); @@ -1438,14 +1405,11 @@ int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btT RecoverResult recover_result; if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(shape_idx), p_body->get_bt_collision_object(), otherObject, kinIndex, shape_idx, shape_transform, otherObject->getWorldTransform() * cs->getChildTransform(shape_idx), p_recover_movement_scale, r_delta_recover_movement, &recover_result)) { - ray_count = add_separation_result(&r_results[ray_count], recover_result, kinIndex, otherObject); } } else { - RecoverResult recover_result; if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, shape_transform, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, &recover_result)) { - ray_count = add_separation_result(&r_results[ray_count], recover_result, kinIndex, otherObject); } } diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 32372f1630..5ff421ef52 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -35,7 +35,7 @@ #include "core/vector.h" #include "godot_result_callbacks.h" #include "rid_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include <BulletCollision/BroadphaseCollision/btBroadphaseProxy.h> #include <BulletCollision/BroadphaseCollision/btOverlappingPairCache.h> @@ -67,8 +67,8 @@ class btGjkEpaPenetrationDepthSolver; extern ContactAddedCallback gContactAddedCallback; -class BulletPhysicsDirectSpaceState : public PhysicsDirectSpaceState { - GDCLASS(BulletPhysicsDirectSpaceState, PhysicsDirectSpaceState); +class BulletPhysicsDirectSpaceState : public PhysicsDirectSpaceState3D { + GDCLASS(BulletPhysicsDirectSpaceState, PhysicsDirectSpaceState3D); private: SpaceBullet *space; @@ -79,7 +79,7 @@ public: 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, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); 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, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false); virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &r_closest_safe, float &r_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL); + virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &r_closest_safe, float &r_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr); /// Returns the list of contacts pairs in this order: Local contact, other body contact virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float 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, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); @@ -87,32 +87,34 @@ public: }; class SpaceBullet : public RIDBullet { - friend class AreaBullet; friend void onBulletTickCallback(btDynamicsWorld *world, btScalar timeStep); friend class BulletPhysicsDirectSpaceState; - btBroadphaseInterface *broadphase; - btDefaultCollisionConfiguration *collisionConfiguration; - btCollisionDispatcher *dispatcher; - btConstraintSolver *solver; - btDiscreteDynamicsWorld *dynamicsWorld; - btSoftBodyWorldInfo *soft_body_world_info; - btGhostPairCallback *ghostPairCallback; - GodotFilterCallback *godotFilterCallback; + btBroadphaseInterface *broadphase = nullptr; + btDefaultCollisionConfiguration *collisionConfiguration = nullptr; + btCollisionDispatcher *dispatcher = nullptr; + btConstraintSolver *solver = nullptr; + btDiscreteDynamicsWorld *dynamicsWorld = nullptr; + btSoftBodyWorldInfo *soft_body_world_info = nullptr; + btGhostPairCallback *ghostPairCallback = nullptr; + GodotFilterCallback *godotFilterCallback = nullptr; btGjkEpaPenetrationDepthSolver *gjk_epa_pen_solver; btVoronoiSimplexSolver *gjk_simplex_solver; BulletPhysicsDirectSpaceState *direct_access; - Vector3 gravityDirection; - real_t gravityMagnitude; + Vector3 gravityDirection = Vector3(0, -1, 0); + real_t gravityMagnitude = 10; + + real_t linear_damp = 0.0; + real_t angular_damp = 0.0; Vector<AreaBullet *> areas; Vector<Vector3> contactDebug; - int contactDebugCount; - real_t delta_time; + int contactDebugCount = 0; + real_t delta_time = 0.; public: SpaceBullet(); @@ -131,15 +133,15 @@ public: /// @param p_param: /// AREA_PARAM_GRAVITY to set the gravity magnitude of entire world /// AREA_PARAM_GRAVITY_VECTOR to set the gravity direction of entire world - void set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value); + void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); /// Used to get some parameters to Bullet world /// @param p_param: /// AREA_PARAM_GRAVITY to get the gravity magnitude of entire world /// AREA_PARAM_GRAVITY_VECTOR to get the gravity direction of entire world - Variant get_param(PhysicsServer::AreaParameter p_param); + Variant get_param(PhysicsServer3D::AreaParameter p_param); - void set_param(PhysicsServer::SpaceParameter p_param, real_t p_value); - real_t get_param(PhysicsServer::SpaceParameter p_param); + void set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value); + real_t get_param(PhysicsServer3D::SpaceParameter p_param); void add_area(AreaBullet *p_area); void remove_area(AreaBullet *p_area); @@ -167,7 +169,9 @@ public: contactDebugCount = 0; } _FORCE_INLINE_ void add_debug_contact(const Vector3 &p_contact) { - if (contactDebugCount < contactDebug.size()) contactDebug.write[contactDebugCount++] = p_contact; + if (contactDebugCount < contactDebug.size()) { + contactDebug.write[contactDebugCount++] = p_contact; + } } _FORCE_INLINE_ Vector<Vector3> get_debug_contacts() { return contactDebug; } _FORCE_INLINE_ int get_debug_contact_count() { return contactDebugCount; } @@ -177,8 +181,11 @@ public: void update_gravity(); - bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes); - int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin); + real_t get_linear_damp() const { return linear_damp; } + real_t get_angular_damp() const { return angular_damp; } + + bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes); + int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, float p_margin); private: void create_empty_world(bool p_create_soft_world); @@ -187,33 +194,26 @@ private: void check_body_collision(); struct RecoverResult { - bool hasPenetration; - btVector3 normal; - btVector3 pointWorld; - btScalar penetration_distance; // Negative mean penetration - int other_compound_shape_index; - const btCollisionObject *other_collision_object; - int local_shape_most_recovered; - - RecoverResult() : - hasPenetration(false), - normal(0, 0, 0), - pointWorld(0, 0, 0), - penetration_distance(1e20), - other_compound_shape_index(0), - other_collision_object(NULL), - local_shape_most_recovered(0) {} + bool hasPenetration = false; + btVector3 normal = btVector3(0, 0, 0); + btVector3 pointWorld = btVector3(0, 0, 0); + btScalar penetration_distance = 1e20; // Negative mean penetration + int other_compound_shape_index = 0; + const btCollisionObject *other_collision_object = nullptr; + int local_shape_most_recovered = 0; + + RecoverResult() {} }; - bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); + bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = nullptr); /// This is an API that recover a kinematic object from penetration /// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions - bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); + bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = nullptr); /// This is an API that recover a kinematic object from penetration /// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm - bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); + bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = nullptr); - int add_separation_result(PhysicsServer::SeparationResult *r_results, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const; - int recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results); + int add_separation_result(PhysicsServer3D::SeparationResult *r_results, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const; + int recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer3D::SeparationResult *r_results); }; #endif diff --git a/modules/camera/SCsub b/modules/camera/SCsub index 23f031f06e..63c4e9fbab 100644 --- a/modules/camera/SCsub +++ b/modules/camera/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_camera = env_modules.Clone() @@ -10,7 +10,7 @@ if env["platform"] == "iphone": modules_sources = [] env_camera.add_source_files(modules_sources, "register_types.cpp") env_camera.add_source_files(modules_sources, "camera_ios.mm") - mod_lib = env_modules.add_library('#bin/libgodot_camera_module' + env['LIBSUFFIX'], modules_sources) + mod_lib = env_modules.add_library("#bin/libgodot_camera_module" + env["LIBSUFFIX"], modules_sources) elif env["platform"] == "windows": env_camera.add_source_files(env.modules_sources, "register_types.cpp") @@ -19,4 +19,3 @@ elif env["platform"] == "windows": elif env["platform"] == "osx": env_camera.add_source_files(env.modules_sources, "register_types.cpp") env_camera.add_source_files(env.modules_sources, "camera_osx.mm") - diff --git a/modules/camera/camera_win.cpp b/modules/camera/camera_win.cpp index 875f0b26bc..1646644be3 100644 --- a/modules/camera/camera_win.cpp +++ b/modules/camera/camera_win.cpp @@ -53,9 +53,9 @@ public: void deactivate_feed(); }; -CameraFeedWindows::CameraFeedWindows(){ +CameraFeedWindows::CameraFeedWindows() { ///@TODO implement this, should store information about our available camera -}; +} CameraFeedWindows::~CameraFeedWindows() { // make sure we stop recording if we are! @@ -75,16 +75,16 @@ bool CameraFeedWindows::activate_feed() { ///@TODO we should probably have a callback method here that is being called by the // camera API which provides frames and call back into the CameraServer to update our texture -void CameraFeedWindows::deactivate_feed(){ +void CameraFeedWindows::deactivate_feed() { ///@TODO this should deactivate our camera and stop the process of capturing frames -}; +} ////////////////////////////////////////////////////////////////////////// // CameraWindows - Subclass for our camera server on windows -void CameraWindows::add_active_cameras(){ +void CameraWindows::add_active_cameras() { ///@TODO scan through any active cameras and create CameraFeedWindows objects for them -}; +} CameraWindows::CameraWindows() { // Find cameras active right now @@ -92,7 +92,3 @@ CameraWindows::CameraWindows() { // need to add something that will react to devices being connected/removed... }; - -CameraWindows::~CameraWindows(){ - -}; diff --git a/modules/camera/camera_win.h b/modules/camera/camera_win.h index 39a1b0b86f..bbc8880c12 100644 --- a/modules/camera/camera_win.h +++ b/modules/camera/camera_win.h @@ -40,7 +40,7 @@ private: public: CameraWindows(); - ~CameraWindows(); + ~CameraWindows() {} }; #endif /* CAMERAWIN_H */ diff --git a/modules/camera/config.py b/modules/camera/config.py index d308c04195..87d7542741 100644 --- a/modules/camera/config.py +++ b/modules/camera/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return platform == 'iphone' or platform == 'osx' or platform == 'windows' + return platform == "iphone" or platform == "osx" or platform == "windows" + def configure(env): pass diff --git a/modules/csg/SCsub b/modules/csg/SCsub index 57c504efd8..641a42c187 100644 --- a/modules/csg/SCsub +++ b/modules/csg/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_csg = env_modules.Clone() diff --git a/modules/csg/config.py b/modules/csg/config.py index 38ccc66d91..9106cbceca 100644 --- a/modules/csg/config.py +++ b/modules/csg/config.py @@ -1,21 +1,24 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ - "CSGBox", - "CSGCombiner", - "CSGCylinder", - "CSGMesh", - "CSGPolygon", - "CSGPrimitive", - "CSGShape", - "CSGSphere", - "CSGTorus", + "CSGBox3D", + "CSGCombiner3D", + "CSGCylinder3D", + "CSGMesh3D", + "CSGPolygon3D", + "CSGPrimitive3D", + "CSGShape3D", + "CSGSphere3D", + "CSGTorus3D", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index 3f61e2852f..df798623f9 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -37,30 +37,31 @@ // Static helper functions. inline static bool is_snapable(const Vector3 &p_point1, const Vector3 &p_point2, real_t p_distance) { - return (p_point1 - p_point2).length_squared() < p_distance * p_distance; } inline static Vector2 interpolate_segment_uv(const Vector2 p_segement_points[2], const Vector2 p_uvs[2], const Vector2 &p_interpolation_point) { - float segment_length = (p_segement_points[1] - p_segement_points[0]).length(); - if (segment_length < CMP_EPSILON) + if (segment_length < CMP_EPSILON) { return p_uvs[0]; + } float distance = (p_interpolation_point - p_segement_points[0]).length(); float fraction = distance / segment_length; - return p_uvs[0].linear_interpolate(p_uvs[1], fraction); + return p_uvs[0].lerp(p_uvs[1], fraction); } inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const Vector2 p_uvs[3], const Vector2 &p_interpolation_point) { - - if (p_interpolation_point.distance_squared_to(p_vertices[0]) < CMP_EPSILON2) + if (p_interpolation_point.distance_squared_to(p_vertices[0]) < CMP_EPSILON2) { return p_uvs[0]; - if (p_interpolation_point.distance_squared_to(p_vertices[1]) < CMP_EPSILON2) + } + if (p_interpolation_point.distance_squared_to(p_vertices[1]) < CMP_EPSILON2) { return p_uvs[1]; - if (p_interpolation_point.distance_squared_to(p_vertices[2]) < CMP_EPSILON2) + } + if (p_interpolation_point.distance_squared_to(p_vertices[2]) < CMP_EPSILON2) { return p_uvs[2]; + } Vector2 edge1 = p_vertices[1] - p_vertices[0]; Vector2 edge2 = p_vertices[2] - p_vertices[0]; @@ -72,8 +73,9 @@ inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const float inter_on_edge1 = interpolation.dot(edge1); float inter_on_edge2 = interpolation.dot(edge2); float scale = (edge1_on_edge1 * edge2_on_edge2 - edge1_on_edge2 * edge1_on_edge2); - if (scale == 0) + if (scale == 0) { return p_uvs[0]; + } float v = (edge2_on_edge2 * inter_on_edge1 - edge1_on_edge2 * inter_on_edge2) / scale; float w = (edge1_on_edge1 * inter_on_edge2 - edge1_on_edge2 * inter_on_edge1) / scale; @@ -83,25 +85,27 @@ inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const } static inline bool ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 p_vertices[3], float p_tolerance, Vector3 &r_intersection_point) { - Vector3 edge1 = p_vertices[1] - p_vertices[0]; Vector3 edge2 = p_vertices[2] - p_vertices[0]; Vector3 h = p_dir.cross(edge2); real_t a = edge1.dot(h); // Check if ray is parallel to triangle. - if (Math::is_zero_approx(a)) + if (Math::is_zero_approx(a)) { return false; + } real_t f = 1.0 / a; Vector3 s = p_from - p_vertices[0]; real_t u = f * s.dot(h); - if (u < 0.0 - p_tolerance || u > 1.0 + p_tolerance) + if (u < 0.0 - p_tolerance || u > 1.0 + p_tolerance) { return false; + } Vector3 q = s.cross(edge1); real_t v = f * p_dir.dot(q); - if (v < 0.0 - p_tolerance || u + v > 1.0 + p_tolerance) + if (v < 0.0 - p_tolerance || u + v > 1.0 + p_tolerance) { return false; + } // Ray intersects triangle. // Calculate distance. @@ -110,12 +114,12 @@ static inline bool ray_intersects_triangle(const Vector3 &p_from, const Vector3 if (t >= p_tolerance) { r_intersection_point = p_from + p_dir * t; return true; - } else + } else { return false; + } } inline bool is_point_in_triangle(const Vector3 &p_point, const Vector3 p_vertices[3], int p_shifted = 0) { - real_t det = p_vertices[0].dot(p_vertices[1].cross(p_vertices[2])); // If determinant is, zero try shift the triangle and the point. @@ -138,24 +142,28 @@ inline bool is_point_in_triangle(const Vector3 &p_point, const Vector3 p_vertice lambda[2] = p_vertices[0].cross(p_vertices[1]).dot(p_point) / det; // Point is in the plane if all lambdas sum to 1. - if (!Math::is_equal_approx(lambda[0] + lambda[1] + lambda[2], 1)) return false; + if (!Math::is_equal_approx(lambda[0] + lambda[1] + lambda[2], 1)) { + return false; + } // Point is inside the triangle if all lambdas are positive. - if (lambda[0] < 0 || lambda[1] < 0 || lambda[2] < 0) return false; + if (lambda[0] < 0 || lambda[1] < 0 || lambda[2] < 0) { + return false; + } return true; } inline static bool are_segements_parallel(const Vector2 p_segment1_points[2], const Vector2 p_segment2_points[2], float p_vertex_snap2) { - Vector2 segment1 = p_segment1_points[1] - p_segment1_points[0]; Vector2 segment2 = p_segment2_points[1] - p_segment2_points[0]; real_t segment1_length2 = segment1.dot(segment1); real_t segment2_length2 = segment2.dot(segment2); real_t segment_onto_segment = segment2.dot(segment1); - if (segment1_length2 < p_vertex_snap2 || segment2_length2 < p_vertex_snap2) + if (segment1_length2 < p_vertex_snap2 || segment2_length2 < p_vertex_snap2) { return true; + } real_t max_separation2; if (segment1_length2 > segment2_length2) { @@ -170,7 +178,6 @@ inline static bool are_segements_parallel(const Vector2 p_segment1_points[2], co // CSGBrush void CSGBrush::_regen_face_aabbs() { - for (int i = 0; i < faces.size(); i++) { faces.write[i].aabb = AABB(); faces.write[i].aabb.position = faces[i].vertices[0]; @@ -180,7 +187,6 @@ void CSGBrush::_regen_face_aabbs() { } void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials, const Vector<bool> &p_invert_faces) { - faces.clear(); int vc = p_vertices.size(); @@ -202,7 +208,6 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector< faces.resize(p_vertices.size() / 3); for (int i = 0; i < faces.size(); i++) { - Face &f = faces.write[i]; f.vertices[0] = rv[i * 3 + 0]; f.vertices[1] = rv[i * 3 + 1]; @@ -214,21 +219,21 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector< f.uvs[2] = ruv[i * 3 + 2]; } - if (sc == vc / 3) + if (sc == vc / 3) { f.smooth = rs[i]; - else + } else { f.smooth = false; + } - if (ic == vc / 3) + if (ic == vc / 3) { f.invert = ri[i]; - else + } else { f.invert = false; + } if (mc == vc / 3) { - Ref<Material> mat = rm[i]; if (mat.is_valid()) { - const Map<Ref<Material>, int>::Element *E = material_map.find(mat); if (E) { @@ -253,7 +258,6 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector< } void CSGBrush::copy_from(const CSGBrush &p_brush, const Transform &p_xform) { - faces = p_brush.faces; materials = p_brush.materials; @@ -269,7 +273,6 @@ void CSGBrush::copy_from(const CSGBrush &p_brush, const Transform &p_xform) { // CSGBrushOperation void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_brush_a, const CSGBrush &p_brush_b, CSGBrush &r_merged_brush, float p_vertex_snap) { - // Check for face collisions and add necessary faces. Build2DFaceCollection build2DFaceCollection; for (int i = 0; i < p_brush_a.faces.size(); i++) { @@ -285,7 +288,6 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b mesh_merge.vertex_snap = p_vertex_snap; for (int i = 0; i < p_brush_a.faces.size(); i++) { - Ref<Material> material; if (p_brush_a.faces[i].material != -1) { material = p_brush_a.materials[p_brush_a.faces[i].material]; @@ -305,7 +307,6 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b } for (int i = 0; i < p_brush_b.faces.size(); i++) { - Ref<Material> material; if (p_brush_b.faces[i].material != -1) { material = p_brush_b.materials[p_brush_b.faces[i].material]; @@ -331,14 +332,13 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b r_merged_brush.faces.clear(); switch (p_operation) { - case OPERATION_UNION: { - int outside_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - if (mesh_merge.faces[i].inside) + if (mesh_merge.faces[i].inside) { continue; + } outside_count++; } @@ -347,9 +347,9 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b outside_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - - if (mesh_merge.faces[i].inside) + if (mesh_merge.faces[i].inside) { continue; + } for (int j = 0; j < 3; j++) { r_merged_brush.faces.write[outside_count].vertices[j] = mesh_merge.points[mesh_merge.faces[i].points[j]]; @@ -367,12 +367,12 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b } break; case OPERATION_INTERSECTION: { - int inside_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - if (!mesh_merge.faces[i].inside) + if (!mesh_merge.faces[i].inside) { continue; + } inside_count++; } @@ -381,9 +381,9 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b inside_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - - if (!mesh_merge.faces[i].inside) + if (!mesh_merge.faces[i].inside) { continue; + } for (int j = 0; j < 3; j++) { r_merged_brush.faces.write[inside_count].vertices[j] = mesh_merge.points[mesh_merge.faces[i].points[j]]; @@ -401,14 +401,15 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b } break; case OPERATION_SUBSTRACTION: { - int face_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - if (mesh_merge.faces[i].from_b && !mesh_merge.faces[i].inside) + if (mesh_merge.faces[i].from_b && !mesh_merge.faces[i].inside) { continue; - if (!mesh_merge.faces[i].from_b && mesh_merge.faces[i].inside) + } + if (!mesh_merge.faces[i].from_b && mesh_merge.faces[i].inside) { continue; + } face_count++; } @@ -417,11 +418,12 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b face_count = 0; for (int i = 0; i < mesh_merge.faces.size(); i++) { - - if (mesh_merge.faces[i].from_b && !mesh_merge.faces[i].inside) + if (mesh_merge.faces[i].from_b && !mesh_merge.faces[i].inside) { continue; - if (!mesh_merge.faces[i].from_b && mesh_merge.faces[i].inside) + } + if (!mesh_merge.faces[i].from_b && mesh_merge.faces[i].inside) { continue; + } for (int j = 0; j < 3; j++) { r_merged_brush.faces.write[face_count].vertices[j] = mesh_merge.points[mesh_merge.faces[i].points[j]]; @@ -458,7 +460,6 @@ void CSGBrushOperation::merge_brushes(Operation p_operation, const CSGBrush &p_b #define BVH_LIMIT 8 int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **facebvhptrptr, int p_from, int p_size, int p_depth, int &r_max_depth, int &r_max_alloc) { - if (p_depth > r_max_depth) { r_max_depth = p_depth; } @@ -483,7 +484,6 @@ int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **fac int li = aabb.get_longest_axis_index(); switch (li) { - case Vector3::AXIS_X: { SortArray<FaceBVH *, FaceBVHCmpX> sort_x; sort_x.nth_element(0, p_size, p_size / 2, &facebvhptrptr[p_from]); @@ -519,18 +519,19 @@ int CSGBrushOperation::MeshMerge::_create_bvh(FaceBVH *facebvhptr, FaceBVH **fac } void CSGBrushOperation::MeshMerge::_add_distance(List<real_t> &r_intersectionsA, List<real_t> &r_intersectionsB, bool p_from_B, real_t p_distance) const { - List<real_t> &intersections = p_from_B ? r_intersectionsB : r_intersectionsA; // Check if distance exists. - for (const List<real_t>::Element *E = intersections.front(); E; E = E->next()) - if (Math::abs(**E - p_distance) < vertex_snap) return; + for (const List<real_t>::Element *E = intersections.front(); E; E = E->next()) { + if (Math::abs(**E - p_distance) < vertex_snap) { + return; + } + } intersections.push_back(p_distance); } bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_depth, int p_bvh_first, int p_face_idx) const { - Face face = faces[p_face_idx]; Vector3 face_points[3] = { points[face.points[0]], @@ -560,22 +561,16 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de stack[0] = pos; while (true) { - uint32_t node = stack[level] & NODE_IDX_MASK; const FaceBVH *current_facebvhptr = &(facebvhptr[node]); bool done = false; switch (stack[level] >> VISITED_BIT_SHIFT) { - case TEST_AABB_BIT: { - if (current_facebvhptr->face >= 0) { - while (current_facebvhptr) { - if (p_face_idx != current_facebvhptr->face && current_facebvhptr->aabb.intersects_ray(face_center, face_normal)) { - const Face ¤t_face = faces[current_facebvhptr->face]; Vector3 current_points[3] = { points[current_face.points[0]], @@ -589,8 +584,9 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de if ((current_normal - face_normal).length_squared() < CMP_EPSILON2 && is_point_in_triangle(face_center, current_points)) { // Only add an intersection if checking a B face. - if (face.from_b) + if (face.from_b) { _add_distance(intersectionsA, intersectionsB, current_face.from_b, 0); + } } else if (ray_intersects_triangle(face_center, face_normal, current_points, CMP_EPSILON, intersection_point)) { real_t distance = (intersection_point - face_center).length(); _add_distance(intersectionsA, intersectionsB, current_face.from_b, distance); @@ -607,7 +603,6 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - bool valid = current_facebvhptr->aabb.intersects_ray(face_center, face_normal); if (!valid) { @@ -620,7 +615,6 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de } case VISIT_LEFT_BIT: { - stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = current_facebvhptr->left | TEST_AABB_BIT; level++; @@ -628,7 +622,6 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de } case VISIT_RIGHT_BIT: { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = current_facebvhptr->right | TEST_AABB_BIT; level++; @@ -636,18 +629,19 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de } case VISIT_DONE_BIT: { - if (level == 0) { done = true; break; - } else + } else { level--; + } continue; } } - if (done) + if (done) { break; + } } // Inside if face normal intersects other faces an odd number of times. @@ -655,7 +649,6 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de } void CSGBrushOperation::MeshMerge::mark_inside_faces() { - // Mark faces that are inside. This helps later do the boolean ops when merging. // This approach is very brute force with a bunch of optimizations, // such as BVH and pre AABB intersection test. @@ -701,8 +694,9 @@ void CSGBrushOperation::MeshMerge::mark_inside_faces() { AABB intersection_aabb = aabb_a.intersection(aabb_b); // Check if shape AABBs intersect. - if (intersection_aabb.size == Vector3()) + if (intersection_aabb.size == Vector3()) { return; + } Vector<FaceBVH *> bvhtrvec; bvhtrvec.resize(faces.size()); @@ -716,21 +710,20 @@ void CSGBrushOperation::MeshMerge::mark_inside_faces() { _create_bvh(facebvh, bvhptr, 0, faces.size(), 1, max_depth, max_alloc); for (int i = 0; i < faces.size(); i++) { - // Check if face AABB intersects the intersection AABB. - if (!intersection_aabb.intersects_inclusive(facebvh[i].aabb)) + if (!intersection_aabb.intersects_inclusive(facebvh[i].aabb)) { continue; + } - if (_bvh_inside(facebvh, max_depth, max_alloc - 1, i)) + if (_bvh_inside(facebvh, max_depth, max_alloc - 1, i)) { faces.write[i].inside = true; + } } } void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vector2 p_uvs[], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) { - int indices[3]; for (int i = 0; i < 3; i++) { - VertexKey vk; vk.x = int((double(p_points[i].x) + double(vertex_snap) * 0.31234) / double(vertex_snap)); vk.y = int((double(p_points[i].y) + double(vertex_snap) * 0.31234) / double(vertex_snap)); @@ -747,8 +740,9 @@ void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vect } // Don't add degenerate faces. - if (indices[0] == indices[2] || indices[0] == indices[1] || indices[1] == indices[2]) + if (indices[0] == indices[2] || indices[0] == indices[1] || indices[1] == indices[2]) { return; + } MeshMerge::Face face; face.from_b = p_from_b; @@ -778,26 +772,26 @@ void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vect // CSGBrushOperation::Build2DFaces int CSGBrushOperation::Build2DFaces::_get_point_idx(const Vector2 &p_point) { - for (int vertex_idx = 0; vertex_idx < vertices.size(); ++vertex_idx) { - if ((p_point - vertices[vertex_idx].point).length_squared() < vertex_snap2) + if ((p_point - vertices[vertex_idx].point).length_squared() < vertex_snap2) { return vertex_idx; + } } return -1; } int CSGBrushOperation::Build2DFaces::_add_vertex(const Vertex2D &p_vertex) { - // Check if vertex exists. int vertex_id = _get_point_idx(p_vertex.point); - if (vertex_id != -1) return vertex_id; + if (vertex_id != -1) { + return vertex_id; + } vertices.push_back(p_vertex); return vertices.size() - 1; } void CSGBrushOperation::Build2DFaces::_add_vertex_idx_sorted(Vector<int> &r_vertex_indices, int p_new_vertex_index) { - if (p_new_vertex_index >= 0 && r_vertex_indices.find(p_new_vertex_index) == -1) { ERR_FAIL_COND_MSG(p_new_vertex_index >= vertices.size(), "Invalid vertex index."); @@ -810,19 +804,21 @@ void CSGBrushOperation::Build2DFaces::_add_vertex_idx_sorted(Vector<int> &r_vert // The second vertex. if (r_vertex_indices.size() == 1) { - Vector2 first_point = vertices[r_vertex_indices[0]].point; Vector2 new_point = vertices[p_new_vertex_index].point; // Sort along the axis with the greatest difference. int axis = 0; - if (Math::abs(new_point.x - first_point.x) < Math::abs(new_point.y - first_point.y)) axis = 1; + if (Math::abs(new_point.x - first_point.x) < Math::abs(new_point.y - first_point.y)) { + axis = 1; + } // Add it to the beginning or the end appropriately. - if (new_point[axis] < first_point[axis]) + if (new_point[axis] < first_point[axis]) { r_vertex_indices.insert(0, p_new_vertex_index); - else + } else { r_vertex_indices.push_back(p_new_vertex_index); + } return; } @@ -834,7 +830,9 @@ void CSGBrushOperation::Build2DFaces::_add_vertex_idx_sorted(Vector<int> &r_vert // Determine axis being sorted against i.e. the axis with the greatest difference. int axis = 0; - if (Math::abs(last_point.x - first_point.x) < Math::abs(last_point.y - first_point.y)) axis = 1; + if (Math::abs(last_point.x - first_point.x) < Math::abs(last_point.y - first_point.y)) { + axis = 1; + } // Insert the point at the appropriate index. for (int insert_idx = 0; insert_idx < r_vertex_indices.size(); ++insert_idx) { @@ -851,13 +849,13 @@ void CSGBrushOperation::Build2DFaces::_add_vertex_idx_sorted(Vector<int> &r_vert } void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_indices) { - int segments = p_segment_indices.size() - 1; - if (segments < 2) return; + if (segments < 2) { + return; + } // Faces around an inner vertex are merged by moving the inner vertex to the first vertex. for (int sorted_idx = 1; sorted_idx < segments; ++sorted_idx) { - int closest_idx = 0; int inner_idx = p_segment_indices[sorted_idx]; @@ -886,14 +884,15 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ // Create the new faces. for (int merge_idx = 0; merge_idx < merge_faces.size(); ++merge_idx) { - int outer_edge_idx[2]; outer_edge_idx[0] = merge_faces[merge_idx].vertex_idx[(merge_faces_inner_vertex_idx[merge_idx] + 1) % 3]; outer_edge_idx[1] = merge_faces[merge_idx].vertex_idx[(merge_faces_inner_vertex_idx[merge_idx] + 2) % 3]; // Skip flattened faces. if (outer_edge_idx[0] == p_segment_indices[closest_idx] || - outer_edge_idx[1] == p_segment_indices[closest_idx]) continue; + outer_edge_idx[1] == p_segment_indices[closest_idx]) { + continue; + } //Don't create degenerate triangles. Vector2 edge1[2] = { @@ -921,14 +920,16 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ // Delete the old faces in reverse index order. merge_faces_idx.sort(); merge_faces_idx.invert(); - for (int i = 0; i < merge_faces_idx.size(); ++i) + for (int i = 0; i < merge_faces_idx.size(); ++i) { faces.remove(merge_faces_idx[i]); + } - if (degenerate_points.size() == 0) continue; + if (degenerate_points.size() == 0) { + continue; + } // Split faces using degenerate points. for (int face_idx = 0; face_idx < faces.size(); ++face_idx) { - Face2D face = faces[face_idx]; Vertex2D face_vertices[3] = { vertices[face.vertex_idx[0]], @@ -942,7 +943,6 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ }; for (int point_idx = 0; point_idx < degenerate_points.size(); ++point_idx) { - int degenerate_idx = degenerate_points[point_idx]; Vector2 point_2D = vertices[degenerate_idx].point; @@ -954,11 +954,12 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ break; } } - if (existing) continue; + if (existing) { + continue; + } // Check if point is on an each edge. for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) { - Vector2 edge_points[2] = { face_points[face_edge_idx], face_points[(face_edge_idx + 1) % 3] @@ -966,7 +967,6 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(point_2D, edge_points); if ((closest_point - point_2D).length_squared() < vertex_snap2) { - int opposite_vertex_idx = face.vertex_idx[(face_edge_idx + 2) % 3]; // If new vertex snaps to degenerate vertex, just delete this face. @@ -1004,10 +1004,8 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ } void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_segment_points[2], Vector<int> &r_segment_indices) { - // For each face. for (int face_idx = 0; face_idx < faces.size(); ++face_idx) { - Face2D face = faces[face_idx]; Vertex2D face_vertices[3] = { vertices[face.vertex_idx[0]], @@ -1017,7 +1015,6 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s // Check each edge. for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) { - Vector2 edge_points[2] = { face_vertices[face_edge_idx].point, face_vertices[(face_edge_idx + 1) % 3].point @@ -1040,13 +1037,16 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s // Else check if the segment intersects the edge. if (on_edge || Geometry::segment_intersects_segment_2d(p_segment_points[0], p_segment_points[1], edge_points[0], edge_points[1], &intersection_point)) { - // Check if intersection point is an edge point. if ((intersection_point - edge_points[0]).length_squared() < vertex_snap2 || - (intersection_point - edge_points[1]).length_squared() < vertex_snap2) continue; + (intersection_point - edge_points[1]).length_squared() < vertex_snap2) { + continue; + } // Check if edge exists, by checking if the intersecting segment is parallel to the edge. - if (are_segements_parallel(p_segment_points, edge_points, vertex_snap2)) continue; + if (are_segements_parallel(p_segment_points, edge_points, vertex_snap2)) { + continue; + } // Add the intersection point as a new vertex. Vertex2D new_vertex; @@ -1075,8 +1075,9 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s // If opposite point is on the segemnt, add its index to segment indices too. Vector2 closest_point = Geometry::get_closest_point_to_segment_2d(vertices[opposite_vertex_idx].point, p_segment_points); - if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) + if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) { _add_vertex_idx_sorted(r_segment_indices, opposite_vertex_idx); + } // Create two new faces around the new edge and remove this face. // The new edge is the last edge. @@ -1101,11 +1102,9 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s } int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { - int new_vertex_idx = -1; for (int face_idx = 0; face_idx < faces.size(); ++face_idx) { - Face2D face = faces[face_idx]; Vertex2D face_vertices[3] = { vertices[face.vertex_idx[0]], @@ -1125,14 +1124,14 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { // Check if point is existing face vertex. for (int i = 0; i < 3; ++i) { - if ((p_point - face_vertices[i].point).length_squared() < vertex_snap2) + if ((p_point - face_vertices[i].point).length_squared() < vertex_snap2) { return face.vertex_idx[i]; + } } // Check if point is on an each edge. bool on_edge = false; for (int face_edge_idx = 0; face_edge_idx < 3; ++face_edge_idx) { - Vector2 edge_points[2] = { points[face_edge_idx], points[(face_edge_idx + 1) % 3] @@ -1194,7 +1193,6 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { // If not on an edge, check if the point is inside the face. if (!on_edge && Geometry::is_point_in_triangle(p_point, face_vertices[0].point, face_vertices[1].point, face_vertices[2].point)) { - // Add the point as a new vertex. Vertex2D new_vertex; new_vertex.point = p_point; @@ -1204,7 +1202,6 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { // Create three new faces around this point and remove this face. // The new vertex is the last vertex. for (int i = 0; i < 3; ++i) { - // Don't create degenerate triangles. Vector2 edge[2] = { points[i], points[(i + 1) % 3] }; Vector2 new_edge1[2] = { vertices[new_vertex_idx].point, points[i] }; @@ -1231,7 +1228,6 @@ int CSGBrushOperation::Build2DFaces::_insert_point(const Vector2 &p_point) { } void CSGBrushOperation::Build2DFaces::insert(const CSGBrush &p_brush, int p_face_idx) { - // Find edge points that cross the plane and face points that are in the plane. // Map those points to 2D. // Create new faces from those points. @@ -1240,7 +1236,6 @@ void CSGBrushOperation::Build2DFaces::insert(const CSGBrush &p_brush, int p_face int points_count = 0; for (int i = 0; i < 3; i++) { - Vector3 point_3D = p_brush.faces[p_face_idx].vertices[i]; if (plane.has_point(point_3D)) { @@ -1250,13 +1245,14 @@ void CSGBrushOperation::Build2DFaces::insert(const CSGBrush &p_brush, int p_face points_2D[points_count++] = Vector2(point_2D.x, point_2D.y); } else { - Vector3 next_point_3D = p_brush.faces[p_face_idx].vertices[(i + 1) % 3]; - if (plane.has_point(next_point_3D)) + if (plane.has_point(next_point_3D)) { continue; // Next point is in plane, it will be added separately. - if (plane.is_point_over(point_3D) == plane.is_point_over(next_point_3D)) + } + if (plane.is_point_over(point_3D) == plane.is_point_over(next_point_3D)) { continue; // Both points on the same side of the plane, ignore. + } // Edge crosses the plane, find and add the intersection point. Vector3 point_2D; @@ -1303,7 +1299,6 @@ void CSGBrushOperation::Build2DFaces::insert(const CSGBrush &p_brush, int p_face } void CSGBrushOperation::Build2DFaces::addFacesToMesh(MeshMerge &r_mesh_merge, bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) { - for (int face_idx = 0; face_idx < faces.size(); ++face_idx) { Face2D face = faces[face_idx]; Vertex2D fv[3] = { @@ -1327,7 +1322,6 @@ void CSGBrushOperation::Build2DFaces::addFacesToMesh(MeshMerge &r_mesh_merge, bo CSGBrushOperation::Build2DFaces::Build2DFaces(const CSGBrush &p_brush, int p_face_idx, float p_vertex_snap2) : vertex_snap2(p_vertex_snap2 * p_vertex_snap2) { - // Convert 3D vertex points to 2D. Vector3 points_3D[3] = { p_brush.faces[p_face_idx].vertices[0], @@ -1356,7 +1350,6 @@ CSGBrushOperation::Build2DFaces::Build2DFaces(const CSGBrush &p_brush, int p_fac } void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face_idx_a, const CSGBrush &p_brush_b, const int p_face_idx_b, Build2DFaceCollection &p_collection, float p_vertex_snap) { - Vector3 vertices_a[3] = { p_brush_a.faces[p_face_idx_a].vertices[0], p_brush_a.faces[p_face_idx_a].vertices[1], @@ -1384,7 +1377,9 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face p_collection.build2DFacesB[p_face_idx_b] = Build2DFaces(); has_degenerate = true; } - if (has_degenerate) return; + if (has_degenerate) { + return; + } // Ensure B has points either side of or in the plane of A. int in_plane_count = 0, over_count = 0, under_count = 0; @@ -1392,15 +1387,18 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face ERR_FAIL_COND_MSG(plane_a.normal == Vector3(), "Couldn't form plane from Brush A face."); for (int i = 0; i < 3; i++) { - if (plane_a.has_point(vertices_b[i])) + if (plane_a.has_point(vertices_b[i])) { in_plane_count++; - else if (plane_a.is_point_over(vertices_b[i])) + } else if (plane_a.is_point_over(vertices_b[i])) { over_count++; - else + } else { under_count++; + } } // If all points under or over the plane, there is no intesection. - if (over_count == 3 || under_count == 3) return; + if (over_count == 3 || under_count == 3) { + return; + } // Ensure A has points either side of or in the plane of B. in_plane_count = 0; @@ -1410,31 +1408,32 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face ERR_FAIL_COND_MSG(plane_b.normal == Vector3(), "Couldn't form plane from Brush B face."); for (int i = 0; i < 3; i++) { - if (plane_b.has_point(vertices_a[i])) + if (plane_b.has_point(vertices_a[i])) { in_plane_count++; - else if (plane_b.is_point_over(vertices_a[i])) + } else if (plane_b.is_point_over(vertices_a[i])) { over_count++; - else + } else { under_count++; + } } // If all points under or over the plane, there is no intesection. - if (over_count == 3 || under_count == 3) return; + if (over_count == 3 || under_count == 3) { + return; + } // Check for intersection using the SAT theorem. { - // Edge pair cross product combinations. for (int i = 0; i < 3; i++) { - Vector3 axis_a = (vertices_a[i] - vertices_a[(i + 1) % 3]).normalized(); for (int j = 0; j < 3; j++) { - Vector3 axis_b = (vertices_b[j] - vertices_b[(j + 1) % 3]).normalized(); Vector3 sep_axis = axis_a.cross(axis_b); - if (sep_axis == Vector3()) + if (sep_axis == Vector3()) { continue; //colineal + } sep_axis.normalize(); real_t min_a = 1e20, max_a = -1e20; diff --git a/modules/csg/csg.h b/modules/csg/csg.h index d389cbc283..34ee239c17 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -44,7 +44,6 @@ #include "scene/resources/material.h" struct CSGBrush { - struct Face { Vector3 vertices[3]; Vector2 uvs[3]; @@ -65,7 +64,6 @@ struct CSGBrush { }; struct CSGBrushOperation { - enum Operation { OPERATION_UNION, OPERATION_INTERSECTION, @@ -75,7 +73,6 @@ struct CSGBrushOperation { void merge_brushes(Operation p_operation, const CSGBrush &p_brush_a, const CSGBrush &p_brush_b, CSGBrush &r_merged_brush, float p_vertex_snap); struct MeshMerge { - struct Face { bool from_b; bool inside; @@ -156,7 +153,6 @@ struct CSGBrushOperation { }; struct Build2DFaces { - struct Vertex2D { Vector2 point; Vector2 uv; diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp index 1b63bccb06..9fa7dc1340 100644 --- a/modules/csg/csg_gizmos.cpp +++ b/modules/csg/csg_gizmos.cpp @@ -32,8 +32,7 @@ /////////// -CSGShapeSpatialGizmoPlugin::CSGShapeSpatialGizmoPlugin() { - +CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/csg", Color(0.0, 0.4, 1, 0.15)); create_material("shape_union_material", gizmo_color); create_material("shape_union_solid_material", gizmo_color); @@ -49,70 +48,64 @@ CSGShapeSpatialGizmoPlugin::CSGShapeSpatialGizmoPlugin() { create_handle_material("handles"); } -String CSGShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { - - CSGShape *cs = Object::cast_to<CSGShape>(p_gizmo->get_spatial_node()); - - if (Object::cast_to<CSGSphere>(cs)) { +String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const { + CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); + if (Object::cast_to<CSGSphere3D>(cs)) { return "Radius"; } - if (Object::cast_to<CSGBox>(cs)) { - + if (Object::cast_to<CSGBox3D>(cs)) { static const char *hname[3] = { "Width", "Height", "Depth" }; return hname[p_idx]; } - if (Object::cast_to<CSGCylinder>(cs)) { - + if (Object::cast_to<CSGCylinder3D>(cs)) { return p_idx == 0 ? "Radius" : "Height"; } - if (Object::cast_to<CSGTorus>(cs)) { - + if (Object::cast_to<CSGTorus3D>(cs)) { return p_idx == 0 ? "InnerRadius" : "OuterRadius"; } return ""; } -Variant CSGShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { - CSGShape *cs = Object::cast_to<CSGShape>(p_gizmo->get_spatial_node()); +Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const { + CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); - if (Object::cast_to<CSGSphere>(cs)) { - - CSGSphere *s = Object::cast_to<CSGSphere>(cs); + if (Object::cast_to<CSGSphere3D>(cs)) { + CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs); return s->get_radius(); } - if (Object::cast_to<CSGBox>(cs)) { - - CSGBox *s = Object::cast_to<CSGBox>(cs); + if (Object::cast_to<CSGBox3D>(cs)) { + CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); switch (p_idx) { - case 0: return s->get_width(); - case 1: return s->get_height(); - case 2: return s->get_depth(); + case 0: + return s->get_width(); + case 1: + return s->get_height(); + case 2: + return s->get_depth(); } } - if (Object::cast_to<CSGCylinder>(cs)) { - - CSGCylinder *s = Object::cast_to<CSGCylinder>(cs); + if (Object::cast_to<CSGCylinder3D>(cs)) { + CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); return p_idx == 0 ? s->get_radius() : s->get_height(); } - if (Object::cast_to<CSGTorus>(cs)) { - - CSGTorus *s = Object::cast_to<CSGTorus>(cs); + if (Object::cast_to<CSGTorus3D>(cs)) { + CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs); return p_idx == 0 ? s->get_inner_radius() : s->get_outer_radius(); } return Variant(); } -void CSGShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { - CSGShape *cs = Object::cast_to<CSGShape>(p_gizmo->get_spatial_node()); +void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) { + CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); Transform gt = cs->get_global_transform(); //gt.orthonormalize(); @@ -123,127 +116,147 @@ void CSGShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - if (Object::cast_to<CSGSphere>(cs)) { - - CSGSphere *s = Object::cast_to<CSGSphere>(cs); + if (Object::cast_to<CSGSphere3D>(cs)) { + CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs); Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb); float d = ra.x; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; + } s->set_radius(d); } - if (Object::cast_to<CSGBox>(cs)) { - - CSGBox *s = Object::cast_to<CSGBox>(cs); + if (Object::cast_to<CSGBox3D>(cs)) { + CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); Vector3 axis; axis[p_idx] = 1.0; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; + } switch (p_idx) { - case 0: s->set_width(d * 2); break; - case 1: s->set_height(d * 2); break; - case 2: s->set_depth(d * 2); break; + case 0: + s->set_width(d * 2); + break; + case 1: + s->set_height(d * 2); + break; + case 2: + s->set_depth(d * 2); + break; } } - if (Object::cast_to<CSGCylinder>(cs)) { - - CSGCylinder *s = Object::cast_to<CSGCylinder>(cs); + if (Object::cast_to<CSGCylinder3D>(cs)) { + CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); Vector3 axis; axis[p_idx == 0 ? 0 : 1] = 1.0; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; + } - if (p_idx == 0) + if (p_idx == 0) { s->set_radius(d); - else if (p_idx == 1) + } else if (p_idx == 1) { s->set_height(d * 2.0); + } } - if (Object::cast_to<CSGTorus>(cs)) { - - CSGTorus *s = Object::cast_to<CSGTorus>(cs); + if (Object::cast_to<CSGTorus3D>(cs)) { + CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs); Vector3 axis; axis[0] = 1.0; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::stepify(d, Node3DEditor::get_singleton()->get_translate_snap()); } - if (d < 0.001) + if (d < 0.001) { d = 0.001; + } - if (p_idx == 0) + if (p_idx == 0) { s->set_inner_radius(d); - else if (p_idx == 1) + } else if (p_idx == 1) { s->set_outer_radius(d); + } } } -void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - CSGShape *cs = Object::cast_to<CSGShape>(p_gizmo->get_spatial_node()); +void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { + CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); - if (Object::cast_to<CSGSphere>(cs)) { - CSGSphere *s = Object::cast_to<CSGSphere>(cs); + if (Object::cast_to<CSGSphere3D>(cs)) { + CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs); if (p_cancel) { s->set_radius(p_restore); return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Sphere Shape Radius")); ur->add_do_method(s, "set_radius", s->get_radius()); ur->add_undo_method(s, "set_radius", p_restore); ur->commit_action(); } - if (Object::cast_to<CSGBox>(cs)) { - CSGBox *s = Object::cast_to<CSGBox>(cs); + if (Object::cast_to<CSGBox3D>(cs)) { + CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); if (p_cancel) { switch (p_idx) { - case 0: s->set_width(p_restore); break; - case 1: s->set_height(p_restore); break; - case 2: s->set_depth(p_restore); break; + case 0: + s->set_width(p_restore); + break; + case 1: + s->set_height(p_restore); + break; + case 2: + s->set_depth(p_restore); + break; } return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Box Shape Extents")); static const char *method[3] = { "set_width", "set_height", "set_depth" }; float current = 0; switch (p_idx) { - case 0: current = s->get_width(); break; - case 1: current = s->get_height(); break; - case 2: current = s->get_depth(); break; + case 0: + current = s->get_width(); + break; + case 1: + current = s->get_height(); + break; + case 2: + current = s->get_depth(); + break; } ur->add_do_method(s, method[p_idx], current); @@ -251,17 +264,18 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int ur->commit_action(); } - if (Object::cast_to<CSGCylinder>(cs)) { - CSGCylinder *s = Object::cast_to<CSGCylinder>(cs); + if (Object::cast_to<CSGCylinder3D>(cs)) { + CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); if (p_cancel) { - if (p_idx == 0) + if (p_idx == 0) { s->set_radius(p_restore); - else + } else { s->set_height(p_restore); + } return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); if (p_idx == 0) { ur->create_action(TTR("Change Cylinder Radius")); ur->add_do_method(s, "set_radius", s->get_radius()); @@ -275,17 +289,18 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int ur->commit_action(); } - if (Object::cast_to<CSGTorus>(cs)) { - CSGTorus *s = Object::cast_to<CSGTorus>(cs); + if (Object::cast_to<CSGTorus3D>(cs)) { + CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs); if (p_cancel) { - if (p_idx == 0) + if (p_idx == 0) { s->set_inner_radius(p_restore); - else + } else { s->set_outer_radius(p_restore); + } return; } - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); if (p_idx == 0) { ur->create_action(TTR("Change Torus Inner Radius")); ur->add_do_method(s, "set_inner_radius", s->get_inner_radius()); @@ -299,37 +314,37 @@ void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int ur->commit_action(); } } -bool CSGShapeSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to<CSGSphere>(p_spatial) || Object::cast_to<CSGBox>(p_spatial) || Object::cast_to<CSGCylinder>(p_spatial) || Object::cast_to<CSGTorus>(p_spatial) || Object::cast_to<CSGMesh>(p_spatial) || Object::cast_to<CSGPolygon>(p_spatial); + +bool CSGShape3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<CSGSphere3D>(p_spatial) || Object::cast_to<CSGBox3D>(p_spatial) || Object::cast_to<CSGCylinder3D>(p_spatial) || Object::cast_to<CSGTorus3D>(p_spatial) || Object::cast_to<CSGMesh3D>(p_spatial) || Object::cast_to<CSGPolygon3D>(p_spatial); } -String CSGShapeSpatialGizmoPlugin::get_name() const { - return "CSGShapes"; +String CSGShape3DGizmoPlugin::get_name() const { + return "CSGShape3D"; } -int CSGShapeSpatialGizmoPlugin::get_priority() const { +int CSGShape3DGizmoPlugin::get_priority() const { return -1; } -bool CSGShapeSpatialGizmoPlugin::is_selectable_when_hidden() const { +bool CSGShape3DGizmoPlugin::is_selectable_when_hidden() const { return true; } -void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - - CSGShape *cs = Object::cast_to<CSGShape>(p_gizmo->get_spatial_node()); +void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node()); p_gizmo->clear(); Ref<Material> material; switch (cs->get_operation()) { - case CSGShape::OPERATION_UNION: + case CSGShape3D::OPERATION_UNION: material = get_material("shape_union_material", p_gizmo); break; - case CSGShape::OPERATION_INTERSECTION: + case CSGShape3D::OPERATION_INTERSECTION: material = get_material("shape_intersection_material", p_gizmo); break; - case CSGShape::OPERATION_SUBTRACTION: + case CSGShape3D::OPERATION_SUBTRACTION: material = get_material("shape_subtraction_material", p_gizmo); break; } @@ -366,13 +381,13 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Ref<Material> solid_material; switch (cs->get_operation()) { - case CSGShape::OPERATION_UNION: + case CSGShape3D::OPERATION_UNION: solid_material = get_material("shape_union_solid_material", p_gizmo); break; - case CSGShape::OPERATION_INTERSECTION: + case CSGShape3D::OPERATION_INTERSECTION: solid_material = get_material("shape_intersection_solid_material", p_gizmo); break; - case CSGShape::OPERATION_SUBTRACTION: + case CSGShape3D::OPERATION_SUBTRACTION: solid_material = get_material("shape_subtraction_solid_material", p_gizmo); break; } @@ -380,8 +395,8 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), solid_material); } - if (Object::cast_to<CSGSphere>(cs)) { - CSGSphere *s = Object::cast_to<CSGSphere>(cs); + if (Object::cast_to<CSGSphere3D>(cs)) { + CSGSphere3D *s = Object::cast_to<CSGSphere3D>(cs); float r = s->get_radius(); Vector<Vector3> handles; @@ -389,8 +404,8 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to<CSGBox>(cs)) { - CSGBox *s = Object::cast_to<CSGBox>(cs); + if (Object::cast_to<CSGBox3D>(cs)) { + CSGBox3D *s = Object::cast_to<CSGBox3D>(cs); Vector<Vector3> handles; handles.push_back(Vector3(s->get_width() * 0.5, 0, 0)); @@ -399,8 +414,8 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to<CSGCylinder>(cs)) { - CSGCylinder *s = Object::cast_to<CSGCylinder>(cs); + if (Object::cast_to<CSGCylinder3D>(cs)) { + CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs); Vector<Vector3> handles; handles.push_back(Vector3(s->get_radius(), 0, 0)); @@ -408,8 +423,8 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, handles_material); } - if (Object::cast_to<CSGTorus>(cs)) { - CSGTorus *s = Object::cast_to<CSGTorus>(cs); + if (Object::cast_to<CSGTorus3D>(cs)) { + CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs); Vector<Vector3> handles; handles.push_back(Vector3(s->get_inner_radius(), 0, 0)); @@ -419,6 +434,6 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { } EditorPluginCSG::EditorPluginCSG(EditorNode *p_editor) { - Ref<CSGShapeSpatialGizmoPlugin> gizmo_plugin = Ref<CSGShapeSpatialGizmoPlugin>(memnew(CSGShapeSpatialGizmoPlugin)); - SpatialEditor::get_singleton()->add_gizmo_plugin(gizmo_plugin); + Ref<CSGShape3DGizmoPlugin> gizmo_plugin = Ref<CSGShape3DGizmoPlugin>(memnew(CSGShape3DGizmoPlugin)); + Node3DEditor::get_singleton()->add_gizmo_plugin(gizmo_plugin); } diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h index 966b654802..48a414d9c7 100644 --- a/modules/csg/csg_gizmos.h +++ b/modules/csg/csg_gizmos.h @@ -33,25 +33,24 @@ #include "csg_shape.h" #include "editor/editor_plugin.h" -#include "editor/spatial_editor_gizmos.h" +#include "editor/node_3d_editor_gizmos.h" -class CSGShapeSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { - - GDCLASS(CSGShapeSpatialGizmoPlugin, EditorSpatialGizmoPlugin); +class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin); public: - bool has_gizmo(Spatial *p_spatial); + bool has_gizmo(Node3D *p_spatial); String get_name() const; int get_priority() const; bool is_selectable_when_hidden() const; - void redraw(EditorSpatialGizmo *p_gizmo); + void redraw(EditorNode3DGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); + String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const; + Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const; + void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point); + void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); - CSGShapeSpatialGizmoPlugin(); + CSGShape3DGizmoPlugin(); }; class EditorPluginCSG : public EditorPlugin { diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 54635ae320..7df65b04c4 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -29,112 +29,107 @@ /*************************************************************************/ #include "csg_shape.h" -#include "scene/3d/path.h" +#include "scene/3d/path_3d.h" -void CSGShape::set_use_collision(bool p_enable) { - - if (use_collision == p_enable) +void CSGShape3D::set_use_collision(bool p_enable) { + if (use_collision == p_enable) { return; + } use_collision = p_enable; - if (!is_inside_tree() || !is_root_shape()) + if (!is_inside_tree() || !is_root_shape()) { return; + } if (use_collision) { root_collision_shape.instance(); - root_collision_instance = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_state(root_collision_instance, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); - PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space()); - PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); + root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC); + PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); + PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space()); + PhysicsServer3D::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); set_collision_layer(collision_layer); set_collision_mask(collision_mask); _make_dirty(); //force update } else { - PhysicsServer::get_singleton()->free(root_collision_instance); + PhysicsServer3D::get_singleton()->free(root_collision_instance); root_collision_instance = RID(); root_collision_shape.unref(); } _change_notify(); } -bool CSGShape::is_using_collision() const { +bool CSGShape3D::is_using_collision() const { return use_collision; } -void CSGShape::set_collision_layer(uint32_t p_layer) { +void CSGShape3D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; if (root_collision_instance.is_valid()) { - PhysicsServer::get_singleton()->body_set_collision_layer(root_collision_instance, p_layer); + PhysicsServer3D::get_singleton()->body_set_collision_layer(root_collision_instance, p_layer); } } -uint32_t CSGShape::get_collision_layer() const { - +uint32_t CSGShape3D::get_collision_layer() const { return collision_layer; } -void CSGShape::set_collision_mask(uint32_t p_mask) { - +void CSGShape3D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; if (root_collision_instance.is_valid()) { - PhysicsServer::get_singleton()->body_set_collision_mask(root_collision_instance, p_mask); + PhysicsServer3D::get_singleton()->body_set_collision_mask(root_collision_instance, p_mask); } } -uint32_t CSGShape::get_collision_mask() const { - +uint32_t CSGShape3D::get_collision_mask() const { return collision_mask; } -void CSGShape::set_collision_mask_bit(int p_bit, bool p_value) { - +void CSGShape3D::set_collision_mask_bit(int p_bit, bool p_value) { uint32_t mask = get_collision_mask(); - if (p_value) + if (p_value) { mask |= 1 << p_bit; - else + } else { mask &= ~(1 << p_bit); + } set_collision_mask(mask); } -bool CSGShape::get_collision_mask_bit(int p_bit) const { - +bool CSGShape3D::get_collision_mask_bit(int p_bit) const { return get_collision_mask() & (1 << p_bit); } -void CSGShape::set_collision_layer_bit(int p_bit, bool p_value) { - +void CSGShape3D::set_collision_layer_bit(int p_bit, bool p_value) { uint32_t mask = get_collision_layer(); - if (p_value) + if (p_value) { mask |= 1 << p_bit; - else + } else { mask &= ~(1 << p_bit); + } set_collision_layer(mask); } -bool CSGShape::get_collision_layer_bit(int p_bit) const { - +bool CSGShape3D::get_collision_layer_bit(int p_bit) const { return get_collision_layer() & (1 << p_bit); } -bool CSGShape::is_root_shape() const { - +bool CSGShape3D::is_root_shape() const { return !parent; } -void CSGShape::set_snap(float p_snap) { +void CSGShape3D::set_snap(float p_snap) { snap = p_snap; } -float CSGShape::get_snap() const { +float CSGShape3D::get_snap() const { return snap; } -void CSGShape::_make_dirty() { - - if (!is_inside_tree()) +void CSGShape3D::_make_dirty() { + if (!is_inside_tree()) { return; + } if (dirty) { return; @@ -150,34 +145,34 @@ void CSGShape::_make_dirty() { } } -CSGBrush *CSGShape::_get_brush() { - +CSGBrush *CSGShape3D::_get_brush() { if (dirty) { if (brush) { memdelete(brush); } - brush = NULL; + brush = nullptr; CSGBrush *n = _build_brush(); for (int i = 0; i < get_child_count(); i++) { - - CSGShape *child = Object::cast_to<CSGShape>(get_child(i)); - if (!child) + CSGShape3D *child = Object::cast_to<CSGShape3D>(get_child(i)); + if (!child) { continue; - if (!child->is_visible_in_tree()) + } + if (!child->is_visible_in_tree()) { continue; + } CSGBrush *n2 = child->_get_brush(); - if (!n2) + if (!n2) { continue; + } if (!n) { n = memnew(CSGBrush); n->copy_from(*n2, child->get_transform()); } else { - CSGBrush *nn = memnew(CSGBrush); CSGBrush *nn2 = memnew(CSGBrush); nn2->copy_from(*n2, child->get_transform()); @@ -185,9 +180,15 @@ CSGBrush *CSGShape::_get_brush() { CSGBrushOperation bop; switch (child->get_operation()) { - case CSGShape::OPERATION_UNION: bop.merge_brushes(CSGBrushOperation::OPERATION_UNION, *n, *nn2, *nn, snap); break; - case CSGShape::OPERATION_INTERSECTION: bop.merge_brushes(CSGBrushOperation::OPERATION_INTERSECTION, *n, *nn2, *nn, snap); break; - case CSGShape::OPERATION_SUBTRACTION: bop.merge_brushes(CSGBrushOperation::OPERATION_SUBSTRACTION, *n, *nn2, *nn, snap); break; + case CSGShape3D::OPERATION_UNION: + bop.merge_brushes(CSGBrushOperation::OPERATION_UNION, *n, *nn2, *nn, snap); + break; + case CSGShape3D::OPERATION_INTERSECTION: + bop.merge_brushes(CSGBrushOperation::OPERATION_INTERSECTION, *n, *nn2, *nn, snap); + break; + case CSGShape3D::OPERATION_SUBTRACTION: + bop.merge_brushes(CSGBrushOperation::OPERATION_SUBSTRACTION, *n, *nn2, *nn, snap); + break; } memdelete(n); memdelete(nn2); @@ -199,10 +200,11 @@ CSGBrush *CSGShape::_get_brush() { AABB aabb; for (int i = 0; i < n->faces.size(); i++) { for (int j = 0; j < 3; j++) { - if (i == 0 && j == 0) + if (i == 0 && j == 0) { aabb.position = n->faces[i].vertices[j]; - else + } else { aabb.expand_to(n->faces[i].vertices[j]); + } } } node_aabb = aabb; @@ -218,18 +220,18 @@ CSGBrush *CSGShape::_get_brush() { return brush; } -int CSGShape::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { +int CSGShape3D::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); return surface.vertices.size() / 3; } -int CSGShape::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { +int CSGShape3D::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { // always 3 return 3; } -void CSGShape::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { +void CSGShape3D::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); Vector3 v = surface.verticesw[iFace * 3 + iVert]; @@ -238,7 +240,7 @@ void CSGShape::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosO fvPosOut[2] = v.z; } -void CSGShape::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { +void CSGShape3D::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); Vector3 n = surface.normalsw[iFace * 3 + iVert]; @@ -247,7 +249,7 @@ void CSGShape::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOu fvNormOut[2] = n.z; } -void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { +void CSGShape3D::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); Vector2 t = surface.uvsw[iFace * 3 + iVert]; @@ -255,9 +257,8 @@ void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexc fvTexcOut[1] = t.y; } -void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, +void CSGShape3D::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, const tbool bIsOrientationPreserving, const int iFace, const int iVert) { - ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); int i = iFace * 3 + iVert; @@ -273,10 +274,10 @@ void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const f surface.tansw[i++] = d < 0 ? -1 : 1; } -void CSGShape::_update_shape() { - - if (parent) +void CSGShape3D::_update_shape() { + if (parent) { return; + } set_base(RID()); root_mesh.unref(); //byebye root mesh @@ -296,20 +297,18 @@ void CSGShape::_update_shape() { int mat = n->faces[i].material; ERR_CONTINUE(mat < -1 || mat >= face_count.size()); int idx = mat == -1 ? face_count.size() - 1 : mat; - if (n->faces[i].smooth) { - Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]); + Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]); - for (int j = 0; j < 3; j++) { - Vector3 v = n->faces[i].vertices[j]; - Vector3 add; - if (vec_map.lookup(v, add)) { - add += p.normal; - } else { - add = p.normal; - } - vec_map.set(v, add); + for (int j = 0; j < 3; j++) { + Vector3 v = n->faces[i].vertices[j]; + Vector3 add; + if (vec_map.lookup(v, add)) { + add += p.normal; + } else { + add = p.normal; } + vec_map.set(v, add); } face_count.write[idx]++; @@ -321,7 +320,6 @@ void CSGShape::_update_shape() { //create arrays for (int i = 0; i < surfaces.size(); i++) { - surfaces.write[i].vertices.resize(face_count[i] * 3); surfaces.write[i].normals.resize(face_count[i] * 3); surfaces.write[i].uvs.resize(face_count[i] * 3); @@ -342,35 +340,36 @@ void CSGShape::_update_shape() { } } - //fill arrays - Vector<Vector3> physics_faces; - bool fill_physics_faces = false; + // Update collision faces. if (root_collision_shape.is_valid()) { + Vector<Vector3> physics_faces; physics_faces.resize(n->faces.size() * 3); - fill_physics_faces = true; - } + Vector3 *physicsw = physics_faces.ptrw(); - { - Vector3 *physicsw; + for (int i = 0; i < n->faces.size(); i++) { + int order[3] = { 0, 1, 2 }; - if (fill_physics_faces) { - physicsw = physics_faces.ptrw(); + if (n->faces[i].invert) { + SWAP(order[1], order[2]); + } + + physicsw[i * 3 + 0] = n->faces[i].vertices[order[0]]; + physicsw[i * 3 + 1] = n->faces[i].vertices[order[1]]; + physicsw[i * 3 + 2] = n->faces[i].vertices[order[2]]; } - for (int i = 0; i < n->faces.size(); i++) { + root_collision_shape->set_faces(physics_faces); + } + //fill arrays + { + for (int i = 0; i < n->faces.size(); i++) { int order[3] = { 0, 1, 2 }; if (n->faces[i].invert) { SWAP(order[1], order[2]); } - if (fill_physics_faces) { - physicsw[i * 3 + 0] = n->faces[i].vertices[order[0]]; - physicsw[i * 3 + 1] = n->faces[i].vertices[order[1]]; - physicsw[i * 3 + 2] = n->faces[i].vertices[order[2]]; - } - int mat = n->faces[i].material; ERR_CONTINUE(mat < -1 || mat >= face_count.size()); int idx = mat == -1 ? face_count.size() - 1 : mat; @@ -380,7 +379,6 @@ void CSGShape::_update_shape() { Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]); for (int j = 0; j < 3; j++) { - Vector3 v = n->faces[i].vertices[j]; Vector3 normal = p.normal; @@ -390,7 +388,6 @@ void CSGShape::_update_shape() { } if (n->faces[i].invert) { - normal = -normal; } @@ -427,7 +424,7 @@ void CSGShape::_update_shape() { mkif.m_getPosition = mikktGetPosition; mkif.m_getTexCoord = mikktGetTexCoord; mkif.m_setTSpace = mikktSetTSpaceDefault; - mkif.m_setTSpaceBasic = NULL; + mkif.m_setTSpaceBasic = nullptr; SMikkTSpaceContext msc; msc.m_pInterface = &mkif; @@ -435,8 +432,9 @@ void CSGShape::_update_shape() { have_tangents = genTangSpaceDefault(&msc); } - if (surfaces[i].last_added == 0) + if (surfaces[i].last_added == 0) { continue; + } // and convert to surface array Array array; @@ -454,17 +452,14 @@ void CSGShape::_update_shape() { root_mesh->surface_set_material(idx, surfaces[i].material); } - if (root_collision_shape.is_valid()) { - root_collision_shape->set_faces(physics_faces); - } - set_base(root_mesh->get_rid()); } -AABB CSGShape::get_aabb() const { + +AABB CSGShape3D::get_aabb() const { return node_aabb; } -Vector<Vector3> CSGShape::get_brush_faces() { +Vector<Vector3> CSGShape3D::get_brush_faces() { ERR_FAIL_COND_V(!is_inside_tree(), Vector<Vector3>()); CSGBrush *b = _get_brush(); if (!b) { @@ -486,18 +481,15 @@ Vector<Vector3> CSGShape::get_brush_faces() { return faces; } -Vector<Face3> CSGShape::get_faces(uint32_t p_usage_flags) const { - +Vector<Face3> CSGShape3D::get_faces(uint32_t p_usage_flags) const { return Vector<Face3>(); } -void CSGShape::_notification(int p_what) { - +void CSGShape3D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - Node *parentn = get_parent(); if (parentn) { - parent = Object::cast_to<CSGShape>(parentn); + parent = Object::cast_to<CSGShape3D>(parentn); if (parent) { set_base(RID()); root_mesh.unref(); @@ -506,11 +498,11 @@ void CSGShape::_notification(int p_what) { if (use_collision && is_root_shape()) { root_collision_shape.instance(); - root_collision_instance = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_state(root_collision_instance, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); - PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space()); - PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); + root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC); + PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); + PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space()); + PhysicsServer3D::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); set_collision_layer(collision_layer); set_collision_mask(collision_mask); } @@ -519,27 +511,25 @@ void CSGShape::_notification(int p_what) { } if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - if (parent) { parent->_make_dirty(); } } if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (parent) { parent->_make_dirty(); } } if (p_what == NOTIFICATION_EXIT_TREE) { - - if (parent) + if (parent) { parent->_make_dirty(); - parent = NULL; + } + parent = nullptr; if (use_collision && is_root_shape() && root_collision_instance.is_valid()) { - PhysicsServer::get_singleton()->free(root_collision_instance); + PhysicsServer3D::get_singleton()->free(root_collision_instance); root_collision_instance = RID(); root_collision_shape.unref(); } @@ -547,27 +537,26 @@ void CSGShape::_notification(int p_what) { } } -void CSGShape::set_operation(Operation p_operation) { - +void CSGShape3D::set_operation(Operation p_operation) { operation = p_operation; _make_dirty(); update_gizmo(); } -CSGShape::Operation CSGShape::get_operation() const { +CSGShape3D::Operation CSGShape3D::get_operation() const { return operation; } -void CSGShape::set_calculate_tangents(bool p_calculate_tangents) { +void CSGShape3D::set_calculate_tangents(bool p_calculate_tangents) { calculate_tangents = p_calculate_tangents; _make_dirty(); } -bool CSGShape::is_calculating_tangents() const { +bool CSGShape3D::is_calculating_tangents() const { return calculate_tangents; } -void CSGShape::_validate_property(PropertyInfo &property) const { +void CSGShape3D::_validate_property(PropertyInfo &property) const { bool is_collision_prefixed = property.name.begins_with("collision_"); if ((is_collision_prefixed || property.name.begins_with("use_collision")) && is_inside_tree() && !is_root_shape()) { //hide collision if not root @@ -577,8 +566,7 @@ void CSGShape::_validate_property(PropertyInfo &property) const { } } -Array CSGShape::get_meshes() const { - +Array CSGShape3D::get_meshes() const { if (root_mesh.is_valid()) { Array arr; arr.resize(2); @@ -589,36 +577,36 @@ Array CSGShape::get_meshes() const { return Array(); } -void CSGShape::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_shape"), &CSGShape::_update_shape); - ClassDB::bind_method(D_METHOD("is_root_shape"), &CSGShape::is_root_shape); +void CSGShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_shape"), &CSGShape3D::_update_shape); + ClassDB::bind_method(D_METHOD("is_root_shape"), &CSGShape3D::is_root_shape); - ClassDB::bind_method(D_METHOD("set_operation", "operation"), &CSGShape::set_operation); - ClassDB::bind_method(D_METHOD("get_operation"), &CSGShape::get_operation); + ClassDB::bind_method(D_METHOD("set_operation", "operation"), &CSGShape3D::set_operation); + ClassDB::bind_method(D_METHOD("get_operation"), &CSGShape3D::get_operation); - ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap); - ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap); + ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape3D::set_snap); + ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape3D::get_snap); - ClassDB::bind_method(D_METHOD("set_use_collision", "operation"), &CSGShape::set_use_collision); - ClassDB::bind_method(D_METHOD("is_using_collision"), &CSGShape::is_using_collision); + ClassDB::bind_method(D_METHOD("set_use_collision", "operation"), &CSGShape3D::set_use_collision); + ClassDB::bind_method(D_METHOD("is_using_collision"), &CSGShape3D::is_using_collision); - ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CSGShape::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &CSGShape::get_collision_layer); + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CSGShape3D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &CSGShape3D::get_collision_layer); - ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CSGShape::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &CSGShape::get_collision_mask); + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CSGShape3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &CSGShape3D::get_collision_mask); - ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CSGShape::set_collision_mask_bit); - ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CSGShape::get_collision_mask_bit); + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CSGShape3D::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CSGShape3D::get_collision_mask_bit); - ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CSGShape::set_collision_layer_bit); - ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CSGShape::get_collision_layer_bit); + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CSGShape3D::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CSGShape3D::get_collision_layer_bit); - ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents); - ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents); + ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape3D::set_calculate_tangents); + ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape3D::is_calculating_tangents); - ClassDB::bind_method(D_METHOD("get_meshes"), &CSGShape::get_meshes); + ClassDB::bind_method(D_METHOD("get_meshes"), &CSGShape3D::get_meshes); ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap"); @@ -634,10 +622,10 @@ void CSGShape::_bind_methods() { BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION); } -CSGShape::CSGShape() { +CSGShape3D::CSGShape3D() { operation = OPERATION_UNION; - parent = NULL; - brush = NULL; + parent = nullptr; + brush = nullptr; dirty = false; snap = 0.001; use_collision = false; @@ -647,26 +635,25 @@ CSGShape::CSGShape() { set_notify_local_transform(true); } -CSGShape::~CSGShape() { +CSGShape3D::~CSGShape3D() { if (brush) { memdelete(brush); - brush = NULL; + brush = nullptr; } } -////////////////////////////////// -CSGBrush *CSGCombiner::_build_brush() { +////////////////////////////////// - return NULL; //does not build anything +CSGBrush *CSGCombiner3D::_build_brush() { + return nullptr; //does not build anything } -CSGCombiner::CSGCombiner() { +CSGCombiner3D::CSGCombiner3D() { } ///////////////////// -CSGBrush *CSGPrimitive::_create_brush_from_arrays(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uv, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials) { - +CSGBrush *CSGPrimitive3D::_create_brush_from_arrays(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uv, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials) { CSGBrush *brush = memnew(CSGBrush); Vector<bool> invert; @@ -683,37 +670,37 @@ CSGBrush *CSGPrimitive::_create_brush_from_arrays(const Vector<Vector3> &p_verti return brush; } -void CSGPrimitive::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_invert_faces", "invert_faces"), &CSGPrimitive::set_invert_faces); - ClassDB::bind_method(D_METHOD("is_inverting_faces"), &CSGPrimitive::is_inverting_faces); +void CSGPrimitive3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_invert_faces", "invert_faces"), &CSGPrimitive3D::set_invert_faces); + ClassDB::bind_method(D_METHOD("is_inverting_faces"), &CSGPrimitive3D::is_inverting_faces); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_faces"), "set_invert_faces", "is_inverting_faces"); } -void CSGPrimitive::set_invert_faces(bool p_invert) { - if (invert_faces == p_invert) +void CSGPrimitive3D::set_invert_faces(bool p_invert) { + if (invert_faces == p_invert) { return; + } invert_faces = p_invert; _make_dirty(); } -bool CSGPrimitive::is_inverting_faces() { +bool CSGPrimitive3D::is_inverting_faces() { return invert_faces; } -CSGPrimitive::CSGPrimitive() { +CSGPrimitive3D::CSGPrimitive3D() { invert_faces = false; } ///////////////////// -CSGBrush *CSGMesh::_build_brush() { - - if (!mesh.is_valid()) - return NULL; +CSGBrush *CSGMesh3D::_build_brush() { + if (!mesh.is_valid()) { + return nullptr; + } Vector<Vector3> vertices; Vector<bool> smooth; @@ -722,7 +709,6 @@ CSGBrush *CSGMesh::_build_brush() { Ref<Material> material = get_material(); for (int i = 0; i < mesh->get_surface_count(); i++) { - if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { continue; } @@ -731,29 +717,26 @@ CSGBrush *CSGMesh::_build_brush() { if (arrays.size() == 0) { _make_dirty(); - ERR_FAIL_COND_V(arrays.size() == 0, NULL); + ERR_FAIL_COND_V(arrays.size() == 0, nullptr); } Vector<Vector3> avertices = arrays[Mesh::ARRAY_VERTEX]; - if (avertices.size() == 0) + if (avertices.size() == 0) { continue; + } const Vector3 *vr = avertices.ptr(); Vector<Vector3> anormals = arrays[Mesh::ARRAY_NORMAL]; - const Vector3 *nr; - bool nr_used = false; + const Vector3 *nr = nullptr; if (anormals.size()) { nr = anormals.ptr(); - nr_used = true; } Vector<Vector2> auvs = arrays[Mesh::ARRAY_TEX_UV]; - const Vector2 *uvr; - bool uvr_used = false; + const Vector2 *uvr = nullptr; if (auvs.size()) { uvr = auvs.ptr(); - uvr_used = true; } Ref<Material> mat; @@ -781,7 +764,6 @@ CSGBrush *CSGMesh::_build_brush() { const int *ir = aindices.ptr(); for (int j = 0; j < is; j += 3) { - Vector3 vertex[3]; Vector3 normal[3]; Vector2 uv[3]; @@ -789,10 +771,10 @@ CSGBrush *CSGMesh::_build_brush() { for (int k = 0; k < 3; k++) { int idx = ir[j + k]; vertex[k] = vr[idx]; - if (nr_used) { + if (nr) { normal[k] = nr[idx]; } - if (uvr_used) { + if (uvr) { uv[k] = uvr[idx]; } } @@ -825,17 +807,16 @@ CSGBrush *CSGMesh::_build_brush() { Ref<Material> *mw = materials.ptrw(); for (int j = 0; j < is; j += 3) { - Vector3 vertex[3]; Vector3 normal[3]; Vector2 uv[3]; for (int k = 0; k < 3; k++) { vertex[k] = vr[j + k]; - if (nr_used) { + if (nr) { normal[k] = nr[j + k]; } - if (uvr_used) { + if (uvr) { uv[k] = uvr[j + k]; } } @@ -856,65 +837,64 @@ CSGBrush *CSGMesh::_build_brush() { } } - if (vertices.size() == 0) - return NULL; + if (vertices.size() == 0) { + return nullptr; + } return _create_brush_from_arrays(vertices, uvs, smooth, materials); } -void CSGMesh::_mesh_changed() { +void CSGMesh3D::_mesh_changed() { _make_dirty(); update_gizmo(); } -void CSGMesh::set_material(const Ref<Material> &p_material) { - if (material == p_material) +void CSGMesh3D::set_material(const Ref<Material> &p_material) { + if (material == p_material) { return; + } material = p_material; _make_dirty(); } -Ref<Material> CSGMesh::get_material() const { - +Ref<Material> CSGMesh3D::get_material() const { return material; } -void CSGMesh::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CSGMesh::set_mesh); - ClassDB::bind_method(D_METHOD("get_mesh"), &CSGMesh::get_mesh); +void CSGMesh3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CSGMesh3D::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &CSGMesh3D::get_mesh); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGMesh::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGMesh::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGMesh3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGMesh3D::get_material); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGMesh::set_mesh(const Ref<Mesh> &p_mesh) { - - if (mesh == p_mesh) +void CSGMesh3D::set_mesh(const Ref<Mesh> &p_mesh) { + if (mesh == p_mesh) { return; + } if (mesh.is_valid()) { - mesh->disconnect("changed", callable_mp(this, &CSGMesh::_mesh_changed)); + mesh->disconnect("changed", callable_mp(this, &CSGMesh3D::_mesh_changed)); } mesh = p_mesh; if (mesh.is_valid()) { - mesh->connect("changed", callable_mp(this, &CSGMesh::_mesh_changed)); + mesh->connect("changed", callable_mp(this, &CSGMesh3D::_mesh_changed)); } _make_dirty(); } -Ref<Mesh> CSGMesh::get_mesh() { +Ref<Mesh> CSGMesh3D::get_mesh() { return mesh; } //////////////////////////////// -CSGBrush *CSGSphere::_build_brush() { - +CSGBrush *CSGSphere3D::_build_brush() { // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -938,7 +918,6 @@ CSGBrush *CSGSphere::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -959,7 +938,6 @@ CSGBrush *CSGSphere::_build_brush() { double u1 = double(i) / rings; for (int j = radial_segments; j >= 1; j--) { - double lng0 = 2 * Math_PI * (double)(j - 1) / radial_segments; double x0 = Math::cos(lng0); double y0 = Math::sin(lng0); @@ -986,7 +964,6 @@ CSGBrush *CSGSphere::_build_brush() { }; if (i < rings) { - //face 1 facesw[face * 3 + 0] = v[0]; facesw[face * 3 + 1] = v[1]; @@ -1032,20 +1009,20 @@ CSGBrush *CSGSphere::_build_brush() { return brush; } -void CSGSphere::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CSGSphere::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &CSGSphere::get_radius); +void CSGSphere3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CSGSphere3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CSGSphere3D::get_radius); - ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &CSGSphere::set_radial_segments); - ClassDB::bind_method(D_METHOD("get_radial_segments"), &CSGSphere::get_radial_segments); - ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CSGSphere::set_rings); - ClassDB::bind_method(D_METHOD("get_rings"), &CSGSphere::get_rings); + ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &CSGSphere3D::set_radial_segments); + ClassDB::bind_method(D_METHOD("get_radial_segments"), &CSGSphere3D::get_radial_segments); + ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CSGSphere3D::set_rings); + ClassDB::bind_method(D_METHOD("get_rings"), &CSGSphere3D::get_rings); - ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGSphere::set_smooth_faces); - ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGSphere::get_smooth_faces); + ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGSphere3D::set_smooth_faces); + ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGSphere3D::get_smooth_faces); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGSphere::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGSphere::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGSphere3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGSphere3D::get_material); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments"); @@ -1054,7 +1031,7 @@ void CSGSphere::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGSphere::set_radius(const float p_radius) { +void CSGSphere3D::set_radius(const float p_radius) { ERR_FAIL_COND(p_radius <= 0); radius = p_radius; _make_dirty(); @@ -1062,51 +1039,49 @@ void CSGSphere::set_radius(const float p_radius) { _change_notify("radius"); } -float CSGSphere::get_radius() const { +float CSGSphere3D::get_radius() const { return radius; } -void CSGSphere::set_radial_segments(const int p_radial_segments) { +void CSGSphere3D::set_radial_segments(const int p_radial_segments) { radial_segments = p_radial_segments > 4 ? p_radial_segments : 4; _make_dirty(); update_gizmo(); } -int CSGSphere::get_radial_segments() const { +int CSGSphere3D::get_radial_segments() const { return radial_segments; } -void CSGSphere::set_rings(const int p_rings) { +void CSGSphere3D::set_rings(const int p_rings) { rings = p_rings > 1 ? p_rings : 1; _make_dirty(); update_gizmo(); } -int CSGSphere::get_rings() const { +int CSGSphere3D::get_rings() const { return rings; } -void CSGSphere::set_smooth_faces(const bool p_smooth_faces) { +void CSGSphere3D::set_smooth_faces(const bool p_smooth_faces) { smooth_faces = p_smooth_faces; _make_dirty(); } -bool CSGSphere::get_smooth_faces() const { +bool CSGSphere3D::get_smooth_faces() const { return smooth_faces; } -void CSGSphere::set_material(const Ref<Material> &p_material) { - +void CSGSphere3D::set_material(const Ref<Material> &p_material) { material = p_material; _make_dirty(); } -Ref<Material> CSGSphere::get_material() const { - +Ref<Material> CSGSphere3D::get_material() const { return material; } -CSGSphere::CSGSphere() { +CSGSphere3D::CSGSphere3D() { // defaults radius = 1.0; radial_segments = 12; @@ -1116,8 +1091,7 @@ CSGSphere::CSGSphere() { /////////////// -CSGBrush *CSGBox::_build_brush() { - +CSGBrush *CSGBox3D::_build_brush() { // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -1141,7 +1115,6 @@ CSGBrush *CSGBox::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1153,25 +1126,22 @@ CSGBrush *CSGBox::_build_brush() { Vector3 vertex_mul(width * 0.5, height * 0.5, depth * 0.5); { - for (int i = 0; i < 6; i++) { - Vector3 face_points[4]; float uv_points[8] = { 0, 0, 0, 1, 1, 1, 1, 0 }; for (int j = 0; j < 4; j++) { - float v[3]; v[0] = 1.0; v[1] = 1 - 2 * ((j >> 1) & 1); v[2] = v[1] * (1 - 2 * (j & 1)); for (int k = 0; k < 3; k++) { - - if (i < 3) + if (i < 3) { face_points[j][(i + k) % 3] = v[k]; - else + } else { face_points[3 - j][(i + k) % 3] = -v[k]; + } } } @@ -1221,18 +1191,18 @@ CSGBrush *CSGBox::_build_brush() { return brush; } -void CSGBox::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_width", "width"), &CSGBox::set_width); - ClassDB::bind_method(D_METHOD("get_width"), &CSGBox::get_width); +void CSGBox3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_width", "width"), &CSGBox3D::set_width); + ClassDB::bind_method(D_METHOD("get_width"), &CSGBox3D::get_width); - ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGBox::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CSGBox::get_height); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGBox3D::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CSGBox3D::get_height); - ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGBox::set_depth); - ClassDB::bind_method(D_METHOD("get_depth"), &CSGBox::get_depth); + ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGBox3D::set_depth); + ClassDB::bind_method(D_METHOD("get_depth"), &CSGBox3D::get_depth); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGBox::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGBox::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGBox3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGBox3D::get_material); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_height", "get_height"); @@ -1240,52 +1210,50 @@ void CSGBox::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGBox::set_width(const float p_width) { +void CSGBox3D::set_width(const float p_width) { width = p_width; _make_dirty(); update_gizmo(); _change_notify("width"); } -float CSGBox::get_width() const { +float CSGBox3D::get_width() const { return width; } -void CSGBox::set_height(const float p_height) { +void CSGBox3D::set_height(const float p_height) { height = p_height; _make_dirty(); update_gizmo(); _change_notify("height"); } -float CSGBox::get_height() const { +float CSGBox3D::get_height() const { return height; } -void CSGBox::set_depth(const float p_depth) { +void CSGBox3D::set_depth(const float p_depth) { depth = p_depth; _make_dirty(); update_gizmo(); _change_notify("depth"); } -float CSGBox::get_depth() const { +float CSGBox3D::get_depth() const { return depth; } -void CSGBox::set_material(const Ref<Material> &p_material) { - +void CSGBox3D::set_material(const Ref<Material> &p_material) { material = p_material; _make_dirty(); update_gizmo(); } -Ref<Material> CSGBox::get_material() const { - +Ref<Material> CSGBox3D::get_material() const { return material; } -CSGBox::CSGBox() { +CSGBox3D::CSGBox3D() { // defaults width = 2.0; height = 2.0; @@ -1294,8 +1262,7 @@ CSGBox::CSGBox() { /////////////// -CSGBrush *CSGCylinder::_build_brush() { - +CSGBrush *CSGCylinder3D::_build_brush() { // set our bounding box CSGBrush *brush = memnew(CSGBrush); @@ -1319,7 +1286,6 @@ CSGBrush *CSGCylinder::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1331,9 +1297,7 @@ CSGBrush *CSGCylinder::_build_brush() { Vector3 vertex_mul(radius, height * 0.5, radius); { - for (int i = 0; i < sides; i++) { - float inc = float(i) / sides; float inc_n = float((i + 1)) / sides; @@ -1430,24 +1394,24 @@ CSGBrush *CSGCylinder::_build_brush() { return brush; } -void CSGCylinder::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CSGCylinder::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &CSGCylinder::get_radius); +void CSGCylinder3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CSGCylinder3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CSGCylinder3D::get_radius); - ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGCylinder::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CSGCylinder::get_height); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CSGCylinder3D::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CSGCylinder3D::get_height); - ClassDB::bind_method(D_METHOD("set_sides", "sides"), &CSGCylinder::set_sides); - ClassDB::bind_method(D_METHOD("get_sides"), &CSGCylinder::get_sides); + ClassDB::bind_method(D_METHOD("set_sides", "sides"), &CSGCylinder3D::set_sides); + ClassDB::bind_method(D_METHOD("get_sides"), &CSGCylinder3D::get_sides); - ClassDB::bind_method(D_METHOD("set_cone", "cone"), &CSGCylinder::set_cone); - ClassDB::bind_method(D_METHOD("is_cone"), &CSGCylinder::is_cone); + ClassDB::bind_method(D_METHOD("set_cone", "cone"), &CSGCylinder3D::set_cone); + ClassDB::bind_method(D_METHOD("is_cone"), &CSGCylinder3D::is_cone); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGCylinder::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGCylinder::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGCylinder3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGCylinder3D::get_material); - ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGCylinder::set_smooth_faces); - ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGCylinder::get_smooth_faces); + ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGCylinder3D::set_smooth_faces); + ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGCylinder3D::get_smooth_faces); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_height", "get_height"); @@ -1457,70 +1421,68 @@ void CSGCylinder::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGCylinder::set_radius(const float p_radius) { +void CSGCylinder3D::set_radius(const float p_radius) { radius = p_radius; _make_dirty(); update_gizmo(); _change_notify("radius"); } -float CSGCylinder::get_radius() const { +float CSGCylinder3D::get_radius() const { return radius; } -void CSGCylinder::set_height(const float p_height) { +void CSGCylinder3D::set_height(const float p_height) { height = p_height; _make_dirty(); update_gizmo(); _change_notify("height"); } -float CSGCylinder::get_height() const { +float CSGCylinder3D::get_height() const { return height; } -void CSGCylinder::set_sides(const int p_sides) { +void CSGCylinder3D::set_sides(const int p_sides) { ERR_FAIL_COND(p_sides < 3); sides = p_sides; _make_dirty(); update_gizmo(); } -int CSGCylinder::get_sides() const { +int CSGCylinder3D::get_sides() const { return sides; } -void CSGCylinder::set_cone(const bool p_cone) { +void CSGCylinder3D::set_cone(const bool p_cone) { cone = p_cone; _make_dirty(); update_gizmo(); } -bool CSGCylinder::is_cone() const { +bool CSGCylinder3D::is_cone() const { return cone; } -void CSGCylinder::set_smooth_faces(const bool p_smooth_faces) { +void CSGCylinder3D::set_smooth_faces(const bool p_smooth_faces) { smooth_faces = p_smooth_faces; _make_dirty(); } -bool CSGCylinder::get_smooth_faces() const { +bool CSGCylinder3D::get_smooth_faces() const { return smooth_faces; } -void CSGCylinder::set_material(const Ref<Material> &p_material) { - +void CSGCylinder3D::set_material(const Ref<Material> &p_material) { material = p_material; _make_dirty(); } -Ref<Material> CSGCylinder::get_material() const { - +Ref<Material> CSGCylinder3D::get_material() const { return material; } -CSGCylinder::CSGCylinder() { +CSGCylinder3D::CSGCylinder3D() { // defaults radius = 1.0; height = 1.0; @@ -1531,15 +1493,15 @@ CSGCylinder::CSGCylinder() { /////////////// -CSGBrush *CSGTorus::_build_brush() { - +CSGBrush *CSGTorus3D::_build_brush() { // set our bounding box float min_radius = inner_radius; float max_radius = outer_radius; - if (min_radius == max_radius) - return NULL; //sorry, can't + if (min_radius == max_radius) { + return nullptr; //sorry, can't + } if (min_radius > max_radius) { SWAP(min_radius, max_radius); @@ -1568,7 +1530,6 @@ CSGBrush *CSGTorus::_build_brush() { invert.resize(face_count); { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1578,9 +1539,7 @@ CSGBrush *CSGTorus::_build_brush() { int face = 0; { - for (int i = 0; i < sides; i++) { - float inci = float(i) / sides; float inci_n = float((i + 1)) / sides; @@ -1591,7 +1550,6 @@ CSGBrush *CSGTorus::_build_brush() { Vector3 normali_n = Vector3(Math::cos(angi_n), 0, Math::sin(angi_n)); for (int j = 0; j < ring_sides; j++) { - float incj = float(j) / ring_sides; float incj_n = float((j + 1)) / ring_sides; @@ -1657,24 +1615,24 @@ CSGBrush *CSGTorus::_build_brush() { return brush; } -void CSGTorus::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &CSGTorus::set_inner_radius); - ClassDB::bind_method(D_METHOD("get_inner_radius"), &CSGTorus::get_inner_radius); +void CSGTorus3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &CSGTorus3D::set_inner_radius); + ClassDB::bind_method(D_METHOD("get_inner_radius"), &CSGTorus3D::get_inner_radius); - ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &CSGTorus::set_outer_radius); - ClassDB::bind_method(D_METHOD("get_outer_radius"), &CSGTorus::get_outer_radius); + ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &CSGTorus3D::set_outer_radius); + ClassDB::bind_method(D_METHOD("get_outer_radius"), &CSGTorus3D::get_outer_radius); - ClassDB::bind_method(D_METHOD("set_sides", "sides"), &CSGTorus::set_sides); - ClassDB::bind_method(D_METHOD("get_sides"), &CSGTorus::get_sides); + ClassDB::bind_method(D_METHOD("set_sides", "sides"), &CSGTorus3D::set_sides); + ClassDB::bind_method(D_METHOD("get_sides"), &CSGTorus3D::get_sides); - ClassDB::bind_method(D_METHOD("set_ring_sides", "sides"), &CSGTorus::set_ring_sides); - ClassDB::bind_method(D_METHOD("get_ring_sides"), &CSGTorus::get_ring_sides); + ClassDB::bind_method(D_METHOD("set_ring_sides", "sides"), &CSGTorus3D::set_ring_sides); + ClassDB::bind_method(D_METHOD("get_ring_sides"), &CSGTorus3D::get_ring_sides); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGTorus::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGTorus::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGTorus3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGTorus3D::get_material); - ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGTorus::set_smooth_faces); - ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGTorus::get_smooth_faces); + ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGTorus3D::set_smooth_faces); + ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGTorus3D::get_smooth_faces); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_inner_radius", "get_inner_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_EXP_RANGE, "0.001,1000.0,0.001,or_greater"), "set_outer_radius", "get_outer_radius"); @@ -1684,71 +1642,69 @@ void CSGTorus::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "StandardMaterial3D,ShaderMaterial"), "set_material", "get_material"); } -void CSGTorus::set_inner_radius(const float p_inner_radius) { +void CSGTorus3D::set_inner_radius(const float p_inner_radius) { inner_radius = p_inner_radius; _make_dirty(); update_gizmo(); _change_notify("inner_radius"); } -float CSGTorus::get_inner_radius() const { +float CSGTorus3D::get_inner_radius() const { return inner_radius; } -void CSGTorus::set_outer_radius(const float p_outer_radius) { +void CSGTorus3D::set_outer_radius(const float p_outer_radius) { outer_radius = p_outer_radius; _make_dirty(); update_gizmo(); _change_notify("outer_radius"); } -float CSGTorus::get_outer_radius() const { +float CSGTorus3D::get_outer_radius() const { return outer_radius; } -void CSGTorus::set_sides(const int p_sides) { +void CSGTorus3D::set_sides(const int p_sides) { ERR_FAIL_COND(p_sides < 3); sides = p_sides; _make_dirty(); update_gizmo(); } -int CSGTorus::get_sides() const { +int CSGTorus3D::get_sides() const { return sides; } -void CSGTorus::set_ring_sides(const int p_ring_sides) { +void CSGTorus3D::set_ring_sides(const int p_ring_sides) { ERR_FAIL_COND(p_ring_sides < 3); ring_sides = p_ring_sides; _make_dirty(); update_gizmo(); } -int CSGTorus::get_ring_sides() const { +int CSGTorus3D::get_ring_sides() const { return ring_sides; } -void CSGTorus::set_smooth_faces(const bool p_smooth_faces) { +void CSGTorus3D::set_smooth_faces(const bool p_smooth_faces) { smooth_faces = p_smooth_faces; _make_dirty(); } -bool CSGTorus::get_smooth_faces() const { +bool CSGTorus3D::get_smooth_faces() const { return smooth_faces; } -void CSGTorus::set_material(const Ref<Material> &p_material) { - +void CSGTorus3D::set_material(const Ref<Material> &p_material) { material = p_material; _make_dirty(); } -Ref<Material> CSGTorus::get_material() const { - +Ref<Material> CSGTorus3D::get_material() const { return material; } -CSGTorus::CSGTorus() { +CSGTorus3D::CSGTorus3D() { // defaults inner_radius = 2.0; outer_radius = 3.0; @@ -1759,12 +1715,12 @@ CSGTorus::CSGTorus() { /////////////// -CSGBrush *CSGPolygon::_build_brush() { - +CSGBrush *CSGPolygon3D::_build_brush() { // set our bounding box - if (polygon.size() < 3) - return NULL; + if (polygon.size() < 3) { + return nullptr; + } Vector<Point2> final_polygon = polygon; @@ -1774,10 +1730,11 @@ CSGBrush *CSGPolygon::_build_brush() { Vector<int> triangles = Geometry::triangulate_polygon(final_polygon); - if (triangles.size() < 3) - return NULL; + if (triangles.size() < 3) { + return nullptr; + } - Path *path = NULL; + Path3D *path = nullptr; Ref<Curve3D> curve; // get bounds for our polygon @@ -1789,51 +1746,68 @@ CSGBrush *CSGPolygon::_build_brush() { final_polygon_min = p; final_polygon_max = final_polygon_min; } else { - if (p.x < final_polygon_min.x) final_polygon_min.x = p.x; - if (p.y < final_polygon_min.y) final_polygon_min.y = p.y; + if (p.x < final_polygon_min.x) { + final_polygon_min.x = p.x; + } + if (p.y < final_polygon_min.y) { + final_polygon_min.y = p.y; + } - if (p.x > final_polygon_max.x) final_polygon_max.x = p.x; - if (p.y > final_polygon_max.y) final_polygon_max.y = p.y; + if (p.x > final_polygon_max.x) { + final_polygon_max.x = p.x; + } + if (p.y > final_polygon_max.y) { + final_polygon_max.y = p.y; + } } } Vector2 final_polygon_size = final_polygon_max - final_polygon_min; if (mode == MODE_PATH) { - if (!has_node(path_node)) - return NULL; + if (!has_node(path_node)) { + return nullptr; + } Node *n = get_node(path_node); - if (!n) - return NULL; - path = Object::cast_to<Path>(n); - if (!path) - return NULL; + if (!n) { + return nullptr; + } + path = Object::cast_to<Path3D>(n); + if (!path) { + return nullptr; + } if (path != path_cache) { if (path_cache) { - path_cache->disconnect("tree_exited", callable_mp(this, &CSGPolygon::_path_exited)); - path_cache->disconnect("curve_changed", callable_mp(this, &CSGPolygon::_path_changed)); - path_cache = NULL; + path_cache->disconnect("tree_exited", callable_mp(this, &CSGPolygon3D::_path_exited)); + path_cache->disconnect("curve_changed", callable_mp(this, &CSGPolygon3D::_path_changed)); + path_cache = nullptr; } path_cache = path; - path_cache->connect("tree_exited", callable_mp(this, &CSGPolygon::_path_exited)); - path_cache->connect("curve_changed", callable_mp(this, &CSGPolygon::_path_changed)); - path_cache = NULL; + path_cache->connect("tree_exited", callable_mp(this, &CSGPolygon3D::_path_exited)); + path_cache->connect("curve_changed", callable_mp(this, &CSGPolygon3D::_path_changed)); + path_cache = nullptr; } curve = path->get_curve(); - if (curve.is_null()) - return NULL; - if (curve->get_baked_length() <= 0) - return NULL; + if (curve.is_null()) { + return nullptr; + } + if (curve->get_baked_length() <= 0) { + return nullptr; + } } CSGBrush *brush = memnew(CSGBrush); int face_count = 0; switch (mode) { - case MODE_DEPTH: face_count = triangles.size() * 2 / 3 + (final_polygon.size()) * 2; break; - case MODE_SPIN: face_count = (spin_degrees < 360 ? triangles.size() * 2 / 3 : 0) + (final_polygon.size()) * 2 * spin_sides; break; + case MODE_DEPTH: + face_count = triangles.size() * 2 / 3 + (final_polygon.size()) * 2; + break; + case MODE_SPIN: + face_count = (spin_degrees < 360 ? triangles.size() * 2 / 3 : 0) + (final_polygon.size()) * 2 * spin_sides; + break; case MODE_PATH: { float bl = curve->get_baked_length(); int splits = MAX(2, Math::ceil(bl / path_interval)); @@ -1863,7 +1837,6 @@ CSGBrush *CSGPolygon::_build_brush() { AABB aabb; //must be computed { - Vector3 *facesw = faces.ptrw(); Vector2 *uvsw = uvs.ptrw(); bool *smoothw = smooth.ptrw(); @@ -1874,10 +1847,8 @@ CSGBrush *CSGPolygon::_build_brush() { switch (mode) { case MODE_DEPTH: { - //add triangles, front and back for (int i = 0; i < 2; i++) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, i == 0 ? 1 : 2, i == 0 ? 2 : 1 }; @@ -1902,7 +1873,6 @@ CSGBrush *CSGPolygon::_build_brush() { //add triangles for depth for (int i = 0; i < final_polygon.size(); i++) { - int i_n = (i + 1) % final_polygon.size(); Vector3 v[4] = { @@ -1952,9 +1922,7 @@ CSGBrush *CSGPolygon::_build_brush() { } break; case MODE_SPIN: { - for (int i = 0; i < spin_sides; i++) { - float inci = float(i) / spin_sides; float inci_n = float((i + 1)) / spin_sides; @@ -1966,7 +1934,6 @@ CSGBrush *CSGPolygon::_build_brush() { //add triangles for depth for (int j = 0; j < final_polygon.size(); j++) { - int j_n = (j + 1) % final_polygon.size(); Vector3 v[4] = { @@ -2015,7 +1982,6 @@ CSGBrush *CSGPolygon::_build_brush() { } if (i == 0 && spin_degrees < 360) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, 2, 1 }; @@ -2033,7 +1999,6 @@ CSGBrush *CSGPolygon::_build_brush() { } if (i == spin_sides - 1 && spin_degrees < 360) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, 1, 2 }; @@ -2053,7 +2018,6 @@ CSGBrush *CSGPolygon::_build_brush() { } } break; case MODE_PATH: { - float bl = curve->get_baked_length(); int splits = MAX(2, Math::ceil(bl / path_interval)); float u1 = 0.0; @@ -2079,7 +2043,6 @@ CSGBrush *CSGPolygon::_build_brush() { } for (int i = 0; i <= splits; i++) { - float ofs = i * path_interval; if (ofs > bl) { ofs = bl; @@ -2119,7 +2082,6 @@ CSGBrush *CSGPolygon::_build_brush() { //put triangles where they belong //add triangles for depth for (int j = 0; j < final_polygon.size(); j++) { - int j_n = (j + 1) % final_polygon.size(); Vector3 v[4] = { @@ -2169,7 +2131,6 @@ CSGBrush *CSGPolygon::_build_brush() { } if (i == 0 && !path_joined) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, 1, 2 }; @@ -2187,7 +2148,6 @@ CSGBrush *CSGPolygon::_build_brush() { } if (i == splits && !path_joined) { - for (int j = 0; j < triangles.size(); j += 3) { for (int k = 0; k < 3; k++) { int src[3] = { 0, 2, 1 }; @@ -2231,17 +2191,17 @@ CSGBrush *CSGPolygon::_build_brush() { return brush; } -void CSGPolygon::_notification(int p_what) { +void CSGPolygon3D::_notification(int p_what) { if (p_what == NOTIFICATION_EXIT_TREE) { if (path_cache) { - path_cache->disconnect("tree_exited", callable_mp(this, &CSGPolygon::_path_exited)); - path_cache->disconnect("curve_changed", callable_mp(this, &CSGPolygon::_path_changed)); - path_cache = NULL; + path_cache->disconnect("tree_exited", callable_mp(this, &CSGPolygon3D::_path_exited)); + path_cache->disconnect("curve_changed", callable_mp(this, &CSGPolygon3D::_path_changed)); + path_cache = nullptr; } } } -void CSGPolygon::_validate_property(PropertyInfo &property) const { +void CSGPolygon3D::_validate_property(PropertyInfo &property) const { if (property.name.begins_with("spin") && mode != MODE_SPIN) { property.usage = 0; } @@ -2252,60 +2212,60 @@ void CSGPolygon::_validate_property(PropertyInfo &property) const { property.usage = 0; } - CSGShape::_validate_property(property); + CSGShape3D::_validate_property(property); } -void CSGPolygon::_path_changed() { +void CSGPolygon3D::_path_changed() { _make_dirty(); update_gizmo(); } -void CSGPolygon::_path_exited() { - path_cache = NULL; +void CSGPolygon3D::_path_exited() { + path_cache = nullptr; } -void CSGPolygon::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CSGPolygon::set_polygon); - ClassDB::bind_method(D_METHOD("get_polygon"), &CSGPolygon::get_polygon); +void CSGPolygon3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &CSGPolygon3D::set_polygon); + ClassDB::bind_method(D_METHOD("get_polygon"), &CSGPolygon3D::get_polygon); - ClassDB::bind_method(D_METHOD("set_mode", "mode"), &CSGPolygon::set_mode); - ClassDB::bind_method(D_METHOD("get_mode"), &CSGPolygon::get_mode); + ClassDB::bind_method(D_METHOD("set_mode", "mode"), &CSGPolygon3D::set_mode); + ClassDB::bind_method(D_METHOD("get_mode"), &CSGPolygon3D::get_mode); - ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGPolygon::set_depth); - ClassDB::bind_method(D_METHOD("get_depth"), &CSGPolygon::get_depth); + ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CSGPolygon3D::set_depth); + ClassDB::bind_method(D_METHOD("get_depth"), &CSGPolygon3D::get_depth); - ClassDB::bind_method(D_METHOD("set_spin_degrees", "degrees"), &CSGPolygon::set_spin_degrees); - ClassDB::bind_method(D_METHOD("get_spin_degrees"), &CSGPolygon::get_spin_degrees); + ClassDB::bind_method(D_METHOD("set_spin_degrees", "degrees"), &CSGPolygon3D::set_spin_degrees); + ClassDB::bind_method(D_METHOD("get_spin_degrees"), &CSGPolygon3D::get_spin_degrees); - ClassDB::bind_method(D_METHOD("set_spin_sides", "spin_sides"), &CSGPolygon::set_spin_sides); - ClassDB::bind_method(D_METHOD("get_spin_sides"), &CSGPolygon::get_spin_sides); + ClassDB::bind_method(D_METHOD("set_spin_sides", "spin_sides"), &CSGPolygon3D::set_spin_sides); + ClassDB::bind_method(D_METHOD("get_spin_sides"), &CSGPolygon3D::get_spin_sides); - ClassDB::bind_method(D_METHOD("set_path_node", "path"), &CSGPolygon::set_path_node); - ClassDB::bind_method(D_METHOD("get_path_node"), &CSGPolygon::get_path_node); + ClassDB::bind_method(D_METHOD("set_path_node", "path"), &CSGPolygon3D::set_path_node); + ClassDB::bind_method(D_METHOD("get_path_node"), &CSGPolygon3D::get_path_node); - ClassDB::bind_method(D_METHOD("set_path_interval", "distance"), &CSGPolygon::set_path_interval); - ClassDB::bind_method(D_METHOD("get_path_interval"), &CSGPolygon::get_path_interval); + ClassDB::bind_method(D_METHOD("set_path_interval", "distance"), &CSGPolygon3D::set_path_interval); + ClassDB::bind_method(D_METHOD("get_path_interval"), &CSGPolygon3D::get_path_interval); - ClassDB::bind_method(D_METHOD("set_path_rotation", "mode"), &CSGPolygon::set_path_rotation); - ClassDB::bind_method(D_METHOD("get_path_rotation"), &CSGPolygon::get_path_rotation); + ClassDB::bind_method(D_METHOD("set_path_rotation", "mode"), &CSGPolygon3D::set_path_rotation); + ClassDB::bind_method(D_METHOD("get_path_rotation"), &CSGPolygon3D::get_path_rotation); - ClassDB::bind_method(D_METHOD("set_path_local", "enable"), &CSGPolygon::set_path_local); - ClassDB::bind_method(D_METHOD("is_path_local"), &CSGPolygon::is_path_local); + ClassDB::bind_method(D_METHOD("set_path_local", "enable"), &CSGPolygon3D::set_path_local); + ClassDB::bind_method(D_METHOD("is_path_local"), &CSGPolygon3D::is_path_local); - ClassDB::bind_method(D_METHOD("set_path_continuous_u", "enable"), &CSGPolygon::set_path_continuous_u); - ClassDB::bind_method(D_METHOD("is_path_continuous_u"), &CSGPolygon::is_path_continuous_u); + ClassDB::bind_method(D_METHOD("set_path_continuous_u", "enable"), &CSGPolygon3D::set_path_continuous_u); + ClassDB::bind_method(D_METHOD("is_path_continuous_u"), &CSGPolygon3D::is_path_continuous_u); - ClassDB::bind_method(D_METHOD("set_path_joined", "enable"), &CSGPolygon::set_path_joined); - ClassDB::bind_method(D_METHOD("is_path_joined"), &CSGPolygon::is_path_joined); + ClassDB::bind_method(D_METHOD("set_path_joined", "enable"), &CSGPolygon3D::set_path_joined); + ClassDB::bind_method(D_METHOD("is_path_joined"), &CSGPolygon3D::is_path_joined); - ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGPolygon::set_material); - ClassDB::bind_method(D_METHOD("get_material"), &CSGPolygon::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGPolygon3D::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGPolygon3D::get_material); - ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGPolygon::set_smooth_faces); - ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGPolygon::get_smooth_faces); + ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGPolygon3D::set_smooth_faces); + ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGPolygon3D::get_smooth_faces); - ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CSGPolygon::_is_editable_3d_polygon); - ClassDB::bind_method(D_METHOD("_has_editable_3d_polygon_no_depth"), &CSGPolygon::_has_editable_3d_polygon_no_depth); + ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CSGPolygon3D::_is_editable_3d_polygon); + ClassDB::bind_method(D_METHOD("_has_editable_3d_polygon_no_depth"), &CSGPolygon3D::_has_editable_3d_polygon_no_depth); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Depth,Spin,Path"), "set_mode", "get_mode"); @@ -2330,148 +2290,147 @@ void CSGPolygon::_bind_methods() { BIND_ENUM_CONSTANT(PATH_ROTATION_PATH_FOLLOW); } -void CSGPolygon::set_polygon(const Vector<Vector2> &p_polygon) { +void CSGPolygon3D::set_polygon(const Vector<Vector2> &p_polygon) { polygon = p_polygon; _make_dirty(); update_gizmo(); } -Vector<Vector2> CSGPolygon::get_polygon() const { +Vector<Vector2> CSGPolygon3D::get_polygon() const { return polygon; } -void CSGPolygon::set_mode(Mode p_mode) { +void CSGPolygon3D::set_mode(Mode p_mode) { mode = p_mode; _make_dirty(); update_gizmo(); _change_notify(); } -CSGPolygon::Mode CSGPolygon::get_mode() const { +CSGPolygon3D::Mode CSGPolygon3D::get_mode() const { return mode; } -void CSGPolygon::set_depth(const float p_depth) { +void CSGPolygon3D::set_depth(const float p_depth) { ERR_FAIL_COND(p_depth < 0.001); depth = p_depth; _make_dirty(); update_gizmo(); } -float CSGPolygon::get_depth() const { +float CSGPolygon3D::get_depth() const { return depth; } -void CSGPolygon::set_path_continuous_u(bool p_enable) { +void CSGPolygon3D::set_path_continuous_u(bool p_enable) { path_continuous_u = p_enable; _make_dirty(); } -bool CSGPolygon::is_path_continuous_u() const { +bool CSGPolygon3D::is_path_continuous_u() const { return path_continuous_u; } -void CSGPolygon::set_spin_degrees(const float p_spin_degrees) { +void CSGPolygon3D::set_spin_degrees(const float p_spin_degrees) { ERR_FAIL_COND(p_spin_degrees < 0.01 || p_spin_degrees > 360); spin_degrees = p_spin_degrees; _make_dirty(); update_gizmo(); } -float CSGPolygon::get_spin_degrees() const { +float CSGPolygon3D::get_spin_degrees() const { return spin_degrees; } -void CSGPolygon::set_spin_sides(const int p_spin_sides) { +void CSGPolygon3D::set_spin_sides(const int p_spin_sides) { ERR_FAIL_COND(p_spin_sides < 3); spin_sides = p_spin_sides; _make_dirty(); update_gizmo(); } -int CSGPolygon::get_spin_sides() const { +int CSGPolygon3D::get_spin_sides() const { return spin_sides; } -void CSGPolygon::set_path_node(const NodePath &p_path) { +void CSGPolygon3D::set_path_node(const NodePath &p_path) { path_node = p_path; _make_dirty(); update_gizmo(); } -NodePath CSGPolygon::get_path_node() const { +NodePath CSGPolygon3D::get_path_node() const { return path_node; } -void CSGPolygon::set_path_interval(float p_interval) { +void CSGPolygon3D::set_path_interval(float p_interval) { ERR_FAIL_COND_MSG(p_interval < 0.001, "Path interval cannot be smaller than 0.001."); path_interval = p_interval; _make_dirty(); update_gizmo(); } -float CSGPolygon::get_path_interval() const { + +float CSGPolygon3D::get_path_interval() const { return path_interval; } -void CSGPolygon::set_path_rotation(PathRotation p_rotation) { +void CSGPolygon3D::set_path_rotation(PathRotation p_rotation) { path_rotation = p_rotation; _make_dirty(); update_gizmo(); } -CSGPolygon::PathRotation CSGPolygon::get_path_rotation() const { +CSGPolygon3D::PathRotation CSGPolygon3D::get_path_rotation() const { return path_rotation; } -void CSGPolygon::set_path_local(bool p_enable) { +void CSGPolygon3D::set_path_local(bool p_enable) { path_local = p_enable; _make_dirty(); update_gizmo(); } -bool CSGPolygon::is_path_local() const { +bool CSGPolygon3D::is_path_local() const { return path_local; } -void CSGPolygon::set_path_joined(bool p_enable) { +void CSGPolygon3D::set_path_joined(bool p_enable) { path_joined = p_enable; _make_dirty(); update_gizmo(); } -bool CSGPolygon::is_path_joined() const { +bool CSGPolygon3D::is_path_joined() const { return path_joined; } -void CSGPolygon::set_smooth_faces(const bool p_smooth_faces) { +void CSGPolygon3D::set_smooth_faces(const bool p_smooth_faces) { smooth_faces = p_smooth_faces; _make_dirty(); } -bool CSGPolygon::get_smooth_faces() const { +bool CSGPolygon3D::get_smooth_faces() const { return smooth_faces; } -void CSGPolygon::set_material(const Ref<Material> &p_material) { - +void CSGPolygon3D::set_material(const Ref<Material> &p_material) { material = p_material; _make_dirty(); } -Ref<Material> CSGPolygon::get_material() const { - +Ref<Material> CSGPolygon3D::get_material() const { return material; } -bool CSGPolygon::_is_editable_3d_polygon() const { +bool CSGPolygon3D::_is_editable_3d_polygon() const { return true; } -bool CSGPolygon::_has_editable_3d_polygon_no_depth() const { +bool CSGPolygon3D::_has_editable_3d_polygon_no_depth() const { return true; } -CSGPolygon::CSGPolygon() { +CSGPolygon3D::CSGPolygon3D() { // defaults mode = MODE_DEPTH; polygon.push_back(Vector2(0, 0)); @@ -2487,5 +2446,5 @@ CSGPolygon::CSGPolygon() { path_local = false; path_continuous_u = false; path_joined = false; - path_cache = NULL; + path_cache = nullptr; } diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h index fdbf979fe7..7e95d685c5 100644 --- a/modules/csg/csg_shape.h +++ b/modules/csg/csg_shape.h @@ -34,12 +34,12 @@ #define CSGJS_HEADER_ONLY #include "csg.h" -#include "scene/3d/visual_instance.h" -#include "scene/resources/concave_polygon_shape.h" +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/concave_polygon_shape_3d.h" #include "thirdparty/misc/mikktspace.h" -class CSGShape : public GeometryInstance { - GDCLASS(CSGShape, GeometryInstance); +class CSGShape3D : public GeometryInstance3D { + GDCLASS(CSGShape3D, GeometryInstance3D); public: enum Operation { @@ -51,7 +51,7 @@ public: private: Operation operation; - CSGShape *parent; + CSGShape3D *parent; CSGBrush *brush; @@ -63,7 +63,7 @@ private: bool use_collision; uint32_t collision_layer; uint32_t collision_mask; - Ref<ConcavePolygonShape> root_collision_shape; + Ref<ConcavePolygonShape3D> root_collision_shape; RID root_collision_instance; bool calculate_tangents; @@ -111,7 +111,7 @@ protected: static void _bind_methods(); - friend class CSGCombiner; + friend class CSGCombiner3D; CSGBrush *_get_brush(); virtual void _validate_property(PropertyInfo &property) const; @@ -149,24 +149,24 @@ public: bool is_calculating_tangents() const; bool is_root_shape() const; - CSGShape(); - ~CSGShape(); + CSGShape3D(); + ~CSGShape3D(); }; -VARIANT_ENUM_CAST(CSGShape::Operation) +VARIANT_ENUM_CAST(CSGShape3D::Operation) -class CSGCombiner : public CSGShape { - GDCLASS(CSGCombiner, CSGShape); +class CSGCombiner3D : public CSGShape3D { + GDCLASS(CSGCombiner3D, CSGShape3D); private: virtual CSGBrush *_build_brush(); public: - CSGCombiner(); + CSGCombiner3D(); }; -class CSGPrimitive : public CSGShape { - GDCLASS(CSGPrimitive, CSGShape); +class CSGPrimitive3D : public CSGShape3D { + GDCLASS(CSGPrimitive3D, CSGShape3D); private: bool invert_faces; @@ -179,11 +179,11 @@ public: void set_invert_faces(bool p_invert); bool is_inverting_faces(); - CSGPrimitive(); + CSGPrimitive3D(); }; -class CSGMesh : public CSGPrimitive { - GDCLASS(CSGMesh, CSGPrimitive); +class CSGMesh3D : public CSGPrimitive3D { + GDCLASS(CSGMesh3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); @@ -203,9 +203,8 @@ public: Ref<Material> get_material() const; }; -class CSGSphere : public CSGPrimitive { - - GDCLASS(CSGSphere, CSGPrimitive); +class CSGSphere3D : public CSGPrimitive3D { + GDCLASS(CSGSphere3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); Ref<Material> material; @@ -233,12 +232,11 @@ public: void set_smooth_faces(bool p_smooth_faces); bool get_smooth_faces() const; - CSGSphere(); + CSGSphere3D(); }; -class CSGBox : public CSGPrimitive { - - GDCLASS(CSGBox, CSGPrimitive); +class CSGBox3D : public CSGPrimitive3D { + GDCLASS(CSGBox3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); Ref<Material> material; @@ -262,12 +260,11 @@ public: void set_material(const Ref<Material> &p_material); Ref<Material> get_material() const; - CSGBox(); + CSGBox3D(); }; -class CSGCylinder : public CSGPrimitive { - - GDCLASS(CSGCylinder, CSGPrimitive); +class CSGCylinder3D : public CSGPrimitive3D { + GDCLASS(CSGCylinder3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); Ref<Material> material; @@ -299,12 +296,11 @@ public: void set_material(const Ref<Material> &p_material); Ref<Material> get_material() const; - CSGCylinder(); + CSGCylinder3D(); }; -class CSGTorus : public CSGPrimitive { - - GDCLASS(CSGTorus, CSGPrimitive); +class CSGTorus3D : public CSGPrimitive3D { + GDCLASS(CSGTorus3D, CSGPrimitive3D); virtual CSGBrush *_build_brush(); Ref<Material> material; @@ -336,12 +332,11 @@ public: void set_material(const Ref<Material> &p_material); Ref<Material> get_material() const; - CSGTorus(); + CSGTorus3D(); }; -class CSGPolygon : public CSGPrimitive { - - GDCLASS(CSGPolygon, CSGPrimitive); +class CSGPolygon3D : public CSGPrimitive3D { + GDCLASS(CSGPolygon3D, CSGPrimitive3D); public: enum Mode { @@ -431,10 +426,10 @@ public: void set_material(const Ref<Material> &p_material); Ref<Material> get_material() const; - CSGPolygon(); + CSGPolygon3D(); }; -VARIANT_ENUM_CAST(CSGPolygon::Mode) -VARIANT_ENUM_CAST(CSGPolygon::PathRotation) +VARIANT_ENUM_CAST(CSGPolygon3D::Mode) +VARIANT_ENUM_CAST(CSGPolygon3D::PathRotation) #endif // CSG_SHAPE_H diff --git a/modules/csg/doc_classes/CSGBox.xml b/modules/csg/doc_classes/CSGBox3D.xml index e2f0f8488a..492bf68c44 100644 --- a/modules/csg/doc_classes/CSGBox.xml +++ b/modules/csg/doc_classes/CSGBox3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGBox" inherits="CSGPrimitive" version="4.0"> +<class name="CSGBox3D" inherits="CSGPrimitive3D" version="4.0"> <brief_description> A CSG Box shape. </brief_description> diff --git a/modules/csg/doc_classes/CSGCombiner.xml b/modules/csg/doc_classes/CSGCombiner.xml deleted file mode 100644 index ab95d3c3ee..0000000000 --- a/modules/csg/doc_classes/CSGCombiner.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGCombiner" inherits="CSGShape" version="4.0"> - <brief_description> - A CSG node that allows you to combine other CSG modifiers. - </brief_description> - <description> - For complex arrangements of shapes, it is sometimes needed to add structure to your CSG nodes. The CSGCombiner node allows you to create this structure. The node encapsulates the result of the CSG operations of its children. In this way, it is possible to do operations on one set of shapes that are children of one CSGCombiner node, and a set of separate operations on a second set of shapes that are children of a second CSGCombiner node, and then do an operation that takes the two end results as its input to create the final shape. - </description> - <tutorials> - </tutorials> - <methods> - </methods> - <constants> - </constants> -</class> diff --git a/modules/csg/doc_classes/CSGCombiner3D.xml b/modules/csg/doc_classes/CSGCombiner3D.xml new file mode 100644 index 0000000000..b55111eee4 --- /dev/null +++ b/modules/csg/doc_classes/CSGCombiner3D.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CSGCombiner3D" inherits="CSGShape3D" version="4.0"> + <brief_description> + A CSG node that allows you to combine other CSG modifiers. + </brief_description> + <description> + For complex arrangements of shapes, it is sometimes needed to add structure to your CSG nodes. The CSGCombiner3D node allows you to create this structure. The node encapsulates the result of the CSG operations of its children. In this way, it is possible to do operations on one set of shapes that are children of one CSGCombiner3D node, and a set of separate operations on a second set of shapes that are children of a second CSGCombiner3D node, and then do an operation that takes the two end results as its input to create the final shape. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/modules/csg/doc_classes/CSGCylinder.xml b/modules/csg/doc_classes/CSGCylinder3D.xml index 2dd8c6a8d0..bfd2a5d5f2 100644 --- a/modules/csg/doc_classes/CSGCylinder.xml +++ b/modules/csg/doc_classes/CSGCylinder3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGCylinder" inherits="CSGPrimitive" version="4.0"> +<class name="CSGCylinder3D" inherits="CSGPrimitive3D" version="4.0"> <brief_description> A CSG Cylinder shape. </brief_description> diff --git a/modules/csg/doc_classes/CSGMesh.xml b/modules/csg/doc_classes/CSGMesh3D.xml index f1fe2c286b..1bab8f4ee9 100644 --- a/modules/csg/doc_classes/CSGMesh.xml +++ b/modules/csg/doc_classes/CSGMesh3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGMesh" inherits="CSGPrimitive" version="4.0"> +<class name="CSGMesh3D" inherits="CSGPrimitive3D" version="4.0"> <brief_description> A CSG Mesh shape that uses a mesh resource. </brief_description> diff --git a/modules/csg/doc_classes/CSGPolygon.xml b/modules/csg/doc_classes/CSGPolygon3D.xml index 02b2e8b03f..c55fa0983e 100644 --- a/modules/csg/doc_classes/CSGPolygon.xml +++ b/modules/csg/doc_classes/CSGPolygon3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGPolygon" inherits="CSGPrimitive" version="4.0"> +<class name="CSGPolygon3D" inherits="CSGPrimitive3D" version="4.0"> <brief_description> Extrudes a 2D polygon shape to create a 3D mesh. </brief_description> @@ -17,7 +17,7 @@ <member name="material" type="Material" setter="set_material" getter="get_material"> Material to use for the resulting mesh. </member> - <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="CSGPolygon.Mode" default="0"> + <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="CSGPolygon3D.Mode" default="0"> Extrusion mode. </member> <member name="path_continuous_u" type="bool" setter="set_path_continuous_u" getter="is_path_continuous_u"> @@ -30,12 +30,12 @@ If [code]true[/code] the start and end of our path are joined together ensuring there is no seam when [member mode] is [constant MODE_PATH]. </member> <member name="path_local" type="bool" setter="set_path_local" getter="is_path_local"> - If [code]false[/code] we extrude centered on our path, if [code]true[/code] we extrude in relation to the position of our CSGPolygon when [member mode] is [constant MODE_PATH]. + If [code]false[/code] we extrude centered on our path, if [code]true[/code] we extrude in relation to the position of our CSGPolygon3D when [member mode] is [constant MODE_PATH]. </member> <member name="path_node" type="NodePath" setter="set_path_node" getter="get_path_node"> - The [Shape] object containing the path along which we extrude when [member mode] is [constant MODE_PATH]. + The [Shape3D] object containing the path along which we extrude when [member mode] is [constant MODE_PATH]. </member> - <member name="path_rotation" type="int" setter="set_path_rotation" getter="get_path_rotation" enum="CSGPolygon.PathRotation"> + <member name="path_rotation" type="int" setter="set_path_rotation" getter="get_path_rotation" enum="CSGPolygon3D.PathRotation"> The method by which each slice is rotated along the path when [member mode] is [constant MODE_PATH]. </member> <member name="polygon" type="PackedVector2Array" setter="set_polygon" getter="get_polygon" default="PackedVector2Array( 0, 0, 0, 1, 1, 1, 1, 0 )"> @@ -53,13 +53,13 @@ </members> <constants> <constant name="MODE_DEPTH" value="0" enum="Mode"> - Shape is extruded to [member depth]. + Shape3D is extruded to [member depth]. </constant> <constant name="MODE_SPIN" value="1" enum="Mode"> - Shape is extruded by rotating it around an axis. + Shape3D is extruded by rotating it around an axis. </constant> <constant name="MODE_PATH" value="2" enum="Mode"> - Shape is extruded along a path set by a [Shape] set in [member path_node]. + Shape3D is extruded along a path set by a [Shape3D] set in [member path_node]. </constant> <constant name="PATH_ROTATION_POLYGON" value="0" enum="PathRotation"> Slice is not rotated. diff --git a/modules/csg/doc_classes/CSGPrimitive.xml b/modules/csg/doc_classes/CSGPrimitive3D.xml index ba395b7edd..31b7360fac 100644 --- a/modules/csg/doc_classes/CSGPrimitive.xml +++ b/modules/csg/doc_classes/CSGPrimitive3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGPrimitive" inherits="CSGShape" version="4.0"> +<class name="CSGPrimitive3D" inherits="CSGShape3D" version="4.0"> <brief_description> Base class for CSG primitives. </brief_description> diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape3D.xml index 64a2fb1840..43ce988c30 100644 --- a/modules/csg/doc_classes/CSGShape.xml +++ b/modules/csg/doc_classes/CSGShape3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGShape" inherits="GeometryInstance" version="4.0"> +<class name="CSGShape3D" inherits="GeometryInstance3D" version="4.0"> <brief_description> The CSG base class. </brief_description> @@ -76,7 +76,7 @@ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The physics layers this CSG shape scans for collisions. </member> - <member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape.Operation" default="0"> + <member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape3D.Operation" default="0"> The operation that is performed on this shape. This is ignored for the first CSG child node as the operation is between this node and the previous child of this nodes parent. </member> <member name="snap" type="float" setter="set_snap" getter="get_snap" default="0.001"> diff --git a/modules/csg/doc_classes/CSGSphere.xml b/modules/csg/doc_classes/CSGSphere3D.xml index 847cc63586..4d5b3be099 100644 --- a/modules/csg/doc_classes/CSGSphere.xml +++ b/modules/csg/doc_classes/CSGSphere3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGSphere" inherits="CSGPrimitive" version="4.0"> +<class name="CSGSphere3D" inherits="CSGPrimitive3D" version="4.0"> <brief_description> A CSG Sphere shape. </brief_description> diff --git a/modules/csg/doc_classes/CSGTorus.xml b/modules/csg/doc_classes/CSGTorus3D.xml index 84a08edaf5..abe3eab913 100644 --- a/modules/csg/doc_classes/CSGTorus.xml +++ b/modules/csg/doc_classes/CSGTorus3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSGTorus" inherits="CSGPrimitive" version="4.0"> +<class name="CSGTorus3D" inherits="CSGPrimitive3D" version="4.0"> <brief_description> A CSG Torus shape. </brief_description> diff --git a/modules/csg/icons/CSGBox.svg b/modules/csg/icons/CSGBox3D.svg index 67e34df444..67e34df444 100644 --- a/modules/csg/icons/CSGBox.svg +++ b/modules/csg/icons/CSGBox3D.svg diff --git a/modules/csg/icons/CSGCapsule.svg b/modules/csg/icons/CSGCapsule3D.svg index 92a7b5a870..92a7b5a870 100644 --- a/modules/csg/icons/CSGCapsule.svg +++ b/modules/csg/icons/CSGCapsule3D.svg diff --git a/modules/csg/icons/CSGCombiner.svg b/modules/csg/icons/CSGCombiner3D.svg index cce2902e24..cce2902e24 100644 --- a/modules/csg/icons/CSGCombiner.svg +++ b/modules/csg/icons/CSGCombiner3D.svg diff --git a/modules/csg/icons/CSGCylinder.svg b/modules/csg/icons/CSGCylinder3D.svg index 645a74c79b..645a74c79b 100644 --- a/modules/csg/icons/CSGCylinder.svg +++ b/modules/csg/icons/CSGCylinder3D.svg diff --git a/modules/csg/icons/CSGMesh.svg b/modules/csg/icons/CSGMesh3D.svg index 6e940a4aa5..6e940a4aa5 100644 --- a/modules/csg/icons/CSGMesh.svg +++ b/modules/csg/icons/CSGMesh3D.svg diff --git a/modules/csg/icons/CSGPolygon.svg b/modules/csg/icons/CSGPolygon3D.svg index 71b03cb8e6..71b03cb8e6 100644 --- a/modules/csg/icons/CSGPolygon.svg +++ b/modules/csg/icons/CSGPolygon3D.svg diff --git a/modules/csg/icons/CSGSphere.svg b/modules/csg/icons/CSGSphere3D.svg index f81b566993..f81b566993 100644 --- a/modules/csg/icons/CSGSphere.svg +++ b/modules/csg/icons/CSGSphere3D.svg diff --git a/modules/csg/icons/CSGTorus.svg b/modules/csg/icons/CSGTorus3D.svg index 3d30aa47b2..3d30aa47b2 100644 --- a/modules/csg/icons/CSGTorus.svg +++ b/modules/csg/icons/CSGTorus3D.svg diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp index 677a20df38..a8bcc2fed1 100644 --- a/modules/csg/register_types.cpp +++ b/modules/csg/register_types.cpp @@ -34,18 +34,17 @@ #include "csg_shape.h" void register_csg_types() { - #ifndef _3D_DISABLED - ClassDB::register_virtual_class<CSGShape>(); - ClassDB::register_virtual_class<CSGPrimitive>(); - ClassDB::register_class<CSGMesh>(); - ClassDB::register_class<CSGSphere>(); - ClassDB::register_class<CSGBox>(); - ClassDB::register_class<CSGCylinder>(); - ClassDB::register_class<CSGTorus>(); - ClassDB::register_class<CSGPolygon>(); - ClassDB::register_class<CSGCombiner>(); + ClassDB::register_virtual_class<CSGShape3D>(); + ClassDB::register_virtual_class<CSGPrimitive3D>(); + ClassDB::register_class<CSGMesh3D>(); + ClassDB::register_class<CSGSphere3D>(); + ClassDB::register_class<CSGBox3D>(); + ClassDB::register_class<CSGCylinder3D>(); + ClassDB::register_class<CSGTorus3D>(); + ClassDB::register_class<CSGPolygon3D>(); + ClassDB::register_class<CSGCombiner3D>(); #ifdef TOOLS_ENABLED EditorPlugins::add_by_type<EditorPluginCSG>(); diff --git a/modules/csg/register_types.h b/modules/csg/register_types.h index 4eadeea254..926e598561 100644 --- a/modules/csg/register_types.h +++ b/modules/csg/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef CSG_REGISTER_TYPES_H +#define CSG_REGISTER_TYPES_H + void register_csg_types(); void unregister_csg_types(); + +#endif // CSG_REGISTER_TYPES_H diff --git a/modules/cvtt/SCsub b/modules/cvtt/SCsub index 746b23ca28..5438f7ebac 100644 --- a/modules/cvtt/SCsub +++ b/modules/cvtt/SCsub @@ -1,14 +1,14 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_cvtt = env_modules.Clone() # Thirdparty source files thirdparty_dir = "#thirdparty/cvtt/" thirdparty_sources = [ - "ConvectionKernels.cpp" + "ConvectionKernels.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] diff --git a/modules/cvtt/config.py b/modules/cvtt/config.py index 098f1eafa9..53b8f2f2e3 100644 --- a/modules/cvtt/config.py +++ b/modules/cvtt/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return env['tools'] + return env["tools"] + def configure(env): pass diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp index 9dbaa88202..2a4f836478 100644 --- a/modules/cvtt/image_compress_cvtt.cpp +++ b/modules/cvtt/image_compress_cvtt.cpp @@ -137,9 +137,9 @@ static void _digest_job_queue(void *p_job_queue) { } void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChannels p_channels) { - - if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA) + if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA) { return; //do not compress, already compressed + } int w = p_image->get_width(); int h = p_image->get_height(); @@ -154,16 +154,17 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann cvtt::Options options; uint32_t flags = cvtt::Flags::Fastest; - if (p_lossy_quality > 0.85) + if (p_lossy_quality > 0.85) { flags = cvtt::Flags::Ultra; - else if (p_lossy_quality > 0.75) + } else if (p_lossy_quality > 0.75) { flags = cvtt::Flags::Better; - else if (p_lossy_quality > 0.55) + } else if (p_lossy_quality > 0.55) { flags = cvtt::Flags::Default; - else if (p_lossy_quality > 0.35) + } else if (p_lossy_quality > 0.35) { flags = cvtt::Flags::Fast; - else if (p_lossy_quality > 0.15) + } else if (p_lossy_quality > 0.15) { flags = cvtt::Flags::Faster; + } flags |= cvtt::Flags::BC7_RespectPunchThrough; @@ -222,7 +223,6 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann Vector<CVTTCompressionRowTask> tasks; for (int i = 0; i <= mm_count; i++) { - int bw = w % 4 != 0 ? w + (4 - w % 4) : w; int bh = h % 4 != 0 ? h + (4 - h % 4) : h; @@ -280,7 +280,6 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann } void image_decompress_cvtt(Image *p_image) { - Image::Format target_format; bool is_signed = false; bool is_hdr = false; @@ -318,7 +317,6 @@ void image_decompress_cvtt(Image *p_image) { int dst_ofs = 0; for (int i = 0; i <= mm_count; i++) { - int src_ofs = p_image->get_mipmap_offset(i); const uint8_t *in_bytes = &rb[src_ofs]; diff --git a/modules/cvtt/register_types.cpp b/modules/cvtt/register_types.cpp index 38542a33b9..e4a01cc787 100644 --- a/modules/cvtt/register_types.cpp +++ b/modules/cvtt/register_types.cpp @@ -35,7 +35,6 @@ #include "image_compress_cvtt.h" void register_cvtt_types() { - Image::set_compress_bptc_func(image_compress_cvtt); Image::_image_decompress_bptc = image_decompress_cvtt; } diff --git a/modules/cvtt/register_types.h b/modules/cvtt/register_types.h index 93f684cdd1..8472980c6a 100644 --- a/modules/cvtt/register_types.h +++ b/modules/cvtt/register_types.h @@ -29,6 +29,13 @@ /*************************************************************************/ #ifdef TOOLS_ENABLED + +#ifndef CVTT_REGISTER_TYPES_H +#define CVTT_REGISTER_TYPES_H + void register_cvtt_types(); void unregister_cvtt_types(); -#endif + +#endif // CVTT_REGISTER_TYPES_H + +#endif // TOOLS_ENABLED diff --git a/modules/dds/SCsub b/modules/dds/SCsub index 3d92ff02d6..06980bd670 100644 --- a/modules/dds/SCsub +++ b/modules/dds/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_dds = env_modules.Clone() diff --git a/modules/dds/config.py b/modules/dds/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/dds/config.py +++ b/modules/dds/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/dds/register_types.cpp b/modules/dds/register_types.cpp index c6281ff01b..3991964a28 100644 --- a/modules/dds/register_types.cpp +++ b/modules/dds/register_types.cpp @@ -35,13 +35,11 @@ static Ref<ResourceFormatDDS> resource_loader_dds; void register_dds_types() { - resource_loader_dds.instance(); ResourceLoader::add_resource_format_loader(resource_loader_dds); } void unregister_dds_types() { - ResourceLoader::remove_resource_format_loader(resource_loader_dds); resource_loader_dds.unref(); } diff --git a/modules/dds/register_types.h b/modules/dds/register_types.h index 1808a4af36..3cb7b5c2a6 100644 --- a/modules/dds/register_types.h +++ b/modules/dds/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef DDS_REGISTER_TYPES_H +#define DDS_REGISTER_TYPES_H + void register_dds_types(); void unregister_dds_types(); + +#endif // DDS_REGISTER_TYPES_H diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index ae21156b8b..ba425371a8 100644 --- a/modules/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp @@ -94,19 +94,21 @@ static const DDSFormatInfo dds_format_info[DDS_MAX] = { { "GRAYSCALE_ALPHA", false, false, 1, 2, Image::FORMAT_LA8 } }; -RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - - if (r_error) +RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_CANT_OPEN; + } Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - if (!f) + if (!f) { return RES(); + } FileAccessRef fref(f); - if (r_error) + if (r_error) { *r_error = ERR_FILE_CORRUPT; + } ERR_FAIL_COND_V_MSG(err != OK, RES(), "Unable to open DDS texture file '" + p_path + "'."); @@ -120,13 +122,13 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, uint32_t mipmaps = f->get_32(); //skip 11 - for (int i = 0; i < 11; i++) + for (int i = 0; i < 11; i++) { f->get_32(); + } //validate if (magic != DDS_MAGIC || hsize != 124 || !(flags & DDSD_PIXELFORMAT) || !(flags & DDSD_CAPS)) { - ERR_FAIL_V_MSG(RES(), "Invalid or unsupported DDS texture file '" + p_path + "'."); } @@ -157,70 +159,55 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, */ //must avoid this later - while (f->get_position() < 128) + while (f->get_position() < 128) { f->get_8(); + } DDSFormat dds_format; if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC("DXT1")) { - dds_format = DDS_DXT1; } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC("DXT3")) { - dds_format = DDS_DXT3; } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC("DXT5")) { - dds_format = DDS_DXT5; } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC("ATI1")) { - dds_format = DDS_ATI1; } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC("ATI2")) { - dds_format = DDS_ATI2; } else if (format_flags & DDPF_FOURCC && format_fourcc == PF_FOURCC("A2XY")) { - dds_format = DDS_A2XY; } else if (format_flags & DDPF_RGB && format_flags & DDPF_ALPHAPIXELS && format_rgb_bits == 32 && format_red_mask == 0xff0000 && format_green_mask == 0xff00 && format_blue_mask == 0xff && format_alpha_mask == 0xff000000) { - dds_format = DDS_BGRA8; } else if (format_flags & DDPF_RGB && !(format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 24 && format_red_mask == 0xff0000 && format_green_mask == 0xff00 && format_blue_mask == 0xff) { - dds_format = DDS_BGR8; } else if (format_flags & DDPF_RGB && format_flags & DDPF_ALPHAPIXELS && format_rgb_bits == 32 && format_red_mask == 0xff && format_green_mask == 0xff00 && format_blue_mask == 0xff0000 && format_alpha_mask == 0xff000000) { - dds_format = DDS_RGBA8; } else if (format_flags & DDPF_RGB && !(format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 24 && format_red_mask == 0xff && format_green_mask == 0xff00 && format_blue_mask == 0xff0000) { - dds_format = DDS_RGB8; } else if (format_flags & DDPF_RGB && format_flags & DDPF_ALPHAPIXELS && format_rgb_bits == 16 && format_red_mask == 0x00007c00 && format_green_mask == 0x000003e0 && format_blue_mask == 0x0000001f && format_alpha_mask == 0x00008000) { - dds_format = DDS_BGR5A1; } else if (format_flags & DDPF_RGB && format_flags & DDPF_ALPHAPIXELS && format_rgb_bits == 32 && format_red_mask == 0x3ff00000 && format_green_mask == 0xffc00 && format_blue_mask == 0x3ff && format_alpha_mask == 0xc0000000) { - dds_format = DDS_BGR10A2; } else if (format_flags & DDPF_RGB && !(format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 16 && format_red_mask == 0x0000f800 && format_green_mask == 0x000007e0 && format_blue_mask == 0x0000001f) { - dds_format = DDS_BGR565; } else if (!(format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 8 && format_red_mask == 0xff && format_green_mask == 0xff && format_blue_mask == 0xff) { - dds_format = DDS_LUMINANCE; } else if ((format_flags & DDPF_ALPHAPIXELS) && format_rgb_bits == 16 && format_red_mask == 0xff && format_green_mask == 0xff && format_blue_mask == 0xff && format_alpha_mask == 0xff00) { - dds_format = DDS_LUMINANCE_ALPHA; } else if (format_flags & DDPF_INDEXED && format_rgb_bits == 8) { - dds_format = DDS_BGR565; } else { - printf("unrecognized fourcc %x format_flags: %x - rgbbits %i - red_mask %x green mask %x blue mask %x alpha mask %x\n", format_fourcc, format_flags, format_rgb_bits, format_red_mask, format_green_mask, format_blue_mask, format_alpha_mask); ERR_FAIL_V_MSG(RES(), "Unrecognized or unsupported color layout in DDS '" + p_path + "'."); } - if (!(flags & DDSD_MIPMAPCOUNT)) + if (!(flags & DDSD_MIPMAPCOUNT)) { mipmaps = 1; + } Vector<uint8_t> src_data; @@ -236,7 +223,6 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, ERR_FAIL_COND_V(!(flags & DDSD_LINEARSIZE), RES()); for (uint32_t i = 1; i < mipmaps; i++) { - w = MAX(1, w >> 1); h = MAX(1, h >> 1); uint32_t bsize = MAX(info.divisor, w) / info.divisor * MAX(info.divisor, h) / info.divisor * info.block_size; @@ -249,7 +235,6 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, f->get_buffer(wb, size); } else if (info.palette) { - //indexed ERR_FAIL_COND_V(!(flags & DDSD_PITCH), RES()); ERR_FAIL_COND_V(format_rgb_bits != 8, RES()); @@ -262,16 +247,15 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, int colsize = 3; for (int i = 0; i < 256; i++) { - - if (palette[i * 4 + 3] < 255) + if (palette[i * 4 + 3] < 255) { colsize = 4; + } } int w2 = width; int h2 = height; for (uint32_t i = 1; i < mipmaps; i++) { - w2 = (w2 + 1) >> 1; h2 = (h2 + 1) >> 1; size += w2 * h2 * info.block_size; @@ -282,14 +266,14 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, f->get_buffer(wb, size); for (int i = 0; i < 256; i++) { - int dst_ofs = size + i * colsize; int src_ofs = i * 4; wb[dst_ofs + 0] = palette[src_ofs + 2]; wb[dst_ofs + 1] = palette[src_ofs + 1]; wb[dst_ofs + 2] = palette[src_ofs + 0]; - if (colsize == 4) + if (colsize == 4) { wb[dst_ofs + 3] = palette[src_ofs + 3]; + } } } else { //uncompressed generic... @@ -297,30 +281,27 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, uint32_t size = width * height * info.block_size; for (uint32_t i = 1; i < mipmaps; i++) { - w = (w + 1) >> 1; h = (h + 1) >> 1; size += w * h * info.block_size; } - if (dds_format == DDS_BGR565) + if (dds_format == DDS_BGR565) { size = size * 3 / 2; - else if (dds_format == DDS_BGR5A1) + } else if (dds_format == DDS_BGR5A1) { size = size * 2; + } src_data.resize(size); uint8_t *wb = src_data.ptrw(); f->get_buffer(wb, size); switch (dds_format) { - case DDS_BGR5A1: { - // TO RGBA int colcount = size / 4; for (int i = colcount - 1; i >= 0; i--) { - int src_ofs = i * 2; int dst_ofs = i * 4; @@ -335,11 +316,9 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, } } break; case DDS_BGR565: { - int colcount = size / 3; for (int i = colcount - 1; i >= 0; i--) { - int src_ofs = i * 2; int dst_ofs = i * 3; @@ -353,12 +332,10 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, } break; case DDS_BGR10A2: { - // TO RGBA int colcount = size / 4; for (int i = colcount - 1; i >= 0; i--) { - int ofs = i * 4; uint32_t w32 = uint32_t(wb[ofs + 0]) | (uint32_t(wb[ofs + 1]) << 8) | (uint32_t(wb[ofs + 2]) << 16) | (uint32_t(wb[ofs + 3]) << 24); @@ -375,26 +352,21 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, } } break; case DDS_BGRA8: { - int colcount = size / 4; for (int i = 0; i < colcount; i++) { - SWAP(wb[i * 4 + 0], wb[i * 4 + 2]); } } break; case DDS_BGR8: { - int colcount = size / 3; for (int i = 0; i < colcount; i++) { - SWAP(wb[i * 3 + 0], wb[i * 3 + 2]); } } break; case DDS_RGBA8: { - /* do nothing either int colcount = size/4; @@ -413,7 +385,6 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, */ } break; case DDS_RGB8: { - // do nothing /* int colcount = size/3; @@ -424,12 +395,10 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, }*/ } break; case DDS_LUMINANCE: { - // do nothing i guess? } break; case DDS_LUMINANCE_ALPHA: { - // do nothing i guess? } break; @@ -444,25 +413,24 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Ref<ImageTexture> texture = memnew(ImageTexture); texture->create_from_image(img); - if (r_error) + if (r_error) { *r_error = OK; + } return texture; } void ResourceFormatDDS::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("dds"); } bool ResourceFormatDDS::handles_type(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "Texture2D"); } String ResourceFormatDDS::get_resource_type(const String &p_path) const { - - if (p_path.get_extension().to_lower() == "dds") + if (p_path.get_extension().to_lower() == "dds") { return "ImageTexture"; + } return ""; } diff --git a/modules/dds/texture_loader_dds.h b/modules/dds/texture_loader_dds.h index de8088af90..ef08967df7 100644 --- a/modules/dds/texture_loader_dds.h +++ b/modules/dds/texture_loader_dds.h @@ -36,7 +36,7 @@ class ResourceFormatDDS : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/denoise/SCsub b/modules/denoise/SCsub new file mode 100644 index 0000000000..0fa65c6296 --- /dev/null +++ b/modules/denoise/SCsub @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +import resource_to_cpp +from platform_methods import run_in_subprocess + +Import("env") +Import("env_modules") + +env_oidn = env_modules.Clone() + +# Thirdparty source files +thirdparty_dir = "#thirdparty/oidn/" +thirdparty_sources = [ + "core/api.cpp", + "core/device.cpp", + "core/filter.cpp", + "core/network.cpp", + "core/autoencoder.cpp", + "core/transfer_function.cpp", + "weights/rtlightmap_hdr.gen.cpp", + "mkl-dnn/src/common/batch_normalization.cpp", + "mkl-dnn/src/common/concat.cpp", + "mkl-dnn/src/common/convolution.cpp", + "mkl-dnn/src/common/convolution_pd.cpp", + "mkl-dnn/src/common/deconvolution.cpp", + "mkl-dnn/src/common/eltwise.cpp", + "mkl-dnn/src/common/engine.cpp", + "mkl-dnn/src/common/inner_product.cpp", + "mkl-dnn/src/common/inner_product_pd.cpp", + "mkl-dnn/src/common/lrn.cpp", + "mkl-dnn/src/common/memory.cpp", + "mkl-dnn/src/common/memory_desc_wrapper.cpp", + "mkl-dnn/src/common/mkldnn_debug.cpp", + "mkl-dnn/src/common/mkldnn_debug_autogenerated.cpp", + "mkl-dnn/src/common/pooling.cpp", + "mkl-dnn/src/common/primitive.cpp", + "mkl-dnn/src/common/primitive_attr.cpp", + "mkl-dnn/src/common/primitive_desc.cpp", + "mkl-dnn/src/common/primitive_exec_types.cpp", + "mkl-dnn/src/common/primitive_iterator.cpp", + "mkl-dnn/src/common/query.cpp", + "mkl-dnn/src/common/reorder.cpp", + "mkl-dnn/src/common/rnn.cpp", + "mkl-dnn/src/common/scratchpad.cpp", + "mkl-dnn/src/common/shuffle.cpp", + "mkl-dnn/src/common/softmax.cpp", + "mkl-dnn/src/common/stream.cpp", + "mkl-dnn/src/common/sum.cpp", + "mkl-dnn/src/common/utils.cpp", + "mkl-dnn/src/common/verbose.cpp", + "mkl-dnn/src/cpu/cpu_barrier.cpp", + "mkl-dnn/src/cpu/cpu_concat.cpp", + "mkl-dnn/src/cpu/cpu_engine.cpp", + "mkl-dnn/src/cpu/cpu_memory.cpp", + "mkl-dnn/src/cpu/cpu_reducer.cpp", + "mkl-dnn/src/cpu/cpu_reorder.cpp", + "mkl-dnn/src/cpu/cpu_sum.cpp", + "mkl-dnn/src/cpu/jit_avx2_conv_kernel_f32.cpp", + "mkl-dnn/src/cpu/jit_avx2_convolution.cpp", + "mkl-dnn/src/cpu/jit_avx512_common_conv_kernel.cpp", + "mkl-dnn/src/cpu/jit_avx512_common_conv_winograd_kernel_f32.cpp", + "mkl-dnn/src/cpu/jit_avx512_common_convolution.cpp", + "mkl-dnn/src/cpu/jit_avx512_common_convolution_winograd.cpp", + "mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_2x3.cpp", + "mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3.cpp", + "mkl-dnn/src/cpu/jit_avx512_core_fp32_wino_conv_4x3_kernel.cpp", + "mkl-dnn/src/cpu/jit_sse42_conv_kernel_f32.cpp", + "mkl-dnn/src/cpu/jit_sse42_convolution.cpp", + "mkl-dnn/src/cpu/jit_transpose_src_utils.cpp", + "mkl-dnn/src/cpu/jit_uni_eltwise.cpp", + "mkl-dnn/src/cpu/jit_uni_pool_kernel_f32.cpp", + "mkl-dnn/src/cpu/jit_uni_pooling.cpp", + "mkl-dnn/src/cpu/jit_uni_reorder.cpp", + "mkl-dnn/src/cpu/jit_uni_reorder_utils.cpp", + "mkl-dnn/src/cpu/jit_utils/jit_utils.cpp", + "mkl-dnn/src/cpu/jit_utils/jitprofiling/jitprofiling.c", + "common/platform.cpp", + "common/thread.cpp", + "common/tensor.cpp", +] +thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + +thirdparty_include_dirs = [ + "", + "include", + "mkl-dnn/include", + "mkl-dnn/src", + "mkl-dnn/src/common", + "mkl-dnn/src/cpu/xbyak", + "mkl-dnn/src/cpu", +] +thirdparty_include_dirs = [thirdparty_dir + file for file in thirdparty_include_dirs] + + +env_oidn.Prepend(CPPPATH=thirdparty_include_dirs) +env_oidn.Append( + CPPDEFINES=[ + "MKLDNN_THR=MKLDNN_THR_SEQ", + "OIDN_STATIC_LIB", + "__STDC_CONSTANT_MACROS", + "__STDC_LIMIT_MACROS", + "DISABLE_VERBOSE", + "MKLDNN_ENABLE_CONCURRENT_EXEC", + "NDEBUG", + ] +) + +env_thirdparty = env_oidn.Clone() +env_thirdparty.disable_warnings() +env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources) + +weights_in_path = thirdparty_dir + "weights/rtlightmap_hdr.tza" +weights_out_path = thirdparty_dir + "weights/rtlightmap_hdr.gen.cpp" + +env_thirdparty.Depends(weights_out_path, weights_in_path) +env_thirdparty.CommandNoCache(weights_out_path, weights_in_path, resource_to_cpp.tza_to_cpp) + +env_oidn.add_source_files(env.modules_sources, "denoise_wrapper.cpp") +env_modules.add_source_files(env.modules_sources, ["register_types.cpp", "lightmap_denoiser.cpp"]) diff --git a/modules/denoise/config.py b/modules/denoise/config.py new file mode 100644 index 0000000000..53b8f2f2e3 --- /dev/null +++ b/modules/denoise/config.py @@ -0,0 +1,6 @@ +def can_build(env, platform): + return env["tools"] + + +def configure(env): + pass diff --git a/modules/denoise/denoise_wrapper.cpp b/modules/denoise/denoise_wrapper.cpp new file mode 100644 index 0000000000..c12c6d9c31 --- /dev/null +++ b/modules/denoise/denoise_wrapper.cpp @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* denoise_wrapper.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "denoise_wrapper.h" +#include "thirdparty/oidn/include/OpenImageDenoise/oidn.h" +#include <stdio.h> + +void *oidn_denoiser_init() { + OIDNDeviceImpl *device = oidnNewDevice(OIDN_DEVICE_TYPE_CPU); + oidnCommitDevice(device); + return device; +} + +bool oidn_denoise(void *deviceptr, float *p_floats, int p_width, int p_height) { + OIDNDeviceImpl *device = (OIDNDeviceImpl *)deviceptr; + OIDNFilter filter = oidnNewFilter(device, "RTLightmap"); + oidnSetSharedFilterImage(filter, "color", (void *)p_floats, OIDN_FORMAT_FLOAT3, p_width, p_height, 0, 0, 0); + oidnSetSharedFilterImage(filter, "output", (void *)p_floats, OIDN_FORMAT_FLOAT3, p_width, p_height, 0, 0, 0); + oidnSetFilter1b(filter, "hdr", true); + //oidnSetFilter1f(filter, "hdrScale", 1.0f); + oidnCommitFilter(filter); + oidnExecuteFilter(filter); + + const char *msg; + bool success = true; + if (oidnGetDeviceError(device, &msg) != OIDN_ERROR_NONE) { + printf("LightmapDenoiser: %s\n", msg); + success = false; + } + + oidnReleaseFilter(filter); + return success; +} + +void oidn_denoiser_finish(void *device) { + oidnReleaseDevice((OIDNDeviceImpl *)device); +} diff --git a/modules/denoise/denoise_wrapper.h b/modules/denoise/denoise_wrapper.h new file mode 100644 index 0000000000..2107df09c1 --- /dev/null +++ b/modules/denoise/denoise_wrapper.h @@ -0,0 +1,38 @@ +/*************************************************************************/ +/* denoise_wrapper.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DENOISE_WRAPPER_H +#define DENOISE_WRAPPER_H + +void *oidn_denoiser_init(); +bool oidn_denoise(void *device, float *p_floats, int p_width, int p_height); +void oidn_denoiser_finish(void *device); + +#endif // DENOISE_WRAPPER_H diff --git a/modules/denoise/lightmap_denoiser.cpp b/modules/denoise/lightmap_denoiser.cpp new file mode 100644 index 0000000000..29d02e8ee2 --- /dev/null +++ b/modules/denoise/lightmap_denoiser.cpp @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* lightmap_denoiser.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "lightmap_denoiser.h" +#include "denoise_wrapper.h" + +LightmapDenoiser *LightmapDenoiserOIDN::create_oidn_denoiser() { + return memnew(LightmapDenoiserOIDN); +} + +void LightmapDenoiserOIDN::make_default_denoiser() { + create_function = create_oidn_denoiser; +} + +Ref<Image> LightmapDenoiserOIDN::denoise_image(const Ref<Image> &p_image) { + Ref<Image> img = p_image->duplicate(); + + img->convert(Image::FORMAT_RGBF); + + Vector<uint8_t> data = img->get_data(); + if (!oidn_denoise(device, (float *)data.ptrw(), img->get_width(), img->get_height())) { + return p_image; + } + + img->create(img->get_width(), img->get_height(), false, img->get_format(), data); + return img; +} + +LightmapDenoiserOIDN::LightmapDenoiserOIDN() { + device = oidn_denoiser_init(); +} + +LightmapDenoiserOIDN::~LightmapDenoiserOIDN() { + oidn_denoiser_finish(device); +} diff --git a/modules/denoise/lightmap_denoiser.h b/modules/denoise/lightmap_denoiser.h new file mode 100644 index 0000000000..5b6e257df8 --- /dev/null +++ b/modules/denoise/lightmap_denoiser.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* lightmap_denoiser.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LIGHTMAP_DENOISER_H +#define LIGHTMAP_DENOISER_H + +#include "core/object.h" +#include "scene/3d/lightmapper.h" + +struct OIDNDeviceImpl; + +class LightmapDenoiserOIDN : public LightmapDenoiser { + GDCLASS(LightmapDenoiserOIDN, LightmapDenoiser); + +protected: + void *device = nullptr; + +public: + static LightmapDenoiser *create_oidn_denoiser(); + + Ref<Image> denoise_image(const Ref<Image> &p_image); + + static void make_default_denoiser(); + + LightmapDenoiserOIDN(); + ~LightmapDenoiserOIDN(); +}; + +#endif // LIGHTMAP_DENOISER_H diff --git a/modules/gdnative/arvr/register_types.cpp b/modules/denoise/register_types.cpp index 0f6e2bca1a..b78734a531 100644 --- a/modules/gdnative/arvr/register_types.cpp +++ b/modules/denoise/register_types.cpp @@ -29,11 +29,12 @@ /*************************************************************************/ #include "register_types.h" -#include "arvr_interface_gdnative.h" +#include "core/engine.h" +#include "lightmap_denoiser.h" -void register_arvr_types() { - ClassDB::register_class<ARVRInterfaceGDNative>(); +void register_denoise_types() { + LightmapDenoiserOIDN::make_default_denoiser(); } -void unregister_arvr_types() { +void unregister_denoise_types() { } diff --git a/modules/gdnative/arvr/register_types.h b/modules/denoise/register_types.h index 815f112fbf..2ffc36ee2c 100644 --- a/modules/gdnative/arvr/register_types.h +++ b/modules/denoise/register_types.h @@ -28,5 +28,5 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -void register_arvr_types(); -void unregister_arvr_types(); +void register_denoise_types(); +void unregister_denoise_types(); diff --git a/modules/denoise/resource_to_cpp.py b/modules/denoise/resource_to_cpp.py new file mode 100644 index 0000000000..4c0b67f701 --- /dev/null +++ b/modules/denoise/resource_to_cpp.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +## ======================================================================== ## +## Copyright 2009-2019 Intel Corporation ## +## ## +## Licensed under the Apache License, Version 2.0 (the "License"); ## +## you may not use this file except in compliance with the License. ## +## You may obtain a copy of the License at ## +## ## +## http://www.apache.org/licenses/LICENSE-2.0 ## +## ## +## Unless required by applicable law or agreed to in writing, software ## +## distributed under the License is distributed on an "AS IS" BASIS, ## +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## +## See the License for the specific language governing permissions and ## +## limitations under the License. ## +## ======================================================================== ## + +import os +import sys +import argparse +from array import array + +# Generates a C++ file from the specified binary resource file +def generate(in_path, out_path): + + namespace = "oidn::weights" + scopes = namespace.split("::") + + file_name = os.path.basename(in_path) + var_name = os.path.splitext(file_name)[0] + + with open(in_path, "rb") as in_file, open(out_path, "w") as out_file: + # Header + out_file.write("// Generated from: %s\n" % file_name) + out_file.write("#include <cstddef>\n\n") + + # Open the namespaces + for s in scopes: + out_file.write("namespace %s {\n" % s) + if scopes: + out_file.write("\n") + + # Read the file + in_data = array("B", in_file.read()) + + # Write the size + out_file.write("//const size_t %s_size = %d;\n\n" % (var_name, len(in_data))) + + # Write the data + out_file.write("unsigned char %s[] = {" % var_name) + for i in range(len(in_data)): + c = in_data[i] + if i > 0: + out_file.write(",") + if (i + 1) % 20 == 1: + out_file.write("\n") + out_file.write("%d" % c) + out_file.write("\n};\n") + + # Close the namespaces + if scopes: + out_file.write("\n") + for scope in reversed(scopes): + out_file.write("} // namespace %s\n" % scope) + + +def tza_to_cpp(target, source, env): + for x in zip(source, target): + generate(str(x[0]), str(x[1])) diff --git a/modules/enet/SCsub b/modules/enet/SCsub index 485c33b1a8..c8f4b3885e 100644 --- a/modules/enet/SCsub +++ b/modules/enet/SCsub @@ -1,13 +1,13 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_enet = env_modules.Clone() # Thirdparty source files -if env['builtin_enet']: +if env["builtin_enet"]: thirdparty_dir = "#thirdparty/enet/" thirdparty_sources = [ "godot.cpp", diff --git a/modules/enet/config.py b/modules/enet/config.py index 3e30bbe778..5fd343c75d 100644 --- a/modules/enet/config.py +++ b/modules/enet/config.py @@ -1,13 +1,16 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "NetworkedMultiplayerENet", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index 406eb467f0..4e7698b67c 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -34,21 +34,18 @@ #include "core/os/os.h" void NetworkedMultiplayerENet::set_transfer_mode(TransferMode p_mode) { - transfer_mode = p_mode; } -NetworkedMultiplayerPeer::TransferMode NetworkedMultiplayerENet::get_transfer_mode() const { +NetworkedMultiplayerPeer::TransferMode NetworkedMultiplayerENet::get_transfer_mode() const { return transfer_mode; } void NetworkedMultiplayerENet::set_target_peer(int p_peer) { - target_peer = p_peer; } int NetworkedMultiplayerENet::get_packet_peer() const { - ERR_FAIL_COND_V_MSG(!active, 1, "The multiplayer instance isn't currently active."); ERR_FAIL_COND_V(incoming_packets.size() == 0, 1); @@ -56,7 +53,6 @@ int NetworkedMultiplayerENet::get_packet_peer() const { } int NetworkedMultiplayerENet::get_packet_channel() const { - ERR_FAIL_COND_V_MSG(!active, -1, "The multiplayer instance isn't currently active."); ERR_FAIL_COND_V(incoming_packets.size() == 0, -1); @@ -64,7 +60,6 @@ int NetworkedMultiplayerENet::get_packet_channel() const { } int NetworkedMultiplayerENet::get_last_packet_channel() const { - ERR_FAIL_COND_V_MSG(!active, -1, "The multiplayer instance isn't currently active."); ERR_FAIL_COND_V(!current_packet.packet, -1); @@ -72,7 +67,6 @@ int NetworkedMultiplayerENet::get_last_packet_channel() const { } Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int p_in_bandwidth, int p_out_bandwidth) { - ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "The multiplayer instance is already active."); ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The port number must be set between 0 and 65535 (inclusive)."); ERR_FAIL_COND_V_MSG(p_max_clients < 1 || p_max_clients > 4095, ERR_INVALID_PARAMETER, "The number of clients must be set between 1 and 4095 (inclusive)."); @@ -120,8 +114,8 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int connection_status = CONNECTION_CONNECTED; return OK; } -Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_port, int p_in_bandwidth, int p_out_bandwidth, int p_client_port) { +Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_port, int p_in_bandwidth, int p_out_bandwidth, int p_client_port) { ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "The multiplayer instance is already active."); ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The server port number must be set between 0 and 65535 (inclusive)."); ERR_FAIL_COND_V_MSG(p_client_port < 0 || p_client_port > 65535, ERR_INVALID_PARAMETER, "The client port number must be set between 0 and 65535 (inclusive)."); @@ -154,7 +148,7 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por p_in_bandwidth /* limit incoming bandwidth if > 0 */, p_out_bandwidth /* limit outgoing bandwidth if > 0 */); } else { - host = enet_host_create(NULL /* create a client host */, + host = enet_host_create(nullptr /* create a client host */, 1 /* only allow 1 outgoing connection */, channel_count /* allow up to channel_count to be used */, p_in_bandwidth /* limit incoming bandwidth if > 0 */, @@ -197,7 +191,7 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por // Initiate connection, allocating enough channels ENetPeer *peer = enet_host_connect(host, &address, channel_count, unique_id); - if (peer == NULL) { + if (peer == nullptr) { enet_host_destroy(host); ERR_FAIL_COND_V_MSG(!peer, ERR_CANT_CREATE, "Couldn't connect to the ENet multiplayer server."); } @@ -213,7 +207,6 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por } void NetworkedMultiplayerENet::poll() { - ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active."); _pop_current_packet(); @@ -221,9 +214,9 @@ void NetworkedMultiplayerENet::poll() { ENetEvent event; /* Keep servicing until there are no available events left in queue. */ while (true) { - - if (!host || !active) // Might have been disconnected while emitting a notification + if (!host || !active) { // Might have been disconnected while emitting a notification return; + } int ret = enet_host_service(host, &event, 0); @@ -267,33 +260,32 @@ void NetworkedMultiplayerENet::poll() { if (server) { // Do not notify other peers when server_relay is disabled. - if (!server_relay) + if (!server_relay) { break; + } // Someone connected, notify all the peers available for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) { - - if (E->key() == *new_id) + if (E->key() == *new_id) { continue; + } // Send existing peers to new peer - ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE); + ENetPacket *packet = enet_packet_create(nullptr, 8, ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_ADD_PEER, &packet->data[0]); encode_uint32(E->key(), &packet->data[4]); enet_peer_send(event.peer, SYSCH_CONFIG, packet); // Send the new peer to existing peers - packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE); + packet = enet_packet_create(nullptr, 8, ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_ADD_PEER, &packet->data[0]); encode_uint32(*new_id, &packet->data[4]); enet_peer_send(E->get(), SYSCH_CONFIG, packet); } } else { - emit_signal("connection_succeeded"); } } break; case ENET_EVENT_TYPE_DISCONNECT: { - // Reset the peer's client information. int *id = (int *)event.peer->data; @@ -307,20 +299,18 @@ void NetworkedMultiplayerENet::poll() { } if (!server) { - // Client just disconnected from server. emit_signal("server_disconnected"); close_connection(); return; } else if (server_relay) { - // Server just received a client disconnect and is in relay mode, notify everyone else. for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) { - - if (E->key() == *id) + if (E->key() == *id) { continue; + } - ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE); + ENetPacket *packet = enet_packet_create(nullptr, 8, ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_REMOVE_PEER, &packet->data[0]); encode_uint32(*id, &packet->data[4]); enet_peer_send(E->get(), SYSCH_CONFIG, packet); @@ -332,7 +322,6 @@ void NetworkedMultiplayerENet::poll() { memdelete(id); } break; case ENET_EVENT_TYPE_RECEIVE: { - if (event.channelID == SYSCH_CONFIG) { // Some config message ERR_CONTINUE(event.packet->dataLength < 8); @@ -345,13 +334,11 @@ void NetworkedMultiplayerENet::poll() { switch (msg) { case SYSMSG_ADD_PEER: { - - peer_map[id] = NULL; + peer_map[id] = nullptr; emit_signal("peer_connected", id); } break; case SYSMSG_REMOVE_PEER: { - peer_map.erase(id); emit_signal("peer_disconnected", id); } break; @@ -359,7 +346,6 @@ void NetworkedMultiplayerENet::poll() { enet_packet_destroy(event.packet); } else if (event.channelID < channel_count) { - Packet packet; packet.packet = event.packet; @@ -391,9 +377,9 @@ void NetworkedMultiplayerENet::poll() { incoming_packets.push_back(packet); // And make copies for sending for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) { - - if (uint32_t(E->key()) == source) // Do not resend to self + if (uint32_t(E->key()) == source) { // Do not resend to self continue; + } ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, packet.packet->flags); @@ -405,9 +391,9 @@ void NetworkedMultiplayerENet::poll() { // And make copies for sending for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) { - - if (uint32_t(E->key()) == source || E->key() == -target) // Do not resend to self, also do not send to excluded + if (uint32_t(E->key()) == source || E->key() == -target) { // Do not resend to self, also do not send to excluded continue; + } ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, packet.packet->flags); @@ -428,7 +414,6 @@ void NetworkedMultiplayerENet::poll() { enet_peer_send(peer_map[target], event.channelID, packet.packet); } } else { - incoming_packets.push_back(packet); } @@ -452,7 +437,6 @@ bool NetworkedMultiplayerENet::is_server() const { } void NetworkedMultiplayerENet::close_connection(uint32_t wait_usec) { - ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active."); _pop_current_packet(); @@ -484,7 +468,6 @@ void NetworkedMultiplayerENet::close_connection(uint32_t wait_usec) { } void NetworkedMultiplayerENet::disconnect_peer(int p_peer, bool now) { - ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active."); ERR_FAIL_COND_MSG(!is_server(), "Can't disconnect a peer when not acting as a server."); ERR_FAIL_COND_MSG(!peer_map.has(p_peer), vformat("Peer ID %d not found in the list of peers.", p_peer)); @@ -497,20 +480,20 @@ void NetworkedMultiplayerENet::disconnect_peer(int p_peer, bool now) { // notify everyone else, send disconnect signal & remove from peer_map like in poll() if (server_relay) { for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) { - if (E->key() == p_peer) { continue; } - ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE); + ENetPacket *packet = enet_packet_create(nullptr, 8, ENET_PACKET_FLAG_RELIABLE); encode_uint32(SYSMSG_REMOVE_PEER, &packet->data[0]); encode_uint32(p_peer, &packet->data[4]); enet_peer_send(E->get(), SYSCH_CONFIG, packet); } } - if (id) + if (id) { memdelete(id); + } emit_signal("peer_disconnected", p_peer); peer_map.erase(p_peer); @@ -520,12 +503,10 @@ void NetworkedMultiplayerENet::disconnect_peer(int p_peer, bool now) { } int NetworkedMultiplayerENet::get_available_packet_count() const { - return incoming_packets.size(); } Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - ERR_FAIL_COND_V_MSG(incoming_packets.size() == 0, ERR_UNAVAILABLE, "No incoming packets available."); _pop_current_packet(); @@ -540,7 +521,6 @@ Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buff } Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - ERR_FAIL_COND_V_MSG(!active, ERR_UNCONFIGURED, "The multiplayer instance isn't currently active."); ERR_FAIL_COND_V_MSG(connection_status != CONNECTION_CONNECTED, ERR_UNCONFIGURED, "The multiplayer instance isn't currently connected to any server or client."); @@ -549,10 +529,11 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer switch (transfer_mode) { case TRANSFER_MODE_UNRELIABLE: { - if (always_ordered) + if (always_ordered) { packet_flags = 0; - else + } else { packet_flags = ENET_PACKET_FLAG_UNSEQUENCED; + } channel = SYSCH_UNRELIABLE; } break; case TRANSFER_MODE_UNRELIABLE_ORDERED: { @@ -565,24 +546,23 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer } break; } - if (transfer_channel > SYSCH_CONFIG) + if (transfer_channel > SYSCH_CONFIG) { channel = transfer_channel; + } - Map<int, ENetPeer *>::Element *E = NULL; + Map<int, ENetPeer *>::Element *E = nullptr; if (target_peer != 0) { - E = peer_map.find(ABS(target_peer)); ERR_FAIL_COND_V_MSG(!E, ERR_INVALID_PARAMETER, vformat("Invalid target peer: %d", target_peer)); } - ENetPacket *packet = enet_packet_create(NULL, p_buffer_size + 8, packet_flags); + ENetPacket *packet = enet_packet_create(nullptr, p_buffer_size + 8, packet_flags); encode_uint32(unique_id, &packet->data[0]); // Source ID encode_uint32(target_peer, &packet->data[4]); // Dest ID copymem(&packet->data[8], p_buffer, p_buffer_size); if (server) { - if (target_peer == 0) { enet_host_broadcast(host, channel, packet); } else if (target_peer < 0) { @@ -592,9 +572,9 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer int exclude = -target_peer; for (Map<int, ENetPeer *>::Element *F = peer_map.front(); F; F = F->next()) { - - if (F->key() == exclude) // Exclude packet + if (F->key() == exclude) { // Exclude packet continue; + } ENetPacket *packet2 = enet_packet_create(packet->data, packet->dataLength, packet_flags); @@ -606,7 +586,6 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer enet_peer_send(E->get(), channel, packet); } } else { - ERR_FAIL_COND_V(!peer_map.has(1), ERR_BUG); enet_peer_send(peer_map[1], channel, packet); // Send to server for broadcast } @@ -617,31 +596,26 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer } int NetworkedMultiplayerENet::get_max_packet_size() const { - return 1 << 24; // Anything is good } void NetworkedMultiplayerENet::_pop_current_packet() { - if (current_packet.packet) { enet_packet_destroy(current_packet.packet); - current_packet.packet = NULL; + current_packet.packet = nullptr; current_packet.from = 0; current_packet.channel = -1; } } NetworkedMultiplayerPeer::ConnectionStatus NetworkedMultiplayerENet::get_connection_status() const { - return connection_status; } uint32_t NetworkedMultiplayerENet::_gen_unique_id() const { - uint32_t hash = 0; while (hash == 0 || hash == 1) { - hash = hash_djb2_one_32( (uint32_t)OS::get_singleton()->get_ticks_usec()); hash = hash_djb2_one_32( @@ -660,33 +634,27 @@ uint32_t NetworkedMultiplayerENet::_gen_unique_id() const { } int NetworkedMultiplayerENet::get_unique_id() const { - ERR_FAIL_COND_V_MSG(!active, 0, "The multiplayer instance isn't currently active."); return unique_id; } void NetworkedMultiplayerENet::set_refuse_new_connections(bool p_enable) { - refuse_connections = p_enable; } bool NetworkedMultiplayerENet::is_refusing_new_connections() const { - return refuse_connections; } void NetworkedMultiplayerENet::set_compression_mode(CompressionMode p_mode) { - compression_mode = p_mode; } NetworkedMultiplayerENet::CompressionMode NetworkedMultiplayerENet::get_compression_mode() const { - return compression_mode; } size_t NetworkedMultiplayerENet::enet_compress(void *context, const ENetBuffer *inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 *outData, size_t outLimit) { - NetworkedMultiplayerENet *enet = (NetworkedMultiplayerENet *)(context); if (size_t(enet->src_compressor_mem.size()) < inLimit) { @@ -727,11 +695,13 @@ size_t NetworkedMultiplayerENet::enet_compress(void *context, const ENetBuffer * } int ret = Compression::compress(enet->dst_compressor_mem.ptrw(), enet->src_compressor_mem.ptr(), ofs, mode); - if (ret < 0) + if (ret < 0) { return 0; + } - if (ret > int(outLimit)) + if (ret > int(outLimit)) { return 0; // Do not bother + } copymem(outData, enet->dst_compressor_mem.ptr(), ret); @@ -739,20 +709,16 @@ size_t NetworkedMultiplayerENet::enet_compress(void *context, const ENetBuffer * } size_t NetworkedMultiplayerENet::enet_decompress(void *context, const enet_uint8 *inData, size_t inLimit, enet_uint8 *outData, size_t outLimit) { - NetworkedMultiplayerENet *enet = (NetworkedMultiplayerENet *)(context); int ret = -1; switch (enet->compression_mode) { case COMPRESS_FASTLZ: { - ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_FASTLZ); } break; case COMPRESS_ZLIB: { - ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_DEFLATE); } break; case COMPRESS_ZSTD: { - ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_ZSTD); } break; default: { @@ -766,12 +732,9 @@ size_t NetworkedMultiplayerENet::enet_decompress(void *context, const enet_uint8 } void NetworkedMultiplayerENet::_setup_compressor() { - switch (compression_mode) { - case COMPRESS_NONE: { - - enet_host_compress(host, NULL); + enet_host_compress(host, nullptr); } break; case COMPRESS_RANGE_CODER: { enet_host_compress_with_range_coder(host); @@ -779,22 +742,19 @@ void NetworkedMultiplayerENet::_setup_compressor() { case COMPRESS_FASTLZ: case COMPRESS_ZLIB: case COMPRESS_ZSTD: { - enet_host_compress(host, &enet_compressor); } break; } } void NetworkedMultiplayerENet::enet_compressor_destroy(void *context) { - // Nothing to do } IP_Address NetworkedMultiplayerENet::get_peer_address(int p_peer_id) const { - ERR_FAIL_COND_V_MSG(!peer_map.has(p_peer_id), IP_Address(), vformat("Peer ID %d not found in the list of peers.", p_peer_id)); ERR_FAIL_COND_V_MSG(!is_server() && p_peer_id != 1, IP_Address(), "Can't get the address of peers other than the server (ID -1) when acting as a client."); - ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == NULL, IP_Address(), vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id)); + ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == nullptr, IP_Address(), vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id)); IP_Address out; #ifdef GODOT_ENET @@ -807,10 +767,9 @@ IP_Address NetworkedMultiplayerENet::get_peer_address(int p_peer_id) const { } int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const { - ERR_FAIL_COND_V_MSG(!peer_map.has(p_peer_id), 0, vformat("Peer ID %d not found in the list of peers.", p_peer_id)); ERR_FAIL_COND_V_MSG(!is_server() && p_peer_id != 1, 0, "Can't get the address of peers other than the server (ID -1) when acting as a client."); - ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == NULL, 0, vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id)); + ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == nullptr, 0, vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id)); #ifdef GODOT_ENET return peer_map[p_peer_id]->address.port; #else @@ -819,7 +778,6 @@ int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const { } void NetworkedMultiplayerENet::set_transfer_channel(int p_channel) { - ERR_FAIL_COND_MSG(p_channel < -1 || p_channel >= channel_count, vformat("The transfer channel must be set between 0 and %d, inclusive (got %d).", channel_count - 1, p_channel)); ERR_FAIL_COND_MSG(p_channel == SYSCH_CONFIG, vformat("The channel %d is reserved.", SYSCH_CONFIG)); transfer_channel = p_channel; @@ -830,7 +788,6 @@ int NetworkedMultiplayerENet::get_transfer_channel() const { } void NetworkedMultiplayerENet::set_channel_count(int p_channel) { - ERR_FAIL_COND_MSG(active, "The channel count can't be set while the multiplayer instance is active."); ERR_FAIL_COND_MSG(p_channel < SYSCH_MAX, vformat("The channel count must be greater than or equal to %d to account for reserved channels (got %d).", SYSCH_MAX, p_channel)); channel_count = p_channel; @@ -859,7 +816,6 @@ bool NetworkedMultiplayerENet::is_server_relay_enabled() const { } void NetworkedMultiplayerENet::_bind_methods() { - ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0)); ClassDB::bind_method(D_METHOD("create_client", "address", "port", "in_bandwidth", "out_bandwidth", "client_port"), &NetworkedMultiplayerENet::create_client, DEFVAL(0), DEFVAL(0), DEFVAL(0)); ClassDB::bind_method(D_METHOD("close_connection", "wait_usec"), &NetworkedMultiplayerENet::close_connection, DEFVAL(100)); @@ -903,14 +859,13 @@ void NetworkedMultiplayerENet::_bind_methods() { } NetworkedMultiplayerENet::NetworkedMultiplayerENet() { - active = false; server = false; refuse_connections = false; server_relay = true; unique_id = 0; target_peer = 0; - current_packet.packet = NULL; + current_packet.packet = nullptr; transfer_mode = TRANSFER_MODE_RELIABLE; channel_count = SYSCH_MAX; transfer_channel = -1; @@ -929,7 +884,6 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet() { } NetworkedMultiplayerENet::~NetworkedMultiplayerENet() { - if (active) { close_connection(); } diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h index ff436ce2c0..b2ed951327 100644 --- a/modules/enet/networked_multiplayer_enet.h +++ b/modules/enet/networked_multiplayer_enet.h @@ -38,7 +38,6 @@ #include <enet/enet.h> class NetworkedMultiplayerENet : public NetworkedMultiplayerPeer { - GDCLASS(NetworkedMultiplayerENet, NetworkedMultiplayerPeer); public: @@ -86,7 +85,6 @@ private: Map<int, ENetPeer *> peer_map; struct Packet { - ENetPacket *packet; int from; int channel; diff --git a/modules/enet/register_types.cpp b/modules/enet/register_types.cpp index 27f27196d6..18051f756a 100644 --- a/modules/enet/register_types.cpp +++ b/modules/enet/register_types.cpp @@ -35,7 +35,6 @@ static bool enet_ok = false; void register_enet_types() { - if (enet_initialize() != 0) { ERR_PRINT("ENet initialization failure"); } else { @@ -46,7 +45,7 @@ void register_enet_types() { } void unregister_enet_types() { - - if (enet_ok) + if (enet_ok) { enet_deinitialize(); + } } diff --git a/modules/enet/register_types.h b/modules/enet/register_types.h index 19f8c5a352..cac0a4f7ee 100644 --- a/modules/enet/register_types.h +++ b/modules/enet/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef ENET_REGISTER_TYPES_H +#define ENET_REGISTER_TYPES_H + void register_enet_types(); void unregister_enet_types(); + +#endif // ENET_REGISTER_TYPES_H diff --git a/modules/etc/SCsub b/modules/etc/SCsub index 1742d3534f..383bbf83c3 100644 --- a/modules/etc/SCsub +++ b/modules/etc/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_etc = env_modules.Clone() @@ -9,21 +9,21 @@ env_etc = env_modules.Clone() # Not unbundled so far since not widespread as shared library thirdparty_dir = "#thirdparty/etc2comp/" thirdparty_sources = [ - "EtcBlock4x4.cpp", - "EtcBlock4x4Encoding.cpp", - "EtcBlock4x4Encoding_ETC1.cpp", - "EtcBlock4x4Encoding_R11.cpp", - "EtcBlock4x4Encoding_RG11.cpp", - "EtcBlock4x4Encoding_RGB8A1.cpp", - "EtcBlock4x4Encoding_RGB8.cpp", - "EtcBlock4x4Encoding_RGBA8.cpp", - "Etc.cpp", - "EtcDifferentialTrys.cpp", - "EtcFilter.cpp", - "EtcImage.cpp", - "EtcIndividualTrys.cpp", - "EtcMath.cpp", - "EtcSortedBlockList.cpp", + "EtcBlock4x4.cpp", + "EtcBlock4x4Encoding.cpp", + "EtcBlock4x4Encoding_ETC1.cpp", + "EtcBlock4x4Encoding_R11.cpp", + "EtcBlock4x4Encoding_RG11.cpp", + "EtcBlock4x4Encoding_RGB8A1.cpp", + "EtcBlock4x4Encoding_RGB8.cpp", + "EtcBlock4x4Encoding_RGBA8.cpp", + "Etc.cpp", + "EtcDifferentialTrys.cpp", + "EtcFilter.cpp", + "EtcImage.cpp", + "EtcIndividualTrys.cpp", + "EtcMath.cpp", + "EtcSortedBlockList.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] diff --git a/modules/etc/config.py b/modules/etc/config.py index 098f1eafa9..53b8f2f2e3 100644 --- a/modules/etc/config.py +++ b/modules/etc/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return env['tools'] + return env["tools"] + def configure(env): pass diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp index b3f7b1d94f..9b6d8a2d35 100644 --- a/modules/etc/image_etc.cpp +++ b/modules/etc/image_etc.cpp @@ -127,8 +127,9 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f Ref<Image> img = p_img->duplicate(); - if (img->get_format() != Image::FORMAT_RGBA8) + if (img->get_format() != Image::FORMAT_RGBA8) { img->convert(Image::FORMAT_RGBA8); //still uses RGBA to convert + } if (img->has_mipmaps()) { if (next_power_of_2(imgw) != imgw || next_power_of_2(imgh) != imgh) { @@ -165,12 +166,13 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f int encoding_time = 0; float effort = 0.0; //default, reasonable time - if (p_lossy_quality > 0.75) + if (p_lossy_quality > 0.75) { effort = 0.4; - else if (p_lossy_quality > 0.85) + } else if (p_lossy_quality > 0.85) { effort = 0.6; - else if (p_lossy_quality > 0.95) + } else if (p_lossy_quality > 0.95) { effort = 0.8; + } Etc::ErrorMetric error_metric = Etc::ErrorMetric::RGBX; // NOTE: we can experiment with other error metrics Etc::Image::Format etc2comp_etc_format = _image_format_to_etc2comp_format(etc_format); @@ -192,7 +194,7 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f src_rgba_f[j] = Etc::ColorFloatRGBA::ConvertFromRGBA8(src[si], src[si + 1], src[si + 2], src[si + 3]); } - unsigned char *etc_data = NULL; + unsigned char *etc_data = nullptr; unsigned int etc_data_len = 0; unsigned int extended_width = 0, extended_height = 0; Etc::Encode((float *)src_rgba_f, mipmap_w, mipmap_h, etc2comp_etc_format, error_metric, effort, num_cpus, num_cpus, &etc_data, &etc_data_len, &extended_width, &extended_height, &encoding_time); @@ -219,7 +221,6 @@ static void _compress_etc2(Image *p_img, float p_lossy_quality, Image::UsedChann } void _register_etc_compress_func() { - Image::_image_compress_etc1_func = _compress_etc1; Image::_image_compress_etc2_func = _compress_etc2; } diff --git a/modules/etc/register_types.cpp b/modules/etc/register_types.cpp index 26809e0de9..0972857808 100644 --- a/modules/etc/register_types.cpp +++ b/modules/etc/register_types.cpp @@ -36,7 +36,6 @@ static Ref<ResourceFormatPKM> resource_loader_pkm; void register_etc_types() { - resource_loader_pkm.instance(); ResourceLoader::add_resource_format_loader(resource_loader_pkm); @@ -44,7 +43,6 @@ void register_etc_types() { } void unregister_etc_types() { - ResourceLoader::remove_resource_format_loader(resource_loader_pkm); resource_loader_pkm.unref(); } diff --git a/modules/etc/register_types.h b/modules/etc/register_types.h index fac83e7d17..247c7213af 100644 --- a/modules/etc/register_types.h +++ b/modules/etc/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef ETC_REGISTER_TYPES_H +#define ETC_REGISTER_TYPES_H + void register_etc_types(); void unregister_etc_types(); + +#endif // ETC_REGISTER_TYPES_H diff --git a/modules/etc/texture_loader_pkm.cpp b/modules/etc/texture_loader_pkm.cpp index ad0cc91c96..c40e9612a8 100644 --- a/modules/etc/texture_loader_pkm.cpp +++ b/modules/etc/texture_loader_pkm.cpp @@ -42,19 +42,21 @@ struct ETC1Header { uint16_t origHeight; }; -RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - - if (r_error) +RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_CANT_OPEN; + } Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - if (!f) + if (!f) { return RES(); + } FileAccessRef fref(f); - if (r_error) + if (r_error) { *r_error = ERR_FILE_CORRUPT; + } ERR_FAIL_COND_V_MSG(err != OK, RES(), "Unable to open PKM texture file '" + p_path + "'."); @@ -87,8 +89,9 @@ RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path, Ref<ImageTexture> texture = memnew(ImageTexture); texture->create_from_image(img); - if (r_error) + if (r_error) { *r_error = OK; + } f->close(); memdelete(f); @@ -96,18 +99,16 @@ RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path, } void ResourceFormatPKM::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("pkm"); } bool ResourceFormatPKM::handles_type(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "Texture2D"); } String ResourceFormatPKM::get_resource_type(const String &p_path) const { - - if (p_path.get_extension().to_lower() == "pkm") + if (p_path.get_extension().to_lower() == "pkm") { return "ImageTexture"; + } return ""; } diff --git a/modules/etc/texture_loader_pkm.h b/modules/etc/texture_loader_pkm.h index d6011993e3..6507e0bdec 100644 --- a/modules/etc/texture_loader_pkm.h +++ b/modules/etc/texture_loader_pkm.h @@ -36,7 +36,7 @@ class ResourceFormatPKM : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index 7b66aa1c76..bfc1658bb4 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -1,14 +1,12 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') - -from compat import isbasestring +Import("env") +Import("env_modules") env_freetype = env_modules.Clone() # Thirdparty source files -if env['builtin_freetype']: +if env["builtin_freetype"]: thirdparty_dir = "#thirdparty/freetype/" thirdparty_sources = [ "src/autofit/autofit.c", @@ -55,31 +53,31 @@ if env['builtin_freetype']: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - if env['platform'] == 'uwp': + if env["platform"] == "uwp": # Include header for UWP to fix build issues - env_freetype.Append(CCFLAGS=['/FI', '"modules/freetype/uwpdef.h"']) + env_freetype.Append(CCFLAGS=["/FI", '"modules/freetype/uwpdef.h"']) # Globally too, as freetype is used in scene (see bottom) - env.Append(CCFLAGS=['/FI', '"modules/freetype/uwpdef.h"']) + env.Append(CCFLAGS=["/FI", '"modules/freetype/uwpdef.h"']) env_freetype.Prepend(CPPPATH=[thirdparty_dir + "/include"]) # Also needed in main env for scene/ env.Prepend(CPPPATH=[thirdparty_dir + "/include"]) - env_freetype.Append(CPPDEFINES=['FT2_BUILD_LIBRARY', 'FT_CONFIG_OPTION_USE_PNG']) - if (env['target'] == 'debug'): - env_freetype.Append(CPPDEFINES=['ZLIB_DEBUG']) + env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG"]) + if env["target"] == "debug": + env_freetype.Append(CPPDEFINES=["ZLIB_DEBUG"]) # Also requires libpng headers - if env['builtin_libpng']: + if env["builtin_libpng"]: env_freetype.Prepend(CPPPATH=["#thirdparty/libpng"]) - sfnt = thirdparty_dir + 'src/sfnt/sfnt.c' + sfnt = thirdparty_dir + "src/sfnt/sfnt.c" # Must be done after all CPPDEFINES are being set so we can copy them. - if env['platform'] == 'javascript': + if env["platform"] == "javascript": # Forcibly undefine this macro so SIMD is not used in this file, # since currently unsupported in WASM tmp_env = env_freetype.Clone() - tmp_env.Append(CPPFLAGS=['-U__OPTIMIZE__']) + tmp_env.Append(CPPFLAGS=["-U__OPTIMIZE__"]) sfnt = tmp_env.Object(sfnt) thirdparty_sources += [sfnt] @@ -93,7 +91,7 @@ if env['builtin_freetype']: # and then plain strings for system library. We insert between the two. inserted = False for idx, linklib in enumerate(env["LIBS"]): - if isbasestring(linklib): # first system lib such as "X11", otherwise SCons lib object + if isinstance(linklib, (str, bytes)): # first system lib such as "X11", otherwise SCons lib object env["LIBS"].insert(idx, lib) inserted = True break diff --git a/modules/freetype/config.py b/modules/freetype/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/freetype/config.py +++ b/modules/freetype/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/freetype/register_types.h b/modules/freetype/register_types.h index 336969d079..aa8088d2e8 100644 --- a/modules/freetype/register_types.h +++ b/modules/freetype/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef FREETYPE_REGISTER_TYPES_H +#define FREETYPE_REGISTER_TYPES_H + void register_freetype_types(); void unregister_freetype_types(); + +#endif // FREETYPE_REGISTER_TYPES_H diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index a18c75fa27..cab05549d2 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_gdnative = env_modules.Clone() env_gdnative.add_source_files(env.modules_sources, "gdnative.cpp") @@ -12,12 +12,12 @@ env_gdnative.add_source_files(env.modules_sources, "nativescript/*.cpp") env_gdnative.add_source_files(env.modules_sources, "gdnative_library_singleton_editor.cpp") env_gdnative.add_source_files(env.modules_sources, "gdnative_library_editor_plugin.cpp") -env_gdnative.Prepend(CPPPATH=['#modules/gdnative/include/']) +env_gdnative.Prepend(CPPPATH=["#modules/gdnative/include/"]) -Export('env_gdnative') +Export("env_gdnative") SConscript("net/SCsub") -SConscript("arvr/SCsub") +SConscript("xr/SCsub") SConscript("pluginscript/SCsub") SConscript("videodecoder/SCsub") @@ -25,8 +25,11 @@ SConscript("videodecoder/SCsub") from platform_methods import run_in_subprocess import gdnative_builders -_, gensource = env_gdnative.CommandNoCache(['include/gdnative_api_struct.gen.h', 'gdnative_api_struct.gen.cpp'], - 'gdnative_api.json', run_in_subprocess(gdnative_builders.build_gdnative_api_struct)) +_, gensource = env_gdnative.CommandNoCache( + ["include/gdnative_api_struct.gen.h", "gdnative_api_struct.gen.cpp"], + "gdnative_api.json", + run_in_subprocess(gdnative_builders.build_gdnative_api_struct), +) env_gdnative.add_source_files(env.modules_sources, [gensource]) env.use_ptrcall = True diff --git a/modules/gdnative/android/android_gdn.cpp b/modules/gdnative/android/android_gdn.cpp index 6e0358342f..bc39be1813 100644 --- a/modules/gdnative/android/android_gdn.cpp +++ b/modules/gdnative/android/android_gdn.cpp @@ -50,7 +50,7 @@ JNIEnv *GDAPI godot_android_get_env() { #ifdef __ANDROID__ return ThreadAndroid::get_env(); #else - return NULL; + return nullptr; #endif } @@ -59,7 +59,7 @@ jobject GDAPI godot_android_get_activity() { OS_Android *os_android = (OS_Android *)OS::get_singleton(); return os_android->get_godot_java()->get_activity(); #else - return NULL; + return nullptr; #endif } @@ -68,7 +68,7 @@ jobject GDAPI godot_android_get_surface() { OS_Android *os_android = (OS_Android *)OS::get_singleton(); return os_android->get_godot_java()->get_surface(); #else - return NULL; + return nullptr; #endif } diff --git a/modules/gdnative/arvr/SCsub b/modules/gdnative/arvr/SCsub deleted file mode 100644 index 20eaa99592..0000000000 --- a/modules/gdnative/arvr/SCsub +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python - -Import('env') -Import('env_gdnative') - -env_gdnative.add_source_files(env.modules_sources, '*.cpp') diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp deleted file mode 100644 index a033c2b7f9..0000000000 --- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/*************************************************************************/ -/* arvr_interface_gdnative.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "arvr_interface_gdnative.h" -#include "main/input_default.h" -#include "servers/arvr/arvr_positional_tracker.h" -#include "servers/visual/visual_server_globals.h" - -void ARVRInterfaceGDNative::_bind_methods() { - ADD_PROPERTY_DEFAULT("interface_is_initialized", false); - ADD_PROPERTY_DEFAULT("ar_is_anchor_detection_enabled", false); -} - -ARVRInterfaceGDNative::ARVRInterfaceGDNative() { - print_verbose("Construct gdnative interface\n"); - - // we won't have our data pointer until our library gets set - data = NULL; - - interface = NULL; -} - -ARVRInterfaceGDNative::~ARVRInterfaceGDNative() { - print_verbose("Destruct gdnative interface\n"); - - if (interface != NULL && is_initialized()) { - uninitialize(); - }; - - // cleanup after ourselves - cleanup(); -} - -void ARVRInterfaceGDNative::cleanup() { - if (interface != NULL) { - interface->destructor(data); - data = NULL; - interface = NULL; - } -} - -void ARVRInterfaceGDNative::set_interface(const godot_arvr_interface_gdnative *p_interface) { - // this should only be called once, just being paranoid.. - if (interface) { - cleanup(); - } - - // bind to our interface - interface = p_interface; - - // Now we do our constructing... - data = interface->constructor((godot_object *)this); -} - -StringName ARVRInterfaceGDNative::get_name() const { - - ERR_FAIL_COND_V(interface == NULL, StringName()); - - godot_string result = interface->get_name(data); - - StringName name = *(String *)&result; - - godot_string_destroy(&result); - - return name; -} - -int ARVRInterfaceGDNative::get_capabilities() const { - int capabilities; - - ERR_FAIL_COND_V(interface == NULL, 0); // 0 = None - - capabilities = interface->get_capabilities(data); - - return capabilities; -} - -bool ARVRInterfaceGDNative::get_anchor_detection_is_enabled() const { - - ERR_FAIL_COND_V(interface == NULL, false); - - return interface->get_anchor_detection_is_enabled(data); -} - -void ARVRInterfaceGDNative::set_anchor_detection_is_enabled(bool p_enable) { - - ERR_FAIL_COND(interface == NULL); - - interface->set_anchor_detection_is_enabled(data, p_enable); -} - -int ARVRInterfaceGDNative::get_camera_feed_id() { - - ERR_FAIL_COND_V(interface == NULL, 0); - - if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 1))) { - return (unsigned int)interface->get_camera_feed_id(data); - } else { - return 0; - } -} - -bool ARVRInterfaceGDNative::is_stereo() { - bool stereo; - - ERR_FAIL_COND_V(interface == NULL, false); - - stereo = interface->is_stereo(data); - - return stereo; -} - -bool ARVRInterfaceGDNative::is_initialized() const { - - ERR_FAIL_COND_V(interface == NULL, false); - - return interface->is_initialized(data); -} - -bool ARVRInterfaceGDNative::initialize() { - ERR_FAIL_COND_V(interface == NULL, false); - - bool initialized = interface->initialize(data); - - if (initialized) { - // if we successfully initialize our interface and we don't have a primary interface yet, this becomes our primary interface - - ARVRServer *arvr_server = ARVRServer::get_singleton(); - if ((arvr_server != NULL) && (arvr_server->get_primary_interface() == NULL)) { - arvr_server->set_primary_interface(this); - }; - }; - - return initialized; -} - -void ARVRInterfaceGDNative::uninitialize() { - ERR_FAIL_COND(interface == NULL); - - 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); - } - - interface->uninitialize(data); -} - -Size2 ARVRInterfaceGDNative::get_render_targetsize() { - - ERR_FAIL_COND_V(interface == NULL, Size2()); - - godot_vector2 result = interface->get_render_targetsize(data); - Vector2 *vec = (Vector2 *)&result; - - return *vec; -} - -Transform ARVRInterfaceGDNative::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) { - Transform *ret; - - ERR_FAIL_COND_V(interface == NULL, Transform()); - - godot_transform t = interface->get_transform_for_eye(data, (int)p_eye, (godot_transform *)&p_cam_transform); - - ret = (Transform *)&t; - - return *ret; -} - -CameraMatrix ARVRInterfaceGDNative::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { - CameraMatrix cm; - - ERR_FAIL_COND_V(interface == NULL, CameraMatrix()); - - interface->fill_projection_for_eye(data, (godot_real *)cm.matrix, (godot_int)p_eye, p_aspect, p_z_near, p_z_far); - - return cm; -} - -unsigned int ARVRInterfaceGDNative::get_external_texture_for_eye(ARVRInterface::Eyes p_eye) { - - ERR_FAIL_COND_V(interface == NULL, 0); - - if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 1))) { - return (unsigned int)interface->get_external_texture_for_eye(data, (godot_int)p_eye); - } else { - return 0; - } -} - -void ARVRInterfaceGDNative::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { - - ERR_FAIL_COND(interface == NULL); - - interface->commit_for_eye(data, (godot_int)p_eye, (godot_rid *)&p_render_target, (godot_rect2 *)&p_screen_rect); -} - -void ARVRInterfaceGDNative::process() { - ERR_FAIL_COND(interface == NULL); - - interface->process(data); -} - -void ARVRInterfaceGDNative::notification(int p_what) { - ERR_FAIL_COND(interface == NULL); - - // this is only available in interfaces that implement 1.1 or later - if ((interface->version.major > 1) || ((interface->version.major == 1) && (interface->version.minor > 0))) { - interface->notification(data, p_what); - } -} - -///////////////////////////////////////////////////////////////////////////////////// -// some helper callbacks - -extern "C" { - -void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface) { - // If our major version is 0 or bigger then 10, we're likely looking at our constructor pointer from an older plugin - ERR_FAIL_COND_MSG((p_interface->version.major == 0) || (p_interface->version.major > 10), "GDNative ARVR interfaces build for Godot 3.0 are not supported."); - - Ref<ARVRInterfaceGDNative> new_interface; - new_interface.instance(); - new_interface->set_interface((const godot_arvr_interface_gdnative *)p_interface); - ARVRServer::get_singleton()->add_interface(new_interface); -} - -godot_real GDAPI godot_arvr_get_worldscale() { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, 1.0); - - return arvr_server->get_world_scale(); -} - -godot_transform GDAPI godot_arvr_get_reference_frame() { - godot_transform reference_frame; - Transform *reference_frame_ptr = (Transform *)&reference_frame; - - ARVRServer *arvr_server = ARVRServer::get_singleton(); - if (arvr_server != NULL) { - *reference_frame_ptr = arvr_server->get_reference_frame(); - } else { - godot_transform_new_identity(&reference_frame); - } - - return reference_frame; -} - -void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect) { - // blits out our texture as is, handy for preview display of one of the eyes that is already rendered with lens distortion on an external HMD - ARVRInterface::Eyes eye = (ARVRInterface::Eyes)p_eye; -#if 0 - RID *render_target = (RID *)p_render_target; -#endif - Rect2 screen_rect = *(Rect2 *)p_rect; - - if (eye == ARVRInterface::EYE_LEFT) { - screen_rect.size.x /= 2.0; - } else if (p_eye == ARVRInterface::EYE_RIGHT) { - screen_rect.size.x /= 2.0; - screen_rect.position.x += screen_rect.size.x; - } -#ifndef _MSC_VER -#warning this needs to be redone -#endif -#if 0 - VSG::rasterizer->blit_render_target_to_screen(*render_target, screen_rect, 0); -#endif -} - -godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target) { - // In order to send off our textures to display on our hardware we need the opengl texture ID instead of the render target RID - // This is a handy function to expose that. -#if 0 - RID *render_target = (RID *)p_render_target; - - RID eye_texture = VSG::storage->render_target_get_texture(*render_target); -#endif - -#ifndef _MSC_VER -#warning need to obtain this ID again -#endif - uint32_t texid = 0; //VS::get_singleton()->texture_get_texid(eye_texture); - - return texid; -} - -godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position) { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, 0); - - InputDefault *input = (InputDefault *)Input::get_singleton(); - ERR_FAIL_NULL_V(input, 0); - - ARVRPositionalTracker *new_tracker = memnew(ARVRPositionalTracker); - new_tracker->set_name(p_device_name); - new_tracker->set_type(ARVRServer::TRACKER_CONTROLLER); - if (p_hand == 1) { - new_tracker->set_hand(ARVRPositionalTracker::TRACKER_LEFT_HAND); - } else if (p_hand == 2) { - new_tracker->set_hand(ARVRPositionalTracker::TRACKER_RIGHT_HAND); - } - - // also register as joystick... - int joyid = input->get_unused_joy_id(); - if (joyid != -1) { - new_tracker->set_joy_id(joyid); - input->joy_connection_changed(joyid, true, p_device_name, ""); - } - - if (p_tracks_orientation) { - Basis orientation; - new_tracker->set_orientation(orientation); - } - if (p_tracks_position) { - Vector3 position; - new_tracker->set_position(position); - } - - // add our tracker to our server and remember its pointer - arvr_server->add_tracker(new_tracker); - - // note, this ID is only unique within controllers! - return new_tracker->get_tracker_id(); -} - -void GDAPI godot_arvr_remove_controller(godot_int p_controller_id) { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); - - InputDefault *input = (InputDefault *)Input::get_singleton(); - ERR_FAIL_NULL(input); - - ARVRPositionalTracker *remove_tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id); - if (remove_tracker != NULL) { - // unset our joystick if applicable - int joyid = remove_tracker->get_joy_id(); - if (joyid != -1) { - input->joy_connection_changed(joyid, false, "", ""); - remove_tracker->set_joy_id(-1); - } - - // remove our tracker from our server - arvr_server->remove_tracker(remove_tracker); - memdelete(remove_tracker); - } -} - -void GDAPI godot_arvr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); - - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id); - if (tracker != NULL) { - Transform *transform = (Transform *)p_transform; - if (p_tracks_orientation) { - tracker->set_orientation(transform->basis); - } - if (p_tracks_position) { - tracker->set_rw_position(transform->origin); - } - } -} - -void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed) { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); - - InputDefault *input = (InputDefault *)Input::get_singleton(); - ERR_FAIL_NULL(input); - - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id); - if (tracker != NULL) { - int joyid = tracker->get_joy_id(); - if (joyid != -1) { - input->joy_button(joyid, p_button, p_is_pressed); - } - } -} - -void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative) { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL(arvr_server); - - InputDefault *input = (InputDefault *)Input::get_singleton(); - ERR_FAIL_NULL(input); - - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id); - if (tracker != NULL) { - int joyid = tracker->get_joy_id(); - if (joyid != -1) { - InputDefault::JoyAxis jx; - jx.min = p_can_be_negative ? -1 : 0; - jx.value = p_value; - input->joy_axis(joyid, p_axis, jx); - } - } -} - -godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id) { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, 0.0); - - ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id); - if (tracker != NULL) { - return tracker->get_rumble(); - } - - return 0.0; -} -} diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py index b9e5afcdf3..4b997e4bfe 100644 --- a/modules/gdnative/config.py +++ b/modules/gdnative/config.py @@ -1,13 +1,15 @@ def can_build(env, platform): return True + def configure(env): env.use_ptrcall = True + def get_doc_classes(): return [ "@NativeScript", - "ARVRInterfaceGDNative", + "XRInterfaceGDNative", "GDNative", "GDNativeLibrary", "MultiplayerPeerGDNative", @@ -20,5 +22,6 @@ def get_doc_classes(): "WebRTCDataChannelGDNative", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml deleted file mode 100644 index e8405b64a3..0000000000 --- a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" version="4.0"> - <brief_description> - GDNative wrapper for an ARVR interface. - </brief_description> - <description> - This is a wrapper class for GDNative implementations of the ARVR interface. To use a GDNative ARVR interface, simply instantiate this object and set your GDNative library containing the ARVR interface implementation. - </description> - <tutorials> - </tutorials> - <methods> - </methods> - <constants> - </constants> -</class> diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml index 601e132d42..1aab864102 100644 --- a/modules/gdnative/doc_classes/GDNativeLibrary.xml +++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml @@ -4,7 +4,7 @@ An external library containing functions or script classes to use in Godot. </brief_description> <description> - A GDNative library can implement [NativeScript]s, global functions to call with the [GDNative] class, or low-level engine extensions through interfaces such as [ARVRInterfaceGDNative]. The library must be compiled for each platform and architecture that the project will run on. + A GDNative library can implement [NativeScript]s, global functions to call with the [GDNative] class, or low-level engine extensions through interfaces such as [XRInterfaceGDNative]. The library must be compiled for each platform and architecture that the project will run on. </description> <tutorials> <link>https://docs.godotengine.org/en/latest/tutorials/plugins/gdnative/gdnative-c-example.html</link> diff --git a/modules/gdnative/doc_classes/XRInterfaceGDNative.xml b/modules/gdnative/doc_classes/XRInterfaceGDNative.xml new file mode 100644 index 0000000000..13de815793 --- /dev/null +++ b/modules/gdnative/doc_classes/XRInterfaceGDNative.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="XRInterfaceGDNative" inherits="XRInterface" version="4.0"> + <brief_description> + GDNative wrapper for an XR interface. + </brief_description> + <description> + This is a wrapper class for GDNative implementations of the XR interface. To use a GDNative XR interface, simply instantiate this object and set your GDNative library containing the XR interface implementation. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 0457a42f30..3d747ba41e 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -63,7 +63,6 @@ GDNativeLibrary::~GDNativeLibrary() { } bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_property) { - String name = p_name; if (name.begins_with("entry/")) { @@ -115,8 +114,9 @@ void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { // set entries List<String> entry_key_list; - if (config_file->has_section("entry")) + if (config_file->has_section("entry")) { config_file->get_section_keys("entry", &entry_key_list); + } for (List<String>::Element *E = entry_key_list.front(); E; E = E->next()) { String key = E->get(); @@ -132,8 +132,9 @@ void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { // set dependencies List<String> dependency_key_list; - if (config_file->has_section("dependencies")) + if (config_file->has_section("dependencies")) { config_file->get_section_keys("dependencies", &dependency_key_list); + } for (List<String>::Element *E = dependency_key_list.front(); E; E = E->next()) { String key = E->get(); @@ -148,7 +149,6 @@ void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { } void GDNativeLibrary::set_config_file(Ref<ConfigFile> p_config_file) { - set_singleton(p_config_file->get_value("general", "singleton", default_singleton)); set_load_once(p_config_file->get_value("general", "load_once", default_load_once)); set_symbol_prefix(p_config_file->get_value("general", "symbol_prefix", default_symbol_prefix)); @@ -156,11 +156,11 @@ void GDNativeLibrary::set_config_file(Ref<ConfigFile> p_config_file) { String entry_lib_path; { - List<String> entry_keys; - if (p_config_file->has_section("entry")) + if (p_config_file->has_section("entry")) { p_config_file->get_section_keys("entry", &entry_keys); + } for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) { String key = E->get(); @@ -188,11 +188,11 @@ void GDNativeLibrary::set_config_file(Ref<ConfigFile> p_config_file) { Vector<String> dependency_paths; { - List<String> dependency_keys; - if (p_config_file->has_section("dependencies")) + if (p_config_file->has_section("dependencies")) { p_config_file->get_section_keys("dependencies", &dependency_keys); + } for (List<String>::Element *E = dependency_keys.front(); E; E = E->next()) { String key = E->get(); @@ -248,7 +248,7 @@ void GDNativeLibrary::_bind_methods() { } GDNative::GDNative() { - native_handle = NULL; + native_handle = nullptr; initialized = false; } @@ -338,7 +338,7 @@ bool GDNative::initialize() { if (err || !library_init) { OS::get_singleton()->close_dynamic_library(native_handle); - native_handle = NULL; + native_handle = nullptr; ERR_PRINT("Failed to obtain " + library->get_symbol_prefix() + "gdnative_init symbol"); return false; } @@ -383,7 +383,6 @@ bool GDNative::initialize() { } bool GDNative::terminate() { - if (!initialized) { ERR_PRINT("No valid library handle, can't terminate GDNative object"); return false; @@ -408,7 +407,7 @@ bool GDNative::terminate() { Error error = get_symbol(library->get_symbol_prefix() + terminate_symbol, library_terminate); if (error || !library_terminate) { OS::get_singleton()->close_dynamic_library(native_handle); - native_handle = NULL; + native_handle = nullptr; initialized = false; return true; } @@ -426,7 +425,7 @@ bool GDNative::terminate() { // GDNativeScriptLanguage::get_singleton()->initialized_libraries.erase(p_native_lib->path); OS::get_singleton()->close_dynamic_library(native_handle); - native_handle = NULL; + native_handle = nullptr; return true; } @@ -452,7 +451,6 @@ Vector<StringName> GDNativeCallRegistry::get_native_call_types() { } Variant GDNative::call_native(StringName p_native_call_type, StringName p_procedure_name, Array p_arguments) { - Map<StringName, native_call_cb>::Element *E = GDNativeCallRegistry::singleton->native_calls.find(p_native_call_type); if (!E) { ERR_PRINT((String("No handler for native call type \"" + p_native_call_type) + "\" found").utf8().get_data()); @@ -466,7 +464,7 @@ Variant GDNative::call_native(StringName p_native_call_type, StringName p_proced p_procedure_name, procedure_handle); - if (err != OK || procedure_handle == NULL) { + if (err != OK || procedure_handle == nullptr) { return Variant(); } @@ -478,7 +476,6 @@ Variant GDNative::call_native(StringName p_native_call_type, StringName p_proced } Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional) const { - if (!initialized) { ERR_PRINT("No valid library handle, can't get symbol from GDNative object"); return ERR_CANT_OPEN; @@ -493,7 +490,7 @@ Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_ return result; } -RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { +RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { Ref<GDNativeLibrary> lib; lib.instance(); @@ -520,13 +517,13 @@ bool GDNativeLibraryResourceLoader::handles_type(const String &p_type) const { String GDNativeLibraryResourceLoader::get_resource_type(const String &p_path) const { String el = p_path.get_extension().to_lower(); - if (el == "gdnlib") + if (el == "gdnlib") { return "GDNativeLibrary"; + } return ""; } Error GDNativeLibraryResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref<GDNativeLibrary> lib = p_resource; if (lib.is_null()) { @@ -544,11 +541,11 @@ Error GDNativeLibraryResourceSaver::save(const String &p_path, const RES &p_reso } bool GDNativeLibraryResourceSaver::recognize(const RES &p_resource) const { - return Object::cast_to<GDNativeLibrary>(*p_resource) != NULL; + return Object::cast_to<GDNativeLibrary>(*p_resource) != nullptr; } void GDNativeLibraryResourceSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (Object::cast_to<GDNativeLibrary>(*p_resource) != NULL) { + if (Object::cast_to<GDNativeLibrary>(*p_resource) != nullptr) { p_extensions->push_back("gdnlib"); } } diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index 9ef9c706d1..6d26c2141d 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -166,7 +166,7 @@ public: class GDNativeLibraryResourceLoader : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/gdnative/gdnative/aabb.cpp b/modules/gdnative/gdnative/aabb.cpp index 246e5d4e8d..7f22c7dfe3 100644 --- a/modules/gdnative/gdnative/aabb.cpp +++ b/modules/gdnative/gdnative/aabb.cpp @@ -37,6 +37,8 @@ extern "C" { #endif +static_assert(sizeof(godot_aabb) == sizeof(AABB), "AABB size mismatch"); + void GDAPI godot_aabb_new(godot_aabb *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size) { const Vector3 *pos = (const Vector3 *)p_pos; const Vector3 *size = (const Vector3 *)p_size; diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp index 0c764ab8fd..59953f5182 100644 --- a/modules/gdnative/gdnative/array.cpp +++ b/modules/gdnative/gdnative/array.cpp @@ -41,6 +41,8 @@ extern "C" { #endif +static_assert(sizeof(godot_array) == sizeof(Array), "Array size mismatch"); + void GDAPI godot_array_new(godot_array *r_dest) { Array *dest = (Array *)r_dest; memnew_placement(dest, Array); @@ -100,9 +102,33 @@ void GDAPI godot_array_new_packed_string_array(godot_array *r_dest, const godot_ } } -void GDAPI godot_array_new_packed_real_array(godot_array *r_dest, const godot_packed_real_array *p_pra) { +void GDAPI godot_array_new_packed_float32_array(godot_array *r_dest, const godot_packed_float32_array *p_pra) { + Array *dest = (Array *)r_dest; + Vector<float> *pca = (Vector<float> *)p_pra; + memnew_placement(dest, Array); + dest->resize(pca->size()); + + for (int i = 0; i < dest->size(); i++) { + Variant v = pca->operator[](i); + dest->operator[](i) = v; + } +} + +void GDAPI godot_array_new_packed_float64_array(godot_array *r_dest, const godot_packed_float64_array *p_pra) { + Array *dest = (Array *)r_dest; + Vector<double> *pca = (Vector<double> *)p_pra; + memnew_placement(dest, Array); + dest->resize(pca->size()); + + for (int i = 0; i < dest->size(); i++) { + Variant v = pca->operator[](i); + dest->operator[](i) = v; + } +} + +void GDAPI godot_array_new_packed_int32_array(godot_array *r_dest, const godot_packed_int32_array *p_pia) { Array *dest = (Array *)r_dest; - Vector<godot_real> *pca = (Vector<godot_real> *)p_pra; + Vector<int32_t> *pca = (Vector<int32_t> *)p_pia; memnew_placement(dest, Array); dest->resize(pca->size()); @@ -112,9 +138,9 @@ void GDAPI godot_array_new_packed_real_array(godot_array *r_dest, const godot_pa } } -void GDAPI godot_array_new_packed_int_array(godot_array *r_dest, const godot_packed_int_array *p_pia) { +void GDAPI godot_array_new_packed_int64_array(godot_array *r_dest, const godot_packed_int64_array *p_pia) { Array *dest = (Array *)r_dest; - Vector<godot_int> *pca = (Vector<godot_int> *)p_pia; + Vector<int64_t> *pca = (Vector<int64_t> *)p_pia; memnew_placement(dest, Array); dest->resize(pca->size()); diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp index 4f489287b9..990fd3795d 100644 --- a/modules/gdnative/gdnative/basis.cpp +++ b/modules/gdnative/gdnative/basis.cpp @@ -37,6 +37,8 @@ extern "C" { #endif +static_assert(sizeof(godot_basis) == sizeof(Basis), "Basis size mismatch"); + void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis) { const Vector3 *x_axis = (const Vector3 *)p_x_axis; const Vector3 *y_axis = (const Vector3 *)p_y_axis; diff --git a/modules/gdnative/gdnative/callable.cpp b/modules/gdnative/gdnative/callable.cpp new file mode 100644 index 0000000000..868b324227 --- /dev/null +++ b/modules/gdnative/gdnative/callable.cpp @@ -0,0 +1,252 @@ +/*************************************************************************/ +/* callable.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "gdnative/callable.h" + +#include "core/callable.h" +#include "core/resource.h" +#include "core/variant.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static_assert(sizeof(godot_callable) == sizeof(Callable), "Callable size mismatch"); +static_assert(sizeof(godot_signal) == sizeof(Signal), "Signal size mismatch"); + +// Callable + +void GDAPI godot_callable_new_with_object(godot_callable *r_dest, const godot_object *p_object, const godot_string_name *p_method) { + Callable *dest = (Callable *)r_dest; + const Object *object = (const Object *)p_object; + const StringName *method = (const StringName *)p_method; + memnew_placement(dest, Callable(object, *method)); +} + +void GDAPI godot_callable_new_with_object_id(godot_callable *r_dest, uint64_t p_objectid, const godot_string_name *p_method) { + Callable *dest = (Callable *)r_dest; + const StringName *method = (const StringName *)p_method; + memnew_placement(dest, Callable(ObjectID(p_objectid), *method)); +} + +void GDAPI godot_callable_new_copy(godot_callable *r_dest, const godot_callable *p_src) { + Callable *dest = (Callable *)r_dest; + const Callable *src = (const Callable *)p_src; + memnew_placement(dest, Callable(*src)); +} + +void GDAPI godot_callable_destroy(godot_callable *p_self) { + Callable *self = (Callable *)p_self; + self->~Callable(); +} + +godot_int GDAPI godot_callable_call(const godot_callable *p_self, const godot_variant **p_arguments, godot_int p_argcount, godot_variant *r_return_value) { + const Callable *self = (const Callable *)p_self; + const Variant **arguments = (const Variant **)p_arguments; + Variant *return_value = (Variant *)r_return_value; + Variant ret; + Callable::CallError err; + self->call(arguments, p_argcount, ret, err); + if (return_value) + (*return_value) = ret; + return (godot_int)err.error; +} + +void GDAPI godot_callable_call_deferred(const godot_callable *p_self, const godot_variant **p_arguments, godot_int p_argcount) { + const Callable *self = (const Callable *)p_self; + const Variant **arguments = (const Variant **)p_arguments; + self->call_deferred(arguments, p_argcount); +} + +godot_bool GDAPI godot_callable_is_null(const godot_callable *p_self) { + const Callable *self = (const Callable *)p_self; + return self->is_null(); +} + +godot_bool GDAPI godot_callable_is_custom(const godot_callable *p_self) { + const Callable *self = (const Callable *)p_self; + return self->is_custom(); +} + +godot_bool GDAPI godot_callable_is_standard(const godot_callable *p_self) { + const Callable *self = (const Callable *)p_self; + return self->is_standard(); +} + +godot_object GDAPI *godot_callable_get_object(const godot_callable *p_self) { + const Callable *self = (const Callable *)p_self; + return (godot_object *)self->get_object(); +} + +uint64_t GDAPI godot_callable_get_object_id(const godot_callable *p_self) { + const Callable *self = (const Callable *)p_self; + return (uint64_t)self->get_object_id(); +} + +godot_string_name GDAPI godot_callable_get_method(const godot_callable *p_self) { + godot_string_name raw_dest; + const Callable *self = (const Callable *)p_self; + StringName *dest = (StringName *)&raw_dest; + memnew_placement(dest, StringName(self->get_method())); + return raw_dest; +} + +uint32_t GDAPI godot_callable_hash(const godot_callable *p_self) { + const Callable *self = (const Callable *)p_self; + return self->hash(); +} + +godot_string GDAPI godot_callable_as_string(const godot_callable *p_self) { + godot_string ret; + const Callable *self = (const Callable *)p_self; + memnew_placement(&ret, String(*self)); + return ret; +} + +godot_bool GDAPI godot_callable_operator_equal(const godot_callable *p_self, const godot_callable *p_other) { + const Callable *self = (const Callable *)p_self; + const Callable *other = (const Callable *)p_other; + return *self == *other; +} + +godot_bool GDAPI godot_callable_operator_less(const godot_callable *p_self, const godot_callable *p_other) { + const Callable *self = (const Callable *)p_self; + const Callable *other = (const Callable *)p_other; + return *self < *other; +} + +// Signal + +void GDAPI godot_signal_new_with_object(godot_signal *r_dest, const godot_object *p_object, const godot_string_name *p_name) { + Signal *dest = (Signal *)r_dest; + const Object *object = (const Object *)p_object; + const StringName *name = (const StringName *)p_name; + memnew_placement(dest, Signal(object, *name)); +} + +void GDAPI godot_signal_new_with_object_id(godot_signal *r_dest, uint64_t p_objectid, const godot_string_name *p_name) { + Signal *dest = (Signal *)r_dest; + const StringName *name = (const StringName *)p_name; + memnew_placement(dest, Signal(ObjectID(p_objectid), *name)); +} + +void GDAPI godot_signal_new_copy(godot_signal *r_dest, const godot_signal *p_src) { + Signal *dest = (Signal *)r_dest; + const Signal *src = (const Signal *)p_src; + memnew_placement(dest, Signal(*src)); +} + +void GDAPI godot_signal_destroy(godot_signal *p_self) { + Signal *self = (Signal *)p_self; + self->~Signal(); +} + +godot_int GDAPI godot_signal_emit(const godot_signal *p_self, const godot_variant **p_arguments, godot_int p_argcount) { + const Signal *self = (const Signal *)p_self; + const Variant **arguments = (const Variant **)p_arguments; + return (godot_int)self->emit(arguments, p_argcount); +} + +godot_int GDAPI godot_signal_connect(godot_signal *p_self, const godot_callable *p_callable, const godot_array *p_binds, uint32_t p_flags) { + Signal *self = (Signal *)p_self; + const Callable *callable = (const Callable *)p_callable; + const Array *binds_ar = (const Array *)p_binds; + Vector<Variant> binds; + for (int i = 0; i < binds_ar->size(); i++) { + binds.push_back(binds_ar->get(i)); + } + return (godot_int)self->connect(*callable, binds, p_flags); +} + +void GDAPI godot_signal_disconnect(godot_signal *p_self, const godot_callable *p_callable) { + Signal *self = (Signal *)p_self; + const Callable *callable = (const Callable *)p_callable; + self->disconnect(*callable); +} + +godot_bool GDAPI godot_signal_is_null(const godot_signal *p_self) { + const Signal *self = (const Signal *)p_self; + return self->is_null(); +} + +godot_bool GDAPI godot_signal_is_connected(const godot_signal *p_self, const godot_callable *p_callable) { + const Signal *self = (const Signal *)p_self; + const Callable *callable = (const Callable *)p_callable; + return self->is_connected(*callable); +} + +godot_array GDAPI godot_signal_get_connections(const godot_signal *p_self) { + godot_array raw_dest; + const Signal *self = (const Signal *)p_self; + Array *dest = (Array *)&raw_dest; + memnew_placement(dest, Array(self->get_connections())); + return raw_dest; +} + +godot_object GDAPI *godot_signal_get_object(const godot_signal *p_self) { + const Signal *self = (const Signal *)p_self; + return (godot_object *)self->get_object(); +} + +uint64_t GDAPI godot_signal_get_object_id(const godot_signal *p_self) { + const Signal *self = (const Signal *)p_self; + return (uint64_t)self->get_object_id(); +} + +godot_string_name GDAPI godot_signal_get_name(const godot_signal *p_self) { + godot_string_name raw_dest; + const Signal *self = (const Signal *)p_self; + StringName *dest = (StringName *)&raw_dest; + memnew_placement(dest, StringName(self->get_name())); + return raw_dest; +} + +godot_string GDAPI godot_signal_as_string(const godot_signal *p_self) { + godot_string ret; + const Signal *self = (const Signal *)p_self; + memnew_placement(&ret, String(*self)); + return ret; +} + +godot_bool GDAPI godot_signal_operator_equal(const godot_signal *p_self, const godot_signal *p_other) { + const Signal *self = (const Signal *)p_self; + const Signal *other = (const Signal *)p_other; + return *self == *other; +} + +godot_bool GDAPI godot_signal_operator_less(const godot_signal *p_self, const godot_signal *p_other) { + const Signal *self = (const Signal *)p_self; + const Signal *other = (const Signal *)p_other; + return *self < *other; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/gdnative/gdnative/color.cpp b/modules/gdnative/gdnative/color.cpp index 914d5b03f4..c75e74daba 100644 --- a/modules/gdnative/gdnative/color.cpp +++ b/modules/gdnative/gdnative/color.cpp @@ -37,14 +37,14 @@ extern "C" { #endif -void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a) { +static_assert(sizeof(godot_color) == sizeof(Color), "Color size mismatch"); +void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a) { Color *dest = (Color *)r_dest; *dest = Color(p_r, p_g, p_b, p_a); } void GDAPI godot_color_new_rgb(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b) { - Color *dest = (Color *)r_dest; *dest = Color(p_r, p_g, p_b); } @@ -155,11 +155,11 @@ godot_color GDAPI godot_color_contrasted(const godot_color *p_self) { return dest; } -godot_color GDAPI godot_color_linear_interpolate(const godot_color *p_self, const godot_color *p_b, const godot_real p_t) { +godot_color GDAPI godot_color_lerp(const godot_color *p_self, const godot_color *p_b, const godot_real p_t) { godot_color dest; const Color *self = (const Color *)p_self; const Color *b = (const Color *)p_b; - *((Color *)&dest) = self->linear_interpolate(*b, p_t); + *((Color *)&dest) = self->lerp(*b, p_t); return dest; } diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp index b145b88934..a126974815 100644 --- a/modules/gdnative/gdnative/dictionary.cpp +++ b/modules/gdnative/gdnative/dictionary.cpp @@ -39,6 +39,8 @@ extern "C" { #endif +static_assert(sizeof(godot_dictionary) == sizeof(Dictionary), "Dictionary size mismatch"); + void GDAPI godot_dictionary_new(godot_dictionary *r_dest) { Dictionary *dest = (Dictionary *)r_dest; memnew_placement(dest, Dictionary); diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp index d996b006a5..e94190b07b 100644 --- a/modules/gdnative/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative/gdnative.cpp @@ -56,14 +56,12 @@ godot_object GDAPI *godot_global_get_singleton(char *p_name) { // MethodBind API godot_method_bind GDAPI *godot_method_bind_get_method(const char *p_classname, const char *p_methodname) { - MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname)); // MethodBind *mb = ClassDB::get_method("Node", "get_name"); return (godot_method_bind *)mb; } void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret) { - MethodBind *mb = (MethodBind *)p_method_bind; Object *o = (Object *)p_instance; mb->ptrcall(o, p_args, p_ret); @@ -93,9 +91,10 @@ godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, god godot_class_constructor GDAPI godot_get_class_constructor(const char *p_classname) { ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(StringName(p_classname)); - if (class_info) + if (class_info) { return (godot_class_constructor)class_info->creation_func; - return NULL; + } + return nullptr; } godot_dictionary GDAPI godot_get_global_constants() { @@ -166,21 +165,28 @@ void _gdnative_report_loading_error(const godot_object *p_library, const char *p _err_print_error("gdnative_init", library->get_current_library_path().utf8().ptr(), 0, message.utf8().ptr()); } -godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id) { +godot_object GDAPI *godot_instance_from_id(uint64_t p_instance_id) { return (godot_object *)ObjectDB::get_instance(ObjectID(p_instance_id)); } void *godot_get_class_tag(const godot_string_name *p_class) { StringName class_name = *(StringName *)p_class; ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(class_name); - return class_info ? class_info->class_ptr : NULL; + return class_info ? class_info->class_ptr : nullptr; } godot_object *godot_object_cast_to(const godot_object *p_object, void *p_class_tag) { - if (!p_object) return NULL; + if (!p_object) { + return nullptr; + } Object *o = (Object *)p_object; - return o->is_class_ptr(p_class_tag) ? (godot_object *)o : NULL; + return o->is_class_ptr(p_class_tag) ? (godot_object *)o : nullptr; +} + +uint64_t GDAPI godot_object_get_instance_id(const godot_object *p_object) { + const Object *o = (const Object *)p_object; + return (uint64_t)o->get_instance_id(); } #ifdef __cplusplus diff --git a/modules/gdnative/gdnative/node_path.cpp b/modules/gdnative/gdnative/node_path.cpp index 93f43835c8..88ed650ebe 100644 --- a/modules/gdnative/gdnative/node_path.cpp +++ b/modules/gdnative/gdnative/node_path.cpp @@ -37,6 +37,8 @@ extern "C" { #endif +static_assert(sizeof(godot_node_path) == sizeof(NodePath), "NodePath size mismatch"); + void GDAPI godot_node_path_new(godot_node_path *r_dest, const godot_string *p_from) { NodePath *dest = (NodePath *)r_dest; const String *from = (const String *)p_from; diff --git a/modules/gdnative/gdnative/pool_arrays.cpp b/modules/gdnative/gdnative/packed_arrays.cpp index 589b4d4dfe..675d66056a 100644 --- a/modules/gdnative/gdnative/pool_arrays.cpp +++ b/modules/gdnative/gdnative/packed_arrays.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pool_arrays.cpp */ +/* packed_arrays.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "gdnative/pool_arrays.h" +#include "gdnative/packed_arrays.h" #include "core/array.h" @@ -42,6 +42,16 @@ extern "C" { #endif +static_assert(sizeof(godot_packed_byte_array) == sizeof(Vector<uint8_t>), "Vector<uint8_t> size mismatch"); +static_assert(sizeof(godot_packed_int32_array) == sizeof(Vector<int32_t>), "Vector<int32_t> size mismatch"); +static_assert(sizeof(godot_packed_int64_array) == sizeof(Vector<int64_t>), "Vector<int64_t> size mismatch"); +static_assert(sizeof(godot_packed_float32_array) == sizeof(Vector<float>), "Vector<float> size mismatch"); +static_assert(sizeof(godot_packed_float64_array) == sizeof(Vector<double>), "Vector<double> size mismatch"); +static_assert(sizeof(godot_packed_string_array) == sizeof(Vector<String>), "Vector<String> size mismatch"); +static_assert(sizeof(godot_packed_vector2_array) == sizeof(Vector<Vector2>), "Vector<Vector2> size mismatch"); +static_assert(sizeof(godot_packed_vector3_array) == sizeof(Vector<Vector3>), "Vector<Vector3> size mismatch"); +static_assert(sizeof(godot_packed_color_array) == sizeof(Vector<Color>), "Vector<Color> size mismatch"); + #define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr) // byte @@ -128,23 +138,191 @@ void GDAPI godot_packed_byte_array_destroy(godot_packed_byte_array *p_self) { ((Vector<uint8_t> *)p_self)->~Vector(); } -// int +// int32 + +void GDAPI godot_packed_int32_array_new(godot_packed_int32_array *r_dest) { + Vector<int32_t> *dest = (Vector<int32_t> *)r_dest; + memnew_placement(dest, Vector<int32_t>); +} + +void GDAPI godot_packed_int32_array_new_copy(godot_packed_int32_array *r_dest, const godot_packed_int32_array *p_src) { + Vector<int32_t> *dest = (Vector<int32_t> *)r_dest; + const Vector<int32_t> *src = (const Vector<int32_t> *)p_src; + memnew_placement(dest, Vector<int32_t>(*src)); +} + +void GDAPI godot_packed_int32_array_new_with_array(godot_packed_int32_array *r_dest, const godot_array *p_a) { + Vector<int32_t> *dest = (Vector<int32_t> *)r_dest; + Array *a = (Array *)p_a; + memnew_placement(dest, Vector<int32_t>); + + dest->resize(a->size()); + for (int i = 0; i < a->size(); i++) { + dest->set(i, (*a)[i]); + } +} + +void GDAPI godot_packed_int32_array_append(godot_packed_int32_array *p_self, const int32_t p_data) { + Vector<int32_t> *self = (Vector<int32_t> *)p_self; + self->push_back(p_data); +} + +void GDAPI godot_packed_int32_array_append_array(godot_packed_int32_array *p_self, const godot_packed_int32_array *p_array) { + Vector<int32_t> *self = (Vector<int32_t> *)p_self; + Vector<int32_t> *array = (Vector<int32_t> *)p_array; + self->append_array(*array); +} + +godot_error GDAPI godot_packed_int32_array_insert(godot_packed_int32_array *p_self, const godot_int p_idx, const int32_t p_data) { + Vector<int32_t> *self = (Vector<int32_t> *)p_self; + return (godot_error)self->insert(p_idx, p_data); +} + +void GDAPI godot_packed_int32_array_invert(godot_packed_int32_array *p_self) { + Vector<int32_t> *self = (Vector<int32_t> *)p_self; + self->invert(); +} + +void GDAPI godot_packed_int32_array_push_back(godot_packed_int32_array *p_self, const int32_t p_data) { + Vector<int32_t> *self = (Vector<int32_t> *)p_self; + self->push_back(p_data); +} + +void GDAPI godot_packed_int32_array_remove(godot_packed_int32_array *p_self, const godot_int p_idx) { + Vector<int32_t> *self = (Vector<int32_t> *)p_self; + self->remove(p_idx); +} + +void GDAPI godot_packed_int32_array_resize(godot_packed_int32_array *p_self, const godot_int p_size) { + Vector<int32_t> *self = (Vector<int32_t> *)p_self; + self->resize(p_size); +} + +void GDAPI godot_packed_int32_array_set(godot_packed_int32_array *p_self, const godot_int p_idx, const int32_t p_data) { + Vector<int32_t> *self = (Vector<int32_t> *)p_self; + self->set(p_idx, p_data); +} + +int32_t GDAPI godot_packed_int32_array_get(const godot_packed_int32_array *p_self, const godot_int p_idx) { + const Vector<int32_t> *self = (const Vector<int32_t> *)p_self; + return self->get(p_idx); +} + +godot_int GDAPI godot_packed_int32_array_size(const godot_packed_int32_array *p_self) { + const Vector<int32_t> *self = (const Vector<int32_t> *)p_self; + return self->size(); +} + +godot_bool GDAPI godot_packed_int32_array_empty(const godot_packed_int32_array *p_self) { + const Vector<int32_t> *self = (const Vector<int32_t> *)p_self; + return self->empty(); +} + +void GDAPI godot_packed_int32_array_destroy(godot_packed_int32_array *p_self) { + ((Vector<int32_t> *)p_self)->~Vector(); +} + +// int64 + +void GDAPI godot_packed_int64_array_new(godot_packed_int64_array *r_dest) { + Vector<int64_t> *dest = (Vector<int64_t> *)r_dest; + memnew_placement(dest, Vector<int64_t>); +} + +void GDAPI godot_packed_int64_array_new_copy(godot_packed_int64_array *r_dest, const godot_packed_int64_array *p_src) { + Vector<int64_t> *dest = (Vector<int64_t> *)r_dest; + const Vector<int64_t> *src = (const Vector<int64_t> *)p_src; + memnew_placement(dest, Vector<int64_t>(*src)); +} + +void GDAPI godot_packed_int64_array_new_with_array(godot_packed_int64_array *r_dest, const godot_array *p_a) { + Vector<int64_t> *dest = (Vector<int64_t> *)r_dest; + Array *a = (Array *)p_a; + memnew_placement(dest, Vector<int64_t>); + + dest->resize(a->size()); + for (int i = 0; i < a->size(); i++) { + dest->set(i, (*a)[i]); + } +} + +void GDAPI godot_packed_int64_array_append(godot_packed_int64_array *p_self, const int64_t p_data) { + Vector<int64_t> *self = (Vector<int64_t> *)p_self; + self->push_back(p_data); +} + +void GDAPI godot_packed_int64_array_append_array(godot_packed_int64_array *p_self, const godot_packed_int64_array *p_array) { + Vector<int64_t> *self = (Vector<int64_t> *)p_self; + Vector<int64_t> *array = (Vector<int64_t> *)p_array; + self->append_array(*array); +} + +godot_error GDAPI godot_packed_int64_array_insert(godot_packed_int64_array *p_self, const godot_int p_idx, const int64_t p_data) { + Vector<int64_t> *self = (Vector<int64_t> *)p_self; + return (godot_error)self->insert(p_idx, p_data); +} + +void GDAPI godot_packed_int64_array_invert(godot_packed_int64_array *p_self) { + Vector<int64_t> *self = (Vector<int64_t> *)p_self; + self->invert(); +} + +void GDAPI godot_packed_int64_array_push_back(godot_packed_int64_array *p_self, const int64_t p_data) { + Vector<int64_t> *self = (Vector<int64_t> *)p_self; + self->push_back(p_data); +} + +void GDAPI godot_packed_int64_array_remove(godot_packed_int64_array *p_self, const godot_int p_idx) { + Vector<int64_t> *self = (Vector<int64_t> *)p_self; + self->remove(p_idx); +} + +void GDAPI godot_packed_int64_array_resize(godot_packed_int64_array *p_self, const godot_int p_size) { + Vector<int64_t> *self = (Vector<int64_t> *)p_self; + self->resize(p_size); +} + +void GDAPI godot_packed_int64_array_set(godot_packed_int64_array *p_self, const godot_int p_idx, const int64_t p_data) { + Vector<int64_t> *self = (Vector<int64_t> *)p_self; + self->set(p_idx, p_data); +} + +int64_t GDAPI godot_packed_int64_array_get(const godot_packed_int64_array *p_self, const godot_int p_idx) { + const Vector<int64_t> *self = (const Vector<int64_t> *)p_self; + return self->get(p_idx); +} + +godot_int GDAPI godot_packed_int64_array_size(const godot_packed_int64_array *p_self) { + const Vector<int64_t> *self = (const Vector<int64_t> *)p_self; + return self->size(); +} + +godot_bool GDAPI godot_packed_int64_array_empty(const godot_packed_int64_array *p_self) { + const Vector<int64_t> *self = (const Vector<int64_t> *)p_self; + return self->empty(); +} + +void GDAPI godot_packed_int64_array_destroy(godot_packed_int64_array *p_self) { + ((Vector<int64_t> *)p_self)->~Vector(); +} + +// float32 -void GDAPI godot_packed_int_array_new(godot_packed_int_array *r_dest) { - Vector<godot_int> *dest = (Vector<godot_int> *)r_dest; - memnew_placement(dest, Vector<godot_int>); +void GDAPI godot_packed_float32_array_new(godot_packed_float32_array *r_dest) { + Vector<float> *dest = (Vector<float> *)r_dest; + memnew_placement(dest, Vector<float>); } -void GDAPI godot_packed_int_array_new_copy(godot_packed_int_array *r_dest, const godot_packed_int_array *p_src) { - Vector<godot_int> *dest = (Vector<godot_int> *)r_dest; - const Vector<godot_int> *src = (const Vector<godot_int> *)p_src; - memnew_placement(dest, Vector<godot_int>(*src)); +void GDAPI godot_packed_float32_array_new_copy(godot_packed_float32_array *r_dest, const godot_packed_float32_array *p_src) { + Vector<float> *dest = (Vector<float> *)r_dest; + const Vector<float> *src = (const Vector<float> *)p_src; + memnew_placement(dest, Vector<float>(*src)); } -void GDAPI godot_packed_int_array_new_with_array(godot_packed_int_array *r_dest, const godot_array *p_a) { - Vector<godot_int> *dest = (Vector<godot_int> *)r_dest; +void GDAPI godot_packed_float32_array_new_with_array(godot_packed_float32_array *r_dest, const godot_array *p_a) { + Vector<float> *dest = (Vector<float> *)r_dest; Array *a = (Array *)p_a; - memnew_placement(dest, Vector<godot_int>); + memnew_placement(dest, Vector<float>); dest->resize(a->size()); for (int i = 0; i < a->size(); i++) { @@ -152,83 +330,83 @@ void GDAPI godot_packed_int_array_new_with_array(godot_packed_int_array *r_dest, } } -void GDAPI godot_packed_int_array_append(godot_packed_int_array *p_self, const godot_int p_data) { - Vector<godot_int> *self = (Vector<godot_int> *)p_self; +void GDAPI godot_packed_float32_array_append(godot_packed_float32_array *p_self, const float p_data) { + Vector<float> *self = (Vector<float> *)p_self; self->push_back(p_data); } -void GDAPI godot_packed_int_array_append_array(godot_packed_int_array *p_self, const godot_packed_int_array *p_array) { - Vector<godot_int> *self = (Vector<godot_int> *)p_self; - Vector<godot_int> *array = (Vector<godot_int> *)p_array; +void GDAPI godot_packed_float32_array_append_array(godot_packed_float32_array *p_self, const godot_packed_float32_array *p_array) { + Vector<float> *self = (Vector<float> *)p_self; + Vector<float> *array = (Vector<float> *)p_array; self->append_array(*array); } -godot_error GDAPI godot_packed_int_array_insert(godot_packed_int_array *p_self, const godot_int p_idx, const godot_int p_data) { - Vector<godot_int> *self = (Vector<godot_int> *)p_self; +godot_error GDAPI godot_packed_float32_array_insert(godot_packed_float32_array *p_self, const godot_int p_idx, const float p_data) { + Vector<float> *self = (Vector<float> *)p_self; return (godot_error)self->insert(p_idx, p_data); } -void GDAPI godot_packed_int_array_invert(godot_packed_int_array *p_self) { - Vector<godot_int> *self = (Vector<godot_int> *)p_self; +void GDAPI godot_packed_float32_array_invert(godot_packed_float32_array *p_self) { + Vector<float> *self = (Vector<float> *)p_self; self->invert(); } -void GDAPI godot_packed_int_array_push_back(godot_packed_int_array *p_self, const godot_int p_data) { - Vector<godot_int> *self = (Vector<godot_int> *)p_self; +void GDAPI godot_packed_float32_array_push_back(godot_packed_float32_array *p_self, const float p_data) { + Vector<float> *self = (Vector<float> *)p_self; self->push_back(p_data); } -void GDAPI godot_packed_int_array_remove(godot_packed_int_array *p_self, const godot_int p_idx) { - Vector<godot_int> *self = (Vector<godot_int> *)p_self; +void GDAPI godot_packed_float32_array_remove(godot_packed_float32_array *p_self, const godot_int p_idx) { + Vector<float> *self = (Vector<float> *)p_self; self->remove(p_idx); } -void GDAPI godot_packed_int_array_resize(godot_packed_int_array *p_self, const godot_int p_size) { - Vector<godot_int> *self = (Vector<godot_int> *)p_self; +void GDAPI godot_packed_float32_array_resize(godot_packed_float32_array *p_self, const godot_int p_size) { + Vector<float> *self = (Vector<float> *)p_self; self->resize(p_size); } -void GDAPI godot_packed_int_array_set(godot_packed_int_array *p_self, const godot_int p_idx, const godot_int p_data) { - Vector<godot_int> *self = (Vector<godot_int> *)p_self; +void GDAPI godot_packed_float32_array_set(godot_packed_float32_array *p_self, const godot_int p_idx, const float p_data) { + Vector<float> *self = (Vector<float> *)p_self; self->set(p_idx, p_data); } -godot_int GDAPI godot_packed_int_array_get(const godot_packed_int_array *p_self, const godot_int p_idx) { - const Vector<godot_int> *self = (const Vector<godot_int> *)p_self; +float GDAPI godot_packed_float32_array_get(const godot_packed_float32_array *p_self, const godot_int p_idx) { + const Vector<float> *self = (const Vector<float> *)p_self; return self->get(p_idx); } -godot_int GDAPI godot_packed_int_array_size(const godot_packed_int_array *p_self) { - const Vector<godot_int> *self = (const Vector<godot_int> *)p_self; +godot_int GDAPI godot_packed_float32_array_size(const godot_packed_float32_array *p_self) { + const Vector<float> *self = (const Vector<float> *)p_self; return self->size(); } -godot_bool GDAPI godot_packed_int_array_empty(const godot_packed_int_array *p_self) { - const Vector<godot_int> *self = (const Vector<godot_int> *)p_self; +godot_bool GDAPI godot_packed_float32_array_empty(const godot_packed_float32_array *p_self) { + const Vector<float> *self = (const Vector<float> *)p_self; return self->empty(); } -void GDAPI godot_packed_int_array_destroy(godot_packed_int_array *p_self) { - ((Vector<godot_int> *)p_self)->~Vector(); +void GDAPI godot_packed_float32_array_destroy(godot_packed_float32_array *p_self) { + ((Vector<float> *)p_self)->~Vector(); } -// real +// float64 -void GDAPI godot_packed_real_array_new(godot_packed_real_array *r_dest) { - Vector<godot_real> *dest = (Vector<godot_real> *)r_dest; - memnew_placement(dest, Vector<godot_real>); +void GDAPI godot_packed_float64_array_new(godot_packed_float64_array *r_dest) { + Vector<double> *dest = (Vector<double> *)r_dest; + memnew_placement(dest, Vector<double>); } -void GDAPI godot_packed_real_array_new_copy(godot_packed_real_array *r_dest, const godot_packed_real_array *p_src) { - Vector<godot_real> *dest = (Vector<godot_real> *)r_dest; - const Vector<godot_real> *src = (const Vector<godot_real> *)p_src; - memnew_placement(dest, Vector<godot_real>(*src)); +void GDAPI godot_packed_float64_array_new_copy(godot_packed_float64_array *r_dest, const godot_packed_float64_array *p_src) { + Vector<double> *dest = (Vector<double> *)r_dest; + const Vector<double> *src = (const Vector<double> *)p_src; + memnew_placement(dest, Vector<double>(*src)); } -void GDAPI godot_packed_real_array_new_with_array(godot_packed_real_array *r_dest, const godot_array *p_a) { - Vector<godot_real> *dest = (Vector<godot_real> *)r_dest; +void GDAPI godot_packed_float64_array_new_with_array(godot_packed_float64_array *r_dest, const godot_array *p_a) { + Vector<double> *dest = (Vector<double> *)r_dest; Array *a = (Array *)p_a; - memnew_placement(dest, Vector<godot_real>); + memnew_placement(dest, Vector<double>); dest->resize(a->size()); for (int i = 0; i < a->size(); i++) { @@ -236,64 +414,64 @@ void GDAPI godot_packed_real_array_new_with_array(godot_packed_real_array *r_des } } -void GDAPI godot_packed_real_array_append(godot_packed_real_array *p_self, const godot_real p_data) { - Vector<godot_real> *self = (Vector<godot_real> *)p_self; +void GDAPI godot_packed_float64_array_append(godot_packed_float64_array *p_self, const double p_data) { + Vector<double> *self = (Vector<double> *)p_self; self->push_back(p_data); } -void GDAPI godot_packed_real_array_append_array(godot_packed_real_array *p_self, const godot_packed_real_array *p_array) { - Vector<godot_real> *self = (Vector<godot_real> *)p_self; - Vector<godot_real> *array = (Vector<godot_real> *)p_array; +void GDAPI godot_packed_float64_array_append_array(godot_packed_float64_array *p_self, const godot_packed_float64_array *p_array) { + Vector<double> *self = (Vector<double> *)p_self; + Vector<double> *array = (Vector<double> *)p_array; self->append_array(*array); } -godot_error GDAPI godot_packed_real_array_insert(godot_packed_real_array *p_self, const godot_int p_idx, const godot_real p_data) { - Vector<godot_real> *self = (Vector<godot_real> *)p_self; +godot_error GDAPI godot_packed_float64_array_insert(godot_packed_float64_array *p_self, const godot_int p_idx, const double p_data) { + Vector<double> *self = (Vector<double> *)p_self; return (godot_error)self->insert(p_idx, p_data); } -void GDAPI godot_packed_real_array_invert(godot_packed_real_array *p_self) { - Vector<godot_real> *self = (Vector<godot_real> *)p_self; +void GDAPI godot_packed_float64_array_invert(godot_packed_float64_array *p_self) { + Vector<double> *self = (Vector<double> *)p_self; self->invert(); } -void GDAPI godot_packed_real_array_push_back(godot_packed_real_array *p_self, const godot_real p_data) { - Vector<godot_real> *self = (Vector<godot_real> *)p_self; +void GDAPI godot_packed_float64_array_push_back(godot_packed_float64_array *p_self, const double p_data) { + Vector<double> *self = (Vector<double> *)p_self; self->push_back(p_data); } -void GDAPI godot_packed_real_array_remove(godot_packed_real_array *p_self, const godot_int p_idx) { - Vector<godot_real> *self = (Vector<godot_real> *)p_self; +void GDAPI godot_packed_float64_array_remove(godot_packed_float64_array *p_self, const godot_int p_idx) { + Vector<double> *self = (Vector<double> *)p_self; self->remove(p_idx); } -void GDAPI godot_packed_real_array_resize(godot_packed_real_array *p_self, const godot_int p_size) { - Vector<godot_real> *self = (Vector<godot_real> *)p_self; +void GDAPI godot_packed_float64_array_resize(godot_packed_float64_array *p_self, const godot_int p_size) { + Vector<double> *self = (Vector<double> *)p_self; self->resize(p_size); } -void GDAPI godot_packed_real_array_set(godot_packed_real_array *p_self, const godot_int p_idx, const godot_real p_data) { - Vector<godot_real> *self = (Vector<godot_real> *)p_self; +void GDAPI godot_packed_float64_array_set(godot_packed_float64_array *p_self, const godot_int p_idx, const double p_data) { + Vector<double> *self = (Vector<double> *)p_self; self->set(p_idx, p_data); } -godot_real GDAPI godot_packed_real_array_get(const godot_packed_real_array *p_self, const godot_int p_idx) { - const Vector<godot_real> *self = (const Vector<godot_real> *)p_self; +double GDAPI godot_packed_float64_array_get(const godot_packed_float64_array *p_self, const godot_int p_idx) { + const Vector<double> *self = (const Vector<double> *)p_self; return self->get(p_idx); } -godot_int GDAPI godot_packed_real_array_size(const godot_packed_real_array *p_self) { - const Vector<godot_real> *self = (const Vector<godot_real> *)p_self; +godot_int GDAPI godot_packed_float64_array_size(const godot_packed_float64_array *p_self) { + const Vector<double> *self = (const Vector<double> *)p_self; return self->size(); } -godot_bool GDAPI godot_packed_real_array_empty(const godot_packed_real_array *p_self) { - const Vector<godot_real> *self = (const Vector<godot_real> *)p_self; +godot_bool GDAPI godot_packed_float64_array_empty(const godot_packed_float64_array *p_self) { + const Vector<double> *self = (const Vector<double> *)p_self; return self->empty(); } -void GDAPI godot_packed_real_array_destroy(godot_packed_real_array *p_self) { - ((Vector<godot_real> *)p_self)->~Vector(); +void GDAPI godot_packed_float64_array_destroy(godot_packed_float64_array *p_self) { + ((Vector<double> *)p_self)->~Vector(); } // string diff --git a/modules/gdnative/gdnative/plane.cpp b/modules/gdnative/gdnative/plane.cpp index 17221fe081..663937f906 100644 --- a/modules/gdnative/gdnative/plane.cpp +++ b/modules/gdnative/gdnative/plane.cpp @@ -37,8 +37,9 @@ extern "C" { #endif -void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d) { +static_assert(sizeof(godot_plane) == sizeof(Plane), "Plane size mismatch"); +void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d) { Plane *dest = (Plane *)r_dest; *dest = Plane(p_a, p_b, p_c, p_d); } diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp index be30b89e5f..de6308ad2a 100644 --- a/modules/gdnative/gdnative/quat.cpp +++ b/modules/gdnative/gdnative/quat.cpp @@ -37,8 +37,9 @@ extern "C" { #endif -void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w) { +static_assert(sizeof(godot_quat) == sizeof(Quat), "Quat size mismatch"); +void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w) { Quat *dest = (Quat *)r_dest; *dest = Quat(p_x, p_y, p_z, p_w); } diff --git a/modules/gdnative/gdnative/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp index 906b4f0932..516f4d75ce 100644 --- a/modules/gdnative/gdnative/rect2.cpp +++ b/modules/gdnative/gdnative/rect2.cpp @@ -37,6 +37,11 @@ extern "C" { #endif +static_assert(sizeof(godot_rect2) == sizeof(Rect2), "Rect2 size mismatch"); +static_assert(sizeof(godot_rect2i) == sizeof(Rect2i), "Rect2i size mismatch"); + +// Rect2 + void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size) { const Vector2 *position = (const Vector2 *)p_pos; const Vector2 *size = (const Vector2 *)p_size; @@ -45,7 +50,6 @@ void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const god } void GDAPI godot_rect2_new(godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height) { - Rect2 *dest = (Rect2 *)r_dest; *dest = Rect2(p_x, p_y, p_width, p_height); } @@ -57,6 +61,13 @@ godot_string GDAPI godot_rect2_as_string(const godot_rect2 *p_self) { return ret; } +godot_rect2i GDAPI godot_rect2_as_rect2i(const godot_rect2 *p_self) { + godot_rect2i dest; + const Rect2 *self = (const Rect2 *)p_self; + *((Rect2i *)&dest) = Rect2i(*self); + return dest; +} + godot_real GDAPI godot_rect2_get_area(const godot_rect2 *p_self) { const Rect2 *self = (const Rect2 *)p_self; return self->get_area(); @@ -172,6 +183,149 @@ void GDAPI godot_rect2_set_size(godot_rect2 *p_self, const godot_vector2 *p_size self->set_size(*size); } +// Rect2i + +void GDAPI godot_rect2i_new_with_position_and_size(godot_rect2i *r_dest, const godot_vector2i *p_pos, const godot_vector2i *p_size) { + const Vector2i *position = (const Vector2i *)p_pos; + const Vector2i *size = (const Vector2i *)p_size; + Rect2i *dest = (Rect2i *)r_dest; + *dest = Rect2i(*position, *size); +} + +void GDAPI godot_rect2i_new(godot_rect2i *r_dest, const godot_int p_x, const godot_int p_y, const godot_int p_width, const godot_int p_height) { + Rect2i *dest = (Rect2i *)r_dest; + *dest = Rect2i(p_x, p_y, p_width, p_height); +} + +godot_string GDAPI godot_rect2i_as_string(const godot_rect2i *p_self) { + godot_string ret; + const Rect2i *self = (const Rect2i *)p_self; + memnew_placement(&ret, String(*self)); + return ret; +} + +godot_rect2 GDAPI godot_rect2i_as_rect2(const godot_rect2i *p_self) { + godot_rect2 dest; + const Rect2i *self = (const Rect2i *)p_self; + *((Rect2 *)&dest) = Rect2(*self); + return dest; +} + +godot_int GDAPI godot_rect2i_get_area(const godot_rect2i *p_self) { + const Rect2i *self = (const Rect2i *)p_self; + return self->get_area(); +} + +godot_bool GDAPI godot_rect2i_intersects(const godot_rect2i *p_self, const godot_rect2i *p_b) { + const Rect2i *self = (const Rect2i *)p_self; + const Rect2i *b = (const Rect2i *)p_b; + return self->intersects(*b); +} + +godot_bool GDAPI godot_rect2i_encloses(const godot_rect2i *p_self, const godot_rect2i *p_b) { + const Rect2i *self = (const Rect2i *)p_self; + const Rect2i *b = (const Rect2i *)p_b; + return self->encloses(*b); +} + +godot_bool GDAPI godot_rect2i_has_no_area(const godot_rect2i *p_self) { + const Rect2i *self = (const Rect2i *)p_self; + return self->has_no_area(); +} + +godot_rect2i GDAPI godot_rect2i_clip(const godot_rect2i *p_self, const godot_rect2i *p_b) { + godot_rect2i dest; + const Rect2i *self = (const Rect2i *)p_self; + const Rect2i *b = (const Rect2i *)p_b; + *((Rect2i *)&dest) = self->clip(*b); + return dest; +} + +godot_rect2i GDAPI godot_rect2i_merge(const godot_rect2i *p_self, const godot_rect2i *p_b) { + godot_rect2i dest; + const Rect2i *self = (const Rect2i *)p_self; + const Rect2i *b = (const Rect2i *)p_b; + *((Rect2i *)&dest) = self->merge(*b); + return dest; +} + +godot_bool GDAPI godot_rect2i_has_point(const godot_rect2i *p_self, const godot_vector2i *p_point) { + const Rect2i *self = (const Rect2i *)p_self; + const Vector2i *point = (const Vector2i *)p_point; + return self->has_point(*point); +} + +godot_rect2i GDAPI godot_rect2i_grow(const godot_rect2i *p_self, const godot_int p_by) { + godot_rect2i dest; + const Rect2i *self = (const Rect2i *)p_self; + + *((Rect2i *)&dest) = self->grow(p_by); + return dest; +} + +godot_rect2i GDAPI godot_rect2i_grow_individual(const godot_rect2i *p_self, const godot_int p_left, const godot_int p_top, const godot_int p_right, const godot_int p_bottom) { + godot_rect2i dest; + const Rect2i *self = (const Rect2i *)p_self; + *((Rect2i *)&dest) = self->grow_individual(p_left, p_top, p_right, p_bottom); + return dest; +} + +godot_rect2i GDAPI godot_rect2i_grow_margin(const godot_rect2i *p_self, const godot_int p_margin, const godot_int p_by) { + godot_rect2i dest; + const Rect2i *self = (const Rect2i *)p_self; + *((Rect2i *)&dest) = self->grow_margin((Margin)p_margin, p_by); + return dest; +} + +godot_rect2i GDAPI godot_rect2i_abs(const godot_rect2i *p_self) { + godot_rect2i dest; + const Rect2i *self = (const Rect2i *)p_self; + *((Rect2i *)&dest) = self->abs(); + return dest; +} + +godot_rect2i GDAPI godot_rect2i_expand(const godot_rect2i *p_self, const godot_vector2i *p_to) { + godot_rect2i dest; + const Rect2i *self = (const Rect2i *)p_self; + const Vector2i *to = (const Vector2i *)p_to; + *((Rect2i *)&dest) = self->expand(*to); + return dest; +} + +godot_bool GDAPI godot_rect2i_operator_equal(const godot_rect2i *p_self, const godot_rect2i *p_b) { + const Rect2i *self = (const Rect2i *)p_self; + const Rect2i *b = (const Rect2i *)p_b; + return *self == *b; +} + +godot_vector2i GDAPI godot_rect2i_get_position(const godot_rect2i *p_self) { + godot_vector2i dest; + Vector2i *d = (Vector2i *)&dest; + const Rect2i *self = (const Rect2i *)p_self; + *d = self->get_position(); + return dest; +} + +godot_vector2i GDAPI godot_rect2i_get_size(const godot_rect2i *p_self) { + godot_vector2i dest; + Vector2i *d = (Vector2i *)&dest; + const Rect2i *self = (const Rect2i *)p_self; + *d = self->get_size(); + return dest; +} + +void GDAPI godot_rect2i_set_position(godot_rect2i *p_self, const godot_vector2i *p_pos) { + Rect2i *self = (Rect2i *)p_self; + const Vector2i *position = (const Vector2i *)p_pos; + self->set_position(*position); +} + +void GDAPI godot_rect2i_set_size(godot_rect2i *p_self, const godot_vector2i *p_size) { + Rect2i *self = (Rect2i *)p_self; + const Vector2i *size = (const Vector2i *)p_size; + self->set_size(*size); +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/rid.cpp b/modules/gdnative/gdnative/rid.cpp index 7ea80123a3..d7a63f33a7 100644 --- a/modules/gdnative/gdnative/rid.cpp +++ b/modules/gdnative/gdnative/rid.cpp @@ -38,6 +38,8 @@ extern "C" { #endif +static_assert(sizeof(godot_rid) == sizeof(RID), "RID size mismatch"); + void GDAPI godot_rid_new(godot_rid *r_dest) { RID *dest = (RID *)r_dest; memnew_placement(dest, RID); diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 4cb55900b0..724a4b56cb 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -40,6 +40,10 @@ extern "C" { #endif +static_assert(sizeof(godot_char_string) == sizeof(CharString), "CharString size mismatch"); +static_assert(sizeof(godot_string) == sizeof(String), "String size mismatch"); +static_assert(sizeof(godot_char_type) == sizeof(CharType), "CharType size mismatch"); + godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs) { const CharString *cs = (const CharString *)p_cs; @@ -137,6 +141,7 @@ signed char GDAPI godot_string_nocasecmp_to(const godot_string *p_self, const go return self->nocasecmp_to(*str); } + signed char GDAPI godot_string_naturalnocasecmp_to(const godot_string *p_self, const godot_string *p_str) { const String *self = (const String *)p_self; const String *str = (const String *)p_str; diff --git a/modules/gdnative/gdnative/string_name.cpp b/modules/gdnative/gdnative/string_name.cpp index 1abb4486b1..7bbaaeeaa0 100644 --- a/modules/gdnative/gdnative/string_name.cpp +++ b/modules/gdnative/gdnative/string_name.cpp @@ -39,6 +39,8 @@ extern "C" { #endif +static_assert(sizeof(godot_string_name) == sizeof(StringName), "StringName size mismatch"); + void GDAPI godot_string_name_new(godot_string_name *r_dest, const godot_string *p_name) { StringName *dest = (StringName *)r_dest; const String *name = (const String *)p_name; diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp index c9b3e37fb2..d19de93e9b 100644 --- a/modules/gdnative/gdnative/transform.cpp +++ b/modules/gdnative/gdnative/transform.cpp @@ -37,6 +37,8 @@ extern "C" { #endif +static_assert(sizeof(godot_transform) == sizeof(Transform), "Transform size mismatch"); + void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin) { const Vector3 *x_axis = (const Vector3 *)p_x_axis; const Vector3 *y_axis = (const Vector3 *)p_y_axis; diff --git a/modules/gdnative/gdnative/transform2d.cpp b/modules/gdnative/gdnative/transform2d.cpp index 26a71333b1..c0f7878eb0 100644 --- a/modules/gdnative/gdnative/transform2d.cpp +++ b/modules/gdnative/gdnative/transform2d.cpp @@ -37,6 +37,8 @@ extern "C" { #endif +static_assert(sizeof(godot_transform2d) == sizeof(Transform2D), "Transform2D size mismatch"); + void GDAPI godot_transform2d_new(godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos) { const Vector2 *pos = (const Vector2 *)p_pos; Transform2D *dest = (Transform2D *)r_dest; diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp index f0fc44ae8a..dac4feb0e5 100644 --- a/modules/gdnative/gdnative/variant.cpp +++ b/modules/gdnative/gdnative/variant.cpp @@ -37,6 +37,8 @@ extern "C" { #endif +static_assert(sizeof(godot_variant) == sizeof(Variant), "Variant size mismatch"); + // Workaround GCC ICE on armv7hl which was affected GCC 6.0 up to 8.0 (GH-16100). // It was fixed upstream in 8.1, and a fix was backported to 7.4. // This can be removed once no supported distro ships with versions older than 7.4. @@ -97,24 +99,48 @@ void GDAPI godot_variant_new_string(godot_variant *r_dest, const godot_string *p memnew_placement_custom(dest, Variant, Variant(*s)); } +void GDAPI godot_variant_new_string_name(godot_variant *r_dest, const godot_string_name *p_s) { + Variant *dest = (Variant *)r_dest; + StringName *s = (StringName *)p_s; + memnew_placement_custom(dest, Variant, Variant(*s)); +} + void GDAPI godot_variant_new_vector2(godot_variant *r_dest, const godot_vector2 *p_v2) { Variant *dest = (Variant *)r_dest; Vector2 *v2 = (Vector2 *)p_v2; memnew_placement_custom(dest, Variant, Variant(*v2)); } +void GDAPI godot_variant_new_vector2i(godot_variant *r_dest, const godot_vector2i *p_v2) { + Variant *dest = (Variant *)r_dest; + Vector2i *v2 = (Vector2i *)p_v2; + memnew_placement_custom(dest, Variant, Variant(*v2)); +} + void GDAPI godot_variant_new_rect2(godot_variant *r_dest, const godot_rect2 *p_rect2) { Variant *dest = (Variant *)r_dest; Rect2 *rect2 = (Rect2 *)p_rect2; memnew_placement_custom(dest, Variant, Variant(*rect2)); } +void GDAPI godot_variant_new_rect2i(godot_variant *r_dest, const godot_rect2i *p_rect2) { + Variant *dest = (Variant *)r_dest; + Rect2i *rect2 = (Rect2i *)p_rect2; + memnew_placement_custom(dest, Variant, Variant(*rect2)); +} + void GDAPI godot_variant_new_vector3(godot_variant *r_dest, const godot_vector3 *p_v3) { Variant *dest = (Variant *)r_dest; Vector3 *v3 = (Vector3 *)p_v3; memnew_placement_custom(dest, Variant, Variant(*v3)); } +void GDAPI godot_variant_new_vector3i(godot_variant *r_dest, const godot_vector3i *p_v3) { + Variant *dest = (Variant *)r_dest; + Vector3i *v3 = (Vector3i *)p_v3; + memnew_placement_custom(dest, Variant, Variant(*v3)); +} + void GDAPI godot_variant_new_transform2d(godot_variant *r_dest, const godot_transform2d *p_t2d) { Variant *dest = (Variant *)r_dest; Transform2D *t2d = (Transform2D *)p_t2d; @@ -169,6 +195,18 @@ void GDAPI godot_variant_new_rid(godot_variant *r_dest, const godot_rid *p_rid) memnew_placement_custom(dest, Variant, Variant(*rid)); } +void GDAPI godot_variant_new_callable(godot_variant *r_dest, const godot_callable *p_cb) { + Variant *dest = (Variant *)r_dest; + Callable *cb = (Callable *)p_cb; + memnew_placement_custom(dest, Variant, Variant(*cb)); +} + +void GDAPI godot_variant_new_signal(godot_variant *r_dest, const godot_signal *p_signal) { + Variant *dest = (Variant *)r_dest; + Signal *signal = (Signal *)p_signal; + memnew_placement_custom(dest, Variant, Variant(*signal)); +} + void GDAPI godot_variant_new_object(godot_variant *r_dest, const godot_object *p_obj) { Variant *dest = (Variant *)r_dest; Object *obj = (Object *)p_obj; @@ -207,18 +245,30 @@ void GDAPI godot_variant_new_packed_byte_array(godot_variant *r_dest, const godo memnew_placement_custom(dest, Variant, Variant(*pba)); } -void GDAPI godot_variant_new_packed_int_array(godot_variant *r_dest, const godot_packed_int_array *p_pia) { +void GDAPI godot_variant_new_packed_int32_array(godot_variant *r_dest, const godot_packed_int32_array *p_pia) { Variant *dest = (Variant *)r_dest; PackedInt32Array *pia = (PackedInt32Array *)p_pia; memnew_placement_custom(dest, Variant, Variant(*pia)); } -void GDAPI godot_variant_new_packed_real_array(godot_variant *r_dest, const godot_packed_real_array *p_pra) { +void GDAPI godot_variant_new_packed_int64_array(godot_variant *r_dest, const godot_packed_int64_array *p_pia) { + Variant *dest = (Variant *)r_dest; + PackedInt64Array *pia = (PackedInt64Array *)p_pia; + memnew_placement_custom(dest, Variant, Variant(*pia)); +} + +void GDAPI godot_variant_new_packed_float32_array(godot_variant *r_dest, const godot_packed_float32_array *p_pra) { Variant *dest = (Variant *)r_dest; PackedFloat32Array *pra = (PackedFloat32Array *)p_pra; memnew_placement_custom(dest, Variant, Variant(*pra)); } +void GDAPI godot_variant_new_packed_float64_array(godot_variant *r_dest, const godot_packed_float64_array *p_pra) { + Variant *dest = (Variant *)r_dest; + PackedFloat64Array *pra = (PackedFloat64Array *)p_pra; + memnew_placement_custom(dest, Variant, Variant(*pra)); +} + void GDAPI godot_variant_new_packed_string_array(godot_variant *r_dest, const godot_packed_string_array *p_psa) { Variant *dest = (Variant *)r_dest; PackedStringArray *psa = (PackedStringArray *)p_psa; @@ -271,6 +321,14 @@ godot_string GDAPI godot_variant_as_string(const godot_variant *p_self) { return raw_dest; } +godot_string_name GDAPI godot_variant_as_string_name(const godot_variant *p_self) { + godot_string_name raw_dest; + const Variant *self = (const Variant *)p_self; + StringName *dest = (StringName *)&raw_dest; + memnew_placement(dest, StringName(self->operator StringName())); // operator = is overloaded by StringName + return raw_dest; +} + godot_vector2 GDAPI godot_variant_as_vector2(const godot_variant *p_self) { godot_vector2 raw_dest; const Variant *self = (const Variant *)p_self; @@ -279,6 +337,14 @@ godot_vector2 GDAPI godot_variant_as_vector2(const godot_variant *p_self) { return raw_dest; } +godot_vector2i GDAPI godot_variant_as_vector2i(const godot_variant *p_self) { + godot_vector2i raw_dest; + const Variant *self = (const Variant *)p_self; + Vector2i *dest = (Vector2i *)&raw_dest; + *dest = *self; + return raw_dest; +} + godot_rect2 GDAPI godot_variant_as_rect2(const godot_variant *p_self) { godot_rect2 raw_dest; const Variant *self = (const Variant *)p_self; @@ -287,6 +353,14 @@ godot_rect2 GDAPI godot_variant_as_rect2(const godot_variant *p_self) { return raw_dest; } +godot_rect2i GDAPI godot_variant_as_rect2i(const godot_variant *p_self) { + godot_rect2i raw_dest; + const Variant *self = (const Variant *)p_self; + Rect2i *dest = (Rect2i *)&raw_dest; + *dest = *self; + return raw_dest; +} + godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_self) { godot_vector3 raw_dest; const Variant *self = (const Variant *)p_self; @@ -295,6 +369,14 @@ godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_self) { return raw_dest; } +godot_vector3i GDAPI godot_variant_as_vector3i(const godot_variant *p_self) { + godot_vector3i raw_dest; + const Variant *self = (const Variant *)p_self; + Vector3i *dest = (Vector3i *)&raw_dest; + *dest = *self; + return raw_dest; +} + godot_transform2d GDAPI godot_variant_as_transform2d(const godot_variant *p_self) { godot_transform2d raw_dest; const Variant *self = (const Variant *)p_self; @@ -367,6 +449,22 @@ godot_rid GDAPI godot_variant_as_rid(const godot_variant *p_self) { return raw_dest; } +godot_callable GDAPI godot_variant_as_callable(const godot_variant *p_self) { + godot_callable raw_dest; + const Variant *self = (const Variant *)p_self; + Callable *dest = (Callable *)&raw_dest; + *dest = *self; + return raw_dest; +} + +godot_signal GDAPI godot_variant_as_signal(const godot_variant *p_self) { + godot_signal raw_dest; + const Variant *self = (const Variant *)p_self; + Signal *dest = (Signal *)&raw_dest; + *dest = *self; + return raw_dest; +} + godot_object GDAPI *godot_variant_as_object(const godot_variant *p_self) { const Variant *self = (const Variant *)p_self; Object *dest; @@ -399,8 +497,8 @@ godot_packed_byte_array GDAPI godot_variant_as_packed_byte_array(const godot_var return raw_dest; } -godot_packed_int_array GDAPI godot_variant_as_packed_int_array(const godot_variant *p_self) { - godot_packed_int_array raw_dest; +godot_packed_int32_array GDAPI godot_variant_as_packed_int32_array(const godot_variant *p_self) { + godot_packed_int32_array raw_dest; const Variant *self = (const Variant *)p_self; PackedInt32Array *dest = (PackedInt32Array *)&raw_dest; memnew_placement(dest, PackedInt32Array(self->operator PackedInt32Array())); // operator = is overloaded by PackedInt32Array @@ -408,8 +506,17 @@ godot_packed_int_array GDAPI godot_variant_as_packed_int_array(const godot_varia return raw_dest; } -godot_packed_real_array GDAPI godot_variant_as_packed_real_array(const godot_variant *p_self) { - godot_packed_real_array raw_dest; +godot_packed_int64_array GDAPI godot_variant_as_packed_int64_array(const godot_variant *p_self) { + godot_packed_int64_array raw_dest; + const Variant *self = (const Variant *)p_self; + PackedInt64Array *dest = (PackedInt64Array *)&raw_dest; + memnew_placement(dest, PackedInt64Array(self->operator PackedInt64Array())); // operator = is overloaded by PackedInt64Array + *dest = *self; + return raw_dest; +} + +godot_packed_float32_array GDAPI godot_variant_as_packed_float32_array(const godot_variant *p_self) { + godot_packed_float32_array raw_dest; const Variant *self = (const Variant *)p_self; PackedFloat32Array *dest = (PackedFloat32Array *)&raw_dest; memnew_placement(dest, PackedFloat32Array(self->operator PackedFloat32Array())); // operator = is overloaded by PackedFloat32Array @@ -417,6 +524,15 @@ godot_packed_real_array GDAPI godot_variant_as_packed_real_array(const godot_var return raw_dest; } +godot_packed_float64_array GDAPI godot_variant_as_packed_float64_array(const godot_variant *p_self) { + godot_packed_float64_array raw_dest; + const Variant *self = (const Variant *)p_self; + PackedFloat64Array *dest = (PackedFloat64Array *)&raw_dest; + memnew_placement(dest, PackedFloat64Array(self->operator PackedFloat64Array())); // operator = is overloaded by PackedFloat64Array + *dest = *self; + return raw_dest; +} + godot_packed_string_array GDAPI godot_variant_as_packed_string_array(const godot_variant *p_self) { godot_packed_string_array raw_dest; const Variant *self = (const Variant *)p_self; @@ -487,6 +603,11 @@ godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const return self->operator<(*other); } +uint32_t GDAPI godot_variant_hash(const godot_variant *p_self) { + const Variant *self = (const Variant *)p_self; + return self->hash(); +} + godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other) { const Variant *self = (const Variant *)p_self; const Variant *other = (const Variant *)p_other; diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp index e9e2a8edf8..1ee716df86 100644 --- a/modules/gdnative/gdnative/vector2.cpp +++ b/modules/gdnative/gdnative/vector2.cpp @@ -37,8 +37,12 @@ extern "C" { #endif -void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y) { +static_assert(sizeof(godot_vector2) == sizeof(Vector2), "Vector2 size mismatch"); +static_assert(sizeof(godot_vector2i) == sizeof(Vector2i), "Vector2i size mismatch"); + +// Vector2 +void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y) { Vector2 *dest = (Vector2 *)r_dest; *dest = Vector2(p_x, p_y); } @@ -50,6 +54,13 @@ godot_string GDAPI godot_vector2_as_string(const godot_vector2 *p_self) { return ret; } +godot_vector2i GDAPI godot_vector2_as_vector2i(const godot_vector2 *p_self) { + godot_vector2i dest; + const Vector2 *self = (const Vector2 *)p_self; + *((Vector2i *)&dest) = Vector2i(*self); + return dest; +} + godot_vector2 GDAPI godot_vector2_normalized(const godot_vector2 *p_self) { godot_vector2 dest; const Vector2 *self = (const Vector2 *)p_self; @@ -109,11 +120,11 @@ godot_real GDAPI godot_vector2_angle_to_point(const godot_vector2 *p_self, const return self->angle_to_point(*to); } -godot_vector2 GDAPI godot_vector2_linear_interpolate(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t) { +godot_vector2 GDAPI godot_vector2_lerp(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t) { godot_vector2 dest; const Vector2 *self = (const Vector2 *)p_self; const Vector2 *b = (const Vector2 *)p_b; - *((Vector2 *)&dest) = self->linear_interpolate(*b, p_t); + *((Vector2 *)&dest) = self->lerp(*b, p_t); return dest; } @@ -157,6 +168,13 @@ godot_vector2 GDAPI godot_vector2_floor(const godot_vector2 *p_self) { return dest; } +godot_vector2 GDAPI godot_vector2_sign(const godot_vector2 *p_self) { + godot_vector2 dest; + const Vector2 *self = (const Vector2 *)p_self; + *((Vector2 *)&dest) = self->sign(); + return dest; +} + godot_vector2 GDAPI godot_vector2_snapped(const godot_vector2 *p_self, const godot_vector2 *p_by) { godot_vector2 dest; const Vector2 *self = (const Vector2 *)p_self; @@ -307,6 +325,138 @@ godot_real GDAPI godot_vector2_get_y(const godot_vector2 *p_self) { return self->y; } +// Vector2i + +void GDAPI godot_vector2i_new(godot_vector2i *r_dest, const godot_int p_x, const godot_int p_y) { + Vector2i *dest = (Vector2i *)r_dest; + *dest = Vector2i(p_x, p_y); +} + +godot_string GDAPI godot_vector2i_as_string(const godot_vector2i *p_self) { + godot_string ret; + const Vector2i *self = (const Vector2i *)p_self; + memnew_placement(&ret, String(*self)); + return ret; +} + +godot_vector2 GDAPI godot_vector2i_as_vector2(const godot_vector2i *p_self) { + godot_vector2 dest; + const Vector2i *self = (const Vector2i *)p_self; + *((Vector2 *)&dest) = Vector2(*self); + return dest; +} + +godot_real GDAPI godot_vector2i_aspect(const godot_vector2i *p_self) { + const Vector2i *self = (const Vector2i *)p_self; + return self->aspect(); +} + +godot_vector2i GDAPI godot_vector2i_abs(const godot_vector2i *p_self) { + godot_vector2i dest; + const Vector2i *self = (const Vector2i *)p_self; + *((Vector2i *)&dest) = self->abs(); + return dest; +} + +godot_vector2i GDAPI godot_vector2i_sign(const godot_vector2i *p_self) { + godot_vector2i dest; + const Vector2i *self = (const Vector2i *)p_self; + *((Vector2i *)&dest) = self->sign(); + return dest; +} + +godot_vector2i GDAPI godot_vector2i_operator_add(const godot_vector2i *p_self, const godot_vector2i *p_b) { + godot_vector2i raw_dest; + Vector2i *dest = (Vector2i *)&raw_dest; + const Vector2i *self = (const Vector2i *)p_self; + const Vector2i *b = (const Vector2i *)p_b; + *dest = *self + *b; + return raw_dest; +} + +godot_vector2i GDAPI godot_vector2i_operator_subtract(const godot_vector2i *p_self, const godot_vector2i *p_b) { + godot_vector2i raw_dest; + Vector2i *dest = (Vector2i *)&raw_dest; + const Vector2i *self = (const Vector2i *)p_self; + const Vector2i *b = (const Vector2i *)p_b; + *dest = *self - *b; + return raw_dest; +} + +godot_vector2i GDAPI godot_vector2i_operator_multiply_vector(const godot_vector2i *p_self, const godot_vector2i *p_b) { + godot_vector2i raw_dest; + Vector2i *dest = (Vector2i *)&raw_dest; + const Vector2i *self = (const Vector2i *)p_self; + const Vector2i *b = (const Vector2i *)p_b; + *dest = *self * *b; + return raw_dest; +} + +godot_vector2i GDAPI godot_vector2i_operator_multiply_scalar(const godot_vector2i *p_self, const godot_int p_b) { + godot_vector2i raw_dest; + Vector2i *dest = (Vector2i *)&raw_dest; + const Vector2i *self = (const Vector2i *)p_self; + *dest = *self * p_b; + return raw_dest; +} + +godot_vector2i GDAPI godot_vector2i_operator_divide_vector(const godot_vector2i *p_self, const godot_vector2i *p_b) { + godot_vector2i raw_dest; + Vector2i *dest = (Vector2i *)&raw_dest; + const Vector2i *self = (const Vector2i *)p_self; + const Vector2i *b = (const Vector2i *)p_b; + *dest = *self / *b; + return raw_dest; +} + +godot_vector2i GDAPI godot_vector2i_operator_divide_scalar(const godot_vector2i *p_self, const godot_int p_b) { + godot_vector2i raw_dest; + Vector2i *dest = (Vector2i *)&raw_dest; + const Vector2i *self = (const Vector2i *)p_self; + *dest = *self / p_b; + return raw_dest; +} + +godot_bool GDAPI godot_vector2i_operator_equal(const godot_vector2i *p_self, const godot_vector2i *p_b) { + const Vector2i *self = (const Vector2i *)p_self; + const Vector2i *b = (const Vector2i *)p_b; + return *self == *b; +} + +godot_bool GDAPI godot_vector2i_operator_less(const godot_vector2i *p_self, const godot_vector2i *p_b) { + const Vector2i *self = (const Vector2i *)p_self; + const Vector2i *b = (const Vector2i *)p_b; + return *self < *b; +} + +godot_vector2i GDAPI godot_vector2i_operator_neg(const godot_vector2i *p_self) { + godot_vector2i raw_dest; + Vector2i *dest = (Vector2i *)&raw_dest; + const Vector2i *self = (const Vector2i *)p_self; + *dest = -(*self); + return raw_dest; +} + +void GDAPI godot_vector2i_set_x(godot_vector2i *p_self, const godot_int p_x) { + Vector2i *self = (Vector2i *)p_self; + self->x = p_x; +} + +void GDAPI godot_vector2i_set_y(godot_vector2i *p_self, const godot_int p_y) { + Vector2i *self = (Vector2i *)p_self; + self->y = p_y; +} + +godot_int GDAPI godot_vector2i_get_x(const godot_vector2i *p_self) { + const Vector2i *self = (const Vector2i *)p_self; + return self->x; +} + +godot_int GDAPI godot_vector2i_get_y(const godot_vector2i *p_self) { + const Vector2i *self = (const Vector2i *)p_self; + return self->y; +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp index e34a9370a5..32cad30c17 100644 --- a/modules/gdnative/gdnative/vector3.cpp +++ b/modules/gdnative/gdnative/vector3.cpp @@ -37,8 +37,12 @@ extern "C" { #endif -void GDAPI godot_vector3_new(godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z) { +static_assert(sizeof(godot_vector3) == sizeof(Vector3), "Vector3 size mismatch"); +static_assert(sizeof(godot_vector3i) == sizeof(Vector3i), "Vector3i size mismatch"); + +// Vector3 +void GDAPI godot_vector3_new(godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z) { Vector3 *dest = (Vector3 *)r_dest; *dest = Vector3(p_x, p_y, p_z); } @@ -50,6 +54,13 @@ godot_string GDAPI godot_vector3_as_string(const godot_vector3 *p_self) { return ret; } +godot_vector3i GDAPI godot_vector3_as_vector3i(const godot_vector3 *p_self) { + godot_vector3i dest; + const Vector3 *self = (const Vector3 *)p_self; + *((Vector3i *)&dest) = Vector3i(*self); + return dest; +} + godot_int GDAPI godot_vector3_min_axis(const godot_vector3 *p_self) { const Vector3 *self = (const Vector3 *)p_self; return self->min_axis(); @@ -106,11 +117,11 @@ godot_vector3 GDAPI godot_vector3_rotated(const godot_vector3 *p_self, const god return dest; } -godot_vector3 GDAPI godot_vector3_linear_interpolate(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t) { +godot_vector3 GDAPI godot_vector3_lerp(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t) { godot_vector3 dest; const Vector3 *self = (const Vector3 *)p_self; const Vector3 *b = (const Vector3 *)p_b; - *((Vector3 *)&dest) = self->linear_interpolate(*b, p_t); + *((Vector3 *)&dest) = self->lerp(*b, p_t); return dest; } @@ -168,6 +179,13 @@ godot_vector3 GDAPI godot_vector3_abs(const godot_vector3 *p_self) { return dest; } +godot_vector3 GDAPI godot_vector3_sign(const godot_vector3 *p_self) { + godot_vector3 dest; + const Vector3 *self = (const Vector3 *)p_self; + *((Vector3 *)&dest) = self->sign(); + return dest; +} + godot_vector3 GDAPI godot_vector3_floor(const godot_vector3 *p_self) { godot_vector3 dest; const Vector3 *self = (const Vector3 *)p_self; @@ -314,6 +332,133 @@ godot_real GDAPI godot_vector3_get_axis(const godot_vector3 *p_self, const godot return self->get_axis(p_axis); } +// Vector3i + +void GDAPI godot_vector3i_new(godot_vector3i *r_dest, const godot_int p_x, const godot_int p_y, const godot_int p_z) { + Vector3i *dest = (Vector3i *)r_dest; + *dest = Vector3i(p_x, p_y, p_z); +} + +godot_string GDAPI godot_vector3i_as_string(const godot_vector3i *p_self) { + godot_string ret; + const Vector3i *self = (const Vector3i *)p_self; + memnew_placement(&ret, String(*self)); + return ret; +} + +godot_vector3 GDAPI godot_vector3i_as_vector3(const godot_vector3i *p_self) { + godot_vector3 dest; + const Vector3i *self = (const Vector3i *)p_self; + *((Vector3 *)&dest) = Vector3(*self); + return dest; +} + +godot_int GDAPI godot_vector3i_min_axis(const godot_vector3i *p_self) { + const Vector3i *self = (const Vector3i *)p_self; + return self->min_axis(); +} + +godot_int GDAPI godot_vector3i_max_axis(const godot_vector3i *p_self) { + const Vector3i *self = (const Vector3i *)p_self; + return self->max_axis(); +} + +godot_vector3i GDAPI godot_vector3i_abs(const godot_vector3i *p_self) { + godot_vector3i dest; + const Vector3i *self = (const Vector3i *)p_self; + *((Vector3i *)&dest) = self->abs(); + return dest; +} + +godot_vector3i GDAPI godot_vector3i_sign(const godot_vector3i *p_self) { + godot_vector3i dest; + const Vector3i *self = (const Vector3i *)p_self; + *((Vector3i *)&dest) = self->sign(); + return dest; +} + +godot_vector3i GDAPI godot_vector3i_operator_add(const godot_vector3i *p_self, const godot_vector3i *p_b) { + godot_vector3i raw_dest; + Vector3i *dest = (Vector3i *)&raw_dest; + Vector3i *self = (Vector3i *)p_self; + const Vector3i *b = (const Vector3i *)p_b; + *dest = *self + *b; + return raw_dest; +} + +godot_vector3i GDAPI godot_vector3i_operator_subtract(const godot_vector3i *p_self, const godot_vector3i *p_b) { + godot_vector3i raw_dest; + Vector3i *dest = (Vector3i *)&raw_dest; + Vector3i *self = (Vector3i *)p_self; + const Vector3i *b = (const Vector3i *)p_b; + *dest = *self - *b; + return raw_dest; +} + +godot_vector3i GDAPI godot_vector3i_operator_multiply_vector(const godot_vector3i *p_self, const godot_vector3i *p_b) { + godot_vector3i raw_dest; + Vector3i *dest = (Vector3i *)&raw_dest; + Vector3i *self = (Vector3i *)p_self; + const Vector3i *b = (const Vector3i *)p_b; + *dest = *self * *b; + return raw_dest; +} + +godot_vector3i GDAPI godot_vector3i_operator_multiply_scalar(const godot_vector3i *p_self, const godot_int p_b) { + godot_vector3i raw_dest; + Vector3i *dest = (Vector3i *)&raw_dest; + Vector3i *self = (Vector3i *)p_self; + *dest = *self * p_b; + return raw_dest; +} + +godot_vector3i GDAPI godot_vector3i_operator_divide_vector(const godot_vector3i *p_self, const godot_vector3i *p_b) { + godot_vector3i raw_dest; + Vector3i *dest = (Vector3i *)&raw_dest; + Vector3i *self = (Vector3i *)p_self; + const Vector3i *b = (const Vector3i *)p_b; + *dest = *self / *b; + return raw_dest; +} + +godot_vector3i GDAPI godot_vector3i_operator_divide_scalar(const godot_vector3i *p_self, const godot_int p_b) { + godot_vector3i raw_dest; + Vector3i *dest = (Vector3i *)&raw_dest; + Vector3i *self = (Vector3i *)p_self; + *dest = *self / p_b; + return raw_dest; +} + +godot_bool GDAPI godot_vector3i_operator_equal(const godot_vector3i *p_self, const godot_vector3i *p_b) { + Vector3i *self = (Vector3i *)p_self; + const Vector3i *b = (const Vector3i *)p_b; + return *self == *b; +} + +godot_bool GDAPI godot_vector3i_operator_less(const godot_vector3i *p_self, const godot_vector3i *p_b) { + Vector3i *self = (Vector3i *)p_self; + const Vector3i *b = (const Vector3i *)p_b; + return *self < *b; +} + +godot_vector3i GDAPI godot_vector3i_operator_neg(const godot_vector3i *p_self) { + godot_vector3i raw_dest; + Vector3i *dest = (Vector3i *)&raw_dest; + const Vector3i *self = (const Vector3i *)p_self; + *dest = -(*self); + return raw_dest; +} + +void GDAPI godot_vector3i_set_axis(godot_vector3i *p_self, const godot_vector3_axis p_axis, const godot_int p_val) { + Vector3i *self = (Vector3i *)p_self; + self->set_axis(p_axis, p_val); +} + +godot_int GDAPI godot_vector3i_get_axis(const godot_vector3i *p_self, const godot_vector3_axis p_axis) { + const Vector3i *self = (const Vector3i *)p_self; + return self->get_axis(p_axis); +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index e1d6c0c867..9c38c8b58d 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -17,7 +17,1125 @@ "major": 1, "minor": 2 }, - "next": null, + "next": { + "type": "CORE", + "version": { + "major": 1, + "minor": 3 + }, + "next": null, + "api": [ + { + "name": "godot_object_get_instance_id", + "return_type": "uint64_t", + "arguments": [ + ["const godot_object *", "p_object"] + ] + }, + { + "name": "godot_array_new_packed_float64_array", + "return_type": "void", + "arguments": [ + ["godot_array *", "r_dest"], + ["const godot_packed_float64_array *", "p_pra"] + ] + }, + { + "name": "godot_array_new_packed_int64_array", + "return_type": "void", + "arguments": [ + ["godot_array *", "r_dest"], + ["const godot_packed_int64_array *", "p_pia"] + ] + }, + { + "name": "godot_callable_new_with_object", + "return_type": "void", + "arguments": [ + ["godot_callable *", "r_dest"], + ["const godot_object *", "p_object"], + ["const godot_string_name *", "p_method"] + ] + }, + { + "name": "godot_callable_new_with_object_id", + "return_type": "void", + "arguments": [ + ["godot_callable *", "r_dest"], + ["uint64_t", "p_objectid"], + ["const godot_string_name *", "p_method"] + ] + }, + { + "name": "godot_callable_new_copy", + "return_type": "void", + "arguments": [ + ["godot_callable *", "r_dest"], + ["const godot_callable *", "p_src"] + ] + }, + { + "name": "godot_callable_destroy", + "return_type": "void", + "arguments": [ + ["godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_call", + "return_type": "godot_int", + "arguments": [ + ["const godot_callable *", "p_self"], + ["const godot_variant **", "p_arguments"], + ["godot_int", "p_argcount"], + ["godot_variant *", "r_return_value"] + ] + }, + { + "name": "godot_callable_call_deferred", + "return_type": "void", + "arguments": [ + ["const godot_callable *", "p_self"], + ["const godot_variant **", "p_arguments"], + ["godot_int", "p_argcount"] + ] + }, + { + "name": "godot_callable_is_null", + "return_type": "godot_bool", + "arguments": [ + ["const godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_is_custom", + "return_type": "godot_bool", + "arguments": [ + ["const godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_is_standard", + "return_type": "godot_bool", + "arguments": [ + ["const godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_get_object", + "return_type": "godot_object *", + "arguments": [ + ["const godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_get_object_id", + "return_type": "uint64_t", + "arguments": [ + ["const godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_get_method", + "return_type": "godot_string_name", + "arguments": [ + ["const godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_hash", + "return_type": "uint32_t", + "arguments": [ + ["const godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_as_string", + "return_type": "godot_string", + "arguments": [ + ["const godot_callable *", "p_self"] + ] + }, + { + "name": "godot_callable_operator_equal", + "return_type": "godot_bool", + "arguments": [ + ["const godot_callable *", "p_self"], + ["const godot_callable *", "p_other"] + ] + }, + { + "name": "godot_callable_operator_less", + "return_type": "godot_bool", + "arguments": [ + ["const godot_callable *", "p_self"], + ["const godot_callable *", "p_other"] + ] + }, + { + "name": "godot_signal_new_with_object", + "return_type": "void", + "arguments": [ + ["godot_signal *", "r_dest"], + ["const godot_object *", "p_object"], + ["const godot_string_name *", "p_method"] + ] + }, + { + "name": "godot_signal_new_with_object_id", + "return_type": "void", + "arguments": [ + ["godot_signal *", "r_dest"], + ["uint64_t", "p_objectid"], + ["const godot_string_name *", "p_method"] + ] + }, + { + "name": "godot_signal_new_copy", + "return_type": "void", + "arguments": [ + ["godot_signal *", "r_dest"], + ["const godot_signal *", "p_src"] + ] + }, + { + "name": "godot_signal_destroy", + "return_type": "void", + "arguments": [ + ["godot_signal *", "p_self"] + ] + }, + { + "name": "godot_signal_emit", + "return_type": "godot_int", + "arguments": [ + ["const godot_signal *", "p_self"], + ["const godot_variant **", "p_arguments"], + ["godot_int", "p_argcount"] + ] + }, + { + "name": "godot_signal_connect", + "return_type": "godot_int", + "arguments": [ + ["godot_signal *", "p_self"], + ["const godot_callable *", "p_callable"], + ["const godot_array *", "p_binds"], + ["uint32_t", "p_flags"] + ] + }, + { + "name": "godot_signal_disconnect", + "return_type": "void", + "arguments": [ + ["godot_signal *", "p_self"], + ["const godot_callable *", "p_callable"] + ] + }, + { + "name": "godot_signal_is_null", + "return_type": "godot_bool", + "arguments": [ + ["const godot_signal *", "p_self"] + ] + }, + { + "name": "godot_signal_is_connected", + "return_type": "godot_bool", + "arguments": [ + ["const godot_signal *", "p_self"], + ["const godot_callable *", "p_callable"] + ] + }, + { + "name": "godot_signal_get_connections", + "return_type": "godot_array", + "arguments": [ + ["const godot_signal *", "p_self"] + ] + }, + { + "name": "godot_signal_get_object", + "return_type": "godot_object *", + "arguments": [ + ["const godot_signal *", "p_self"] + ] + }, + { + "name": "godot_signal_get_object_id", + "return_type": "uint64_t", + "arguments": [ + ["const godot_signal *", "p_self"] + ] + }, + { + "name": "godot_signal_get_name", + "return_type": "godot_string_name", + "arguments": [ + ["const godot_signal *", "p_self"] + ] + }, + { + "name": "godot_signal_as_string", + "return_type": "godot_string", + "arguments": [ + ["const godot_signal *", "p_self"] + ] + }, + { + "name": "godot_signal_operator_equal", + "return_type": "godot_bool", + "arguments": [ + ["const godot_signal *", "p_self"], + ["const godot_signal *", "p_other"] + ] + }, + { + "name": "godot_signal_operator_less", + "return_type": "godot_bool", + "arguments": [ + ["const godot_signal *", "p_self"], + ["const godot_signal *", "p_other"] + ] + }, + { + "name": "godot_packed_int64_array_new", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "r_dest"] + ] + }, + { + "name": "godot_packed_int64_array_new_copy", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "r_dest"], + ["const godot_packed_int64_array *", "p_src"] + ] + }, + { + "name": "godot_packed_int64_array_new_with_array", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "r_dest"], + ["const godot_array *", "p_a"] + ] + }, + { + "name": "godot_packed_int64_array_append", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "p_self"], + ["const int64_t", "p_data"] + ] + }, + { + "name": "godot_packed_int64_array_append_array", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "p_self"], + ["const godot_packed_int64_array *", "p_array"] + ] + }, + { + "name": "godot_packed_int64_array_insert", + "return_type": "godot_error", + "arguments": [ + ["godot_packed_int64_array *", "p_self"], + ["const godot_int", "p_idx"], + ["const int64_t", "p_data"] + ] + }, + { + "name": "godot_packed_int64_array_invert", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "p_self"] + ] + }, + { + "name": "godot_packed_int64_array_push_back", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "p_self"], + ["const int64_t", "p_data"] + ] + }, + { + "name": "godot_packed_int64_array_remove", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "p_self"], + ["const godot_int", "p_idx"] + ] + }, + { + "name": "godot_packed_int64_array_resize", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "p_self"], + ["const godot_int", "p_size"] + ] + }, + { + "name": "godot_packed_int64_array_set", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "p_self"], + ["const godot_int", "p_idx"], + ["const int64_t", "p_data"] + ] + }, + { + "name": "godot_packed_int64_array_get", + "return_type": "int64_t", + "arguments": [ + ["const godot_packed_int64_array *", "p_self"], + ["const godot_int", "p_idx"] + ] + }, + { + "name": "godot_packed_int64_array_size", + "return_type": "godot_int", + "arguments": [ + ["const godot_packed_int64_array *", "p_self"] + ] + }, + { + "name": "godot_packed_int64_array_destroy", + "return_type": "void", + "arguments": [ + ["godot_packed_int64_array *", "p_self"] + ] + }, + { + "name": "godot_packed_float64_array_new", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "r_dest"] + ] + }, + { + "name": "godot_packed_float64_array_new_copy", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "r_dest"], + ["const godot_packed_float64_array *", "p_src"] + ] + }, + { + "name": "godot_packed_float64_array_new_with_array", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "r_dest"], + ["const godot_array *", "p_a"] + ] + }, + { + "name": "godot_packed_float64_array_append", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "p_self"], + ["const double", "p_data"] + ] + }, + { + "name": "godot_packed_float64_array_append_array", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "p_self"], + ["const godot_packed_float64_array *", "p_array"] + ] + }, + { + "name": "godot_packed_float64_array_insert", + "return_type": "godot_error", + "arguments": [ + ["godot_packed_float64_array *", "p_self"], + ["const godot_int", "p_idx"], + ["const double", "p_data"] + ] + }, + { + "name": "godot_packed_float64_array_invert", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "p_self"] + ] + }, + { + "name": "godot_packed_float64_array_push_back", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "p_self"], + ["const double", "p_data"] + ] + }, + { + "name": "godot_packed_float64_array_remove", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "p_self"], + ["const godot_int", "p_idx"] + ] + }, + { + "name": "godot_packed_float64_array_resize", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "p_self"], + ["const godot_int", "p_size"] + ] + }, + { + "name": "godot_packed_float64_array_set", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "p_self"], + ["const godot_int", "p_idx"], + ["const double", "p_data"] + ] + }, + { + "name": "godot_packed_float64_array_get", + "return_type": "double", + "arguments": [ + ["const godot_packed_float64_array *", "p_self"], + ["const godot_int", "p_idx"] + ] + }, + { + "name": "godot_packed_float64_array_size", + "return_type": "godot_int", + "arguments": [ + ["const godot_packed_float64_array *", "p_self"] + ] + }, + { + "name": "godot_packed_float64_array_destroy", + "return_type": "void", + "arguments": [ + ["godot_packed_float64_array *", "p_self"] + ] + }, + { + "name": "godot_rect2_as_rect2i", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_rect2 *", "p_self"] + ] + }, + { + "name": "godot_rect2i_new_with_position_and_size", + "return_type": "void", + "arguments": [ + ["godot_rect2i *", "r_dest"], + ["const godot_vector2i *", "p_pos"], + ["const godot_vector2i *", "p_size"] + ] + }, + { + "name": "godot_rect2i_new", + "return_type": "void", + "arguments": [ + ["godot_rect2i *", "r_dest"], + ["const godot_int", "p_x"], + ["const godot_int", "p_y"], + ["const godot_int", "p_width"], + ["const godot_int", "p_height"] + ] + }, + { + "name": "godot_rect2i_as_string", + "return_type": "godot_string", + "arguments": [ + ["const godot_rect2i *", "p_self"] + ] + }, + { + "name": "godot_rect2i_as_rect2", + "return_type": "godot_rect2", + "arguments": [ + ["const godot_rect2i *", "p_self"] + ] + }, + { + "name": "godot_rect2i_get_area", + "return_type": "godot_int", + "arguments": [ + ["const godot_rect2i *", "p_self"] + ] + }, + { + "name": "godot_rect2i_intersects", + "return_type": "godot_bool", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_rect2i *", "p_b"] + ] + }, + { + "name": "godot_rect2i_encloses", + "return_type": "godot_bool", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_rect2i *", "p_b"] + ] + }, + { + "name": "godot_rect2i_has_no_area", + "return_type": "godot_bool", + "arguments": [ + ["const godot_rect2i *", "p_self"] + ] + }, + { + "name": "godot_rect2i_clip", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_rect2i *", "p_b"] + ] + }, + { + "name": "godot_rect2i_merge", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_rect2i *", "p_b"] + ] + }, + { + "name": "godot_rect2i_has_point", + "return_type": "godot_bool", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_vector2i *", "p_point"] + ] + }, + { + "name": "godot_rect2i_grow", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_int", "p_by"] + ] + }, + { + "name": "godot_rect2i_grow_individual", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_int", "p_left"], + ["const godot_int", "p_top"], + ["const godot_int", "p_right"], + ["const godot_int", "p_bottom"] + ] + }, + { + "name": "godot_rect2i_grow_margin", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_int", "p_margin"], + ["const godot_int", "p_by"] + ] + }, + { + "name": "godot_rect2i_abs", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_rect2i *", "p_self"] + ] + }, + { + "name": "godot_rect2i_expand", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_vector2i *", "p_to"] + ] + }, + { + "name": "godot_rect2i_operator_equal", + "return_type": "godot_bool", + "arguments": [ + ["const godot_rect2i *", "p_self"], + ["const godot_rect2i *", "p_b"] + ] + }, + { + "name": "godot_rect2i_get_position", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_rect2i *", "p_self"] + ] + }, + { + "name": "godot_rect2i_get_size", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_rect2i *", "p_self"] + ] + }, + { + "name": "godot_rect2i_set_position", + "return_type": "void", + "arguments": [ + ["godot_rect2i *", "p_self"], + ["const godot_vector2i *", "p_pos"] + ] + }, + { + "name": "godot_rect2i_set_size", + "return_type": "void", + "arguments": [ + ["godot_rect2i *", "p_self"], + ["const godot_vector2i *", "p_size"] + ] + }, + { + "name": "godot_variant_new_string_name", + "return_type": "void", + "arguments": [ + ["godot_variant *", "r_dest"], + ["const godot_string_name *", "p_s"] + ] + }, + { + "name": "godot_variant_new_vector2i", + "return_type": "void", + "arguments": [ + ["godot_variant *", "r_dest"], + ["const godot_vector2i *", "p_v2"] + ] + }, + { + "name": "godot_variant_new_rect2i", + "return_type": "void", + "arguments": [ + ["godot_variant *", "r_dest"], + ["const godot_rect2i *", "p_rect2"] + ] + }, + { + "name": "godot_variant_new_vector3i", + "return_type": "void", + "arguments": [ + ["godot_variant *", "r_dest"], + ["const godot_vector3i *", "p_v3"] + ] + }, + { + "name": "godot_variant_new_callable", + "return_type": "void", + "arguments": [ + ["godot_variant *", "r_dest"], + ["const godot_callable *", "p_cb"] + ] + }, + { + "name": "godot_variant_new_signal", + "return_type": "void", + "arguments": [ + ["godot_variant *", "r_dest"], + ["const godot_signal *", "p_signal"] + ] + }, + { + "name": "godot_variant_new_packed_int64_array", + "return_type": "void", + "arguments": [ + ["godot_variant *", "r_dest"], + ["const godot_packed_int64_array *", "p_pia"] + ] + }, + { + "name": "godot_variant_new_packed_float64_array", + "return_type": "void", + "arguments": [ + ["godot_variant *", "r_dest"], + ["const godot_packed_float64_array *", "p_pra"] + ] + }, + { + "name": "godot_variant_as_string_name", + "return_type": "godot_string_name", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_variant_as_vector2i", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_variant_as_rect2i", + "return_type": "godot_rect2i", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_variant_as_vector3i", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_variant_as_callable", + "return_type": "godot_callable", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_variant_as_signal", + "return_type": "godot_signal", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_variant_as_packed_int64_array", + "return_type": "godot_packed_int64_array", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_variant_as_packed_float64_array", + "return_type": "godot_packed_float64_array", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_variant_hash", + "return_type": "uint32_t", + "arguments": [ + ["const godot_variant *", "p_self"] + ] + }, + { + "name": "godot_vector2_as_vector2i", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2 *", "p_self"] + ] + }, + { + "name": "godot_vector2_sign", + "return_type": "godot_vector2", + "arguments": [ + ["const godot_vector2 *", "p_self"] + ] + }, + { + "name": "godot_vector2i_new", + "return_type": "void", + "arguments": [ + ["godot_vector2i *", "r_dest"], + ["const godot_int", "p_x"], + ["const godot_int", "p_y"] + ] + }, + { + "name": "godot_vector2i_as_string", + "return_type": "godot_string", + "arguments": [ + ["const godot_vector2i *", "p_self"] + ] + }, + { + "name": "godot_vector2i_as_vector2", + "return_type": "godot_vector2", + "arguments": [ + ["const godot_vector2i *", "p_self"] + ] + }, + { + "name": "godot_vector2i_aspect", + "return_type": "godot_real", + "arguments": [ + ["const godot_vector2i *", "p_self"] + ] + }, + { + "name": "godot_vector2i_abs", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"] + ] + }, + { + "name": "godot_vector2i_sign", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"] + ] + }, + { + "name": "godot_vector2i_operator_add", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"], + ["const godot_vector2i *", "p_b"] + ] + }, + { + "name": "godot_vector2i_operator_subtract", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"], + ["const godot_vector2i *", "p_b"] + ] + }, + { + "name": "godot_vector2i_operator_multiply_vector", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"], + ["const godot_vector2i *", "p_b"] + ] + }, + { + "name": "godot_vector2i_operator_multiply_scalar", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"], + ["const godot_int", "p_b"] + ] + }, + { + "name": "godot_vector2i_operator_divide_vector", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"], + ["const godot_vector2i *", "p_b"] + ] + }, + { + "name": "godot_vector2i_operator_divide_scalar", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"], + ["const godot_int", "p_b"] + ] + }, + { + "name": "godot_vector2i_operator_equal", + "return_type": "godot_bool", + "arguments": [ + ["const godot_vector2i *", "p_self"], + ["const godot_vector2i *", "p_b"] + ] + }, + { + "name": "godot_vector2i_operator_less", + "return_type": "godot_bool", + "arguments": [ + ["const godot_vector2i *", "p_self"], + ["const godot_vector2i *", "p_b"] + ] + }, + { + "name": "godot_vector2i_operator_neg", + "return_type": "godot_vector2i", + "arguments": [ + ["const godot_vector2i *", "p_self"] + ] + }, + { + "name": "godot_vector2i_set_x", + "return_type": "void", + "arguments": [ + ["godot_vector2i *", "p_self"], + ["const godot_int", "p_x"] + ] + }, + { + "name": "godot_vector2i_set_y", + "return_type": "void", + "arguments": [ + ["godot_vector2i *", "p_self"], + ["const godot_int", "p_y"] + ] + }, + { + "name": "godot_vector2i_get_x", + "return_type": "godot_int", + "arguments": [ + ["const godot_vector2i *", "p_self"] + ] + }, + { + "name": "godot_vector2i_get_y", + "return_type": "godot_int", + "arguments": [ + ["const godot_vector2i *", "p_self"] + ] + }, + { + "name": "godot_vector3_as_vector3i", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3 *", "p_self"] + ] + }, + { + "name": "godot_vector3_sign", + "return_type": "godot_vector3", + "arguments": [ + ["const godot_vector3 *", "p_self"] + ] + }, + { + "name": "godot_vector3i_new", + "return_type": "void", + "arguments": [ + ["godot_vector3i *", "r_dest"], + ["const godot_int", "p_x"], + ["const godot_int", "p_y"], + ["const godot_int", "p_z"] + ] + }, + { + "name": "godot_vector3i_as_string", + "return_type": "godot_string", + "arguments": [ + ["const godot_vector3i *", "p_self"] + ] + }, + { + "name": "godot_vector3i_as_vector3", + "return_type": "godot_vector3", + "arguments": [ + ["const godot_vector3i *", "p_self"] + ] + }, + { + "name": "godot_vector3i_min_axis", + "return_type": "godot_int", + "arguments": [ + ["const godot_vector3i *", "p_self"] + ] + }, + { + "name": "godot_vector3i_max_axis", + "return_type": "godot_int", + "arguments": [ + ["const godot_vector3i *", "p_self"] + ] + }, + { + "name": "godot_vector3i_abs", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"] + ] + }, + { + "name": "godot_vector3i_sign", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"] + ] + }, + { + "name": "godot_vector3i_operator_add", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_vector3i *", "p_b"] + ] + }, + { + "name": "godot_vector3i_operator_subtract", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_vector3i *", "p_b"] + ] + }, + { + "name": "godot_vector3i_operator_multiply_vector", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_vector3i *", "p_b"] + ] + }, + { + "name": "godot_vector3i_operator_multiply_scalar", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_int", "p_b"] + ] + }, + { + "name": "godot_vector3i_operator_divide_vector", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_vector3i *", "p_b"] + ] + }, + { + "name": "godot_vector3i_operator_divide_scalar", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_int", "p_b"] + ] + }, + { + "name": "godot_vector3i_operator_equal", + "return_type": "godot_bool", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_vector3i *", "p_b"] + ] + }, + { + "name": "godot_vector3i_operator_less", + "return_type": "godot_bool", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_vector3i *", "p_b"] + ] + }, + { + "name": "godot_vector3i_operator_neg", + "return_type": "godot_vector3i", + "arguments": [ + ["const godot_vector3i *", "p_self"] + ] + }, + { + "name": "godot_vector3i_set_axis", + "return_type": "void", + "arguments": [ + ["godot_vector3i *", "p_self"], + ["const godot_vector3_axis", "p_axis"], + ["const godot_int", "p_val"] + ] + }, + { + "name": "godot_vector3i_get_axis", + "return_type": "godot_int", + "arguments": [ + ["const godot_vector3i *", "p_self"], + ["const godot_vector3_axis", "p_axis"] + ] + } + ] + }, "api": [ { "name": "godot_dictionary_duplicate", @@ -100,17 +1218,17 @@ ] }, { - "name": "godot_packed_int_array_empty", + "name": "godot_packed_int32_array_empty", "return_type": "godot_bool", "arguments": [ - ["const godot_packed_int_array *", "p_self"] + ["const godot_packed_int32_array *", "p_self"] ] }, { - "name": "godot_packed_real_array_empty", + "name": "godot_packed_float32_array_empty", "return_type": "godot_bool", "arguments": [ - ["const godot_packed_real_array *", "p_self"] + ["const godot_packed_float32_array *", "p_self"] ] }, { @@ -160,7 +1278,7 @@ "name": "godot_instance_from_id", "return_type": "godot_object *", "arguments": [ - ["godot_int", "p_instance_id"] + ["uint64_t", "p_instance_id"] ] } ] @@ -586,7 +1704,7 @@ ] }, { - "name": "godot_color_linear_interpolate", + "name": "godot_color_lerp", "return_type": "godot_color", "arguments": [ ["const godot_color *", "p_self"], @@ -710,7 +1828,7 @@ ] }, { - "name": "godot_vector2_linear_interpolate", + "name": "godot_vector2_lerp", "return_type": "godot_vector2", "arguments": [ ["const godot_vector2 *", "p_self"], @@ -1449,7 +2567,7 @@ ] }, { - "name": "godot_vector3_linear_interpolate", + "name": "godot_vector3_lerp", "return_type": "godot_vector3", "arguments": [ ["const godot_vector3 *", "p_self"], @@ -1767,223 +2885,223 @@ ] }, { - "name": "godot_packed_int_array_new", + "name": "godot_packed_int32_array_new", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "r_dest"] + ["godot_packed_int32_array *", "r_dest"] ] }, { - "name": "godot_packed_int_array_new_copy", + "name": "godot_packed_int32_array_new_copy", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "r_dest"], - ["const godot_packed_int_array *", "p_src"] + ["godot_packed_int32_array *", "r_dest"], + ["const godot_packed_int32_array *", "p_src"] ] }, { - "name": "godot_packed_int_array_new_with_array", + "name": "godot_packed_int32_array_new_with_array", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "r_dest"], + ["godot_packed_int32_array *", "r_dest"], ["const godot_array *", "p_a"] ] }, { - "name": "godot_packed_int_array_append", + "name": "godot_packed_int32_array_append", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "p_self"], - ["const godot_int", "p_data"] + ["godot_packed_int32_array *", "p_self"], + ["const int32_t", "p_data"] ] }, { - "name": "godot_packed_int_array_append_array", + "name": "godot_packed_int32_array_append_array", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "p_self"], - ["const godot_packed_int_array *", "p_array"] + ["godot_packed_int32_array *", "p_self"], + ["const godot_packed_int32_array *", "p_array"] ] }, { - "name": "godot_packed_int_array_insert", + "name": "godot_packed_int32_array_insert", "return_type": "godot_error", "arguments": [ - ["godot_packed_int_array *", "p_self"], + ["godot_packed_int32_array *", "p_self"], ["const godot_int", "p_idx"], - ["const godot_int", "p_data"] + ["const int32_t", "p_data"] ] }, { - "name": "godot_packed_int_array_invert", + "name": "godot_packed_int32_array_invert", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "p_self"] + ["godot_packed_int32_array *", "p_self"] ] }, { - "name": "godot_packed_int_array_push_back", + "name": "godot_packed_int32_array_push_back", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "p_self"], - ["const godot_int", "p_data"] + ["godot_packed_int32_array *", "p_self"], + ["const int32_t", "p_data"] ] }, { - "name": "godot_packed_int_array_remove", + "name": "godot_packed_int32_array_remove", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "p_self"], + ["godot_packed_int32_array *", "p_self"], ["const godot_int", "p_idx"] ] }, { - "name": "godot_packed_int_array_resize", + "name": "godot_packed_int32_array_resize", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "p_self"], + ["godot_packed_int32_array *", "p_self"], ["const godot_int", "p_size"] ] }, { - "name": "godot_packed_int_array_set", + "name": "godot_packed_int32_array_set", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "p_self"], + ["godot_packed_int32_array *", "p_self"], ["const godot_int", "p_idx"], - ["const godot_int", "p_data"] + ["const int32_t", "p_data"] ] }, { - "name": "godot_packed_int_array_get", - "return_type": "godot_int", + "name": "godot_packed_int32_array_get", + "return_type": "int32_t", "arguments": [ - ["const godot_packed_int_array *", "p_self"], + ["const godot_packed_int32_array *", "p_self"], ["const godot_int", "p_idx"] ] }, { - "name": "godot_packed_int_array_size", + "name": "godot_packed_int32_array_size", "return_type": "godot_int", "arguments": [ - ["const godot_packed_int_array *", "p_self"] + ["const godot_packed_int32_array *", "p_self"] ] }, { - "name": "godot_packed_int_array_destroy", + "name": "godot_packed_int32_array_destroy", "return_type": "void", "arguments": [ - ["godot_packed_int_array *", "p_self"] + ["godot_packed_int32_array *", "p_self"] ] }, { - "name": "godot_packed_real_array_new", + "name": "godot_packed_float32_array_new", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "r_dest"] + ["godot_packed_float32_array *", "r_dest"] ] }, { - "name": "godot_packed_real_array_new_copy", + "name": "godot_packed_float32_array_new_copy", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "r_dest"], - ["const godot_packed_real_array *", "p_src"] + ["godot_packed_float32_array *", "r_dest"], + ["const godot_packed_float32_array *", "p_src"] ] }, { - "name": "godot_packed_real_array_new_with_array", + "name": "godot_packed_float32_array_new_with_array", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "r_dest"], + ["godot_packed_float32_array *", "r_dest"], ["const godot_array *", "p_a"] ] }, { - "name": "godot_packed_real_array_append", + "name": "godot_packed_float32_array_append", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "p_self"], - ["const godot_real", "p_data"] + ["godot_packed_float32_array *", "p_self"], + ["const float", "p_data"] ] }, { - "name": "godot_packed_real_array_append_array", + "name": "godot_packed_float32_array_append_array", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "p_self"], - ["const godot_packed_real_array *", "p_array"] + ["godot_packed_float32_array *", "p_self"], + ["const godot_packed_float32_array *", "p_array"] ] }, { - "name": "godot_packed_real_array_insert", + "name": "godot_packed_float32_array_insert", "return_type": "godot_error", "arguments": [ - ["godot_packed_real_array *", "p_self"], + ["godot_packed_float32_array *", "p_self"], ["const godot_int", "p_idx"], - ["const godot_real", "p_data"] + ["const float", "p_data"] ] }, { - "name": "godot_packed_real_array_invert", + "name": "godot_packed_float32_array_invert", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "p_self"] + ["godot_packed_float32_array *", "p_self"] ] }, { - "name": "godot_packed_real_array_push_back", + "name": "godot_packed_float32_array_push_back", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "p_self"], - ["const godot_real", "p_data"] + ["godot_packed_float32_array *", "p_self"], + ["const float", "p_data"] ] }, { - "name": "godot_packed_real_array_remove", + "name": "godot_packed_float32_array_remove", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "p_self"], + ["godot_packed_float32_array *", "p_self"], ["const godot_int", "p_idx"] ] }, { - "name": "godot_packed_real_array_resize", + "name": "godot_packed_float32_array_resize", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "p_self"], + ["godot_packed_float32_array *", "p_self"], ["const godot_int", "p_size"] ] }, { - "name": "godot_packed_real_array_set", + "name": "godot_packed_float32_array_set", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "p_self"], + ["godot_packed_float32_array *", "p_self"], ["const godot_int", "p_idx"], - ["const godot_real", "p_data"] + ["const float", "p_data"] ] }, { - "name": "godot_packed_real_array_get", - "return_type": "godot_real", + "name": "godot_packed_float32_array_get", + "return_type": "float", "arguments": [ - ["const godot_packed_real_array *", "p_self"], + ["const godot_packed_float32_array *", "p_self"], ["const godot_int", "p_idx"] ] }, { - "name": "godot_packed_real_array_size", + "name": "godot_packed_float32_array_size", "return_type": "godot_int", "arguments": [ - ["const godot_packed_real_array *", "p_self"] + ["const godot_packed_float32_array *", "p_self"] ] }, { - "name": "godot_packed_real_array_destroy", + "name": "godot_packed_float32_array_destroy", "return_type": "void", "arguments": [ - ["godot_packed_real_array *", "p_self"] + ["godot_packed_float32_array *", "p_self"] ] }, { @@ -2474,19 +3592,19 @@ ] }, { - "name": "godot_array_new_packed_real_array", + "name": "godot_array_new_packed_float32_array", "return_type": "void", "arguments": [ ["godot_array *", "r_dest"], - ["const godot_packed_real_array *", "p_pra"] + ["const godot_packed_float32_array *", "p_pra"] ] }, { - "name": "godot_array_new_packed_int_array", + "name": "godot_array_new_packed_int32_array", "return_type": "void", "arguments": [ ["godot_array *", "r_dest"], - ["const godot_packed_int_array *", "p_pia"] + ["const godot_packed_int32_array *", "p_pia"] ] }, { @@ -4059,19 +5177,19 @@ ] }, { - "name": "godot_variant_new_packed_int_array", + "name": "godot_variant_new_packed_int32_array", "return_type": "void", "arguments": [ ["godot_variant *", "r_dest"], - ["const godot_packed_int_array *", "p_pia"] + ["const godot_packed_int32_array *", "p_pia"] ] }, { - "name": "godot_variant_new_packed_real_array", + "name": "godot_variant_new_packed_float32_array", "return_type": "void", "arguments": [ ["godot_variant *", "r_dest"], - ["const godot_packed_real_array *", "p_pra"] + ["const godot_packed_float32_array *", "p_pra"] ] }, { @@ -4254,15 +5372,15 @@ ] }, { - "name": "godot_variant_as_packed_int_array", - "return_type": "godot_packed_int_array", + "name": "godot_variant_as_packed_int32_array", + "return_type": "godot_packed_int32_array", "arguments": [ ["const godot_variant *", "p_self"] ] }, { - "name": "godot_variant_as_packed_real_array", - "return_type": "godot_packed_real_array", + "name": "godot_variant_as_packed_float32_array", + "return_type": "godot_packed_float32_array", "arguments": [ ["const godot_variant *", "p_self"] ] @@ -5869,7 +6987,7 @@ "arguments": [ ["void *", "p_gdnative_handle"], ["const char *", "p_name"], - ["const godot_signal *", "p_signal"] + ["const godot_nativescript_signal *", "p_signal"] ] }, { @@ -5935,8 +7053,8 @@ ] }, { - "name": "arvr", - "type": "ARVR", + "name": "xr", + "type": "XR", "version": { "major": 1, "minor": 1 @@ -5944,24 +7062,24 @@ "next": null, "api": [ { - "name": "godot_arvr_register_interface", + "name": "godot_xr_register_interface", "return_type": "void", "arguments": [ - ["const godot_arvr_interface_gdnative *", "p_interface"] + ["const godot_xr_interface_gdnative *", "p_interface"] ] }, { - "name": "godot_arvr_get_worldscale", + "name": "godot_xr_get_worldscale", "return_type": "godot_real", "arguments": [] }, { - "name": "godot_arvr_get_reference_frame", + "name": "godot_xr_get_reference_frame", "return_type": "godot_transform", "arguments": [] }, { - "name": "godot_arvr_blit", + "name": "godot_xr_blit", "return_type": "void", "arguments": [ ["godot_int", "p_eye"], @@ -5970,14 +7088,14 @@ ] }, { - "name": "godot_arvr_get_texid", + "name": "godot_xr_get_texid", "return_type": "godot_int", "arguments": [ ["godot_rid *", "p_render_target"] ] }, { - "name": "godot_arvr_add_controller", + "name": "godot_xr_add_controller", "return_type": "godot_int", "arguments": [ ["char *", "p_device_name"], @@ -5987,14 +7105,14 @@ ] }, { - "name": "godot_arvr_remove_controller", + "name": "godot_xr_remove_controller", "return_type": "void", "arguments": [ ["godot_int", "p_controller_id"] ] }, { - "name": "godot_arvr_set_controller_transform", + "name": "godot_xr_set_controller_transform", "return_type": "void", "arguments": [ ["godot_int", "p_controller_id"], @@ -6004,7 +7122,7 @@ ] }, { - "name": "godot_arvr_set_controller_button", + "name": "godot_xr_set_controller_button", "return_type": "void", "arguments": [ ["godot_int", "p_controller_id"], @@ -6013,7 +7131,7 @@ ] }, { - "name": "godot_arvr_set_controller_axis", + "name": "godot_xr_set_controller_axis", "return_type": "void", "arguments": [ ["godot_int", "p_controller_id"], @@ -6023,7 +7141,7 @@ ] }, { - "name": "godot_arvr_get_controller_rumble", + "name": "godot_xr_get_controller_rumble", "return_type": "godot_real", "arguments": [ ["godot_int", "p_controller_id"] diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py index 0d95a65b7e..620935795f 100644 --- a/modules/gdnative/gdnative_builders.py +++ b/modules/gdnative/gdnative_builders.py @@ -8,209 +8,249 @@ from platform_methods import subprocess_main def _spaced(e): - return e if e[-1] == '*' else e + ' ' + return e if e[-1] == "*" else e + " " def _build_gdnative_api_struct_header(api): out = [ - '/* THIS FILE IS GENERATED DO NOT EDIT */', - '#ifndef GODOT_GDNATIVE_API_STRUCT_H', - '#define GODOT_GDNATIVE_API_STRUCT_H', - '', - '#include <gdnative/gdnative.h>', - '#include <android/godot_android.h>', - '#include <arvr/godot_arvr.h>', - '#include <nativescript/godot_nativescript.h>', - '#include <net/godot_net.h>', - '#include <pluginscript/godot_pluginscript.h>', - '#include <videodecoder/godot_videodecoder.h>', - '', - '#ifdef __cplusplus', + "/* THIS FILE IS GENERATED DO NOT EDIT */", + "#ifndef GODOT_GDNATIVE_API_STRUCT_H", + "#define GODOT_GDNATIVE_API_STRUCT_H", + "", + "#include <gdnative/gdnative.h>", + "#include <android/godot_android.h>", + "#include <xr/godot_xr.h>", + "#include <nativescript/godot_nativescript.h>", + "#include <net/godot_net.h>", + "#include <pluginscript/godot_pluginscript.h>", + "#include <videodecoder/godot_videodecoder.h>", + "", + "#ifdef __cplusplus", 'extern "C" {', - '#endif', - '', - 'enum GDNATIVE_API_TYPES {', - '\tGDNATIVE_' + api['core']['type'] + ',' + "#endif", + "", + "enum GDNATIVE_API_TYPES {", + "\tGDNATIVE_" + api["core"]["type"] + ",", ] - for ext in api['extensions']: - out += ['\tGDNATIVE_EXT_' + ext['type'] + ','] + for ext in api["extensions"]: + out += ["\tGDNATIVE_EXT_" + ext["type"] + ","] - out += ['};', ''] + out += ["};", ""] def generate_extension_struct(name, ext, include_version=True): ret_val = [] - if ext['next']: - ret_val += generate_extension_struct(name, ext['next']) + if ext["next"]: + ret_val += generate_extension_struct(name, ext["next"]) ret_val += [ - 'typedef struct godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct {', - '\tunsigned int type;', - '\tgodot_gdnative_api_version version;', - '\tconst godot_gdnative_api_struct *next;' + "typedef struct godot_gdnative_ext_" + + name + + ("" if not include_version else ("_{0}_{1}".format(ext["version"]["major"], ext["version"]["minor"]))) + + "_api_struct {", + "\tunsigned int type;", + "\tgodot_gdnative_api_version version;", + "\tconst godot_gdnative_api_struct *next;", ] - for funcdef in ext['api']: - args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) - ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args)) + for funcdef in ext["api"]: + args = ", ".join(["%s%s" % (_spaced(t), n) for t, n in funcdef["arguments"]]) + ret_val.append("\t%s(*%s)(%s);" % (_spaced(funcdef["return_type"]), funcdef["name"], args)) - ret_val += ['} godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct;', ''] + ret_val += [ + "} godot_gdnative_ext_" + + name + + ("" if not include_version else ("_{0}_{1}".format(ext["version"]["major"], ext["version"]["minor"]))) + + "_api_struct;", + "", + ] return ret_val - def generate_core_extension_struct(core): ret_val = [] - if core['next']: - ret_val += generate_core_extension_struct(core['next']) + if core["next"]: + ret_val += generate_core_extension_struct(core["next"]) ret_val += [ - 'typedef struct godot_gdnative_core_' + ('{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + '_api_struct {', - '\tunsigned int type;', - '\tgodot_gdnative_api_version version;', - '\tconst godot_gdnative_api_struct *next;', + "typedef struct godot_gdnative_core_" + + ("{0}_{1}".format(core["version"]["major"], core["version"]["minor"])) + + "_api_struct {", + "\tunsigned int type;", + "\tgodot_gdnative_api_version version;", + "\tconst godot_gdnative_api_struct *next;", ] - for funcdef in core['api']: - args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) - ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args)) + for funcdef in core["api"]: + args = ", ".join(["%s%s" % (_spaced(t), n) for t, n in funcdef["arguments"]]) + ret_val.append("\t%s(*%s)(%s);" % (_spaced(funcdef["return_type"]), funcdef["name"], args)) - ret_val += ['} godot_gdnative_core_' + '{0}_{1}'.format(core['version']['major'], core['version']['minor']) + '_api_struct;', ''] + ret_val += [ + "} godot_gdnative_core_" + + "{0}_{1}".format(core["version"]["major"], core["version"]["minor"]) + + "_api_struct;", + "", + ] return ret_val - - for ext in api['extensions']: - name = ext['name'] + for ext in api["extensions"]: + name = ext["name"] out += generate_extension_struct(name, ext, False) - if api['core']['next']: - out += generate_core_extension_struct(api['core']['next']) + if api["core"]["next"]: + out += generate_core_extension_struct(api["core"]["next"]) out += [ - 'typedef struct godot_gdnative_core_api_struct {', - '\tunsigned int type;', - '\tgodot_gdnative_api_version version;', - '\tconst godot_gdnative_api_struct *next;', - '\tunsigned int num_extensions;', - '\tconst godot_gdnative_api_struct **extensions;', + "typedef struct godot_gdnative_core_api_struct {", + "\tunsigned int type;", + "\tgodot_gdnative_api_version version;", + "\tconst godot_gdnative_api_struct *next;", + "\tunsigned int num_extensions;", + "\tconst godot_gdnative_api_struct **extensions;", ] - for funcdef in api['core']['api']: - args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) - out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args)) + for funcdef in api["core"]["api"]: + args = ", ".join(["%s%s" % (_spaced(t), n) for t, n in funcdef["arguments"]]) + out.append("\t%s(*%s)(%s);" % (_spaced(funcdef["return_type"]), funcdef["name"], args)) out += [ - '} godot_gdnative_core_api_struct;', - '', - '#ifdef __cplusplus', - '}', - '#endif', - '', - '#endif // GODOT_GDNATIVE_API_STRUCT_H', - '' + "} godot_gdnative_core_api_struct;", + "", + "#ifdef __cplusplus", + "}", + "#endif", + "", + "#endif // GODOT_GDNATIVE_API_STRUCT_H", + "", ] - return '\n'.join(out) + return "\n".join(out) def _build_gdnative_api_struct_source(api): - out = [ - '/* THIS FILE IS GENERATED DO NOT EDIT */', - '', - '#include <gdnative_api_struct.gen.h>', - '' - ] + out = ["/* THIS FILE IS GENERATED DO NOT EDIT */", "", "#include <gdnative_api_struct.gen.h>", ""] def get_extension_struct_name(name, ext, include_version=True): - return 'godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct' + return ( + "godot_gdnative_ext_" + + name + + ("" if not include_version else ("_{0}_{1}".format(ext["version"]["major"], ext["version"]["minor"]))) + + "_api_struct" + ) def get_extension_struct_instance_name(name, ext, include_version=True): - return 'api_extension_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_struct' + return ( + "api_extension_" + + name + + ("" if not include_version else ("_{0}_{1}".format(ext["version"]["major"], ext["version"]["minor"]))) + + "_struct" + ) def get_extension_struct_definition(name, ext, include_version=True): ret_val = [] - if ext['next']: - ret_val += get_extension_struct_definition(name, ext['next']) + if ext["next"]: + ret_val += get_extension_struct_definition(name, ext["next"]) ret_val += [ - 'extern const ' + get_extension_struct_name(name, ext, include_version) + ' ' + get_extension_struct_instance_name(name, ext, include_version) + ' = {', - '\tGDNATIVE_EXT_' + ext['type'] + ',', - '\t{' + str(ext['version']['major']) + ', ' + str(ext['version']['minor']) + '},', - '\t' + ('NULL' if not ext['next'] else ('(const godot_gdnative_api_struct *)&' + get_extension_struct_instance_name(name, ext['next']))) + ',' + "extern const " + + get_extension_struct_name(name, ext, include_version) + + " " + + get_extension_struct_instance_name(name, ext, include_version) + + " = {", + "\tGDNATIVE_EXT_" + ext["type"] + ",", + "\t{" + str(ext["version"]["major"]) + ", " + str(ext["version"]["minor"]) + "},", + "\t" + + ( + "nullptr" + if not ext["next"] + else ("(const godot_gdnative_api_struct *)&" + get_extension_struct_instance_name(name, ext["next"])) + ) + + ",", ] - for funcdef in ext['api']: - ret_val.append('\t%s,' % funcdef['name']) + for funcdef in ext["api"]: + ret_val.append("\t%s," % funcdef["name"]) - ret_val += ['};\n'] + ret_val += ["};\n"] return ret_val - def get_core_struct_definition(core): ret_val = [] - if core['next']: - ret_val += get_core_struct_definition(core['next']) + if core["next"]: + ret_val += get_core_struct_definition(core["next"]) ret_val += [ - 'extern const godot_gdnative_core_' + ('{0}_{1}_api_struct api_{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + ' = {', - '\tGDNATIVE_' + core['type'] + ',', - '\t{' + str(core['version']['major']) + ', ' + str(core['version']['minor']) + '},', - '\t' + ('NULL' if not core['next'] else ('(const godot_gdnative_api_struct *)& api_{0}_{1}'.format(core['next']['version']['major'], core['next']['version']['minor']))) + ',' + "extern const godot_gdnative_core_" + + ("{0}_{1}_api_struct api_{0}_{1}".format(core["version"]["major"], core["version"]["minor"])) + + " = {", + "\tGDNATIVE_" + core["type"] + ",", + "\t{" + str(core["version"]["major"]) + ", " + str(core["version"]["minor"]) + "},", + "\t" + + ( + "nullptr" + if not core["next"] + else ( + "(const godot_gdnative_api_struct *)& api_{0}_{1}".format( + core["next"]["version"]["major"], core["next"]["version"]["minor"] + ) + ) + ) + + ",", ] - for funcdef in core['api']: - ret_val.append('\t%s,' % funcdef['name']) + for funcdef in core["api"]: + ret_val.append("\t%s," % funcdef["name"]) - ret_val += ['};\n'] + ret_val += ["};\n"] return ret_val - for ext in api['extensions']: - name = ext['name'] + for ext in api["extensions"]: + name = ext["name"] out += get_extension_struct_definition(name, ext, False) - out += ['', 'const godot_gdnative_api_struct *gdnative_extensions_pointers[] = {'] + out += ["", "const godot_gdnative_api_struct *gdnative_extensions_pointers[] = {"] - for ext in api['extensions']: - name = ext['name'] - out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,'] + for ext in api["extensions"]: + name = ext["name"] + out += ["\t(godot_gdnative_api_struct *)&api_extension_" + name + "_struct,"] - out += ['};\n'] + out += ["};\n"] - if api['core']['next']: - out += get_core_struct_definition(api['core']['next']) + if api["core"]["next"]: + out += get_core_struct_definition(api["core"]["next"]) out += [ - 'extern const godot_gdnative_core_api_struct api_struct = {', - '\tGDNATIVE_' + api['core']['type'] + ',', - '\t{' + str(api['core']['version']['major']) + ', ' + str(api['core']['version']['minor']) + '},', - '\t(const godot_gdnative_api_struct *)&api_1_1,', - '\t' + str(len(api['extensions'])) + ',', - '\tgdnative_extensions_pointers,', + "extern const godot_gdnative_core_api_struct api_struct = {", + "\tGDNATIVE_" + api["core"]["type"] + ",", + "\t{" + str(api["core"]["version"]["major"]) + ", " + str(api["core"]["version"]["minor"]) + "},", + "\t(const godot_gdnative_api_struct *)&api_1_1,", + "\t" + str(len(api["extensions"])) + ",", + "\tgdnative_extensions_pointers,", ] - for funcdef in api['core']['api']: - out.append('\t%s,' % funcdef['name']) - out.append('};\n') + for funcdef in api["core"]["api"]: + out.append("\t%s," % funcdef["name"]) + out.append("};\n") - return '\n'.join(out) + return "\n".join(out) def build_gdnative_api_struct(target, source, env): - with open(source[0], 'r') as fd: + with open(source[0], "r") as fd: api = json.load(fd) header, source = target - with open(header, 'w') as fd: + with open(header, "w") as fd: fd.write(_build_gdnative_api_struct_header(api)) - with open(source, 'w') as fd: + with open(source, "w") as fd: fd.write(_build_gdnative_api_struct_source(api)) -if __name__ == '__main__': +if __name__ == "__main__": subprocess_main(globals()) diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp index db90199e63..2a9836329e 100644 --- a/modules/gdnative/gdnative_library_editor_plugin.cpp +++ b/modules/gdnative/gdnative_library_editor_plugin.cpp @@ -40,7 +40,6 @@ void GDNativeLibraryEditor::edit(Ref<GDNativeLibrary> p_library) { for (Map<String, NativePlatformConfig>::Element *E = platforms.front(); E; E = E->next()) { for (List<String>::Element *it = E->value().entries.front(); it; it = it->next()) { - String target = E->key() + "." + it->get(); TargetConfig ecfg; ecfg.library = config->get_value("entry", target, ""); @@ -56,14 +55,12 @@ void GDNativeLibraryEditor::_bind_methods() { } void GDNativeLibraryEditor::_update_tree() { - tree->clear(); TreeItem *root = tree->create_item(); PopupMenu *filter_list = filter->get_popup(); String text = ""; for (int i = 0; i < filter_list->get_item_count(); i++) { - if (!filter_list->is_item_checked(i)) { continue; } @@ -77,71 +74,69 @@ void GDNativeLibraryEditor::_update_tree() { platform->set_text(0, E->get().name); platform->set_metadata(0, E->get().library_extension); - platform->set_custom_bg_color(0, get_color("prop_category", "Editor")); - platform->set_custom_bg_color(1, get_color("prop_category", "Editor")); - platform->set_custom_bg_color(2, get_color("prop_category", "Editor")); + platform->set_custom_bg_color(0, get_theme_color("prop_category", "Editor")); + platform->set_custom_bg_color(1, get_theme_color("prop_category", "Editor")); + platform->set_custom_bg_color(2, get_theme_color("prop_category", "Editor")); platform->set_selectable(0, false); platform->set_expand_right(0, true); for (List<String>::Element *it = E->value().entries.front(); it; it = it->next()) { - String target = E->key() + "." + it->get(); TreeItem *bit = tree->create_item(platform); bit->set_text(0, it->get()); bit->set_metadata(0, target); bit->set_selectable(0, false); - bit->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); + bit->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor")); - bit->add_button(1, get_icon("Folder", "EditorIcons"), BUTTON_SELECT_LIBRARY, false, TTR("Select the dynamic library for this entry")); + bit->add_button(1, get_theme_icon("Folder", "EditorIcons"), BUTTON_SELECT_LIBRARY, false, TTR("Select the dynamic library for this entry")); String file = entry_configs[target].library; if (!file.empty()) { - bit->add_button(1, get_icon("Clear", "EditorIcons"), BUTTON_CLEAR_LIBRARY, false, TTR("Clear")); + bit->add_button(1, get_theme_icon("Clear", "EditorIcons"), BUTTON_CLEAR_LIBRARY, false, TTR("Clear")); } bit->set_text(1, file); - bit->add_button(2, get_icon("Folder", "EditorIcons"), BUTTON_SELECT_DEPENDENCES, false, TTR("Select dependencies of the library for this entry")); + bit->add_button(2, get_theme_icon("Folder", "EditorIcons"), BUTTON_SELECT_DEPENDENCES, false, TTR("Select dependencies of the library for this entry")); Array files = entry_configs[target].dependencies; if (files.size()) { - bit->add_button(2, get_icon("Clear", "EditorIcons"), BUTTON_CLEAR_DEPENDENCES, false, TTR("Clear")); + bit->add_button(2, get_theme_icon("Clear", "EditorIcons"), BUTTON_CLEAR_DEPENDENCES, false, TTR("Clear")); } bit->set_text(2, Variant(files)); - bit->add_button(3, get_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP, false, TTR("Move Up")); - bit->add_button(3, get_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN, false, TTR("Move Down")); - bit->add_button(3, get_icon("Remove", "EditorIcons"), BUTTON_ERASE_ENTRY, false, TTR("Remove current entry")); + bit->add_button(3, get_theme_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP, false, TTR("Move Up")); + bit->add_button(3, get_theme_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN, false, TTR("Move Down")); + bit->add_button(3, get_theme_icon("Remove", "EditorIcons"), BUTTON_ERASE_ENTRY, false, TTR("Remove current entry")); } TreeItem *new_arch = tree->create_item(platform); new_arch->set_text(0, TTR("Double click to create a new entry")); new_arch->set_text_align(0, TreeItem::ALIGN_CENTER); - new_arch->set_custom_color(0, get_color("accent_color", "Editor")); + new_arch->set_custom_color(0, get_theme_color("accent_color", "Editor")); new_arch->set_expand_right(0, true); new_arch->set_metadata(1, E->key()); - platform->set_collapsed(collapsed_items.find(E->get().name) != NULL); + platform->set_collapsed(collapsed_items.find(E->get().name) != nullptr); } filter->set_text(text); } void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) { - String target = Object::cast_to<TreeItem>(item)->get_metadata(0); String platform = target.substr(0, target.find(".")); String entry = target.substr(platform.length() + 1, target.length()); String section = (id == BUTTON_SELECT_DEPENDENCES || id == BUTTON_CLEAR_DEPENDENCES) ? "dependencies" : "entry"; if (id == BUTTON_SELECT_LIBRARY || id == BUTTON_SELECT_DEPENDENCES) { - - EditorFileDialog::Mode mode = EditorFileDialog::MODE_OPEN_FILE; - if (id == BUTTON_SELECT_DEPENDENCES) - mode = EditorFileDialog::MODE_OPEN_FILES; + EditorFileDialog::FileMode mode = EditorFileDialog::FILE_MODE_OPEN_FILE; + if (id == BUTTON_SELECT_DEPENDENCES) { + mode = EditorFileDialog::FILE_MODE_OPEN_FILES; + } file_dialog->set_meta("target", target); file_dialog->set_meta("section", section); file_dialog->clear_filters(); file_dialog->add_filter(Object::cast_to<TreeItem>(item)->get_parent()->get_metadata(0)); - file_dialog->set_mode(mode); + file_dialog->set_file_mode(mode); file_dialog->popup_centered_ratio(); } else if (id == BUTTON_CLEAR_LIBRARY) { @@ -156,24 +151,20 @@ void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) { } void GDNativeLibraryEditor::_on_library_selected(const String &file) { - _set_target_value(file_dialog->get_meta("section"), file_dialog->get_meta("target"), file); } void GDNativeLibraryEditor::_on_dependencies_selected(const PackedStringArray &files) { - _set_target_value(file_dialog->get_meta("section"), file_dialog->get_meta("target"), files); } void GDNativeLibraryEditor::_on_filter_selected(int index) { - PopupMenu *filter_list = filter->get_popup(); filter_list->set_item_checked(index, !filter_list->is_item_checked(index)); _update_tree(); } void GDNativeLibraryEditor::_on_item_collapsed(Object *p_item) { - TreeItem *item = Object::cast_to<TreeItem>(p_item); String name = item->get_text(0); @@ -185,7 +176,6 @@ void GDNativeLibraryEditor::_on_item_collapsed(Object *p_item) { } void GDNativeLibraryEditor::_on_item_activated() { - TreeItem *item = tree->get_selected(); if (item && tree->get_selected_column() == 0 && item->get_metadata(0).get_type() == Variant::NIL) { new_architecture_dialog->set_meta("platform", item->get_metadata(1)); @@ -194,7 +184,6 @@ void GDNativeLibraryEditor::_on_item_activated() { } void GDNativeLibraryEditor::_on_create_new_entry() { - String platform = new_architecture_dialog->get_meta("platform"); String entry = new_architecture_input->get_text().strip_edges(); if (!entry.empty()) { @@ -204,19 +193,18 @@ void GDNativeLibraryEditor::_on_create_new_entry() { } void GDNativeLibraryEditor::_set_target_value(const String §ion, const String &target, Variant file) { - if (section == "entry") + if (section == "entry") { entry_configs[target].library = file; - else if (section == "dependencies") + } else if (section == "dependencies") { entry_configs[target].dependencies = file; + } _translate_to_config_file(); _update_tree(); } void GDNativeLibraryEditor::_erase_entry(const String &platform, const String &entry) { - if (platforms.has(platform)) { if (List<String>::Element *E = platforms[platform].entries.find(entry)) { - String target = platform + "." + entry; platforms[platform].entries.erase(E); @@ -243,19 +231,17 @@ void GDNativeLibraryEditor::_move_entry(const String &platform, const String &en } void GDNativeLibraryEditor::_translate_to_config_file() { - if (!library.is_null()) { - Ref<ConfigFile> config = library->get_config_file(); config->erase_section("entry"); config->erase_section("dependencies"); for (Map<String, NativePlatformConfig>::Element *E = platforms.front(); E; E = E->next()) { for (List<String>::Element *it = E->value().entries.front(); it; it = it->next()) { - String target = E->key() + "." + it->get(); - if (entry_configs[target].library.empty() && entry_configs[target].dependencies.empty()) + if (entry_configs[target].library.empty() && entry_configs[target].dependencies.empty()) { continue; + } config->set_value("entry", target, entry_configs[target].library); config->set_value("dependencies", target, entry_configs[target].dependencies); @@ -267,7 +253,6 @@ void GDNativeLibraryEditor::_translate_to_config_file() { } GDNativeLibraryEditor::GDNativeLibraryEditor() { - { // Define platforms NativePlatformConfig platform_windows; platform_windows.name = "Windows"; @@ -372,7 +357,7 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { file_dialog = memnew(EditorFileDialog); file_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); - file_dialog->set_resizable(true); + //file_dialog->set_resizable(true); add_child(file_dialog); file_dialog->connect("file_selected", callable_mp(this, &GDNativeLibraryEditor::_on_library_selected)); file_dialog->connect("files_selected", callable_mp(this, &GDNativeLibraryEditor::_on_dependencies_selected)); @@ -382,38 +367,36 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { new_architecture_dialog->set_title(TTR("Add an architecture entry")); new_architecture_input = memnew(LineEdit); new_architecture_dialog->add_child(new_architecture_input); - new_architecture_dialog->set_custom_minimum_size(Vector2(300, 80) * EDSCALE); + // new_architecture_dialog->set_custom_minimum_size(Vector2(300, 80) * EDSCALE); new_architecture_input->set_anchors_and_margins_preset(PRESET_HCENTER_WIDE, PRESET_MODE_MINSIZE, 5 * EDSCALE); new_architecture_dialog->get_ok()->connect("pressed", callable_mp(this, &GDNativeLibraryEditor::_on_create_new_entry)); } void GDNativeLibraryEditorPlugin::edit(Object *p_node) { - Ref<GDNativeLibrary> new_library = Object::cast_to<GDNativeLibrary>(p_node); - if (new_library.is_valid()) + if (new_library.is_valid()) { library_editor->edit(new_library); + } } bool GDNativeLibraryEditorPlugin::handles(Object *p_node) const { - return p_node->is_class("GDNativeLibrary"); } void GDNativeLibraryEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { button->show(); EditorNode::get_singleton()->make_bottom_panel_item_visible(library_editor); } else { - if (library_editor->is_visible_in_tree()) + if (library_editor->is_visible_in_tree()) { EditorNode::get_singleton()->hide_bottom_panel(); + } button->hide(); } } GDNativeLibraryEditorPlugin::GDNativeLibraryEditorPlugin(EditorNode *p_node) { - library_editor = memnew(GDNativeLibraryEditor); library_editor->set_custom_minimum_size(Size2(0, 250 * EDSCALE)); button = p_node->add_bottom_panel_item(TTR("GDNativeLibrary"), library_editor); diff --git a/modules/gdnative/gdnative_library_editor_plugin.h b/modules/gdnative/gdnative_library_editor_plugin.h index b1274d08b3..5fdb860ca3 100644 --- a/modules/gdnative/gdnative_library_editor_plugin.h +++ b/modules/gdnative/gdnative_library_editor_plugin.h @@ -36,7 +36,6 @@ #include "gdnative.h" class GDNativeLibraryEditor : public Control { - GDCLASS(GDNativeLibraryEditor, Control); struct NativePlatformConfig { @@ -94,7 +93,6 @@ public: }; class GDNativeLibraryEditorPlugin : public EditorPlugin { - GDCLASS(GDNativeLibraryEditorPlugin, EditorPlugin); GDNativeLibraryEditor *library_editor; diff --git a/modules/gdnative/gdnative_library_singleton_editor.cpp b/modules/gdnative/gdnative_library_singleton_editor.cpp index 378339ecea..409b6cbffe 100644 --- a/modules/gdnative/gdnative_library_singleton_editor.cpp +++ b/modules/gdnative/gdnative_library_singleton_editor.cpp @@ -35,7 +35,6 @@ #include "editor/editor_node.h" Set<String> GDNativeLibrarySingletonEditor::_find_singletons_recursive(EditorFileSystemDirectory *p_dir) { - Set<String> file_paths; // check children @@ -67,7 +66,6 @@ Set<String> GDNativeLibrarySingletonEditor::_find_singletons_recursive(EditorFil } void GDNativeLibrarySingletonEditor::_discover_singletons() { - EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem(); Set<String> file_paths = _find_singletons_recursive(dir); @@ -97,7 +95,6 @@ void GDNativeLibrarySingletonEditor::_discover_singletons() { } if (changed) { - ProjectSettings::get_singleton()->set("gdnative/singletons", files); _update_libraries(); // So singleton options (i.e. disabled) updates too ProjectSettings::get_singleton()->save(); @@ -105,7 +102,6 @@ void GDNativeLibrarySingletonEditor::_discover_singletons() { } void GDNativeLibrarySingletonEditor::_update_libraries() { - updating = true; libraries->clear(); libraries->create_item(); // root item @@ -139,19 +135,22 @@ void GDNativeLibrarySingletonEditor::_update_libraries() { } // The singletons list changed, we must update the settings - if (updated_disabled.size() != singletons_disabled.size()) + if (updated_disabled.size() != singletons_disabled.size()) { ProjectSettings::get_singleton()->set("gdnative/singletons_disabled", updated_disabled); + } updating = false; } void GDNativeLibrarySingletonEditor::_item_edited() { - if (updating) + if (updating) { return; + } TreeItem *item = libraries->get_edited(); - if (!item) + if (!item) { return; + } bool enabled = item->get_range(1); String path = item->get_metadata(0); @@ -169,8 +168,9 @@ void GDNativeLibrarySingletonEditor::_item_edited() { if (enabled) { disabled_paths.erase(path); } else { - if (disabled_paths.find(path) == -1) + if (disabled_paths.find(path) == -1) { disabled_paths.push_back(path); + } } undo_redo->create_action(enabled ? TTR("Enabled GDNative Singleton") : TTR("Disabled GDNative Singleton")); @@ -182,7 +182,6 @@ void GDNativeLibrarySingletonEditor::_item_edited() { } void GDNativeLibrarySingletonEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { if (is_visible_in_tree()) { _update_libraries(); @@ -191,7 +190,6 @@ void GDNativeLibrarySingletonEditor::_notification(int p_what) { } void GDNativeLibrarySingletonEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_libraries"), &GDNativeLibrarySingletonEditor::_update_libraries); } diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h index e3114e9348..4db685873f 100644 --- a/modules/gdnative/include/gdnative/array.h +++ b/modules/gdnative/include/gdnative/array.h @@ -51,7 +51,7 @@ typedef struct { } #endif -#include <gdnative/pool_arrays.h> +#include <gdnative/packed_arrays.h> #include <gdnative/variant.h> #include <gdnative/gdnative.h> @@ -66,8 +66,10 @@ void GDAPI godot_array_new_packed_color_array(godot_array *r_dest, const godot_p void GDAPI godot_array_new_packed_vector3_array(godot_array *r_dest, const godot_packed_vector3_array *p_pv3a); void GDAPI godot_array_new_packed_vector2_array(godot_array *r_dest, const godot_packed_vector2_array *p_pv2a); void GDAPI godot_array_new_packed_string_array(godot_array *r_dest, const godot_packed_string_array *p_psa); -void GDAPI godot_array_new_packed_real_array(godot_array *r_dest, const godot_packed_real_array *p_pra); -void GDAPI godot_array_new_packed_int_array(godot_array *r_dest, const godot_packed_int_array *p_pia); +void GDAPI godot_array_new_packed_float32_array(godot_array *r_dest, const godot_packed_float32_array *p_pra); +void GDAPI godot_array_new_packed_float64_array(godot_array *r_dest, const godot_packed_float64_array *p_pra); +void GDAPI godot_array_new_packed_int32_array(godot_array *r_dest, const godot_packed_int32_array *p_pia); +void GDAPI godot_array_new_packed_int64_array(godot_array *r_dest, const godot_packed_int64_array *p_pia); void GDAPI godot_array_new_packed_byte_array(godot_array *r_dest, const godot_packed_byte_array *p_pba); void GDAPI godot_array_set(godot_array *p_self, const godot_int p_idx, const godot_variant *p_value); diff --git a/modules/gdnative/include/gdnative/callable.h b/modules/gdnative/include/gdnative/callable.h new file mode 100644 index 0000000000..dbb5d02590 --- /dev/null +++ b/modules/gdnative/include/gdnative/callable.h @@ -0,0 +1,126 @@ +/*************************************************************************/ +/* callable.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef GODOT_CALLABLE_H +#define GODOT_CALLABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#define GODOT_CALLABLE_SIZE (16) + +#ifndef GODOT_CORE_API_GODOT_CALLABLE_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_CALLABLE_TYPE_DEFINED +typedef struct { + uint8_t _dont_touch_that[GODOT_CALLABLE_SIZE]; +} godot_callable; +#endif + +#define GODOT_SIGNAL_SIZE (16) + +#ifndef GODOT_CORE_API_GODOT_SIGNAL_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_SIGNAL_TYPE_DEFINED +typedef struct { + uint8_t _dont_touch_that[GODOT_SIGNAL_SIZE]; +} godot_signal; +#endif + +#ifdef __cplusplus +} +#endif + +#include <gdnative/gdnative.h> +#include <gdnative/string_name.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Callable + +void GDAPI godot_callable_new_with_object(godot_callable *r_dest, const godot_object *p_object, const godot_string_name *p_method); +void GDAPI godot_callable_new_with_object_id(godot_callable *r_dest, uint64_t p_objectid, const godot_string_name *p_method); +void GDAPI godot_callable_new_copy(godot_callable *r_dest, const godot_callable *p_src); + +void GDAPI godot_callable_destroy(godot_callable *p_self); + +godot_int GDAPI godot_callable_call(const godot_callable *p_self, const godot_variant **p_arguments, godot_int p_argcount, godot_variant *r_return_value); +void GDAPI godot_callable_call_deferred(const godot_callable *p_self, const godot_variant **p_arguments, godot_int p_argcount); + +godot_bool GDAPI godot_callable_is_null(const godot_callable *p_self); +godot_bool GDAPI godot_callable_is_custom(const godot_callable *p_self); +godot_bool GDAPI godot_callable_is_standard(const godot_callable *p_self); + +godot_object GDAPI *godot_callable_get_object(const godot_callable *p_self); +uint64_t GDAPI godot_callable_get_object_id(const godot_callable *p_self); +godot_string_name GDAPI godot_callable_get_method(const godot_callable *p_self); + +uint32_t GDAPI godot_callable_hash(const godot_callable *p_self); + +godot_string GDAPI godot_callable_as_string(const godot_callable *p_self); + +godot_bool GDAPI godot_callable_operator_equal(const godot_callable *p_self, const godot_callable *p_other); +godot_bool GDAPI godot_callable_operator_less(const godot_callable *p_self, const godot_callable *p_other); + +// Signal + +void GDAPI godot_signal_new_with_object(godot_signal *r_dest, const godot_object *p_object, const godot_string_name *p_name); +void GDAPI godot_signal_new_with_object_id(godot_signal *r_dest, uint64_t p_objectid, const godot_string_name *p_name); +void GDAPI godot_signal_new_copy(godot_signal *r_dest, const godot_signal *p_src); + +void GDAPI godot_signal_destroy(godot_signal *p_self); + +godot_int GDAPI godot_signal_emit(const godot_signal *p_self, const godot_variant **p_arguments, godot_int p_argcount); + +godot_int GDAPI godot_signal_connect(godot_signal *p_self, const godot_callable *p_callable, const godot_array *p_binds, uint32_t p_flags); +void GDAPI godot_signal_disconnect(godot_signal *p_self, const godot_callable *p_callable); + +godot_bool GDAPI godot_signal_is_null(const godot_signal *p_self); +godot_bool GDAPI godot_signal_is_connected(const godot_signal *p_self, const godot_callable *p_callable); + +godot_array GDAPI godot_signal_get_connections(const godot_signal *p_self); + +godot_object GDAPI *godot_signal_get_object(const godot_signal *p_self); +uint64_t GDAPI godot_signal_get_object_id(const godot_signal *p_self); +godot_string_name GDAPI godot_signal_get_name(const godot_signal *p_self); + +godot_string GDAPI godot_signal_as_string(const godot_signal *p_self); + +godot_bool GDAPI godot_signal_operator_equal(const godot_signal *p_self, const godot_signal *p_other); +godot_bool GDAPI godot_signal_operator_less(const godot_signal *p_self, const godot_signal *p_other); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/modules/gdnative/include/gdnative/color.h b/modules/gdnative/include/gdnative/color.h index 47c01dbb20..e7737bf8e1 100644 --- a/modules/gdnative/include/gdnative/color.h +++ b/modules/gdnative/include/gdnative/color.h @@ -95,7 +95,7 @@ godot_color GDAPI godot_color_inverted(const godot_color *p_self); godot_color GDAPI godot_color_contrasted(const godot_color *p_self); -godot_color GDAPI godot_color_linear_interpolate(const godot_color *p_self, const godot_color *p_b, const godot_real p_t); +godot_color GDAPI godot_color_lerp(const godot_color *p_self, const godot_color *p_b, const godot_real p_t); godot_color GDAPI godot_color_blend(const godot_color *p_self, const godot_color *p_over); diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h index 6fdca30122..6a0a375da8 100644 --- a/modules/gdnative/include/gdnative/gdnative.h +++ b/modules/gdnative/include/gdnative/gdnative.h @@ -144,15 +144,15 @@ typedef void godot_object; #include <gdnative/string_name.h> -////// Vector2 +////// Vector2 & Vector2i #include <gdnative/vector2.h> -////// Rect2 +////// Rect2 & Rect2i #include <gdnative/rect2.h> -////// Vector3 +////// Vector3 & Vector3i #include <gdnative/vector3.h> @@ -192,6 +192,10 @@ typedef void godot_object; #include <gdnative/rid.h> +/////// Callable & Signal + +#include <gdnative/callable.h> + /////// Dictionary #include <gdnative/dictionary.h> @@ -200,8 +204,8 @@ typedef void godot_object; #include <gdnative/array.h> -// single API file for Pool*Array -#include <gdnative/pool_arrays.h> +// single API file for Packed*Array +#include <gdnative/packed_arrays.h> void GDAPI godot_object_destroy(godot_object *p_o); @@ -289,7 +293,9 @@ void GDAPI *godot_get_class_tag(const godot_string_name *p_class); godot_object GDAPI *godot_object_cast_to(const godot_object *p_object, void *p_class_tag); // equivalent of GDScript's instance_from_id -godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id); +godot_object GDAPI *godot_instance_from_id(uint64_t p_instance_id); + +uint64_t GDAPI godot_object_get_instance_id(const godot_object *p_object); #ifdef __cplusplus } diff --git a/modules/gdnative/include/gdnative/pool_arrays.h b/modules/gdnative/include/gdnative/packed_arrays.h index c610377f54..d5bad70bdc 100644 --- a/modules/gdnative/include/gdnative/pool_arrays.h +++ b/modules/gdnative/include/gdnative/packed_arrays.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pool_arrays.h */ +/* packed_arrays.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_POOL_ARRAYS_H -#define GODOT_POOL_ARRAYS_H +#ifndef GODOT_PACKED_ARRAYS_H +#define GODOT_PACKED_ARRAYS_H #ifdef __cplusplus extern "C" { @@ -39,7 +39,7 @@ extern "C" { /////// PackedByteArray -#define GODOT_PACKED_BYTE_ARRAY_SIZE sizeof(void *) +#define GODOT_PACKED_BYTE_ARRAY_SIZE (2 * sizeof(void *)) #ifndef GODOT_CORE_API_GODOT_PACKED_BYTE_ARRAY_TYPE_DEFINED #define GODOT_CORE_API_GODOT_PACKED_BYTE_ARRAY_TYPE_DEFINED @@ -50,29 +50,51 @@ typedef struct { /////// PackedInt32Array -#define GODOT_PACKED_INT_ARRAY_SIZE sizeof(void *) +#define GODOT_PACKED_INT32_ARRAY_SIZE (2 * sizeof(void *)) -#ifndef GODOT_CORE_API_GODOT_PACKED_INT_ARRAY_TYPE_DEFINED -#define GODOT_CORE_API_GODOT_PACKED_INT_ARRAY_TYPE_DEFINED +#ifndef GODOT_CORE_API_GODOT_PACKED_INT32_ARRAY_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_PACKED_INT32_ARRAY_TYPE_DEFINED typedef struct { - uint8_t _dont_touch_that[GODOT_PACKED_INT_ARRAY_SIZE]; -} godot_packed_int_array; + uint8_t _dont_touch_that[GODOT_PACKED_INT32_ARRAY_SIZE]; +} godot_packed_int32_array; +#endif + +/////// PackedInt64Array + +#define GODOT_PACKED_INT64_ARRAY_SIZE (2 * sizeof(void *)) + +#ifndef GODOT_CORE_API_GODOT_PACKED_INT64_ARRAY_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_PACKED_INT64_ARRAY_TYPE_DEFINED +typedef struct { + uint8_t _dont_touch_that[GODOT_PACKED_INT64_ARRAY_SIZE]; +} godot_packed_int64_array; #endif /////// PackedFloat32Array -#define GODOT_PACKED_REAL_ARRAY_SIZE sizeof(void *) +#define GODOT_PACKED_FLOAT32_ARRAY_SIZE (2 * sizeof(void *)) + +#ifndef GODOT_CORE_API_GODOT_PACKED_FLOAT32_ARRAY_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_PACKED_FLOAT32_ARRAY_TYPE_DEFINED +typedef struct { + uint8_t _dont_touch_that[GODOT_PACKED_FLOAT32_ARRAY_SIZE]; +} godot_packed_float32_array; +#endif + +/////// PackedFloat64Array -#ifndef GODOT_CORE_API_GODOT_PACKED_REAL_ARRAY_TYPE_DEFINED -#define GODOT_CORE_API_GODOT_PACKED_REAL_ARRAY_TYPE_DEFINED +#define GODOT_PACKED_FLOAT64_ARRAY_SIZE (2 * sizeof(void *)) + +#ifndef GODOT_CORE_API_GODOT_PACKED_FLOAT64_ARRAY_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_PACKED_FLOAT64_ARRAY_TYPE_DEFINED typedef struct { - uint8_t _dont_touch_that[GODOT_PACKED_REAL_ARRAY_SIZE]; -} godot_packed_real_array; + uint8_t _dont_touch_that[GODOT_PACKED_FLOAT64_ARRAY_SIZE]; +} godot_packed_float64_array; #endif /////// PackedStringArray -#define GODOT_PACKED_STRING_ARRAY_SIZE sizeof(void *) +#define GODOT_PACKED_STRING_ARRAY_SIZE (2 * sizeof(void *)) #ifndef GODOT_CORE_API_GODOT_PACKED_STRING_ARRAY_TYPE_DEFINED #define GODOT_CORE_API_GODOT_PACKED_STRING_ARRAY_TYPE_DEFINED @@ -83,7 +105,7 @@ typedef struct { /////// PackedVector2Array -#define GODOT_PACKED_VECTOR2_ARRAY_SIZE sizeof(void *) +#define GODOT_PACKED_VECTOR2_ARRAY_SIZE (2 * sizeof(void *)) #ifndef GODOT_CORE_API_GODOT_PACKED_VECTOR2_ARRAY_TYPE_DEFINED #define GODOT_CORE_API_GODOT_PACKED_VECTOR2_ARRAY_TYPE_DEFINED @@ -94,7 +116,7 @@ typedef struct { /////// PackedVector3Array -#define GODOT_PACKED_VECTOR3_ARRAY_SIZE sizeof(void *) +#define GODOT_PACKED_VECTOR3_ARRAY_SIZE (2 * sizeof(void *)) #ifndef GODOT_CORE_API_GODOT_PACKED_VECTOR3_ARRAY_TYPE_DEFINED #define GODOT_CORE_API_GODOT_PACKED_VECTOR3_ARRAY_TYPE_DEFINED @@ -105,7 +127,7 @@ typedef struct { /////// PackedColorArray -#define GODOT_PACKED_COLOR_ARRAY_SIZE sizeof(void *) +#define GODOT_PACKED_COLOR_ARRAY_SIZE (2 * sizeof(void *)) #ifndef GODOT_CORE_API_GODOT_PACKED_COLOR_ARRAY_TYPE_DEFINED #define GODOT_CORE_API_GODOT_PACKED_COLOR_ARRAY_TYPE_DEFINED @@ -159,63 +181,121 @@ godot_bool GDAPI godot_packed_byte_array_empty(const godot_packed_byte_array *p_ void GDAPI godot_packed_byte_array_destroy(godot_packed_byte_array *p_self); -// int +// int32 + +void GDAPI godot_packed_int32_array_new(godot_packed_int32_array *r_dest); +void GDAPI godot_packed_int32_array_new_copy(godot_packed_int32_array *r_dest, const godot_packed_int32_array *p_src); +void GDAPI godot_packed_int32_array_new_with_array(godot_packed_int32_array *r_dest, const godot_array *p_a); + +void GDAPI godot_packed_int32_array_append(godot_packed_int32_array *p_self, const int32_t p_data); + +void GDAPI godot_packed_int32_array_append_array(godot_packed_int32_array *p_self, const godot_packed_int32_array *p_array); + +godot_error GDAPI godot_packed_int32_array_insert(godot_packed_int32_array *p_self, const godot_int p_idx, const int32_t p_data); + +void GDAPI godot_packed_int32_array_invert(godot_packed_int32_array *p_self); + +void GDAPI godot_packed_int32_array_push_back(godot_packed_int32_array *p_self, const int32_t p_data); + +void GDAPI godot_packed_int32_array_remove(godot_packed_int32_array *p_self, const godot_int p_idx); + +void GDAPI godot_packed_int32_array_resize(godot_packed_int32_array *p_self, const godot_int p_size); + +void GDAPI godot_packed_int32_array_set(godot_packed_int32_array *p_self, const godot_int p_idx, const int32_t p_data); +int32_t GDAPI godot_packed_int32_array_get(const godot_packed_int32_array *p_self, const godot_int p_idx); + +godot_int GDAPI godot_packed_int32_array_size(const godot_packed_int32_array *p_self); + +godot_bool GDAPI godot_packed_int32_array_empty(const godot_packed_int32_array *p_self); + +void GDAPI godot_packed_int32_array_destroy(godot_packed_int32_array *p_self); + +// int64 + +void GDAPI godot_packed_int64_array_new(godot_packed_int64_array *r_dest); +void GDAPI godot_packed_int64_array_new_copy(godot_packed_int64_array *r_dest, const godot_packed_int64_array *p_src); +void GDAPI godot_packed_int64_array_new_with_array(godot_packed_int64_array *r_dest, const godot_array *p_a); + +void GDAPI godot_packed_int64_array_append(godot_packed_int64_array *p_self, const int64_t p_data); + +void GDAPI godot_packed_int64_array_append_array(godot_packed_int64_array *p_self, const godot_packed_int64_array *p_array); + +godot_error GDAPI godot_packed_int64_array_insert(godot_packed_int64_array *p_self, const godot_int p_idx, const int64_t p_data); + +void GDAPI godot_packed_int64_array_invert(godot_packed_int64_array *p_self); + +void GDAPI godot_packed_int64_array_push_back(godot_packed_int64_array *p_self, const int64_t p_data); + +void GDAPI godot_packed_int64_array_remove(godot_packed_int64_array *p_self, const godot_int p_idx); + +void GDAPI godot_packed_int64_array_resize(godot_packed_int64_array *p_self, const godot_int p_size); + +void GDAPI godot_packed_int64_array_set(godot_packed_int64_array *p_self, const godot_int p_idx, const int64_t p_data); +int64_t GDAPI godot_packed_int64_array_get(const godot_packed_int64_array *p_self, const godot_int p_idx); + +godot_int GDAPI godot_packed_int64_array_size(const godot_packed_int64_array *p_self); + +godot_bool GDAPI godot_packed_int64_array_empty(const godot_packed_int64_array *p_self); + +void GDAPI godot_packed_int64_array_destroy(godot_packed_int64_array *p_self); + +// float32 -void GDAPI godot_packed_int_array_new(godot_packed_int_array *r_dest); -void GDAPI godot_packed_int_array_new_copy(godot_packed_int_array *r_dest, const godot_packed_int_array *p_src); -void GDAPI godot_packed_int_array_new_with_array(godot_packed_int_array *r_dest, const godot_array *p_a); +void GDAPI godot_packed_float32_array_new(godot_packed_float32_array *r_dest); +void GDAPI godot_packed_float32_array_new_copy(godot_packed_float32_array *r_dest, const godot_packed_float32_array *p_src); +void GDAPI godot_packed_float32_array_new_with_array(godot_packed_float32_array *r_dest, const godot_array *p_a); -void GDAPI godot_packed_int_array_append(godot_packed_int_array *p_self, const godot_int p_data); +void GDAPI godot_packed_float32_array_append(godot_packed_float32_array *p_self, const float p_data); -void GDAPI godot_packed_int_array_append_array(godot_packed_int_array *p_self, const godot_packed_int_array *p_array); +void GDAPI godot_packed_float32_array_append_array(godot_packed_float32_array *p_self, const godot_packed_float32_array *p_array); -godot_error GDAPI godot_packed_int_array_insert(godot_packed_int_array *p_self, const godot_int p_idx, const godot_int p_data); +godot_error GDAPI godot_packed_float32_array_insert(godot_packed_float32_array *p_self, const godot_int p_idx, const float p_data); -void GDAPI godot_packed_int_array_invert(godot_packed_int_array *p_self); +void GDAPI godot_packed_float32_array_invert(godot_packed_float32_array *p_self); -void GDAPI godot_packed_int_array_push_back(godot_packed_int_array *p_self, const godot_int p_data); +void GDAPI godot_packed_float32_array_push_back(godot_packed_float32_array *p_self, const float p_data); -void GDAPI godot_packed_int_array_remove(godot_packed_int_array *p_self, const godot_int p_idx); +void GDAPI godot_packed_float32_array_remove(godot_packed_float32_array *p_self, const godot_int p_idx); -void GDAPI godot_packed_int_array_resize(godot_packed_int_array *p_self, const godot_int p_size); +void GDAPI godot_packed_float32_array_resize(godot_packed_float32_array *p_self, const godot_int p_size); -void GDAPI godot_packed_int_array_set(godot_packed_int_array *p_self, const godot_int p_idx, const godot_int p_data); -godot_int GDAPI godot_packed_int_array_get(const godot_packed_int_array *p_self, const godot_int p_idx); +void GDAPI godot_packed_float32_array_set(godot_packed_float32_array *p_self, const godot_int p_idx, const float p_data); +float GDAPI godot_packed_float32_array_get(const godot_packed_float32_array *p_self, const godot_int p_idx); -godot_int GDAPI godot_packed_int_array_size(const godot_packed_int_array *p_self); +godot_int GDAPI godot_packed_float32_array_size(const godot_packed_float32_array *p_self); -godot_bool GDAPI godot_packed_int_array_empty(const godot_packed_int_array *p_self); +godot_bool GDAPI godot_packed_float32_array_empty(const godot_packed_float32_array *p_self); -void GDAPI godot_packed_int_array_destroy(godot_packed_int_array *p_self); +void GDAPI godot_packed_float32_array_destroy(godot_packed_float32_array *p_self); -// real +// float64 -void GDAPI godot_packed_real_array_new(godot_packed_real_array *r_dest); -void GDAPI godot_packed_real_array_new_copy(godot_packed_real_array *r_dest, const godot_packed_real_array *p_src); -void GDAPI godot_packed_real_array_new_with_array(godot_packed_real_array *r_dest, const godot_array *p_a); +void GDAPI godot_packed_float64_array_new(godot_packed_float64_array *r_dest); +void GDAPI godot_packed_float64_array_new_copy(godot_packed_float64_array *r_dest, const godot_packed_float64_array *p_src); +void GDAPI godot_packed_float64_array_new_with_array(godot_packed_float64_array *r_dest, const godot_array *p_a); -void GDAPI godot_packed_real_array_append(godot_packed_real_array *p_self, const godot_real p_data); +void GDAPI godot_packed_float64_array_append(godot_packed_float64_array *p_self, const double p_data); -void GDAPI godot_packed_real_array_append_array(godot_packed_real_array *p_self, const godot_packed_real_array *p_array); +void GDAPI godot_packed_float64_array_append_array(godot_packed_float64_array *p_self, const godot_packed_float64_array *p_array); -godot_error GDAPI godot_packed_real_array_insert(godot_packed_real_array *p_self, const godot_int p_idx, const godot_real p_data); +godot_error GDAPI godot_packed_float64_array_insert(godot_packed_float64_array *p_self, const godot_int p_idx, const double p_data); -void GDAPI godot_packed_real_array_invert(godot_packed_real_array *p_self); +void GDAPI godot_packed_float64_array_invert(godot_packed_float64_array *p_self); -void GDAPI godot_packed_real_array_push_back(godot_packed_real_array *p_self, const godot_real p_data); +void GDAPI godot_packed_float64_array_push_back(godot_packed_float64_array *p_self, const double p_data); -void GDAPI godot_packed_real_array_remove(godot_packed_real_array *p_self, const godot_int p_idx); +void GDAPI godot_packed_float64_array_remove(godot_packed_float64_array *p_self, const godot_int p_idx); -void GDAPI godot_packed_real_array_resize(godot_packed_real_array *p_self, const godot_int p_size); +void GDAPI godot_packed_float64_array_resize(godot_packed_float64_array *p_self, const godot_int p_size); -void GDAPI godot_packed_real_array_set(godot_packed_real_array *p_self, const godot_int p_idx, const godot_real p_data); -godot_real GDAPI godot_packed_real_array_get(const godot_packed_real_array *p_self, const godot_int p_idx); +void GDAPI godot_packed_float64_array_set(godot_packed_float64_array *p_self, const godot_int p_idx, const double p_data); +double GDAPI godot_packed_float64_array_get(const godot_packed_float64_array *p_self, const godot_int p_idx); -godot_int GDAPI godot_packed_real_array_size(const godot_packed_real_array *p_self); +godot_int GDAPI godot_packed_float64_array_size(const godot_packed_float64_array *p_self); -godot_bool GDAPI godot_packed_real_array_empty(const godot_packed_real_array *p_self); +godot_bool GDAPI godot_packed_float64_array_empty(const godot_packed_float64_array *p_self); -void GDAPI godot_packed_real_array_destroy(godot_packed_real_array *p_self); +void GDAPI godot_packed_float64_array_destroy(godot_packed_float64_array *p_self); // string diff --git a/modules/gdnative/include/gdnative/rect2.h b/modules/gdnative/include/gdnative/rect2.h index 0ecf072471..f317afc9da 100644 --- a/modules/gdnative/include/gdnative/rect2.h +++ b/modules/gdnative/include/gdnative/rect2.h @@ -44,6 +44,13 @@ typedef struct godot_rect2 { } godot_rect2; #endif +#ifndef GODOT_CORE_API_GODOT_RECT2I_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_RECT2I_TYPE_DEFINED +typedef struct godot_rect2i { + uint8_t _dont_touch_that[16]; +} godot_rect2i; +#endif + // reduce extern "C" nesting for VS2013 #ifdef __cplusplus } @@ -56,11 +63,15 @@ typedef struct godot_rect2 { extern "C" { #endif +// Rect2 + void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size); void GDAPI godot_rect2_new(godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height); godot_string GDAPI godot_rect2_as_string(const godot_rect2 *p_self); +godot_rect2i GDAPI godot_rect2_as_rect2i(const godot_rect2 *p_self); + godot_real GDAPI godot_rect2_get_area(const godot_rect2 *p_self); godot_bool GDAPI godot_rect2_intersects(const godot_rect2 *p_self, const godot_rect2 *p_b); @@ -95,6 +106,49 @@ void GDAPI godot_rect2_set_position(godot_rect2 *p_self, const godot_vector2 *p_ void GDAPI godot_rect2_set_size(godot_rect2 *p_self, const godot_vector2 *p_size); +// Rect2I + +void GDAPI godot_rect2i_new_with_position_and_size(godot_rect2i *r_dest, const godot_vector2i *p_pos, const godot_vector2i *p_size); +void GDAPI godot_rect2i_new(godot_rect2i *r_dest, const godot_int p_x, const godot_int p_y, const godot_int p_width, const godot_int p_height); + +godot_string GDAPI godot_rect2i_as_string(const godot_rect2i *p_self); + +godot_rect2 GDAPI godot_rect2i_as_rect2(const godot_rect2i *p_self); + +godot_int GDAPI godot_rect2i_get_area(const godot_rect2i *p_self); + +godot_bool GDAPI godot_rect2i_intersects(const godot_rect2i *p_self, const godot_rect2i *p_b); + +godot_bool GDAPI godot_rect2i_encloses(const godot_rect2i *p_self, const godot_rect2i *p_b); + +godot_bool GDAPI godot_rect2i_has_no_area(const godot_rect2i *p_self); + +godot_rect2i GDAPI godot_rect2i_clip(const godot_rect2i *p_self, const godot_rect2i *p_b); + +godot_rect2i GDAPI godot_rect2i_merge(const godot_rect2i *p_self, const godot_rect2i *p_b); + +godot_bool GDAPI godot_rect2i_has_point(const godot_rect2i *p_self, const godot_vector2i *p_point); + +godot_rect2i GDAPI godot_rect2i_grow(const godot_rect2i *p_self, const godot_int p_by); + +godot_rect2i GDAPI godot_rect2i_grow_individual(const godot_rect2i *p_self, const godot_int p_left, const godot_int p_top, const godot_int p_right, const godot_int p_bottom); + +godot_rect2i GDAPI godot_rect2i_grow_margin(const godot_rect2i *p_self, const godot_int p_margin, const godot_int p_by); + +godot_rect2i GDAPI godot_rect2i_abs(const godot_rect2i *p_self); + +godot_rect2i GDAPI godot_rect2i_expand(const godot_rect2i *p_self, const godot_vector2i *p_to); + +godot_bool GDAPI godot_rect2i_operator_equal(const godot_rect2i *p_self, const godot_rect2i *p_b); + +godot_vector2i GDAPI godot_rect2i_get_position(const godot_rect2i *p_self); + +godot_vector2i GDAPI godot_rect2i_get_size(const godot_rect2i *p_self); + +void GDAPI godot_rect2i_set_position(godot_rect2i *p_self, const godot_vector2i *p_pos); + +void GDAPI godot_rect2i_set_size(godot_rect2i *p_self, const godot_vector2i *p_size); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/gdnative/rid.h b/modules/gdnative/include/gdnative/rid.h index 04661cedc8..73b601dc04 100644 --- a/modules/gdnative/include/gdnative/rid.h +++ b/modules/gdnative/include/gdnative/rid.h @@ -37,7 +37,7 @@ extern "C" { #include <stdint.h> -#define GODOT_RID_SIZE sizeof(void *) +#define GODOT_RID_SIZE sizeof(uint64_t) #ifndef GODOT_CORE_API_GODOT_RID_TYPE_DEFINED #define GODOT_CORE_API_GODOT_RID_TYPE_DEFINED diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h index 934e856fbf..0a611b76e9 100644 --- a/modules/gdnative/include/gdnative/variant.h +++ b/modules/gdnative/include/gdnative/variant.h @@ -37,7 +37,7 @@ extern "C" { #include <stdint.h> -#define GODOT_VARIANT_SIZE (16 + sizeof(void *)) +#define GODOT_VARIANT_SIZE (16 + sizeof(int64_t)) #ifndef GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED #define GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED @@ -71,16 +71,21 @@ typedef enum godot_variant_type { // misc types GODOT_VARIANT_TYPE_COLOR, + GODOT_VARIANT_TYPE_STRING_NAME, GODOT_VARIANT_TYPE_NODE_PATH, GODOT_VARIANT_TYPE_RID, GODOT_VARIANT_TYPE_OBJECT, + GODOT_VARIANT_TYPE_CALLABLE, + GODOT_VARIANT_TYPE_SIGNAL, GODOT_VARIANT_TYPE_DICTIONARY, GODOT_VARIANT_TYPE_ARRAY, // arrays GODOT_VARIANT_TYPE_PACKED_BYTE_ARRAY, - GODOT_VARIANT_TYPE_PACKED_INT_ARRAY, - GODOT_VARIANT_TYPE_PACKED_REAL_ARRAY, + GODOT_VARIANT_TYPE_PACKED_INT32_ARRAY, + GODOT_VARIANT_TYPE_PACKED_INT64_ARRAY, + GODOT_VARIANT_TYPE_PACKED_FLOAT32_ARRAY, + GODOT_VARIANT_TYPE_PACKED_FLOAT64_ARRAY, GODOT_VARIANT_TYPE_PACKED_STRING_ARRAY, GODOT_VARIANT_TYPE_PACKED_VECTOR2_ARRAY, GODOT_VARIANT_TYPE_PACKED_VECTOR3_ARRAY, @@ -149,15 +154,17 @@ typedef enum godot_variant_operator { #include <gdnative/aabb.h> #include <gdnative/array.h> #include <gdnative/basis.h> +#include <gdnative/callable.h> #include <gdnative/color.h> #include <gdnative/dictionary.h> #include <gdnative/node_path.h> +#include <gdnative/packed_arrays.h> #include <gdnative/plane.h> -#include <gdnative/pool_arrays.h> #include <gdnative/quat.h> #include <gdnative/rect2.h> #include <gdnative/rid.h> #include <gdnative/string.h> +#include <gdnative/string_name.h> #include <gdnative/transform.h> #include <gdnative/transform2d.h> #include <gdnative/variant.h> @@ -181,9 +188,13 @@ void GDAPI godot_variant_new_uint(godot_variant *r_dest, const uint64_t p_i); void GDAPI godot_variant_new_int(godot_variant *r_dest, const int64_t p_i); void GDAPI godot_variant_new_real(godot_variant *r_dest, const double p_r); void GDAPI godot_variant_new_string(godot_variant *r_dest, const godot_string *p_s); +void GDAPI godot_variant_new_string_name(godot_variant *r_dest, const godot_string_name *p_s); void GDAPI godot_variant_new_vector2(godot_variant *r_dest, const godot_vector2 *p_v2); +void GDAPI godot_variant_new_vector2i(godot_variant *r_dest, const godot_vector2i *p_v2); void GDAPI godot_variant_new_rect2(godot_variant *r_dest, const godot_rect2 *p_rect2); +void GDAPI godot_variant_new_rect2i(godot_variant *r_dest, const godot_rect2i *p_rect2); void GDAPI godot_variant_new_vector3(godot_variant *r_dest, const godot_vector3 *p_v3); +void GDAPI godot_variant_new_vector3i(godot_variant *r_dest, const godot_vector3i *p_v3); void GDAPI godot_variant_new_transform2d(godot_variant *r_dest, const godot_transform2d *p_t2d); void GDAPI godot_variant_new_plane(godot_variant *r_dest, const godot_plane *p_plane); void GDAPI godot_variant_new_quat(godot_variant *r_dest, const godot_quat *p_quat); @@ -193,12 +204,16 @@ void GDAPI godot_variant_new_transform(godot_variant *r_dest, const godot_transf void GDAPI godot_variant_new_color(godot_variant *r_dest, const godot_color *p_color); void GDAPI godot_variant_new_node_path(godot_variant *r_dest, const godot_node_path *p_np); void GDAPI godot_variant_new_rid(godot_variant *r_dest, const godot_rid *p_rid); +void GDAPI godot_variant_new_callable(godot_variant *r_dest, const godot_callable *p_callable); +void GDAPI godot_variant_new_signal(godot_variant *r_dest, const godot_signal *p_signal); void GDAPI godot_variant_new_object(godot_variant *r_dest, const godot_object *p_obj); void GDAPI godot_variant_new_dictionary(godot_variant *r_dest, const godot_dictionary *p_dict); void GDAPI godot_variant_new_array(godot_variant *r_dest, const godot_array *p_arr); void GDAPI godot_variant_new_packed_byte_array(godot_variant *r_dest, const godot_packed_byte_array *p_pba); -void GDAPI godot_variant_new_packed_int_array(godot_variant *r_dest, const godot_packed_int_array *p_pia); -void GDAPI godot_variant_new_packed_real_array(godot_variant *r_dest, const godot_packed_real_array *p_pra); +void GDAPI godot_variant_new_packed_int32_array(godot_variant *r_dest, const godot_packed_int32_array *p_pia); +void GDAPI godot_variant_new_packed_int64_array(godot_variant *r_dest, const godot_packed_int64_array *p_pia); +void GDAPI godot_variant_new_packed_float32_array(godot_variant *r_dest, const godot_packed_float32_array *p_pra); +void GDAPI godot_variant_new_packed_float64_array(godot_variant *r_dest, const godot_packed_float64_array *p_pra); void GDAPI godot_variant_new_packed_string_array(godot_variant *r_dest, const godot_packed_string_array *p_psa); void GDAPI godot_variant_new_packed_vector2_array(godot_variant *r_dest, const godot_packed_vector2_array *p_pv2a); void GDAPI godot_variant_new_packed_vector3_array(godot_variant *r_dest, const godot_packed_vector3_array *p_pv3a); @@ -209,9 +224,13 @@ uint64_t GDAPI godot_variant_as_uint(const godot_variant *p_self); int64_t GDAPI godot_variant_as_int(const godot_variant *p_self); double GDAPI godot_variant_as_real(const godot_variant *p_self); godot_string GDAPI godot_variant_as_string(const godot_variant *p_self); +godot_string_name GDAPI godot_variant_as_string_name(const godot_variant *p_self); godot_vector2 GDAPI godot_variant_as_vector2(const godot_variant *p_self); +godot_vector2i GDAPI godot_variant_as_vector2i(const godot_variant *p_self); godot_rect2 GDAPI godot_variant_as_rect2(const godot_variant *p_self); +godot_rect2i GDAPI godot_variant_as_rect2i(const godot_variant *p_self); godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_self); +godot_vector3i GDAPI godot_variant_as_vector3i(const godot_variant *p_self); godot_transform2d GDAPI godot_variant_as_transform2d(const godot_variant *p_self); godot_plane GDAPI godot_variant_as_plane(const godot_variant *p_self); godot_quat GDAPI godot_variant_as_quat(const godot_variant *p_self); @@ -221,12 +240,16 @@ godot_transform GDAPI godot_variant_as_transform(const godot_variant *p_self); godot_color GDAPI godot_variant_as_color(const godot_variant *p_self); godot_node_path GDAPI godot_variant_as_node_path(const godot_variant *p_self); godot_rid GDAPI godot_variant_as_rid(const godot_variant *p_self); +godot_callable GDAPI godot_variant_as_callable(const godot_variant *p_self); +godot_signal GDAPI godot_variant_as_signal(const godot_variant *p_self); godot_object GDAPI *godot_variant_as_object(const godot_variant *p_self); godot_dictionary GDAPI godot_variant_as_dictionary(const godot_variant *p_self); godot_array GDAPI godot_variant_as_array(const godot_variant *p_self); godot_packed_byte_array GDAPI godot_variant_as_packed_byte_array(const godot_variant *p_self); -godot_packed_int_array GDAPI godot_variant_as_packed_int_array(const godot_variant *p_self); -godot_packed_real_array GDAPI godot_variant_as_packed_real_array(const godot_variant *p_self); +godot_packed_int32_array GDAPI godot_variant_as_packed_int32_array(const godot_variant *p_self); +godot_packed_int64_array GDAPI godot_variant_as_packed_int64_array(const godot_variant *p_self); +godot_packed_float32_array GDAPI godot_variant_as_packed_float32_array(const godot_variant *p_self); +godot_packed_float64_array GDAPI godot_variant_as_packed_float64_array(const godot_variant *p_self); godot_packed_string_array GDAPI godot_variant_as_packed_string_array(const godot_variant *p_self); godot_packed_vector2_array GDAPI godot_variant_as_packed_vector2_array(const godot_variant *p_self); godot_packed_vector3_array GDAPI godot_variant_as_packed_vector3_array(const godot_variant *p_self); @@ -239,6 +262,7 @@ godot_bool GDAPI godot_variant_has_method(const godot_variant *p_self, const god godot_bool GDAPI godot_variant_operator_equal(const godot_variant *p_self, const godot_variant *p_other); godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const godot_variant *p_other); +uint32_t GDAPI godot_variant_hash(const godot_variant *p_self); godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other); godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self); diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h index 15a1a6063b..35b02c5a75 100644 --- a/modules/gdnative/include/gdnative/vector2.h +++ b/modules/gdnative/include/gdnative/vector2.h @@ -46,6 +46,15 @@ typedef struct { } godot_vector2; #endif +#define GODOT_VECTOR2I_SIZE 8 + +#ifndef GODOT_CORE_API_GODOT_VECTOR2I_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_VECTOR2I_TYPE_DEFINED +typedef struct { + uint8_t _dont_touch_that[GODOT_VECTOR2I_SIZE]; +} godot_vector2i; +#endif + // reduce extern "C" nesting for VS2013 #ifdef __cplusplus } @@ -57,10 +66,14 @@ typedef struct { extern "C" { #endif +// Vector2 + void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y); godot_string GDAPI godot_vector2_as_string(const godot_vector2 *p_self); +godot_vector2i GDAPI godot_vector2_as_vector2i(const godot_vector2 *p_self); + godot_vector2 GDAPI godot_vector2_normalized(const godot_vector2 *p_self); godot_real GDAPI godot_vector2_length(const godot_vector2 *p_self); @@ -81,7 +94,7 @@ godot_real GDAPI godot_vector2_angle_to(const godot_vector2 *p_self, const godot godot_real GDAPI godot_vector2_angle_to_point(const godot_vector2 *p_self, const godot_vector2 *p_to); -godot_vector2 GDAPI godot_vector2_linear_interpolate(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t); +godot_vector2 GDAPI godot_vector2_lerp(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t); godot_vector2 GDAPI godot_vector2_cubic_interpolate(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_vector2 *p_pre_a, const godot_vector2 *p_post_b, const godot_real p_t); @@ -93,6 +106,8 @@ godot_vector2 GDAPI godot_vector2_tangent(const godot_vector2 *p_self); godot_vector2 GDAPI godot_vector2_floor(const godot_vector2 *p_self); +godot_vector2 GDAPI godot_vector2_sign(const godot_vector2 *p_self); + godot_vector2 GDAPI godot_vector2_snapped(const godot_vector2 *p_self, const godot_vector2 *p_by); godot_real GDAPI godot_vector2_aspect(const godot_vector2 *p_self); @@ -135,6 +150,46 @@ godot_real GDAPI godot_vector2_get_x(const godot_vector2 *p_self); godot_real GDAPI godot_vector2_get_y(const godot_vector2 *p_self); +// Vector2i + +void GDAPI godot_vector2i_new(godot_vector2i *r_dest, const godot_int p_x, const godot_int p_y); + +godot_string GDAPI godot_vector2i_as_string(const godot_vector2i *p_self); + +godot_vector2 GDAPI godot_vector2i_as_vector2(const godot_vector2i *p_self); + +godot_real GDAPI godot_vector2i_aspect(const godot_vector2i *p_self); + +godot_vector2i GDAPI godot_vector2i_abs(const godot_vector2i *p_self); + +godot_vector2i GDAPI godot_vector2i_sign(const godot_vector2i *p_self); + +godot_vector2i GDAPI godot_vector2i_operator_add(const godot_vector2i *p_self, const godot_vector2i *p_b); + +godot_vector2i GDAPI godot_vector2i_operator_subtract(const godot_vector2i *p_self, const godot_vector2i *p_b); + +godot_vector2i GDAPI godot_vector2i_operator_multiply_vector(const godot_vector2i *p_self, const godot_vector2i *p_b); + +godot_vector2i GDAPI godot_vector2i_operator_multiply_scalar(const godot_vector2i *p_self, const godot_int p_b); + +godot_vector2i GDAPI godot_vector2i_operator_divide_vector(const godot_vector2i *p_self, const godot_vector2i *p_b); + +godot_vector2i GDAPI godot_vector2i_operator_divide_scalar(const godot_vector2i *p_self, const godot_int p_b); + +godot_bool GDAPI godot_vector2i_operator_equal(const godot_vector2i *p_self, const godot_vector2i *p_b); + +godot_bool GDAPI godot_vector2i_operator_less(const godot_vector2i *p_self, const godot_vector2i *p_b); + +godot_vector2i GDAPI godot_vector2i_operator_neg(const godot_vector2i *p_self); + +void GDAPI godot_vector2i_set_x(godot_vector2i *p_self, const godot_int p_x); + +void GDAPI godot_vector2i_set_y(godot_vector2i *p_self, const godot_int p_y); + +godot_int GDAPI godot_vector2i_get_x(const godot_vector2i *p_self); + +godot_int GDAPI godot_vector2i_get_y(const godot_vector2i *p_self); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h index 1b344590ea..5127b8789b 100644 --- a/modules/gdnative/include/gdnative/vector3.h +++ b/modules/gdnative/include/gdnative/vector3.h @@ -46,6 +46,15 @@ typedef struct { } godot_vector3; #endif +#define GODOT_VECTOR3I_SIZE 12 + +#ifndef GODOT_CORE_API_GODOT_VECTOR3I_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_VECTOR3I_TYPE_DEFINED +typedef struct { + uint8_t _dont_touch_that[GODOT_VECTOR3I_SIZE]; +} godot_vector3i; +#endif + // reduce extern "C" nesting for VS2013 #ifdef __cplusplus } @@ -64,10 +73,14 @@ typedef enum { GODOT_VECTOR3_AXIS_Z, } godot_vector3_axis; +// Vector3 + void GDAPI godot_vector3_new(godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z); godot_string GDAPI godot_vector3_as_string(const godot_vector3 *p_self); +godot_vector3i GDAPI godot_vector3_as_vector3i(const godot_vector3 *p_self); + godot_int GDAPI godot_vector3_min_axis(const godot_vector3 *p_self); godot_int GDAPI godot_vector3_max_axis(const godot_vector3 *p_self); @@ -86,7 +99,7 @@ godot_vector3 GDAPI godot_vector3_snapped(const godot_vector3 *p_self, const god godot_vector3 GDAPI godot_vector3_rotated(const godot_vector3 *p_self, const godot_vector3 *p_axis, const godot_real p_phi); -godot_vector3 GDAPI godot_vector3_linear_interpolate(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t); +godot_vector3 GDAPI godot_vector3_lerp(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t); godot_vector3 GDAPI godot_vector3_cubic_interpolate(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_vector3 *p_pre_a, const godot_vector3 *p_post_b, const godot_real p_t); @@ -102,6 +115,8 @@ godot_basis GDAPI godot_vector3_to_diagonal_matrix(const godot_vector3 *p_self); godot_vector3 GDAPI godot_vector3_abs(const godot_vector3 *p_self); +godot_vector3 GDAPI godot_vector3_sign(const godot_vector3 *p_self); + godot_vector3 GDAPI godot_vector3_floor(const godot_vector3 *p_self); godot_vector3 GDAPI godot_vector3_ceil(const godot_vector3 *p_self); @@ -142,6 +157,44 @@ void GDAPI godot_vector3_set_axis(godot_vector3 *p_self, const godot_vector3_axi godot_real GDAPI godot_vector3_get_axis(const godot_vector3 *p_self, const godot_vector3_axis p_axis); +// Vector3i + +void GDAPI godot_vector3i_new(godot_vector3i *r_dest, const godot_int p_x, const godot_int p_y, const godot_int p_z); + +godot_string GDAPI godot_vector3i_as_string(const godot_vector3i *p_self); + +godot_vector3 GDAPI godot_vector3i_as_vector3(const godot_vector3i *p_self); + +godot_int GDAPI godot_vector3i_min_axis(const godot_vector3i *p_self); + +godot_int GDAPI godot_vector3i_max_axis(const godot_vector3i *p_self); + +godot_vector3i GDAPI godot_vector3i_abs(const godot_vector3i *p_self); + +godot_vector3i GDAPI godot_vector3i_sign(const godot_vector3i *p_self); + +godot_vector3i GDAPI godot_vector3i_operator_add(const godot_vector3i *p_self, const godot_vector3i *p_b); + +godot_vector3i GDAPI godot_vector3i_operator_subtract(const godot_vector3i *p_self, const godot_vector3i *p_b); + +godot_vector3i GDAPI godot_vector3i_operator_multiply_vector(const godot_vector3i *p_self, const godot_vector3i *p_b); + +godot_vector3i GDAPI godot_vector3i_operator_multiply_scalar(const godot_vector3i *p_self, const godot_int p_b); + +godot_vector3i GDAPI godot_vector3i_operator_divide_vector(const godot_vector3i *p_self, const godot_vector3i *p_b); + +godot_vector3i GDAPI godot_vector3i_operator_divide_scalar(const godot_vector3i *p_self, const godot_int p_b); + +godot_bool GDAPI godot_vector3i_operator_equal(const godot_vector3i *p_self, const godot_vector3i *p_b); + +godot_bool GDAPI godot_vector3i_operator_less(const godot_vector3i *p_self, const godot_vector3i *p_b); + +godot_vector3i GDAPI godot_vector3i_operator_neg(const godot_vector3i *p_self); + +void GDAPI godot_vector3i_set_axis(godot_vector3i *p_self, const godot_vector3_axis p_axis, const godot_int p_val); + +godot_int GDAPI godot_vector3i_get_axis(const godot_vector3i *p_self, const godot_vector3_axis p_axis); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index 1b131c8cf0..d65b3f91f4 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -54,7 +54,6 @@ typedef enum { GODOT_PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc" GODOT_PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease) GODOT_PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer) - GODOT_PROPERTY_HINT_SPRITE_FRAME, // FIXME: Obsolete: drop whenever we can break compat GODOT_PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer) GODOT_PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) GODOT_PROPERTY_HINT_LAYERS_2D_RENDER, @@ -96,8 +95,7 @@ typedef enum { GODOT_PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings GODOT_PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor GODOT_PROPERTY_USAGE_CATEGORY = 256, - GODOT_PROPERTY_USAGE_STORE_IF_NONZERO = 512, // FIXME: Obsolete: drop whenever we can break compat - GODOT_PROPERTY_USAGE_STORE_IF_NONONE = 1024, // FIXME: Obsolete: drop whenever we can break compat + GODOT_PROPERTY_USAGE_SUBGROUP = 512, GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE = 2048, GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED = 4096, GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE = 8192, @@ -174,17 +172,17 @@ typedef struct { godot_string hint_string; godot_property_usage_flags usage; godot_variant default_value; -} godot_signal_argument; +} godot_nativescript_signal_argument; typedef struct { godot_string name; int num_args; - godot_signal_argument *args; + godot_nativescript_signal_argument *args; int num_default_args; godot_variant *default_args; -} godot_signal; +} godot_nativescript_signal; -void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal); +void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_nativescript_signal *p_signal); void GDAPI *godot_nativescript_get_userdata(godot_object *p_instance); diff --git a/modules/gdnative/include/net/godot_net.h b/modules/gdnative/include/net/godot_net.h index d245f3b965..42804112f2 100644 --- a/modules/gdnative/include/net/godot_net.h +++ b/modules/gdnative/include/net/godot_net.h @@ -45,7 +45,6 @@ extern "C" { #define GODOT_NET_API_MINOR 1 typedef struct { - godot_gdnative_api_version version; /* version of our API */ godot_object *data; /* User reference */ diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h index 341e7f9e2b..406c3ba663 100644 --- a/modules/gdnative/include/pluginscript/godot_pluginscript.h +++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h @@ -60,7 +60,7 @@ typedef struct { //this is used by script languages that keep a reference counter of their own //you can make make Ref<> not die when it reaches zero, so deleting the reference //depends entirely from the script. - // Note: You can set those function pointer to NULL if not needed. + // Note: You can set those function pointer to nullptr if not needed. void (*refcount_incremented)(godot_pluginscript_instance_data *p_data); bool (*refcount_decremented)(godot_pluginscript_instance_data *p_data); // return true if it can die } godot_pluginscript_instance_desc; @@ -119,18 +119,18 @@ typedef struct { const char *name; const char *type; const char *extension; - const char **recognized_extensions; // NULL terminated array + const char **recognized_extensions; // nullptr terminated array godot_pluginscript_language_data *(*init)(); void (*finish)(godot_pluginscript_language_data *p_data); - const char **reserved_words; // NULL terminated array - const char **comment_delimiters; // NULL terminated array - const char **string_delimiters; // NULL terminated array + const char **reserved_words; // nullptr terminated array + const char **comment_delimiters; // nullptr terminated array + const char **string_delimiters; // nullptr terminated array godot_bool has_named_classes; godot_bool supports_builtin_mode; godot_string (*get_template_source_code)(godot_pluginscript_language_data *p_data, const godot_string *p_class_name, const godot_string *p_base_class_name); godot_bool (*validate)(godot_pluginscript_language_data *p_data, const godot_string *p_script, int *r_line_error, int *r_col_error, godot_string *r_test_error, const godot_string *p_path, godot_packed_string_array *r_functions); - int (*find_function)(godot_pluginscript_language_data *p_data, const godot_string *p_function, const godot_string *p_code); // Can be NULL + int (*find_function)(godot_pluginscript_language_data *p_data, const godot_string *p_function, const godot_string *p_code); // Can be nullptr godot_string (*make_function)(godot_pluginscript_language_data *p_data, const godot_string *p_class, const godot_string *p_name, const godot_packed_string_array *p_args); godot_error (*complete_code)(godot_pluginscript_language_data *p_data, const godot_string *p_code, const godot_string *p_path, godot_object *p_owner, godot_array *r_options, godot_bool *r_force, godot_string *r_call_hint); void (*auto_indent_code)(godot_pluginscript_language_data *p_data, godot_string *p_code, int p_from_line, int p_to_line); diff --git a/modules/gdnative/include/videodecoder/godot_videodecoder.h b/modules/gdnative/include/videodecoder/godot_videodecoder.h index 3e91a2e9ac..16c92abd22 100644 --- a/modules/gdnative/include/videodecoder/godot_videodecoder.h +++ b/modules/gdnative/include/videodecoder/godot_videodecoder.h @@ -46,7 +46,7 @@ typedef struct void *next; void *(*constructor)(godot_object *); void (*destructor)(void *); - const char *(*get_plugin_name)(void); + const char *(*get_plugin_name)(); const char **(*get_supported_extensions)(int *count); godot_bool (*open_file)(void *, void *); // data struct, and a FileAccess pointer godot_real (*get_length)(const void *); diff --git a/modules/gdnative/include/arvr/godot_arvr.h b/modules/gdnative/include/xr/godot_xr.h index aaef31a855..22f7f021c4 100644 --- a/modules/gdnative/include/arvr/godot_arvr.h +++ b/modules/gdnative/include/xr/godot_xr.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* godot_arvr.h */ +/* godot_xr.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_NATIVEARVR_H -#define GODOT_NATIVEARVR_H +#ifndef GODOT_NATIVEXR_H +#define GODOT_NATIVEXR_H #include <gdnative/gdnative.h> @@ -61,32 +61,31 @@ typedef struct { void (*fill_projection_for_eye)(void *, godot_real *, godot_int, godot_real, godot_real, godot_real); void (*commit_for_eye)(void *, godot_int, godot_rid *, godot_rect2 *); void (*process)(void *); - // only in 1.1 onwards godot_int (*get_external_texture_for_eye)(void *, godot_int); void (*notification)(void *, godot_int); godot_int (*get_camera_feed_id)(void *); -} godot_arvr_interface_gdnative; +} godot_xr_interface_gdnative; -void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface); +void GDAPI godot_xr_register_interface(const godot_xr_interface_gdnative *p_interface); -// helper functions to access ARVRServer data -godot_real GDAPI godot_arvr_get_worldscale(); -godot_transform GDAPI godot_arvr_get_reference_frame(); +// helper functions to access XRServer data +godot_real GDAPI godot_xr_get_worldscale(); +godot_transform GDAPI godot_xr_get_reference_frame(); // helper functions for rendering -void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect); -godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target); +void GDAPI godot_xr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect); +godot_int GDAPI godot_xr_get_texid(godot_rid *p_render_target); -// helper functions for updating ARVR controllers -godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position); -void GDAPI godot_arvr_remove_controller(godot_int p_controller_id); -void GDAPI godot_arvr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position); -void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed); -void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative); -godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id); +// helper functions for updating XR controllers +godot_int GDAPI godot_xr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position); +void GDAPI godot_xr_remove_controller(godot_int p_controller_id); +void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position); +void GDAPI godot_xr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed); +void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative); +godot_real GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id); #ifdef __cplusplus } #endif -#endif /* !GODOT_NATIVEARVR_H */ +#endif /* !GODOT_NATIVEXR_H */ diff --git a/modules/gdnative/nativescript/SCsub b/modules/gdnative/nativescript/SCsub index 92c9d6630d..4212e87a87 100644 --- a/modules/gdnative/nativescript/SCsub +++ b/modules/gdnative/nativescript/SCsub @@ -1,9 +1,9 @@ #!/usr/bin/env python -Import('env') -Import('env_gdnative') +Import("env") +Import("env_gdnative") -env_gdnative.add_source_files(env.modules_sources, '*.cpp') +env_gdnative.add_source_files(env.modules_sources, "*.cpp") -if "platform" in env and env["platform"] in ["x11", "iphone"]: +if "platform" in env and env["platform"] in ["linuxbsd", "iphone"]: env.Append(LINKFLAGS=["-rdynamic"]) diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp index 11fe746e90..62f2ec5024 100644 --- a/modules/gdnative/nativescript/api_generator.cpp +++ b/modules/gdnative/nativescript/api_generator.cpp @@ -41,12 +41,11 @@ // helper stuff static Error save_file(const String &p_path, const List<String> &p_content) { - FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE); ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE); - for (const List<String>::Element *e = p_content.front(); e != NULL; e = e->next()) { + for (const List<String>::Element *e = p_content.front(); e != nullptr; e = e->next()) { file->store_string(e->get()); } @@ -146,7 +145,6 @@ static String get_type_name(const PropertyInfo &info) { struct MethodInfoComparator { StringName::AlphCompare compare; bool operator()(const MethodInfo &p_a, const MethodInfo &p_b) const { - return compare(p_a.name, p_b.name); } }; @@ -154,7 +152,6 @@ struct MethodInfoComparator { struct PropertyInfoComparator { StringName::AlphCompare compare; bool operator()(const PropertyInfo &p_a, const PropertyInfo &p_b) const { - return compare(p_a.name, p_b.name); } }; @@ -162,7 +159,6 @@ struct PropertyInfoComparator { struct ConstantAPIComparator { NoCaseComparator compare; bool operator()(const ConstantAPI &p_a, const ConstantAPI &p_b) const { - return compare(p_a.constant_name, p_b.constant_name); } }; @@ -171,7 +167,6 @@ struct ConstantAPIComparator { * Reads the entire Godot API to a list */ List<ClassAPI> generate_c_api_classes() { - List<ClassAPI> api; List<StringName> classes; @@ -197,7 +192,7 @@ List<ClassAPI> generate_c_api_classes() { api.push_back(global_constants_api); } - for (List<StringName>::Element *e = classes.front(); e != NULL; e = e->next()) { + for (List<StringName>::Element *e = classes.front(); e != nullptr; e = e->next()) { StringName class_name = e->get(); ClassAPI class_api; @@ -229,7 +224,7 @@ List<ClassAPI> generate_c_api_classes() { List<String> constant; ClassDB::get_integer_constant_list(class_name, &constant, true); constant.sort_custom<NoCaseComparator>(); - for (List<String>::Element *c = constant.front(); c != NULL; c = c->next()) { + for (List<String>::Element *c = constant.front(); c != nullptr; c = c->next()) { ConstantAPI constant_api; constant_api.constant_name = c->get(); constant_api.constant_value = ClassDB::get_integer_constant(class_name, c->get()); @@ -284,7 +279,7 @@ List<ClassAPI> generate_c_api_classes() { ClassDB::get_property_list(class_name, &properties, true); properties.sort_custom<PropertyInfoComparator>(); - for (List<PropertyInfo>::Element *p = properties.front(); p != NULL; p = p->next()) { + for (List<PropertyInfo>::Element *p = properties.front(); p != nullptr; p = p->next()) { PropertyAPI property_api; property_api.name = p->get().name; @@ -312,7 +307,7 @@ List<ClassAPI> generate_c_api_classes() { ClassDB::get_method_list(class_name, &methods, true); methods.sort_custom<MethodInfoComparator>(); - for (List<MethodInfo>::Element *m = methods.front(); m != NULL; m = m->next()) { + for (List<MethodInfo>::Element *m = methods.front(); m != nullptr; m = m->next()) { MethodAPI method_api; MethodBind *method_bind = ClassDB::get_method(class_name, m->get().name); MethodInfo &method_info = m->get(); @@ -392,7 +387,7 @@ List<ClassAPI> generate_c_api_classes() { enum_api.name = E->get(); ClassDB::get_enum_constants(class_name, E->get(), &value_names, true); for (List<StringName>::Element *val_e = value_names.front(); val_e; val_e = val_e->next()) { - int int_val = ClassDB::get_integer_constant(class_name, val_e->get(), NULL); + int int_val = ClassDB::get_integer_constant(class_name, val_e->get(), nullptr); enum_api.values.push_back(Pair<int, String>(int_val, val_e->get())); } enum_api.values.sort_custom<PairSort<int, String>>(); @@ -410,14 +405,13 @@ List<ClassAPI> generate_c_api_classes() { * Generates the JSON source from the API in p_api */ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) { - // I'm sorry for the \t mess List<String> source; source.push_back("[\n"); - for (const List<ClassAPI>::Element *c = p_api.front(); c != NULL; c = c->next()) { + for (const List<ClassAPI>::Element *c = p_api.front(); c != nullptr; c = c->next()) { ClassAPI api = c->get(); source.push_back("\t{\n"); @@ -520,7 +514,6 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) { * p_path */ Error generate_c_api(const String &p_path) { - #ifndef TOOLS_ENABLED return ERR_BUG; #else diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp index f953206a34..1aea8ad160 100644 --- a/modules/gdnative/nativescript/godot_nativescript.cpp +++ b/modules/gdnative/nativescript/godot_nativescript.cpp @@ -52,7 +52,6 @@ extern "C" void _native_script_hook() { // Script API void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) { - String *s = (String *)p_gdnative_handle; Map<StringName, NativeScriptDesc> *classes = &NSL->library_classes[*s]; @@ -77,7 +76,7 @@ void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char } } else { - desc.base_data = NULL; + desc.base_data = nullptr; desc.base_native_type = p_base; } @@ -85,7 +84,6 @@ void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char } void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) { - String *s = (String *)p_gdnative_handle; Map<StringName, NativeScriptDesc> *classes = &NSL->library_classes[*s]; @@ -111,7 +109,7 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const } } else { - desc.base_data = NULL; + desc.base_data = nullptr; desc.base_native_type = p_base; } @@ -119,7 +117,6 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const } void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method) { - String *s = (String *)p_gdnative_handle; Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); @@ -139,7 +136,6 @@ void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const cha } void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func) { - String *s = (String *)p_gdnative_handle; Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); @@ -163,8 +159,7 @@ void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const c E->get().properties.insert(p_path, property); } -void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal) { - +void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_nativescript_signal *p_signal) { String *s = (String *)p_gdnative_handle; Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); @@ -176,7 +171,7 @@ void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const cha for (int i = 0; i < p_signal->num_args; i++) { PropertyInfo info; - godot_signal_argument arg = p_signal->args[i]; + godot_nativescript_signal_argument arg = p_signal->args[i]; info.hint = (PropertyHint)arg.hint; info.hint_string = *(String *)&arg.hint_string; @@ -189,7 +184,7 @@ void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const cha for (int i = 0; i < p_signal->num_default_args; i++) { Variant *v; - godot_signal_argument attrib = p_signal->args[i]; + godot_nativescript_signal_argument attrib = p_signal->args[i]; v = (Variant *)&attrib.default_value; @@ -209,12 +204,13 @@ void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const cha void GDAPI *godot_nativescript_get_userdata(godot_object *p_instance) { Object *instance = (Object *)p_instance; - if (!instance) - return NULL; + if (!instance) { + return nullptr; + } if (instance->get_script_instance() && instance->get_script_instance()->get_language() == NativeScriptLanguage::get_singleton()) { return ((NativeScriptInstance *)instance->get_script_instance())->userdata; } - return NULL; + return nullptr; } /* @@ -315,22 +311,22 @@ void GDAPI godot_nativescript_set_type_tag(void *p_gdnative_handle, const char * } const void GDAPI *godot_nativescript_get_type_tag(const godot_object *p_object) { - const Object *o = (Object *)p_object; if (!o->get_script_instance()) { - return NULL; + return nullptr; } else { NativeScript *script = Object::cast_to<NativeScript>(o->get_script_instance()->get_script().ptr()); if (!script) { - return NULL; + return nullptr; } - if (script->get_script_desc()) + if (script->get_script_desc()) { return script->get_script_desc()->type_tag; + } } - return NULL; + return nullptr; } int GDAPI godot_nativescript_register_instance_binding_data_functions(godot_instance_binding_functions p_binding_functions) { diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index fb88479ca3..f3dfd0b68e 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -111,6 +111,13 @@ void NativeScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) #endif +bool NativeScript::inherits_script(const Ref<Script> &p_script) const { +#ifndef _MSC_VER +#warning inheritance needs to be implemented in NativeScript +#endif + return false; +} + void NativeScript::set_class_name(String p_class_name) { class_name = p_class_name; } @@ -162,7 +169,6 @@ String NativeScript::get_script_class_icon_path() const { } bool NativeScript::can_instance() const { - NativeScriptDesc *script_data = get_script_desc(); #ifdef TOOLS_ENABLED @@ -178,8 +184,9 @@ bool NativeScript::can_instance() const { Ref<Script> NativeScript::get_base_script() const { NativeScriptDesc *script_data = get_script_desc(); - if (!script_data) + if (!script_data) { return Ref<Script>(); + } NativeScript *script = (NativeScript *)NSL->create_script(); Ref<NativeScript> ns = Ref<NativeScript>(script); @@ -193,18 +200,18 @@ Ref<Script> NativeScript::get_base_script() const { StringName NativeScript::get_instance_base_type() const { NativeScriptDesc *script_data = get_script_desc(); - if (!script_data) + if (!script_data) { return ""; + } return script_data->base_native_type; } ScriptInstance *NativeScript::instance_create(Object *p_this) { - NativeScriptDesc *script_data = get_script_desc(); if (!script_data) { - return NULL; + return nullptr; } NativeScriptInstance *nsi = memnew(NativeScriptInstance); @@ -214,7 +221,7 @@ ScriptInstance *NativeScript::instance_create(Object *p_this) { #ifndef TOOLS_ENABLED if (!ScriptServer::is_scripting_enabled()) { - nsi->userdata = NULL; + nsi->userdata = nullptr; } else { nsi->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); } @@ -240,7 +247,7 @@ PlaceHolderScriptInstance *NativeScript::placeholder_instance_create(Object *p_t return sins; #else - return NULL; + return nullptr; #endif } @@ -267,8 +274,9 @@ bool NativeScript::has_method(const StringName &p_method) const { NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - if (script_data->methods.has(p_method)) + if (script_data->methods.has(p_method)) { return true; + } script_data = script_data->base_data; } @@ -278,14 +286,16 @@ bool NativeScript::has_method(const StringName &p_method) const { MethodInfo NativeScript::get_method_info(const StringName &p_method) const { NativeScriptDesc *script_data = get_script_desc(); - if (!script_data) + if (!script_data) { return MethodInfo(); + } while (script_data) { Map<StringName, NativeScriptDesc::Method>::Element *M = script_data->methods.find(p_method); - if (M) + if (M) { return M->get().info; + } script_data = script_data->base_data; } @@ -299,8 +309,9 @@ bool NativeScript::is_valid() const { bool NativeScript::is_tool() const { NativeScriptDesc *script_data = get_script_desc(); - if (script_data) + if (script_data) { return script_data->is_tool; + } return false; } @@ -313,8 +324,9 @@ bool NativeScript::has_script_signal(const StringName &p_signal) const { NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - if (script_data->signals_.has(p_signal)) + if (script_data->signals_.has(p_signal)) { return true; + } script_data = script_data->base_data; } return false; @@ -323,13 +335,13 @@ bool NativeScript::has_script_signal(const StringName &p_signal) const { void NativeScript::get_script_signal_list(List<MethodInfo> *r_signals) const { NativeScriptDesc *script_data = get_script_desc(); - if (!script_data) + if (!script_data) { return; + } Set<MethodInfo> signals_; while (script_data) { - for (Map<StringName, NativeScriptDesc::Signal>::Element *S = script_data->signals_.front(); S; S = S->next()) { signals_.insert(S->get().signal); } @@ -350,8 +362,9 @@ bool NativeScript::get_property_default_value(const StringName &p_property, Vari P = script_data->properties.find(p_property); script_data = script_data->base_data; } - if (!P) + if (!P) { return false; + } r_value = P.get().default_value; return true; @@ -363,13 +376,13 @@ void NativeScript::update_exports() { void NativeScript::get_script_method_list(List<MethodInfo> *p_list) const { NativeScriptDesc *script_data = get_script_desc(); - if (!script_data) + if (!script_data) { return; + } Set<MethodInfo> methods; while (script_data) { - for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { methods.insert(E->get().info); } @@ -401,13 +414,11 @@ void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const { } Vector<ScriptNetData> NativeScript::get_rpc_methods() const { - Vector<ScriptNetData> v; NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { if (E->get().rpc_mode != GODOT_METHOD_RPC_MODE_DISABLED) { ScriptNetData nd; @@ -427,7 +438,6 @@ uint16_t NativeScript::get_rpc_method_id(const StringName &p_method) const { NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method); if (E) { return E->get().rpc_method_id; @@ -445,7 +455,6 @@ StringName NativeScript::get_rpc_method(uint16_t p_id) const { NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { if (E->get().rpc_method_id == p_id) { return E->key(); @@ -459,13 +468,11 @@ StringName NativeScript::get_rpc_method(uint16_t p_id) const { } MultiplayerAPI::RPCMode NativeScript::get_rpc_mode_by_id(uint16_t p_id) const { - ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED); NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { if (E->get().rpc_method_id == p_id) { switch (E->get().rpc_mode) { @@ -496,11 +503,9 @@ MultiplayerAPI::RPCMode NativeScript::get_rpc_mode_by_id(uint16_t p_id) const { } MultiplayerAPI::RPCMode NativeScript::get_rpc_mode(const StringName &p_method) const { - NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method); if (E) { switch (E->get().rpc_mode) { @@ -535,7 +540,6 @@ Vector<ScriptNetData> NativeScript::get_rset_properties() const { NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) { if (E.get().rset_mode != GODOT_METHOD_RPC_MODE_DISABLED) { ScriptNetData nd; @@ -554,7 +558,6 @@ uint16_t NativeScript::get_rset_property_id(const StringName &p_variable) const NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable); if (E) { return E.get().rset_property_id; @@ -572,7 +575,6 @@ StringName NativeScript::get_rset_property(uint16_t p_id) const { NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) { if (E.get().rset_property_id == p_id) { return E.key(); @@ -586,13 +588,11 @@ StringName NativeScript::get_rset_property(uint16_t p_id) const { } MultiplayerAPI::RPCMode NativeScript::get_rset_mode_by_id(uint16_t p_id) const { - ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED); NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) { if (E.get().rset_property_id == p_id) { switch (E.get().rset_mode) { @@ -623,11 +623,9 @@ MultiplayerAPI::RPCMode NativeScript::get_rset_mode_by_id(uint16_t p_id) const { } MultiplayerAPI::RPCMode NativeScript::get_rset_mode(const StringName &p_variable) const { - NativeScriptDesc *script_data = get_script_desc(); while (script_data) { - OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable); if (E) { switch (E.get().rset_mode) { @@ -670,7 +668,6 @@ String NativeScript::get_method_documentation(const StringName &p_method) const ERR_FAIL_COND_V_MSG(!script_data, "", "Attempt to get method documentation on invalid NativeScript."); while (script_data) { - Map<StringName, NativeScriptDesc::Method>::Element *method = script_data->methods.find(p_method); if (method) { @@ -689,7 +686,6 @@ String NativeScript::get_signal_documentation(const StringName &p_signal_name) c ERR_FAIL_COND_V_MSG(!script_data, "", "Attempt to get signal documentation on invalid NativeScript."); while (script_data) { - Map<StringName, NativeScriptDesc::Signal>::Element *signal = script_data->signals_.find(p_signal_name); if (signal) { @@ -708,7 +704,6 @@ String NativeScript::get_property_documentation(const StringName &p_path) const ERR_FAIL_COND_V_MSG(!script_data, "", "Attempt to get property documentation on invalid NativeScript."); while (script_data) { - OrderedHashMap<StringName, NativeScriptDesc::Property>::Element property = script_data->properties.find(p_path); if (property) { @@ -722,7 +717,6 @@ String NativeScript::get_property_documentation(const StringName &p_path) const } Variant NativeScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (lib_path.empty() || class_name.empty() || library.is_null()) { r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; return Variant(); @@ -738,7 +732,7 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Callable::Cal r_error.error = Callable::CallError::CALL_OK; REF ref; - Object *owner = NULL; + Object *owner = nullptr; if (!(script_data->base_native_type == "")) { owner = ClassDB::instance(script_data->base_native_type); @@ -833,6 +827,7 @@ bool NativeScriptInstance::set(const StringName &p_name, const Variant &p_value) } return false; } + bool NativeScriptInstance::get(const StringName &p_name, Variant &r_ret) const { NativeScriptDesc *script_data = GET_SCRIPT_DESC(); @@ -877,16 +872,14 @@ void NativeScriptInstance::get_property_list(List<PropertyInfo> *p_properties) c NativeScriptDesc *script_data = GET_SCRIPT_DESC(); while (script_data) { - Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find("_get_property_list"); if (E) { - godot_variant result; result = E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, 0, - NULL); + nullptr); Variant res = *(Variant *)&result; godot_variant_destroy(&result); @@ -929,11 +922,9 @@ void NativeScriptInstance::get_property_list(List<PropertyInfo> *p_properties) c } Variant::Type NativeScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { - NativeScriptDesc *script_data = GET_SCRIPT_DESC(); while (script_data) { - OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = script_data->properties.find(p_name); if (P) { *r_is_valid = true; @@ -954,7 +945,6 @@ bool NativeScriptInstance::has_method(const StringName &p_method) const { } Variant NativeScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - NativeScriptDesc *script_data = GET_SCRIPT_DESC(); while (script_data) { @@ -1007,26 +997,29 @@ void NativeScriptInstance::notification(int p_notification) { String NativeScriptInstance::to_string(bool *r_valid) { if (has_method(CoreStringNames::get_singleton()->_to_string)) { Callable::CallError ce; - Variant ret = call(CoreStringNames::get_singleton()->_to_string, NULL, 0, ce); + Variant ret = call(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce); if (ce.error == Callable::CallError::CALL_OK) { if (ret.get_type() != Variant::STRING) { - if (r_valid) + if (r_valid) { *r_valid = false; + } ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String."); } - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret.operator String(); } } - if (r_valid) + if (r_valid) { *r_valid = false; + } return String(); } void NativeScriptInstance::refcount_incremented() { Callable::CallError err; - call("_refcount_incremented", NULL, 0, err); + call("_refcount_incremented", nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK && err.error != Callable::CallError::CALL_ERROR_INVALID_METHOD) { ERR_PRINT("Failed to invoke _refcount_incremented - should not happen"); } @@ -1034,7 +1027,7 @@ void NativeScriptInstance::refcount_incremented() { bool NativeScriptInstance::refcount_decremented() { Callable::CallError err; - Variant ret = call("_refcount_decremented", NULL, 0, err); + Variant ret = call("_refcount_decremented", nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK && err.error != Callable::CallError::CALL_ERROR_INVALID_METHOD) { ERR_PRINT("Failed to invoke _refcount_decremented - should not happen"); return true; // assume we can destroy the object @@ -1120,11 +1113,11 @@ void NativeScriptInstance::call_multilevel_reversed(const StringName &p_method, } NativeScriptInstance::~NativeScriptInstance() { - NativeScriptDesc *script_data = GET_SCRIPT_DESC(); - if (!script_data) + if (!script_data) { return; + } script_data->destroy_func.destroy_func((godot_object *)owner, script_data->destroy_func.method_data, userdata); @@ -1138,16 +1131,13 @@ NativeScriptInstance::~NativeScriptInstance() { NativeScriptLanguage *NativeScriptLanguage::singleton; void NativeScriptLanguage::_unload_stuff(bool p_reload) { - Map<String, Ref<GDNative>> erase_and_unload; for (Map<String, Map<StringName, NativeScriptDesc>>::Element *L = library_classes.front(); L; L = L->next()) { - String lib_path = L->key(); Map<StringName, NativeScriptDesc> classes = L->get(); if (p_reload) { - Map<String, Ref<GDNative>>::Element *E = library_gdnatives.find(lib_path); Ref<GDNative> gdn; @@ -1177,28 +1167,32 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) { } for (Map<StringName, NativeScriptDesc>::Element *C = classes.front(); C; C = C->next()) { - // free property stuff first for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = C->get().properties.front(); P; P = P.next()) { - if (P.get().getter.free_func) + if (P.get().getter.free_func) { P.get().getter.free_func(P.get().getter.method_data); + } - if (P.get().setter.free_func) + if (P.get().setter.free_func) { P.get().setter.free_func(P.get().setter.method_data); + } } // free method stuff for (Map<StringName, NativeScriptDesc::Method>::Element *M = C->get().methods.front(); M; M = M->next()) { - if (M->get().method.free_func) + if (M->get().method.free_func) { M->get().method.free_func(M->get().method.method_data); + } } // free constructor/destructor - if (C->get().create_func.free_func) + if (C->get().create_func.free_func) { C->get().create_func.free_func(C->get().create_func.method_data); + } - if (C->get().destroy_func.free_func) + if (C->get().destroy_func.free_func) { C->get().destroy_func.free_func(C->get().destroy_func.method_data); + } } erase_and_unload.insert(lib_path, gdn); @@ -1246,13 +1240,10 @@ NativeScriptLanguage::NativeScriptLanguage() { } NativeScriptLanguage::~NativeScriptLanguage() { - for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { - Ref<GDNative> lib = L->get(); // only shut down valid libs, duh! if (lib.is_valid()) { - // If it's a singleton-library then the gdnative module // manages the destruction at engine shutdown, not NativeScript. if (!lib->get_library()->is_singleton()) { @@ -1278,7 +1269,6 @@ void _add_reload_node() { } void NativeScriptLanguage::init() { - #if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) List<String> args = OS::get_singleton()->get_cmdline_args(); @@ -1297,22 +1287,29 @@ void NativeScriptLanguage::init() { EditorNode::add_init_callback(&_add_reload_node); #endif } + String NativeScriptLanguage::get_type() const { return "NativeScript"; } + String NativeScriptLanguage::get_extension() const { return "gdns"; } + Error NativeScriptLanguage::execute_file(const String &p_path) { return OK; // Qué? } + void NativeScriptLanguage::finish() { _unload_stuff(); } + void NativeScriptLanguage::get_reserved_words(List<String> *p_words) const { } + void NativeScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { } + void NativeScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { } @@ -1321,6 +1318,7 @@ Ref<Script> NativeScriptLanguage::get_template(const String &p_class_name, const s->set_class_name(p_class_name); return Ref<NativeScript>(s); } + bool NativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const { return true; } @@ -1329,20 +1327,26 @@ Script *NativeScriptLanguage::create_script() const { NativeScript *script = memnew(NativeScript); return script; } + bool NativeScriptLanguage::has_named_classes() const { return true; } + bool NativeScriptLanguage::supports_builtin_mode() const { return true; } + int NativeScriptLanguage::find_function(const String &p_function, const String &p_code) const { return -1; } + String NativeScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const { return ""; } + void NativeScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_to_line) const { } + void NativeScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) { } @@ -1350,27 +1354,36 @@ void NativeScriptLanguage::add_global_constant(const StringName &p_variable, con String NativeScriptLanguage::debug_get_error() const { return ""; } + int NativeScriptLanguage::debug_get_stack_level_count() const { return -1; } + int NativeScriptLanguage::debug_get_stack_level_line(int p_level) const { return -1; } + String NativeScriptLanguage::debug_get_stack_level_function(int p_level) const { return ""; } + String NativeScriptLanguage::debug_get_stack_level_source(int p_level) const { return ""; } + void NativeScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { } + void NativeScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { } + void NativeScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { } + String NativeScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { return ""; } + // Debugging stuff end. void NativeScriptLanguage::reload_all_scripts() { @@ -1378,6 +1391,7 @@ void NativeScriptLanguage::reload_all_scripts() { void NativeScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { } + void NativeScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("gdns"); } @@ -1412,8 +1426,9 @@ int NativeScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_a int current = 0; for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) { - if (current >= p_info_max) + if (current >= p_info_max) { break; + } p_info_arr[current].call_count = d->get().call_count; p_info_arr[current].self_time = d->get().self_time; @@ -1435,8 +1450,9 @@ int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, in int current = 0; for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) { - if (current >= p_info_max) + if (current >= p_info_max) { break; + } if (d->get().last_frame_call_count) { p_info_arr[current].call_count = d->get().last_frame_call_count; @@ -1483,7 +1499,6 @@ void NativeScriptLanguage::profiling_add_data(StringName p_signature, uint64_t p } int NativeScriptLanguage::register_binding_functions(godot_instance_binding_functions p_binding_functions) { - // find index int idx = -1; @@ -1514,25 +1529,28 @@ void NativeScriptLanguage::unregister_binding_functions(int p_idx) { for (Set<Vector<void *> *>::Element *E = binding_instances.front(); E; E = E->next()) { Vector<void *> &binding_data = *E->get(); - if (p_idx < binding_data.size() && binding_data[p_idx] && binding_functions[p_idx].second.free_instance_binding_data) + if (p_idx < binding_data.size() && binding_data[p_idx] && binding_functions[p_idx].second.free_instance_binding_data) { binding_functions[p_idx].second.free_instance_binding_data(binding_functions[p_idx].second.data, binding_data[p_idx]); + } } binding_functions.write[p_idx].first = false; - if (binding_functions[p_idx].second.free_func) + if (binding_functions[p_idx].second.free_func) { binding_functions[p_idx].second.free_func(binding_functions[p_idx].second.data); + } } void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_object) { - ERR_FAIL_INDEX_V(p_idx, binding_functions.size(), NULL); + ERR_FAIL_INDEX_V(p_idx, binding_functions.size(), nullptr); - ERR_FAIL_COND_V_MSG(!binding_functions[p_idx].first, NULL, "Tried to get binding data for a nativescript binding that does not exist."); + ERR_FAIL_COND_V_MSG(!binding_functions[p_idx].first, nullptr, "Tried to get binding data for a nativescript binding that does not exist."); Vector<void *> *binding_data = (Vector<void *> *)p_object->get_script_instance_binding(lang_idx); - if (!binding_data) - return NULL; // should never happen. + if (!binding_data) { + return nullptr; // should never happen. + } if (binding_data->size() <= p_idx) { // okay, add new elements here. @@ -1541,12 +1559,11 @@ void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_objec binding_data->resize(p_idx + 1); for (int i = old_size; i <= p_idx; i++) { - (*binding_data).write[i] = NULL; + (*binding_data).write[i] = nullptr; } } if (!(*binding_data)[p_idx]) { - const void *global_type_tag = get_global_type_tag(p_idx, p_object->get_class_name()); // no binding data yet, soooooo alloc new one \o/ @@ -1557,13 +1574,12 @@ void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_objec } void *NativeScriptLanguage::alloc_instance_binding_data(Object *p_object) { - Vector<void *> *binding_data = new Vector<void *>; binding_data->resize(binding_functions.size()); for (int i = 0; i < binding_functions.size(); i++) { - (*binding_data).write[i] = NULL; + (*binding_data).write[i] = nullptr; } binding_instances.insert(binding_data); @@ -1572,15 +1588,16 @@ void *NativeScriptLanguage::alloc_instance_binding_data(Object *p_object) { } void NativeScriptLanguage::free_instance_binding_data(void *p_data) { - - if (!p_data) + if (!p_data) { return; + } Vector<void *> &binding_data = *(Vector<void *> *)p_data; for (int i = 0; i < binding_data.size(); i++) { - if (!binding_data[i]) + if (!binding_data[i]) { continue; + } if (binding_functions[i].first && binding_functions[i].second.free_instance_binding_data) { binding_functions[i].second.free_instance_binding_data(binding_functions[i].second.data, binding_data[i]); @@ -1593,20 +1610,22 @@ void NativeScriptLanguage::free_instance_binding_data(void *p_data) { } void NativeScriptLanguage::refcount_incremented_instance_binding(Object *p_object) { - void *data = p_object->get_script_instance_binding(lang_idx); - if (!data) + if (!data) { return; + } Vector<void *> &binding_data = *(Vector<void *> *)data; for (int i = 0; i < binding_data.size(); i++) { - if (!binding_data[i]) + if (!binding_data[i]) { continue; + } - if (!binding_functions[i].first) + if (!binding_functions[i].first) { continue; + } if (binding_functions[i].second.refcount_incremented_instance_binding) { binding_functions[i].second.refcount_incremented_instance_binding(binding_data[i], p_object); @@ -1615,22 +1634,24 @@ void NativeScriptLanguage::refcount_incremented_instance_binding(Object *p_objec } bool NativeScriptLanguage::refcount_decremented_instance_binding(Object *p_object) { - void *data = p_object->get_script_instance_binding(lang_idx); - if (!data) + if (!data) { return true; + } Vector<void *> &binding_data = *(Vector<void *> *)data; bool can_die = true; for (int i = 0; i < binding_data.size(); i++) { - if (!binding_data[i]) + if (!binding_data[i]) { continue; + } - if (!binding_functions[i].first) + if (!binding_functions[i].first) { continue; + } if (binding_functions[i].second.refcount_decremented_instance_binding) { can_die = can_die && binding_functions[i].second.refcount_decremented_instance_binding(binding_data[i], p_object); @@ -1651,13 +1672,15 @@ void NativeScriptLanguage::set_global_type_tag(int p_idx, StringName p_class_nam } const void *NativeScriptLanguage::get_global_type_tag(int p_idx, StringName p_class_name) const { - if (!global_type_tags.has(p_idx)) - return NULL; + if (!global_type_tags.has(p_idx)) { + return nullptr; + } const HashMap<StringName, const void *> &tags = global_type_tags[p_idx]; - if (!tags.has(p_class_name)) - return NULL; + if (!tags.has(p_class_name)) { + return nullptr; + } const void *tag = tags.get(p_class_name); @@ -1693,8 +1716,9 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) { library_classes.insert(lib_path, Map<StringName, NativeScriptDesc>()); - if (!library_script_users.has(lib_path)) + if (!library_script_users.has(lib_path)) { library_script_users.insert(lib_path, Set<NativeScript *>()); + } void *proc_ptr; @@ -1734,13 +1758,11 @@ void NativeScriptLanguage::unregister_script(NativeScript *script) { void NativeScriptLanguage::call_libraries_cb(const StringName &name) { // library_gdnatives is modified only from the main thread, so it's safe not to use mutex here for (Map<String, Ref<GDNative>>::Element *L = library_gdnatives.front(); L; L = L->next()) { - if (L->get().is_null()) { continue; } if (L->get()->is_initialized()) { - void *proc_ptr; Error err = L->get()->get_symbol(L->get()->get_library()->get_symbol_prefix() + name, proc_ptr); @@ -1805,16 +1827,20 @@ String NativeScriptLanguage::get_global_class_name(const String &p_path, String if (!p_path.empty()) { Ref<NativeScript> script = ResourceLoader::load(p_path, "NativeScript"); if (script.is_valid()) { - if (r_base_type) + if (r_base_type) { *r_base_type = script->get_instance_base_type(); - if (r_icon_path) + } + if (r_icon_path) { *r_icon_path = script->get_script_class_icon_path(); + } return script->get_script_class_name(); } - if (r_base_type) + if (r_base_type) { *r_base_type = String(); - if (r_icon_path) + } + if (r_icon_path) { *r_icon_path = String(); + } } return String(); } @@ -1827,15 +1853,14 @@ void NativeReloadNode::_notification(int p_what) { #ifdef TOOLS_ENABLED switch (p_what) { - case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { - - if (unloaded) + case NOTIFICATION_WM_FOCUS_OUT: { + if (unloaded) { break; + } MutexLock lock(NSL->mutex); NSL->_unload_stuff(true); for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { - Ref<GDNative> gdn = L->get(); if (gdn.is_null()) { @@ -1862,15 +1887,14 @@ void NativeReloadNode::_notification(int p_what) { } break; - case MainLoop::NOTIFICATION_WM_FOCUS_IN: { - - if (!unloaded) + case NOTIFICATION_WM_FOCUS_IN: { + if (!unloaded) { break; + } MutexLock lock(NSL->mutex); Set<StringName> libs_to_remove; for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { - Ref<GDNative> gdn = L->get(); if (gdn.is_null()) { @@ -1908,8 +1932,9 @@ void NativeReloadNode::_notification(int p_what) { for (Set<NativeScript *>::Element *S = U->get().front(); S; S = S->next()) { NativeScript *script = S->get(); - if (script->placeholders.size() == 0) + if (script->placeholders.size() == 0) { continue; + } for (Set<PlaceHolderScriptInstance *>::Element *P = script->placeholders.front(); P; P = P->next()) { script->_update_placeholder(P->get()); @@ -1931,7 +1956,7 @@ void NativeReloadNode::_notification(int p_what) { #endif } -RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { +RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { return ResourceFormatLoaderText::singleton->load(p_path, p_original_path, r_error); } @@ -1945,8 +1970,9 @@ bool ResourceFormatLoaderNativeScript::handles_type(const String &p_type) const String ResourceFormatLoaderNativeScript::get_resource_type(const String &p_path) const { String el = p_path.get_extension().to_lower(); - if (el == "gdns") + if (el == "gdns") { return "NativeScript"; + } return ""; } @@ -1956,7 +1982,7 @@ Error ResourceFormatSaverNativeScript::save(const String &p_path, const RES &p_r } bool ResourceFormatSaverNativeScript::recognize(const RES &p_resource) const { - return Object::cast_to<NativeScript>(*p_resource) != NULL; + return Object::cast_to<NativeScript>(*p_resource) != nullptr; } void ResourceFormatSaverNativeScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index aba3f6b2d0..1aca142889 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -43,10 +43,10 @@ #include "scene/main/node.h" #include "modules/gdnative/gdnative.h" + #include <nativescript/godot_nativescript.h> struct NativeScriptDesc { - struct Method { godot_instance_method method; MethodInfo info; @@ -54,6 +54,7 @@ struct NativeScriptDesc { uint16_t rpc_method_id; String documentation; }; + struct Property { godot_property_set_func setter; godot_property_get_func getter; @@ -69,9 +70,9 @@ struct NativeScriptDesc { String documentation; }; - uint16_t rpc_count; + uint16_t rpc_count = 0; Map<StringName, Method> methods; - uint16_t rset_count; + uint16_t rset_count = 0; OrderedHashMap<StringName, Property> properties; Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals StringName base; @@ -82,20 +83,11 @@ struct NativeScriptDesc { String documentation; - const void *type_tag; + const void *type_tag = nullptr; bool is_tool; - inline NativeScriptDesc() : - rpc_count(0), - methods(), - rset_count(0), - properties(), - signals_(), - base(), - base_native_type(), - documentation(), - type_tag(NULL) { + inline NativeScriptDesc() { zeromem(&create_func, sizeof(godot_instance_create_func)); zeromem(&destroy_func, sizeof(godot_instance_destroy_func)); } @@ -133,6 +125,8 @@ protected: public: inline NativeScriptDesc *get_script_desc() const; + bool inherits_script(const Ref<Script> &p_script) const; + void set_class_name(String p_class_name); String get_class_name() const; @@ -199,7 +193,6 @@ public: }; class NativeScriptInstance : public ScriptInstance { - friend class NativeScript; Object *owner; @@ -250,7 +243,6 @@ public: class NativeReloadNode; class NativeScriptLanguage : public ScriptLanguage { - friend class NativeScript; friend class NativeScriptInstance; friend class NativeReloadNode; @@ -341,7 +333,7 @@ public: virtual void get_comment_delimiters(List<String> *p_delimiters) const; virtual void get_string_delimiters(List<String> *p_delimiters) const; virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; - virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings = NULL, Set<int> *r_safe_lines = NULL) const; + virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const; virtual Script *create_script() const; virtual bool has_named_classes() const; virtual bool supports_builtin_mode() const; @@ -389,24 +381,23 @@ public: inline NativeScriptDesc *NativeScript::get_script_desc() const { Map<StringName, NativeScriptDesc>::Element *E = NativeScriptLanguage::singleton->library_classes[lib_path].find(class_name); - return E ? &E->get() : NULL; + return E ? &E->get() : nullptr; } class NativeReloadNode : public Node { GDCLASS(NativeReloadNode, Node); - bool unloaded; + bool unloaded = false; public: static void _bind_methods(); void _notification(int p_what); - NativeReloadNode() : - unloaded(false) {} + NativeReloadNode() {} }; class ResourceFormatLoaderNativeScript : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/gdnative/nativescript/register_types.cpp b/modules/gdnative/nativescript/register_types.cpp index b5e8174e43..ac8c7ab2fd 100644 --- a/modules/gdnative/nativescript/register_types.cpp +++ b/modules/gdnative/nativescript/register_types.cpp @@ -58,7 +58,6 @@ void register_nativescript_types() { } void unregister_nativescript_types() { - ResourceLoader::remove_resource_format_loader(resource_loader_gdns); resource_loader_gdns.unref(); diff --git a/modules/gdnative/nativescript/register_types.h b/modules/gdnative/nativescript/register_types.h index 8fcecb9836..088bf38dd5 100644 --- a/modules/gdnative/nativescript/register_types.h +++ b/modules/gdnative/nativescript/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef NATIVESCRIPT_REGISTER_TYPES_H +#define NATIVESCRIPT_REGISTER_TYPES_H + void register_nativescript_types(); void unregister_nativescript_types(); + +#endif // NATIVESCRIPT_REGISTER_TYPES_H diff --git a/modules/gdnative/net/SCsub b/modules/gdnative/net/SCsub index 18ab9986b0..b76500c003 100644 --- a/modules/gdnative/net/SCsub +++ b/modules/gdnative/net/SCsub @@ -1,13 +1,12 @@ #!/usr/bin/env python -Import('env') -Import('env_gdnative') +Import("env") +Import("env_gdnative") env_net = env_gdnative.Clone() has_webrtc = env_net["module_webrtc_enabled"] if has_webrtc: - env_net.Append(CPPDEFINES=['WEBRTC_GDNATIVE_ENABLED']) - -env_net.add_source_files(env.modules_sources, '*.cpp') + env_net.Append(CPPDEFINES=["WEBRTC_GDNATIVE_ENABLED"]) +env_net.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/gdnative/net/multiplayer_peer_gdnative.cpp b/modules/gdnative/net/multiplayer_peer_gdnative.cpp index 8c43a79cc5..997eec6425 100644 --- a/modules/gdnative/net/multiplayer_peer_gdnative.cpp +++ b/modules/gdnative/net/multiplayer_peer_gdnative.cpp @@ -31,7 +31,7 @@ #include "multiplayer_peer_gdnative.h" MultiplayerPeerGDNative::MultiplayerPeerGDNative() { - interface = NULL; + interface = nullptr; } MultiplayerPeerGDNative::~MultiplayerPeerGDNative() { @@ -42,73 +42,73 @@ void MultiplayerPeerGDNative::set_native_multiplayer_peer(const godot_net_multip } Error MultiplayerPeerGDNative::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->get_packet(interface->data, r_buffer, &r_buffer_size); } Error MultiplayerPeerGDNative::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->put_packet(interface->data, p_buffer, p_buffer_size); } int MultiplayerPeerGDNative::get_max_packet_size() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_max_packet_size(interface->data); } int MultiplayerPeerGDNative::get_available_packet_count() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_available_packet_count(interface->data); } /* NetworkedMultiplayerPeer */ void MultiplayerPeerGDNative::set_transfer_mode(TransferMode p_mode) { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->set_transfer_mode(interface->data, (godot_int)p_mode); } NetworkedMultiplayerPeer::TransferMode MultiplayerPeerGDNative::get_transfer_mode() const { - ERR_FAIL_COND_V(interface == NULL, TRANSFER_MODE_UNRELIABLE); + ERR_FAIL_COND_V(interface == nullptr, TRANSFER_MODE_UNRELIABLE); return (TransferMode)interface->get_transfer_mode(interface->data); } void MultiplayerPeerGDNative::set_target_peer(int p_peer_id) { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->set_target_peer(interface->data, p_peer_id); } int MultiplayerPeerGDNative::get_packet_peer() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_packet_peer(interface->data); } bool MultiplayerPeerGDNative::is_server() const { - ERR_FAIL_COND_V(interface == NULL, false); + ERR_FAIL_COND_V(interface == nullptr, false); return interface->is_server(interface->data); } void MultiplayerPeerGDNative::poll() { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->poll(interface->data); } int MultiplayerPeerGDNative::get_unique_id() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_unique_id(interface->data); } void MultiplayerPeerGDNative::set_refuse_new_connections(bool p_enable) { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->set_refuse_new_connections(interface->data, p_enable); } bool MultiplayerPeerGDNative::is_refusing_new_connections() const { - ERR_FAIL_COND_V(interface == NULL, true); + ERR_FAIL_COND_V(interface == nullptr, true); return interface->is_refusing_new_connections(interface->data); } NetworkedMultiplayerPeer::ConnectionStatus MultiplayerPeerGDNative::get_connection_status() const { - ERR_FAIL_COND_V(interface == NULL, CONNECTION_DISCONNECTED); + ERR_FAIL_COND_V(interface == nullptr, CONNECTION_DISCONNECTED); return (ConnectionStatus)interface->get_connection_status(interface->data); } @@ -120,7 +120,6 @@ void MultiplayerPeerGDNative::_bind_methods() { extern "C" { void GDAPI godot_net_bind_multiplayer_peer(godot_object *p_obj, const godot_net_multiplayer_peer *p_impl) { - ((MultiplayerPeerGDNative *)p_obj)->set_native_multiplayer_peer(p_impl); } } diff --git a/modules/gdnative/net/packet_peer_gdnative.cpp b/modules/gdnative/net/packet_peer_gdnative.cpp index 75e1e0b824..6bb21cb48d 100644 --- a/modules/gdnative/net/packet_peer_gdnative.cpp +++ b/modules/gdnative/net/packet_peer_gdnative.cpp @@ -31,7 +31,7 @@ #include "packet_peer_gdnative.h" PacketPeerGDNative::PacketPeerGDNative() { - interface = NULL; + interface = nullptr; } PacketPeerGDNative::~PacketPeerGDNative() { @@ -45,29 +45,28 @@ void PacketPeerGDNative::_bind_methods() { } Error PacketPeerGDNative::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->get_packet(interface->data, r_buffer, &r_buffer_size); } Error PacketPeerGDNative::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->put_packet(interface->data, p_buffer, p_buffer_size); } int PacketPeerGDNative::get_max_packet_size() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_max_packet_size(interface->data); } int PacketPeerGDNative::get_available_packet_count() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_available_packet_count(interface->data); } extern "C" { void GDAPI godot_net_bind_packet_peer(godot_object *p_obj, const godot_net_packet_peer *p_impl) { - ((PacketPeerGDNative *)p_obj)->set_native_packet_peer(p_impl); } } diff --git a/modules/gdnative/net/register_types.h b/modules/gdnative/net/register_types.h index 526bc49deb..70b266f9b9 100644 --- a/modules/gdnative/net/register_types.h +++ b/modules/gdnative/net/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef NET_REGISTER_TYPES_H +#define NET_REGISTER_TYPES_H + void register_net_types(); void unregister_net_types(); + +#endif // NET_REGISTER_TYPES_H diff --git a/modules/gdnative/net/stream_peer_gdnative.cpp b/modules/gdnative/net/stream_peer_gdnative.cpp index 22634daf5f..9dcb184115 100644 --- a/modules/gdnative/net/stream_peer_gdnative.cpp +++ b/modules/gdnative/net/stream_peer_gdnative.cpp @@ -31,7 +31,7 @@ #include "stream_peer_gdnative.h" StreamPeerGDNative::StreamPeerGDNative() { - interface = NULL; + interface = nullptr; } StreamPeerGDNative::~StreamPeerGDNative() { @@ -45,27 +45,27 @@ void StreamPeerGDNative::_bind_methods() { } Error StreamPeerGDNative::put_data(const uint8_t *p_data, int p_bytes) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)(interface->put_data(interface->data, p_data, p_bytes)); } Error StreamPeerGDNative::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)(interface->put_partial_data(interface->data, p_data, p_bytes, &r_sent)); } Error StreamPeerGDNative::get_data(uint8_t *p_buffer, int p_bytes) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)(interface->get_data(interface->data, p_buffer, p_bytes)); } Error StreamPeerGDNative::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)(interface->get_partial_data(interface->data, p_buffer, p_bytes, &r_received)); } int StreamPeerGDNative::get_available_bytes() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_available_bytes(interface->data); } diff --git a/modules/gdnative/net/stream_peer_gdnative.h b/modules/gdnative/net/stream_peer_gdnative.h index f3711e0f0f..0b2f995aa7 100644 --- a/modules/gdnative/net/stream_peer_gdnative.h +++ b/modules/gdnative/net/stream_peer_gdnative.h @@ -36,7 +36,6 @@ #include "modules/gdnative/include/net/godot_net.h" class StreamPeerGDNative : public StreamPeer { - GDCLASS(StreamPeerGDNative, StreamPeer); protected: diff --git a/modules/gdnative/pluginscript/SCsub b/modules/gdnative/pluginscript/SCsub index 20eaa99592..0b2db3b504 100644 --- a/modules/gdnative/pluginscript/SCsub +++ b/modules/gdnative/pluginscript/SCsub @@ -1,6 +1,6 @@ #!/usr/bin/env python -Import('env') -Import('env_gdnative') +Import("env") +Import("env_gdnative") -env_gdnative.add_source_files(env.modules_sources, '*.cpp') +env_gdnative.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp index 22e8372130..7d17a7d5ab 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.cpp +++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp @@ -156,7 +156,7 @@ bool PluginScriptInstance::init(PluginScript *p_script, Object *p_owner) { _script = Ref<PluginScript>(p_script); _desc = &p_script->_desc->instance_desc; _data = _desc->init(p_script->_data, (godot_object *)p_owner); - ERR_FAIL_COND_V(_data == NULL, false); + ERR_FAIL_COND_V(_data == nullptr, false); p_owner->set_script_instance(this); return true; } diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h index c91ad643a7..6309b6fde3 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.h +++ b/modules/gdnative/pluginscript/pluginscript_instance.h @@ -55,7 +55,7 @@ public: virtual bool set(const StringName &p_name, const Variant &p_value); virtual bool get(const StringName &p_name, Variant &r_ret) const; virtual void get_property_list(List<PropertyInfo> *p_properties) const; - virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const; + virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const; virtual void get_method_list(List<MethodInfo> *p_list) const; virtual bool has_method(const StringName &p_method) const; diff --git a/modules/gdnative/pluginscript/pluginscript_language.h b/modules/gdnative/pluginscript/pluginscript_language.h index 809034744a..dd6758713f 100644 --- a/modules/gdnative/pluginscript/pluginscript_language.h +++ b/modules/gdnative/pluginscript/pluginscript_language.h @@ -74,7 +74,7 @@ public: virtual void get_comment_delimiters(List<String> *p_delimiters) const; virtual void get_string_delimiters(List<String> *p_delimiters) const; virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; - virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL, List<ScriptLanguage::Warning> *r_warnings = NULL, Set<int> *r_safe_lines = NULL) const; + virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const; virtual Script *create_script() const; virtual bool has_named_classes() const; virtual bool supports_builtin_mode() const; diff --git a/modules/gdnative/pluginscript/pluginscript_loader.cpp b/modules/gdnative/pluginscript/pluginscript_loader.cpp index 46db20b6c2..4feee4f4a5 100644 --- a/modules/gdnative/pluginscript/pluginscript_loader.cpp +++ b/modules/gdnative/pluginscript/pluginscript_loader.cpp @@ -39,9 +39,10 @@ ResourceFormatLoaderPluginScript::ResourceFormatLoaderPluginScript(PluginScriptL _language = language; } -RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - if (r_error) +RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_FILE_CANT_OPEN; + } PluginScript *script = memnew(PluginScript); script->init(_language); @@ -55,8 +56,9 @@ RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p script->reload(); - if (r_error) + if (r_error) { *r_error = OK; + } return scriptres; } @@ -71,8 +73,9 @@ bool ResourceFormatLoaderPluginScript::handles_type(const String &p_type) const String ResourceFormatLoaderPluginScript::get_resource_type(const String &p_path) const { String el = p_path.get_extension().to_lower(); - if (el == _language->get_extension()) + if (el == _language->get_extension()) { return _language->get_type(); + } return ""; } @@ -101,13 +104,11 @@ Error ResourceFormatSaverPluginScript::save(const String &p_path, const RES &p_r } void ResourceFormatSaverPluginScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (Object::cast_to<PluginScript>(*p_resource)) { p_extensions->push_back(_language->get_extension()); } } bool ResourceFormatSaverPluginScript::recognize(const RES &p_resource) const { - - return Object::cast_to<PluginScript>(*p_resource) != NULL; + return Object::cast_to<PluginScript>(*p_resource) != nullptr; } diff --git a/modules/gdnative/pluginscript/pluginscript_loader.h b/modules/gdnative/pluginscript/pluginscript_loader.h index a039072fdc..35fc79c2ca 100644 --- a/modules/gdnative/pluginscript/pluginscript_loader.h +++ b/modules/gdnative/pluginscript/pluginscript_loader.h @@ -39,19 +39,17 @@ class PluginScriptLanguage; class ResourceFormatLoaderPluginScript : public ResourceFormatLoader { - PluginScriptLanguage *_language; public: ResourceFormatLoaderPluginScript(PluginScriptLanguage *language); - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; }; class ResourceFormatSaverPluginScript : public ResourceFormatSaver { - PluginScriptLanguage *_language; public: diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp index b7cbedc51a..87c6288806 100644 --- a/modules/gdnative/pluginscript/pluginscript_script.cpp +++ b/modules/gdnative/pluginscript/pluginscript_script.cpp @@ -56,7 +56,6 @@ void PluginScript::_bind_methods() { } PluginScriptInstance *PluginScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_OK; // Create instance @@ -69,7 +68,7 @@ PluginScriptInstance *PluginScript::_create_instance(const Variant **p_args, int } else { r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; memdelete(instance); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } // Construct @@ -84,7 +83,6 @@ PluginScriptInstance *PluginScript::_create_instance(const Variant **p_args, int } Variant PluginScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_OK; if (!_valid) { @@ -93,7 +91,7 @@ Variant PluginScript::_new(const Variant **p_args, int p_argcount, Callable::Cal } REF ref; - Object *owner = NULL; + Object *owner = nullptr; if (get_instance_base_type() == "") { owner = memnew(Reference); @@ -140,6 +138,13 @@ bool PluginScript::can_instance() const { return can; } +bool PluginScript::inherits_script(const Ref<Script> &p_script) const { +#ifndef _MSC_VER +#warning inheritance needs to be implemented in PluginScript +#endif + return false; +} + Ref<Script> PluginScript::get_base_script() const { if (_ref_base_parent.is_valid()) { return Ref<PluginScript>(_ref_base_parent); @@ -149,10 +154,12 @@ Ref<Script> PluginScript::get_base_script() const { } StringName PluginScript::get_instance_base_type() const { - if (_native_parent) + if (_native_parent) { return _native_parent; - if (_ref_base_parent.is_valid()) + } + if (_ref_base_parent.is_valid()) { return _ref_base_parent->get_instance_base_type(); + } return StringName(); } @@ -160,7 +167,6 @@ void PluginScript::update_exports() { #ifdef TOOLS_ENABLED ASSERT_SCRIPT_VALID(); if (placeholders.size()) { - //update placeholders if any Map<StringName, Variant> propdefvalues; List<PropertyInfo> propinfos; @@ -175,7 +181,7 @@ void PluginScript::update_exports() { // TODO: rename p_this "p_owner" ? ScriptInstance *PluginScript::instance_create(Object *p_this) { - ASSERT_SCRIPT_VALID_V(NULL); + ASSERT_SCRIPT_VALID_V(nullptr); // TODO check script validity ? if (!_tool && !ScriptServer::is_scripting_enabled()) { #ifdef TOOLS_ENABLED @@ -185,7 +191,7 @@ ScriptInstance *PluginScript::instance_create(Object *p_this) { update_exports(); return si; #else - return NULL; + return nullptr; #endif } @@ -197,12 +203,12 @@ ScriptInstance *PluginScript::instance_create(Object *p_this) { // if (EngineDebugger::is_active()) { // _language->debug_break_parse(get_path(), 0, msg); // } - ERR_FAIL_V_MSG(NULL, msg); + ERR_FAIL_V_MSG(nullptr, msg); } } Callable::CallError unchecked_error; - return _create_instance(NULL, 0, p_this, unchecked_error); + return _create_instance(nullptr, 0, p_this, unchecked_error); } bool PluginScript::instance_has(const Object *p_this) const { @@ -222,8 +228,9 @@ String PluginScript::get_source_code() const { } void PluginScript::set_source_code(const String &p_code) { - if (_source == p_code) + if (_source == p_code) { return; + } _source = p_code; } @@ -237,11 +244,13 @@ Error PluginScript::reload(bool p_keep_state) { _valid = false; String basedir = _path; - if (basedir == "") + if (basedir == "") { basedir = get_path(); + } - if (basedir != "") + if (basedir != "") { basedir = basedir.get_base_dir(); + } if (_data) { _desc->finish(_data); @@ -274,7 +283,6 @@ Error PluginScript::reload(bool p_keep_state) { // ClassDB name (i.e. `Node2D`) or a resource path (i.e. `res://foo/bar.gd`) StringName *base_name = (StringName *)&manifest.base; if (*base_name) { - if (ClassDB::class_exists(*base_name)) { _native_parent = *base_name; } else { @@ -296,7 +304,7 @@ Error PluginScript::reload(bool p_keep_state) { _tool = manifest.is_tool; Dictionary *members = (Dictionary *)&manifest.member_lines; - for (const Variant *key = members->next(); key != NULL; key = members->next(key)) { + for (const Variant *key = members->next(); key != nullptr; key = members->next(key)) { _member_lines[*key] = (*members)[*key]; } Array *methods = (Array *)&manifest.methods; @@ -366,14 +374,14 @@ Error PluginScript::reload(bool p_keep_state) { void PluginScript::get_script_method_list(List<MethodInfo> *r_methods) const { ASSERT_SCRIPT_VALID(); - for (Map<StringName, MethodInfo>::Element *e = _methods_info.front(); e != NULL; e = e->next()) { + for (Map<StringName, MethodInfo>::Element *e = _methods_info.front(); e != nullptr; e = e->next()) { r_methods->push_back(e->get()); } } void PluginScript::get_script_property_list(List<PropertyInfo> *r_properties) const { ASSERT_SCRIPT_VALID(); - for (Map<StringName, PropertyInfo>::Element *e = _properties_info.front(); e != NULL; e = e->next()) { + for (Map<StringName, PropertyInfo>::Element *e = _properties_info.front(); e != nullptr; e = e->next()) { r_properties->push_back(e->get()); } } @@ -386,7 +394,7 @@ bool PluginScript::has_method(const StringName &p_method) const { MethodInfo PluginScript::get_method_info(const StringName &p_method) const { ASSERT_SCRIPT_VALID_V(MethodInfo()); const Map<StringName, MethodInfo>::Element *e = _methods_info.find(p_method); - if (e != NULL) { + if (e != nullptr) { return e->get(); } else { return MethodInfo(); @@ -401,7 +409,7 @@ bool PluginScript::has_property(const StringName &p_method) const { PropertyInfo PluginScript::get_property_info(const StringName &p_property) const { ASSERT_SCRIPT_VALID_V(PropertyInfo()); const Map<StringName, PropertyInfo>::Element *e = _properties_info.find(p_property); - if (e != NULL) { + if (e != nullptr) { return e->get(); } else { return PropertyInfo(); @@ -412,7 +420,7 @@ bool PluginScript::get_property_default_value(const StringName &p_property, Vari ASSERT_SCRIPT_VALID_V(false); #ifdef TOOLS_ENABLED const Map<StringName, Variant>::Element *e = _properties_default_values.find(p_property); - if (e != NULL) { + if (e != nullptr) { r_value = e->get(); return true; } else { @@ -427,7 +435,6 @@ ScriptLanguage *PluginScript::get_language() const { } Error PluginScript::load_source_code(const String &p_path) { - Vector<uint8_t> sourcef; Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -462,18 +469,18 @@ bool PluginScript::has_script_signal(const StringName &p_signal) const { void PluginScript::get_script_signal_list(List<MethodInfo> *r_signals) const { ASSERT_SCRIPT_VALID(); - for (Map<StringName, MethodInfo>::Element *e = _signals_info.front(); e != NULL; e = e->next()) { + for (Map<StringName, MethodInfo>::Element *e = _signals_info.front(); e != nullptr; e = e->next()) { r_signals->push_back(e->get()); } } int PluginScript::get_member_line(const StringName &p_member) const { #ifdef TOOLS_ENABLED - if (_member_lines.has(p_member)) + if (_member_lines.has(p_member)) { return _member_lines[p_member]; - else + } #endif - return -1; + return -1; } Vector<ScriptNetData> PluginScript::get_rpc_methods() const { @@ -492,15 +499,17 @@ uint16_t PluginScript::get_rpc_method_id(const StringName &p_method) const { StringName PluginScript::get_rpc_method(const uint16_t p_rpc_method_id) const { ASSERT_SCRIPT_VALID_V(StringName()); - if (p_rpc_method_id >= _rpc_methods.size()) + if (p_rpc_method_id >= _rpc_methods.size()) { return StringName(); + } return _rpc_methods[p_rpc_method_id].name; } MultiplayerAPI::RPCMode PluginScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED); - if (p_rpc_method_id >= _rpc_methods.size()) + if (p_rpc_method_id >= _rpc_methods.size()) { return MultiplayerAPI::RPC_MODE_DISABLED; + } return _rpc_methods[p_rpc_method_id].mode; } @@ -525,15 +534,17 @@ uint16_t PluginScript::get_rset_property_id(const StringName &p_property) const StringName PluginScript::get_rset_property(const uint16_t p_rset_property_id) const { ASSERT_SCRIPT_VALID_V(StringName()); - if (p_rset_property_id >= _rpc_variables.size()) + if (p_rset_property_id >= _rpc_variables.size()) { return StringName(); + } return _rpc_variables[p_rset_property_id].name; } MultiplayerAPI::RPCMode PluginScript::get_rset_mode_by_id(const uint16_t p_rset_property_id) const { ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED); - if (p_rset_property_id >= _rpc_variables.size()) + if (p_rset_property_id >= _rpc_variables.size()) { return MultiplayerAPI::RPC_MODE_DISABLED; + } return _rpc_variables[p_rset_property_id].mode; } @@ -543,11 +554,6 @@ MultiplayerAPI::RPCMode PluginScript::get_rset_mode(const StringName &p_variable } PluginScript::PluginScript() : - _data(NULL), - _desc(NULL), - _language(NULL), - _tool(false), - _valid(false), _script_list(this) { } diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h index 5c93ae38f5..659289ef9b 100644 --- a/modules/gdnative/pluginscript/pluginscript_script.h +++ b/modules/gdnative/pluginscript/pluginscript_script.h @@ -38,18 +38,17 @@ #include <pluginscript/godot_pluginscript.h> class PluginScript : public Script { - GDCLASS(PluginScript, Script); friend class PluginScriptInstance; friend class PluginScriptLanguage; private: - godot_pluginscript_script_data *_data; - const godot_pluginscript_script_desc *_desc; - PluginScriptLanguage *_language; - bool _tool; - bool _valid; + godot_pluginscript_script_data *_data = nullptr; + const godot_pluginscript_script_desc *_desc = nullptr; + PluginScriptLanguage *_language = nullptr; + bool _tool = false; + bool _valid = false; Ref<Script> _ref_base_parent; StringName _native_parent; @@ -72,6 +71,8 @@ private: protected: static void _bind_methods(); + bool inherits_script(const Ref<Script> &p_script) const; + PluginScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, Callable::CallError &r_error); Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error); diff --git a/modules/gdnative/pluginscript/register_types.h b/modules/gdnative/pluginscript/register_types.h index a4f7284b54..c6a64b4f40 100644 --- a/modules/gdnative/pluginscript/register_types.h +++ b/modules/gdnative/pluginscript/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef PLUGINSCRIPT_REGISTER_TYPES_H +#define PLUGINSCRIPT_REGISTER_TYPES_H + void register_pluginscript_types(); void unregister_pluginscript_types(); + +#endif // PLUGINSCRIPT_REGISTER_TYPES_H diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 397a020689..136af5bd1e 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -34,11 +34,11 @@ #include "gdnative.h" -#include "arvr/register_types.h" #include "nativescript/register_types.h" #include "net/register_types.h" #include "pluginscript/register_types.h" #include "videodecoder/register_types.h" +#include "xr/register_types.h" #include "core/engine.h" #include "core/io/resource_loader.h" @@ -53,7 +53,6 @@ #include "gdnative_library_singleton_editor.h" class GDNativeExportPlugin : public EditorExportPlugin { - protected: virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); }; @@ -77,7 +76,6 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty Ref<ConfigFile> config = lib->get_config_file(); { - List<String> entry_keys; config->get_section_keys("entry", &entry_keys); @@ -189,7 +187,6 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty } static void editor_init_callback() { - GDNativeLibrarySingletonEditor *library_editor = memnew(GDNativeLibrarySingletonEditor); library_editor->set_name(TTR("GDNative")); ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor); @@ -205,7 +202,6 @@ static void editor_init_callback() { #endif static godot_variant cb_standard_varcall(void *p_procedure_handle, godot_array *p_args) { - godot_gdnative_procedure_fn proc; proc = (godot_gdnative_procedure_fn)p_procedure_handle; @@ -220,7 +216,6 @@ Ref<GDNativeLibraryResourceLoader> resource_loader_gdnlib; Ref<GDNativeLibraryResourceSaver> resource_saver_gdnlib; void register_gdnative_types() { - #ifdef TOOLS_ENABLED EditorNode::add_init_callback(editor_init_callback); @@ -240,7 +235,7 @@ void register_gdnative_types() { GDNativeCallRegistry::singleton->register_native_call_type("standard_varcall", cb_standard_varcall); register_net_types(); - register_arvr_types(); + register_xr_types(); register_nativescript_types(); register_pluginscript_types(); register_videodecoder_types(); @@ -259,8 +254,9 @@ void register_gdnative_types() { for (int i = 0; i < singletons.size(); i++) { String path = singletons[i]; - if (excluded.has(path)) + if (excluded.has(path)) { continue; + } Ref<GDNativeLibrary> lib = ResourceLoader::load(path); Ref<GDNative> singleton; @@ -287,9 +283,7 @@ void register_gdnative_types() { } void unregister_gdnative_types() { - for (int i = 0; i < singleton_gdnatives.size(); i++) { - if (singleton_gdnatives[i].is_null()) { continue; } @@ -305,7 +299,7 @@ void unregister_gdnative_types() { unregister_videodecoder_types(); unregister_pluginscript_types(); unregister_nativescript_types(); - unregister_arvr_types(); + unregister_xr_types(); unregister_net_types(); memdelete(GDNativeCallRegistry::singleton); diff --git a/modules/gdnative/register_types.h b/modules/gdnative/register_types.h index 0091ef3f96..b5c182f8b7 100644 --- a/modules/gdnative/register_types.h +++ b/modules/gdnative/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef GDNATIVE_REGISTER_TYPES_H +#define GDNATIVE_REGISTER_TYPES_H + void register_gdnative_types(); void unregister_gdnative_types(); + +#endif // GDNATIVE_REGISTER_TYPES_H diff --git a/modules/gdnative/videodecoder/SCsub b/modules/gdnative/videodecoder/SCsub index 04cc8ed604..5948b9a3dd 100644 --- a/modules/gdnative/videodecoder/SCsub +++ b/modules/gdnative/videodecoder/SCsub @@ -1,9 +1,9 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_vsdecoder_gdnative = env_modules.Clone() -env_vsdecoder_gdnative.Prepend(CPPPATH=['#modules/gdnative/include/']) -env_vsdecoder_gdnative.add_source_files(env.modules_sources, '*.cpp') +env_vsdecoder_gdnative.Prepend(CPPPATH=["#modules/gdnative/include/"]) +env_vsdecoder_gdnative.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/gdnative/videodecoder/register_types.cpp b/modules/gdnative/videodecoder/register_types.cpp index c53e8f2c78..4181d8813f 100644 --- a/modules/gdnative/videodecoder/register_types.cpp +++ b/modules/gdnative/videodecoder/register_types.cpp @@ -36,7 +36,6 @@ static Ref<ResourceFormatLoaderVideoStreamGDNative> resource_loader_vsgdnative; void register_videodecoder_types() { - resource_loader_vsgdnative.instance(); ResourceLoader::add_resource_format_loader(resource_loader_vsgdnative, true); @@ -44,7 +43,6 @@ void register_videodecoder_types() { } void unregister_videodecoder_types() { - ResourceLoader::remove_resource_format_loader(resource_loader_vsgdnative); resource_loader_vsgdnative.unref(); } diff --git a/modules/gdnative/videodecoder/register_types.h b/modules/gdnative/videodecoder/register_types.h index d81d5c497b..b1a83d4071 100644 --- a/modules/gdnative/videodecoder/register_types.h +++ b/modules/gdnative/videodecoder/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef VIDEODECODER_REGISTER_TYPES_H +#define VIDEODECODER_REGISTER_TYPES_H + void register_videodecoder_types(); void unregister_videodecoder_types(); + +#endif // VIDEODECODER_REGISTER_TYPES_H diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index f6e2bad739..9d9c5b6473 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -33,7 +33,7 @@ #include "core/project_settings.h" #include "servers/audio_server.h" -VideoDecoderServer *VideoDecoderServer::instance = NULL; +VideoDecoderServer *VideoDecoderServer::instance = nullptr; static VideoDecoderServer decoder_server; @@ -105,7 +105,6 @@ int64_t GDAPI godot_videodecoder_file_seek(void *ptr, int64_t pos, int whence) { } void GDAPI godot_videodecoder_register_decoder(const godot_videodecoder_interface_gdnative *p_interface) { - decoder_server.register_decoder_interface(p_interface); } } @@ -113,7 +112,7 @@ void GDAPI godot_videodecoder_register_decoder(const godot_videodecoder_interfac // VideoStreamPlaybackGDNative starts here. bool VideoStreamPlaybackGDNative::open_file(const String &p_file) { - ERR_FAIL_COND_V(interface == NULL, false); + ERR_FAIL_COND_V(interface == nullptr, false); file = FileAccess::open(p_file, FileAccess::READ); bool file_opened = interface->open_file(data_struct, file); @@ -150,7 +149,7 @@ void VideoStreamPlaybackGDNative::update(float p_delta) { return; } time += p_delta; - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->update(data_struct, p_delta); // Don't mix if there's no audio (num_channels == 0). @@ -189,7 +188,7 @@ void VideoStreamPlaybackGDNative::update(float p_delta) { void VideoStreamPlaybackGDNative::update_texture() { PackedByteArray *pba = (PackedByteArray *)interface->get_videoframe(data_struct); - if (pba == NULL) { + if (pba == nullptr) { playing = false; return; } @@ -202,42 +201,29 @@ void VideoStreamPlaybackGDNative::update_texture() { // ctor and dtor VideoStreamPlaybackGDNative::VideoStreamPlaybackGDNative() : - texture(Ref<ImageTexture>(memnew(ImageTexture))), - playing(false), - paused(false), - mix_udata(NULL), - mix_callback(NULL), - num_channels(-1), - time(0), - seek_backward(false), - mix_rate(0), - delay_compensation(0), - pcm(NULL), - pcm_write_idx(0), - samples_decoded(0), - file(NULL), - interface(NULL), - data_struct(NULL) {} + texture(Ref<ImageTexture>(memnew(ImageTexture))) {} VideoStreamPlaybackGDNative::~VideoStreamPlaybackGDNative() { cleanup(); } void VideoStreamPlaybackGDNative::cleanup() { - if (data_struct) + if (data_struct) { interface->destructor(data_struct); - if (pcm) + } + if (pcm) { memfree(pcm); - pcm = NULL; + } + pcm = nullptr; time = 0; num_channels = -1; - interface = NULL; - data_struct = NULL; + interface = nullptr; + data_struct = nullptr; } void VideoStreamPlaybackGDNative::set_interface(const godot_videodecoder_interface_gdnative *p_interface) { - ERR_FAIL_COND(p_interface == NULL); - if (interface != NULL) { + ERR_FAIL_COND(p_interface == nullptr); + if (interface != nullptr) { cleanup(); } interface = p_interface; @@ -255,7 +241,6 @@ bool VideoStreamPlaybackGDNative::is_paused() const { } void VideoStreamPlaybackGDNative::play() { - stop(); playing = true; @@ -272,10 +257,11 @@ void VideoStreamPlaybackGDNative::stop() { } void VideoStreamPlaybackGDNative::seek(float p_time) { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->seek(data_struct, p_time); - if (p_time < time) + if (p_time < time) { seek_backward = true; + } time = p_time; // reset audio buffers memset(pcm, 0, num_channels * AUX_BUFFER_SIZE * sizeof(float)); @@ -292,13 +278,12 @@ Ref<Texture2D> VideoStreamPlaybackGDNative::get_texture() const { } float VideoStreamPlaybackGDNative::get_length() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_length(data_struct); } float VideoStreamPlaybackGDNative::get_playback_position() const { - - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_playback_position(data_struct); } @@ -312,24 +297,23 @@ void VideoStreamPlaybackGDNative::set_loop(bool p_enable) { } void VideoStreamPlaybackGDNative::set_audio_track(int p_idx) { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->set_audio_track(data_struct, p_idx); } void VideoStreamPlaybackGDNative::set_mix_callback(AudioMixCallback p_callback, void *p_userdata) { - mix_udata = p_userdata; mix_callback = p_callback; } int VideoStreamPlaybackGDNative::get_channels() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return (num_channels > 0) ? num_channels : 0; } int VideoStreamPlaybackGDNative::get_mix_rate() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return mix_rate; } @@ -339,27 +323,26 @@ int VideoStreamPlaybackGDNative::get_mix_rate() const { Ref<VideoStreamPlayback> VideoStreamGDNative::instance_playback() { Ref<VideoStreamPlaybackGDNative> pb = memnew(VideoStreamPlaybackGDNative); VideoDecoderGDNative *decoder = decoder_server.get_decoder(file.get_extension().to_lower()); - if (decoder == NULL) - return NULL; + if (decoder == nullptr) { + return nullptr; + } pb->set_interface(decoder->interface); pb->set_audio_track(audio_track); - if (pb->open_file(file)) + if (pb->open_file(file)) { return pb; - return NULL; + } + return nullptr; } void VideoStreamGDNative::set_file(const String &p_file) { - file = p_file; } String VideoStreamGDNative::get_file() { - return file; } void VideoStreamGDNative::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamGDNative::set_file); ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamGDNative::get_file); @@ -367,13 +350,12 @@ void VideoStreamGDNative::_bind_methods() { } void VideoStreamGDNative::set_audio_track(int p_track) { - audio_track = p_track; } /* --- NOTE ResourceFormatLoaderVideoStreamGDNative starts here. ----- */ -RES ResourceFormatLoaderVideoStreamGDNative::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { +RES ResourceFormatLoaderVideoStreamGDNative::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { if (r_error) { @@ -405,7 +387,8 @@ bool ResourceFormatLoaderVideoStreamGDNative::handles_type(const String &p_type) String ResourceFormatLoaderVideoStreamGDNative::get_resource_type(const String &p_path) const { String el = p_path.get_extension().to_lower(); - if (VideoDecoderServer::get_instance()->get_extensions().has(el)) + if (VideoDecoderServer::get_instance()->get_extensions().has(el)) { return "VideoStreamGDNative"; + } return ""; } diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.h b/modules/gdnative/videodecoder/video_stream_gdnative.h index 21b5245a16..53017a6a97 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.h +++ b/modules/gdnative/videodecoder/video_stream_gdnative.h @@ -37,13 +37,11 @@ #include "scene/resources/video_stream.h" struct VideoDecoderGDNative { - const godot_videodecoder_interface_gdnative *interface; - String plugin_name; + const godot_videodecoder_interface_gdnative *interface = nullptr; + String plugin_name = "none"; Vector<String> supported_extensions; - VideoDecoderGDNative() : - interface(NULL), - plugin_name("none") {} + VideoDecoderGDNative() {} VideoDecoderGDNative(const godot_videodecoder_interface_gdnative *p_interface) : interface(p_interface), @@ -88,8 +86,9 @@ public: } VideoDecoderGDNative *get_decoder(const String &extension) { - if (extensions.size() == 0 || !extensions.has(extension)) - return NULL; + if (extensions.size() == 0 || !extensions.has(extension)) { + return nullptr; + } return decoders[extensions[extension]]; } @@ -102,32 +101,31 @@ public: memdelete(decoders[i]); } decoders.clear(); - instance = NULL; + instance = nullptr; } }; class VideoStreamPlaybackGDNative : public VideoStreamPlayback { - GDCLASS(VideoStreamPlaybackGDNative, VideoStreamPlayback); Ref<ImageTexture> texture; - bool playing; - bool paused; + bool playing = false; + bool paused = false; Vector2 texture_size; - void *mix_udata; - AudioMixCallback mix_callback; + void *mix_udata = nullptr; + AudioMixCallback mix_callback = nullptr; - int num_channels; - float time; - bool seek_backward; - int mix_rate; - double delay_compensation; + int num_channels = -1; + float time = 0; + bool seek_backward = false; + int mix_rate = 0; + double delay_compensation = 0; - float *pcm; - int pcm_write_idx; - int samples_decoded; + float *pcm = nullptr; + int pcm_write_idx = 0; + int samples_decoded = 0; void cleanup(); void update_texture(); @@ -135,10 +133,10 @@ class VideoStreamPlaybackGDNative : public VideoStreamPlayback { protected: String file_name; - FileAccess *file; + FileAccess *file = nullptr; - const godot_videodecoder_interface_gdnative *interface; - void *data_struct; + const godot_videodecoder_interface_gdnative *interface = nullptr; + void *data_struct = nullptr; public: VideoStreamPlaybackGDNative(); @@ -177,11 +175,10 @@ public: }; class VideoStreamGDNative : public VideoStream { - GDCLASS(VideoStreamGDNative, VideoStream); String file; - int audio_track; + int audio_track = 0; protected: static void @@ -199,7 +196,7 @@ public: class ResourceFormatLoaderVideoStreamGDNative : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/gdnative/xr/SCsub b/modules/gdnative/xr/SCsub new file mode 100644 index 0000000000..0b2db3b504 --- /dev/null +++ b/modules/gdnative/xr/SCsub @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +Import("env") +Import("env_gdnative") + +env_gdnative.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/gdnative/arvr/config.py b/modules/gdnative/xr/config.py index 53bc827027..d22f9454ed 100644 --- a/modules/gdnative/arvr/config.py +++ b/modules/gdnative/xr/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return True + return True + def configure(env): - pass + pass diff --git a/modules/gdnative/xr/register_types.cpp b/modules/gdnative/xr/register_types.cpp new file mode 100644 index 0000000000..da3a7dc4b8 --- /dev/null +++ b/modules/gdnative/xr/register_types.cpp @@ -0,0 +1,40 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "register_types.h" +#include "xr_interface_gdnative.h" + +void register_xr_types() { + ClassDB::register_class<XRInterfaceGDNative>(); + ClassDB::add_compatibility_class("ARVRInterfaceGDNative", "XRInterfaceGDNative"); +} + +void unregister_xr_types() { +} diff --git a/modules/gdnative/xr/register_types.h b/modules/gdnative/xr/register_types.h new file mode 100644 index 0000000000..2501d28651 --- /dev/null +++ b/modules/gdnative/xr/register_types.h @@ -0,0 +1,37 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef XR_REGISTER_TYPES_H +#define XR_REGISTER_TYPES_H + +void register_xr_types(); +void unregister_xr_types(); + +#endif // XR_REGISTER_TYPES_H diff --git a/modules/gdnative/xr/xr_interface_gdnative.cpp b/modules/gdnative/xr/xr_interface_gdnative.cpp new file mode 100644 index 0000000000..d03fc33935 --- /dev/null +++ b/modules/gdnative/xr/xr_interface_gdnative.cpp @@ -0,0 +1,420 @@ +/*************************************************************************/ +/* xr_interface_gdnative.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "xr_interface_gdnative.h" +#include "core/input/input.h" +#include "servers/rendering/rendering_server_globals.h" +#include "servers/xr/xr_positional_tracker.h" + +void XRInterfaceGDNative::_bind_methods() { + ADD_PROPERTY_DEFAULT("interface_is_initialized", false); + ADD_PROPERTY_DEFAULT("ar_is_anchor_detection_enabled", false); +} + +XRInterfaceGDNative::XRInterfaceGDNative() { + print_verbose("Construct gdnative interface\n"); + + // we won't have our data pointer until our library gets set + data = nullptr; + + interface = nullptr; +} + +XRInterfaceGDNative::~XRInterfaceGDNative() { + print_verbose("Destruct gdnative interface\n"); + + if (interface != nullptr && is_initialized()) { + uninitialize(); + }; + + // cleanup after ourselves + cleanup(); +} + +void XRInterfaceGDNative::cleanup() { + if (interface != nullptr) { + interface->destructor(data); + data = nullptr; + interface = nullptr; + } +} + +void XRInterfaceGDNative::set_interface(const godot_xr_interface_gdnative *p_interface) { + // this should only be called once, just being paranoid.. + if (interface) { + cleanup(); + } + + // bind to our interface + interface = p_interface; + + // Now we do our constructing... + data = interface->constructor((godot_object *)this); +} + +StringName XRInterfaceGDNative::get_name() const { + ERR_FAIL_COND_V(interface == nullptr, StringName()); + + godot_string result = interface->get_name(data); + + StringName name = *(String *)&result; + + godot_string_destroy(&result); + + return name; +} + +int XRInterfaceGDNative::get_capabilities() const { + int capabilities; + + ERR_FAIL_COND_V(interface == nullptr, 0); // 0 = None + + capabilities = interface->get_capabilities(data); + + return capabilities; +} + +bool XRInterfaceGDNative::get_anchor_detection_is_enabled() const { + ERR_FAIL_COND_V(interface == nullptr, false); + + return interface->get_anchor_detection_is_enabled(data); +} + +void XRInterfaceGDNative::set_anchor_detection_is_enabled(bool p_enable) { + ERR_FAIL_COND(interface == nullptr); + + interface->set_anchor_detection_is_enabled(data, p_enable); +} + +int XRInterfaceGDNative::get_camera_feed_id() { + ERR_FAIL_COND_V(interface == nullptr, 0); + + return (unsigned int)interface->get_camera_feed_id(data); +} + +bool XRInterfaceGDNative::is_stereo() { + bool stereo; + + ERR_FAIL_COND_V(interface == nullptr, false); + + stereo = interface->is_stereo(data); + + return stereo; +} + +bool XRInterfaceGDNative::is_initialized() const { + ERR_FAIL_COND_V(interface == nullptr, false); + + return interface->is_initialized(data); +} + +bool XRInterfaceGDNative::initialize() { + ERR_FAIL_COND_V(interface == nullptr, false); + + bool initialized = interface->initialize(data); + + if (initialized) { + // if we successfully initialize our interface and we don't have a primary interface yet, this becomes our primary interface + + XRServer *xr_server = XRServer::get_singleton(); + if ((xr_server != nullptr) && (xr_server->get_primary_interface() == nullptr)) { + xr_server->set_primary_interface(this); + }; + }; + + return initialized; +} + +void XRInterfaceGDNative::uninitialize() { + ERR_FAIL_COND(interface == nullptr); + + XRServer *xr_server = XRServer::get_singleton(); + if (xr_server != nullptr) { + // Whatever happens, make sure this is no longer our primary interface + xr_server->clear_primary_interface_if(this); + } + + interface->uninitialize(data); +} + +Size2 XRInterfaceGDNative::get_render_targetsize() { + ERR_FAIL_COND_V(interface == nullptr, Size2()); + + godot_vector2 result = interface->get_render_targetsize(data); + Vector2 *vec = (Vector2 *)&result; + + return *vec; +} + +Transform XRInterfaceGDNative::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) { + Transform *ret; + + ERR_FAIL_COND_V(interface == nullptr, Transform()); + + godot_transform t = interface->get_transform_for_eye(data, (int)p_eye, (godot_transform *)&p_cam_transform); + + ret = (Transform *)&t; + + return *ret; +} + +CameraMatrix XRInterfaceGDNative::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { + CameraMatrix cm; + + ERR_FAIL_COND_V(interface == nullptr, CameraMatrix()); + + interface->fill_projection_for_eye(data, (godot_real *)cm.matrix, (godot_int)p_eye, p_aspect, p_z_near, p_z_far); + + return cm; +} + +unsigned int XRInterfaceGDNative::get_external_texture_for_eye(XRInterface::Eyes p_eye) { + ERR_FAIL_COND_V(interface == nullptr, 0); + + return (unsigned int)interface->get_external_texture_for_eye(data, (godot_int)p_eye); +} + +void XRInterfaceGDNative::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { + ERR_FAIL_COND(interface == nullptr); + + interface->commit_for_eye(data, (godot_int)p_eye, (godot_rid *)&p_render_target, (godot_rect2 *)&p_screen_rect); +} + +void XRInterfaceGDNative::process() { + ERR_FAIL_COND(interface == nullptr); + + interface->process(data); +} + +void XRInterfaceGDNative::notification(int p_what) { + ERR_FAIL_COND(interface == nullptr); + + interface->notification(data, p_what); +} + +///////////////////////////////////////////////////////////////////////////////////// +// some helper callbacks + +extern "C" { + +void GDAPI godot_xr_register_interface(const godot_xr_interface_gdnative *p_interface) { + // Must be on a version 4 plugin + ERR_FAIL_COND_MSG(p_interface->version.major < 4, "GDNative XR interfaces build for Godot 3.x are not supported."); + + Ref<XRInterfaceGDNative> new_interface; + new_interface.instance(); + new_interface->set_interface((const godot_xr_interface_gdnative *)p_interface); + XRServer::get_singleton()->add_interface(new_interface); +} + +godot_real GDAPI godot_xr_get_worldscale() { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, 1.0); + + return xr_server->get_world_scale(); +} + +godot_transform GDAPI godot_xr_get_reference_frame() { + godot_transform reference_frame; + Transform *reference_frame_ptr = (Transform *)&reference_frame; + + XRServer *xr_server = XRServer::get_singleton(); + if (xr_server != nullptr) { + *reference_frame_ptr = xr_server->get_reference_frame(); + } else { + godot_transform_new_identity(&reference_frame); + } + + return reference_frame; +} + +void GDAPI godot_xr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect) { + // blits out our texture as is, handy for preview display of one of the eyes that is already rendered with lens distortion on an external HMD + XRInterface::Eyes eye = (XRInterface::Eyes)p_eye; +#if 0 + RID *render_target = (RID *)p_render_target; +#endif + Rect2 screen_rect = *(Rect2 *)p_rect; + + if (eye == XRInterface::EYE_LEFT) { + screen_rect.size.x /= 2.0; + } else if (p_eye == XRInterface::EYE_RIGHT) { + screen_rect.size.x /= 2.0; + screen_rect.position.x += screen_rect.size.x; + } +#ifndef _MSC_VER +#warning this needs to be redone +#endif +#if 0 + RSG::rasterizer->blit_render_target_to_screen(*render_target, screen_rect, 0); +#endif +} + +godot_int GDAPI godot_xr_get_texid(godot_rid *p_render_target) { + // In order to send off our textures to display on our hardware we need the opengl texture ID instead of the render target RID + // This is a handy function to expose that. +#if 0 + RID *render_target = (RID *)p_render_target; + + RID eye_texture = RSG::storage->render_target_get_texture(*render_target); +#endif + +#ifndef _MSC_VER +#warning need to obtain this ID again +#endif + uint32_t texid = 0; //RS::get_singleton()->texture_get_texid(eye_texture); + + return texid; +} + +godot_int GDAPI godot_xr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position) { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, 0); + + Input *input = Input::get_singleton(); + ERR_FAIL_NULL_V(input, 0); + + XRPositionalTracker *new_tracker = memnew(XRPositionalTracker); + new_tracker->set_name(p_device_name); + new_tracker->set_type(XRServer::TRACKER_CONTROLLER); + if (p_hand == 1) { + new_tracker->set_hand(XRPositionalTracker::TRACKER_LEFT_HAND); + } else if (p_hand == 2) { + new_tracker->set_hand(XRPositionalTracker::TRACKER_RIGHT_HAND); + } + + // also register as joystick... + int joyid = input->get_unused_joy_id(); + if (joyid != -1) { + new_tracker->set_joy_id(joyid); + input->joy_connection_changed(joyid, true, p_device_name, ""); + } + + if (p_tracks_orientation) { + Basis orientation; + new_tracker->set_orientation(orientation); + } + if (p_tracks_position) { + Vector3 position; + new_tracker->set_position(position); + } + + // add our tracker to our server and remember its pointer + xr_server->add_tracker(new_tracker); + + // note, this ID is only unique within controllers! + return new_tracker->get_tracker_id(); +} + +void GDAPI godot_xr_remove_controller(godot_int p_controller_id) { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); + + Input *input = Input::get_singleton(); + ERR_FAIL_NULL(input); + + XRPositionalTracker *remove_tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (remove_tracker != nullptr) { + // unset our joystick if applicable + int joyid = remove_tracker->get_joy_id(); + if (joyid != -1) { + input->joy_connection_changed(joyid, false, "", ""); + remove_tracker->set_joy_id(-1); + } + + // remove our tracker from our server + xr_server->remove_tracker(remove_tracker); + memdelete(remove_tracker); + } +} + +void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); + + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (tracker != nullptr) { + Transform *transform = (Transform *)p_transform; + if (p_tracks_orientation) { + tracker->set_orientation(transform->basis); + } + if (p_tracks_position) { + tracker->set_rw_position(transform->origin); + } + } +} + +void GDAPI godot_xr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed) { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); + + Input *input = Input::get_singleton(); + ERR_FAIL_NULL(input); + + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (tracker != nullptr) { + int joyid = tracker->get_joy_id(); + if (joyid != -1) { + input->joy_button(joyid, p_button, p_is_pressed); + } + } +} + +void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative) { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); + + Input *input = Input::get_singleton(); + ERR_FAIL_NULL(input); + + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (tracker != nullptr) { + int joyid = tracker->get_joy_id(); + if (joyid != -1) { + Input::JoyAxis jx; + jx.min = p_can_be_negative ? -1 : 0; + jx.value = p_value; + input->joy_axis(joyid, p_axis, jx); + } + } +} + +godot_real GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id) { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, 0.0); + + XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + if (tracker != nullptr) { + return tracker->get_rumble(); + } + + return 0.0; +} +} diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.h b/modules/gdnative/xr/xr_interface_gdnative.h index e38eb435c6..64f1282a7e 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.h +++ b/modules/gdnative/xr/xr_interface_gdnative.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* arvr_interface_gdnative.h */ +/* xr_interface_gdnative.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef ARVR_INTERFACE_GDNATIVE_H -#define ARVR_INTERFACE_GDNATIVE_H +#ifndef XR_INTERFACE_GDNATIVE_H +#define XR_INTERFACE_GDNATIVE_H #include "modules/gdnative/gdnative.h" -#include "servers/arvr/arvr_interface.h" +#include "servers/xr/xr_interface.h" /** @authors Hinsbart & Karroffel & Mux213 @@ -40,23 +40,23 @@ This subclass of our AR/VR interface forms a bridge to GDNative. */ -class ARVRInterfaceGDNative : public ARVRInterface { - GDCLASS(ARVRInterfaceGDNative, ARVRInterface); +class XRInterfaceGDNative : public XRInterface { + GDCLASS(XRInterfaceGDNative, XRInterface); void cleanup(); protected: - const godot_arvr_interface_gdnative *interface; + const godot_xr_interface_gdnative *interface; void *data; static void _bind_methods(); public: /** general interface information **/ - ARVRInterfaceGDNative(); - ~ARVRInterfaceGDNative(); + XRInterfaceGDNative(); + ~XRInterfaceGDNative(); - void set_interface(const godot_arvr_interface_gdnative *p_interface); + void set_interface(const godot_xr_interface_gdnative *p_interface); virtual StringName get_name() const; virtual int get_capabilities() const; @@ -73,19 +73,19 @@ public: /** rendering and internal **/ virtual Size2 get_render_targetsize(); virtual bool is_stereo(); - virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform); + virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform); // we expose a Vector<float> version of this function to GDNative - Vector<float> _get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far); + Vector<float> _get_projection_for_eye(XRInterface::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); + // and a CameraMatrix version to XRServer + virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far); - virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye); - virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect); + virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye); + virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect); virtual void process(); virtual void notification(int p_what); }; -#endif // ARVR_INTERFACE_GDNATIVE_H +#endif // XR_INTERFACE_GDNATIVE_H diff --git a/modules/gdnavigation/SCsub b/modules/gdnavigation/SCsub index 9d462f92a7..877d601c6a 100644 --- a/modules/gdnavigation/SCsub +++ b/modules/gdnavigation/SCsub @@ -1,25 +1,25 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_navigation = env_modules.Clone() # Recast Thirdparty source files -if env['builtin_recast']: +if env["builtin_recast"]: thirdparty_dir = "#thirdparty/recastnavigation/Recast/" thirdparty_sources = [ - "Source/Recast.cpp", - "Source/RecastAlloc.cpp", - "Source/RecastArea.cpp", - "Source/RecastAssert.cpp", - "Source/RecastContour.cpp", - "Source/RecastFilter.cpp", - "Source/RecastLayers.cpp", - "Source/RecastMesh.cpp", - "Source/RecastMeshDetail.cpp", - "Source/RecastRasterization.cpp", - "Source/RecastRegion.cpp", + "Source/Recast.cpp", + "Source/RecastAlloc.cpp", + "Source/RecastArea.cpp", + "Source/RecastAssert.cpp", + "Source/RecastContour.cpp", + "Source/RecastFilter.cpp", + "Source/RecastLayers.cpp", + "Source/RecastMesh.cpp", + "Source/RecastMeshDetail.cpp", + "Source/RecastRasterization.cpp", + "Source/RecastRegion.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] @@ -31,11 +31,11 @@ if env['builtin_recast']: # RVO Thirdparty source files -if env['builtin_rvo2']: +if env["builtin_rvo2"]: thirdparty_dir = "#thirdparty/rvo2" thirdparty_sources = [ - "/src/Agent.cpp", - "/src/KdTree.cpp", + "/src/Agent.cpp", + "/src/KdTree.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] diff --git a/modules/gdnavigation/config.py b/modules/gdnavigation/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/gdnavigation/config.py +++ b/modules/gdnavigation/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp index a1f6ddfedc..c80cdcfeab 100644 --- a/modules/gdnavigation/gd_navigation_server.cpp +++ b/modules/gdnavigation/gd_navigation_server.cpp @@ -114,8 +114,7 @@ void GdNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) GdNavigationServer::GdNavigationServer() : - NavigationServer(), - active(true) { + NavigationServer3D() { } GdNavigationServer::~GdNavigationServer() { @@ -141,7 +140,7 @@ RID GdNavigationServer::map_create() const { COMMAND_2(map_set_active, RID, p_map, bool, p_active) { NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND(map == NULL); + ERR_FAIL_COND(map == nullptr); if (p_active) { if (!map_is_active(p_map)) { @@ -154,84 +153,84 @@ COMMAND_2(map_set_active, RID, p_map, bool, p_active) { bool GdNavigationServer::map_is_active(RID p_map) const { NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, false); + ERR_FAIL_COND_V(map == nullptr, false); return active_maps.find(map) >= 0; } COMMAND_2(map_set_up, RID, p_map, Vector3, p_up) { NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND(map == NULL); + ERR_FAIL_COND(map == nullptr); map->set_up(p_up); } Vector3 GdNavigationServer::map_get_up(RID p_map) const { const NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, Vector3()); + ERR_FAIL_COND_V(map == nullptr, Vector3()); return map->get_up(); } COMMAND_2(map_set_cell_size, RID, p_map, real_t, p_cell_size) { NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND(map == NULL); + ERR_FAIL_COND(map == nullptr); map->set_cell_size(p_cell_size); } real_t GdNavigationServer::map_get_cell_size(RID p_map) const { const NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, 0); + ERR_FAIL_COND_V(map == nullptr, 0); return map->get_cell_size(); } COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin) { NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND(map == NULL); + ERR_FAIL_COND(map == nullptr); map->set_edge_connection_margin(p_connection_margin); } real_t GdNavigationServer::map_get_edge_connection_margin(RID p_map) const { const NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, 0); + ERR_FAIL_COND_V(map == nullptr, 0); return map->get_edge_connection_margin(); } Vector<Vector3> GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const { const NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, Vector<Vector3>()); + ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>()); return map->get_path(p_origin, p_destination, p_optimize); } Vector3 GdNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const { const NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, Vector3()); + ERR_FAIL_COND_V(map == nullptr, Vector3()); return map->get_closest_point_to_segment(p_from, p_to, p_use_collision); } Vector3 GdNavigationServer::map_get_closest_point(RID p_map, const Vector3 &p_point) const { const NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, Vector3()); + ERR_FAIL_COND_V(map == nullptr, Vector3()); return map->get_closest_point(p_point); } Vector3 GdNavigationServer::map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const { const NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, Vector3()); + ERR_FAIL_COND_V(map == nullptr, Vector3()); return map->get_closest_point_normal(p_point); } RID GdNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const { const NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND_V(map == NULL, RID()); + ERR_FAIL_COND_V(map == nullptr, RID()); return map->get_closest_point_owner(p_point); } @@ -247,20 +246,20 @@ RID GdNavigationServer::region_create() const { COMMAND_2(region_set_map, RID, p_region, RID, p_map) { NavRegion *region = region_owner.getornull(p_region); - ERR_FAIL_COND(region == NULL); + ERR_FAIL_COND(region == nullptr); - if (region->get_map() != NULL) { - - if (region->get_map()->get_self() == p_map) + if (region->get_map() != nullptr) { + if (region->get_map()->get_self() == p_map) { return; // Pointless + } region->get_map()->remove_region(region); - region->set_map(NULL); + region->set_map(nullptr); } if (p_map.is_valid()) { NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND(map == NULL); + ERR_FAIL_COND(map == nullptr); map->add_region(region); region->set_map(map); @@ -269,21 +268,21 @@ COMMAND_2(region_set_map, RID, p_region, RID, p_map) { COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform) { NavRegion *region = region_owner.getornull(p_region); - ERR_FAIL_COND(region == NULL); + ERR_FAIL_COND(region == nullptr); region->set_transform(p_transform); } COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) { NavRegion *region = region_owner.getornull(p_region); - ERR_FAIL_COND(region == NULL); + ERR_FAIL_COND(region == nullptr); region->set_mesh(p_nav_mesh); } void GdNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const { ERR_FAIL_COND(r_mesh.is_null()); - ERR_FAIL_COND(p_node == NULL); + ERR_FAIL_COND(p_node == nullptr); #ifndef _3D_DISABLED NavigationMeshGenerator::get_singleton()->clear(r_mesh); @@ -302,20 +301,21 @@ RID GdNavigationServer::agent_create() const { COMMAND_2(agent_set_map, RID, p_agent, RID, p_map) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); if (agent->get_map()) { - if (agent->get_map()->get_self() == p_map) + if (agent->get_map()->get_self() == p_map) { return; // Pointless + } agent->get_map()->remove_agent(agent); } - agent->set_map(NULL); + agent->set_map(nullptr); if (p_map.is_valid()) { NavMap *map = map_owner.getornull(p_map); - ERR_FAIL_COND(map == NULL); + ERR_FAIL_COND(map == nullptr); agent->set_map(map); map->add_agent(agent); @@ -328,82 +328,82 @@ COMMAND_2(agent_set_map, RID, p_agent, RID, p_map) { COMMAND_2(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->neighborDist_ = p_dist; } COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->maxNeighbors_ = p_count; } COMMAND_2(agent_set_time_horizon, RID, p_agent, real_t, p_time) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->timeHorizon_ = p_time; } COMMAND_2(agent_set_radius, RID, p_agent, real_t, p_radius) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->radius_ = p_radius; } COMMAND_2(agent_set_max_speed, RID, p_agent, real_t, p_max_speed) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->maxSpeed_ = p_max_speed; } COMMAND_2(agent_set_velocity, RID, p_agent, Vector3, p_velocity) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->velocity_ = RVO::Vector3(p_velocity.x, p_velocity.y, p_velocity.z); } COMMAND_2(agent_set_target_velocity, RID, p_agent, Vector3, p_velocity) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->prefVelocity_ = RVO::Vector3(p_velocity.x, p_velocity.y, p_velocity.z); } COMMAND_2(agent_set_position, RID, p_agent, Vector3, p_position) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->position_ = RVO::Vector3(p_position.x, p_position.y, p_position.z); } COMMAND_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); agent->get_agent()->ignore_y_ = p_ignore; } bool GdNavigationServer::agent_is_map_changed(RID p_agent) const { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND_V(agent == NULL, false); + ERR_FAIL_COND_V(agent == nullptr, false); return agent->is_map_changed(); } COMMAND_4(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata) { RvoAgent *agent = agent_owner.getornull(p_agent); - ERR_FAIL_COND(agent == NULL); + ERR_FAIL_COND(agent == nullptr); - agent->set_callback(p_receiver == NULL ? ObjectID() : p_receiver->get_instance_id(), p_method, p_udata); + agent->set_callback(p_receiver == nullptr ? ObjectID() : p_receiver->get_instance_id(), p_method, p_udata); if (agent->get_map()) { - if (p_receiver == NULL) { + if (p_receiver == nullptr) { agent->get_map()->remove_agent_as_controlled(agent); } else { agent->get_map()->set_agent_as_controlled(agent); @@ -419,14 +419,14 @@ COMMAND_1(free, RID, p_object) { std::vector<NavRegion *> regions = map->get_regions(); for (size_t i(0); i < regions.size(); i++) { map->remove_region(regions[i]); - regions[i]->set_map(NULL); + regions[i]->set_map(nullptr); } // Remove any assigned agent std::vector<RvoAgent *> agents = map->get_agents(); for (size_t i(0); i < agents.size(); i++) { map->remove_agent(agents[i]); - agents[i]->set_map(NULL); + agents[i]->set_map(nullptr); } active_maps.erase(map); @@ -437,9 +437,9 @@ COMMAND_1(free, RID, p_object) { NavRegion *region = region_owner.getornull(p_object); // Removes this region from the map if assigned - if (region->get_map() != NULL) { + if (region->get_map() != nullptr) { region->get_map()->remove_region(region); - region->set_map(NULL); + region->set_map(nullptr); } region_owner.free(p_object); @@ -449,9 +449,9 @@ COMMAND_1(free, RID, p_object) { RvoAgent *agent = agent_owner.getornull(p_object); // Removes this agent from the map if assigned - if (agent->get_map() != NULL) { + if (agent->get_map() != nullptr) { agent->get_map()->remove_agent(agent); - agent->set_map(NULL); + agent->set_map(nullptr); } agent_owner.free(p_object); diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/gdnavigation/gd_navigation_server.h index e9f5c1ffe6..e3e02f3d7c 100644 --- a/modules/gdnavigation/gd_navigation_server.h +++ b/modules/gdnavigation/gd_navigation_server.h @@ -33,7 +33,7 @@ #include "core/rid.h" #include "core/rid_owner.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" #include "nav_map.h" #include "nav_region.h" @@ -67,7 +67,7 @@ struct SetCommand { virtual void exec(GdNavigationServer *server) = 0; }; -class GdNavigationServer : public NavigationServer { +class GdNavigationServer : public NavigationServer3D { Mutex commands_mutex; /// Mutex used to make any operation threadsafe. Mutex operations_mutex; @@ -78,7 +78,7 @@ class GdNavigationServer : public NavigationServer { mutable RID_PtrOwner<NavRegion> region_owner; mutable RID_PtrOwner<RvoAgent> agent_owner; - bool active; + bool active = true; Vector<NavMap *> active_maps; public: diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp index 338e49eb9f..4bea007104 100644 --- a/modules/gdnavigation/nav_map.cpp +++ b/modules/gdnavigation/nav_map.cpp @@ -33,6 +33,7 @@ #include "core/os/threaded_array_processor.h" #include "nav_region.h" #include "rvo_agent.h" + #include <algorithm> /** @@ -41,16 +42,6 @@ #define USE_ENTRY_POINT -NavMap::NavMap() : - up(0, 1, 0), - cell_size(0.3), - edge_connection_margin(5.0), - regenerate_polygons(true), - regenerate_links(true), - agents_dirty(false), - deltatime(0.0), - map_update_id(0) {} - void NavMap::set_up(Vector3 p_up) { up = p_up; regenerate_polygons = true; @@ -80,9 +71,8 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const { } Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize) const { - - const gd::Polygon *begin_poly = NULL; - const gd::Polygon *end_poly = NULL; + const gd::Polygon *begin_poly = nullptr; + const gd::Polygon *end_poly = nullptr; Vector3 begin_point; Vector3 end_point; float begin_d = 1e20; @@ -94,7 +84,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p // For each point cast a face and check the distance between the origin/destination for (size_t point_id = 2; point_id < p.points.size(); point_id++) { - Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos); Vector3 spoint = f.get_closest_point_to(p_origin); float dpoint = spoint.distance_to(p_origin); @@ -120,7 +109,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p } if (begin_poly == end_poly) { - Vector<Vector3> path; path.resize(2); path.write[0] = begin_point; @@ -146,20 +134,20 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p open_list.push_back(0); - const gd::Polygon *reachable_end = NULL; + const gd::Polygon *reachable_end = nullptr; float reachable_d = 1e30; bool is_reachable = true; while (found_route == false) { - { // Takes the current least_cost_poly neighbors and compute the traveled_distance of each for (size_t i = 0; i < navigation_polys[least_cost_id].poly->edges.size(); i++) { gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id]; const gd::Edge &edge = least_cost_poly->poly->edges[i]; - if (!edge.other_polygon) + if (!edge.other_polygon) { continue; + } #ifdef USE_ENTRY_POINT Vector3 edge_line[2] = { @@ -181,7 +169,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p if (it != navigation_polys.end()) { // Oh this was visited already, can we win the cost? if (it->traveled_distance > new_distance) { - it->prev_navigation_poly_id = least_cost_id; it->back_navigation_edge = edge.other_edge; it->traveled_distance = new_distance; @@ -215,7 +202,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p // so use the further reachable polygon ERR_BREAK_MSG(is_reachable == false, "It's not expect to not find the most reachable polygons"); is_reachable = false; - if (reachable_end == NULL) { + if (reachable_end == nullptr) { // The path is not found and there is not a way out. break; } @@ -240,7 +227,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p open_list.clear(); open_list.push_back(0); - reachable_end = NULL; + reachable_end = nullptr; continue; } @@ -249,7 +236,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p least_cost_id = -1; float least_cost = 1e30; - for (auto element = open_list.front(); element != NULL; element = element->next()) { + for (auto element = open_list.front(); element != nullptr; element = element->next()) { gd::NavigationPoly *np = &navigation_polys[element->get()]; float cost = np->traveled_distance; #ifdef USE_ENTRY_POINT @@ -283,10 +270,8 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p } if (found_route) { - Vector<Vector3> path; if (p_optimize) { - // String pulling gd::NavigationPoly *apex_poly = &navigation_polys[least_cost_id]; @@ -300,7 +285,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p path.push_back(end_point); while (p) { - Vector3 left; Vector3 right; @@ -315,7 +299,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p left = p->poly->points[prev].pos; right = p->poly->points[prev_n].pos; - //if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){ if (p->poly->clockwise) { SWAP(left, right); } @@ -329,7 +312,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p left_poly = p; portal_left = left; } else { - clip_path(navigation_polys, path, apex_poly, portal_right, right_poly); apex_point = portal_right; @@ -349,7 +331,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p right_poly = p; portal_right = right; } else { - clip_path(navigation_polys, path, apex_poly, portal_left, left_poly); apex_point = portal_left; @@ -362,15 +343,17 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p } } - if (p->prev_navigation_poly_id != -1) + if (p->prev_navigation_poly_id != -1) { p = &navigation_polys[p->prev_navigation_poly_id]; - else + } else { // The end - p = NULL; + p = nullptr; + } } - if (path[path.size() - 1] != begin_point) + if (path[path.size() - 1] != begin_point) { path.push_back(begin_point); + } path.invert(); @@ -380,7 +363,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p // Add mid points int np_id = least_cost_id; while (np_id != -1) { - #ifdef USE_ENTRY_POINT Vector3 point = navigation_polys[np_id].entry; #else @@ -402,7 +384,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p } Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const { - bool use_collision = p_use_collision; Vector3 closest_point; real_t closest_point_d = 1e20; @@ -413,7 +394,6 @@ Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector // For each point cast a face and check the distance to the segment for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) { - const Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos); Vector3 inters; if (f.intersects_segment(p_from, p_to, &inters)) { @@ -423,7 +403,6 @@ Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector use_collision = true; closest_point_d = d; } else if (closest_point_d > d) { - closest_point = inters; closest_point_d = d; } @@ -431,9 +410,7 @@ Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector } if (use_collision == false) { - for (size_t point_id = 0; point_id < p.points.size(); point_id += 1) { - Vector3 a, b; Geometry::get_closest_points_between_segments( @@ -446,7 +423,6 @@ Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector const real_t d = a.distance_to(b); if (d < closest_point_d) { - closest_point_d = d; closest_point = b; } @@ -469,7 +445,6 @@ Vector3 NavMap::get_closest_point(const Vector3 &p_point) const { // For each point cast a face and check the distance to the point for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) { - const Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos); const Vector3 inters = f.get_closest_point_to(p_point); const real_t d = inters.distance_to(p_point); @@ -496,7 +471,6 @@ Vector3 NavMap::get_closest_point_normal(const Vector3 &p_point) const { // For each point cast a face and check the distance to the point for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) { - const Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos); const Vector3 inters = f.get_closest_point_to(p_point); const real_t d = inters.distance_to(p_point); @@ -524,7 +498,6 @@ RID NavMap::get_closest_point_owner(const Vector3 &p_point) const { // For each point cast a face and check the distance to the point for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) { - const Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos); const Vector3 inters = f.get_closest_point_to(p_point); const real_t d = inters.distance_to(p_point); @@ -588,7 +561,6 @@ void NavMap::remove_agent_as_controlled(RvoAgent *agent) { } void NavMap::sync() { - if (regenerate_polygons) { for (size_t r(0); r < regions.size(); r++) { regions[r]->scratch_polygons(); @@ -637,12 +609,12 @@ void NavMap::sync() { gd::Connection c; c.A = &poly; c.A_edge = p; - c.B = NULL; + c.B = nullptr; c.B_edge = -1; connections[ek] = c; - } else if (connection->get().B == NULL) { - CRASH_COND(connection->get().A == NULL); // Unreachable + } else if (connection->get().B == nullptr) { + CRASH_COND(connection->get().A == nullptr); // Unreachable // Connect the two Polygons by this edge connection->get().B = &poly; @@ -657,7 +629,7 @@ void NavMap::sync() { connection->get().B->edges[connection->get().B_edge].other_edge = connection->get().A_edge; } else { // The edge is already connected with another edge, skip. - ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the Navigation's `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem."); + ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the Navigation3D's `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem."); } } } @@ -667,8 +639,8 @@ void NavMap::sync() { free_edges.reserve(connections.size()); for (auto connection_element = connections.front(); connection_element; connection_element = connection_element->next()) { - if (connection_element->get().B == NULL) { - CRASH_COND(connection_element->get().A == NULL); // Unreachable + if (connection_element->get().B == nullptr) { + CRASH_COND(connection_element->get().A == nullptr); // Unreachable CRASH_COND(connection_element->get().A_edge < 0); // Unreachable // This is a free edge @@ -741,8 +713,9 @@ void NavMap::sync() { if (agents_dirty) { std::vector<RVO::Agent *> raw_agents; raw_agents.reserve(agents.size()); - for (size_t i(0); i < agents.size(); i++) + for (size_t i(0); i < agents.size(); i++) { raw_agents.push_back(agents[i]->get_agent()); + } rvo.buildAgentTree(raw_agents); } @@ -776,17 +749,18 @@ void NavMap::dispatch_callbacks() { void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const { Vector3 from = path[path.size() - 1]; - if (from.distance_to(p_to_point) < CMP_EPSILON) + if (from.distance_to(p_to_point) < CMP_EPSILON) { return; + } Plane cut_plane; cut_plane.normal = (from - p_to_point).cross(up); - if (cut_plane.normal == Vector3()) + if (cut_plane.normal == Vector3()) { return; + } cut_plane.normal.normalize(); cut_plane.d = cut_plane.normal.dot(from); while (from_poly != p_to_poly) { - int back_nav_edge = from_poly->back_navigation_edge; Vector3 a = from_poly->poly->points[back_nav_edge].pos; Vector3 b = from_poly->poly->points[(back_nav_edge + 1) % from_poly->poly->points.size()].pos; @@ -795,7 +769,6 @@ void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys from_poly = &p_navigation_polys[from_poly->prev_navigation_poly_id]; if (a.distance_to(b) > CMP_EPSILON) { - Vector3 inters; if (cut_plane.intersects_segment(a, b, &inters)) { if (inters.distance_to(p_to_point) > CMP_EPSILON && inters.distance_to(path[path.size() - 1]) > CMP_EPSILON) { diff --git a/modules/gdnavigation/nav_map.h b/modules/gdnavigation/nav_map.h index 4543f00926..892755f3f9 100644 --- a/modules/gdnavigation/nav_map.h +++ b/modules/gdnavigation/nav_map.h @@ -46,19 +46,18 @@ class RvoAgent; class NavRegion; class NavMap : public NavRid { - /// Map Up - Vector3 up; + Vector3 up = Vector3(0, 1, 0); /// To find the polygons edges the vertices are displaced in a grid where /// each cell has the following cell_size. - real_t cell_size; + real_t cell_size = 0.3; /// This value is used to detect the near edges to connect. - real_t edge_connection_margin; + real_t edge_connection_margin = 5.0; - bool regenerate_polygons; - bool regenerate_links; + bool regenerate_polygons = true; + bool regenerate_links = true; std::vector<NavRegion *> regions; @@ -69,7 +68,7 @@ class NavMap : public NavRid { RVO::KdTree rvo; /// Is agent array modified? - bool agents_dirty; + bool agents_dirty = false; /// All the Agents (even the controlled one) std::vector<RvoAgent *> agents; @@ -78,13 +77,13 @@ class NavMap : public NavRid { std::vector<RvoAgent *> controlled_agents; /// Physics delta time - real_t deltatime; + real_t deltatime = 0.0; /// Change the id each time the map is updated. - uint32_t map_update_id; + uint32_t map_update_id = 0; public: - NavMap(); + NavMap() {} void set_up(Vector3 p_up); Vector3 get_up() const { diff --git a/modules/gdnavigation/nav_region.cpp b/modules/gdnavigation/nav_region.cpp index 0215821305..51fba67cc3 100644 --- a/modules/gdnavigation/nav_region.cpp +++ b/modules/gdnavigation/nav_region.cpp @@ -36,11 +36,6 @@ @author AndreaCatania */ -NavRegion::NavRegion() : - map(NULL), - polygons_dirty(true) { -} - void NavRegion::set_map(NavMap *p_map) { map = p_map; polygons_dirty = true; @@ -71,17 +66,19 @@ void NavRegion::update_polygons() { polygons.clear(); polygons_dirty = false; - if (map == NULL) { + if (map == nullptr) { return; } - if (mesh.is_null()) + if (mesh.is_null()) { return; + } Vector<Vector3> vertices = mesh->get_vertices(); int len = vertices.size(); - if (len == 0) + if (len == 0) { return; + } const Vector3 *vertices_r = vertices.ptr(); @@ -89,7 +86,6 @@ void NavRegion::update_polygons() { // Build for (size_t i(0); i < polygons.size(); i++) { - gd::Polygon &p = polygons[i]; p.owner = this; @@ -103,7 +99,6 @@ void NavRegion::update_polygons() { float sum(0); for (int j(0); j < mesh_poly.size(); j++) { - int idx = indices[j]; if (idx < 0 || idx >= len) { valid = false; diff --git a/modules/gdnavigation/nav_region.h b/modules/gdnavigation/nav_region.h index d99254d1ad..731855bfb5 100644 --- a/modules/gdnavigation/nav_region.h +++ b/modules/gdnavigation/nav_region.h @@ -34,7 +34,7 @@ #include "nav_rid.h" #include "nav_utils.h" -#include "scene/3d/navigation.h" +#include "scene/3d/navigation_3d.h" #include <vector> /** @@ -45,17 +45,17 @@ class NavMap; class NavRegion; class NavRegion : public NavRid { - NavMap *map; + NavMap *map = nullptr; Transform transform; Ref<NavigationMesh> mesh; - bool polygons_dirty; + bool polygons_dirty = true; /// Cache std::vector<gd::Polygon> polygons; public: - NavRegion(); + NavRegion() {} void scratch_polygons() { polygons_dirty = true; diff --git a/modules/gdnavigation/nav_utils.h b/modules/gdnavigation/nav_utils.h index bdf9eb34a8..40e54df553 100644 --- a/modules/gdnavigation/nav_utils.h +++ b/modules/gdnavigation/nav_utils.h @@ -32,6 +32,7 @@ #define NAV_UTILS_H #include "core/math/vector3.h" + #include <vector> /** @@ -44,7 +45,6 @@ namespace gd { struct Polygon; union PointKey { - struct { int64_t x : 21; int64_t y : 22; @@ -56,7 +56,6 @@ union PointKey { }; struct EdgeKey { - PointKey a; PointKey b; @@ -80,19 +79,15 @@ struct Point { struct Edge { /// This edge ID - int this_edge; + int this_edge = -1; /// Other Polygon - Polygon *other_polygon; + Polygon *other_polygon = nullptr; /// The other `Polygon` at this edge id has this `Polygon`. - int other_edge; + int other_edge = -1; - Edge() { - this_edge = -1; - other_polygon = NULL; - other_edge = -1; - } + Edge() {} }; struct Polygon { @@ -112,40 +107,29 @@ struct Polygon { }; struct Connection { + Polygon *A = nullptr; + int A_edge = -1; + Polygon *B = nullptr; + int B_edge = -1; - Polygon *A; - int A_edge; - Polygon *B; - int B_edge; - - Connection() { - A = NULL; - B = NULL; - A_edge = -1; - B_edge = -1; - } + Connection() {} }; struct NavigationPoly { - uint32_t self_id; + uint32_t self_id = 0; /// This poly. const Polygon *poly; /// The previous navigation poly (id in the `navigation_poly` array). - int prev_navigation_poly_id; + int prev_navigation_poly_id = -1; /// The edge id in this `Poly` to reach the `prev_navigation_poly_id`. - uint32_t back_navigation_edge; + uint32_t back_navigation_edge = 0; /// The entry location of this poly. Vector3 entry; /// The distance to the destination. - float traveled_distance; + float traveled_distance = 0.0; NavigationPoly(const Polygon *p_poly) : - self_id(0), - poly(p_poly), - prev_navigation_poly_id(-1), - back_navigation_edge(0), - traveled_distance(0.0) { - } + poly(p_poly) {} bool operator==(const NavigationPoly &other) const { return this->poly == other.poly; diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp index e6ff7a7afa..5fe1060aae 100644 --- a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp +++ b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp @@ -34,24 +34,21 @@ #include "core/io/marshalls.h" #include "core/io/resource_saver.h" #include "navigation_mesh_generator.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/gui/box_container.h" void NavigationMeshEditor::_node_removed(Node *p_node) { - if (p_node == node) { - node = NULL; + node = nullptr; hide(); } } void NavigationMeshEditor::_notification(int p_option) { - if (p_option == NOTIFICATION_ENTER_TREE) { - - button_bake->set_icon(get_icon("Bake", "EditorIcons")); - button_reset->set_icon(get_icon("Reload", "EditorIcons")); + button_bake->set_icon(get_theme_icon("Bake", "EditorIcons")); + button_reset->set_icon(get_theme_icon("Reload", "EditorIcons")); } } @@ -61,7 +58,7 @@ void NavigationMeshEditor::_bake_pressed() { ERR_FAIL_COND(!node); if (!node->get_navigation_mesh().is_valid()) { err_dialog->set_text(TTR("A NavigationMesh resource must be set or created for this node to work.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -72,9 +69,9 @@ void NavigationMeshEditor::_bake_pressed() { } void NavigationMeshEditor::_clear_pressed() { - - if (node) + if (node) { NavigationMeshGenerator::get_singleton()->clear(node->get_navigation_mesh()); + } button_bake->set_pressed(false); bake_info->set_text(""); @@ -84,9 +81,8 @@ void NavigationMeshEditor::_clear_pressed() { } } -void NavigationMeshEditor::edit(NavigationRegion *p_nav_region) { - - if (p_nav_region == NULL || node == p_nav_region) { +void NavigationMeshEditor::edit(NavigationRegion3D *p_nav_region) { + if (p_nav_region == nullptr || node == p_nav_region) { return; } @@ -97,7 +93,6 @@ void NavigationMeshEditor::_bind_methods() { } NavigationMeshEditor::NavigationMeshEditor() { - bake_hbox = memnew(HBoxContainer); button_bake = memnew(ToolButton); @@ -117,37 +112,32 @@ NavigationMeshEditor::NavigationMeshEditor() { err_dialog = memnew(AcceptDialog); add_child(err_dialog); - node = NULL; + node = nullptr; } NavigationMeshEditor::~NavigationMeshEditor() { } void NavigationMeshEditorPlugin::edit(Object *p_object) { - - navigation_mesh_editor->edit(Object::cast_to<NavigationRegion>(p_object)); + navigation_mesh_editor->edit(Object::cast_to<NavigationRegion3D>(p_object)); } bool NavigationMeshEditorPlugin::handles(Object *p_object) const { - - return p_object->is_class("NavigationRegion"); + return p_object->is_class("NavigationRegion3D"); } void NavigationMeshEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { navigation_mesh_editor->show(); navigation_mesh_editor->bake_hbox->show(); } else { - navigation_mesh_editor->hide(); navigation_mesh_editor->bake_hbox->hide(); - navigation_mesh_editor->edit(NULL); + navigation_mesh_editor->edit(nullptr); } } NavigationMeshEditorPlugin::NavigationMeshEditorPlugin(EditorNode *p_node) { - editor = p_node; navigation_mesh_editor = memnew(NavigationMeshEditor); editor->get_viewport()->add_child(navigation_mesh_editor); diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.h b/modules/gdnavigation/navigation_mesh_editor_plugin.h index 847ad4f63d..da3a981f8c 100644 --- a/modules/gdnavigation/navigation_mesh_editor_plugin.h +++ b/modules/gdnavigation/navigation_mesh_editor_plugin.h @@ -36,7 +36,7 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -class NavigationRegion; +class NavigationRegion3D; class NavigationMeshEditor : public Control { friend class NavigationMeshEditorPlugin; @@ -50,7 +50,7 @@ class NavigationMeshEditor : public Control { ToolButton *button_reset; Label *bake_info; - NavigationRegion *node; + NavigationRegion3D *node; void _bake_pressed(); void _clear_pressed(); @@ -61,13 +61,12 @@ protected: void _notification(int p_option); public: - void edit(NavigationRegion *p_nav_region); + void edit(NavigationRegion3D *p_nav_region); NavigationMeshEditor(); ~NavigationMeshEditor(); }; class NavigationMeshEditorPlugin : public EditorPlugin { - GDCLASS(NavigationMeshEditorPlugin, EditorPlugin); NavigationMeshEditor *navigation_mesh_editor; diff --git a/modules/gdnavigation/navigation_mesh_generator.cpp b/modules/gdnavigation/navigation_mesh_generator.cpp index e7038b38a2..7dc08fbf29 100644 --- a/modules/gdnavigation/navigation_mesh_generator.cpp +++ b/modules/gdnavigation/navigation_mesh_generator.cpp @@ -34,18 +34,18 @@ #include "core/math/quick_hull.h" #include "core/os/thread.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/physics_body.h" -#include "scene/resources/box_shape.h" -#include "scene/resources/capsule_shape.h" -#include "scene/resources/concave_polygon_shape.h" -#include "scene/resources/convex_polygon_shape.h" -#include "scene/resources/cylinder_shape.h" +#include "scene/3d/collision_shape_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/resources/box_shape_3d.h" +#include "scene/resources/capsule_shape_3d.h" +#include "scene/resources/concave_polygon_shape_3d.h" +#include "scene/resources/convex_polygon_shape_3d.h" +#include "scene/resources/cylinder_shape_3d.h" #include "scene/resources/primitive_meshes.h" -#include "scene/resources/shape.h" -#include "scene/resources/sphere_shape.h" -#include "scene/resources/world_margin_shape.h" +#include "scene/resources/shape_3d.h" +#include "scene/resources/sphere_shape_3d.h" +#include "scene/resources/world_margin_shape_3d.h" #include "modules/modules_enabled.gen.h" #ifdef TOOLS_ENABLED @@ -60,7 +60,7 @@ #include "modules/gridmap/grid_map.h" #endif -NavigationMeshGenerator *NavigationMeshGenerator::singleton = NULL; +NavigationMeshGenerator *NavigationMeshGenerator::singleton = nullptr; void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies) { p_verticies.push_back(p_vec3.x); @@ -74,8 +74,9 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform for (int i = 0; i < p_mesh->get_surface_count(); i++) { current_vertex_count = p_verticies.size() / 3; - if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) + if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { continue; + } int index_count = 0; if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) { @@ -94,7 +95,6 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform const Vector3 *vr = mesh_vertices.ptr(); if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) { - Vector<int> mesh_indices = a[Mesh::ARRAY_INDEX]; const int *ir = mesh_indices.ptr(); @@ -139,10 +139,8 @@ void NavigationMeshGenerator::_add_faces(const PackedVector3Array &p_faces, cons } void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int p_generate_from, uint32_t p_collision_mask, bool p_recurse_children) { - - if (Object::cast_to<MeshInstance>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { - - MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(p_node); + if (Object::cast_to<MeshInstance3D>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { + MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(p_node); Ref<Mesh> mesh = mesh_instance->get_mesh(); if (mesh.is_valid()) { _add_mesh(mesh, p_accumulated_transform * mesh_instance->get_transform(), p_verticies, p_indices); @@ -150,9 +148,8 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, } #ifdef MODULE_CSG_ENABLED - if (Object::cast_to<CSGShape>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { - - CSGShape *csg_shape = Object::cast_to<CSGShape>(p_node); + if (Object::cast_to<CSGShape3D>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) { + CSGShape3D *csg_shape = Object::cast_to<CSGShape3D>(p_node); Array meshes = csg_shape->get_meshes(); if (!meshes.empty()) { Ref<Mesh> mesh = meshes[1]; @@ -163,22 +160,21 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, } #endif - if (Object::cast_to<StaticBody>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES) { - StaticBody *static_body = Object::cast_to<StaticBody>(p_node); + if (Object::cast_to<StaticBody3D>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_MESH_INSTANCES) { + StaticBody3D *static_body = Object::cast_to<StaticBody3D>(p_node); if (static_body->get_collision_layer() & p_collision_mask) { - for (int i = 0; i < p_node->get_child_count(); ++i) { Node *child = p_node->get_child(i); - if (Object::cast_to<CollisionShape>(child)) { - CollisionShape *col_shape = Object::cast_to<CollisionShape>(child); + if (Object::cast_to<CollisionShape3D>(child)) { + CollisionShape3D *col_shape = Object::cast_to<CollisionShape3D>(child); Transform transform = p_accumulated_transform * static_body->get_transform() * col_shape->get_transform(); Ref<Mesh> mesh; - Ref<Shape> s = col_shape->get_shape(); + Ref<Shape3D> s = col_shape->get_shape(); - BoxShape *box = Object::cast_to<BoxShape>(*s); + BoxShape3D *box = Object::cast_to<BoxShape3D>(*s); if (box) { Ref<CubeMesh> cube_mesh; cube_mesh.instance(); @@ -186,7 +182,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, mesh = cube_mesh; } - CapsuleShape *capsule = Object::cast_to<CapsuleShape>(*s); + CapsuleShape3D *capsule = Object::cast_to<CapsuleShape3D>(*s); if (capsule) { Ref<CapsuleMesh> capsule_mesh; capsule_mesh.instance(); @@ -195,7 +191,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, mesh = capsule_mesh; } - CylinderShape *cylinder = Object::cast_to<CylinderShape>(*s); + CylinderShape3D *cylinder = Object::cast_to<CylinderShape3D>(*s); if (cylinder) { Ref<CylinderMesh> cylinder_mesh; cylinder_mesh.instance(); @@ -205,7 +201,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, mesh = cylinder_mesh; } - SphereShape *sphere = Object::cast_to<SphereShape>(*s); + SphereShape3D *sphere = Object::cast_to<SphereShape3D>(*s); if (sphere) { Ref<SphereMesh> sphere_mesh; sphere_mesh.instance(); @@ -214,12 +210,12 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, mesh = sphere_mesh; } - ConcavePolygonShape *concave_polygon = Object::cast_to<ConcavePolygonShape>(*s); + ConcavePolygonShape3D *concave_polygon = Object::cast_to<ConcavePolygonShape3D>(*s); if (concave_polygon) { _add_faces(concave_polygon->get_faces(), transform, p_verticies, p_indices); } - ConvexPolygonShape *convex_polygon = Object::cast_to<ConvexPolygonShape>(*s); + ConvexPolygonShape3D *convex_polygon = Object::cast_to<ConvexPolygonShape3D>(*s); if (convex_polygon) { Vector<Vector3> varr = Variant(convex_polygon->get_points()); Geometry::MeshData md; @@ -265,8 +261,8 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, } #endif - if (Object::cast_to<Spatial>(p_node)) { - Spatial *spatial = Object::cast_to<Spatial>(p_node); + if (Object::cast_to<Node3D>(p_node)) { + Node3D *spatial = Object::cast_to<Node3D>(p_node); p_accumulated_transform = p_accumulated_transform * spatial->get_transform(); } @@ -278,7 +274,6 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform, } void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh) { - Vector<Vector3> nav_vertices; for (int i = 0; i < p_detail_mesh->nverts; i++) { @@ -320,8 +315,9 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( rcContext ctx; #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Setting up Configuration..."), 1); + } #endif const float *verts = vertices.ptr(); @@ -357,14 +353,16 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( cfg.bmax[2] = bmax[2]; #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Calculating grid size..."), 2); + } #endif rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height); #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Creating heightfield..."), 3); + } #endif hf = rcAllocHeightfield(); @@ -372,8 +370,9 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( ERR_FAIL_COND(!rcCreateHeightfield(&ctx, *hf, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch)); #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Marking walkable triangles..."), 4); + } #endif { Vector<unsigned char> tri_areas; @@ -387,16 +386,20 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( ERR_FAIL_COND(!rcRasterizeTriangles(&ctx, verts, nverts, tris, tri_areas.ptr(), ntris, *hf, cfg.walkableClimb)); } - if (p_nav_mesh->get_filter_low_hanging_obstacles()) + if (p_nav_mesh->get_filter_low_hanging_obstacles()) { rcFilterLowHangingWalkableObstacles(&ctx, cfg.walkableClimb, *hf); - if (p_nav_mesh->get_filter_ledge_spans()) + } + if (p_nav_mesh->get_filter_ledge_spans()) { rcFilterLedgeSpans(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf); - if (p_nav_mesh->get_filter_walkable_low_height_spans()) + } + if (p_nav_mesh->get_filter_walkable_low_height_spans()) { rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf); + } #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Constructing compact heightfield..."), 5); + } #endif chf = rcAllocCompactHeightfield(); @@ -405,18 +408,20 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( ERR_FAIL_COND(!rcBuildCompactHeightfield(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf, *chf)); rcFreeHeightField(hf); - hf = 0; + hf = nullptr; #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Eroding walkable area..."), 6); + } #endif ERR_FAIL_COND(!rcErodeWalkableArea(&ctx, cfg.walkableRadius, *chf)); #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Partitioning..."), 7); + } #endif if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) { @@ -429,8 +434,9 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( } #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Creating contours..."), 8); + } #endif cset = rcAllocContourSet(); @@ -439,8 +445,9 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( ERR_FAIL_COND(!rcBuildContours(&ctx, *chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cset)); #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Creating polymesh..."), 9); + } #endif poly_mesh = rcAllocPolyMesh(); @@ -452,21 +459,22 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh( ERR_FAIL_COND(!rcBuildPolyMeshDetail(&ctx, *poly_mesh, *chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *detail_mesh)); rcFreeCompactHeightfield(chf); - chf = 0; + chf = nullptr; rcFreeContourSet(cset); - cset = 0; + cset = nullptr; #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Converting to native navigation mesh..."), 10); + } #endif _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_nav_mesh); rcFreePolyMesh(poly_mesh); - poly_mesh = 0; + poly_mesh = nullptr; rcFreePolyMeshDetail(detail_mesh); - detail_mesh = 0; + detail_mesh = nullptr; } NavigationMeshGenerator *NavigationMeshGenerator::get_singleton() { @@ -481,17 +489,17 @@ NavigationMeshGenerator::~NavigationMeshGenerator() { } void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) { - ERR_FAIL_COND(!p_nav_mesh.is_valid()); #ifdef TOOLS_ENABLED - EditorProgress *ep(NULL); + EditorProgress *ep(nullptr); if (Engine::get_singleton()->is_editor_hint()) { ep = memnew(EditorProgress("bake", TTR("Navigation Mesh Generator Setup:"), 11)); } - if (ep) + if (ep) { ep->step(TTR("Parsing Geometry..."), 0); + } #endif Vector<float> vertices; @@ -505,7 +513,7 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) p_node->get_tree()->get_nodes_in_group(p_nav_mesh->get_source_group_name(), &parse_nodes); } - Transform navmesh_xform = Object::cast_to<Spatial>(p_node)->get_transform().affine_inverse(); + Transform navmesh_xform = Object::cast_to<Node3D>(p_node)->get_transform().affine_inverse(); for (const List<Node *>::Element *E = parse_nodes.front(); E; E = E->next()) { int geometry_type = p_nav_mesh->get_parsed_geometry_type(); uint32_t collision_mask = p_nav_mesh->get_collision_mask(); @@ -514,12 +522,11 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) } if (vertices.size() > 0 && indices.size() > 0) { - - rcHeightfield *hf = NULL; - rcCompactHeightfield *chf = NULL; - rcContourSet *cset = NULL; - rcPolyMesh *poly_mesh = NULL; - rcPolyMeshDetail *detail_mesh = NULL; + rcHeightfield *hf = nullptr; + rcCompactHeightfield *chf = nullptr; + rcContourSet *cset = nullptr; + rcPolyMesh *poly_mesh = nullptr; + rcPolyMeshDetail *detail_mesh = nullptr; _build_recast_navigation_mesh( p_nav_mesh, @@ -535,27 +542,29 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) indices); rcFreeHeightField(hf); - hf = 0; + hf = nullptr; rcFreeCompactHeightfield(chf); - chf = 0; + chf = nullptr; rcFreeContourSet(cset); - cset = 0; + cset = nullptr; rcFreePolyMesh(poly_mesh); - poly_mesh = 0; + poly_mesh = nullptr; rcFreePolyMeshDetail(detail_mesh); - detail_mesh = 0; + detail_mesh = nullptr; } #ifdef TOOLS_ENABLED - if (ep) + if (ep) { ep->step(TTR("Done!"), 11); + } - if (ep) + if (ep) { memdelete(ep); + } #endif } diff --git a/modules/gdnavigation/navigation_mesh_generator.h b/modules/gdnavigation/navigation_mesh_generator.h index d1f2e4b56f..c5f7b2ab81 100644 --- a/modules/gdnavigation/navigation_mesh_generator.h +++ b/modules/gdnavigation/navigation_mesh_generator.h @@ -33,7 +33,7 @@ #ifndef _3D_DISABLED -#include "scene/3d/navigation_region.h" +#include "scene/3d/navigation_region_3d.h" #include <Recast.h> diff --git a/modules/gdnavigation/register_types.cpp b/modules/gdnavigation/register_types.cpp index d717733787..088b26bf17 100644 --- a/modules/gdnavigation/register_types.cpp +++ b/modules/gdnavigation/register_types.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "gd_navigation_server.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" #ifndef _3D_DISABLED #include "navigation_mesh_generator.h" @@ -47,15 +47,15 @@ */ #ifndef _3D_DISABLED -NavigationMeshGenerator *_nav_mesh_generator = NULL; +NavigationMeshGenerator *_nav_mesh_generator = nullptr; #endif -NavigationServer *new_server() { +NavigationServer3D *new_server() { return memnew(GdNavigationServer); } void register_gdnavigation_types() { - NavigationServerManager::set_default_server(new_server); + NavigationServer3DManager::set_default_server(new_server); #ifndef _3D_DISABLED _nav_mesh_generator = memnew(NavigationMeshGenerator); diff --git a/modules/gdnavigation/register_types.h b/modules/gdnavigation/register_types.h index bd15eaaada..cdbff1b937 100644 --- a/modules/gdnavigation/register_types.h +++ b/modules/gdnavigation/register_types.h @@ -32,5 +32,10 @@ @author AndreaCatania */ +#ifndef GDNAVIGATION_REGISTER_TYPES_H +#define GDNAVIGATION_REGISTER_TYPES_H + void register_gdnavigation_types(); void unregister_gdnavigation_types(); + +#endif // GDNAVIGATION_REGISTER_TYPES_H diff --git a/modules/gdnavigation/rvo_agent.cpp b/modules/gdnavigation/rvo_agent.cpp index 677e525bbf..1e1bdbd07d 100644 --- a/modules/gdnavigation/rvo_agent.cpp +++ b/modules/gdnavigation/rvo_agent.cpp @@ -36,8 +36,7 @@ @author AndreaCatania */ -RvoAgent::RvoAgent() : - map(NULL) { +RvoAgent::RvoAgent() { callback.id = ObjectID(); } @@ -70,7 +69,7 @@ void RvoAgent::dispatch_callback() { return; } Object *obj = ObjectDB::get_instance(callback.id); - if (obj == NULL) { + if (obj == nullptr) { callback.id = ObjectID(); } diff --git a/modules/gdnavigation/rvo_agent.h b/modules/gdnavigation/rvo_agent.h index 914cbaa7d9..f5c579ba84 100644 --- a/modules/gdnavigation/rvo_agent.h +++ b/modules/gdnavigation/rvo_agent.h @@ -49,7 +49,7 @@ class RvoAgent : public NavRid { Variant new_velocity; }; - NavMap *map; + NavMap *map = nullptr; RVO::Agent agent; AvoidanceComputedCallback callback; uint32_t map_update_id; diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index 74e653ce43..e58a1d8edc 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -1,19 +1,19 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_gdscript = env_modules.Clone() env_gdscript.add_source_files(env.modules_sources, "*.cpp") -if env['tools']: +if env["tools"]: env_gdscript.add_source_files(env.modules_sources, "./editor/*.cpp") # Those two modules are required for the language server protocol - if env['module_jsonrpc_enabled'] and env['module_websocket_enabled']: + if env["module_jsonrpc_enabled"] and env["module_websocket_enabled"]: env_gdscript.add_source_files(env.modules_sources, "./language_server/*.cpp") else: # Using a define in the disabled case, to avoid having an extra define # in regular builds where all modules are enabled. - env_gdscript.Append(CPPDEFINES=['GDSCRIPT_NO_LSP']) + env_gdscript.Append(CPPDEFINES=["GDSCRIPT_NO_LSP"]) diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py index a525eedaaa..6fc227e7f5 100644 --- a/modules/gdscript/config.py +++ b/modules/gdscript/config.py @@ -1,16 +1,18 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "@GDScript", "GDScript", "GDScriptFunctionState", - "GDScriptNativeClass", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 2f6f9f30a4..be159b6407 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -90,14 +90,18 @@ </return> <argument index="0" name="condition" type="bool"> </argument> + <argument index="1" name="message" type="String" default=""""> + </argument> <description> - Asserts that the [code]condition[/code] is [code]true[/code] . If the [code]condition[/code] is [code]false[/code], an error is generated and the program is halted until you resume it. Only executes in debug builds, or when running the game from the editor. Use it for debugging purposes, to make sure a statement is [code]true[/code] during development. + Asserts that the [code]condition[/code] is [code]true[/code]. If the [code]condition[/code] is [code]false[/code], an error is generated and the program is halted until you resume it. Only executes in debug builds, or when running the game from the editor. Use it for debugging purposes, to make sure a statement is [code]true[/code] during development. + The optional [code]message[/code] argument, if given, is shown in addition to the generic "Assertion failed" message. You can use this to provide additional details about why the assertion failed. [codeblock] # Imagine we always want speed to be between 0 and 20 speed = -10 assert(speed < 20) # True, the program will continue assert(speed >= 0) # False, the program will stop assert(speed >= 0 && speed < 20) # You can also combine the two conditional statements in one check + assert(speed < 20, "speed = %f, but the speed limit is 20" % speed) # Show a message with clarifying details [/codeblock] </description> </method> @@ -564,7 +568,7 @@ <description> Linearly interpolates between two values by a normalized value. This is the opposite of [method inverse_lerp]. If the [code]from[/code] and [code]to[/code] arguments are of type [int] or [float], the return value is a [float]. - If both are of the same vector type ([Vector2], [Vector3] or [Color]), the return value will be of the same type ([code]lerp[/code] then calls the vector type's [code]linear_interpolate[/code] method). + If both are of the same vector type ([Vector2], [Vector3] or [Color]), the return value will be of the same type ([code]lerp[/code] then calls the vector type's [code]lerp[/code] method). [codeblock] lerp(0, 4, 0.75) # Returns 3.0 lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Returns Vector2(2, 3.5) @@ -1216,7 +1220,7 @@ <description> Returns whether the given class exists in [ClassDB]. [codeblock] - type_exists("Sprite") # Returns true + type_exists("Sprite2D") # Returns true type_exists("Variant") # Returns false [/codeblock] </description> diff --git a/modules/gdscript/doc_classes/GDScriptNativeClass.xml b/modules/gdscript/doc_classes/GDScriptNativeClass.xml deleted file mode 100644 index 0a8982de8e..0000000000 --- a/modules/gdscript/doc_classes/GDScriptNativeClass.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="GDScriptNativeClass" inherits="Reference" version="4.0"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> - <methods> - <method name="new"> - <return type="Variant"> - </return> - <description> - </description> - </method> - </methods> - <constants> - </constants> -</class> diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 687e1785be..d0f27b632b 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -34,17 +34,14 @@ #include "scene/gui/text_edit.h" inline bool _is_symbol(CharType c) { - return is_symbol(c); } static bool _is_text_char(CharType c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; } static bool _is_char(CharType c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } @@ -180,10 +177,10 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } if (in_region == -1 && !in_keyword && is_char && !prev_is_char) { - int to = j; - while (to < str.length() && _is_text_char(str[to])) + while (to < str.length() && _is_text_char(str[to])) { to++; + } String word = str.substr(j, to - j); Color col = Color(); @@ -208,7 +205,6 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } if (!in_function_name && in_word && !in_keyword) { - int k = j; while (k < str.length() && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') { k++; @@ -238,7 +234,6 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } if (is_symbol) { - if (in_function_name) { in_function_args = true; } @@ -358,11 +353,11 @@ List<String> GDScriptSyntaxHighlighter::get_supported_languages() { } void GDScriptSyntaxHighlighter::_update_cache() { - font_color = text_editor->get_color("font_color"); - symbol_color = text_editor->get_color("symbol_color"); - function_color = text_editor->get_color("function_color"); - number_color = text_editor->get_color("number_color"); - member_color = text_editor->get_color("member_variable_color"); + font_color = text_editor->get_theme_color("font_color"); + symbol_color = text_editor->get_theme_color("symbol_color"); + function_color = text_editor->get_theme_color("function_color"); + number_color = text_editor->get_theme_color("number_color"); + member_color = text_editor->get_theme_color("member_variable_color"); const String text_editor_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme"); const bool default_theme = text_editor_color_theme == "Default"; diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 05e9f8652e..632407c61f 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -44,12 +44,10 @@ /////////////////////////// GDScriptNativeClass::GDScriptNativeClass(const StringName &p_name) { - name = p_name; } bool GDScriptNativeClass::_get(const StringName &p_name, Variant &r_ret) const { - bool ok; int v = ClassDB::get_integer_constant(name, p_name, &ok); @@ -62,12 +60,10 @@ bool GDScriptNativeClass::_get(const StringName &p_name, Variant &r_ret) const { } void GDScriptNativeClass::_bind_methods() { - ClassDB::bind_method(D_METHOD("new"), &GDScriptNativeClass::_new); } Variant GDScriptNativeClass::_new() { - Object *o = instance(); ERR_FAIL_COND_V_MSG(!o, Variant(), "Class type: '" + String(name) + "' is not instantiable."); @@ -80,12 +76,10 @@ Variant GDScriptNativeClass::_new() { } Object *GDScriptNativeClass::instance() { - return ClassDB::instance(name); } GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error) { - /* STEP 1, CREATE */ GDScriptInstance *instance = memnew(GDScriptInstance); @@ -103,32 +97,28 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco instance->owner->set_script_instance(instance); /* STEP 2, INITIALIZE AND CONSTRUCT */ - { MutexLock lock(GDScriptLanguage::singleton->lock); - instances.insert(instance->owner); } - + if (p_argcount < 0) { + return instance; + } initializer->call(instance, p_args, p_argcount, r_error); - if (r_error.error != Callable::CallError::CALL_OK) { instance->script = Ref<GDScript>(); - instance->owner->set_script_instance(NULL); + instance->owner->set_script_instance(nullptr); { MutexLock lock(GDScriptLanguage::singleton->lock); instances.erase(p_owner); } - - ERR_FAIL_COND_V(r_error.error != Callable::CallError::CALL_OK, NULL); //error constructing + ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance."); } - //@TODO make thread safe return instance; } Variant GDScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - /* STEP 1, CREATE */ if (!valid) { @@ -138,7 +128,7 @@ Variant GDScript::_new(const Variant **p_args, int p_argcount, Callable::CallErr r_error.error = Callable::CallError::CALL_OK; REF ref; - Object *owner = NULL; + Object *owner = nullptr; GDScript *_baseptr = this; while (_baseptr->_base) { @@ -158,7 +148,7 @@ Variant GDScript::_new(const Variant **p_args, int p_argcount, Callable::CallErr ref = REF(r); } - GDScriptInstance *instance = _create_instance(p_args, p_argcount, owner, r != NULL, r_error); + GDScriptInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error); if (!instance) { if (ref.is_null()) { memdelete(owner); //no owner, sorry @@ -174,7 +164,6 @@ Variant GDScript::_new(const Variant **p_args, int p_argcount, Callable::CallErr } bool GDScript::can_instance() const { - #ifdef TOOLS_ENABLED return valid && (tool || ScriptServer::is_scripting_enabled()); #else @@ -183,7 +172,6 @@ bool GDScript::can_instance() const { } Ref<Script> GDScript::get_base_script() const { - if (_base) { return Ref<GDScript>(_base); } else { @@ -192,16 +180,16 @@ Ref<Script> GDScript::get_base_script() const { } StringName GDScript::get_instance_base_type() const { - - if (native.is_valid()) + if (native.is_valid()) { return native->get_name(); - if (base.is_valid() && base->is_valid()) + } + if (base.is_valid() && base->is_valid()) { return base->get_instance_base_type(); + } return StringName(); } struct _GDScriptMemberSort { - int index; StringName name; _FORCE_INLINE_ bool operator<(const _GDScriptMemberSort &p_member) const { return index < p_member.index; } @@ -210,13 +198,11 @@ struct _GDScriptMemberSort { #ifdef TOOLS_ENABLED void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { - placeholders.erase(p_placeholder); } #endif void GDScript::get_script_method_list(List<MethodInfo> *p_list) const { - const GDScript *current = this; while (current) { for (const Map<StringName, GDScriptFunction *>::Element *E = current->member_functions.front(); E; E = E->next()) { @@ -236,15 +222,12 @@ void GDScript::get_script_method_list(List<MethodInfo> *p_list) const { } void GDScript::get_script_property_list(List<PropertyInfo> *p_list) const { - const GDScript *sptr = this; List<PropertyInfo> props; while (sptr) { - Vector<_GDScriptMemberSort> msort; for (Map<StringName, PropertyInfo>::Element *E = sptr->member_info.front(); E; E = E->next()) { - _GDScriptMemberSort ms; ERR_CONTINUE(!sptr->member_indices.has(E->key())); ms.index = sptr->member_indices[E->key()].index; @@ -255,7 +238,6 @@ void GDScript::get_script_property_list(List<PropertyInfo> *p_list) const { msort.sort(); msort.invert(); for (int i = 0; i < msort.size(); i++) { - props.push_front(sptr->member_info[msort[i].name]); } @@ -268,15 +250,14 @@ void GDScript::get_script_property_list(List<PropertyInfo> *p_list) const { } bool GDScript::has_method(const StringName &p_method) const { - return member_functions.has(p_method); } MethodInfo GDScript::get_method_info(const StringName &p_method) const { - const Map<StringName, GDScriptFunction *>::Element *E = member_functions.find(p_method); - if (!E) + if (!E) { return MethodInfo(); + } GDScriptFunction *func = E->get(); MethodInfo mi; @@ -290,7 +271,6 @@ MethodInfo GDScript::get_method_info(const StringName &p_method) const { } bool GDScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { - #ifdef TOOLS_ENABLED const Map<StringName, Variant>::Element *E = member_default_values_cache.find(p_property); @@ -307,23 +287,22 @@ bool GDScript::get_property_default_value(const StringName &p_property, Variant } ScriptInstance *GDScript::instance_create(Object *p_this) { - GDScript *top = this; - while (top->_base) + while (top->_base) { top = top->_base; + } if (top->native.is_valid()) { if (!ClassDB::is_parent_class(p_this->get_class_name(), top->native->get_name())) { - if (EngineDebugger::is_active()) { GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'"); } - ERR_FAIL_V_MSG(NULL, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instanced in object of type '" + p_this->get_class() + "'" + "."); + ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instanced in object of type '" + p_this->get_class() + "'" + "."); } } Callable::CallError unchecked_error; - return _create_instance(NULL, 0, p_this, Object::cast_to<Reference>(p_this) != NULL, unchecked_error); + return _create_instance(nullptr, 0, p_this, Object::cast_to<Reference>(p_this) != nullptr, unchecked_error); } PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this) { @@ -333,29 +312,28 @@ PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this) _update_exports(); return si; #else - return NULL; + return nullptr; #endif } bool GDScript::instance_has(const Object *p_this) const { - MutexLock lock(GDScriptLanguage::singleton->lock); return instances.has((Object *)p_this); } bool GDScript::has_source_code() const { - return source != ""; } -String GDScript::get_source_code() const { +String GDScript::get_source_code() const { return source; } -void GDScript::set_source_code(const String &p_code) { - if (source == p_code) +void GDScript::set_source_code(const String &p_code) { + if (source == p_code) { return; + } source = p_code; #ifdef TOOLS_ENABLED source_changed_cache = true; @@ -364,7 +342,6 @@ void GDScript::set_source_code(const String &p_code) { #ifdef TOOLS_ENABLED void GDScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) { - if (base_cache.is_valid()) { base_cache->_update_exports_values(values, propnames); } @@ -379,10 +356,15 @@ void GDScript::_update_exports_values(Map<StringName, Variant> &values, List<Pro } #endif -bool GDScript::_update_exports() { - +bool GDScript::_update_exports(bool *r_err, bool p_recursive_call) { #ifdef TOOLS_ENABLED + static Vector<GDScript *> base_caches; + if (!p_recursive_call) { + base_caches.clear(); + } + base_caches.append(this); + bool changed = false; if (source_changed_cache) { @@ -391,17 +373,18 @@ bool GDScript::_update_exports() { String basedir = path; - if (basedir == "") + if (basedir == "") { basedir = get_path(); + } - if (basedir != "") + if (basedir != "") { basedir = basedir.get_base_dir(); + } GDScriptParser parser; Error err = parser.parse(source, basedir, true, path); if (err == OK) { - const GDScriptParser::Node *root = parser.get_parse_tree(); ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, false); @@ -417,10 +400,8 @@ bool GDScript::_update_exports() { if (String(c->extends_file) != "" && String(c->extends_file) != get_path()) { path = c->extends_file; if (path.is_rel_path()) { - String base = get_path(); if (base == "" || base.is_rel_path()) { - ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data()); } else { path = base.get_base_dir().plus_file(path); @@ -429,17 +410,16 @@ bool GDScript::_update_exports() { } else if (c->extends_class.size() != 0) { String base = c->extends_class[0]; - if (ScriptServer::is_global_class(base)) + if (ScriptServer::is_global_class(base)) { path = ScriptServer::get_global_class_path(base); + } } if (path != "") { if (path != get_path()) { - Ref<GDScript> bf = ResourceLoader::load(path); if (bf.is_valid()) { - base_cache = bf; bf->inheriters_cache.insert(get_instance_id()); } @@ -453,8 +433,9 @@ bool GDScript::_update_exports() { member_default_values_cache.clear(); for (int i = 0; i < c->variables.size(); i++) { - if (c->variables[i]._export.type == Variant::NIL) + if (c->variables[i]._export.type == Variant::NIL) { continue; + } members_cache.push_back(c->variables[i]._export); member_default_values_cache[c->variables[i].identifier] = c->variables[i].default_value; @@ -476,7 +457,24 @@ bool GDScript::_update_exports() { placeholder_fallback_enabled = false; if (base_cache.is_valid() && base_cache->is_valid()) { - if (base_cache->_update_exports()) { + for (int i = 0; i < base_caches.size(); i++) { + if (base_caches[i] == base_cache.ptr()) { + if (r_err) { + *r_err = true; + } + valid = false; // to show error in the editor + base_cache->valid = false; + base_cache->inheriters_cache.clear(); // to prevent future stackoverflows + base_cache.unref(); + base.unref(); + _base = nullptr; + ERR_FAIL_V_MSG(false, "Cyclic inheritance in script class."); + } + } + if (base_cache->_update_exports(r_err, true)) { + if (r_err && *r_err) { + return false; + } changed = true; } } @@ -501,18 +499,22 @@ bool GDScript::_update_exports() { } void GDScript::update_exports() { - #ifdef TOOLS_ENABLED - _update_exports(); + bool cyclic_error = false; + _update_exports(&cyclic_error); + if (cyclic_error) { + return; + } Set<ObjectID> copy = inheriters_cache; //might get modified for (Set<ObjectID>::Element *E = copy.front(); E; E = E->next()) { Object *id = ObjectDB::get_instance(E->get()); GDScript *s = Object::cast_to<GDScript>(id); - if (!s) + if (!s) { continue; + } s->update_exports(); } @@ -520,16 +522,13 @@ void GDScript::update_exports() { } void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) { - p_sc->path = p_path; for (Map<StringName, Ref<GDScript>>::Element *E = p_sc->subclasses.front(); E; E = E->next()) { - _set_subclass_path(E->get(), p_path); } } Error GDScript::reload(bool p_keep_state) { - bool has_instances; { MutexLock lock(GDScriptLanguage::singleton->lock); @@ -541,11 +540,13 @@ Error GDScript::reload(bool p_keep_state) { String basedir = path; - if (basedir == "") + if (basedir == "") { basedir = get_path(); + } - if (basedir != "") + if (basedir != "") { basedir = basedir.get_base_dir(); + } if (source.find("%BASE%") != -1) { //loading a template, don't parse @@ -569,7 +570,6 @@ Error GDScript::reload(bool p_keep_state) { err = compiler.compile(&parser, this, p_keep_state); if (err) { - if (can_run) { if (EngineDebugger::is_active()) { GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error()); @@ -593,7 +593,6 @@ Error GDScript::reload(bool p_keep_state) { valid = true; for (Map<StringName, Ref<GDScript>>::Element *E = subclasses.front(); E; E = E->next()) { - _set_subclass_path(E->get(), path); } @@ -603,12 +602,10 @@ Error GDScript::reload(bool p_keep_state) { } ScriptLanguage *GDScript::get_language() const { - return GDScriptLanguage::get_singleton(); } void GDScript::get_constants(Map<StringName, Variant> *p_constants) { - if (p_constants) { for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { (*p_constants)[E->key()] = E->value(); @@ -638,12 +635,16 @@ uint16_t GDScript::get_rpc_method_id(const StringName &p_method) const { } StringName GDScript::get_rpc_method(const uint16_t p_rpc_method_id) const { - ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName()); + if (p_rpc_method_id >= rpc_functions.size()) { + return StringName(); + } return rpc_functions[p_rpc_method_id].name; } MultiplayerAPI::RPCMode GDScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { - ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED); + if (p_rpc_method_id >= rpc_functions.size()) { + return MultiplayerAPI::RPC_MODE_DISABLED; + } return rpc_functions[p_rpc_method_id].mode; } @@ -665,12 +666,16 @@ uint16_t GDScript::get_rset_property_id(const StringName &p_variable) const { } StringName GDScript::get_rset_property(const uint16_t p_rset_member_id) const { - ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName()); + if (p_rset_member_id >= rpc_variables.size()) { + return StringName(); + } return rpc_variables[p_rset_member_id].name; } MultiplayerAPI::RPCMode GDScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const { - ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), MultiplayerAPI::RPC_MODE_DISABLED); + if (p_rset_member_id >= rpc_variables.size()) { + return MultiplayerAPI::RPC_MODE_DISABLED; + } return rpc_variables[p_rset_member_id].mode; } @@ -679,16 +684,13 @@ MultiplayerAPI::RPCMode GDScript::get_rset_mode(const StringName &p_variable) co } Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - GDScript *top = this; while (top) { - Map<StringName, GDScriptFunction *>::Element *E = top->member_functions.find(p_method); if (E) { - ERR_FAIL_COND_V_MSG(!E->get()->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script."); - return E->get()->call(NULL, p_args, p_argcount, r_error); + return E->get()->call(nullptr, p_args, p_argcount, r_error); } top = top->_base; } @@ -699,16 +701,12 @@ Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p } bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { - { - const GDScript *top = this; while (top) { - { const Map<StringName, Variant>::Element *E = top->constants.find(p_name); if (E) { - r_ret = E->get(); return true; } @@ -717,7 +715,6 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { { const Map<StringName, Ref<GDScript>>::Element *E = subclasses.find(p_name); if (E) { - r_ret = E->get(); return true; } @@ -726,7 +723,6 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { } if (p_name == GDScriptLanguage::get_singleton()->strings._script_source) { - r_ret = get_source_code(); return true; } @@ -734,42 +730,37 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const { return false; } -bool GDScript::_set(const StringName &p_name, const Variant &p_value) { +bool GDScript::_set(const StringName &p_name, const Variant &p_value) { if (p_name == GDScriptLanguage::get_singleton()->strings._script_source) { - set_source_code(p_value); reload(); - } else + } else { return false; + } return true; } void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const { - p_properties->push_back(PropertyInfo(Variant::STRING, "script/source", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); } void GDScript::_bind_methods() { - ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &GDScript::_new, MethodInfo("new")); ClassDB::bind_method(D_METHOD("get_as_byte_code"), &GDScript::get_as_byte_code); } Vector<uint8_t> GDScript::get_as_byte_code() const { - GDScriptTokenizerBuffer tokenizer; return tokenizer.parse_code_string(source); }; Error GDScript::load_byte_code(const String &p_path) { - Vector<uint8_t> bytecode; if (p_path.ends_with("gde")) { - FileAccess *fa = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V(!fa, ERR_CANT_OPEN); @@ -798,7 +789,6 @@ Error GDScript::load_byte_code(const String &p_path) { memdelete(fae); } else { - bytecode = FileAccess::get_file_as_array(p_path); } @@ -807,11 +797,13 @@ Error GDScript::load_byte_code(const String &p_path) { String basedir = path; - if (basedir == "") + if (basedir == "") { basedir = get_path(); + } - if (basedir != "") + if (basedir != "") { basedir = basedir.get_base_dir(); + } valid = false; GDScriptParser parser; @@ -832,7 +824,6 @@ Error GDScript::load_byte_code(const String &p_path) { valid = true; for (Map<StringName, Ref<GDScript>>::Element *E = subclasses.front(); E; E = E->next()) { - _set_subclass_path(E->get(), path); } @@ -842,12 +833,10 @@ Error GDScript::load_byte_code(const String &p_path) { } Error GDScript::load_source_code(const String &p_path) { - Vector<uint8_t> sourcef; Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); if (err) { - ERR_FAIL_COND_V(err, err); } @@ -862,7 +851,6 @@ Error GDScript::load_source_code(const String &p_path) { String s; if (s.parse_utf8((const char *)w)) { - ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode."); } @@ -875,29 +863,45 @@ Error GDScript::load_source_code(const String &p_path) { } const Map<StringName, GDScriptFunction *> &GDScript::debug_get_member_functions() const { - return member_functions; } StringName GDScript::debug_get_member_by_index(int p_idx) const { - for (const Map<StringName, MemberInfo>::Element *E = member_indices.front(); E; E = E->next()) { - - if (E->get().index == p_idx) + if (E->get().index == p_idx) { return E->key(); + } } return "<error>"; } Ref<GDScript> GDScript::get_base() const { - return base; } +bool GDScript::inherits_script(const Ref<Script> &p_script) const { + Ref<GDScript> gd = p_script; + if (gd.is_null()) { + return false; + } + + const GDScript *s = this; + + while (s) { + if (s == p_script.ptr()) { + return true; + } + s = s->_base; + } + + return false; +} + bool GDScript::has_script_signal(const StringName &p_signal) const { - if (_signals.has(p_signal)) + if (_signals.has(p_signal)) { return true; + } if (base.is_valid()) { return base->has_script_signal(p_signal); } @@ -908,10 +912,9 @@ bool GDScript::has_script_signal(const StringName &p_signal) const { #endif return false; } -void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const { +void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const { for (const Map<StringName, Vector<StringName>>::Element *E = _signals.front(); E; E = E->next()) { - MethodInfo mi; mi.name = E->key(); for (int i = 0; i < E->get().size(); i++) { @@ -935,12 +938,11 @@ void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const { GDScript::GDScript() : script_list(this) { - valid = false; subclass_count = 0; - initializer = NULL; - _base = NULL; - _owner = NULL; + initializer = nullptr; + _base = nullptr; + _owner = nullptr; tool = false; #ifdef TOOLS_ENABLED source_changed_cache = false; @@ -964,7 +966,7 @@ void GDScript::_save_orphaned_subclasses() { Vector<ClassRefWithName> weak_subclasses; // collect subclasses ObjectID and name for (Map<StringName, Ref<GDScript>>::Element *E = subclasses.front(); E; E = E->next()) { - E->get()->_owner = NULL; //bye, you are no longer owned cause I died + E->get()->_owner = nullptr; //bye, you are no longer owned cause I died ClassRefWithName subclass; subclass.id = E->get()->get_instance_id(); subclass.fully_qualified_name = E->get()->fully_qualified_name; @@ -980,8 +982,9 @@ void GDScript::_save_orphaned_subclasses() { for (int i = 0; i < weak_subclasses.size(); i++) { ClassRefWithName subclass = weak_subclasses[i]; Object *obj = ObjectDB::get_instance(subclass.id); - if (!obj) + if (!obj) { continue; + } // subclass is not released GDScriptLanguage::get_singleton()->add_orphan_subclass(subclass.fully_qualified_name, subclass.id); } @@ -1022,13 +1025,15 @@ void GDScript::_init_rpc_methods_properties() { } } - if (cscript != this) + if (cscript != this) { sub_E = sub_E->next(); + } - if (sub_E) + if (sub_E) { cscript = sub_E->get().ptr(); - else - cscript = NULL; + } else { + cscript = nullptr; + } } // Sort so we are 100% that they are always the same. @@ -1037,6 +1042,15 @@ void GDScript::_init_rpc_methods_properties() { } GDScript::~GDScript() { + { + MutexLock lock(GDScriptLanguage::get_singleton()->lock); + + while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { + E->self()->_clear_stack(); + pending_func_states.remove(E); + } + } + for (Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) { memdelete(E->get()); } @@ -1057,7 +1071,6 @@ GDScript::~GDScript() { ////////////////////////////// bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { - //member { const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name); @@ -1092,17 +1105,16 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { GDScript *sptr = script.ptr(); while (sptr) { - Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set); if (E) { - Variant name = p_name; const Variant *args[2] = { &name, &p_value }; Callable::CallError err; Variant ret = E->get()->call(this, (const Variant **)args, 2, err); - if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) + if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) { return true; + } } sptr = sptr->_base; } @@ -1111,16 +1123,14 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { } bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { - const GDScript *sptr = script.ptr(); while (sptr) { - { const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name); if (E) { if (E->get().getter) { Callable::CallError err; - r_ret = const_cast<GDScriptInstance *>(this)->call(E->get().getter, NULL, 0, err); + r_ret = const_cast<GDScriptInstance *>(this)->call(E->get().getter, nullptr, 0, err); if (err.error == Callable::CallError::CALL_OK) { return true; } @@ -1131,7 +1141,6 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { } { - const GDScript *sl = sptr; while (sl) { const Map<StringName, Variant>::Element *E = sl->constants.find(p_name); @@ -1146,7 +1155,6 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { { const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get); if (E) { - Variant name = p_name; const Variant *args[1] = { &name }; @@ -1165,20 +1173,20 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const { } Variant::Type GDScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { - const GDScript *sptr = script.ptr(); while (sptr) { - if (sptr->member_info.has(p_name)) { - if (r_is_valid) + if (r_is_valid) { *r_is_valid = true; + } return sptr->member_info[p_name].type; } sptr = sptr->_base; } - if (r_is_valid) + if (r_is_valid) { *r_is_valid = false; + } return Variant::NIL; } @@ -1189,19 +1197,15 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const List<PropertyInfo> props; while (sptr) { - const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list); if (E) { - Callable::CallError err; - Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), NULL, 0, err); + Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err); if (err.error == Callable::CallError::CALL_OK) { - ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries."); Array arr = ret; for (int i = 0; i < arr.size(); i++) { - Dictionary d = arr[i]; ERR_CONTINUE(!d.has("name")); ERR_CONTINUE(!d.has("type")); @@ -1210,12 +1214,15 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX); pinfo.name = d["name"]; ERR_CONTINUE(pinfo.name == ""); - if (d.has("hint")) + if (d.has("hint")) { pinfo.hint = PropertyHint(d["hint"].operator int()); - if (d.has("hint_string")) + } + if (d.has("hint_string")) { pinfo.hint_string = d["hint_string"]; - if (d.has("usage")) + } + if (d.has("usage")) { pinfo.usage = d["usage"]; + } props.push_back(pinfo); } @@ -1226,7 +1233,6 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const Vector<_GDScriptMemberSort> msort; for (Map<StringName, PropertyInfo>::Element *F = sptr->member_info.front(); F; F = F->next()) { - _GDScriptMemberSort ms; ERR_CONTINUE(!sptr->member_indices.has(F->key())); ms.index = sptr->member_indices[F->key()].index; @@ -1237,7 +1243,6 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const msort.sort(); msort.invert(); for (int i = 0; i < msort.size(); i++) { - props.push_front(sptr->member_info[msort[i].name]); } @@ -1245,23 +1250,20 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const } for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - p_properties->push_back(E->get()); } } void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const { - const GDScript *sptr = script.ptr(); while (sptr) { - for (Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.front(); E; E = E->next()) { - MethodInfo mi; mi.name = E->key(); mi.flags |= METHOD_FLAG_FROM_SCRIPT; - for (int i = 0; i < E->get()->get_argument_count(); i++) + for (int i = 0; i < E->get()->get_argument_count(); i++) { mi.arguments.push_back(PropertyInfo(Variant::NIL, "arg" + itos(i))); + } p_list->push_back(mi); } sptr = sptr->_base; @@ -1269,19 +1271,19 @@ void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const { } bool GDScriptInstance::has_method(const StringName &p_method) const { - const GDScript *sptr = script.ptr(); while (sptr) { const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method); - if (E) + if (E) { return true; + } sptr = sptr->_base; } return false; } -Variant GDScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Variant GDScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { GDScript *sptr = script.ptr(); while (sptr) { Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method); @@ -1295,7 +1297,6 @@ Variant GDScriptInstance::call(const StringName &p_method, const Variant **p_arg } void GDScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) { - GDScript *sptr = script.ptr(); Callable::CallError ce; @@ -1309,9 +1310,9 @@ void GDScriptInstance::call_multilevel(const StringName &p_method, const Variant } void GDScriptInstance::_ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount) { - - if (sptr->_base) + if (sptr->_base) { _ml_call_reversed(sptr->_base, p_method, p_args, p_argcount); + } Callable::CallError ce; @@ -1322,14 +1323,12 @@ void GDScriptInstance::_ml_call_reversed(GDScript *sptr, const StringName &p_met } void GDScriptInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) { - if (script.ptr()) { _ml_call_reversed(script.ptr(), p_method, p_args, p_argcount); } } void GDScriptInstance::notification(int p_notification) { - //notification is not virtual, it gets called at ALL levels just like in C. Variant value = p_notification; const Variant *args[1] = { &value }; @@ -1351,30 +1350,31 @@ void GDScriptInstance::notification(int p_notification) { String GDScriptInstance::to_string(bool *r_valid) { if (has_method(CoreStringNames::get_singleton()->_to_string)) { Callable::CallError ce; - Variant ret = call(CoreStringNames::get_singleton()->_to_string, NULL, 0, ce); + Variant ret = call(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce); if (ce.error == Callable::CallError::CALL_OK) { if (ret.get_type() != Variant::STRING) { - if (r_valid) + if (r_valid) { *r_valid = false; + } ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String."); } - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret.operator String(); } } - if (r_valid) + if (r_valid) { *r_valid = false; + } return String(); } Ref<Script> GDScriptInstance::get_script() const { - return script; } ScriptLanguage *GDScriptInstance::get_language() { - return GDScriptLanguage::get_singleton(); } @@ -1419,7 +1419,6 @@ MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_vari } void GDScriptInstance::reload_members() { - #ifdef DEBUG_ENABLED members.resize(script->member_indices.size()); //resize @@ -1429,7 +1428,6 @@ void GDScriptInstance::reload_members() { //pass the values to the new indices for (Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.front(); E; E = E->next()) { - if (member_indices_cache.has(E->key())) { Variant value = members[member_indices_cache[E->key()]]; new_members.write[E->get().index] = value; @@ -1442,7 +1440,6 @@ void GDScriptInstance::reload_members() { //pass the values to the new indices member_indices_cache.clear(); for (Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.front(); E; E = E->next()) { - member_indices_cache[E->key()] = E->get().index; } @@ -1450,31 +1447,34 @@ void GDScriptInstance::reload_members() { } GDScriptInstance::GDScriptInstance() { - owner = NULL; + owner = nullptr; base_ref = false; } GDScriptInstance::~GDScriptInstance() { - if (script.is_valid() && owner) { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->lock); + + while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { + E->self()->_clear_stack(); + pending_func_states.remove(E); + } + if (script.is_valid() && owner) { script->instances.erase(owner); } } /************* SCRIPT LANGUAGE **************/ -GDScriptLanguage *GDScriptLanguage::singleton = NULL; +GDScriptLanguage *GDScriptLanguage::singleton = nullptr; String GDScriptLanguage::get_name() const { - return "GDScript"; } /* LANGUAGE FUNCTIONS */ void GDScriptLanguage::_add_global(const StringName &p_name, const Variant &p_value) { - if (globals.has(p_name)) { //overwrite existing global_array.write[globals[p_name]] = p_value; @@ -1486,7 +1486,6 @@ void GDScriptLanguage::_add_global(const StringName &p_name, const Variant &p_va } void GDScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) { - _add_global(p_variable, p_value); } @@ -1500,11 +1499,9 @@ void GDScriptLanguage::remove_named_global_constant(const StringName &p_name) { } void GDScriptLanguage::init() { - //populate global constants int gcc = GlobalConstants::get_global_constant_count(); for (int i = 0; i < gcc; i++) { - _add_global(StaticCString::create(GlobalConstants::get_global_constant_name(i)), GlobalConstants::get_global_constant_value(i)); } @@ -1518,14 +1515,15 @@ void GDScriptLanguage::init() { List<StringName> class_list; ClassDB::get_class_list(&class_list); for (List<StringName>::Element *E = class_list.front(); E; E = E->next()) { - StringName n = E->get(); String s = String(n); - if (s.begins_with("_")) + if (s.begins_with("_")) { n = s.substr(1, s.length()); + } - if (globals.has(n)) + if (globals.has(n)) { continue; + } Ref<GDScriptNativeClass> nc = memnew(GDScriptNativeClass(E->get())); _add_global(n, nc); } @@ -1535,29 +1533,27 @@ void GDScriptLanguage::init() { List<Engine::Singleton> singletons; Engine::get_singleton()->get_singletons(&singletons); for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) { - _add_global(E->get().name, E->get().ptr); } } String GDScriptLanguage::get_type() const { - return "GDScript"; } -String GDScriptLanguage::get_extension() const { +String GDScriptLanguage::get_extension() const { return "gd"; } -Error GDScriptLanguage::execute_file(const String &p_path) { +Error GDScriptLanguage::execute_file(const String &p_path) { // ?? return OK; } + void GDScriptLanguage::finish() { } void GDScriptLanguage::profiling_start() { - #ifdef DEBUG_ENABLED MutexLock lock(this->lock); @@ -1580,7 +1576,6 @@ void GDScriptLanguage::profiling_start() { } void GDScriptLanguage::profiling_stop() { - #ifdef DEBUG_ENABLED MutexLock lock(this->lock); @@ -1589,7 +1584,6 @@ void GDScriptLanguage::profiling_stop() { } int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) { - int current = 0; #ifdef DEBUG_ENABLED @@ -1597,8 +1591,9 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { - if (current >= p_info_max) + if (current >= p_info_max) { break; + } p_info_arr[current].call_count = elem->self()->profile.call_count; p_info_arr[current].self_time = elem->self()->profile.self_time; p_info_arr[current].total_time = elem->self()->profile.total_time; @@ -1612,7 +1607,6 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, } int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) { - int current = 0; #ifdef DEBUG_ENABLED @@ -1620,8 +1614,9 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_ SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { - if (current >= p_info_max) + if (current >= p_info_max) { break; + } if (elem->self()->profile.last_frame_call_count > 0) { p_info_arr[current].call_count = elem->self()->profile.last_frame_call_count; p_info_arr[current].self_time = elem->self()->profile.last_frame_self_time; @@ -1637,12 +1632,11 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_ } struct GDScriptDepSort { - //must support sorting so inheritance works properly (parent must be reloaded first) bool operator()(const Ref<GDScript> &A, const Ref<GDScript> &B) const { - - if (A == B) + if (A == B) { return false; //shouldn't happen but.. + } const GDScript *I = B->get_base().ptr(); while (I) { if (I == A.ptr()) { @@ -1658,7 +1652,6 @@ struct GDScriptDepSort { }; void GDScriptLanguage::reload_all_scripts() { - #ifdef DEBUG_ENABLED print_verbose("GDScript: Reloading all scripts"); List<Ref<GDScript>> scripts; @@ -1680,7 +1673,6 @@ void GDScriptLanguage::reload_all_scripts() { scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order for (List<Ref<GDScript>>::Element *E = scripts.front(); E; E = E->next()) { - print_verbose("GDScript: Reloading: " + E->get()->get_path()); E->get()->load_source_code(E->get()->get_path()); E->get()->reload(true); @@ -1689,7 +1681,6 @@ void GDScriptLanguage::reload_all_scripts() { } void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { - #ifdef DEBUG_ENABLED List<Ref<GDScript>> scripts; @@ -1699,7 +1690,6 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so SelfList<GDScript> *elem = script_list.first(); while (elem) { if (elem->self()->get_path().is_resource_file()) { - scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident } elem = elem->next(); @@ -1715,16 +1705,15 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order for (List<Ref<GDScript>>::Element *E = scripts.front(); E; E = E->next()) { - bool reload = E->get() == p_script || to_reload.has(E->get()->get_base()); - if (!reload) + if (!reload) { continue; + } to_reload.insert(E->get(), Map<ObjectID, List<Pair<StringName, Variant>>>()); if (!p_soft_reload) { - //save state and remove script from instances Map<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[E->get()]; @@ -1733,7 +1722,6 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so //save instance info List<Pair<StringName, Variant>> state; if (obj->get_script_instance()) { - obj->get_script_instance()->get_property_state(state); map[obj->get_instance_id()] = state; obj->set_script(Variant()); @@ -1748,7 +1736,6 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so //save instance info if (obj->get_script_instance()) { - map.insert(obj->get_instance_id(), List<Pair<StringName, Variant>>()); List<Pair<StringName, Variant>> &state = map[obj->get_instance_id()]; obj->get_script_instance()->get_property_state(state); @@ -1768,18 +1755,17 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so } for (Map<Ref<GDScript>, Map<ObjectID, List<Pair<StringName, Variant>>>>::Element *E = to_reload.front(); E; E = E->next()) { - Ref<GDScript> scr = E->key(); scr->reload(p_soft_reload); //restore state if saved for (Map<ObjectID, List<Pair<StringName, Variant>>>::Element *F = E->get().front(); F; F = F->next()) { - List<Pair<StringName, Variant>> &saved_state = F->get(); Object *obj = ObjectDB::get_instance(F->key()); - if (!obj) + if (!obj) { continue; + } if (!p_soft_reload) { //clear it just in case (may be a pending reload state) @@ -1818,7 +1804,6 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so } void GDScriptLanguage::frame() { - calls = 0; #ifdef DEBUG_ENABLED @@ -1842,7 +1827,6 @@ void GDScriptLanguage::frame() { /* EDITOR FUNCTIONS */ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { - static const char *_reserved_words[] = { // operators "and", @@ -1900,13 +1884,12 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { "remotesync", "mastersync", "puppetsync", - 0 + nullptr }; const char **w = _reserved_words; while (*w) { - p_words->push_back(*w); w++; } @@ -1917,12 +1900,10 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const { } bool GDScriptLanguage::handles_global_class_type(const String &p_type) const { - return p_type == "GDScript"; } String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const { - Vector<uint8_t> sourcef; Error err; FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -1933,19 +1914,18 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b String source = f->get_as_utf8_string(); GDScriptParser parser; - parser.parse(source, p_path.get_base_dir(), true, p_path, false, NULL, true); + parser.parse(source, p_path.get_base_dir(), true, p_path, false, nullptr, true); if (parser.get_parse_tree() && parser.get_parse_tree()->type == GDScriptParser::Node::TYPE_CLASS) { - const GDScriptParser::ClassNode *c = static_cast<const GDScriptParser::ClassNode *>(parser.get_parse_tree()); if (r_icon_path) { - if (c->icon_path.empty() || c->icon_path.is_abs_path()) + if (c->icon_path.empty() || c->icon_path.is_abs_path()) { *r_icon_path = c->icon_path; - else if (c->icon_path.is_rel_path()) + } else if (c->icon_path.is_rel_path()) { *r_icon_path = p_path.get_base_dir().plus_file(c->icon_path).simplify_path(); + } } if (r_base_type) { - const GDScriptParser::ClassNode *subclass = c; String path = p_path; GDScriptParser subparser; @@ -1954,7 +1934,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b if (subclass->extends_file) { if (subclass->extends_class.size() == 0) { get_global_class_name(subclass->extends_file, r_base_type); - subclass = NULL; + subclass = nullptr; break; } else { Vector<StringName> extend_classes = subclass->extends_class; @@ -1973,7 +1953,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b subpath = path.get_base_dir().plus_file(subpath).simplify_path(); } - if (OK != subparser.parse(subsource, subpath.get_base_dir(), true, subpath, false, NULL, true)) { + if (OK != subparser.parse(subsource, subpath.get_base_dir(), true, subpath, false, nullptr, true)) { break; } path = subpath; @@ -1994,20 +1974,20 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b } } if (!found) { - subclass = NULL; + subclass = nullptr; break; } } } } else if (subclass->extends_class.size() == 1) { *r_base_type = subclass->extends_class[0]; - subclass = NULL; + subclass = nullptr; } else { break; } } else { *r_base_type = "Reference"; - subclass = NULL; + subclass = nullptr; } } } @@ -2019,7 +1999,6 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b #ifdef DEBUG_ENABLED String GDScriptWarning::get_message() const { - #define CHECK_SYMBOLS(m_amount) ERR_FAIL_COND_V(symbols.size() < m_amount, String()); switch (code) { @@ -2126,7 +2105,8 @@ String GDScriptWarning::get_message() const { case STANDALONE_TERNARY: { return "Standalone ternary conditional operator: the return value is being discarded."; } - case WARNING_MAX: break; // Can't happen, but silences warning + case WARNING_MAX: + break; // Can't happen, but silences warning } ERR_FAIL_V_MSG(String(), "Invalid GDScript warning code: " + get_name_from_code(code) + "."); @@ -2168,7 +2148,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "UNSAFE_CALL_ARGUMENT", "DEPRECATED_KEYWORD", "STANDALONE_TERNARY", - NULL + nullptr }; return names[(int)p_code]; @@ -2187,7 +2167,6 @@ GDScriptWarning::Code GDScriptWarning::get_code_from_name(const String &p_name) #endif // DEBUG_ENABLED GDScriptLanguage::GDScriptLanguage() { - calls = 0; ERR_FAIL_COND(singleton); singleton = this; @@ -2215,7 +2194,7 @@ GDScriptLanguage::GDScriptLanguage() { } else { _debug_max_call_stack = 0; - _call_stack = NULL; + _call_stack = nullptr; } #ifdef DEBUG_ENABLED @@ -2232,11 +2211,10 @@ GDScriptLanguage::GDScriptLanguage() { } GDScriptLanguage::~GDScriptLanguage() { - if (_call_stack) { memdelete_arr(_call_stack); } - singleton = NULL; + singleton = nullptr; } void GDScriptLanguage::add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass) { @@ -2245,29 +2223,30 @@ void GDScriptLanguage::add_orphan_subclass(const String &p_qualified_name, const Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_name) { Map<String, ObjectID>::Element *orphan_subclass_element = orphan_subclasses.find(p_qualified_name); - if (!orphan_subclass_element) + if (!orphan_subclass_element) { return Ref<GDScript>(); + } ObjectID orphan_subclass = orphan_subclass_element->get(); Object *obj = ObjectDB::get_instance(orphan_subclass); orphan_subclasses.erase(orphan_subclass_element); - if (!obj) + if (!obj) { return Ref<GDScript>(); + } return Ref<GDScript>(Object::cast_to<GDScript>(obj)); } /*************** RESOURCE ***************/ -RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - - if (r_error) +RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_FILE_CANT_OPEN; + } GDScript *script = memnew(GDScript); Ref<GDScript> scriptres(script); if (p_path.ends_with(".gde") || p_path.ends_with(".gdc")) { - script->set_script_path(p_original_path); // script needs this. script->set_path(p_original_path); Error err = script->load_byte_code(p_path); @@ -2282,34 +2261,32 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori script->reload(); } - if (r_error) + if (r_error) { *r_error = OK; + } return scriptres; } void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("gd"); p_extensions->push_back("gdc"); p_extensions->push_back("gde"); } bool ResourceFormatLoaderGDScript::handles_type(const String &p_type) const { - return (p_type == "Script" || p_type == "GDScript"); } String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "gd" || el == "gdc" || el == "gde") + if (el == "gd" || el == "gdc" || el == "gde") { return "GDScript"; + } return ""; } void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { - FileAccessRef file = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_MSG(!file, "Cannot open file '" + p_path + "'."); @@ -2319,7 +2296,7 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S } GDScriptParser parser; - if (OK != parser.parse(source, p_path.get_base_dir(), true, p_path, false, NULL, true)) { + if (OK != parser.parse(source, p_path.get_base_dir(), true, p_path, false, nullptr, true)) { return; } @@ -2329,7 +2306,6 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S } Error ResourceFormatSaverGDScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref<GDScript> sqscr = p_resource; ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); @@ -2356,12 +2332,11 @@ Error ResourceFormatSaverGDScript::save(const String &p_path, const RES &p_resou } void ResourceFormatSaverGDScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (Object::cast_to<GDScript>(*p_resource)) { p_extensions->push_back("gd"); } } -bool ResourceFormatSaverGDScript::recognize(const RES &p_resource) const { - return Object::cast_to<GDScript>(*p_resource) != NULL; +bool ResourceFormatSaverGDScript::recognize(const RES &p_resource) const { + return Object::cast_to<GDScript>(*p_resource) != nullptr; } diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 3fedc604bf..e770dc3abd 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -39,7 +39,6 @@ #include "gdscript_function.h" class GDScriptNativeClass : public Reference { - GDCLASS(GDScriptNativeClass, Reference); StringName name; @@ -56,7 +55,6 @@ public: }; class GDScript : public Script { - GDCLASS(GDScript, Script); bool tool; bool valid; @@ -117,6 +115,8 @@ class GDScript : public Script { String fully_qualified_name; SelfList<GDScript> script_list; + SelfList<GDScriptFunctionState>::List pending_func_states; + GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error); void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path); @@ -133,7 +133,7 @@ class GDScript : public Script { #endif - bool _update_exports(); + bool _update_exports(bool *r_err = nullptr, bool p_recursive_call = false); void _save_orphaned_subclasses(); void _init_rpc_methods_properties(); @@ -151,6 +151,8 @@ protected: public: virtual bool is_valid() const { return valid; } + bool inherits_script(const Ref<Script> &p_script) const; + const Map<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; } const Map<StringName, Variant> &get_constants() const { return constants; } const Set<StringName> &get_members() const { return members; } @@ -207,11 +209,11 @@ public: virtual int get_member_line(const StringName &p_member) const { #ifdef TOOLS_ENABLED - if (member_lines.has(p_member)) + if (member_lines.has(p_member)) { return member_lines[p_member]; - else + } #endif - return -1; + return -1; } virtual void get_constants(Map<StringName, Variant> *p_constants); @@ -252,6 +254,8 @@ class GDScriptInstance : public ScriptInstance { Vector<Variant> members; bool base_ref; + SelfList<GDScriptFunctionState>::List pending_func_states; + void _ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount); public: @@ -260,7 +264,7 @@ public: virtual bool set(const StringName &p_name, const Variant &p_value); virtual bool get(const StringName &p_name, Variant &r_ret) const; virtual void get_property_list(List<PropertyInfo> *p_properties) const; - virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const; + virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const; virtual void get_method_list(List<MethodInfo> *p_list) const; virtual bool has_method(const StringName &p_method) const; @@ -328,22 +332,23 @@ struct GDScriptWarning { DEPRECATED_KEYWORD, // The keyword is deprecated and should be replaced STANDALONE_TERNARY, // Return value of ternary expression is discarded WARNING_MAX, - } code; + }; + + Code code = WARNING_MAX; Vector<String> symbols; - int line; + int line = -1; String get_name() const; String get_message() const; static String get_name_from_code(Code p_code); static Code get_code_from_name(const String &p_name); - GDScriptWarning() : - code(WARNING_MAX), - line(-1) {} + GDScriptWarning() {} }; #endif // DEBUG_ENABLED class GDScriptLanguage : public ScriptLanguage { + friend class GDScriptFunctionState; static GDScriptLanguage *singleton; @@ -353,7 +358,6 @@ class GDScriptLanguage : public ScriptLanguage { Map<StringName, Variant> named_globals; struct CallLevel { - Variant *stack; GDScriptFunction *function; GDScriptInstance *instance; @@ -392,12 +396,13 @@ public: bool debug_break_parse(const String &p_file, int p_line, const String &p_error); _FORCE_INLINE_ void enter_function(GDScriptInstance *p_instance, GDScriptFunction *p_function, Variant *p_stack, int *p_ip, int *p_line) { - - if (Thread::get_main_id() != Thread::get_caller_id()) + if (Thread::get_main_id() != Thread::get_caller_id()) { return; //no support for other threads than main for now + } - if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) + if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) { EngineDebugger::get_script_debugger()->set_depth(EngineDebugger::get_script_debugger()->get_depth() + 1); + } if (_debug_call_stack_pos >= _debug_max_call_stack) { //stack overflow @@ -415,15 +420,15 @@ public: } _FORCE_INLINE_ void exit_function() { - - if (Thread::get_main_id() != Thread::get_caller_id()) + if (Thread::get_main_id() != Thread::get_caller_id()) { return; //no support for other threads than main for now + } - if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) + if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) { EngineDebugger::get_script_debugger()->set_depth(EngineDebugger::get_script_debugger()->get_depth() - 1); + } if (_debug_call_stack_pos == 0) { - _debug_error = "Stack Underflow (Engine Bug)"; EngineDebugger::get_script_debugger()->debug(this); return; @@ -433,8 +438,9 @@ public: } virtual Vector<StackInfo> debug_get_current_stack_info() { - if (Thread::get_main_id() != Thread::get_caller_id()) + if (Thread::get_main_id() != Thread::get_caller_id()) { return Vector<StackInfo>(); + } Vector<StackInfo> csi; csi.resize(_debug_call_stack_pos); @@ -449,7 +455,6 @@ public: } struct { - StringName _init; StringName _notification; StringName _set; @@ -483,7 +488,7 @@ public: virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; virtual bool is_using_templates(); virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script); - virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL, List<ScriptLanguage::Warning> *r_warnings = NULL, Set<int> *r_safe_lines = NULL) const; + virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const; virtual Script *create_script() const; virtual bool has_named_classes() const; virtual bool supports_builtin_mode() const; @@ -534,7 +539,7 @@ public: /* GLOBAL CLASSES */ virtual bool handles_global_class_type(const String &p_type) const; - virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL, String *r_icon_path = NULL) const; + virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr) const; void add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass); Ref<GDScript> get_orphan_subclass(const String &p_qualified_name); @@ -545,7 +550,7 @@ public: class ResourceFormatLoaderGDScript : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index fb514aab0c..bc095ae1f9 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -33,24 +33,24 @@ #include "gdscript.h" bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) { - - if (codegen.function_node && codegen.function_node->_static) + if (codegen.function_node && codegen.function_node->_static) { return false; + } - if (codegen.stack_identifiers.has(p_name)) + if (codegen.stack_identifiers.has(p_name)) { return false; //shadowed + } return _is_class_member_property(codegen.script, p_name); } bool GDScriptCompiler::_is_class_member_property(GDScript *owner, const StringName &p_name) { - GDScript *scr = owner; - GDScriptNativeClass *nc = NULL; + GDScriptNativeClass *nc = nullptr; while (scr) { - - if (scr->native.is_valid()) + if (scr->native.is_valid()) { nc = scr->native.ptr(); + } scr = scr->_base; } @@ -60,9 +60,9 @@ bool GDScriptCompiler::_is_class_member_property(GDScript *owner, const StringNa } void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::Node *p_node) { - - if (error != "") + if (error != "") { return; + } error = p_error; if (p_node) { @@ -75,12 +75,12 @@ void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::N } bool GDScriptCompiler::_create_unary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level) { - ERR_FAIL_COND_V(on->arguments.size() != 1, false); int src_address_a = _parse_expression(codegen, on->arguments[0], p_stack_level); - if (src_address_a < 0) + if (src_address_a < 0) { return false; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_OPERATOR); // perform operator codegen.opcodes.push_back(op); //which operator @@ -91,18 +91,20 @@ bool GDScriptCompiler::_create_unary_operator(CodeGen &codegen, const GDScriptPa } bool GDScriptCompiler::_create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer, int p_index_addr) { - ERR_FAIL_COND_V(on->arguments.size() != 2, false); int src_address_a = _parse_expression(codegen, on->arguments[0], p_stack_level, false, p_initializer, p_index_addr); - if (src_address_a < 0) + if (src_address_a < 0) { return false; - if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) + } + if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { p_stack_level++; //uses stack for return, increase stack + } int src_address_b = _parse_expression(codegen, on->arguments[1], p_stack_level, false, p_initializer); - if (src_address_b < 0) + if (src_address_b < 0) { return false; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_OPERATOR); // perform operator codegen.opcodes.push_back(op); //which operator @@ -172,28 +174,44 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D } int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level, int p_index_addr) { - Variant::Operator var_op = Variant::OP_MAX; switch (p_expression->op) { - - case GDScriptParser::OperatorNode::OP_ASSIGN_ADD: var_op = Variant::OP_ADD; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBTRACT; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_MUL: var_op = Variant::OP_MULTIPLY; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_DIV: var_op = Variant::OP_DIVIDE; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_MOD: var_op = Variant::OP_MODULE; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: var_op = Variant::OP_SHIFT_LEFT; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: var_op = Variant::OP_SHIFT_RIGHT; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_AND: var_op = Variant::OP_BIT_AND; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_OR: var_op = Variant::OP_BIT_OR; break; - case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_XOR: var_op = Variant::OP_BIT_XOR; break; + case GDScriptParser::OperatorNode::OP_ASSIGN_ADD: + var_op = Variant::OP_ADD; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_SUB: + var_op = Variant::OP_SUBTRACT; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_MUL: + var_op = Variant::OP_MULTIPLY; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_DIV: + var_op = Variant::OP_DIVIDE; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_MOD: + var_op = Variant::OP_MODULE; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: + var_op = Variant::OP_SHIFT_LEFT; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: + var_op = Variant::OP_SHIFT_RIGHT; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_AND: + var_op = Variant::OP_BIT_AND; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_OR: + var_op = Variant::OP_BIT_OR; + break; + case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_XOR: + var_op = Variant::OP_BIT_XOR; + break; case GDScriptParser::OperatorNode::OP_INIT_ASSIGN: case GDScriptParser::OperatorNode::OP_ASSIGN: { - //none } break; default: { - ERR_FAIL_V(-1); } } @@ -201,12 +219,12 @@ int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDS bool initializer = p_expression->op == GDScriptParser::OperatorNode::OP_INIT_ASSIGN; if (var_op == Variant::OP_MAX) { - return _parse_expression(codegen, p_expression->arguments[1], p_stack_level, false, initializer); } - if (!_create_binary_operator(codegen, p_expression, var_op, p_stack_level, initializer, p_index_addr)) + if (!_create_binary_operator(codegen, p_expression, var_op, p_stack_level, initializer, p_index_addr)) { return -1; + } int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode @@ -215,7 +233,6 @@ int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDS } int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root, bool p_initializer, int p_index_addr) { - switch (p_expression->type) { //should parse variable declaration and adjust stack accordingly... case GDScriptParser::Node::TYPE_IDENTIFIER: { @@ -231,7 +248,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: // TRY STACK! if (!p_initializer && codegen.stack_identifiers.has(identifier)) { - int pos = codegen.stack_identifiers[identifier]; return pos | (GDScriptFunction::ADDR_TYPE_STACK_VARIABLE << GDScriptFunction::ADDR_BITS); } @@ -249,11 +265,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: //TRY MEMBERS! if (!codegen.function_node || !codegen.function_node->_static) { - // TRY MEMBER VARIABLES! //static function if (codegen.script->member_indices.has(identifier)) { - int idx = codegen.script->member_indices[identifier].index; return idx | (GDScriptFunction::ADDR_TYPE_MEMBER << GDScriptFunction::ADDR_BITS); //argument (stack root) } @@ -263,26 +277,23 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: GDScript *owner = codegen.script; while (owner) { - GDScript *scr = owner; - GDScriptNativeClass *nc = NULL; + GDScriptNativeClass *nc = nullptr; while (scr) { - if (scr->constants.has(identifier)) { - //int idx=scr->constants[identifier]; int idx = codegen.get_name_map_pos(identifier); return idx | (GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS); //argument (stack root) } - if (scr->native.is_valid()) + if (scr->native.is_valid()) { nc = scr->native.ptr(); + } scr = scr->_base; } // CLASS C++ Integer Constant if (nc) { - bool success = false; int constant = ClassDB::get_integer_constant(nc->get_name(), identifier, &success); if (success) { @@ -290,7 +301,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int idx; if (!codegen.constant_map.has(key)) { - idx = codegen.constant_map.size(); codegen.constant_map[key] = idx; @@ -306,7 +316,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) { - int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier]; return idx | (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root) } @@ -314,7 +323,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: /* TRY GLOBAL CLASSES */ if (ScriptServer::is_global_class(identifier)) { - const GDScriptParser::ClassNode *class_node = codegen.class_node; while (class_node->owner) { class_node = class_node->owner; @@ -335,7 +343,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int idx; if (!codegen.constant_map.has(key)) { - idx = codegen.constant_map.size(); codegen.constant_map[key] = idx; @@ -348,7 +355,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: #ifdef TOOLS_ENABLED if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) { - int idx = codegen.named_globals.find(identifier); if (idx == -1) { idx = codegen.named_globals.size(); @@ -372,7 +378,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int idx; if (!codegen.constant_map.has(cn->value)) { - idx = codegen.constant_map.size(); codegen.constant_map[cn->value] = idx; @@ -392,17 +397,16 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: return (GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS); } break; case GDScriptParser::Node::TYPE_ARRAY: { - const GDScriptParser::ArrayNode *an = static_cast<const GDScriptParser::ArrayNode *>(p_expression); Vector<int> values; int slevel = p_stack_level; for (int i = 0; i < an->elements.size(); i++) { - int ret = _parse_expression(codegen, an->elements[i], slevel); - if (ret < 0) + if (ret < 0) { return ret; + } if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); @@ -413,8 +417,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY); codegen.opcodes.push_back(values.size()); - for (int i = 0; i < values.size(); i++) + for (int i = 0; i < values.size(); i++) { codegen.opcodes.push_back(values[i]); + } int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode @@ -423,17 +428,16 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } break; case GDScriptParser::Node::TYPE_DICTIONARY: { - const GDScriptParser::DictionaryNode *dn = static_cast<const GDScriptParser::DictionaryNode *>(p_expression); Vector<int> values; int slevel = p_stack_level; for (int i = 0; i < dn->elements.size(); i++) { - int ret = _parse_expression(codegen, dn->elements[i].key, slevel); - if (ret < 0) + if (ret < 0) { return ret; + } if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); @@ -442,8 +446,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: values.push_back(ret); ret = _parse_expression(codegen, dn->elements[i].value, slevel); - if (ret < 0) + if (ret < 0) { return ret; + } if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); @@ -454,8 +459,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY); codegen.opcodes.push_back(dn->elements.size()); - for (int i = 0; i < values.size(); i++) + for (int i = 0; i < values.size(); i++) { codegen.opcodes.push_back(values[i]); + } int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode @@ -468,8 +474,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int slevel = p_stack_level; int src_addr = _parse_expression(codegen, cn->source_node, slevel); - if (src_addr < 0) + if (src_addr < 0) { return src_addr; + } if (src_addr & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { slevel++; codegen.alloc_stack(slevel); @@ -485,7 +492,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: case GDScriptDataType::NATIVE: { int class_idx; if (GDScriptLanguage::get_singleton()->get_global_map().has(cast_type.native_type)) { - class_idx = GDScriptLanguage::get_singleton()->get_global_map()[cast_type.native_type]; class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root) } else { @@ -497,7 +503,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } break; case GDScriptDataType::SCRIPT: case GDScriptDataType::GDSCRIPT: { - Variant script = cast_type.script_type; int idx = codegen.get_constant_pos(script); idx |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS; //make it a local constant (faster access) @@ -523,10 +528,8 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: const GDScriptParser::OperatorNode *on = static_cast<const GDScriptParser::OperatorNode *>(p_expression); switch (on->op) { - //call/constructor operator case GDScriptParser::OperatorNode::OP_PARENT_CALL: { - ERR_FAIL_COND_V(on->arguments.size() < 1, -1); const GDScriptParser::IdentifierNode *in = (const GDScriptParser::IdentifierNode *)on->arguments[0]; @@ -534,10 +537,10 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: Vector<int> arguments; int slevel = p_stack_level; for (int i = 1; i < on->arguments.size(); i++) { - int ret = _parse_expression(codegen, on->arguments[i], slevel); - if (ret < 0) + if (ret < 0) { return ret; + } if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); @@ -551,12 +554,12 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(codegen.get_name_map_pos(in->name)); //instance codegen.opcodes.push_back(arguments.size()); //argument count codegen.alloc_call(arguments.size()); - for (int i = 0; i < arguments.size(); i++) + for (int i = 0; i < arguments.size(); i++) { codegen.opcodes.push_back(arguments[i]); //arguments + } } break; case GDScriptParser::OperatorNode::OP_CALL: { - if (on->arguments[0]->type == GDScriptParser::Node::TYPE_TYPE) { //construct a basic type ERR_FAIL_COND_V(on->arguments.size() < 1, -1); @@ -567,10 +570,10 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: Vector<int> arguments; int slevel = p_stack_level; for (int i = 1; i < on->arguments.size(); i++) { - int ret = _parse_expression(codegen, on->arguments[i], slevel); - if (ret < 0) + if (ret < 0) { return ret; + } if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); @@ -583,8 +586,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(vtype); //instance codegen.opcodes.push_back(arguments.size()); //argument count codegen.alloc_call(arguments.size()); - for (int i = 0; i < arguments.size(); i++) + for (int i = 0; i < arguments.size(); i++) { codegen.opcodes.push_back(arguments[i]); //arguments + } } else if (on->arguments[0]->type == GDScriptParser::Node::TYPE_BUILT_IN_FUNCTION) { //built in function @@ -594,10 +598,10 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: Vector<int> arguments; int slevel = p_stack_level; for (int i = 1; i < on->arguments.size(); i++) { - int ret = _parse_expression(codegen, on->arguments[i], slevel); - if (ret < 0) + if (ret < 0) { return ret; + } if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; @@ -611,8 +615,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(static_cast<const GDScriptParser::BuiltInFunctionNode *>(on->arguments[0])->function); codegen.opcodes.push_back(on->arguments.size() - 1); codegen.alloc_call(on->arguments.size() - 1); - for (int i = 0; i < arguments.size(); i++) + for (int i = 0; i < arguments.size(); i++) { codegen.opcodes.push_back(arguments[i]); + } } else { //regular function @@ -628,14 +633,12 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int slevel = p_stack_level; for (int i = 0; i < on->arguments.size(); i++) { - int ret; if (i == 0 && on->arguments[i]->type == GDScriptParser::Node::TYPE_SELF && codegen.function_node && codegen.function_node->_static) { //static call to self ret = (GDScriptFunction::ADDR_TYPE_CLASS << GDScriptFunction::ADDR_BITS); } else if (i == 1) { - if (on->arguments[i]->type != GDScriptParser::Node::TYPE_IDENTIFIER) { _set_error("Attempt to call a non-identifier.", on); return -1; @@ -644,10 +647,10 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: ret = codegen.get_name_map_pos(id->name); } else { - ret = _parse_expression(codegen, on->arguments[i], slevel); - if (ret < 0) + if (ret < 0) { return ret; + } if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); @@ -659,21 +662,21 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(p_root ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN); // perform operator codegen.opcodes.push_back(on->arguments.size() - 2); codegen.alloc_call(on->arguments.size() - 2); - for (int i = 0; i < arguments.size(); i++) + for (int i = 0; i < arguments.size(); i++) { codegen.opcodes.push_back(arguments[i]); + } } } break; case GDScriptParser::OperatorNode::OP_YIELD: { - ERR_FAIL_COND_V(on->arguments.size() && on->arguments.size() != 2, -1); Vector<int> arguments; int slevel = p_stack_level; for (int i = 0; i < on->arguments.size(); i++) { - int ret = _parse_expression(codegen, on->arguments[i], slevel); - if (ret < 0) + if (ret < 0) { return ret; + } if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) { slevel++; codegen.alloc_stack(slevel); @@ -683,8 +686,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: //push call bytecode codegen.opcodes.push_back(arguments.size() == 0 ? GDScriptFunction::OPCODE_YIELD : GDScriptFunction::OPCODE_YIELD_SIGNAL); // basic type constructor - for (int i = 0; i < arguments.size(); i++) + for (int i = 0; i < arguments.size(); i++) { codegen.opcodes.push_back(arguments[i]); //arguments + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_YIELD_RESUME); //next will be where to place the result :) @@ -693,22 +697,21 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: //indexing operator case GDScriptParser::OperatorNode::OP_INDEX: case GDScriptParser::OperatorNode::OP_INDEX_NAMED: { - ERR_FAIL_COND_V(on->arguments.size() != 2, -1); int slevel = p_stack_level; bool named = (on->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED); int from = _parse_expression(codegen, on->arguments[0], slevel); - if (from < 0) + if (from < 0) { return from; + } int index; if (p_index_addr != 0) { index = p_index_addr; } else if (named) { if (on->arguments[0]->type == GDScriptParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) { - GDScriptParser::IdentifierNode *identifier = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1]); const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(identifier->name); @@ -729,7 +732,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: index = codegen.get_name_map_pos(static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1])->name); } else { - if (on->arguments[1]->type == GDScriptParser::Node::TYPE_CONSTANT && static_cast<const GDScriptParser::ConstantNode *>(on->arguments[1])->value.get_type() == Variant::STRING) { //also, somehow, named (speed up anyway) StringName name = static_cast<const GDScriptParser::ConstantNode *>(on->arguments[1])->value; @@ -744,8 +746,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } index = _parse_expression(codegen, on->arguments[1], slevel); - if (index < 0) + if (index < 0) { return index; + } } } @@ -755,20 +758,21 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } break; case GDScriptParser::OperatorNode::OP_AND: { - // AND operator with early out on failure int res = _parse_expression(codegen, on->arguments[0], p_stack_level); - if (res < 0) + if (res < 0) { return res; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT); codegen.opcodes.push_back(res); int jump_fail_pos = codegen.opcodes.size(); codegen.opcodes.push_back(0); res = _parse_expression(codegen, on->arguments[1], p_stack_level); - if (res < 0) + if (res < 0) { return res; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT); codegen.opcodes.push_back(res); @@ -788,20 +792,21 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } break; case GDScriptParser::OperatorNode::OP_OR: { - // OR operator with early out on success int res = _parse_expression(codegen, on->arguments[0], p_stack_level); - if (res < 0) + if (res < 0) { return res; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF); codegen.opcodes.push_back(res); int jump_success_pos = codegen.opcodes.size(); codegen.opcodes.push_back(0); res = _parse_expression(codegen, on->arguments[1], p_stack_level); - if (res < 0) + if (res < 0) { return res; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF); codegen.opcodes.push_back(res); @@ -822,20 +827,21 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } break; // ternary operators case GDScriptParser::OperatorNode::OP_TERNARY_IF: { - // x IF a ELSE y operator with early out on failure int res = _parse_expression(codegen, on->arguments[0], p_stack_level); - if (res < 0) + if (res < 0) { return res; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT); codegen.opcodes.push_back(res); int jump_fail_pos = codegen.opcodes.size(); codegen.opcodes.push_back(0); res = _parse_expression(codegen, on->arguments[1], p_stack_level); - if (res < 0) + if (res < 0) { return res; + } codegen.alloc_stack(p_stack_level); //it will be used.. codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN); @@ -847,8 +853,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.write[jump_fail_pos] = codegen.opcodes.size(); res = _parse_expression(codegen, on->arguments[2], p_stack_level); - if (res < 0) + if (res < 0) { return res; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN); codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); @@ -861,71 +868,113 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } break; //unary operators case GDScriptParser::OperatorNode::OP_NEG: { - if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) return -1; + if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_POS: { - if (!_create_unary_operator(codegen, on, Variant::OP_POSITIVE, p_stack_level)) return -1; + if (!_create_unary_operator(codegen, on, Variant::OP_POSITIVE, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_NOT: { - if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) return -1; + if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_BIT_INVERT: { - if (!_create_unary_operator(codegen, on, Variant::OP_BIT_NEGATE, p_stack_level)) return -1; + if (!_create_unary_operator(codegen, on, Variant::OP_BIT_NEGATE, p_stack_level)) { + return -1; + } } break; //binary operators (in precedence order) case GDScriptParser::OperatorNode::OP_IN: { - if (!_create_binary_operator(codegen, on, Variant::OP_IN, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_IN, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_EQUAL: { - if (!_create_binary_operator(codegen, on, Variant::OP_EQUAL, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_EQUAL, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_NOT_EQUAL: { - if (!_create_binary_operator(codegen, on, Variant::OP_NOT_EQUAL, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_NOT_EQUAL, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_LESS: { - if (!_create_binary_operator(codegen, on, Variant::OP_LESS, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_LESS, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_LESS_EQUAL: { - if (!_create_binary_operator(codegen, on, Variant::OP_LESS_EQUAL, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_LESS_EQUAL, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_GREATER: { - if (!_create_binary_operator(codegen, on, Variant::OP_GREATER, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_GREATER, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_GREATER_EQUAL: { - if (!_create_binary_operator(codegen, on, Variant::OP_GREATER_EQUAL, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_GREATER_EQUAL, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_ADD: { - if (!_create_binary_operator(codegen, on, Variant::OP_ADD, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_ADD, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_SUB: { - if (!_create_binary_operator(codegen, on, Variant::OP_SUBTRACT, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_SUBTRACT, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_MUL: { - if (!_create_binary_operator(codegen, on, Variant::OP_MULTIPLY, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_MULTIPLY, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_DIV: { - if (!_create_binary_operator(codegen, on, Variant::OP_DIVIDE, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_DIVIDE, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_MOD: { - if (!_create_binary_operator(codegen, on, Variant::OP_MODULE, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_MODULE, p_stack_level)) { + return -1; + } } break; //case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_LEFT,p_stack_level)) return -1;} break; //case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_RIGHT,p_stack_level)) return -1;} break; case GDScriptParser::OperatorNode::OP_BIT_AND: { - if (!_create_binary_operator(codegen, on, Variant::OP_BIT_AND, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_BIT_AND, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_BIT_OR: { - if (!_create_binary_operator(codegen, on, Variant::OP_BIT_OR, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_BIT_OR, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_BIT_XOR: { - if (!_create_binary_operator(codegen, on, Variant::OP_BIT_XOR, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_BIT_XOR, p_stack_level)) { + return -1; + } } break; //shift case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: { - if (!_create_binary_operator(codegen, on, Variant::OP_SHIFT_LEFT, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_SHIFT_LEFT, p_stack_level)) { + return -1; + } } break; case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: { - if (!_create_binary_operator(codegen, on, Variant::OP_SHIFT_RIGHT, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_SHIFT_RIGHT, p_stack_level)) { + return -1; + } } break; //assignment operators case GDScriptParser::OperatorNode::OP_ASSIGN_ADD: @@ -940,18 +989,15 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_XOR: case GDScriptParser::OperatorNode::OP_INIT_ASSIGN: case GDScriptParser::OperatorNode::OP_ASSIGN: { - ERR_FAIL_COND_V(on->arguments.size() != 2, -1); if (on->arguments[0]->type == GDScriptParser::Node::TYPE_OPERATOR && (static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX || static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED)) { - // SET (chained) MODE! #ifdef DEBUG_ENABLED if (static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED) { const GDScriptParser::OperatorNode *inon = static_cast<GDScriptParser::OperatorNode *>(on->arguments[0]); if (inon->arguments[0]->type == GDScriptParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) { - const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(static_cast<GDScriptParser::IdentifierNode *>(inon->arguments[1])->name); if (MI && MI->get().setter == codegen.function_node->name) { String n = static_cast<GDScriptParser::IdentifierNode *>(inon->arguments[1])->name; @@ -976,13 +1022,10 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: //create get/set chain GDScriptParser::OperatorNode *n = op; while (true) { - chain.push_back(n); if (n->arguments[0]->type != GDScriptParser::Node::TYPE_OPERATOR) { - //check for a built-in property if (n->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER) { - GDScriptParser::IdentifierNode *identifier = static_cast<GDScriptParser::IdentifierNode *>(n->arguments[0]); if (_is_class_member_property(codegen, identifier->name)) { assign_property = identifier->name; @@ -991,8 +1034,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: break; } n = static_cast<GDScriptParser::OperatorNode *>(n->arguments[0]); - if (n->op != GDScriptParser::OperatorNode::OP_INDEX && n->op != GDScriptParser::OperatorNode::OP_INDEX_NAMED) + if (n->op != GDScriptParser::OperatorNode::OP_INDEX && n->op != GDScriptParser::OperatorNode::OP_INDEX_NAMED) { break; + } } } @@ -1000,8 +1044,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: //get at (potential) root stack pos, so it can be returned int prev_pos = _parse_expression(codegen, chain.back()->get()->arguments[0], slevel); - if (prev_pos < 0) + if (prev_pos < 0) { return prev_pos; + } int retval = prev_pos; if (retval & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { @@ -1012,7 +1057,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: Vector<int> setchain; if (assign_property != StringName()) { - // recover and assign at the end, this allows stuff like // position.x+=2.0 // in Node2D @@ -1022,20 +1066,18 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } for (List<GDScriptParser::OperatorNode *>::Element *E = chain.back(); E; E = E->prev()) { - - if (E == chain.front()) //ignore first + if (E == chain.front()) { //ignore first break; + } bool named = E->get()->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED; int key_idx; if (named) { - key_idx = codegen.get_name_map_pos(static_cast<const GDScriptParser::IdentifierNode *>(E->get()->arguments[1])->name); //printf("named key %x\n",key_idx); } else { - if (prev_pos & (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)) { slevel++; codegen.alloc_stack(slevel); @@ -1048,8 +1090,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: //stack was raised here if retval was stack but.. } - if (key_idx < 0) //error + if (key_idx < 0) { //error return key_idx; + } codegen.opcodes.push_back(named ? GDScriptFunction::OPCODE_GET_NAMED : GDScriptFunction::OPCODE_GET); codegen.opcodes.push_back(prev_pos); @@ -1076,17 +1119,16 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: bool named = false; if (op->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED) { - set_index = codegen.get_name_map_pos(static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[1])->name); named = true; } else { - set_index = _parse_expression(codegen, op->arguments[1], slevel + 1); named = false; } - if (set_index < 0) //error + if (set_index < 0) { //error return set_index; + } if (set_index & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { slevel++; @@ -1094,8 +1136,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } int set_value = _parse_assign_right_expression(codegen, on, slevel + 1, named ? 0 : set_index); - if (set_value < 0) //error + if (set_value < 0) { //error return set_value; + } codegen.opcodes.push_back(named ? GDScriptFunction::OPCODE_SET_NAMED : GDScriptFunction::OPCODE_SET); codegen.opcodes.push_back(prev_pos); @@ -1103,7 +1146,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(set_value); for (int i = 0; i < setchain.size(); i++) { - codegen.opcodes.push_back(setchain[i]); } @@ -1115,8 +1157,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int slevel = p_stack_level; int src_address = _parse_assign_right_expression(codegen, on, slevel); - if (src_address < 0) + if (src_address < 0) { return -1; + } StringName name = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[0])->name; @@ -1126,14 +1169,14 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: return GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS; } else { - //REGULAR ASSIGNMENT MODE!! int slevel = p_stack_level; int dst_address_a = _parse_expression(codegen, on->arguments[0], slevel, false, on->op == GDScriptParser::OperatorNode::OP_INIT_ASSIGN); - if (dst_address_a < 0) + if (dst_address_a < 0) { return -1; + } if (dst_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { slevel++; @@ -1141,8 +1184,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } int src_address_b = _parse_assign_right_expression(codegen, on, slevel); - if (src_address_b < 0) + if (src_address_b < 0) { return -1; + } GDScriptDataType assign_type = _gdtype_from_datatype(on->arguments[0]->get_datatype()); @@ -1158,7 +1202,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: case GDScriptDataType::NATIVE: { int class_idx; if (GDScriptLanguage::get_singleton()->get_global_map().has(assign_type.native_type)) { - class_idx = GDScriptLanguage::get_singleton()->get_global_map()[assign_type.native_type]; class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root) } else { @@ -1172,7 +1215,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } break; case GDScriptDataType::SCRIPT: case GDScriptDataType::GDSCRIPT: { - Variant script = assign_type.script_type; int idx = codegen.get_constant_pos(script); idx |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS; //make it a local constant (faster access) @@ -1201,21 +1243,23 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } } break; case GDScriptParser::OperatorNode::OP_IS: { - ERR_FAIL_COND_V(on->arguments.size() != 2, false); int slevel = p_stack_level; int src_address_a = _parse_expression(codegen, on->arguments[0], slevel); - if (src_address_a < 0) + if (src_address_a < 0) { return -1; + } - if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) + if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { slevel++; //uses stack for return, increase stack + } int src_address_b = _parse_expression(codegen, on->arguments[1], slevel); - if (src_address_b < 0) + if (src_address_b < 0) { return -1; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_EXTENDS_TEST); // perform operator codegen.opcodes.push_back(src_address_a); // argument 1 @@ -1229,11 +1273,13 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: int slevel = p_stack_level; int src_address_a = _parse_expression(codegen, on->arguments[0], slevel); - if (src_address_a < 0) + if (src_address_a < 0) { return -1; + } - if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) + if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) { slevel++; //uses stack for return, increase stack + } const GDScriptParser::TypeNode *tn = static_cast<const GDScriptParser::TypeNode *>(on->arguments[1]); @@ -1242,7 +1288,6 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back((int)tn->vtype); // argument 2 (unary only takes one parameter) } break; default: { - ERR_FAIL_V_MSG(0, "Bug in bytecode compiler, unexpected operator #" + itos(on->op) + " in parse tree while parsing expression."); //unreachable code } break; @@ -1255,20 +1300,17 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } break; //TYPE_TYPE, default: { - ERR_FAIL_V_MSG(-1, "Bug in bytecode compiler, unexpected node in parse tree while parsing expression."); //unreachable code } break; } } Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level, int p_break_addr, int p_continue_addr) { - codegen.push_stack_identifiers(); int new_identifiers = 0; codegen.current_line = p_block->line; for (int i = 0; i < p_block->statements.size(); i++) { - const GDScriptParser::Node *s = p_block->statements[i]; switch (s->type) { @@ -1286,7 +1328,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo const GDScriptParser::ControlFlowNode *cf = static_cast<const GDScriptParser::ControlFlowNode *>(s); switch (cf->cf_type) { - case GDScriptParser::ControlFlowNode::CF_MATCH: { GDScriptParser::MatchNode *match = cf->match; @@ -1360,10 +1401,10 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } break; case GDScriptParser::ControlFlowNode::CF_IF: { - int ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); - if (ret2 < 0) + if (ret2 < 0) { return ERR_PARSE_ERROR; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT); codegen.opcodes.push_back(ret2); @@ -1371,19 +1412,20 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.push_back(0); //temporary Error err = _parse_block(codegen, cf->body, p_stack_level, p_break_addr, p_continue_addr); - if (err) + if (err) { return err; + } if (cf->body_else) { - codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); int end_addr = codegen.opcodes.size(); codegen.opcodes.push_back(0); codegen.opcodes.write[else_addr] = codegen.opcodes.size(); Error err2 = _parse_block(codegen, cf->body_else, p_stack_level, p_break_addr, p_continue_addr); - if (err2) + if (err2) { return err2; + } codegen.opcodes.write[end_addr] = codegen.opcodes.size(); } else { @@ -1393,7 +1435,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } break; case GDScriptParser::ControlFlowNode::CF_FOR: { - int slevel = p_stack_level; int iter_stack_pos = slevel; int iterator_pos = (slevel++) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); @@ -1405,8 +1446,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.add_stack_identifier(static_cast<const GDScriptParser::IdentifierNode *>(cf->arguments[0])->name, iter_stack_pos); int ret2 = _parse_expression(codegen, cf->arguments[1], slevel, false); - if (ret2 < 0) + if (ret2 < 0) { return ERR_COMPILATION_FAILED; + } //assign container codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN); @@ -1434,8 +1476,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.push_back(iterator_pos); Error err = _parse_block(codegen, cf->body, slevel, break_pos, continue_pos); - if (err) + if (err) { return err; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); codegen.opcodes.push_back(continue_pos); @@ -1445,7 +1488,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } break; case GDScriptParser::ControlFlowNode::CF_WHILE: { - codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); codegen.opcodes.push_back(codegen.opcodes.size() + 3); int break_addr = codegen.opcodes.size(); @@ -1454,14 +1496,16 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo int continue_addr = codegen.opcodes.size(); int ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); - if (ret2 < 0) + if (ret2 < 0) { return ERR_PARSE_ERROR; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT); codegen.opcodes.push_back(ret2); codegen.opcodes.push_back(break_addr); Error err = _parse_block(codegen, cf->body, p_stack_level, break_addr, continue_addr); - if (err) + if (err) { return err; + } codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); codegen.opcodes.push_back(continue_addr); @@ -1469,9 +1513,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } break; case GDScriptParser::ControlFlowNode::CF_BREAK: { - if (p_break_addr < 0) { - _set_error("'break'' not within loop", cf); return ERR_COMPILATION_FAILED; } @@ -1480,9 +1522,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } break; case GDScriptParser::ControlFlowNode::CF_CONTINUE: { - if (p_continue_addr < 0) { - _set_error("'continue' not within loop", cf); return ERR_COMPILATION_FAILED; } @@ -1492,17 +1532,15 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } break; case GDScriptParser::ControlFlowNode::CF_RETURN: { - int ret2; if (cf->arguments.size()) { - ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false); - if (ret2 < 0) + if (ret2 < 0) { return ERR_PARSE_ERROR; + } } else { - ret2 = GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS; } @@ -1519,14 +1557,16 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo const GDScriptParser::AssertNode *as = static_cast<const GDScriptParser::AssertNode *>(s); int ret2 = _parse_expression(codegen, as->condition, p_stack_level, false); - if (ret2 < 0) + if (ret2 < 0) { return ERR_PARSE_ERROR; + } int message_ret = 0; if (as->message) { message_ret = _parse_expression(codegen, as->message, p_stack_level + 1, false); - if (message_ret < 0) + if (message_ret < 0) { return ERR_PARSE_ERROR; + } } codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSERT); @@ -1541,7 +1581,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo #endif } break; case GDScriptParser::Node::TYPE_LOCAL_VAR: { - const GDScriptParser::LocalVarNode *lv = static_cast<const GDScriptParser::LocalVarNode *>(s); // since we are using properties now for most class access, allow shadowing of class members to make user's life easier. @@ -1559,8 +1598,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo default: { //expression int ret2 = _parse_expression(codegen, s, p_stack_level, true); - if (ret2 < 0) + if (ret2 < 0) { return ERR_PARSE_ERROR; + } } break; } } @@ -1569,7 +1609,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo } Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) { - Vector<int> bytecode; CodeGen codegen; @@ -1610,7 +1649,6 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser if (is_initializer || (p_func && String(p_func->name) == "_init")) { //parse initializer for class members if (!p_func && p_class->extends_used && p_script->native.is_null()) { - //call implicit parent constructor codegen.opcodes.push_back(GDScriptFunction::OPCODE_CALL_SELF_BASE); codegen.opcodes.push_back(codegen.get_name_map_pos("_init")); @@ -1618,8 +1656,9 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser codegen.opcodes.push_back((GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) | 0); } Error err = _parse_block(codegen, p_class->initializer, stack_level); - if (err) + if (err) { return err; + } is_initializer = true; } @@ -1627,8 +1666,9 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser //parse initializer for class members if (p_class->ready->statements.size()) { Error err = _parse_block(codegen, p_class->ready, stack_level); - if (err) + if (err) { return err; + } } } @@ -1638,13 +1678,10 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser StringName func_name; if (p_func) { - if (p_func->default_values.size()) { - codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT); defarg_addr.push_back(codegen.opcodes.size()); for (int i = 0; i < p_func->default_values.size(); i++) { - _parse_expression(codegen, p_func->default_values[i], stack_level, true); defarg_addr.push_back(codegen.opcodes.size()); } @@ -1653,15 +1690,17 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser } Error err = _parse_block(codegen, p_func->body, stack_level); - if (err) + if (err) { return err; + } func_name = p_func->name; } else { - if (p_for_ready) + if (p_for_ready) { func_name = "_ready"; - else + } else { func_name = "_init"; + } } codegen.opcodes.push_back(GDScriptFunction::OPCODE_END); @@ -1700,29 +1739,26 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser gdfunc->_constant_count = codegen.constant_map.size(); gdfunc->constants.resize(codegen.constant_map.size()); gdfunc->_constants_ptr = gdfunc->constants.ptrw(); - const Variant *K = NULL; + const Variant *K = nullptr; while ((K = codegen.constant_map.next(K))) { int idx = codegen.constant_map[*K]; gdfunc->constants.write[idx] = *K; } } else { - - gdfunc->_constants_ptr = NULL; + gdfunc->_constants_ptr = nullptr; gdfunc->_constant_count = 0; } //global names if (codegen.name_map.size()) { - gdfunc->global_names.resize(codegen.name_map.size()); gdfunc->_global_names_ptr = &gdfunc->global_names[0]; for (Map<StringName, int>::Element *E = codegen.name_map.front(); E; E = E->next()) { - gdfunc->global_names.write[E->get()] = E->key(); } gdfunc->_global_names_count = gdfunc->global_names.size(); } else { - gdfunc->_global_names_ptr = NULL; + gdfunc->_global_names_ptr = nullptr; gdfunc->_global_names_count = 0; } @@ -1739,25 +1775,22 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser #endif if (codegen.opcodes.size()) { - gdfunc->code = codegen.opcodes; gdfunc->_code_ptr = &gdfunc->code[0]; gdfunc->_code_size = codegen.opcodes.size(); } else { - - gdfunc->_code_ptr = NULL; + gdfunc->_code_ptr = nullptr; gdfunc->_code_size = 0; } if (defarg_addr.size()) { - gdfunc->default_arguments = defarg_addr; gdfunc->_default_arg_count = defarg_addr.size() - 1; gdfunc->_default_arg_ptr = &gdfunc->default_arguments[0]; } else { gdfunc->_default_arg_count = 0; - gdfunc->_default_arg_ptr = NULL; + gdfunc->_default_arg_ptr = nullptr; } gdfunc->_argument_count = p_func ? p_func->arguments.size() : 0; @@ -1768,8 +1801,9 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser if (EngineDebugger::is_active()) { String signature; //path - if (p_script->get_path() != String()) + if (p_script->get_path() != String()) { signature += p_script->get_path(); + } //loc if (p_func) { signature += "::" + itos(p_func->body->line); @@ -1809,17 +1843,18 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser gdfunc->_initial_line = 0; } - if (codegen.debug_stack) + if (codegen.debug_stack) { gdfunc->stack_debug = codegen.stack_debug; + } - if (is_initializer) + if (is_initializer) { p_script->initializer = gdfunc; + } return OK; } Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { - parsing_classes.insert(p_script); if (p_class->owner && p_class->owner->owner) { @@ -1838,7 +1873,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar p_script->native = Ref<GDScriptNativeClass>(); p_script->base = Ref<GDScript>(); - p_script->_base = NULL; + p_script->_base = nullptr; p_script->members.clear(); p_script->constants.clear(); for (Map<StringName, GDScriptFunction *>::Element *E = p_script->member_functions.front(); E; E = E->next()) { @@ -1848,7 +1883,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar p_script->member_indices.clear(); p_script->member_info.clear(); p_script->_signals.clear(); - p_script->initializer = NULL; + p_script->initializer = nullptr; p_script->tool = p_class->tool; p_script->name = p_class->name; @@ -1890,7 +1925,6 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar } for (int i = 0; i < p_class->variables.size(); i++) { - StringName name = p_class->variables[i].identifier; GDScript::MemberInfo minfo; @@ -1905,7 +1939,6 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar PropertyInfo export_info = p_class->variables[i]._export; if (export_info.type != Variant::NIL) { - if (!minfo.data_type.has_type) { prop_info.type = export_info.type; prop_info.class_name = export_info.class_name; @@ -1932,7 +1965,6 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar } for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_class->constant_expressions.front(); E; E = E->next()) { - StringName name = E->key(); ERR_CONTINUE(E->get().expression->type != GDScriptParser::Node::TYPE_CONSTANT); @@ -1947,13 +1979,11 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar } for (int i = 0; i < p_class->_signals.size(); i++) { - StringName name = p_class->_signals[i].name; GDScript *c = p_script; while (c) { - if (c->_signals.has(name)) { _set_error("Signal '" + name + "' redefined (in current or parent class)", p_class); return ERR_ALREADY_EXISTS; @@ -1962,7 +1992,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar if (c->base.is_valid()) { c = c->base.ptr(); } else { - c = NULL; + c = nullptr; } } @@ -1989,8 +2019,9 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar // Subclass might still be parsing, just skip it if (!parsed_classes.has(subclass_ptr) && !parsing_classes.has(subclass_ptr)) { Error err = _parse_class_level(subclass_ptr, p_class->subclasses[i], p_keep_state); - if (err) + if (err) { return err; + } } #ifdef TOOLS_ENABLED @@ -2011,37 +2042,41 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa bool has_ready = false; for (int i = 0; i < p_class->functions.size(); i++) { - - if (!has_initializer && p_class->functions[i]->name == "_init") + if (!has_initializer && p_class->functions[i]->name == "_init") { has_initializer = true; - if (!has_ready && p_class->functions[i]->name == "_ready") + } + if (!has_ready && p_class->functions[i]->name == "_ready") { has_ready = true; + } Error err = _parse_function(p_script, p_class, p_class->functions[i]); - if (err) + if (err) { return err; + } } //parse static methods for (int i = 0; i < p_class->static_functions.size(); i++) { - Error err = _parse_function(p_script, p_class, p_class->static_functions[i]); - if (err) + if (err) { return err; + } } if (!has_initializer) { //create a constructor - Error err = _parse_function(p_script, p_class, NULL); - if (err) + Error err = _parse_function(p_script, p_class, nullptr); + if (err) { return err; + } } if (!has_ready && p_class->ready->statements.size()) { //create a constructor - Error err = _parse_function(p_script, p_class, NULL, true); - if (err) + Error err = _parse_function(p_script, p_class, nullptr, true); + if (err) { return err; + } } #ifdef DEBUG_ENABLED @@ -2050,7 +2085,6 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa if (p_keep_state) { for (Set<Object *>::Element *E = p_script->instances.front(); E;) { - Set<Object *>::Element *N = E->next(); ScriptInstance *si = E->get()->get_script_instance(); @@ -2077,7 +2111,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa /* STEP 2, INITIALIZE AND CONSTRUCT */ Callable::CallError ce; - p_script->initializer->call(instance, NULL, 0, ce); + p_script->initializer->call(instance, nullptr, 0, ce); if (ce.error != Callable::CallError::CALL_OK) { //well, tough luck, not goinna do anything here @@ -2085,7 +2119,6 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa } #endif } else { - GDScriptInstance *gi = static_cast<GDScriptInstance *>(si); gi->reload_members(); } @@ -2110,7 +2143,6 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa } void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { - Map<StringName, Ref<GDScript>> old_subclasses; if (p_keep_state) { @@ -2145,7 +2177,6 @@ void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::C } Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state) { - err_line = -1; err_column = -1; error = ""; @@ -2162,30 +2193,31 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri // Create scripts for subclasses beforehand so they can be referenced _make_scripts(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state); - p_script->_owner = NULL; + p_script->_owner = nullptr; Error err = _parse_class_level(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state); - if (err) + if (err) { return err; + } err = _parse_class_blocks(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state); - if (err) + if (err) { return err; + } return OK; } String GDScriptCompiler::get_error() const { - return error; } -int GDScriptCompiler::get_error_line() const { +int GDScriptCompiler::get_error_line() const { return err_line; } -int GDScriptCompiler::get_error_column() const { +int GDScriptCompiler::get_error_column() const { return err_column; } diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 34b066b5c7..315d4f1842 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -36,13 +36,11 @@ #include "gdscript_parser.h" class GDScriptCompiler { - const GDScriptParser *parser; Set<GDScript *> parsed_classes; Set<GDScript *> parsing_classes; GDScript *main_script; struct CodeGen { - GDScript *script; const GDScriptParser::ClassNode *class_node; const GDScriptParser::FunctionNode *function_node; @@ -71,7 +69,6 @@ class GDScriptCompiler { void push_stack_identifiers() { stack_id_stack.push_back(stack_identifiers); if (debug_stack) { - block_identifier_stack.push_back(block_identifiers); block_identifiers.clear(); } @@ -83,7 +80,6 @@ class GDScriptCompiler { if (debug_stack) { for (Map<StringName, int>::Element *E = block_identifiers.front(); E; E = E->next()) { - GDScriptFunction::StackDebug sd; sd.added = false; sd.identifier = E->key(); @@ -114,8 +110,9 @@ class GDScriptCompiler { } int get_constant_pos(const Variant &p_constant) { - if (constant_map.has(p_constant)) + if (constant_map.has(p_constant)) { return constant_map[p_constant]; + } int pos = constant_map.size(); constant_map[p_constant] = pos; return pos; @@ -123,10 +120,14 @@ class GDScriptCompiler { Vector<int> opcodes; void alloc_stack(int p_level) { - if (p_level >= stack_max) stack_max = p_level + 1; + if (p_level >= stack_max) { + stack_max = p_level + 1; + } } void alloc_call(int p_params) { - if (p_params >= call_max) call_max = p_params; + if (p_params >= call_max) { + call_max = p_params; + } } int current_line; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 98e09159ec..7433c4a5bc 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -41,19 +41,16 @@ #endif void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { - p_delimiters->push_back("#"); } void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { - p_delimiters->push_back("\" \""); p_delimiters->push_back("' '"); p_delimiters->push_back("\"\"\" \"\"\""); } String GDScriptLanguage::_get_processed_template(const String &p_template, const String &p_base_class_name) const { - String processed_template = p_template; #ifdef TOOLS_ENABLED @@ -109,18 +106,15 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str } bool GDScriptLanguage::is_using_templates() { - return true; } void GDScriptLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) { - String _template = _get_processed_template(p_script->get_source_code(), p_base_class_name); p_script->set_source_code(_template); } bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const { - GDScriptParser parser; Error err = parser.parse(p_script, p_path.get_base_dir(), true, p_path, false, r_safe_lines); @@ -143,35 +137,29 @@ bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int & r_test_error = parser.get_error(); return false; } else { - const GDScriptParser::Node *root = parser.get_parse_tree(); ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, false); const GDScriptParser::ClassNode *cl = static_cast<const GDScriptParser::ClassNode *>(root); Map<int, String> funcs; for (int i = 0; i < cl->functions.size(); i++) { - funcs[cl->functions[i]->line] = cl->functions[i]->name; } for (int i = 0; i < cl->static_functions.size(); i++) { - funcs[cl->static_functions[i]->line] = cl->static_functions[i]->name; } for (int i = 0; i < cl->subclasses.size(); i++) { for (int j = 0; j < cl->subclasses[i]->functions.size(); j++) { - funcs[cl->subclasses[i]->functions[j]->line] = String(cl->subclasses[i]->name) + "." + cl->subclasses[i]->functions[j]->name; } for (int j = 0; j < cl->subclasses[i]->static_functions.size(); j++) { - funcs[cl->subclasses[i]->static_functions[j]->line] = String(cl->subclasses[i]->name) + "." + cl->subclasses[i]->static_functions[j]->name; } } for (Map<int, String>::Element *E = funcs.front(); E; E = E->next()) { - r_functions->push_back(E->get() + ":" + itos(E->key())); } } @@ -180,27 +168,22 @@ bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int & } bool GDScriptLanguage::has_named_classes() const { - return false; } bool GDScriptLanguage::supports_builtin_mode() const { - return true; } int GDScriptLanguage::find_function(const String &p_function, const String &p_code) const { - GDScriptTokenizerText tokenizer; tokenizer.set_code(p_code); int indent = 0; while (tokenizer.get_token() != GDScriptTokenizer::TK_EOF && tokenizer.get_token() != GDScriptTokenizer::TK_ERROR) { - if (tokenizer.get_token() == GDScriptTokenizer::TK_NEWLINE) { indent = tokenizer.get_token_line_indent(); } if (indent == 0 && tokenizer.get_token() == GDScriptTokenizer::TK_PR_FUNCTION && tokenizer.get_token(1) == GDScriptTokenizer::TK_IDENTIFIER) { - String identifier = tokenizer.get_token_identifier(1); if (identifier == p_function) { return tokenizer.get_token_line(); @@ -212,7 +195,6 @@ int GDScriptLanguage::find_function(const String &p_function, const String &p_co } Script *GDScriptLanguage::create_script() const { - return memnew(GDScript); } @@ -222,7 +204,6 @@ bool GDScriptLanguage::debug_break_parse(const String &p_file, int p_line, const //break because of parse error if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { - _debug_parse_err_line = p_line; _debug_parse_err_file = p_file; _debug_error = p_error; @@ -234,9 +215,7 @@ bool GDScriptLanguage::debug_break_parse(const String &p_file, int p_line, const } bool GDScriptLanguage::debug_break(const String &p_error, bool p_allow_continue) { - if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { - _debug_parse_err_line = -1; _debug_parse_err_file = ""; _debug_error = p_error; @@ -249,21 +228,21 @@ bool GDScriptLanguage::debug_break(const String &p_error, bool p_allow_continue) } String GDScriptLanguage::debug_get_error() const { - return _debug_error; } int GDScriptLanguage::debug_get_stack_level_count() const { - - if (_debug_parse_err_line >= 0) + if (_debug_parse_err_line >= 0) { return 1; + } return _debug_call_stack_pos; } -int GDScriptLanguage::debug_get_stack_level_line(int p_level) const { - if (_debug_parse_err_line >= 0) +int GDScriptLanguage::debug_get_stack_level_line(int p_level) const { + if (_debug_parse_err_line >= 0) { return _debug_parse_err_line; + } ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, -1); @@ -271,28 +250,31 @@ int GDScriptLanguage::debug_get_stack_level_line(int p_level) const { return *(_call_stack[l].line); } -String GDScriptLanguage::debug_get_stack_level_function(int p_level) const { - if (_debug_parse_err_line >= 0) +String GDScriptLanguage::debug_get_stack_level_function(int p_level) const { + if (_debug_parse_err_line >= 0) { return ""; + } ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, ""); int l = _debug_call_stack_pos - p_level - 1; return _call_stack[l].function->get_name(); } -String GDScriptLanguage::debug_get_stack_level_source(int p_level) const { - if (_debug_parse_err_line >= 0) +String GDScriptLanguage::debug_get_stack_level_source(int p_level) const { + if (_debug_parse_err_line >= 0) { return _debug_parse_err_file; + } ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, ""); int l = _debug_call_stack_pos - p_level - 1; return _call_stack[l].function->get_source(); } -void GDScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { - if (_debug_parse_err_line >= 0) +void GDScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { + if (_debug_parse_err_line >= 0) { return; + } ERR_FAIL_INDEX(p_level, _debug_call_stack_pos); int l = _debug_call_stack_pos - p_level - 1; @@ -303,23 +285,24 @@ void GDScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p f->debug_get_stack_member_state(*_call_stack[l].line, &locals); for (List<Pair<StringName, int>>::Element *E = locals.front(); E; E = E->next()) { - p_locals->push_back(E->get().first); p_values->push_back(_call_stack[l].stack[E->get().second]); } } -void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { - if (_debug_parse_err_line >= 0) +void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { + if (_debug_parse_err_line >= 0) { return; + } ERR_FAIL_INDEX(p_level, _debug_call_stack_pos); int l = _debug_call_stack_pos - p_level - 1; GDScriptInstance *instance = _call_stack[l].instance; - if (!instance) + if (!instance) { return; + } Ref<GDScript> script = instance->get_script(); ERR_FAIL_COND(script.is_null()); @@ -327,18 +310,17 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> * const Map<StringName, GDScript::MemberInfo> &mi = script->debug_get_member_indices(); for (const Map<StringName, GDScript::MemberInfo>::Element *E = mi.front(); E; E = E->next()) { - p_members->push_back(E->key()); p_values->push_back(instance->debug_get_member_by_index(E->get().index)); } } ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) { + if (_debug_parse_err_line >= 0) { + return nullptr; + } - if (_debug_parse_err_line >= 0) - return NULL; - - ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, NULL); + ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, nullptr); int l = _debug_call_stack_pos - p_level - 1; ScriptInstance *instance = _call_stack[l].instance; @@ -347,7 +329,6 @@ ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) { } void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { - const Map<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map(); const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array(); @@ -355,9 +336,9 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> get_public_constants(&cinfo); for (const Map<StringName, int>::Element *E = name_idx.front(); E; E = E->next()) { - - if (ClassDB::class_exists(E->key()) || Engine::get_singleton()->has_singleton(E->key())) + if (ClassDB::class_exists(E->key()) || Engine::get_singleton()->has_singleton(E->key())) { continue; + } bool is_script_constant = false; for (List<Pair<String, Variant>>::Element *CE = cinfo.front(); CE; CE = CE->next()) { @@ -366,13 +347,15 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> break; } } - if (is_script_constant) + if (is_script_constant) { continue; + } const Variant &var = globals[E->value()]; if (Object *obj = var) { - if (Object::cast_to<GDScriptNativeClass>(obj)) + if (Object::cast_to<GDScriptNativeClass>(obj)) { continue; + } } bool skip = false; @@ -382,8 +365,9 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> break; } } - if (skip) + if (skip) { continue; + } p_globals->push_back(E->key()); p_values->push_back(var); @@ -391,19 +375,15 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> } String GDScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { - return ""; } void GDScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("gd"); } void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const { - for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) { - p_functions->push_back(GDScriptFunctions::get_info(GDScriptFunctions::Function(i))); } @@ -430,12 +410,13 @@ void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const mi.name = "assert"; mi.return_val.type = Variant::NIL; mi.arguments.push_back(PropertyInfo(Variant::BOOL, "condition")); + mi.arguments.push_back(PropertyInfo(Variant::STRING, "message")); + mi.default_arguments.push_back(String()); p_functions->push_back(mi); } } void GDScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_constants) const { - Pair<String, Variant> pi; pi.first = "PI"; pi.second = Math_PI; @@ -458,7 +439,6 @@ void GDScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_const } String GDScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const { - #ifdef TOOLS_ENABLED bool th = EditorSettings::get_singleton()->get_setting("text_editor/completion/add_type_hints"); #else @@ -468,8 +448,9 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na String s = "func " + p_name + "("; if (p_args.size()) { for (int i = 0; i < p_args.size(); i++) { - if (i > 0) + if (i > 0) { s += ", "; + } s += p_args[i].get_slice(":", 0); if (th) { String type = p_args[i].get_slice(":", 1); @@ -489,36 +470,27 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na #if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) struct GDScriptCompletionContext { - - const GDScriptParser::ClassNode *_class; - const GDScriptParser::FunctionNode *function; - const GDScriptParser::BlockNode *block; - Object *base; + const GDScriptParser::ClassNode *_class = nullptr; + const GDScriptParser::FunctionNode *function = nullptr; + const GDScriptParser::BlockNode *block = nullptr; + Object *base = nullptr; String base_path; - int line; - uint32_t depth; - - GDScriptCompletionContext() : - _class(NULL), - function(NULL), - block(NULL), - base(NULL), - line(0), - depth(0) {} + int line = 0; + uint32_t depth = 0; + + GDScriptCompletionContext() {} }; struct GDScriptCompletionIdentifier { GDScriptParser::DataType type; String enumeration; Variant value; - const GDScriptParser::Node *assigned_expression; + const GDScriptParser::Node *assigned_expression = nullptr; - GDScriptCompletionIdentifier() : - assigned_expression(NULL) {} + GDScriptCompletionIdentifier() {} }; static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String, ScriptCodeCompletionOption> &r_list) { - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; for (int i = 0; i < p_dir->get_file_count(); i++) { @@ -533,7 +505,6 @@ static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String } static String _get_visual_datatype(const PropertyInfo &p_info, bool p_isarg = true) { - if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { String enum_name = p_info.class_name; if (enum_name.find(".") == -1) { @@ -833,7 +804,6 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G Object *baseptr = base.value; if (all_is_const && String(id) == "get_node" && ClassDB::is_parent_class(native_type.native_type, "Node") && args.size()) { - String arg1 = args[0]; if (arg1.begins_with("/root/")) { String which = arg1.get_slice("/", 2); @@ -847,7 +817,6 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G ProjectSettings::get_singleton()->get_property_list(&props); for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - String s = E->get().name; if (!s.begins_with("autoload/")) { continue; @@ -909,7 +878,7 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G Variant ret = mb->call(baseptr, (const Variant **)argptr.ptr(), argptr.size(), ce); if (ce.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) { - if (ret.get_type() != Variant::OBJECT || ret.operator Object *() != NULL) { + if (ret.get_type() != Variant::OBJECT || ret.operator Object *() != nullptr) { r_type = _type_from_variant(ret); found = true; } @@ -963,7 +932,7 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G break; } - const GDScriptParser::DictionaryNode *dn = NULL; + const GDScriptParser::DictionaryNode *dn = nullptr; if (op->arguments[0]->type == GDScriptParser::Node::TYPE_DICTIONARY) { dn = static_cast<const GDScriptParser::DictionaryNode *>(op->arguments[0]); } else if (base.assigned_expression && base.assigned_expression->type == GDScriptParser::Node::TYPE_DICTIONARY) { @@ -1017,7 +986,7 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G } // Look if it is a dictionary node - const GDScriptParser::DictionaryNode *dn = NULL; + const GDScriptParser::DictionaryNode *dn = nullptr; if (op->arguments[0]->type == GDScriptParser::Node::TYPE_DICTIONARY) { dn = static_cast<const GDScriptParser::DictionaryNode *>(op->arguments[0]); } else if (base.assigned_expression && base.assigned_expression->type == GDScriptParser::Node::TYPE_DICTIONARY) { @@ -1041,7 +1010,7 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G // Look if it is an array node if (!found && index.value.is_num()) { int idx = index.value; - const GDScriptParser::ArrayNode *an = NULL; + const GDScriptParser::ArrayNode *an = nullptr; if (op->arguments[0]->type == GDScriptParser::Node::TYPE_ARRAY) { an = static_cast<const GDScriptParser::ArrayNode *>(op->arguments[0]); } else if (base.assigned_expression && base.assigned_expression->type == GDScriptParser::Node::TYPE_ARRAY) { @@ -1061,7 +1030,7 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G found = _guess_identifier_type_from_base(c, base, id, r_type); } else if (!found && index.type.kind == GDScriptParser::DataType::BUILTIN) { Callable::CallError err; - Variant base_val = Variant::construct(base.type.builtin_type, NULL, 0, err); + Variant base_val = Variant::construct(base.type.builtin_type, nullptr, 0, err); bool valid = false; Variant res = base_val.get(index.value, &valid); if (valid) { @@ -1080,16 +1049,36 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G Variant::Operator vop = Variant::OP_MAX; switch (op->op) { - case GDScriptParser::OperatorNode::OP_ADD: vop = Variant::OP_ADD; break; - case GDScriptParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBTRACT; break; - case GDScriptParser::OperatorNode::OP_MUL: vop = Variant::OP_MULTIPLY; break; - case GDScriptParser::OperatorNode::OP_DIV: vop = Variant::OP_DIVIDE; break; - case GDScriptParser::OperatorNode::OP_MOD: vop = Variant::OP_MODULE; break; - case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: vop = Variant::OP_SHIFT_LEFT; break; - case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: vop = Variant::OP_SHIFT_RIGHT; break; - case GDScriptParser::OperatorNode::OP_BIT_AND: vop = Variant::OP_BIT_AND; break; - case GDScriptParser::OperatorNode::OP_BIT_OR: vop = Variant::OP_BIT_OR; break; - case GDScriptParser::OperatorNode::OP_BIT_XOR: vop = Variant::OP_BIT_XOR; break; + case GDScriptParser::OperatorNode::OP_ADD: + vop = Variant::OP_ADD; + break; + case GDScriptParser::OperatorNode::OP_SUB: + vop = Variant::OP_SUBTRACT; + break; + case GDScriptParser::OperatorNode::OP_MUL: + vop = Variant::OP_MULTIPLY; + break; + case GDScriptParser::OperatorNode::OP_DIV: + vop = Variant::OP_DIVIDE; + break; + case GDScriptParser::OperatorNode::OP_MOD: + vop = Variant::OP_MODULE; + break; + case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: + vop = Variant::OP_SHIFT_LEFT; + break; + case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: + vop = Variant::OP_SHIFT_RIGHT; + break; + case GDScriptParser::OperatorNode::OP_BIT_AND: + vop = Variant::OP_BIT_AND; + break; + case GDScriptParser::OperatorNode::OP_BIT_OR: + vop = Variant::OP_BIT_OR; + break; + case GDScriptParser::OperatorNode::OP_BIT_XOR: + vop = Variant::OP_BIT_XOR; + break; default: { } } @@ -1116,9 +1105,9 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G Callable::CallError ce; bool v1_use_value = p1.value.get_type() != Variant::NIL && p1.value.get_type() != Variant::OBJECT; - Variant v1 = (v1_use_value) ? p1.value : Variant::construct(p1.type.builtin_type, NULL, 0, ce); + Variant v1 = (v1_use_value) ? p1.value : Variant::construct(p1.type.builtin_type, nullptr, 0, ce); bool v2_use_value = p2.value.get_type() != Variant::NIL && p2.value.get_type() != Variant::OBJECT; - Variant v2 = (v2_use_value) ? p2.value : Variant::construct(p2.type.builtin_type, NULL, 0, ce); + Variant v2 = (v2_use_value) ? p2.value : Variant::construct(p2.type.builtin_type, nullptr, 0, ce); // avoid potential invalid ops if ((vop == Variant::OP_DIVIDE || vop == Variant::OP_MODULE) && v2.get_type() == Variant::INT) { v2 = 1; @@ -1169,11 +1158,10 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G } static bool _guess_identifier_type(GDScriptCompletionContext &p_context, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type) { - // Look in blocks first const GDScriptParser::BlockNode *blk = p_context.block; int last_assign_line = -1; - const GDScriptParser::Node *last_assigned_expression = NULL; + const GDScriptParser::Node *last_assigned_expression = nullptr; GDScriptParser::DataType var_type; while (blk) { if (blk->variables.has(p_identifier)) { @@ -1227,7 +1215,7 @@ static bool _guess_identifier_type(GDScriptCompletionContext &p_context, const S r_type.type.is_meta_type = false; // Right-hand of `is` will be a meta type, but the left-hand value is not // Not an assignment, it shouldn't carry any value r_type.value = Variant(); - r_type.assigned_expression = NULL; + r_type.assigned_expression = nullptr; return true; } @@ -1271,8 +1259,8 @@ static bool _guess_identifier_type(GDScriptCompletionContext &p_context, const S return false; } GDScriptCompletionContext c = p_context; - c.function = NULL; - c.block = NULL; + c.function = nullptr; + c.block = nullptr; return _guess_expression_type(c, op->arguments[1], r_type); } } @@ -1425,6 +1413,7 @@ static bool _guess_identifier_type_from_base(GDScriptCompletionContext &p_contex // Variable used in the same expression return false; } + if (_guess_expression_type(p_context, m.expression, r_type)) { return true; } @@ -1534,7 +1523,7 @@ static bool _guess_identifier_type_from_base(GDScriptCompletionContext &p_contex } break; case GDScriptParser::DataType::BUILTIN: { Callable::CallError err; - Variant tmp = Variant::construct(base_type.builtin_type, NULL, 0, err); + Variant tmp = Variant::construct(base_type.builtin_type, nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK) { return false; @@ -1612,7 +1601,7 @@ static bool _guess_method_return_type_from_base(GDScriptCompletionContext &p_con for (int i = 0; i < base_type.class_type->static_functions.size(); i++) { if (base_type.class_type->static_functions[i]->name == p_method) { int last_return_line = -1; - const GDScriptParser::Node *last_returned_value = NULL; + const GDScriptParser::Node *last_returned_value = nullptr; GDScriptCompletionContext c = p_context; c._class = base_type.class_type; c.function = base_type.class_type->static_functions[i]; @@ -1629,7 +1618,7 @@ static bool _guess_method_return_type_from_base(GDScriptCompletionContext &p_con for (int i = 0; i < base_type.class_type->functions.size(); i++) { if (base_type.class_type->functions[i]->name == p_method) { int last_return_line = -1; - const GDScriptParser::Node *last_returned_value = NULL; + const GDScriptParser::Node *last_returned_value = nullptr; GDScriptCompletionContext c = p_context; c._class = base_type.class_type; c.function = base_type.class_type->functions[i]; @@ -1704,7 +1693,7 @@ static bool _guess_method_return_type_from_base(GDScriptCompletionContext &p_con } break; case GDScriptParser::DataType::BUILTIN: { Callable::CallError err; - Variant tmp = Variant::construct(base_type.builtin_type, NULL, 0, err); + Variant tmp = Variant::construct(base_type.builtin_type, nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK) { return false; } @@ -1730,7 +1719,6 @@ static bool _guess_method_return_type_from_base(GDScriptCompletionContext &p_con } static String _make_arguments_hint(const MethodInfo &p_info, int p_arg_idx) { - String arghint = _get_visual_datatype(p_info.return_val, false) + " " + p_info.name + "("; int def_args = p_info.arguments.size() - p_info.default_arguments.size(); @@ -1775,7 +1763,6 @@ static String _make_arguments_hint(const MethodInfo &p_info, int p_arg_idx) { } static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_function, int p_arg_idx) { - String arghint = p_function->return_type.to_string() + " " + p_function->name.operator String() + "("; int def_args = p_function->arguments.size() - p_function->default_values.size(); @@ -1817,7 +1804,6 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio } static void _find_enumeration_candidates(const String p_enum_hint, Map<String, ScriptCodeCompletionOption> &r_result) { - if (p_enum_hint.find(".") == -1) { // Global constant StringName current_enum = p_enum_hint; @@ -1911,8 +1897,8 @@ static void _find_identifiers_in_class(const GDScriptCompletionContext &p_contex base_type.value = p_context.base; GDScriptCompletionContext c = p_context; - c.block = NULL; - c.function = NULL; + c.block = nullptr; + c.function = nullptr; _find_identifiers_in_base(c, base_type, p_only_functions, r_result); } @@ -1932,8 +1918,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context case GDScriptParser::DataType::CLASS: { GDScriptCompletionContext c = p_context; c._class = base_type.class_type; - c.block = NULL; - c.function = NULL; + c.block = nullptr; + c.function = nullptr; _find_identifiers_in_class(c, _static, p_only_functions, false, r_result); base_type = base_type.class_type->base_type; } break; @@ -2055,7 +2041,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context List<PropertyInfo> pinfo; ClassDB::get_property_list(type, &pinfo); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - if (E->get().usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) { + if (E->get().usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP | PROPERTY_USAGE_CATEGORY)) { continue; } if (E->get().name.find("/") != -1) { @@ -2089,14 +2075,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context } break; case GDScriptParser::DataType::BUILTIN: { Callable::CallError err; - Variant tmp = Variant::construct(base_type.builtin_type, NULL, 0, err); + Variant tmp = Variant::construct(base_type.builtin_type, nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK) { return; } if (!p_only_functions) { List<PropertyInfo> members; - p_base.value.get_property_list(&members); + tmp.get_property_list(&members); for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) { if (String(E->get().name).find("/") == -1) { @@ -2128,11 +2114,9 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context } static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result) { - const GDScriptParser::BlockNode *block = p_context.block; if (p_context.function) { - const GDScriptParser::FunctionNode *f = p_context.function; for (int i = 0; i < f->arguments.size(); i++) { @@ -2148,13 +2132,13 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p } const GDScriptParser::ClassNode *clss = p_context._class; - bool _static = !p_context.function || p_context.function->_static; + bool _static = p_context.function && p_context.function->_static; while (clss) { GDScriptCompletionContext c = p_context; c._class = clss; - c.block = NULL; - c.function = NULL; + c.block = nullptr; + c.function = nullptr; _find_identifiers_in_class(c, _static, p_only_functions, false, r_result); _static = true; clss = clss->owner; @@ -2188,7 +2172,7 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p "const", "enum", "export", "onready", "static", "var", "break", "continue", "if", "elif", "else", "for", "pass", "return", "match", "while", "remote", "master", "puppet", "remotesync", "mastersync", "puppetsync", - 0 + nullptr }; const char **kw = _keywords; @@ -2234,6 +2218,8 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; +#define IS_METHOD_SIGNAL(m_method) (m_method == "connect" || m_method == "disconnect" || m_method == "is_connected" || m_method == "emit_signal") + while (base_type.has_type) { switch (base_type.kind) { case GDScriptParser::DataType::CLASS: { @@ -2250,7 +2236,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con } } - if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) { + if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) { for (int i = 0; i < base_type.class_type->_signals.size(); i++) { ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL); option.insert_text = quote_style + option.display + quote_style; @@ -2263,7 +2249,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con case GDScriptParser::DataType::GDSCRIPT: { Ref<GDScript> gds = base_type.script_type; if (gds.is_valid()) { - if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) { + if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) { List<MethodInfo> signals; gds->get_script_signal_list(&signals); for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) { @@ -2325,7 +2311,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con } } - if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) { + if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) { List<MethodInfo> signals; ClassDB::get_signal_list(class_name, &signals); for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) { @@ -2334,6 +2320,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con r_result.insert(option.display, option); } } +#undef IS_METHOD_SIGNAL if (ClassDB::is_parent_class(class_name, "Node") && (p_method == "get_node" || p_method == "has_node") && p_argidx == 0) { // Get autoloads @@ -2373,7 +2360,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con case GDScriptParser::DataType::BUILTIN: { if (base.get_type() == Variant::NIL) { Callable::CallError err; - base = Variant::construct(base_type.builtin_type, NULL, 0, err); + base = Variant::construct(base_type.builtin_type, nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK) { return; } @@ -2398,7 +2385,6 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con } static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Map<String, ScriptCodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) { - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; if (!p_node || p_node->type != GDScriptParser::Node::TYPE_OPERATOR) { @@ -2454,7 +2440,6 @@ static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDS } return; } else if (op->arguments[0]->type == GDScriptParser::Node::TYPE_SELF) { - if (op->arguments.size() < 2 || op->arguments[1]->type != GDScriptParser::Node::TYPE_IDENTIFIER) { return; } @@ -2528,7 +2513,6 @@ static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDS } Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) { - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; GDScriptParser parser; @@ -2542,7 +2526,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path context.function = parser.get_completion_function(); context.line = parser.get_completion_line(); - if (!context._class || context._class->owner == NULL) { + if (!context._class || context._class->owner == nullptr) { context.base = p_owner; context.base_path = p_path.get_base_dir(); } @@ -2576,7 +2560,6 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path p_owner->get_argument_options("get_node", 0, &opts); for (List<String>::Element *E = opts.front(); E; E = E->next()) { - String opt = E->get().strip_edges(); if (opt.is_quoted()) { r_forced = true; @@ -2626,13 +2609,13 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path } GDScriptCompletionContext c = context; - c.function = NULL; - c.block = NULL; - c.base = base.value.get_type() == Variant::OBJECT ? base.value.operator Object *() : NULL; + c.function = nullptr; + c.block = nullptr; + c.base = base.value.get_type() == Variant::OBJECT ? base.value.operator Object *() : nullptr; if (base.type.kind == GDScriptParser::DataType::CLASS) { c._class = base.type.class_type; } else { - c._class = NULL; + c._class = nullptr; } _find_identifiers_in_base(c, base, is_function, options); @@ -2684,7 +2667,6 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path List<MethodInfo> virtual_methods; ClassDB::get_virtual_methods(class_name, &virtual_methods); for (List<MethodInfo>::Element *E = virtual_methods.front(); E; E = E->next()) { - MethodInfo &mi = E->get(); String method_hint = mi.name; if (method_hint.find(":") != -1) { @@ -2818,8 +2800,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = clss->constant_expressions.front(); E; E = E->next()) { GDScriptCompletionIdentifier constant; GDScriptCompletionContext c = context; - c.function = NULL; - c.block = NULL; + c.function = nullptr; + c.block = nullptr; c.line = E->value().expression->line; if (_guess_expression_type(c, E->value().expression, constant)) { if (constant.type.has_type && constant.type.is_meta_type) { @@ -2887,9 +2869,9 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path } GDScriptCompletionContext c = context; - c._class = NULL; - c.function = NULL; - c.block = NULL; + c._class = nullptr; + c.function = nullptr; + c.block = nullptr; bool finding = true; index = index.right(index.find(".") + 1); while (index.find(".") != -1) { @@ -2917,8 +2899,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path GDScriptCompletionIdentifier constant; GDScriptCompletionContext c2 = context; c2._class = base_type.class_type; - c2.function = NULL; - c2.block = NULL; + c2.function = nullptr; + c2.block = nullptr; c2.line = E->value().expression->line; if (_guess_expression_type(c2, E->value().expression, constant)) { if (constant.type.has_type && constant.type.is_meta_type) { @@ -3008,19 +2990,16 @@ String GDScriptLanguage::_get_indentation() const { } void GDScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_to_line) const { - String indent = _get_indentation(); Vector<String> lines = p_code.split("\n"); List<int> indent_stack; for (int i = 0; i < lines.size(); i++) { - String l = lines[i]; int tc = 0; for (int j = 0; j < l.length(); j++) { if (l[j] == ' ' || l[j] == '\t') { - tc++; } else { break; @@ -3028,8 +3007,9 @@ void GDScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_t } String st = l.substr(tc, l.length()).strip_edges(); - if (st == "" || st.begins_with("#")) + if (st == "" || st.begins_with("#")) { continue; //ignore! + } int ilevel = 0; if (indent_stack.size()) { @@ -3043,12 +3023,12 @@ void GDScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_t indent_stack.pop_back(); } - if (indent_stack.size() && indent_stack.back()->get() != tc) + if (indent_stack.size() && indent_stack.back()->get() != tc) { indent_stack.push_back(tc); //this is not right but gets the job done + } } if (i >= p_from_line) { - l = ""; for (int j = 0; j < indent_stack.size(); j++) { l += indent; @@ -3064,8 +3044,9 @@ void GDScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_t p_code = ""; for (int i = 0; i < lines.size(); i++) { - if (i > 0) + if (i > 0) { p_code += "\n"; + } p_code += lines[i]; } } @@ -3220,7 +3201,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co v = v_ref; } else { Callable::CallError err; - v = Variant::construct(base_type.builtin_type, NULL, 0, err); + v = Variant::construct(base_type.builtin_type, nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK) { break; } @@ -3252,7 +3233,6 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co } Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) { - //before parsing, try the usual stuff if (ClassDB::class_exists(p_symbol)) { r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS; @@ -3333,7 +3313,6 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol [[fallthrough]]; } case GDScriptParser::COMPLETION_IDENTIFIER: { - if (!is_function) { is_function = parser.get_completion_identifier_is_function(); } @@ -3385,13 +3364,12 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol ProjectSettings::get_singleton()->get_property_list(&props); for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - String s = E->get().name; - if (!s.begins_with("autoload/")) + if (!s.begins_with("autoload/")) { continue; + } String name = s.get_slice("/", 1); if (name == String(p_symbol)) { - String path = ProjectSettings::get_singleton()->get(s); if (path.begins_with("*")) { String script = path.substr(1, path.length()); @@ -3403,7 +3381,6 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol } if (FileAccess::exists(script)) { - r_result.type = ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; r_result.location = 0; r_result.script = ResourceLoader::load(script); @@ -3440,7 +3417,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol // We cannot determine the exact nature of the identifier here // Otherwise these codes would work StringName enumName = ClassDB::get_integer_constant_enum("@GlobalScope", p_symbol, true); - if (enumName != NULL) { + if (enumName != nullptr) { r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_ENUM; r_result.class_name = "@GlobalScope"; r_result.class_member = enumName; @@ -3485,6 +3462,16 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol return OK; } } break; + case GDScriptParser::COMPLETION_TYPE_HINT: { + GDScriptParser::DataType base_type = context._class->base_type; + base_type.has_type = true; + base_type.kind = GDScriptParser::DataType::CLASS; + base_type.class_type = const_cast<GDScriptParser::ClassNode *>(context._class); + + if (_lookup_symbol_from_base(base_type, p_symbol, false, r_result) == OK) { + return OK; + } + } break; default: { } } diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 0721c25388..fc0c4b3138 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -35,48 +35,43 @@ #include "gdscript_functions.h" Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant &static_ref, Variant *p_stack, String &r_error) const { - int address = p_address & ADDR_MASK; //sequential table (jump table generated by compiler) switch ((p_address & ADDR_TYPE_MASK) >> ADDR_BITS) { - case ADDR_TYPE_SELF: { #ifdef DEBUG_ENABLED if (unlikely(!p_instance)) { r_error = "Cannot access self without instance."; - return NULL; + return nullptr; } #endif return &self; } break; case ADDR_TYPE_CLASS: { - return &static_ref; } break; case ADDR_TYPE_MEMBER: { #ifdef DEBUG_ENABLED if (unlikely(!p_instance)) { r_error = "Cannot access member without instance."; - return NULL; + return nullptr; } #endif //member indexing is O(1) return &p_instance->members.write[address]; } break; case ADDR_TYPE_CLASS_CONSTANT: { - //todo change to index! GDScript *s = p_script; #ifdef DEBUG_ENABLED - ERR_FAIL_INDEX_V(address, _global_names_count, NULL); + ERR_FAIL_INDEX_V(address, _global_names_count, nullptr); #endif const StringName *sn = &_global_names_ptr[address]; while (s) { GDScript *o = s; while (o) { - Map<StringName, Variant>::Element *E = o->constants.find(*sn); if (E) { return &E->get(); @@ -86,31 +81,31 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta s = s->_base; } - ERR_FAIL_V_MSG(NULL, "GDScriptCompiler bug."); + ERR_FAIL_V_MSG(nullptr, "GDScriptCompiler bug."); } break; case ADDR_TYPE_LOCAL_CONSTANT: { #ifdef DEBUG_ENABLED - ERR_FAIL_INDEX_V(address, _constant_count, NULL); + ERR_FAIL_INDEX_V(address, _constant_count, nullptr); #endif return &_constants_ptr[address]; } break; case ADDR_TYPE_STACK: case ADDR_TYPE_STACK_VARIABLE: { #ifdef DEBUG_ENABLED - ERR_FAIL_INDEX_V(address, _stack_size, NULL); + ERR_FAIL_INDEX_V(address, _stack_size, nullptr); #endif return &p_stack[address]; } break; case ADDR_TYPE_GLOBAL: { #ifdef DEBUG_ENABLED - ERR_FAIL_INDEX_V(address, GDScriptLanguage::get_singleton()->get_global_array_size(), NULL); + ERR_FAIL_INDEX_V(address, GDScriptLanguage::get_singleton()->get_global_array_size(), nullptr); #endif return &GDScriptLanguage::get_singleton()->get_global_array()[address]; } break; #ifdef TOOLS_ENABLED case ADDR_TYPE_NAMED_GLOBAL: { #ifdef DEBUG_ENABLED - ERR_FAIL_INDEX_V(address, _named_globals_count, NULL); + ERR_FAIL_INDEX_V(address, _named_globals_count, nullptr); #endif StringName id = _named_globals_ptr[address]; @@ -118,7 +113,7 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta return (Variant *)&GDScriptLanguage::get_singleton()->get_named_globals_map()[id]; } else { r_error = "Autoload singleton '" + String(id) + "' has been removed."; - return NULL; + return nullptr; } } break; #endif @@ -127,13 +122,12 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta } break; } - ERR_FAIL_V_MSG(NULL, "Bad code! (unknown addressing mode)."); - return NULL; + ERR_FAIL_V_MSG(nullptr, "Bad code! (unknown addressing mode)."); + return nullptr; } #ifdef DEBUG_ENABLED static String _get_var_type(const Variant *p_var) { - String basestr; if (p_var->get_type() == Variant::OBJECT) { @@ -146,10 +140,11 @@ static String _get_var_type(const Variant *p_var) { basestr = "previously freed"; } } else { - if (bobj->get_script_instance()) + if (bobj->get_script_instance()) { basestr = bobj->get_class() + " (" + bobj->get_script_instance()->get_script()->get_path().get_file() + ")"; - else + } else { basestr = bobj->get_class(); + } } } else { @@ -161,7 +156,6 @@ static String _get_var_type(const Variant *p_var) { #endif // DEBUG_ENABLED String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const { - String err_text; if (p_err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) { @@ -259,11 +253,9 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const #endif Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state) { - OPCODES_TABLE; if (!_code_ptr) { - return Variant(); } @@ -272,7 +264,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a Variant self; Variant static_ref; Variant retvalue; - Variant *stack = NULL; + Variant *stack = nullptr; Variant **call_args; int defarg = 0; @@ -294,29 +286,23 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a line = p_state->line; ip = p_state->ip; alloca_size = p_state->stack.size(); - script = p_state->script.ptr(); + script = p_state->script; p_instance = p_state->instance; defarg = p_state->defarg; self = p_state->self; - //stack[p_state->result_pos]=p_state->result; //assign stack with result } else { - if (p_argcount != _argument_count) { - if (p_argcount > _argument_count) { - r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_err.argument = _argument_count; return Variant(); } else if (p_argcount < _argument_count - _default_arg_count) { - r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_err.argument = _argument_count - _default_arg_count; return Variant(); } else { - defarg = _argument_count - p_argcount; } } @@ -324,11 +310,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a alloca_size = sizeof(Variant *) * _call_size + sizeof(Variant) * _stack_size; if (alloca_size) { - uint8_t *aptr = (uint8_t *)alloca(alloca_size); if (_stack_size) { - stack = (Variant *)aptr; for (int i = 0; i < p_argcount; i++) { if (!argument_types[i].has_type) { @@ -337,15 +321,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } if (!argument_types[i].is_type(*p_args[i], true)) { - if (argument_types[i].is_type(Variant(), true)) { - memnew_placement(&stack[i], Variant); - continue; - } else { - r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_err.argument = i; - r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT; - return Variant(); - } + r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_err.argument = i; + r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT; + return Variant(); } if (argument_types[i].kind == GDScriptDataType::BUILTIN) { Variant arg = Variant::construct(argument_types[i].builtin_type, &p_args[i], 1, r_err); @@ -358,25 +337,22 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a memnew_placement(&stack[i], Variant); } } else { - stack = NULL; + stack = nullptr; } if (_call_size) { - call_args = (Variant **)&aptr[sizeof(Variant) * _stack_size]; } else { - - call_args = NULL; + call_args = nullptr; } } else { - stack = NULL; - call_args = NULL; + stack = nullptr; + call_args = nullptr; } if (p_instance) { if (p_instance->base_ref && static_cast<Reference *>(p_instance->owner)->is_referenced()) { - self = REF(static_cast<Reference *>(p_instance->owner)); } else { self = p_instance->owner; @@ -391,8 +367,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #ifdef DEBUG_ENABLED - if (EngineDebugger::is_active()) + if (EngineDebugger::is_active()) { GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line); + } #define GD_ERR_BREAK(m_cond) \ { \ @@ -443,9 +420,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif OPCODE_SWITCH(_code_ptr[ip]) { - OPCODE(OPCODE_OPERATOR) { - CHECK_SPACE(5); bool valid; @@ -465,7 +440,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif #ifdef DEBUG_ENABLED if (!valid) { - if (ret.get_type() == Variant::STRING) { //return a string when invalid with the error err_text = ret; @@ -482,7 +456,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_EXTENDS_TEST) { - CHECK_SPACE(4); GET_VARIANT_PTR(a, 1); @@ -490,16 +463,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GET_VARIANT_PTR(dst, 3); #ifdef DEBUG_ENABLED - if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) { - + if (b->get_type() != Variant::OBJECT || b->operator Object *() == nullptr) { err_text = "Right operand of 'is' is not a class."; OPCODE_BREAK; } #endif bool extends_ok = false; - if (a->get_type() == Variant::OBJECT && a->operator Object *() != NULL) { - + if (a->get_type() == Variant::OBJECT && a->operator Object *() != nullptr) { #ifdef DEBUG_ENABLED bool was_freed; Object *obj_A = a->get_validated_object_with_check(was_freed); @@ -528,11 +499,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a //in other situation, this shoul return false. if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) { - GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr()); //bool found=false; while (cmp) { - if (cmp == scr_B) { //inherits from script, all ok extends_ok = true; @@ -544,12 +513,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } } else { - GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B); #ifdef DEBUG_ENABLED if (!nc) { - err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "')."; OPCODE_BREAK; } @@ -564,7 +531,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_IS_BUILTIN) { - CHECK_SPACE(4); GET_VARIANT_PTR(value, 1); @@ -579,7 +545,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_SET) { - CHECK_SPACE(3); GET_VARIANT_PTR(dst, 1); @@ -606,7 +571,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_GET) { - CHECK_SPACE(3); GET_VARIANT_PTR(src, 1); @@ -639,7 +603,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_SET_NAMED) { - CHECK_SPACE(3); GET_VARIANT_PTR(dst, 1); @@ -665,7 +628,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_GET_NAMED) { - CHECK_SPACE(4); GET_VARIANT_PTR(src, 1); @@ -700,7 +662,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_SET_MEMBER) { - CHECK_SPACE(3); int indexname = _code_ptr[ip + 1]; GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); @@ -725,7 +686,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_GET_MEMBER) { - CHECK_SPACE(3); int indexname = _code_ptr[ip + 1]; GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); @@ -746,7 +706,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ASSIGN) { - CHECK_SPACE(3); GET_VARIANT_PTR(dst, 1); GET_VARIANT_PTR(src, 2); @@ -758,7 +717,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ASSIGN_TRUE) { - CHECK_SPACE(2); GET_VARIANT_PTR(dst, 1); @@ -769,7 +727,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ASSIGN_FALSE) { - CHECK_SPACE(2); GET_VARIANT_PTR(dst, 1); @@ -780,7 +737,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ASSIGN_TYPED_BUILTIN) { - CHECK_SPACE(4); GET_VARIANT_PTR(dst, 2); GET_VARIANT_PTR(src, 3); @@ -810,7 +766,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) { - CHECK_SPACE(4); GET_VARIANT_PTR(dst, 2); GET_VARIANT_PTR(src, 3); @@ -839,7 +794,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) { - CHECK_SPACE(4); GET_VARIANT_PTR(dst, 2); GET_VARIANT_PTR(src, 3); @@ -855,8 +809,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } - if (src->get_type() != Variant::NIL && src->operator Object *() != NULL) { - + if (src->get_type() != Variant::NIL && src->operator Object *() != nullptr) { ScriptInstance *scr_inst = src->operator Object *()->get_script_instance(); if (!scr_inst) { err_text = "Trying to assign value of type '" + src->operator Object *()->get_class_name() + @@ -890,7 +843,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_CAST_TO_BUILTIN) { - CHECK_SPACE(4); Variant::Type to_type = (Variant::Type)_code_ptr[ip + 1]; GET_VARIANT_PTR(src, 2); @@ -913,7 +865,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_CAST_TO_NATIVE) { - CHECK_SPACE(4); GET_VARIANT_PTR(to_type, 1); GET_VARIANT_PTR(src, 2); @@ -941,7 +892,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_CAST_TO_SCRIPT) { - CHECK_SPACE(4); GET_VARIANT_PTR(to_type, 1); GET_VARIANT_PTR(src, 2); @@ -960,12 +910,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a bool valid = false; - if (src->get_type() != Variant::NIL && src->operator Object *() != NULL) { - + if (src->get_type() != Variant::NIL && src->operator Object *() != nullptr) { ScriptInstance *scr_inst = src->operator Object *()->get_script_instance(); if (scr_inst) { - Script *src_type = src->operator Object *()->get_script_instance()->get_script().ptr(); while (src_type) { @@ -989,7 +937,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_CONSTRUCT) { - CHECK_SPACE(2); Variant::Type t = Variant::Type(_code_ptr[ip + 1]); int argc = _code_ptr[ip + 2]; @@ -1006,7 +953,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #ifdef DEBUG_ENABLED if (err.error != Callable::CallError::CALL_OK) { - err_text = _get_call_error(err, "'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs); OPCODE_BREAK; } @@ -1018,7 +964,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_CONSTRUCT_ARRAY) { - CHECK_SPACE(1); int argc = _code_ptr[ip + 1]; Array array; //arrays are always shared @@ -1039,7 +984,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_CONSTRUCT_DICTIONARY) { - CHECK_SPACE(1); int argc = _code_ptr[ip + 1]; Dictionary dict; //arrays are always shared @@ -1047,7 +991,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a CHECK_SPACE(argc * 2 + 2); for (int i = 0; i < argc; i++) { - GET_VARIANT_PTR(k, 2 + i * 2 + 0); GET_VARIANT_PTR(v, 2 + i * 2 + 1); dict[*k] = *v; @@ -1063,7 +1006,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_CALL_RETURN) OPCODE(OPCODE_CALL) { - CHECK_SPACE(4); bool call_ret = _code_ptr[ip] == OPCODE_CALL_RETURN; @@ -1094,12 +1036,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif Callable::CallError err; if (call_ret) { - GET_VARIANT_PTR(ret, argc); base->call_ptr(*methodname, (const Variant **)argptrs, argc, ret, err); } else { - - base->call_ptr(*methodname, (const Variant **)argptrs, argc, NULL, err); + base->call_ptr(*methodname, (const Variant **)argptrs, argc, nullptr, err); } #ifdef DEBUG_ENABLED if (GDScriptLanguage::get_singleton()->profiling) { @@ -1107,7 +1047,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } if (err.error != Callable::CallError::CALL_OK) { - String methodstr = *methodname; String basestr = _get_var_type(base); @@ -1119,14 +1058,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } } } else if (methodstr == "free") { - if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) { - if (base->is_ref()) { err_text = "Attempted to free a reference."; OPCODE_BREAK; } else if (base->get_type() == Variant::OBJECT) { - err_text = "Attempted to free a locked object (calling or emitting)."; OPCODE_BREAK; } @@ -1137,13 +1073,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } #endif - //_call_func(NULL,base,*methodname,ip,argc,p_instance,stack); + //_call_func(nullptr,base,*methodname,ip,argc,p_instance,stack); ip += argc + 1; } DISPATCH_OPCODE; OPCODE(OPCODE_CALL_BUILT_IN) { - CHECK_SPACE(4); GDScriptFunctions::Function func = GDScriptFunctions::Function(_code_ptr[ip + 1]); @@ -1167,7 +1102,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #ifdef DEBUG_ENABLED if (err.error != Callable::CallError::CALL_OK) { - String methodstr = GDScriptFunctions::get_func_name(func); if (dst->get_type() == Variant::STRING) { //call provided error string @@ -1183,18 +1117,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_CALL_SELF) { - OPCODE_BREAK; } OPCODE(OPCODE_CALL_SELF_BASE) { - CHECK_SPACE(2); int self_fun = _code_ptr[ip + 1]; #ifdef DEBUG_ENABLED if (self_fun < 0 || self_fun >= _global_names_count) { - err_text = "compiler bug, function name not found"; OPCODE_BREAK; } @@ -1216,23 +1147,21 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a const GDScript *gds = _script; - const Map<StringName, GDScriptFunction *>::Element *E = NULL; + const Map<StringName, GDScriptFunction *>::Element *E = nullptr; while (gds->base.ptr()) { gds = gds->base.ptr(); E = gds->member_functions.find(*methodname); - if (E) + if (E) { break; + } } Callable::CallError err; if (E) { - *dst = E->get()->call(p_instance, (const Variant **)argptrs, argc, err); } else if (gds->native.ptr()) { - if (*methodname != GDScriptLanguage::get_singleton()->strings._init) { - MethodBind *mb = ClassDB::get_method(gds->native->get_name(), *methodname); if (!mb) { err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -1243,7 +1172,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a err.error = Callable::CallError::CALL_OK; } } else { - if (*methodname != GDScriptLanguage::get_singleton()->strings._init) { err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; } else { @@ -1252,7 +1180,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } if (err.error != Callable::CallError::CALL_OK) { - String methodstr = *methodname; err_text = _get_call_error(err, "function '" + methodstr + "'", (const Variant **)argptrs); @@ -1265,7 +1192,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_YIELD) OPCODE(OPCODE_YIELD_SIGNAL) { - int ipofs = 1; if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) { CHECK_SPACE(4); @@ -1285,13 +1211,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a gdfs->state.stack_size = _stack_size; gdfs->state.self = self; gdfs->state.alloca_size = alloca_size; - gdfs->state.script = Ref<GDScript>(_script); gdfs->state.ip = ip + ipofs; gdfs->state.line = line; - gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : ObjectID(); - //gdfs->state.result_pos=ip+ipofs-1; + gdfs->state.script = _script; + { + MutexLock lock(GDScriptLanguage::get_singleton()->lock); + _script->pending_func_states.add(&gdfs->scripts_list); + if (p_instance) { + gdfs->state.instance = p_instance; + p_instance->pending_func_states.add(&gdfs->instances_list); + } else { + gdfs->state.instance = nullptr; + } + } +#ifdef DEBUG_ENABLED + gdfs->state.function_name = name; + gdfs->state.script_path = _script->get_path(); +#endif gdfs->state.defarg = defarg; - gdfs->state.instance = p_instance; gdfs->function = this; retvalue = gdfs; @@ -1327,7 +1264,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } if (signal.length() == 0) { - err_text = "Second argument of yield() is an empty string (for signal name)."; OPCODE_BREAK; } @@ -1353,7 +1289,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } OPCODE(OPCODE_YIELD_RESUME) { - CHECK_SPACE(2); #ifdef DEBUG_ENABLED if (!p_state) { @@ -1368,7 +1303,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_JUMP) { - CHECK_SPACE(2); int to = _code_ptr[ip + 1]; @@ -1378,7 +1312,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_JUMP_IF) { - CHECK_SPACE(3); GET_VARIANT_PTR(test, 1); @@ -1396,7 +1329,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_JUMP_IF_NOT) { - CHECK_SPACE(3); GET_VARIANT_PTR(test, 1); @@ -1414,14 +1346,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_JUMP_TO_DEF_ARGUMENT) { - CHECK_SPACE(2); ip = _default_arg_ptr[defarg]; } DISPATCH_OPCODE; OPCODE(OPCODE_RETURN) { - CHECK_SPACE(2); GET_VARIANT_PTR(r, 1); retvalue = *r; @@ -1432,7 +1362,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } OPCODE(OPCODE_ITERATE_BEGIN) { - CHECK_SPACE(8); //space for this a regular iterate GET_VARIANT_PTR(counter, 1); @@ -1465,7 +1394,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ITERATE) { - CHECK_SPACE(4); GET_VARIANT_PTR(counter, 1); @@ -1541,15 +1469,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a bool do_break = false; if (EngineDebugger::get_script_debugger()->get_lines_left() > 0) { - - if (EngineDebugger::get_script_debugger()->get_depth() <= 0) + if (EngineDebugger::get_script_debugger()->get_depth() <= 0) { EngineDebugger::get_script_debugger()->set_lines_left(EngineDebugger::get_script_debugger()->get_lines_left() - 1); - if (EngineDebugger::get_script_debugger()->get_lines_left() <= 0) + } + if (EngineDebugger::get_script_debugger()->get_lines_left() <= 0) { do_break = true; + } } - if (EngineDebugger::get_script_debugger()->is_breakpoint(line, source)) + if (EngineDebugger::get_script_debugger()->is_breakpoint(line, source)) { do_break = true; + } if (do_break) { GDScriptLanguage::get_singleton()->debug_break("Breakpoint", true); @@ -1577,20 +1507,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODES_END #ifdef DEBUG_ENABLED - if (exit_ok) + if (exit_ok) { OPCODE_OUT; + } //error // function, file, line, error, explanation String err_file; - if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->path != "") + if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->path != "") { err_file = p_instance->script->path; - else if (script) + } else if (script) { err_file = script->path; - if (err_file == "") + } + if (err_file == "") { err_file = "<built-in>"; + } String err_func = name; - if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->name != "") + if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->name != "") { err_func = p_instance->script->name + "." + err_func; + } int err_line = line; if (err_text == "") { err_text = "Internal Script Error! - opcode #" + itos(last_opcode) + " (report please)."; @@ -1622,14 +1556,16 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a // When it's the last resume it will postpone the exit from stack, // so the debugger knows which function triggered the resume of the next function (if any) if (!p_state || yielded) { - if (EngineDebugger::is_active()) + if (EngineDebugger::is_active()) { GDScriptLanguage::get_singleton()->exit_function(); + } #endif if (_stack_size) { //free stack - for (int i = 0; i < _stack_size; i++) + for (int i = 0; i < _stack_size; i++) { stack[i].~Variant(); + } } #ifdef DEBUG_ENABLED @@ -1640,32 +1576,28 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } const int *GDScriptFunction::get_code() const { - return _code_ptr; } -int GDScriptFunction::get_code_size() const { +int GDScriptFunction::get_code_size() const { return _code_size; } Variant GDScriptFunction::get_constant(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, constants.size(), "<errconst>"); return constants[p_idx]; } StringName GDScriptFunction::get_global_name(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, global_names.size(), "<errgname>"); return global_names[p_idx]; } int GDScriptFunction::get_default_argument_count() const { - return _default_arg_count; } -int GDScriptFunction::get_default_argument_addr(int p_idx) const { +int GDScriptFunction::get_default_argument_addr(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, default_arguments.size(), -1); return default_arguments[p_idx]; } @@ -1680,45 +1612,38 @@ GDScriptDataType GDScriptFunction::get_argument_type(int p_idx) const { } StringName GDScriptFunction::get_name() const { - return name; } int GDScriptFunction::get_max_stack_size() const { - return _stack_size; } struct _GDFKC { - int order; List<int> pos; }; struct _GDFKCS { - int order; StringName id; int pos; bool operator<(const _GDFKCS &p_r) const { - return order < p_r.order; } }; void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<StringName, int>> *r_stackvars) const { - int oc = 0; Map<StringName, _GDFKC> sdmap; for (const List<StackDebug>::Element *E = stack_debug.front(); E; E = E->next()) { - const StackDebug &sd = E->get(); - if (sd.line > p_line) + if (sd.line > p_line) { break; + } if (sd.added) { - if (!sdmap.has(sd.identifier)) { _GDFKC d; d.order = oc++; @@ -1729,18 +1654,17 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String sdmap[sd.identifier].pos.push_back(sd.pos); } } else { - ERR_CONTINUE(!sdmap.has(sd.identifier)); sdmap[sd.identifier].pos.pop_back(); - if (sdmap[sd.identifier].pos.empty()) + if (sdmap[sd.identifier].pos.empty()) { sdmap.erase(sd.identifier); + } } } List<_GDFKCS> stackpositions; for (Map<StringName, _GDFKC>::Element *E = sdmap.front(); E; E = E->next()) { - _GDFKCS spp; spp.id = E->key(); spp.order = E->get().order; @@ -1751,7 +1675,6 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String stackpositions.sort(); for (List<_GDFKCS>::Element *E = stackpositions.front(); E; E = E->next()) { - Pair<StringName, int> p; p.first = E->get().id; p.second = E->get().pos; @@ -1761,13 +1684,12 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String GDScriptFunction::GDScriptFunction() : function_list(this) { - _stack_size = 0; _call_size = 0; rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; name = "<anonymous>"; #ifdef DEBUG_ENABLED - _func_cname = NULL; + _func_cname = nullptr; { MutexLock lock(GDScriptLanguage::get_singleton()->lock); @@ -1800,7 +1722,6 @@ GDScriptFunction::~GDScriptFunction() { ///////////////////// Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - Variant arg; r_error.error = Callable::CallError::CALL_OK; @@ -1833,33 +1754,53 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar } bool GDScriptFunctionState::is_valid(bool p_extended_check) const { - - if (function == NULL) + if (function == nullptr) { return false; + } if (p_extended_check) { - //class instance gone? - if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id)) + MutexLock lock(GDScriptLanguage::get_singleton()->lock); + + // Script gone? + if (!scripts_list.in_list()) { return false; + } + // Class instance gone? (if not static function) + if (state.instance && !instances_list.in_list()) { + return false; + } } return true; } Variant GDScriptFunctionState::resume(const Variant &p_arg) { - ERR_FAIL_COND_V(!function, Variant()); - if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id)) { + { + MutexLock lock(GDScriptLanguage::singleton->lock); + + if (!scripts_list.in_list()) { #ifdef DEBUG_ENABLED - ERR_FAIL_V_MSG(Variant(), "Resumed function '" + String(function->get_name()) + "()' after yield, but class instance is gone. At script: " + state.script->get_path() + ":" + itos(state.line)); + ERR_FAIL_V_MSG(Variant(), "Resumed function '" + state.function_name + "()' after yield, but script is gone. At script: " + state.script_path + ":" + itos(state.line)); #else - return Variant(); + return Variant(); +#endif + } + if (state.instance && !instances_list.in_list()) { +#ifdef DEBUG_ENABLED + ERR_FAIL_V_MSG(Variant(), "Resumed function '" + state.function_name + "()' after yield, but class instance is gone. At script: " + state.script_path + ":" + itos(state.line)); +#else + return Variant(); #endif + } + // Do these now to avoid locking again after the call + scripts_list.remove_from_list(); + instances_list.remove_from_list(); } state.result = p_arg; Callable::CallError err; - Variant ret = function->call(NULL, NULL, 0, err, &state); + Variant ret = function->call(nullptr, nullptr, 0, err, &state); bool completed = true; @@ -1873,7 +1814,7 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { } } - function = NULL; //cleaned up; + function = nullptr; //cleaned up; state.result = Variant(); if (completed) { @@ -1884,13 +1825,8 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { } #ifdef DEBUG_ENABLED - if (EngineDebugger::is_active()) + if (EngineDebugger::is_active()) { GDScriptLanguage::get_singleton()->exit_function(); - if (state.stack_size) { - //free stack - Variant *stack = (Variant *)state.stack.ptr(); - for (int i = 0; i < state.stack_size; i++) - stack[i].~Variant(); } #endif } @@ -1898,8 +1834,17 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { return ret; } -void GDScriptFunctionState::_bind_methods() { +void GDScriptFunctionState::_clear_stack() { + if (state.stack_size) { + Variant *stack = (Variant *)state.stack.ptr(); + for (int i = 0; i < state.stack_size; i++) { + stack[i].~Variant(); + } + state.stack_size = 0; + } +} +void GDScriptFunctionState::_bind_methods() { ClassDB::bind_method(D_METHOD("resume", "arg"), &GDScriptFunctionState::resume, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("is_valid", "extended_check"), &GDScriptFunctionState::is_valid, DEFVAL(false)); ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &GDScriptFunctionState::_signal_callback, MethodInfo("_signal_callback")); @@ -1907,18 +1852,18 @@ void GDScriptFunctionState::_bind_methods() { ADD_SIGNAL(MethodInfo("completed", PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); } -GDScriptFunctionState::GDScriptFunctionState() { - - function = NULL; +GDScriptFunctionState::GDScriptFunctionState() : + scripts_list(this), + instances_list(this) { + function = nullptr; } GDScriptFunctionState::~GDScriptFunctionState() { + _clear_stack(); - if (function != NULL) { - //never called, deinitialize stack - for (int i = 0; i < state.stack_size; i++) { - Variant *v = (Variant *)&state.stack[sizeof(Variant) * i]; - v->~Variant(); - } + { + MutexLock lock(GDScriptLanguage::singleton->lock); + scripts_list.remove_from_list(); + instances_list.remove_from_list(); } } diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 0afffcac73..583eab744a 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -43,20 +43,25 @@ class GDScriptInstance; class GDScript; struct GDScriptDataType { - bool has_type; - enum { + enum Kind { UNINITIALIZED, BUILTIN, NATIVE, SCRIPT, GDSCRIPT, - } kind; - Variant::Type builtin_type; + }; + + Kind kind = UNINITIALIZED; + + bool has_type = false; + Variant::Type builtin_type = Variant::NIL; StringName native_type; Ref<Script> script_type; bool is_type(const Variant &p_variant, bool p_allow_implicit_conversion = false) const { - if (!has_type) return true; // Can't type check + if (!has_type) { + return true; // Can't type check + } switch (kind) { case UNINITIALIZED: @@ -105,7 +110,7 @@ struct GDScriptDataType { return false; } - Ref<Script> base = obj && obj->get_script_instance() ? obj->get_script_instance()->get_script() : NULL; + Ref<Script> base = obj && obj->get_script_instance() ? obj->get_script_instance()->get_script() : nullptr; bool valid = false; while (base.is_valid()) { if (base == script_type) { @@ -146,10 +151,7 @@ struct GDScriptDataType { return info; } - GDScriptDataType() : - has_type(false), - kind(UNINITIALIZED), - builtin_type(Variant::NIL) {} + GDScriptDataType() {} }; class GDScriptFunction { @@ -214,7 +216,6 @@ public: }; struct StackDebug { - int line; int pos; bool added; @@ -292,14 +293,16 @@ private: public: struct CallState { - - ObjectID instance_id; + GDScript *script; GDScriptInstance *instance; +#ifdef DEBUG_ENABLED + StringName function_name; + String script_path; +#endif Vector<uint8_t> stack; int stack_size; Variant self; uint32_t alloca_size; - Ref<GDScript> script; int ip; int line; int defarg; @@ -339,7 +342,7 @@ public: return default_arguments[p_idx]; } - Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state = NULL); + Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state = nullptr); _FORCE_INLINE_ MultiplayerAPI::RPCMode get_rpc_mode() const { return rpc_mode; } GDScriptFunction(); @@ -347,7 +350,6 @@ public: }; class GDScriptFunctionState : public Reference { - GDCLASS(GDScriptFunctionState, Reference); friend class GDScriptFunction; GDScriptFunction *function; @@ -355,12 +357,18 @@ class GDScriptFunctionState : public Reference { Variant _signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error); Ref<GDScriptFunctionState> first_state; + SelfList<GDScriptFunctionState> scripts_list; + SelfList<GDScriptFunctionState> instances_list; + protected: static void _bind_methods(); public: bool is_valid(bool p_extended_check = false) const; Variant resume(const Variant &p_arg = Variant()); + + void _clear_stack(); + GDScriptFunctionState(); ~GDScriptFunctionState(); }; diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index aaa308f40f..d4258c385e 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -41,7 +41,6 @@ #include "gdscript.h" const char *GDScriptFunctions::get_func_name(Function p_func) { - ERR_FAIL_INDEX_V(p_func, FUNC_MAX, ""); static const char *_names[FUNC_MAX] = { @@ -140,7 +139,6 @@ const char *GDScriptFunctions::get_func_name(Function p_func) { } void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_count, Variant &r_ret, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_OK; #ifdef DEBUG_ENABLED @@ -176,7 +174,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ //using a switch, so the compiler generates a jumptable switch (p_func) { - case MATH_SIN: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); @@ -269,15 +266,12 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case MATH_ABS: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() == Variant::INT) { - int64_t i = *p_args[0]; r_ret = ABS(i); } else if (p_args[0]->get_type() == Variant::FLOAT) { - double r = *p_args[0]; r_ret = Math::abs(r); } else { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::FLOAT; @@ -287,15 +281,12 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case MATH_SIGN: { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() == Variant::INT) { - int64_t i = *p_args[0]; r_ret = i < 0 ? -1 : (i > 0 ? +1 : 0); } else if (p_args[0]->get_type() == Variant::FLOAT) { - real_t r = *p_args[0]; r_ret = r < 0.0 ? -1.0 : (r > 0.0 ? +1.0 : 0.0); } else { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::FLOAT; @@ -362,13 +353,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ const double t = (double)*p_args[2]; switch (p_args[0]->get_type() == p_args[1]->get_type() ? p_args[0]->get_type() : Variant::FLOAT) { case Variant::VECTOR2: { - r_ret = ((Vector2)*p_args[0]).linear_interpolate((Vector2)*p_args[1], t); + r_ret = ((Vector2)*p_args[0]).lerp((Vector2)*p_args[1], t); } break; case Variant::VECTOR3: { - r_ret = (p_args[0]->operator Vector3()).linear_interpolate(p_args[1]->operator Vector3(), t); + r_ret = (p_args[0]->operator Vector3()).lerp(p_args[1]->operator Vector3(), t); } break; case Variant::COLOR: { - r_ret = ((Color)*p_args[0]).linear_interpolate((Color)*p_args[1], t); + r_ret = ((Color)*p_args[0]).lerp((Color)*p_args[1], t); } break; default: { VALIDATE_ARG_NUM(0); @@ -505,7 +496,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case LOGIC_MAX: { VALIDATE_ARG_COUNT(2); if (p_args[0]->get_type() == Variant::INT && p_args[1]->get_type() == Variant::INT) { - int64_t a = *p_args[0]; int64_t b = *p_args[1]; r_ret = MAX(a, b); @@ -523,7 +513,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case LOGIC_MIN: { VALIDATE_ARG_COUNT(2); if (p_args[0]->get_type() == Variant::INT && p_args[1]->get_type() == Variant::INT) { - int64_t a = *p_args[0]; int64_t b = *p_args[1]; r_ret = MIN(a, b); @@ -540,7 +529,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case LOGIC_CLAMP: { VALIDATE_ARG_COUNT(3); if (p_args[0]->get_type() == Variant::INT && p_args[1]->get_type() == Variant::INT && p_args[2]->get_type() == Variant::INT) { - int64_t a = *p_args[0]; int64_t b = *p_args[1]; int64_t c = *p_args[2]; @@ -595,7 +583,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case FUNC_FUNCREF: { VALIDATE_ARG_COUNT(2); if (p_args[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -603,7 +590,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ return; } if (p_args[1]->get_type() != Variant::STRING && p_args[1]->get_type() != Variant::NODE_PATH) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; r_error.expected = Variant::STRING; @@ -624,7 +610,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ VALIDATE_ARG_NUM(1); int type = *p_args[1]; if (type < 0 || type >= Variant::VARIANT_MAX) { - r_ret = RTR("Invalid type argument to convert(), use TYPE_* constants."); r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -632,18 +617,15 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ return; } else { - r_ret = Variant::construct(Variant::Type(type), p_args, 1, r_error); } } break; case TYPE_OF: { - VALIDATE_ARG_COUNT(1); r_ret = p_args[0]->get_type(); } break; case TYPE_EXISTS: { - VALIDATE_ARG_COUNT(1); r_ret = ClassDB::class_exists(*p_args[0]); @@ -655,11 +637,9 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = String(result); } break; case TEXT_ORD: { - VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() != Variant::STRING) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::STRING; @@ -670,7 +650,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ String str = p_args[0]->operator String(); if (str.length() != 1) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::STRING; @@ -691,23 +670,21 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } String str; for (int i = 0; i < p_arg_count; i++) { - String os = p_args[i]->operator String(); - if (i == 0) + if (i == 0) { str = os; - else + } else { str += os; + } } r_ret = str; } break; case TEXT_PRINT: { - String str; for (int i = 0; i < p_arg_count; i++) { - str += p_args[i]->operator String(); } @@ -716,12 +693,11 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case TEXT_PRINT_TABBED: { - String str; for (int i = 0; i < p_arg_count; i++) { - - if (i) + if (i) { str += "\t"; + } str += p_args[i]->operator String(); } @@ -730,12 +706,11 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case TEXT_PRINT_SPACED: { - String str; for (int i = 0; i < p_arg_count; i++) { - - if (i) + if (i) { str += " "; + } str += p_args[i]->operator String(); } @@ -745,10 +720,8 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case TEXT_PRINTERR: { - String str; for (int i = 0; i < p_arg_count; i++) { - str += p_args[i]->operator String(); } @@ -759,7 +732,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case TEXT_PRINTRAW: { String str; for (int i = 0; i < p_arg_count; i++) { - str += p_args[i]->operator String(); } @@ -770,7 +742,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case TEXT_PRINT_DEBUG: { String str; for (int i = 0; i < p_arg_count; i++) { - str += p_args[i]->operator String(); } @@ -858,7 +829,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ PackedByteArray barr; int len; - Error err = encode_variant(*p_args[0], NULL, len, full_objects); + Error err = encode_variant(*p_args[0], nullptr, len, full_objects); if (err) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -908,7 +879,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ Variant ret; { const uint8_t *r = varr.ptr(); - Error err = decode_variant(ret, r, varr.size(), NULL, allow_objects); + Error err = decode_variant(ret, r, varr.size(), nullptr, allow_objects); if (err != OK) { r_ret = RTR("Not enough bytes for decoding bytes, or invalid format."); r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; @@ -922,18 +893,14 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case GEN_RANGE: { - switch (p_arg_count) { - case 0: { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 1; r_ret = Variant(); } break; case 1: { - VALIDATE_ARG_NUM(0); int count = *p_args[0]; Array arr; @@ -955,7 +922,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = arr; } break; case 2: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); @@ -973,12 +939,12 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = Variant(); return; } - for (int i = from; i < to; i++) + for (int i = from; i < to; i++) { arr[i - from] = i; + } r_ret = arr; } break; case 3: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); @@ -987,7 +953,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ int to = *p_args[1]; int incr = *p_args[2]; if (incr == 0) { - r_ret = RTR("Step argument is zero!"); r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; return; @@ -1006,10 +971,8 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ //calculate how many int count = 0; if (incr > 0) { - count = ((to - from - 1) / incr) + 1; } else { - count = ((from - to - 1) / -incr) + 1; } @@ -1027,7 +990,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ arr[idx++] = i; } } else { - int idx = 0; for (int i = from; i > to; i += incr) { arr[idx++] = i; @@ -1037,7 +999,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = arr; } break; default: { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument = 3; r_ret = Variant(); @@ -1059,7 +1020,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case INST2DICT: { - VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() == Variant::NIL) { @@ -1069,24 +1029,20 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_error.argument = 0; r_ret = Variant(); } else { - Object *obj = *p_args[0]; if (!obj) { r_ret = Variant(); } else if (!obj->get_script_instance() || obj->get_script_instance()->get_language() != GDScriptLanguage::get_singleton()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::DICTIONARY; r_ret = RTR("Not a script with an instance"); return; } else { - GDScriptInstance *ins = static_cast<GDScriptInstance *>(obj->get_script_instance()); Ref<GDScript> base = ins->get_script(); if (base.is_null()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::DICTIONARY; @@ -1098,7 +1054,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ Vector<StringName> sname; while (p->_owner) { - sname.push_back(p->name); p = p->_owner; } @@ -1132,11 +1087,9 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case DICT2INST: { - VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() != Variant::DICTIONARY) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::DICTIONARY; @@ -1148,7 +1101,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ Dictionary d = *p_args[0]; if (!d.has("@path")) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -1159,7 +1111,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ Ref<Script> scr = ResourceLoader::load(d["@path"]); if (!scr.is_valid()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -1170,7 +1121,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ Ref<GDScript> gdscr = scr; if (!gdscr.is_valid()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -1185,10 +1135,8 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } for (int i = 0; i < sub.get_name_count(); i++) { - gdscr = gdscr->subclasses[sub.get_name(i)]; if (!gdscr.is_valid()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -1197,8 +1145,12 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ return; } } + r_ret = gdscr->_new(nullptr, -1 /*skip initializer*/, r_error); - r_ret = gdscr->_new(NULL, 0, r_error); + if (r_error.error != Callable::CallError::CALL_OK) { + r_ret = Variant(); + return; + } GDScriptInstance *ins = static_cast<GDScriptInstance *>(static_cast<Object *>(r_ret)->get_script_instance()); Ref<GDScript> gd_ref = ins->get_script(); @@ -1211,7 +1163,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case VALIDATE_JSON: { - VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() != Variant::STRING) { @@ -1235,7 +1186,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case PARSE_JSON: { - VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() != Variant::STRING) { @@ -1263,13 +1213,11 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = JSON::print(*p_args[0]); } break; case HASH: { - VALIDATE_ARG_COUNT(1); r_ret = p_args[0]->hash(); } break; case COLOR8: { - if (p_arg_count < 3) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 3; @@ -1300,7 +1248,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case COLORN: { - if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 1; @@ -1335,7 +1282,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ ScriptLanguage *script = GDScriptLanguage::get_singleton(); for (int i = 0; i < script->debug_get_stack_level_count(); i++) { - print_line("Frame " + itos(i) + " - " + script->debug_get_stack_level_source(i) + ":" + itos(script->debug_get_stack_level_line(i)) + " in function '" + script->debug_get_stack_level_function(i) + "'"); }; } break; @@ -1346,7 +1292,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ ScriptLanguage *script = GDScriptLanguage::get_singleton(); Array ret; for (int i = 0; i < script->debug_get_stack_level_count(); i++) { - Dictionary frame; frame["source"] = script->debug_get_stack_level_source(i); frame["function"] = script->debug_get_stack_level_function(i); @@ -1357,7 +1302,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case INSTANCE_FROM_ID: { - VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() != Variant::INT && p_args[0]->get_type() != Variant::FLOAT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; @@ -1372,66 +1316,53 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case LEN: { - VALIDATE_ARG_COUNT(1); switch (p_args[0]->get_type()) { case Variant::STRING: { - String d = *p_args[0]; r_ret = d.length(); } break; case Variant::DICTIONARY: { - Dictionary d = *p_args[0]; r_ret = d.size(); } break; case Variant::ARRAY: { - Array d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_BYTE_ARRAY: { - Vector<uint8_t> d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_INT32_ARRAY: { - Vector<int32_t> d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_INT64_ARRAY: { - Vector<int64_t> d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_FLOAT32_ARRAY: { - Vector<float> d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_FLOAT64_ARRAY: { - Vector<double> d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_STRING_ARRAY: { - Vector<String> d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_VECTOR2_ARRAY: { - Vector<Vector2> d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_VECTOR3_ARRAY: { - Vector<Vector3> d = *p_args[0]; r_ret = d.size(); } break; case Variant::PACKED_COLOR_ARRAY: { - Vector<Color> d = *p_args[0]; r_ret = d.size(); } break; @@ -1446,7 +1377,6 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case IS_INSTANCE_VALID: { - VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() != Variant::OBJECT) { r_ret = false; @@ -1457,19 +1387,16 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case FUNC_MAX: { - ERR_FAIL(); } break; } } bool GDScriptFunctions::is_deterministic(Function p_func) { - //man i couldn't have chosen a worse function name, //way too controversial.. switch (p_func) { - case MATH_SIN: case MATH_COS: case MATH_TAN: @@ -1533,12 +1460,10 @@ bool GDScriptFunctions::is_deterministic(Function p_func) { } MethodInfo GDScriptFunctions::get_info(Function p_func) { - #ifdef DEBUG_ENABLED //using a switch, so the compiler generates a jumptable switch (p_func) { - case MATH_SIN: { MethodInfo mi("sin", PropertyInfo(Variant::FLOAT, "s")); mi.return_val.type = Variant::FLOAT; @@ -1813,7 +1738,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { return mi; } break; case OBJ_WEAKREF: { - MethodInfo mi("weakref", PropertyInfo(Variant::OBJECT, "obj")); mi.return_val.type = Variant::OBJECT; mi.return_val.class_name = "WeakRef"; @@ -1822,7 +1746,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case FUNC_FUNCREF: { - MethodInfo mi("funcref", PropertyInfo(Variant::OBJECT, "instance"), PropertyInfo(Variant::STRING, "funcname")); mi.return_val.type = Variant::OBJECT; mi.return_val.class_name = "FuncRef"; @@ -1830,42 +1753,36 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case TYPE_CONVERT: { - MethodInfo mi("convert", PropertyInfo(Variant::NIL, "what", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), PropertyInfo(Variant::INT, "type")); mi.return_val.type = Variant::NIL; mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; return mi; } break; case TYPE_OF: { - MethodInfo mi("typeof", PropertyInfo(Variant::NIL, "what", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT)); mi.return_val.type = Variant::INT; return mi; } break; case TYPE_EXISTS: { - MethodInfo mi("type_exists", PropertyInfo(Variant::STRING, "type")); mi.return_val.type = Variant::BOOL; return mi; } break; case TEXT_CHAR: { - MethodInfo mi("char", PropertyInfo(Variant::INT, "code")); mi.return_val.type = Variant::STRING; return mi; } break; case TEXT_ORD: { - MethodInfo mi("ord", PropertyInfo(Variant::STRING, "char")); mi.return_val.type = Variant::INT; return mi; } break; case TEXT_STR: { - MethodInfo mi("str"); mi.return_val.type = Variant::STRING; mi.flags |= METHOD_FLAG_VARARG; @@ -1873,7 +1790,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case TEXT_PRINT: { - MethodInfo mi("print"); mi.return_val.type = Variant::NIL; mi.flags |= METHOD_FLAG_VARARG; @@ -1881,7 +1797,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case TEXT_PRINT_TABBED: { - MethodInfo mi("printt"); mi.return_val.type = Variant::NIL; mi.flags |= METHOD_FLAG_VARARG; @@ -1889,7 +1804,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case TEXT_PRINT_SPACED: { - MethodInfo mi("prints"); mi.return_val.type = Variant::NIL; mi.flags |= METHOD_FLAG_VARARG; @@ -1897,7 +1811,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case TEXT_PRINTERR: { - MethodInfo mi("printerr"); mi.return_val.type = Variant::NIL; mi.flags |= METHOD_FLAG_VARARG; @@ -1905,7 +1818,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case TEXT_PRINTRAW: { - MethodInfo mi("printraw"); mi.return_val.type = Variant::NIL; mi.flags |= METHOD_FLAG_VARARG; @@ -1913,7 +1825,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case TEXT_PRINT_DEBUG: { - MethodInfo mi("print_debug"); mi.return_val.type = Variant::NIL; mi.flags |= METHOD_FLAG_VARARG; @@ -1921,41 +1832,35 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case PUSH_ERROR: { - MethodInfo mi(Variant::NIL, "push_error", PropertyInfo(Variant::STRING, "message")); mi.return_val.type = Variant::NIL; return mi; } break; case PUSH_WARNING: { - MethodInfo mi(Variant::NIL, "push_warning", PropertyInfo(Variant::STRING, "message")); mi.return_val.type = Variant::NIL; return mi; } break; case VAR_TO_STR: { - MethodInfo mi("var2str", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT)); mi.return_val.type = Variant::STRING; return mi; } break; case STR_TO_VAR: { - MethodInfo mi(Variant::NIL, "str2var", PropertyInfo(Variant::STRING, "string")); mi.return_val.type = Variant::NIL; mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; return mi; } break; case VAR_TO_BYTES: { - MethodInfo mi("var2bytes", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), PropertyInfo(Variant::BOOL, "full_objects")); mi.default_arguments.push_back(false); mi.return_val.type = Variant::PACKED_BYTE_ARRAY; return mi; } break; case BYTES_TO_VAR: { - MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytes"), PropertyInfo(Variant::BOOL, "allow_objects")); mi.default_arguments.push_back(false); mi.return_val.type = Variant::NIL; @@ -1963,65 +1868,55 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { return mi; } break; case GEN_RANGE: { - MethodInfo mi("range"); mi.return_val.type = Variant::ARRAY; mi.flags |= METHOD_FLAG_VARARG; return mi; } break; case RESOURCE_LOAD: { - MethodInfo mi("load", PropertyInfo(Variant::STRING, "path")); mi.return_val.type = Variant::OBJECT; mi.return_val.class_name = "Resource"; return mi; } break; case INST2DICT: { - MethodInfo mi("inst2dict", PropertyInfo(Variant::OBJECT, "inst")); mi.return_val.type = Variant::DICTIONARY; return mi; } break; case DICT2INST: { - MethodInfo mi("dict2inst", PropertyInfo(Variant::DICTIONARY, "dict")); mi.return_val.type = Variant::OBJECT; return mi; } break; case VALIDATE_JSON: { - MethodInfo mi("validate_json", PropertyInfo(Variant::STRING, "json")); mi.return_val.type = Variant::STRING; return mi; } break; case PARSE_JSON: { - MethodInfo mi(Variant::NIL, "parse_json", PropertyInfo(Variant::STRING, "json")); mi.return_val.type = Variant::NIL; mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; return mi; } break; case TO_JSON: { - MethodInfo mi("to_json", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT)); mi.return_val.type = Variant::STRING; return mi; } break; case HASH: { - MethodInfo mi("hash", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT)); mi.return_val.type = Variant::INT; return mi; } break; case COLOR8: { - MethodInfo mi("Color8", PropertyInfo(Variant::INT, "r8"), PropertyInfo(Variant::INT, "g8"), PropertyInfo(Variant::INT, "b8"), PropertyInfo(Variant::INT, "a8")); mi.default_arguments.push_back(255); mi.return_val.type = Variant::COLOR; return mi; } break; case COLORN: { - MethodInfo mi("ColorN", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "alpha")); mi.default_arguments.push_back(1.0f); mi.return_val.type = Variant::COLOR; @@ -2055,7 +1950,6 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { return mi; } break; default: { - ERR_FAIL_V(MethodInfo()); } break; } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 7fcb2cc423..0e498f6895 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -42,14 +42,14 @@ template <class T> T *GDScriptParser::alloc_node() { - T *t = memnew(T); t->next = list; list = t; - if (!head) + if (!head) { head = t; + } t->line = tokenizer->get_token_line(); t->column = tokenizer->get_token_column(); @@ -61,7 +61,6 @@ static String _find_function_name(const GDScriptParser::OperatorNode *p_call); #endif // DEBUG_ENABLED bool GDScriptParser::_end_statement() { - if (tokenizer->get_token() == GDScriptTokenizer::TK_SEMICOLON) { tokenizer->advance(); return true; //handle next @@ -72,8 +71,17 @@ bool GDScriptParser::_end_statement() { return false; } -bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { +void GDScriptParser::_set_end_statement_error(String p_name) { + String error_msg; + if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER) { + error_msg = vformat("Expected end of statement (\"%s\"), got %s (\"%s\") instead.", p_name, tokenizer->get_token_name(tokenizer->get_token()), tokenizer->get_token_identifier()); + } else { + error_msg = vformat("Expected end of statement (\"%s\"), got %s instead.", p_name, tokenizer->get_token_name(tokenizer->get_token())); + } + _set_error(error_msg); +} +bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { if (tokenizer->get_token() != GDScriptTokenizer::TK_COLON) { // report location at the previous token (on the previous line) int error_line = tokenizer->get_token_line(-1); @@ -98,12 +106,10 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { while (true) { if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { - return false; //wtf } else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_EOF) { return false; } else if (tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) { - int indent = tokenizer->get_token_line_indent(); int tabs = tokenizer->get_token_line_tab_indent(); IndentLevel current_level = indent_level.back()->get(); @@ -122,7 +128,6 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { return true; } else if (p_block) { - NewLineNode *nl = alloc_node<NewLineNode>(); nl->line = tokenizer->get_token_line(); p_block->statements.push_back(nl); @@ -133,16 +138,13 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { } bool GDScriptParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete, bool p_parsing_constant) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { tokenizer->advance(); } else { - parenthesis++; int argidx = 0; while (true) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) { _make_completable_call(argidx); completion_node = p_parent; @@ -168,9 +170,7 @@ bool GDScriptParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bo break; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { - if (tokenizer->get_token(1) == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { - _set_error("Expression expected"); return false; } @@ -190,7 +190,6 @@ bool GDScriptParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bo } void GDScriptParser::_make_completable_call(int p_arg) { - completion_cursor = StringName(); completion_type = COMPLETION_CALL_ARGUMENTS; completion_class = current_class; @@ -203,14 +202,12 @@ void GDScriptParser::_make_completable_call(int p_arg) { } bool GDScriptParser::_get_completable_identifier(CompletionType p_type, StringName &identifier) { - identifier = StringName(); if (tokenizer->is_token_literal()) { identifier = tokenizer->get_token_literal(); tokenizer->advance(); } if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) { - completion_cursor = identifier; completion_type = p_type; completion_class = current_class; @@ -236,18 +233,16 @@ bool GDScriptParser::_get_completable_identifier(CompletionType p_type, StringNa } GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign, bool p_parsing_constant) { - //Vector<Node*> expressions; //Vector<OperatorNode::Operator> operators; Vector<Expression> expression; - Node *expr = NULL; + Node *expr = nullptr; int op_line = tokenizer->get_token_line(); // when operators are created at the bottom, the line might have been changed (\n found) while (true) { - /*****************/ /* Parse Operand */ /*****************/ @@ -275,13 +270,13 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s parenthesis++; Node *subexpr = _parse_expression(p_parent, p_static, p_allow_assign, p_parsing_constant); parenthesis--; - if (!subexpr) - return NULL; + if (!subexpr) { + return nullptr; + } if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' in expression"); - return NULL; + return nullptr; } tokenizer->advance(); @@ -296,7 +291,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s int line = tokenizer->get_token_line(); while (!done) { - switch (tokenizer->get_token()) { case GDScriptTokenizer::TK_CURSOR: { completion_type = COMPLETION_GET_NODE; @@ -310,7 +304,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(); } break; case GDScriptTokenizer::TK_CONSTANT: { - if (!need_identifier) { done = true; break; @@ -318,7 +311,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (tokenizer->get_token_constant().get_type() != Variant::STRING) { _set_error("Expected string constant or identifier after '$' or '/'."); - return NULL; + return nullptr; } path += String(tokenizer->get_token_constant()); @@ -327,7 +320,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } break; case GDScriptTokenizer::TK_OP_DIV: { - if (need_identifier) { done = true; break; @@ -355,7 +347,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (path == "") { _set_error("Path expected after $."); - return NULL; + return nullptr; } OperatorNode *op = alloc_node<OperatorNode>(); @@ -382,7 +374,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s continue; //no point in cursor in the middle of expression } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT) { - //constant defined by tokenizer ConstantNode *constant = alloc_node<ConstantNode>(); constant->value = tokenizer->get_token_constant(); @@ -390,7 +381,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(); expr = constant; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONST_PI) { - //constant defined by tokenizer ConstantNode *constant = alloc_node<ConstantNode>(); constant->value = Math_PI; @@ -398,7 +388,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(); expr = constant; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONST_TAU) { - //constant defined by tokenizer ConstantNode *constant = alloc_node<ConstantNode>(); constant->value = Math_TAU; @@ -406,7 +395,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(); expr = constant; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONST_INF) { - //constant defined by tokenizer ConstantNode *constant = alloc_node<ConstantNode>(); constant->value = Math_INF; @@ -414,7 +402,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(); expr = constant; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONST_NAN) { - //constant defined by tokenizer ConstantNode *constant = alloc_node<ConstantNode>(); constant->value = Math_NAN; @@ -422,12 +409,11 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(); expr = constant; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_PRELOAD) { - //constant defined by tokenizer tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) { _set_error("Expected '(' after 'preload'"); - return NULL; + return nullptr; } tokenizer->advance(); @@ -476,23 +462,22 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (!valid) { _set_error("expected string constant as 'preload' argument."); - return NULL; + return nullptr; } - if (!path.is_abs_path() && base_path != "") + if (!path.is_abs_path() && base_path != "") { path = base_path.plus_file(path); + } path = path.replace("///", "//").simplify_path(); if (path == self_path) { - _set_error("Can't preload itself (use 'get_script()')."); - return NULL; + return nullptr; } Ref<Resource> res; dependencies.push_back(path); if (!dependencies_only) { if (!validating) { - //this can be too slow for just validating code if (for_completion && ScriptCodeCompletionCache::get_singleton() && FileAccess::exists(path)) { res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path); @@ -500,29 +485,28 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s res = ResourceLoader::load(path); } } else { - if (!FileAccess::exists(path)) { _set_error("Can't preload resource at path: " + path); - return NULL; + return nullptr; } else if (ScriptCodeCompletionCache::get_singleton()) { res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path); } } if (!res.is_valid()) { _set_error("Can't preload resource at path: " + path); - return NULL; + return nullptr; } } if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ')' after 'preload' path"); - return NULL; + return nullptr; } Ref<GDScript> gds = res; if (gds.is_valid() && !gds->is_valid()) { _set_error("Couldn't fully preload the script, possible cyclic reference or compilation error. Use \"load()\" instead if a cyclic reference is intended."); - return NULL; + return nullptr; } tokenizer->advance(); @@ -533,10 +517,9 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = constant; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_YIELD) { - if (!current_function) { _set_error("\"yield()\" can only be used inside function blocks."); - return NULL; + return nullptr; } current_function->has_yield = true; @@ -544,7 +527,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) { _set_error("Expected \"(\" after \"yield\"."); - return NULL; + return nullptr; } tokenizer->advance(); @@ -560,23 +543,22 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = yield; tokenizer->advance(); } else { - parenthesis++; Node *object = _parse_and_reduce_expression(p_parent, p_static); - if (!object) - return NULL; + if (!object) { + return nullptr; + } yield->arguments.push_back(object); if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { _set_error("Expected \",\" after the first argument of \"yield\"."); - return NULL; + return nullptr; } tokenizer->advance(); if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) { - completion_cursor = StringName(); completion_node = object; completion_type = COMPLETION_YIELD; @@ -590,13 +572,14 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } Node *signal = _parse_and_reduce_expression(p_parent, p_static); - if (!signal) - return NULL; + if (!signal) { + return nullptr; + } yield->arguments.push_back(signal); if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected \")\" after the second argument of \"yield\"."); - return NULL; + return nullptr; } parenthesis--; @@ -607,38 +590,32 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } } else if (tokenizer->get_token() == GDScriptTokenizer::TK_SELF) { - if (p_static) { _set_error("\"self\" isn't allowed in a static function or constant expression."); - return NULL; + return nullptr; } //constant defined by tokenizer SelfNode *self = alloc_node<SelfNode>(); tokenizer->advance(); expr = self; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE && tokenizer->get_token(1) == GDScriptTokenizer::TK_PERIOD) { - Variant::Type bi_type = tokenizer->get_token_type(); tokenizer->advance(2); StringName identifier; if (_get_completable_identifier(COMPLETION_BUILT_IN_TYPE_CONSTANT, identifier)) { - completion_built_in_constant = bi_type; } if (identifier == StringName()) { - _set_error("Built-in type constant or static function expected after \".\"."); - return NULL; + return nullptr; } if (!Variant::has_constant(bi_type, identifier)) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN && Variant::is_method_const(bi_type, identifier) && Variant::get_method_return_type(bi_type, identifier) == bi_type) { - tokenizer->advance(); OperatorNode *construct = alloc_node<OperatorNode>(); @@ -656,8 +633,9 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s id->name = identifier; op->arguments.push_back(id); - if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant)) - return NULL; + if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant)) { + return nullptr; + } expr = op; } else { @@ -674,11 +652,10 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } if (!valid) { _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); - return NULL; + return nullptr; } } } else { - ConstantNode *cn = alloc_node<ConstantNode>(); cn->value = Variant::get_constant_value(bi_type, identifier); cn->datatype = _type_from_variant(cn->value); @@ -723,13 +700,11 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(2); } } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_FUNC) { - BuiltInFunctionNode *bn = alloc_node<BuiltInFunctionNode>(); bn->function = tokenizer->get_token_built_in_func(); op->arguments.push_back(bn); tokenizer->advance(2); } else { - SelfNode *self = alloc_node<SelfNode>(); op->arguments.push_back(self); @@ -746,10 +721,18 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) { _make_completable_call(0); completion_node = op; + + if (op->arguments[0]->type == GDScriptParser::Node::Type::TYPE_BUILT_IN_FUNCTION) { + BuiltInFunctionNode *bn = static_cast<BuiltInFunctionNode *>(op->arguments[0]); + if (bn->function == GDScriptFunctions::Function::RESOURCE_LOAD) { + completion_type = COMPLETION_RESOURCE_PATH; + } + } } if (!replaced) { - if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant)) - return NULL; + if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant)) { + return nullptr; + } expr = op; } } else if (tokenizer->is_token_literal(0, true)) { @@ -789,7 +772,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (lv->assignments == 0) { if (!lv->datatype.has_type) { _set_error("Using assignment with operation on a variable that was never assigned."); - return NULL; + return nullptr; } _add_warning(GDScriptWarning::UNASSIGNED_VARIABLE_OP_ASSIGN, -1, identifier.operator String()); } @@ -827,6 +810,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s //check from singletons ConstantNode *constant = alloc_node<ConstantNode>(); constant->value = GDScriptLanguage::get_singleton()->get_named_globals_map()[identifier]; + constant->datatype = _type_from_variant(constant->value); expr = constant; bfn = true; } @@ -837,6 +821,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (scr.is_valid() && scr->is_valid()) { ConstantNode *constant = alloc_node<ConstantNode>(); constant->value = scr; + constant->datatype = _type_from_variant(constant->value); expr = constant; bfn = true; } @@ -852,6 +837,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (parent_constants.has(identifier)) { ConstantNode *constant = alloc_node<ConstantNode>(); constant->value = parent_constants[identifier]; + constant->datatype = _type_from_variant(constant->value); expr = constant; bfn = true; } @@ -893,17 +879,24 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } } else if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ADD || tokenizer->get_token() == GDScriptTokenizer::TK_OP_SUB || tokenizer->get_token() == GDScriptTokenizer::TK_OP_NOT || tokenizer->get_token() == GDScriptTokenizer::TK_OP_BIT_INVERT) { - //single prefix operators like !expr +expr -expr ++expr --expr alloc_node<OperatorNode>(); Expression e; e.is_op = true; switch (tokenizer->get_token()) { - case GDScriptTokenizer::TK_OP_ADD: e.op = OperatorNode::OP_POS; break; - case GDScriptTokenizer::TK_OP_SUB: e.op = OperatorNode::OP_NEG; break; - case GDScriptTokenizer::TK_OP_NOT: e.op = OperatorNode::OP_NOT; break; - case GDScriptTokenizer::TK_OP_BIT_INVERT: e.op = OperatorNode::OP_BIT_INVERT; break; + case GDScriptTokenizer::TK_OP_ADD: + e.op = OperatorNode::OP_POS; + break; + case GDScriptTokenizer::TK_OP_SUB: + e.op = OperatorNode::OP_NEG; + break; + case GDScriptTokenizer::TK_OP_NOT: + e.op = OperatorNode::OP_NOT; + break; + case GDScriptTokenizer::TK_OP_BIT_INVERT: + e.op = OperatorNode::OP_BIT_INVERT; + break; default: { } } @@ -912,7 +905,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (e.op != OperatorNode::OP_NOT && tokenizer->get_token() == GDScriptTokenizer::TK_OP_NOT) { _set_error("Misplaced 'not'."); - return NULL; + return nullptr; } expression.push_back(e); @@ -921,7 +914,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s /* Node *subexpr=_parse_expression(op,p_static); if (!subexpr) - return NULL; + return nullptr; op->arguments.push_back(subexpr); expr=op;*/ @@ -929,7 +922,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s // 'is' operator with built-in type if (!expr) { _set_error("Expected identifier before 'is' operator"); - return NULL; + return nullptr; } OperatorNode *op = alloc_node<OperatorNode>(); op->op = OperatorNode::OP_IS_BUILTIN; @@ -951,22 +944,19 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s bool expecting_comma = false; while (true) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) { - _set_error("Unterminated array"); - return NULL; + return nullptr; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_CLOSE) { tokenizer->advance(); break; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) { - tokenizer->advance(); //ignore newline } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { if (!expecting_comma) { _set_error("expression or ']' expected"); - return NULL; + return nullptr; } expecting_comma = false; @@ -975,11 +965,12 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s //parse expression if (expecting_comma) { _set_error("',' or ']' expected"); - return NULL; + return nullptr; } Node *n = _parse_expression(arr, p_static, p_allow_assign, p_parsing_constant); - if (!n) - return NULL; + if (!n) { + return nullptr; + } arr->elements.push_back(n); expecting_comma = true; } @@ -1001,81 +992,73 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s }; - Node *key = NULL; + Node *key = nullptr; Set<Variant> keys; DictExpect expecting = DICT_EXPECT_KEY; while (true) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) { - _set_error("Unterminated dictionary"); - return NULL; + return nullptr; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) { - if (expecting == DICT_EXPECT_COLON) { _set_error("':' expected"); - return NULL; + return nullptr; } if (expecting == DICT_EXPECT_VALUE) { _set_error("value expected"); - return NULL; + return nullptr; } tokenizer->advance(); break; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) { - tokenizer->advance(); //ignore newline } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { - if (expecting == DICT_EXPECT_KEY) { _set_error("key or '}' expected"); - return NULL; + return nullptr; } if (expecting == DICT_EXPECT_VALUE) { _set_error("value expected"); - return NULL; + return nullptr; } if (expecting == DICT_EXPECT_COLON) { _set_error("':' expected"); - return NULL; + return nullptr; } expecting = DICT_EXPECT_KEY; tokenizer->advance(); //ignore newline } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) { - if (expecting == DICT_EXPECT_KEY) { _set_error("key or '}' expected"); - return NULL; + return nullptr; } if (expecting == DICT_EXPECT_VALUE) { _set_error("value expected"); - return NULL; + return nullptr; } if (expecting == DICT_EXPECT_COMMA) { _set_error("',' or '}' expected"); - return NULL; + return nullptr; } expecting = DICT_EXPECT_VALUE; tokenizer->advance(); //ignore newline } else { - if (expecting == DICT_EXPECT_COMMA) { _set_error("',' or '}' expected"); - return NULL; + return nullptr; } if (expecting == DICT_EXPECT_COLON) { _set_error("':' expected"); - return NULL; + return nullptr; } if (expecting == DICT_EXPECT_KEY) { - if (tokenizer->is_token_literal() && tokenizer->get_token(1) == GDScriptTokenizer::TK_OP_ASSIGN) { // We check with is_token_literal, as this allows us to use match/sync/etc. as a name //lua style identifier, easier to write @@ -1088,16 +1071,18 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } else { //python/js style more flexible key = _parse_expression(dict, p_static, p_allow_assign, p_parsing_constant); - if (!key) - return NULL; + if (!key) { + return nullptr; + } expecting = DICT_EXPECT_COLON; } } if (expecting == DICT_EXPECT_VALUE) { Node *value = _parse_expression(dict, p_static, p_allow_assign, p_parsing_constant); - if (!value) - return NULL; + if (!value) { + return nullptr; + } expecting = DICT_EXPECT_COMMA; if (key->type == GDScriptParser::Node::TYPE_CONSTANT) { @@ -1105,7 +1090,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (keys.has(keyName)) { _set_error("Duplicate key found in Dictionary literal"); - return NULL; + return nullptr; } keys.insert(keyName); } @@ -1114,7 +1099,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s pair.key = key; pair.value = value; dict->elements.push_back(pair); - key = NULL; + key = nullptr; } } } @@ -1142,12 +1127,12 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) { if (!is_completion) { _set_error("Expected '(' for parent function call."); - return NULL; + return nullptr; } } else { tokenizer->advance(); if (!_parse_arguments(op, op->arguments, p_static, false, p_parsing_constant)) { - return NULL; + return nullptr; } } @@ -1163,30 +1148,27 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = tn; tokenizer->advance(); } else { - //find list [ or find dictionary { _set_error("Error parsing expression, misplaced: " + String(tokenizer->get_token_name(tokenizer->get_token()))); - return NULL; //nothing + return nullptr; //nothing } - ERR_FAIL_COND_V_MSG(!expr, NULL, "GDScriptParser bug, couldn't figure out what expression is."); + ERR_FAIL_COND_V_MSG(!expr, nullptr, "GDScriptParser bug, couldn't figure out what expression is."); /******************/ /* Parse Indexing */ /******************/ while (true) { - //expressions can be indexed any number of times if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD) { - //indexing using "." if (tokenizer->get_token(1) != GDScriptTokenizer::TK_CURSOR && !tokenizer->is_token_literal(1)) { // We check with is_token_literal, as this allows us to use match/sync/etc. as a name _set_error("Expected identifier as member"); - return NULL; + return nullptr; } else if (tokenizer->get_token(2) == GDScriptTokenizer::TK_PARENTHESIS_OPEN) { //call!! OperatorNode *op = alloc_node<OperatorNode>(); @@ -1211,8 +1193,9 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s _make_completable_call(0); completion_node = op; } - if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant)) - return NULL; + if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant)) { + return nullptr; + } expr = op; } else { @@ -1224,7 +1207,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s StringName identifier; if (_get_completable_identifier(COMPLETION_INDEX, identifier)) { - if (identifier == StringName()) { identifier = "@temp"; //so it parses alright } @@ -1251,12 +1233,12 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s Node *subexpr = _parse_expression(op, p_static, p_allow_assign, p_parsing_constant); if (!subexpr) { - return NULL; + return nullptr; } if (tokenizer->get_token() != GDScriptTokenizer::TK_BRACKET_CLOSE) { _set_error("Expected ']'"); - return NULL; + return nullptr; } op->arguments.push_back(expr); @@ -1264,8 +1246,9 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s tokenizer->advance(1); expr = op; - } else + } else { break; + } } /*****************/ @@ -1276,12 +1259,12 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_AS) { if (has_casting) { _set_error("Unexpected 'as'."); - return NULL; + return nullptr; } CastNode *cn = alloc_node<CastNode>(); if (!_parse_type(cn->cast_type)) { _set_error("Expected type after 'as'."); - return NULL; + return nullptr; } has_casting = true; cn->source_node = expr; @@ -1313,31 +1296,61 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s #define _VALIDATE_ASSIGN \ if (!p_allow_assign || has_casting) { \ _set_error("Unexpected assign."); \ - return NULL; \ + return nullptr; \ } \ p_allow_assign = false; switch (tokenizer->get_token()) { //see operator - case GDScriptTokenizer::TK_OP_IN: op = OperatorNode::OP_IN; break; - case GDScriptTokenizer::TK_OP_EQUAL: op = OperatorNode::OP_EQUAL; break; - case GDScriptTokenizer::TK_OP_NOT_EQUAL: op = OperatorNode::OP_NOT_EQUAL; break; - case GDScriptTokenizer::TK_OP_LESS: op = OperatorNode::OP_LESS; break; - case GDScriptTokenizer::TK_OP_LESS_EQUAL: op = OperatorNode::OP_LESS_EQUAL; break; - case GDScriptTokenizer::TK_OP_GREATER: op = OperatorNode::OP_GREATER; break; - case GDScriptTokenizer::TK_OP_GREATER_EQUAL: op = OperatorNode::OP_GREATER_EQUAL; break; - case GDScriptTokenizer::TK_OP_AND: op = OperatorNode::OP_AND; break; - case GDScriptTokenizer::TK_OP_OR: op = OperatorNode::OP_OR; break; - case GDScriptTokenizer::TK_OP_ADD: op = OperatorNode::OP_ADD; break; - case GDScriptTokenizer::TK_OP_SUB: op = OperatorNode::OP_SUB; break; - case GDScriptTokenizer::TK_OP_MUL: op = OperatorNode::OP_MUL; break; - case GDScriptTokenizer::TK_OP_DIV: op = OperatorNode::OP_DIV; break; + case GDScriptTokenizer::TK_OP_IN: + op = OperatorNode::OP_IN; + break; + case GDScriptTokenizer::TK_OP_EQUAL: + op = OperatorNode::OP_EQUAL; + break; + case GDScriptTokenizer::TK_OP_NOT_EQUAL: + op = OperatorNode::OP_NOT_EQUAL; + break; + case GDScriptTokenizer::TK_OP_LESS: + op = OperatorNode::OP_LESS; + break; + case GDScriptTokenizer::TK_OP_LESS_EQUAL: + op = OperatorNode::OP_LESS_EQUAL; + break; + case GDScriptTokenizer::TK_OP_GREATER: + op = OperatorNode::OP_GREATER; + break; + case GDScriptTokenizer::TK_OP_GREATER_EQUAL: + op = OperatorNode::OP_GREATER_EQUAL; + break; + case GDScriptTokenizer::TK_OP_AND: + op = OperatorNode::OP_AND; + break; + case GDScriptTokenizer::TK_OP_OR: + op = OperatorNode::OP_OR; + break; + case GDScriptTokenizer::TK_OP_ADD: + op = OperatorNode::OP_ADD; + break; + case GDScriptTokenizer::TK_OP_SUB: + op = OperatorNode::OP_SUB; + break; + case GDScriptTokenizer::TK_OP_MUL: + op = OperatorNode::OP_MUL; + break; + case GDScriptTokenizer::TK_OP_DIV: + op = OperatorNode::OP_DIV; + break; case GDScriptTokenizer::TK_OP_MOD: op = OperatorNode::OP_MOD; break; //case GDScriptTokenizer::TK_OP_NEG: op=OperatorNode::OP_NEG ; break; - case GDScriptTokenizer::TK_OP_SHIFT_LEFT: op = OperatorNode::OP_SHIFT_LEFT; break; - case GDScriptTokenizer::TK_OP_SHIFT_RIGHT: op = OperatorNode::OP_SHIFT_RIGHT; break; + case GDScriptTokenizer::TK_OP_SHIFT_LEFT: + op = OperatorNode::OP_SHIFT_LEFT; + break; + case GDScriptTokenizer::TK_OP_SHIFT_RIGHT: + op = OperatorNode::OP_SHIFT_RIGHT; + break; case GDScriptTokenizer::TK_OP_ASSIGN: { _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN; @@ -1354,23 +1367,57 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } } break; - case GDScriptTokenizer::TK_OP_ASSIGN_ADD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_ADD; break; - case GDScriptTokenizer::TK_OP_ASSIGN_SUB: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SUB; break; - case GDScriptTokenizer::TK_OP_ASSIGN_MUL: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MUL; break; - case GDScriptTokenizer::TK_OP_ASSIGN_DIV: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_DIV; break; - case GDScriptTokenizer::TK_OP_ASSIGN_MOD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MOD; break; - case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_LEFT: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_LEFT; break; - case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_RIGHT: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_RIGHT; break; - case GDScriptTokenizer::TK_OP_ASSIGN_BIT_AND: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_AND; break; - case GDScriptTokenizer::TK_OP_ASSIGN_BIT_OR: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_OR; break; - case GDScriptTokenizer::TK_OP_ASSIGN_BIT_XOR: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_XOR; break; - case GDScriptTokenizer::TK_OP_BIT_AND: op = OperatorNode::OP_BIT_AND; break; - case GDScriptTokenizer::TK_OP_BIT_OR: op = OperatorNode::OP_BIT_OR; break; - case GDScriptTokenizer::TK_OP_BIT_XOR: op = OperatorNode::OP_BIT_XOR; break; - case GDScriptTokenizer::TK_PR_IS: op = OperatorNode::OP_IS; break; - case GDScriptTokenizer::TK_CF_IF: op = OperatorNode::OP_TERNARY_IF; break; - case GDScriptTokenizer::TK_CF_ELSE: op = OperatorNode::OP_TERNARY_ELSE; break; - default: valid = false; break; + case GDScriptTokenizer::TK_OP_ASSIGN_ADD: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_ADD; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_SUB: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SUB; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_MUL: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MUL; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_DIV: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_DIV; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_MOD: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MOD; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_LEFT: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_LEFT; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_RIGHT: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_RIGHT; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_AND: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_AND; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_OR: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_OR; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_XOR: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_XOR; + break; + case GDScriptTokenizer::TK_OP_BIT_AND: + op = OperatorNode::OP_BIT_AND; + break; + case GDScriptTokenizer::TK_OP_BIT_OR: + op = OperatorNode::OP_BIT_OR; + break; + case GDScriptTokenizer::TK_OP_BIT_XOR: + op = OperatorNode::OP_BIT_XOR; + break; + case GDScriptTokenizer::TK_PR_IS: + op = OperatorNode::OP_IS; + break; + case GDScriptTokenizer::TK_CF_IF: + op = OperatorNode::OP_TERNARY_IF; + break; + case GDScriptTokenizer::TK_CF_ELSE: + op = OperatorNode::OP_TERNARY_ELSE; + break; + default: + valid = false; + break; } if (valid) { @@ -1386,16 +1433,13 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ while (expression.size() > 1) { - int next_op = -1; int min_priority = 0xFFFFF; bool is_unary = false; bool is_ternary = false; for (int i = 0; i < expression.size(); i++) { - if (!expression[i].is_op) { - continue; } @@ -1407,7 +1451,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s bool right_to_left = false; switch (expression[i].op) { - case OperatorNode::OP_IS: case OperatorNode::OP_IS_BUILTIN: priority = -1; @@ -1423,36 +1466,74 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s unary = true; break; - case OperatorNode::OP_MUL: priority = 2; break; - case OperatorNode::OP_DIV: priority = 2; break; - case OperatorNode::OP_MOD: priority = 2; break; + case OperatorNode::OP_MUL: + priority = 2; + break; + case OperatorNode::OP_DIV: + priority = 2; + break; + case OperatorNode::OP_MOD: + priority = 2; + break; - case OperatorNode::OP_ADD: priority = 3; break; - case OperatorNode::OP_SUB: priority = 3; break; + case OperatorNode::OP_ADD: + priority = 3; + break; + case OperatorNode::OP_SUB: + priority = 3; + break; - case OperatorNode::OP_SHIFT_LEFT: priority = 4; break; - case OperatorNode::OP_SHIFT_RIGHT: priority = 4; break; + case OperatorNode::OP_SHIFT_LEFT: + priority = 4; + break; + case OperatorNode::OP_SHIFT_RIGHT: + priority = 4; + break; - case OperatorNode::OP_BIT_AND: priority = 5; break; - case OperatorNode::OP_BIT_XOR: priority = 6; break; - case OperatorNode::OP_BIT_OR: priority = 7; break; + case OperatorNode::OP_BIT_AND: + priority = 5; + break; + case OperatorNode::OP_BIT_XOR: + priority = 6; + break; + case OperatorNode::OP_BIT_OR: + priority = 7; + break; - case OperatorNode::OP_LESS: priority = 8; break; - case OperatorNode::OP_LESS_EQUAL: priority = 8; break; - case OperatorNode::OP_GREATER: priority = 8; break; - case OperatorNode::OP_GREATER_EQUAL: priority = 8; break; + case OperatorNode::OP_LESS: + priority = 8; + break; + case OperatorNode::OP_LESS_EQUAL: + priority = 8; + break; + case OperatorNode::OP_GREATER: + priority = 8; + break; + case OperatorNode::OP_GREATER_EQUAL: + priority = 8; + break; - case OperatorNode::OP_EQUAL: priority = 8; break; - case OperatorNode::OP_NOT_EQUAL: priority = 8; break; + case OperatorNode::OP_EQUAL: + priority = 8; + break; + case OperatorNode::OP_NOT_EQUAL: + priority = 8; + break; - case OperatorNode::OP_IN: priority = 10; break; + case OperatorNode::OP_IN: + priority = 10; + break; case OperatorNode::OP_NOT: priority = 11; unary = true; break; - case OperatorNode::OP_AND: priority = 12; break; - case OperatorNode::OP_OR: priority = 13; break; + case OperatorNode::OP_AND: + priority = 12; + break; + case OperatorNode::OP_OR: + priority = 13; + break; case OperatorNode::OP_TERNARY_IF: priority = 14; @@ -1465,21 +1546,43 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s // Rigth-to-left should be false in this case, otherwise it would always error. break; - case OperatorNode::OP_ASSIGN: priority = 15; break; - case OperatorNode::OP_ASSIGN_ADD: priority = 15; break; - case OperatorNode::OP_ASSIGN_SUB: priority = 15; break; - case OperatorNode::OP_ASSIGN_MUL: priority = 15; break; - case OperatorNode::OP_ASSIGN_DIV: priority = 15; break; - case OperatorNode::OP_ASSIGN_MOD: priority = 15; break; - case OperatorNode::OP_ASSIGN_SHIFT_LEFT: priority = 15; break; - case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: priority = 15; break; - case OperatorNode::OP_ASSIGN_BIT_AND: priority = 15; break; - case OperatorNode::OP_ASSIGN_BIT_OR: priority = 15; break; - case OperatorNode::OP_ASSIGN_BIT_XOR: priority = 15; break; + case OperatorNode::OP_ASSIGN: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_ADD: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_SUB: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_MUL: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_DIV: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_MOD: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_SHIFT_LEFT: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_BIT_AND: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_BIT_OR: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_BIT_XOR: + priority = 15; + break; default: { _set_error("GDScriptParser bug, invalid operator in expression: " + itos(expression[i].op)); - return NULL; + return nullptr; } } @@ -1488,7 +1591,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s // <= is used for right to left if (error) { _set_error("Unexpected operator"); - return NULL; + return nullptr; } next_op = i; min_priority = priority; @@ -1498,28 +1601,24 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } if (next_op == -1) { - _set_error("Yet another parser bug...."); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } // OK! create operator.. if (is_unary) { - int expr_pos = next_op; while (expression[expr_pos].is_op) { - expr_pos++; if (expr_pos == expression.size()) { //can happen.. _set_error("Unexpected end of expression..."); - return NULL; + return nullptr; } } //consecutively do unary operators for (int i = expr_pos - 1; i >= next_op; i--) { - OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; op->arguments.push_back(expression[i + 1].node); @@ -1532,16 +1631,16 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } else if (is_ternary) { if (next_op < 1 || next_op >= (expression.size() - 1)) { _set_error("Parser bug..."); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } if (next_op >= (expression.size() - 2) || expression[next_op + 2].op != OperatorNode::OP_TERNARY_ELSE) { _set_error("Expected else after ternary if."); - return NULL; + return nullptr; } if (next_op >= (expression.size() - 3)) { _set_error("Expected value after ternary else."); - return NULL; + return nullptr; } OperatorNode *op = alloc_node<OperatorNode>(); @@ -1549,9 +1648,8 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s op->line = op_line; //line might have been changed from a \n if (expression[next_op - 1].is_op) { - _set_error("Parser bug..."); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } if (expression[next_op + 1].is_op) { @@ -1561,7 +1659,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s // due to how precedence works, unaries will always disappear first _set_error("Unexpected two consecutive operators after ternary if."); - return NULL; + return nullptr; } if (expression[next_op + 3].is_op) { @@ -1571,7 +1669,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s // due to how precedence works, unaries will always disappear first _set_error("Unexpected two consecutive operators after ternary else."); - return NULL; + return nullptr; } op->arguments.push_back(expression[next_op + 1].node); //next expression goes as first @@ -1585,10 +1683,9 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expression.remove(next_op); expression.remove(next_op); } else { - if (next_op < 1 || next_op >= (expression.size() - 1)) { _set_error("Parser bug..."); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } OperatorNode *op = alloc_node<OperatorNode>(); @@ -1596,9 +1693,8 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s op->line = op_line; //line might have been changed from a \n if (expression[next_op - 1].is_op) { - _set_error("Parser bug..."); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } if (expression[next_op + 1].is_op) { @@ -1608,7 +1704,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s // due to how precedence works, unaries will always disappear first _set_error("Unexpected two consecutive operators."); - return NULL; + return nullptr; } op->arguments.push_back(expression[next_op - 1].node); //expression goes as left @@ -1625,23 +1721,20 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to_const) { - switch (p_node->type) { - case Node::TYPE_BUILT_IN_FUNCTION: { //many may probably be optimizable return p_node; } break; case Node::TYPE_ARRAY: { - ArrayNode *an = static_cast<ArrayNode *>(p_node); bool all_constants = true; for (int i = 0; i < an->elements.size(); i++) { - an->elements.write[i] = _reduce_expression(an->elements[i], p_to_const); - if (an->elements[i]->type != Node::TYPE_CONSTANT) + if (an->elements[i]->type != Node::TYPE_CONSTANT) { all_constants = false; + } } if (all_constants && p_to_const) { @@ -1663,18 +1756,18 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to } break; case Node::TYPE_DICTIONARY: { - DictionaryNode *dn = static_cast<DictionaryNode *>(p_node); bool all_constants = true; for (int i = 0; i < dn->elements.size(); i++) { - dn->elements.write[i].key = _reduce_expression(dn->elements[i].key, p_to_const); - if (dn->elements[i].key->type != Node::TYPE_CONSTANT) + if (dn->elements[i].key->type != Node::TYPE_CONSTANT) { all_constants = false; + } dn->elements.write[i].value = _reduce_expression(dn->elements[i].value, p_to_const); - if (dn->elements[i].value->type != Node::TYPE_CONSTANT) + if (dn->elements[i].value->type != Node::TYPE_CONSTANT) { all_constants = false; + } } if (all_constants && p_to_const) { @@ -1697,14 +1790,12 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to } break; case Node::TYPE_OPERATOR: { - OperatorNode *op = static_cast<OperatorNode *>(p_node); bool all_constants = true; int last_not_constant = -1; for (int i = 0; i < op->arguments.size(); i++) { - op->arguments.write[i] = _reduce_expression(op->arguments[i], p_to_const); if (op->arguments[i]->type != Node::TYPE_CONSTANT) { all_constants = false; @@ -1723,15 +1814,12 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to } else if (op->op == OperatorNode::OP_CALL) { //can reduce base type constructors if ((op->arguments[0]->type == Node::TYPE_TYPE || (op->arguments[0]->type == Node::TYPE_BUILT_IN_FUNCTION && GDScriptFunctions::is_deterministic(static_cast<BuiltInFunctionNode *>(op->arguments[0])->function))) && last_not_constant == 0) { - //native type constructor or intrinsic function - const Variant **vptr = NULL; + const Variant **vptr = nullptr; Vector<Variant *> ptrs; if (op->arguments.size() > 1) { - ptrs.resize(op->arguments.size() - 1); for (int i = 0; i < ptrs.size(); i++) { - ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[i + 1]); ptrs.write[i] = &cn->value; } @@ -1752,7 +1840,6 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to } if (ce.error != Callable::CallError::CALL_OK) { - String errwhere; if (op->arguments[0]->type == Node::TYPE_TYPE) { TypeNode *tn = static_cast<TypeNode *>(op->arguments[0]); @@ -1764,18 +1851,14 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to } switch (ce.error) { - case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { - _set_error("Invalid argument (#" + itos(ce.argument + 1) + ") for " + errwhere + "."); } break; case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { - _set_error("Too many arguments for " + errwhere + "."); } break; case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: { - _set_error("Too few arguments for " + errwhere + "."); } break; default: { @@ -1804,7 +1887,6 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to //can reduce indices into constant arrays or dictionaries if (all_constants) { - ConstantNode *ca = static_cast<ConstantNode *>(op->arguments[0]); ConstantNode *cb = static_cast<ConstantNode *>(op->arguments[1]); @@ -1826,9 +1908,7 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to return op; } else if (op->op == OperatorNode::OP_INDEX_NAMED) { - if (op->arguments[0]->type == Node::TYPE_CONSTANT && op->arguments[1]->type == Node::TYPE_IDENTIFIER) { - ConstantNode *ca = static_cast<ConstantNode *>(op->arguments[0]); IdentifierNode *ib = static_cast<IdentifierNode *>(op->arguments[1]); @@ -1851,7 +1931,6 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to //validate assignment (don't assign to constant expression switch (op->op) { - case OperatorNode::OP_ASSIGN: case OperatorNode::OP_ASSIGN_ADD: case OperatorNode::OP_ASSIGN_SUB: @@ -1863,7 +1942,6 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to case OperatorNode::OP_ASSIGN_BIT_AND: case OperatorNode::OP_ASSIGN_BIT_OR: case OperatorNode::OP_ASSIGN_BIT_XOR: { - if (op->arguments[0]->type == Node::TYPE_CONSTANT) { _set_error("Can't assign to constant", tokenizer->get_token_line() - 1); error_line = op->line; @@ -1889,8 +1967,9 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to } } //now se if all are constants - if (!all_constants) + if (!all_constants) { return op; //nothing to reduce from here on + } #define _REDUCE_UNARY(m_vop) \ bool valid = false; \ Variant res; \ @@ -1920,7 +1999,6 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to return cn; switch (op->op) { - //unary operators case OperatorNode::OP_NEG: { _REDUCE_UNARY(Variant::OP_NEGATE); @@ -2012,18 +2090,53 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to } GDScriptParser::Node *GDScriptParser::_parse_and_reduce_expression(Node *p_parent, bool p_static, bool p_reduce_const, bool p_allow_assign) { - Node *expr = _parse_expression(p_parent, p_static, p_allow_assign, p_reduce_const); - if (!expr || error_set) - return NULL; + if (!expr || error_set) { + return nullptr; + } expr = _reduce_expression(expr, p_reduce_const); - if (!expr || error_set) - return NULL; + if (!expr || error_set) { + return nullptr; + } return expr; } -bool GDScriptParser::_recover_from_completion() { +bool GDScriptParser::_reduce_export_var_type(Variant &p_value, int p_line) { + if (p_value.get_type() == Variant::ARRAY) { + Array arr = p_value; + for (int i = 0; i < arr.size(); i++) { + if (!_reduce_export_var_type(arr[i], p_line)) { + return false; + } + } + return true; + } + + if (p_value.get_type() == Variant::DICTIONARY) { + Dictionary dict = p_value; + for (int i = 0; i < dict.size(); i++) { + Variant value = dict.get_value_at_index(i); + if (!_reduce_export_var_type(value, p_line)) { + return false; + } + } + return true; + } + // validate type + DataType type = _type_from_variant(p_value); + if (type.kind == DataType::BUILTIN) { + return true; + } else if (type.kind == DataType::NATIVE) { + if (ClassDB::is_parent_class(type.native_type, "Resource")) { + return true; + } + } + _set_error("Invalid export type. Only built-in and native resource types can be exported.", p_line); + return false; +} + +bool GDScriptParser::_recover_from_completion() { if (!completion_found) { return false; //can't recover if no completion } @@ -2041,15 +2154,15 @@ bool GDScriptParser::_recover_from_completion() { } GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { - PatternNode *pattern = alloc_node<PatternNode>(); GDScriptTokenizer::Token token = tokenizer->get_token(); - if (error_set) - return NULL; + if (error_set) { + return nullptr; + } if (token == GDScriptTokenizer::TK_EOF) { - return NULL; + return nullptr; } switch (token) { @@ -2058,7 +2171,6 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { tokenizer->advance(); pattern->pt_type = GDScriptParser::PatternNode::PT_ARRAY; while (true) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_CLOSE) { tokenizer->advance(); break; @@ -2078,13 +2190,13 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { break; } else { _set_error("'..' pattern only allowed at the end of an array pattern"); - return NULL; + return nullptr; } } PatternNode *sub_pattern = _parse_pattern(p_static); if (!sub_pattern) { - return NULL; + return nullptr; } pattern->array.push_back(sub_pattern); @@ -2097,7 +2209,7 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { break; } else { _set_error("Not a valid pattern"); - return NULL; + return nullptr; } } } break; @@ -2106,7 +2218,7 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { tokenizer->advance(); if (!tokenizer->is_token_literal()) { _set_error("Expected identifier for binding variable name."); - return NULL; + return nullptr; } pattern->pt_type = GDScriptParser::PatternNode::PT_BIND; pattern->bind = tokenizer->get_token_literal(); @@ -2115,7 +2227,7 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { while (bl) { if (bl->variables.has(pattern->bind)) { _set_error("Binding name of '" + pattern->bind.operator String() + "' is already declared in this scope."); - return NULL; + return nullptr; } bl = bl->parent_block; } @@ -2130,7 +2242,6 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { tokenizer->advance(); pattern->pt_type = GDScriptParser::PatternNode::PT_DICTIONARY; while (true) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) { tokenizer->advance(); break; @@ -2150,19 +2261,19 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { break; } else { _set_error("'..' pattern only allowed at the end of a dictionary pattern"); - return NULL; + return nullptr; } } Node *key = _parse_and_reduce_expression(pattern, p_static); if (!key) { _set_error("Not a valid key in pattern"); - return NULL; + return nullptr; } if (key->type != GDScriptParser::Node::TYPE_CONSTANT) { _set_error("Not a constant expression as key"); - return NULL; + return nullptr; } if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) { @@ -2171,12 +2282,12 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { PatternNode *value = _parse_pattern(p_static); if (!value) { _set_error("Expected pattern in dictionary value"); - return NULL; + return nullptr; } pattern->dictionary.insert(static_cast<ConstantNode *>(key), value); } else { - pattern->dictionary.insert(static_cast<ConstantNode *>(key), NULL); + pattern->dictionary.insert(static_cast<ConstantNode *>(key), nullptr); } if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { @@ -2187,7 +2298,7 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { break; } else { _set_error("Not a valid pattern"); - return NULL; + return nullptr; } } } break; @@ -2200,7 +2311,7 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { Node *value = _parse_and_reduce_expression(pattern, p_static); if (!value) { _set_error("Expect constant expression or variables in a pattern"); - return NULL; + return nullptr; } if (value->type == Node::TYPE_OPERATOR) { @@ -2212,19 +2323,19 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) { if (op_node->op != OperatorNode::OP_INDEX_NAMED) { _set_error("Invalid operator in pattern. Only index (`A.B`) is allowed"); - return NULL; + return nullptr; } current_value = op_node->arguments[0]; } if (current_value->type != Node::TYPE_IDENTIFIER) { _set_error("Only constant expression or variables allowed in a pattern"); - return NULL; + return nullptr; } } else if (value->type != Node::TYPE_IDENTIFIER && value->type != Node::TYPE_CONSTANT) { _set_error("Only constant expressions or variables allowed in a pattern"); - return NULL; + return nullptr; } pattern->pt_type = PatternNode::PT_CONSTANT; @@ -2243,13 +2354,14 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran bool catch_all_appeared = false; while (true) { - - while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline()) + while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline()) { ; + } // GDScriptTokenizer::Token token = tokenizer->get_token(); - if (error_set) + if (error_set) { return; + } if (current_level.indent > indent_level.back()->get().indent) { break; // go back a level @@ -2321,18 +2433,16 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran } void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match, Node *&p_resulting_node, Map<StringName, Node *> &p_bindings) { - const DataType &to_match_type = p_node_to_match->get_datatype(); switch (p_pattern->pt_type) { case PatternNode::PT_CONSTANT: { - DataType pattern_type = _reduce_node_type(p_pattern->constant); if (error_set) { return; } - OperatorNode *type_comp = NULL; + OperatorNode *type_comp = nullptr; // static type check if possible if (pattern_type.has_type && to_match_type.has_type) { @@ -2386,10 +2496,10 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m // a bind always matches ConstantNode *true_value = alloc_node<ConstantNode>(); true_value->value = Variant(true); + true_value->datatype = _type_from_variant(true_value->value); p_resulting_node = true_value; } break; case PatternNode::PT_ARRAY: { - bool open_ended = false; if (p_pattern->array.size() > 0) { @@ -2402,7 +2512,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m // typeof(value_to_match) == TYPE_ARRAY && value_to_match.size() == length { - OperatorNode *type_comp = NULL; + OperatorNode *type_comp = nullptr; // static type check if possible if (to_match_type.has_type) { // must be an array @@ -2432,6 +2542,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m // size ConstantNode *length = alloc_node<ConstantNode>(); length->value = Variant(open_ended ? p_pattern->array.size() - 1 : p_pattern->array.size()); + length->datatype = _type_from_variant(length->value); OperatorNode *call = alloc_node<OperatorNode>(); call->op = OperatorNode::OP_CALL; @@ -2461,10 +2572,11 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m for (int i = 0; i < p_pattern->array.size(); i++) { PatternNode *pattern = p_pattern->array[i]; - Node *condition = NULL; + Node *condition = nullptr; ConstantNode *index = alloc_node<ConstantNode>(); index->value = Variant(i); + index->datatype = _type_from_variant(index->value); OperatorNode *indexed_value = alloc_node<OperatorNode>(); indexed_value->op = OperatorNode::OP_INDEX; @@ -2484,7 +2596,6 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m } break; case PatternNode::PT_DICTIONARY: { - bool open_ended = false; if (p_pattern->array.size() > 0) { @@ -2495,7 +2606,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m // typeof(value_to_match) == TYPE_DICTIONARY && value_to_match.size() == length { - OperatorNode *type_comp = NULL; + OperatorNode *type_comp = nullptr; // static type check if possible if (to_match_type.has_type) { // must be an dictionary @@ -2525,6 +2636,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m // size ConstantNode *length = alloc_node<ConstantNode>(); length->value = Variant(open_ended ? p_pattern->dictionary.size() - 1 : p_pattern->dictionary.size()); + length->datatype = _type_from_variant(length->value); OperatorNode *call = alloc_node<OperatorNode>(); call->op = OperatorNode::OP_CALL; @@ -2552,8 +2664,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m } for (Map<ConstantNode *, PatternNode *>::Element *e = p_pattern->dictionary.front(); e; e = e->next()) { - - Node *condition = NULL; + Node *condition = nullptr; // check for has, then for pattern @@ -2567,7 +2678,6 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m has_call->arguments.push_back(e->key()); if (e->value()) { - OperatorNode *indexed_value = alloc_node<OperatorNode>(); indexed_value->op = OperatorNode::OP_INDEX; indexed_value->arguments.push_back(p_node_to_match); @@ -2601,10 +2711,10 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m // simply generate a `true` ConstantNode *true_value = alloc_node<ConstantNode>(); true_value->value = Variant(true); + true_value->datatype = _type_from_variant(true_value->value); p_resulting_node = true_value; } break; default: { - } break; } } @@ -2625,11 +2735,10 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) { } for (int i = 0; i < p_match_statement->branches.size(); i++) { - PatternBranchNode *branch = p_match_statement->branches[i]; MatchNode::CompiledPatternBranch compiled_branch; - compiled_branch.compiled_pattern = NULL; + compiled_branch.compiled_pattern = nullptr; Map<StringName, Node *> binding; @@ -2638,7 +2747,7 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) { _mark_line_as_safe(pattern->line); Map<StringName, Node *> bindings; - Node *resulting_node = NULL; + Node *resulting_node = nullptr; _generate_pattern(pattern, id, resulting_node, bindings); if (!resulting_node) { @@ -2683,9 +2792,11 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) { LocalVarNode *local_var = branch->body->variables[e->key()]; local_var->assign = e->value(); local_var->set_datatype(local_var->assign->get_datatype()); + local_var->assignments++; IdentifierNode *id2 = alloc_node<IdentifierNode>(); id2->name = local_var->name; + id2->datatype = local_var->datatype; id2->declared_block = branch->body; id2->set_datatype(local_var->assign->get_datatype()); @@ -2706,7 +2817,6 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) { } void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { - IndentLevel current_level = indent_level.back()->get(); #ifdef DEBUG_ENABLED @@ -2733,8 +2843,9 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { is_first_line = false; GDScriptTokenizer::Token token = tokenizer->get_token(); - if (error_set) + if (error_set) { return; + } if (current_level.indent > indent_level.back()->get().indent) { p_block->end_line = tokenizer->get_token_line(); @@ -2742,7 +2853,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } if (pending_newline != -1) { - NewLineNode *nl2 = alloc_node<NewLineNode>(); nl2->line = pending_newline; p_block->statements.push_back(nl2); @@ -2774,7 +2884,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { return; } break; case GDScriptTokenizer::TK_NEWLINE: { - int line = tokenizer->get_token_line(); if (!_parse_newline()) { @@ -2785,6 +2894,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { return; } + _mark_line_as_safe(line); NewLineNode *nl2 = alloc_node<NewLineNode>(); nl2->line = line; p_block->statements.push_back(nl2); @@ -2792,7 +2902,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } break; case GDScriptTokenizer::TK_CF_PASS: { if (tokenizer->get_token(1) != GDScriptTokenizer::TK_SEMICOLON && tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE && tokenizer->get_token(1) != GDScriptTokenizer::TK_EOF) { - _set_error("Expected \";\" or a line break."); return; } @@ -2809,7 +2918,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { tokenizer->advance(); int var_line = tokenizer->get_token_line(); if (!tokenizer->is_token_literal(0, true)) { - _set_error("Expected an identifier for the local variable name."); return; } @@ -2838,7 +2946,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { lv->line = var_line; p_block->statements.push_back(lv); - Node *assigned = NULL; + Node *assigned = nullptr; if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) { if (tokenizer->get_token(1) == GDScriptTokenizer::TK_OP_ASSIGN) { @@ -2854,7 +2962,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { - tokenizer->advance(); Node *subexpr = _parse_and_reduce_expression(p_block, p_static); if (!subexpr) { @@ -2867,7 +2974,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { lv->assignments++; assigned = subexpr; } else { - assigned = _get_default_value_for_type(lv->datatype, var_line); } //must be added later, to avoid self-referencing. @@ -2888,13 +2994,12 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { lv->assign = assigned; if (!_end_statement()) { - _set_error("Expected end of statement (\"var\")."); + _set_end_statement_error("var"); return; } } break; case GDScriptTokenizer::TK_CF_IF: { - tokenizer->advance(); Node *condition = _parse_and_reduce_expression(p_block, p_static); @@ -2926,17 +3031,18 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { _parse_block(cf_if->body, p_static); current_block = p_block; - if (error_set) + if (error_set) { return; + } p_block->statements.push_back(cf_if); bool all_have_return = cf_if->body->has_return; bool have_else = false; while (true) { - - while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline()) + while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline()) { ; + } if (indent_level.back()->get().indent < current_level.indent) { //not at current indent level p_block->end_line = tokenizer->get_token_line(); @@ -2944,9 +3050,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_CF_ELIF) { - if (indent_level.back()->get().indent > current_level.indent) { - _set_error("Invalid indentation."); return; } @@ -2986,13 +3090,13 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { current_block = cf_else->body; _parse_block(cf_else->body, p_static); current_block = p_block; - if (error_set) + if (error_set) { return; + } all_have_return = all_have_return && cf_else->body->has_return; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CF_ELSE) { - if (indent_level.back()->get().indent > current_level.indent) { _set_error("Invalid indentation."); return; @@ -3011,16 +3115,18 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { current_block = cf_if->body_else; _parse_block(cf_if->body_else, p_static); current_block = p_block; - if (error_set) + if (error_set) { return; + } all_have_return = all_have_return && cf_if->body_else->has_return; have_else = true; break; //after else, exit - } else + } else { break; + } } cf_if->body->has_return = all_have_return; @@ -3029,7 +3135,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } break; case GDScriptTokenizer::TK_CF_WHILE: { - tokenizer->advance(); Node *condition2 = _parse_and_reduce_expression(p_block, p_static); if (!condition2) { @@ -3046,6 +3151,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_while->body = alloc_node<BlockNode>(); cf_while->body->parent_block = p_block; + cf_while->body->can_break = true; + cf_while->body->can_continue = true; p_block->sub_blocks.push_back(cf_while->body); if (!_enter_indent_block(cf_while->body)) { @@ -3057,17 +3164,15 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { current_block = cf_while->body; _parse_block(cf_while->body, p_static); current_block = p_block; - if (error_set) + if (error_set) { return; - p_block->has_return = cf_while->body->has_return; + } p_block->statements.push_back(cf_while); } break; case GDScriptTokenizer::TK_CF_FOR: { - tokenizer->advance(); if (!tokenizer->is_token_literal(0, true)) { - _set_error("Identifier expected after \"for\"."); } @@ -3094,7 +3199,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { DataType iter_type; if (container->type == Node::TYPE_OPERATOR) { - OperatorNode *op = static_cast<OperatorNode *>(container); if (op->op == OperatorNode::OP_CALL && op->arguments[0]->type == Node::TYPE_BUILT_IN_FUNCTION && static_cast<BuiltInFunctionNode *>(op->arguments[0])->function == GDScriptFunctions::GEN_RANGE) { //iterating a range, so see if range() can be optimized without allocating memory, by replacing it by vectors (which can work as iterable too!) @@ -3110,22 +3214,27 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { ConstantNode *c = static_cast<ConstantNode *>(op->arguments[i]); if (c->value.get_type() == Variant::FLOAT || c->value.get_type() == Variant::INT) { constants.push_back(c->value); + } else { + constant = false; } } else { constant = false; - break; } } if (args.size() > 0 && args.size() < 4) { - if (constant) { - ConstantNode *cn = alloc_node<ConstantNode>(); switch (args.size()) { - case 1: cn->value = (int)constants[0]; break; - case 2: cn->value = Vector2(constants[0], constants[1]); break; - case 3: cn->value = Vector3(constants[0], constants[1], constants[2]); break; + case 1: + cn->value = (int64_t)constants[0]; + break; + case 2: + cn->value = Vector2i(constants[0], constants[1]); + break; + case 3: + cn->value = Vector3i(constants[0], constants[1], constants[2]); + break; } cn->datatype = _type_from_variant(cn->value); container = cn; @@ -3137,9 +3246,15 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { on->arguments.push_back(tn); switch (args.size()) { - case 1: tn->vtype = Variant::INT; break; - case 2: tn->vtype = Variant::VECTOR2; break; - case 3: tn->vtype = Variant::VECTOR3; break; + case 1: + tn->vtype = Variant::INT; + break; + case 2: + tn->vtype = Variant::VECTOR2I; + break; + case 3: + tn->vtype = Variant::VECTOR3I; + break; } for (int i = 0; i < args.size(); i++) { @@ -3164,6 +3279,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_for->body = alloc_node<BlockNode>(); cf_for->body->parent_block = p_block; + cf_for->body->can_break = true; + cf_for->body->can_continue = true; p_block->sub_blocks.push_back(cf_for->body); if (!_enter_indent_block(cf_for->body)) { @@ -3187,12 +3304,26 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { _parse_block(cf_for->body, p_static); current_block = p_block; - if (error_set) + if (error_set) { return; - p_block->has_return = cf_for->body->has_return; + } p_block->statements.push_back(cf_for); } break; case GDScriptTokenizer::TK_CF_CONTINUE: { + BlockNode *upper_block = p_block; + bool is_continue_valid = false; + while (upper_block) { + if (upper_block->can_continue) { + is_continue_valid = true; + break; + } + upper_block = upper_block->parent_block; + } + + if (!is_continue_valid) { + _set_error("Unexpected keyword \"continue\" outside a loop."); + return; + } _mark_line_as_safe(tokenizer->get_token_line()); tokenizer->advance(); @@ -3200,11 +3331,25 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_continue->cf_type = ControlFlowNode::CF_CONTINUE; p_block->statements.push_back(cf_continue); if (!_end_statement()) { - _set_error("Expected end of statement (\"continue\")."); + _set_end_statement_error("continue"); return; } } break; case GDScriptTokenizer::TK_CF_BREAK: { + BlockNode *upper_block = p_block; + bool is_break_valid = false; + while (upper_block) { + if (upper_block->can_break) { + is_break_valid = true; + break; + } + upper_block = upper_block->parent_block; + } + + if (!is_break_valid) { + _set_error("Unexpected keyword \"break\" outside a loop."); + return; + } _mark_line_as_safe(tokenizer->get_token_line()); tokenizer->advance(); @@ -3212,12 +3357,11 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_break->cf_type = ControlFlowNode::CF_BREAK; p_block->statements.push_back(cf_break); if (!_end_statement()) { - _set_error("Expected end of statement (\"break\")."); + _set_end_statement_error("break"); return; } } break; case GDScriptTokenizer::TK_CF_RETURN: { - tokenizer->advance(); ControlFlowNode *cf_return = alloc_node<ControlFlowNode>(); cf_return->cf_type = ControlFlowNode::CF_RETURN; @@ -3241,7 +3385,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_return->arguments.push_back(retexpr); p_block->statements.push_back(cf_return); if (!_end_statement()) { - _set_error("Expected end of statement after return expression."); + _set_end_statement_error("return"); return; } } @@ -3249,7 +3393,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } break; case GDScriptTokenizer::TK_CF_MATCH: { - tokenizer->advance(); MatchNode *match_node = alloc_node<MatchNode>(); @@ -3273,12 +3416,15 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { BlockNode *compiled_branches = alloc_node<BlockNode>(); compiled_branches->parent_block = p_block; compiled_branches->parent_class = p_block->parent_class; + compiled_branches->can_continue = true; p_block->sub_blocks.push_back(compiled_branches); _parse_pattern_block(compiled_branches, match_node->branches, p_static); - if (error_set) return; + if (error_set) { + return; + } ControlFlowNode *match_cf_node = alloc_node<ControlFlowNode>(); match_cf_node->cf_type = ControlFlowNode::CF_MATCH; @@ -3291,7 +3437,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { _end_statement(); } break; case GDScriptTokenizer::TK_PR_ASSERT: { - tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) { @@ -3299,6 +3444,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { return; } + int assert_line = tokenizer->get_token_line(); + tokenizer->advance(); Vector<Node *> args; @@ -3308,41 +3455,41 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } if (args.empty() || args.size() > 2) { - _set_error("Wrong number of arguments, expected 1 or 2"); + _set_error("Wrong number of arguments, expected 1 or 2", assert_line); return; } AssertNode *an = alloc_node<AssertNode>(); an->condition = _reduce_expression(args[0], p_static); + an->line = assert_line; if (args.size() == 2) { an->message = _reduce_expression(args[1], p_static); } else { ConstantNode *message_node = alloc_node<ConstantNode>(); message_node->value = String(); + message_node->datatype = _type_from_variant(message_node->value); an->message = message_node; } p_block->statements.push_back(an); if (!_end_statement()) { - _set_error("Expected end of statement after \"assert\"."); + _set_end_statement_error("assert"); return; } } break; case GDScriptTokenizer::TK_PR_BREAKPOINT: { - tokenizer->advance(); BreakpointNode *bn = alloc_node<BreakpointNode>(); p_block->statements.push_back(bn); if (!_end_statement()) { - _set_error("Expected end of statement after \"breakpoint\"."); + _set_end_statement_error("breakpoint"); return; } } break; default: { - Node *expression = _parse_and_reduce_expression(p_block, p_static, false, true); if (!expression) { if (_recover_from_completion()) { @@ -3356,7 +3503,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON && tokenizer->get_token(1) == GDScriptTokenizer::TK_OP_ASSIGN) { _set_error("Unexpected ':=', use '=' instead. Expected end of statement after expression."); } else { - _set_error(String() + "Expected end of statement after expression, got " + tokenizer->get_token_name(tokenizer->get_token()) + " instead"); + _set_error(vformat("Expected end of statement after expression, got %s instead.", tokenizer->get_token_name(tokenizer->get_token()))); } return; } @@ -3367,9 +3514,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { } bool GDScriptParser::_parse_newline() { - if (tokenizer->get_token(1) != GDScriptTokenizer::TK_EOF && tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) { - IndentLevel current_level = indent_level.back()->get(); int indent = tokenizer->get_token_line_indent(); int tabs = tokenizer->get_token_line_tab_indent(); @@ -3386,9 +3531,7 @@ bool GDScriptParser::_parse_newline() { } if (indent < current_level.indent) { - while (indent < current_level.indent) { - //exit block if (indent_level.size() == 1) { _set_error("Invalid indentation. Bug?"); @@ -3398,7 +3541,6 @@ bool GDScriptParser::_parse_newline() { indent_level.pop_back(); if (indent_level.back()->get().indent < indent) { - _set_error("Unindent does not match any outer indentation level."); return false; } @@ -3421,15 +3563,12 @@ bool GDScriptParser::_parse_newline() { } void GDScriptParser::_parse_extends(ClassNode *p_class) { - if (p_class->extends_used) { - _set_error("\"extends\" can only be present once per script."); return; } if (!p_class->constant_expressions.empty() || !p_class->subclasses.empty() || !p_class->functions.empty() || !p_class->variables.empty()) { - _set_error("\"extends\" must be used before anything else."); return; } @@ -3446,10 +3585,8 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) { // see if inheritance happens from a file if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT) { - Variant constant = tokenizer->get_token_constant(); if (constant.get_type() != Variant::STRING) { - _set_error("\"extends\" constant must be a string."); return; } @@ -3466,16 +3603,14 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) { if (tokenizer->get_token() != GDScriptTokenizer::TK_PERIOD) { return; - } else + } else { tokenizer->advance(); + } } while (true) { - switch (tokenizer->get_token()) { - case GDScriptTokenizer::TK_IDENTIFIER: { - StringName identifier = tokenizer->get_token_identifier(); p_class->extends_class.push_back(identifier); } break; @@ -3484,7 +3619,6 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) { break; default: { - _set_error("Invalid \"extends\" syntax, expected string constant (path) and/or identifier (parent class)."); return; } @@ -3493,7 +3627,6 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) { tokenizer->advance(1); switch (tokenizer->get_token()) { - case GDScriptTokenizer::TK_IDENTIFIER: case GDScriptTokenizer::TK_PERIOD: continue; @@ -3505,14 +3638,13 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) { } void GDScriptParser::_parse_class(ClassNode *p_class) { - IndentLevel current_level = indent_level.back()->get(); while (true) { - GDScriptTokenizer::Token token = tokenizer->get_token(); - if (error_set) + if (error_set) { return; + } if (current_level.indent > indent_level.back()->get().indent) { p_class->end_line = tokenizer->get_token_line(); @@ -3520,7 +3652,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } switch (token) { - case GDScriptTokenizer::TK_CURSOR: { tokenizer->advance(); } break; @@ -3540,19 +3671,18 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } break; case GDScriptTokenizer::TK_PR_EXTENDS: { - _mark_line_as_safe(tokenizer->get_token_line()); _parse_extends(p_class); - if (error_set) + if (error_set) { return; + } if (!_end_statement()) { - _set_error("Expected end of statement after \"extends\"."); + _set_end_statement_error("extends"); return; } } break; case GDScriptTokenizer::TK_PR_CLASS_NAME: { - _mark_line_as_safe(tokenizer->get_token_line()); if (p_class->owner) { _set_error("\"class_name\" is only valid for the main class namespace."); @@ -3563,7 +3693,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } if (tokenizer->get_token(1) != GDScriptTokenizer::TK_IDENTIFIER) { - _set_error("\"class_name\" syntax: \"class_name <UniqueName>\""); return; } @@ -3629,9 +3758,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } break; case GDScriptTokenizer::TK_PR_TOOL: { - if (p_class->tool) { - _set_error("The \"tool\" keyword can only be present once per script."); return; } @@ -3646,7 +3773,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { StringName name; if (tokenizer->get_token(1) != GDScriptTokenizer::TK_IDENTIFIER) { - _set_error("\"class\" syntax: \"class <Name>:\" or \"class <Name> extends <BaseClass>:\""); return; } @@ -3674,6 +3800,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { _set_error("A constant named \"" + String(name) + "\" already exists in the outer class scope (at line" + itos(outer_class->constant_expressions[name].expression->line) + ")."); return; } + for (int i = 0; i < outer_class->variables.size(); i++) { + if (outer_class->variables[i].identifier == name) { + _set_error("A variable named \"" + String(name) + "\" already exists in the outer class scope (at line " + itos(outer_class->variables[i].line) + ")."); + return; + } + } outer_class = outer_class->owner; } @@ -3689,14 +3821,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { p_class->subclasses.push_back(newclass); if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_EXTENDS) { - _parse_extends(newclass); - if (error_set) + if (error_set) { return; + } } if (!_enter_indent_block()) { - _set_error("Indented block expected."); return; } @@ -3714,7 +3845,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { case GDScriptTokenizer::TK_PR_STATIC: { tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) { - _set_error("Expected \"func\"."); return; } @@ -3722,12 +3852,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { [[fallthrough]]; } case GDScriptTokenizer::TK_PR_FUNCTION: { - bool _static = false; pending_newline = -1; if (tokenizer->get_token(-1) == GDScriptTokenizer::TK_PR_STATIC) { - _static = true; } @@ -3738,7 +3866,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (name == StringName()) { - _set_error("Expected an identifier after \"func\" (syntax: \"func <identifier>([arguments]):\")."); return; } @@ -3771,7 +3898,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { #endif // DEBUG_ENABLED if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) { - _set_error("Expected \"(\" after the identifier (syntax: \"func <identifier>([arguments]):\" )."); return; } @@ -3791,19 +3917,16 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { //has arguments bool defaulting = false; while (true) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) { tokenizer->advance(); continue; } if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_VAR) { - tokenizer->advance(); //var before the identifier is allowed } if (!tokenizer->is_token_literal(0, true)) { - _set_error("Expected an identifier for an argument."); return; } @@ -3835,7 +3958,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { argument_types.push_back(argtype); if (defaulting && tokenizer->get_token() != GDScriptTokenizer::TK_OP_ASSIGN) { - _set_error("Default parameter expected."); return; } @@ -3846,8 +3968,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { defaulting = true; tokenizer->advance(1); Node *defval = _parse_and_reduce_expression(p_class, _static); - if (!defval || error_set) + if (!defval || error_set) { return; + } OperatorNode *on = alloc_node<OperatorNode>(); on->op = OperatorNode::OP_ASSIGN; @@ -3876,7 +3999,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); continue; } else if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { - _set_error("Expected \",\" or \")\"."); return; } @@ -3904,14 +4026,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; if (name == "_init") { - if (_static) { _set_error("The constructor cannot be static."); return; } if (p_class->extends_used) { - OperatorNode *cparent = alloc_node<OperatorNode>(); cparent->op = OperatorNode::OP_PARENT_CALL; block->statements.push_back(cparent); @@ -3932,17 +4052,15 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { //has arguments parenthesis++; while (true) { - current_function = function; Node *arg = _parse_and_reduce_expression(p_class, _static); - current_function = NULL; + current_function = nullptr; cparent->arguments.push_back(arg); if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { tokenizer->advance(); continue; } else if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { - _set_error("Expected \",\" or \")\"."); return; } @@ -3955,9 +4073,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); } } else { - if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD) { - _set_error("Parent constructor call found for a class without inheritance."); return; } @@ -3966,7 +4082,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { DataType return_type; if (tokenizer->get_token() == GDScriptTokenizer::TK_FORWARD_ARROW) { - if (!_parse_type(return_type, true)) { _set_error("Expected a return type for the function."); return; @@ -3974,23 +4089,23 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (!_enter_indent_block(block)) { - - _set_error("Indented block expected."); + _set_error(vformat("Indented block expected after declaration of \"%s\" function.", function->name)); return; } function->return_type = return_type; - if (_static) + if (_static) { p_class->static_functions.push_back(function); - else + } else { p_class->functions.push_back(function); + } current_function = function; function->body = block; current_block = block; _parse_block(block, _static); - current_block = NULL; + current_block = nullptr; //arguments } break; @@ -4006,6 +4121,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { sig.name = tokenizer->get_token_identifier(); sig.emissions = 0; sig.line = tokenizer->get_token_line(); + + for (int i = 0; i < current_class->_signals.size(); i++) { + if (current_class->_signals[i].name == sig.name) { + _set_error("The signal \"" + sig.name + "\" already exists in this class (at line: " + itos(current_class->_signals[i].line) + ")."); + return; + } + } + tokenizer->advance(); if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) { @@ -4045,16 +4168,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { p_class->_signals.push_back(sig); if (!_end_statement()) { - _set_error("Expected end of statement (\"signal\")."); + _set_end_statement_error("signal"); return; } } break; case GDScriptTokenizer::TK_PR_EXPORT: { - tokenizer->advance(); if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) { - #define _ADVANCE_AND_CONSUME_NEWLINES \ do { \ tokenizer->advance(); \ @@ -4079,7 +4200,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE) { - Variant::Type type = tokenizer->get_token_type(); if (type == Variant::NIL) { _set_error("Can't export null type."); @@ -4098,11 +4218,8 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { _ADVANCE_AND_CONSUME_NEWLINES; switch (type) { - case Variant::INT: { - if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") { - _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { @@ -4115,7 +4232,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { bool first = true; while (true) { - if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) { current_export = PropertyInfo(); _set_error("Expected a string constant in the named bit flags hint."); @@ -4123,16 +4239,18 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } String c = tokenizer->get_token_constant(); - if (!first) + if (!first) { current_export.hint_string += ","; - else + } else { first = false; + } current_export.hint_string += c.xml_escape(); _ADVANCE_AND_CONSUME_NEWLINES; - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { break; + } if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { current_export = PropertyInfo(); @@ -4146,7 +4264,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_RENDER") { - _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected \")\" in the layers 2D render hint."); @@ -4157,7 +4274,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_2D_PHYSICS") { - _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected \")\" in the layers 2D physics hint."); @@ -4168,7 +4284,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_RENDER") { - _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected \")\" in the layers 3D render hint."); @@ -4179,7 +4294,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "LAYERS_3D_PHYSICS") { - _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected \")\" in the layers 3D physics hint."); @@ -4194,25 +4308,25 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { current_export.hint = PROPERTY_HINT_ENUM; bool first = true; while (true) { - if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) { - current_export = PropertyInfo(); _set_error("Expected a string constant in the enumeration hint."); return; } String c = tokenizer->get_token_constant(); - if (!first) + if (!first) { current_export.hint_string += ","; - else + } else { first = false; + } current_export.hint_string += c.xml_escape(); _ADVANCE_AND_CONSUME_NEWLINES; - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { break; + } if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { current_export = PropertyInfo(); @@ -4229,7 +4343,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { [[fallthrough]]; } case Variant::FLOAT: { - if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EASE") { current_export.hint = PROPERTY_HINT_EXP_EASING; _ADVANCE_AND_CONSUME_NEWLINES; @@ -4242,19 +4355,19 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { // range if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EXP") { - current_export.hint = PROPERTY_HINT_EXP_RANGE; _ADVANCE_AND_CONSUME_NEWLINES; - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { break; - else if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { + } else if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { _set_error("Expected \")\" or \",\" in the exponential range hint."); return; } _ADVANCE_AND_CONSUME_NEWLINES; - } else + } else { current_export.hint = PROPERTY_HINT_RANGE; + } float sign = 1.0; @@ -4263,7 +4376,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { _ADVANCE_AND_CONSUME_NEWLINES; } if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) { - current_export = PropertyInfo(); _set_error("Expected a range in the numeric hint."); return; @@ -4278,7 +4390,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { - current_export = PropertyInfo(); _set_error("Expected \",\" or \")\" in the numeric range hint."); return; @@ -4293,7 +4404,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) { - current_export = PropertyInfo(); _set_error("Expected a number as upper bound in the numeric range hint."); return; @@ -4302,11 +4412,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { current_export.hint_string += "," + rtos(sign * double(tokenizer->get_token_constant())); _ADVANCE_AND_CONSUME_NEWLINES; - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { break; + } if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { - current_export = PropertyInfo(); _set_error("Expected \",\" or \")\" in the numeric range hint."); return; @@ -4320,7 +4430,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) { - current_export = PropertyInfo(); _set_error("Expected a number as step in the numeric range hint."); return; @@ -4331,30 +4440,29 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } break; case Variant::STRING: { - if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) { //enumeration current_export.hint = PROPERTY_HINT_ENUM; bool first = true; while (true) { - if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) { - current_export = PropertyInfo(); _set_error("Expected a string constant in the enumeration hint."); return; } String c = tokenizer->get_token_constant(); - if (!first) + if (!first) { current_export.hint_string += ","; - else + } else { first = false; + } current_export.hint_string += c.xml_escape(); _ADVANCE_AND_CONSUME_NEWLINES; - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { break; + } if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { current_export = PropertyInfo(); @@ -4368,13 +4476,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "DIR") { - _ADVANCE_AND_CONSUME_NEWLINES; - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { current_export.hint = PROPERTY_HINT_DIR; - else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { - + } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER || !(tokenizer->get_token_identifier() == "GLOBAL")) { @@ -4400,16 +4506,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FILE") { - current_export.hint = PROPERTY_HINT_FILE; _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { - _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "GLOBAL") { - if (!p_class->tool) { _set_error("Global filesystem hints may only be used in tool scripts."); return; @@ -4417,22 +4520,22 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { current_export.hint = PROPERTY_HINT_GLOBAL_FILE; _ADVANCE_AND_CONSUME_NEWLINES; - if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { break; - else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) + } else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { _ADVANCE_AND_CONSUME_NEWLINES; - else { + } else { _set_error("Expected \")\" or \",\" in the hint."); return; } } if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) { - - if (current_export.hint == PROPERTY_HINT_GLOBAL_FILE) + if (current_export.hint == PROPERTY_HINT_GLOBAL_FILE) { _set_error("Expected string constant with filter."); - else + } else { _set_error("Expected \"GLOBAL\" or string constant with filter."); + } return; } current_export.hint_string = tokenizer->get_token_constant(); @@ -4447,7 +4550,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "MULTILINE") { - current_export.hint = PROPERTY_HINT_MULTILINE_TEXT; _ADVANCE_AND_CONSUME_NEWLINES; if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { @@ -4458,9 +4560,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } break; case Variant::COLOR: { - if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER) { - current_export = PropertyInfo(); _set_error("Color type hint expects RGB or RGBA as hints."); return; @@ -4480,7 +4580,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } break; default: { - current_export = PropertyInfo(); _set_error("Type \"" + Variant::get_type_name(type) + "\" can't take hints."); return; @@ -4489,7 +4588,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } } else { - parenthesis++; Node *subexpr = _parse_and_reduce_expression(p_class, true, true); if (!subexpr) { @@ -4549,10 +4647,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { bool first = true; for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { if (enum_values[E->get()].get_type() == Variant::INT) { - if (!first) + if (!first) { current_export.hint_string += ","; - else + } else { first = false; + } current_export.hint_string += E->get().operator String().camelcase_to_underscore(true).capitalize().xml_escape(); if (!is_flags) { @@ -4569,7 +4668,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { - current_export = PropertyInfo(); _set_error("Expected \")\" or \",\" after the export hint."); return; @@ -4591,7 +4689,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPET && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPETSYNC) { - current_export = PropertyInfo(); _set_error("Expected \"var\", \"onready\", \"remote\", \"master\", \"puppet\", \"remotesync\", \"mastersync\", \"puppetsync\"."); return; @@ -4600,7 +4697,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { continue; } break; case GDScriptTokenizer::TK_PR_ONREADY: { - //may be fallthrough from export, ignore if so tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) { @@ -4611,7 +4707,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { continue; } break; case GDScriptTokenizer::TK_PR_REMOTE: { - //may be fallthrough from export, ignore if so tokenizer->advance(); if (current_export.type) { @@ -4631,7 +4726,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { continue; } break; case GDScriptTokenizer::TK_PR_MASTER: { - //may be fallthrough from export, ignore if so tokenizer->advance(); if (current_export.type) { @@ -4651,7 +4745,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { continue; } break; case GDScriptTokenizer::TK_PR_PUPPET: { - //may be fallthrough from export, ignore if so tokenizer->advance(); if (current_export.type) { @@ -4671,14 +4764,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { continue; } break; case GDScriptTokenizer::TK_PR_REMOTESYNC: { - //may be fallthrough from export, ignore if so tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) { - if (current_export.type) + if (current_export.type) { _set_error("Expected \"var\"."); - else + } else { _set_error("Expected \"var\" or \"func\"."); + } return; } @@ -4686,14 +4779,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { continue; } break; case GDScriptTokenizer::TK_PR_MASTERSYNC: { - //may be fallthrough from export, ignore if so tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) { - if (current_export.type) + if (current_export.type) { _set_error("Expected \"var\"."); - else + } else { _set_error("Expected \"var\" or \"func\"."); + } return; } @@ -4701,14 +4794,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { continue; } break; case GDScriptTokenizer::TK_PR_PUPPETSYNC: { - //may be fallthrough from export, ignore if so tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) { - if (current_export.type) + if (current_export.type) { _set_error("Expected \"var\"."); - else + } else { _set_error("Expected \"var\" or \"func\"."); + } return; } @@ -4730,13 +4823,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); if (!tokenizer->is_token_literal(0, true)) { - _set_error("Expected an identifier for the member variable name."); return; } member.identifier = tokenizer->get_token_literal(); - member.expression = NULL; + member.expression = nullptr; member._export.name = member.identifier; member.line = tokenizer->get_token_line(); member.usages = 0; @@ -4816,11 +4908,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { #ifdef TOOLS_ENABLED Callable::CallError ce; - member.default_value = Variant::construct(member._export.type, NULL, 0, ce); + member.default_value = Variant::construct(member._export.type, nullptr, 0, ce); #endif if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { - #ifdef DEBUG_ENABLED int line = tokenizer->get_token_line(); #endif @@ -4836,12 +4927,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { //discourage common error if (!onready && subexpr->type == Node::TYPE_OPERATOR) { - OperatorNode *op = static_cast<OperatorNode *>(subexpr); if (op->op == OperatorNode::OP_CALL && op->arguments[0]->type == Node::TYPE_SELF && op->arguments[1]->type == Node::TYPE_IDENTIFIER) { IdentifierNode *id = static_cast<IdentifierNode *>(op->arguments[1]); if (id->name == "get_node") { - _set_error("Use \"onready var " + String(member.identifier) + " = get_node(...)\" instead."); return; } @@ -4851,25 +4940,27 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { member.expression = subexpr; if (autoexport && !member.data_type.has_type) { - if (subexpr->type != Node::TYPE_CONSTANT) { - _set_error("Type-less export needs a constant expression assigned to infer type."); return; } ConstantNode *cn = static_cast<ConstantNode *>(subexpr); if (cn->value.get_type() == Variant::NIL) { - _set_error("Can't accept a null constant expression for inferring export type."); return; } + + if (!_reduce_export_var_type(cn->value, member.line)) { + return; + } + member._export.type = cn->value.get_type(); member._export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; if (cn->value.get_type() == Variant::OBJECT) { Object *obj = cn->value; Resource *res = Object::cast_to<Resource>(obj); - if (res == NULL) { + if (res == nullptr) { _set_error("The exported constant isn't a type or resource."); return; } @@ -4879,7 +4970,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } #ifdef TOOLS_ENABLED if (subexpr->type == Node::TYPE_CONSTANT && (member._export.type != Variant::NIL || member.data_type.has_type)) { - ConstantNode *cn = static_cast<ConstantNode *>(subexpr); if (cn->value.get_type() != Variant::NIL) { if (member._export.type != Variant::NIL && cn->value.get_type() != member._export.type) { @@ -4899,6 +4989,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { IdentifierNode *id = alloc_node<IdentifierNode>(); id->name = member.identifier; + id->datatype = member.data_type; OperatorNode *op = alloc_node<OperatorNode>(); op->op = OperatorNode::OP_INIT_ASSIGN; @@ -4908,20 +4999,21 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { #ifdef DEBUG_ENABLED NewLineNode *nl2 = alloc_node<NewLineNode>(); nl2->line = line; - if (onready) + if (onready) { p_class->ready->statements.push_back(nl2); - else + } else { p_class->initializer->statements.push_back(nl2); + } #endif - if (onready) + if (onready) { p_class->ready->statements.push_back(op); - else + } else { p_class->initializer->statements.push_back(op); + } member.initial_assignment = op; } else { - if (autoexport && !member.data_type.has_type) { _set_error("Type-less export needs a constant expression assigned to infer type."); return; @@ -4941,6 +5033,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { IdentifierNode *id = alloc_node<IdentifierNode>(); id->name = member.identifier; + id->datatype = member.data_type; OperatorNode *op = alloc_node<OperatorNode>(); op->op = OperatorNode::OP_INIT_ASSIGN; @@ -4953,7 +5046,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_SETGET) { - tokenizer->advance(); if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { @@ -4983,7 +5075,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { p_class->variables.push_back(member); if (!_end_statement()) { - _set_error("Expected end of statement (\"continue\")."); + _set_end_statement_error("var"); return; } } break; @@ -4994,7 +5086,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); if (!tokenizer->is_token_literal(0, true)) { - _set_error("Expected an identifier for the constant."); return; } @@ -5063,7 +5154,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { p_class->constant_expressions.insert(const_id, constant); if (!_end_statement()) { - _set_error("Expected end of statement (constant).", line); + _set_end_statement_error("const"); return; } @@ -5110,14 +5201,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { while (true) { if (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE) { - tokenizer->advance(); // Ignore newlines } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CURLY_BRACKET_CLOSE) { - tokenizer->advance(); break; // End of enum } else if (!tokenizer->is_token_literal(0, true)) { - if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) { _set_error("Unexpected end of file."); } else { @@ -5217,7 +5305,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (!_end_statement()) { - _set_error("Expected end of statement (\"enum\")."); + _set_end_statement_error("enum"); return; } @@ -5238,7 +5326,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } break; default: { - _set_error(String() + "Unexpected token: " + tokenizer->get_token_name(tokenizer->get_token()) + ":" + tokenizer->get_token_identifier()); return; @@ -5248,7 +5335,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive) { - if (p_class->base_type.has_type) { // Already determined } else if (p_class->extends_used) { @@ -5257,13 +5343,12 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive Ref<GDScript> script; StringName native; - ClassNode *base_class = NULL; + ClassNode *base_class = nullptr; if (path != "") { //path (and optionally subclasses) if (path.is_rel_path()) { - String base = base_path; if (base == "" || base.is_rel_path()) { @@ -5278,22 +5363,17 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive return; } if (!script->is_valid()) { - _set_error("Script isn't fully loaded (cyclic preload?): " + path, p_class->line); return; } if (p_class->extends_class.size()) { - for (int i = 0; i < p_class->extends_class.size(); i++) { - String sub = p_class->extends_class[i]; if (script->get_subclasses().has(sub)) { - Ref<Script> subclass = script->get_subclasses()[sub]; //avoid reference from disappearing script = subclass; } else { - _set_error("Couldn't find the subclass: " + sub, p_class->line); return; } @@ -5301,7 +5381,6 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive } } else { - if (p_class->extends_class.size() == 0) { _set_error("Parser bug: undecidable inheritance.", p_class->line); ERR_FAIL(); @@ -5319,7 +5398,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive _set_error("The class \"" + base + "\" couldn't be fully loaded (script error or cyclic dependency).", p_class->line); return; } - p = NULL; + p = nullptr; } else { List<PropertyInfo> props; ProjectSettings::get_singleton()->get_property_list(&props); @@ -5342,13 +5421,12 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive _set_error("Class '" + base + "' could not be fully loaded (script error or cyclic inheritance).", p_class->line); return; } - p = NULL; + p = nullptr; } } } while (p) { - bool found = false; for (int i = 0; i < p->subclasses.size(); i++) { @@ -5377,8 +5455,12 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive } } - if (base_class) break; - if (found) continue; + if (base_class) { + break; + } + if (found) { + continue; + } if (p->constant_expressions.has(base)) { if (p->constant_expressions[base].expression->type != Node::TYPE_CONSTANT) { @@ -5398,21 +5480,17 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive } if (base_script.is_valid()) { - String ident = base; Ref<GDScript> find_subclass = base_script; for (int i = extend_iter; i < p_class->extends_class.size(); i++) { - String subclass = p_class->extends_class[i]; ident += ("." + subclass); if (find_subclass->get_subclasses().has(subclass)) { - find_subclass = find_subclass->get_subclasses()[subclass]; } else if (find_subclass->get_constants().has(subclass)) { - Ref<GDScript> new_base_class = find_subclass->get_constants()[subclass]; if (new_base_class.is_null()) { _set_error("Constant isn't a class: " + ident, p_class->line); @@ -5420,7 +5498,6 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive } find_subclass = new_base_class; } else { - _set_error("Couldn't find the subclass: " + ident, p_class->line); return; } @@ -5429,15 +5506,12 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive script = find_subclass; } else if (!base_class) { - if (p_class->extends_class.size() > 1) { - _set_error("Invalid inheritance (unknown class + subclasses).", p_class->line); return; } //if not found, try engine classes if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) { - _set_error("Unknown class: \"" + base + "\"", p_class->line); return; } @@ -5480,10 +5554,14 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive } String GDScriptParser::DataType::to_string() const { - if (!has_type) return "var"; + if (!has_type) { + return "var"; + } switch (kind) { case BUILTIN: { - if (builtin_type == Variant::NIL) return "null"; + if (builtin_type == Variant::NIL) { + return "null"; + } return Variant::get_type_name(builtin_type); } break; case NATIVE: { @@ -5647,8 +5725,12 @@ bool GDScriptParser::_parse_type(DataType &r_type, bool p_can_be_void) { } GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source, int p_line) { - if (!p_source.has_type) return p_source; - if (p_source.kind != DataType::UNRESOLVED) return p_source; + if (!p_source.has_type) { + return p_source; + } + if (p_source.kind != DataType::UNRESOLVED) { + return p_source; + } Vector<String> full_name = p_source.native_type.operator String().split(".", false); int name_part = 0; @@ -5657,12 +5739,11 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source, result.has_type = true; while (name_part < full_name.size()) { - bool found = false; StringName id = full_name[name_part]; DataType base_type = result; - ClassNode *p = NULL; + ClassNode *p = nullptr; if (name_part == 0) { if (ScriptServer::is_global_class(id)) { String script_path = ScriptServer::get_global_class_path(id); @@ -5944,7 +6025,7 @@ GDScriptParser::DataType GDScriptParser::_get_operation_type(const Variant::Oper a = a_ref; } else { Callable::CallError err; - a = Variant::construct(a_type, NULL, 0, err); + a = Variant::construct(a_type, nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK) { r_valid = false; return DataType(); @@ -5957,7 +6038,7 @@ GDScriptParser::DataType GDScriptParser::_get_operation_type(const Variant::Oper b = b_ref; } else { Callable::CallError err; - b = Variant::construct(b_type, NULL, 0, err); + b = Variant::construct(b_type, nullptr, 0, err); if (err.error != Callable::CallError::CALL_OK) { r_valid = false; return DataType(); @@ -6118,7 +6199,7 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data StringName expr_native; Ref<Script> expr_script; - ClassNode *expr_class = NULL; + ClassNode *expr_class = nullptr; switch (p_expression.kind) { case DataType::NATIVE: { @@ -6229,12 +6310,14 @@ GDScriptParser::Node *GDScriptParser::_get_default_value_for_type(const DataType } else { ConstantNode *c = alloc_node<ConstantNode>(); Callable::CallError err; - c->value = Variant::construct(p_type.builtin_type, NULL, 0, err); + c->value = Variant::construct(p_type.builtin_type, nullptr, 0, err); + c->datatype = _type_from_variant(c->value); result = c; } } else { ConstantNode *c = alloc_node<ConstantNode>(); c->value = Variant(); + c->datatype = _type_from_variant(c->value); result = c; } @@ -6308,7 +6391,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { int idx = current_function->arguments.find(id->name); node_type = current_function->argument_types[idx]; } else { - node_type = _reduce_identifier_type(NULL, id->name, id->line, false); + node_type = _reduce_identifier_type(nullptr, id->name, id->line, false); } } break; case Node::TYPE_CAST: { @@ -6317,7 +6400,6 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { DataType source_type = _reduce_node_type(cn->source_node); cn->cast_type = _resolve_type(cn->cast_type, cn->line); if (source_type.has_type) { - bool valid = false; if (check_types) { if (cn->cast_type.kind == DataType::BUILTIN && source_type.kind == DataType::BUILTIN) { @@ -6371,7 +6453,6 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { } break; case OperatorNode::OP_IS: case OperatorNode::OP_IS_BUILTIN: { - if (op->arguments.size() != 2) { _set_error("Parser bug: binary operation without 2 arguments.", op->line); ERR_FAIL_V(DataType()); @@ -6407,7 +6488,6 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { case OperatorNode::OP_POS: case OperatorNode::OP_NOT: case OperatorNode::OP_BIT_INVERT: { - DataType argument_type = _reduce_node_type(op->arguments[0]); if (!argument_type.has_type) { break; @@ -6445,7 +6525,6 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { case OperatorNode::OP_BIT_AND: case OperatorNode::OP_BIT_OR: case OperatorNode::OP_BIT_XOR: { - if (op->arguments.size() != 2) { _set_error("Parser bug: binary operation without 2 arguments.", op->line); ERR_FAIL_V(DataType()); @@ -6513,7 +6592,6 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { case OperatorNode::OP_ASSIGN_BIT_OR: case OperatorNode::OP_ASSIGN_BIT_XOR: case OperatorNode::OP_INIT_ASSIGN: { - _set_error("Assignment inside an expression isn't allowed (parser bug?).", op->line); return DataType(); @@ -6542,7 +6620,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { } break; default: { Callable::CallError err; - Variant temp = Variant::construct(base_type.builtin_type, NULL, 0, err); + Variant temp = Variant::construct(base_type.builtin_type, nullptr, 0, err); bool valid = false; Variant res = temp.get(member_id->name.operator String(), &valid); @@ -6563,6 +6641,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { node_type = _reduce_identifier_type(&base_type, member_id->name, op->line, true); #ifdef DEBUG_ENABLED if (!node_type.has_type) { + _mark_line_as_unsafe(op->line); _add_warning(GDScriptWarning::UNSAFE_PROPERTY_ACCESS, op->line, member_id->name.operator String(), base_type.to_string()); } #endif // DEBUG_ENABLED @@ -6575,7 +6654,6 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { } } break; case OperatorNode::OP_INDEX: { - if (op->arguments[1]->type == Node::TYPE_CONSTANT) { ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[1]); if (cn->value.get_type() == Variant::STRING) { @@ -6583,6 +6661,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { IdentifierNode *id = alloc_node<IdentifierNode>(); id->name = cn->value.operator StringName(); + id->datatype = cn->datatype; op->op = OperatorNode::OP_INDEX_NAMED; op->arguments.write[1] = id; @@ -6671,7 +6750,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { } default: { Callable::CallError err; - Variant temp = Variant::construct(base_type.builtin_type, NULL, 0, err); + Variant temp = Variant::construct(base_type.builtin_type, nullptr, 0, err); bool valid = false; Variant res = temp.get(cn->value, &valid); @@ -6773,13 +6852,12 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { } bool GDScriptParser::_get_function_signature(DataType &p_base_type, const StringName &p_function, DataType &r_return_type, List<DataType> &r_arg_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) const { - r_static = false; r_default_arg_count = 0; DataType original_type = p_base_type; - ClassNode *base = NULL; - FunctionNode *callee = NULL; + ClassNode *base = nullptr; + FunctionNode *callee = nullptr; if (p_base_type.kind == DataType::CLASS) { base = p_base_type.class_type; @@ -6884,7 +6962,9 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String native = "_" + native.operator String(); } if (!ClassDB::class_exists(native)) { - if (!check_types) return false; + if (!check_types) { + return false; + } ERR_FAIL_V_MSG(false, "Parser bug: Class '" + String(native) + "' not found."); } @@ -6975,7 +7055,9 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat par_types.write[i - 1] = _reduce_node_type(p_call->arguments[i]); } - if (error_set) return DataType(); + if (error_set) { + return DataType(); + } // Special case: check copy constructor. Those are defined implicitly in Variant. if (par_types.size() == 1) { @@ -7043,7 +7125,9 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat err += "' matches the signature '"; err += Variant::get_type_name(tn->vtype) + "("; for (int i = 0; i < par_types.size(); i++) { - if (i > 0) err += ", "; + if (i > 0) { + err += ", "; + } err += par_types[i].to_string(); } err += ")'."; @@ -7112,7 +7196,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat if (base_type.kind == DataType::BUILTIN) { Callable::CallError err; - Variant tmp = Variant::construct(base_type.builtin_type, NULL, 0, err); + Variant tmp = Variant::construct(base_type.builtin_type, nullptr, 0, err); if (check_types) { if (!tmp.has_method(callee_name)) { @@ -7272,17 +7356,20 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat return return_type; } -bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringName &p_member, DataType &r_member_type) const { +bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringName &p_member, DataType &r_member_type, bool *r_is_const) const { DataType base_type = p_base_type; // Check classes in current file - ClassNode *base = NULL; + ClassNode *base = nullptr; if (base_type.kind == DataType::CLASS) { base = base_type.class_type; } while (base) { if (base->constant_expressions.has(p_member)) { + if (r_is_const) { + *r_is_const = true; + } r_member_type = base->constant_expressions[p_member].expression->get_datatype(); return true; } @@ -7365,6 +7452,8 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN } } +#define IS_USAGE_MEMBER(m_usage) (!(m_usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP | PROPERTY_USAGE_CATEGORY))) + // Check other script types while (scr.is_valid()) { Map<StringName, Variant> constants; @@ -7377,7 +7466,7 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN List<PropertyInfo> properties; scr->get_script_property_list(&properties); for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { - if (E->get().name == p_member) { + if (E->get().name == p_member && IS_USAGE_MEMBER(E->get().usage)) { r_member_type = _type_from_property(E->get()); return true; } @@ -7399,7 +7488,9 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN native = "_" + native.operator String(); } if (!ClassDB::class_exists(native)) { - if (!check_types) return false; + if (!check_types) { + return false; + } ERR_FAIL_V_MSG(false, "Parser bug: Class \"" + String(native) + "\" not found."); } @@ -7419,7 +7510,7 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN List<PropertyInfo> properties; ClassDB::get_property_list(native, &properties); for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { - if (E->get().name == p_member) { + if (E->get().name == p_member && IS_USAGE_MEMBER(E->get().usage)) { // Check if a getter exists StringName getter_name = ClassDB::get_property_getter(native, p_member); if (getter_name != StringName()) { @@ -7459,7 +7550,7 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN List<PropertyInfo> properties; ClassDB::get_property_list(native, &properties); for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { - if (E->get().name == p_member) { + if (E->get().name == p_member && IS_USAGE_MEMBER(E->get().usage)) { // Check if a getter exists StringName getter_name = ClassDB::get_property_getter(native, p_member); if (getter_name != StringName()) { @@ -7481,12 +7572,12 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN } } } +#undef IS_USAGE_MEMBER return false; } GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line, bool p_is_indexing) { - if (p_base_type && !p_base_type->has_type) { return DataType(); } @@ -7503,7 +7594,12 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType base_type = DataType(*p_base_type); } - if (_get_member_type(base_type, p_identifier, member_type)) { + bool is_const = false; + if (_get_member_type(base_type, p_identifier, member_type, &is_const)) { + if (!p_base_type && current_function && current_function->_static && !is_const) { + _set_error("Can't access member variable (\"" + p_identifier.operator String() + "\") from a static function.", p_line); + return DataType(); + } return member_type; } @@ -7655,7 +7751,6 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType } void GDScriptParser::_check_class_level_types(ClassNode *p_class) { - // Names of internal object properties that we check to avoid overriding them. // "__meta__" could also be in here, but since it doesn't really affect object metadata, // it is okay to override it on script. @@ -7691,12 +7786,16 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { // Function declarations for (int i = 0; i < p_class->static_functions.size(); i++) { _check_function_types(p_class->static_functions[i]); - if (error_set) return; + if (error_set) { + return; + } } for (int i = 0; i < p_class->functions.size(); i++) { _check_function_types(p_class->functions[i]); - if (error_set) return; + if (error_set) { + return; + } } // Class variables @@ -7711,6 +7810,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { _mark_line_as_safe(v.line); v.data_type = _resolve_type(v.data_type, v.line); + v.initial_assignment->arguments[0]->set_datatype(v.data_type); if (v.expression) { DataType expr_type = _reduce_node_type(v.expression); @@ -7735,7 +7835,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { ConstantNode *tgt_type = alloc_node<ConstantNode>(); tgt_type->line = v.line; - tgt_type->value = (int)v.data_type.builtin_type; + tgt_type->value = (int64_t)v.data_type.builtin_type; OperatorNode *convert_call = alloc_node<OperatorNode>(); convert_call->line = v.line; @@ -7754,6 +7854,10 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { _set_error("The assigned value doesn't have a set type; the variable type can't be inferred.", v.line); return; } + if (expr_type.kind == DataType::BUILTIN && expr_type.builtin_type == Variant::NIL) { + _set_error("The variable type cannot be inferred because its value is \"null\".", v.line); + return; + } v.data_type = expr_type; v.data_type.is_constant = false; } @@ -7771,7 +7875,9 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { } // Setter and getter - if (v.setter == StringName() && v.getter == StringName()) continue; + if (v.setter == StringName() && v.getter == StringName()) { + continue; + } bool found_getter = false; bool found_setter = false; @@ -7814,10 +7920,14 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { return; } } - if (found_getter && found_setter) break; + if (found_getter && found_setter) { + break; + } } - if ((found_getter || v.getter == StringName()) && (found_setter || v.setter == StringName())) continue; + if ((found_getter || v.getter == StringName()) && (found_setter || v.setter == StringName())) { + continue; + } // Check for static functions for (int j = 0; j < p_class->static_functions.size(); j++) { @@ -7844,17 +7954,59 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { } } + // Signals + DataType base = p_class->base_type; + + while (base.kind == DataType::CLASS) { + ClassNode *base_class = base.class_type; + for (int i = 0; i < p_class->_signals.size(); i++) { + for (int j = 0; j < base_class->_signals.size(); j++) { + if (p_class->_signals[i].name == base_class->_signals[j].name) { + _set_error("The signal \"" + p_class->_signals[i].name + "\" already exists in a parent class.", p_class->_signals[i].line); + return; + } + } + } + base = base_class->base_type; + } + + StringName native; + if (base.kind == DataType::GDSCRIPT || base.kind == DataType::SCRIPT) { + Ref<Script> scr = base.script_type; + if (scr.is_valid() && scr->is_valid()) { + native = scr->get_instance_base_type(); + for (int i = 0; i < p_class->_signals.size(); i++) { + if (scr->has_script_signal(p_class->_signals[i].name)) { + _set_error("The signal \"" + p_class->_signals[i].name + "\" already exists in a parent class.", p_class->_signals[i].line); + return; + } + } + } + } else if (base.kind == DataType::NATIVE) { + native = base.native_type; + } + + if (native != StringName()) { + for (int i = 0; i < p_class->_signals.size(); i++) { + if (ClassDB::has_signal(native, p_class->_signals[i].name)) { + _set_error("The signal \"" + p_class->_signals[i].name + "\" already exists in a parent class.", p_class->_signals[i].line); + return; + } + } + } + // Inner classes for (int i = 0; i < p_class->subclasses.size(); i++) { current_class = p_class->subclasses[i]; _check_class_level_types(current_class); - if (error_set) return; + if (error_set) { + return; + } current_class = p_class; } } void GDScriptParser::_check_function_types(FunctionNode *p_function) { - p_function->return_type = _resolve_type(p_function->return_type, p_function->line); // Arguments @@ -7973,30 +8125,20 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) { p_function->return_type.has_type = false; p_function->return_type.may_yield = true; } - -#ifdef DEBUG_ENABLED - for (Map<StringName, LocalVarNode *>::Element *E = p_function->body->variables.front(); E; E = E->next()) { - LocalVarNode *lv = E->get(); - for (int i = 0; i < current_class->variables.size(); i++) { - if (current_class->variables[i].identifier == lv->name) { - _add_warning(GDScriptWarning::SHADOWED_VARIABLE, lv->line, lv->name, itos(current_class->variables[i].line)); - } - } - } -#endif // DEBUG_ENABLED } void GDScriptParser::_check_class_blocks_types(ClassNode *p_class) { - // Function blocks for (int i = 0; i < p_class->static_functions.size(); i++) { current_function = p_class->static_functions[i]; current_block = current_function->body; _mark_line_as_safe(current_function->line); _check_block_types(current_block); - current_block = NULL; - current_function = NULL; - if (error_set) return; + current_block = nullptr; + current_function = nullptr; + if (error_set) { + return; + } } for (int i = 0; i < p_class->functions.size(); i++) { @@ -8004,9 +8146,11 @@ void GDScriptParser::_check_class_blocks_types(ClassNode *p_class) { current_block = current_function->body; _mark_line_as_safe(current_function->line); _check_block_types(current_block); - current_block = NULL; - current_function = NULL; - if (error_set) return; + current_block = nullptr; + current_function = nullptr; + if (error_set) { + return; + } } #ifdef DEBUG_ENABLED @@ -8027,7 +8171,9 @@ void GDScriptParser::_check_class_blocks_types(ClassNode *p_class) { for (int i = 0; i < p_class->subclasses.size(); i++) { current_class = p_class->subclasses[i]; _check_class_blocks_types(current_class); - if (error_set) return; + if (error_set) { + return; + } current_class = p_class; } } @@ -8053,18 +8199,22 @@ static String _find_function_name(const GDScriptParser::OperatorNode *p_call) { #endif // DEBUG_ENABLED void GDScriptParser::_check_block_types(BlockNode *p_block) { - - Node *last_var_assign = NULL; + Node *last_var_assign = nullptr; // Check each statement for (List<Node *>::Element *E = p_block->statements.front(); E; E = E->next()) { Node *statement = E->get(); switch (statement->type) { case Node::TYPE_NEWLINE: - case Node::TYPE_BREAKPOINT: - case Node::TYPE_ASSERT: { + case Node::TYPE_BREAKPOINT: { // Nothing to do } break; + case Node::TYPE_ASSERT: { + AssertNode *an = static_cast<AssertNode *>(statement); + _mark_line_as_safe(an->line); + _reduce_node_type(an->condition); + _reduce_node_type(an->message); + } break; case Node::TYPE_LOCAL_VAR: { LocalVarNode *lv = static_cast<LocalVarNode *>(statement); lv->datatype = _resolve_type(lv->datatype, lv->line); @@ -8086,6 +8236,11 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { if (lv->datatype.has_type && assign_type.may_yield && lv->assign->type == Node::TYPE_OPERATOR) { _add_warning(GDScriptWarning::FUNCTION_MAY_YIELD, lv->line, _find_function_name(static_cast<OperatorNode *>(lv->assign))); } + for (int i = 0; i < current_class->variables.size(); i++) { + if (current_class->variables[i].identifier == lv->name) { + _add_warning(GDScriptWarning::SHADOWED_VARIABLE, lv->line, lv->name, itos(current_class->variables[i].line)); + } + } #endif // DEBUG_ENABLED if (!_is_type_compatible(lv->datatype, assign_type)) { @@ -8107,7 +8262,8 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { ConstantNode *tgt_type = alloc_node<ConstantNode>(); tgt_type->line = lv->line; - tgt_type->value = (int)lv->datatype.builtin_type; + tgt_type->value = (int64_t)lv->datatype.builtin_type; + tgt_type->datatype = _type_from_variant(tgt_type->value); OperatorNode *convert_call = alloc_node<OperatorNode>(); convert_call->line = lv->line; @@ -8130,6 +8286,10 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { _set_error("The assigned value doesn't have a set type; the variable type can't be inferred.", lv->line); return; } + if (assign_type.kind == DataType::BUILTIN && assign_type.builtin_type == Variant::NIL) { + _set_error("The variable type cannot be inferred because its value is \"null\".", lv->line); + return; + } lv->datatype = assign_type; lv->datatype.is_constant = false; } @@ -8243,6 +8403,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { ConstantNode *tgt_type = alloc_node<ConstantNode>(); tgt_type->line = op->line; tgt_type->value = (int)lh_type.builtin_type; + tgt_type->datatype = _type_from_variant(tgt_type->value); OperatorNode *convert_call = alloc_node<OperatorNode>(); convert_call->line = op->line; @@ -8283,7 +8444,9 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { _add_warning(GDScriptWarning::RETURN_VALUE_DISCARDED, op->line, func_name); } #endif // DEBUG_ENABLED - if (error_set) return; + if (error_set) { + return; + } } break; case OperatorNode::OP_YIELD: { _mark_line_as_safe(op->line); @@ -8318,7 +8481,9 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { } } - if (!function_type.has_type) break; + if (!function_type.has_type) { + break; + } if (function_type.kind == DataType::BUILTIN && function_type.builtin_type == Variant::NIL) { // Return void, should not have arguments @@ -8378,7 +8543,9 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { current_block = p_block->sub_blocks[i]; _check_block_types(current_block); current_block = p_block; - if (error_set) return; + if (error_set) { + return; + } } #ifdef DEBUG_ENABLED @@ -8397,9 +8564,9 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { } void GDScriptParser::_set_error(const String &p_error, int p_line, int p_column) { - - if (error_set) + if (error_set) { return; //allow no further errors + } error = p_error; error_line = p_line < 0 ? tokenizer->get_token_line() : p_line; @@ -8445,7 +8612,7 @@ void GDScriptParser::_add_warning(int p_code, int p_line, const Vector<String> & warn.symbols = p_symbols; warn.line = p_line == -1 ? tokenizer->get_token_line() : p_line; - List<GDScriptWarning>::Element *before = NULL; + List<GDScriptWarning>::Element *before = nullptr; for (List<GDScriptWarning>::Element *E = warnings.front(); E; E = E->next()) { if (E->get().line > warn.line) { break; @@ -8461,16 +8628,14 @@ void GDScriptParser::_add_warning(int p_code, int p_line, const Vector<String> & #endif // DEBUG_ENABLED String GDScriptParser::get_error() const { - return error; } int GDScriptParser::get_error_line() const { - return error_line; } -int GDScriptParser::get_error_column() const { +int GDScriptParser::get_error_column() const { return error_column; } @@ -8479,7 +8644,6 @@ bool GDScriptParser::has_error() const { } Error GDScriptParser::_parse(const String &p_base_path) { - base_path = p_base_path; //assume class @@ -8497,7 +8661,13 @@ Error GDScriptParser::_parse(const String &p_base_path) { _set_error("Parse error: " + tokenizer->get_token_error()); } - if (error_set && !for_completion) { + bool for_completion_error_set = false; + if (error_set && for_completion) { + for_completion_error_set = true; + error_set = false; + } + + if (error_set) { return ERR_PARSE_ERROR; } @@ -8512,10 +8682,12 @@ Error GDScriptParser::_parse(const String &p_base_path) { } current_class = main_class; - current_function = NULL; - current_block = NULL; + current_function = nullptr; + current_block = nullptr; - if (for_completion) check_types = false; + if (for_completion) { + check_types = false; + } // Resolve all class-level stuff before getting into function blocks _check_class_level_types(main_class); @@ -8527,6 +8699,10 @@ Error GDScriptParser::_parse(const String &p_base_path) { // Resolve the function blocks _check_class_blocks_types(main_class); + if (for_completion_error_set) { + error_set = true; + } + if (error_set) { return ERR_PARSE_ERROR; } @@ -8567,7 +8743,6 @@ Error GDScriptParser::_parse(const String &p_base_path) { } Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &p_base_path, const String &p_self_path) { - clear(); self_path = p_self_path; @@ -8576,12 +8751,11 @@ Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const St tokenizer = tb; Error ret = _parse(p_base_path); memdelete(tb); - tokenizer = NULL; + tokenizer = nullptr; return ret; } Error GDScriptParser::parse(const String &p_code, const String &p_base_path, bool p_just_validate, const String &p_self_path, bool p_for_completion, Set<int> *r_safe_lines, bool p_dependencies_only) { - clear(); self_path = p_self_path; @@ -8597,44 +8771,40 @@ Error GDScriptParser::parse(const String &p_code, const String &p_base_path, boo tokenizer = tt; Error ret = _parse(p_base_path); memdelete(tt); - tokenizer = NULL; + tokenizer = nullptr; return ret; } bool GDScriptParser::is_tool_script() const { - return (head && head->type == Node::TYPE_CLASS && static_cast<const ClassNode *>(head)->tool); } const GDScriptParser::Node *GDScriptParser::get_parse_tree() const { - return head; } void GDScriptParser::clear() { - while (list) { - Node *l = list; list = list->next; memdelete(l); } - head = NULL; - list = NULL; + head = nullptr; + list = nullptr; completion_type = COMPLETION_NONE; - completion_node = NULL; - completion_class = NULL; - completion_function = NULL; - completion_block = NULL; - current_block = NULL; - current_class = NULL; + completion_node = nullptr; + completion_class = nullptr; + completion_function = nullptr; + completion_block = nullptr; + current_block = nullptr; + current_class = nullptr; completion_found = false; rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; - current_function = NULL; + current_function = nullptr; validating = false; for_completion = false; @@ -8651,70 +8821,58 @@ void GDScriptParser::clear() { dependencies.clear(); error = ""; #ifdef DEBUG_ENABLED - safe_lines = NULL; + safe_lines = nullptr; #endif // DEBUG_ENABLED } GDScriptParser::CompletionType GDScriptParser::get_completion_type() { - return completion_type; } StringName GDScriptParser::get_completion_cursor() { - return completion_cursor; } int GDScriptParser::get_completion_line() { - return completion_line; } Variant::Type GDScriptParser::get_completion_built_in_constant() { - return completion_built_in_constant; } GDScriptParser::Node *GDScriptParser::get_completion_node() { - return completion_node; } GDScriptParser::BlockNode *GDScriptParser::get_completion_block() { - return completion_block; } GDScriptParser::ClassNode *GDScriptParser::get_completion_class() { - return completion_class; } GDScriptParser::FunctionNode *GDScriptParser::get_completion_function() { - return completion_function; } int GDScriptParser::get_completion_argument_index() { - return completion_argument; } -int GDScriptParser::get_completion_identifier_is_function() { - +bool GDScriptParser::get_completion_identifier_is_function() { return completion_ident_is_call; } GDScriptParser::GDScriptParser() { - - head = NULL; - list = NULL; - tokenizer = NULL; + head = nullptr; + list = nullptr; + tokenizer = nullptr; pending_newline = -1; clear(); } GDScriptParser::~GDScriptParser() { - clear(); } diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index c74d7dd856..7dedb6d6f9 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -45,25 +45,27 @@ public: struct ClassNode; struct DataType { - enum { + enum Kind { BUILTIN, NATIVE, SCRIPT, GDSCRIPT, CLASS, UNRESOLVED - } kind; + }; + + Kind kind = UNRESOLVED; - bool has_type; - bool is_constant; - bool is_meta_type; // Whether the value can be used as a type - bool infer_type; - bool may_yield; // For function calls + bool has_type = false; + bool is_constant = false; + bool is_meta_type = false; // Whether the value can be used as a type + bool infer_type = false; + bool may_yield = false; // For function calls - Variant::Type builtin_type; + Variant::Type builtin_type = Variant::NIL; StringName native_type; Ref<Script> script_type; - ClassNode *class_type; + ClassNode *class_type = nullptr; String to_string() const; @@ -94,19 +96,10 @@ public: return false; } - DataType() : - kind(UNRESOLVED), - has_type(false), - is_constant(false), - is_meta_type(false), - infer_type(false), - may_yield(false), - builtin_type(Variant::NIL), - class_type(NULL) {} + DataType() {} }; struct Node { - enum Type { TYPE_CLASS, TYPE_FUNCTION, @@ -145,7 +138,6 @@ public: struct OperatorNode; struct ClassNode : public Node { - bool tool; StringName name; bool extends_used; @@ -201,12 +193,11 @@ public: extends_used = false; classname_used = false; end_line = -1; - owner = NULL; + owner = nullptr; } }; struct FunctionNode : public Node { - bool _static; MultiplayerAPI::RPCMode rpc_mode; bool has_yield; @@ -235,67 +226,65 @@ public: }; struct BlockNode : public Node { - - ClassNode *parent_class; - BlockNode *parent_block; + ClassNode *parent_class = nullptr; + BlockNode *parent_block = nullptr; List<Node *> statements; Map<StringName, LocalVarNode *> variables; - bool has_return; + bool has_return = false; + bool can_break = false; + bool can_continue = false; - Node *if_condition; //tiny hack to improve code completion on if () blocks + Node *if_condition = nullptr; //tiny hack to improve code completion on if () blocks //the following is useful for code completion List<BlockNode *> sub_blocks; - int end_line; + int end_line = -1; + BlockNode() { - if_condition = NULL; type = TYPE_BLOCK; - end_line = -1; - parent_block = NULL; - parent_class = NULL; - has_return = false; } }; struct TypeNode : public Node { - Variant::Type vtype; - TypeNode() { type = TYPE_TYPE; } + + TypeNode() { + type = TYPE_TYPE; + } }; + struct BuiltInFunctionNode : public Node { GDScriptFunctions::Function function; - BuiltInFunctionNode() { type = TYPE_BUILT_IN_FUNCTION; } + + BuiltInFunctionNode() { + type = TYPE_BUILT_IN_FUNCTION; + } }; struct IdentifierNode : public Node { - StringName name; - BlockNode *declared_block; // Simplify lookup by checking if it is declared locally + BlockNode *declared_block = nullptr; // Simplify lookup by checking if it is declared locally DataType datatype; virtual DataType get_datatype() const { return datatype; } virtual void set_datatype(const DataType &p_datatype) { datatype = p_datatype; } + IdentifierNode() { type = TYPE_IDENTIFIER; - declared_block = NULL; } }; struct LocalVarNode : public Node { - StringName name; - Node *assign; - OperatorNode *assign_op; - int assignments; - int usages; + Node *assign = nullptr; + OperatorNode *assign_op = nullptr; + int assignments = 0; + int usages = 0; DataType datatype; virtual DataType get_datatype() const { return datatype; } virtual void set_datatype(const DataType &p_datatype) { datatype = p_datatype; } + LocalVarNode() { type = TYPE_LOCAL_VAR; - assign = NULL; - assign_op = NULL; - assignments = 0; - usages = 0; } }; @@ -304,15 +293,18 @@ public: DataType datatype; virtual DataType get_datatype() const { return datatype; } virtual void set_datatype(const DataType &p_datatype) { datatype = p_datatype; } - ConstantNode() { type = TYPE_CONSTANT; } + + ConstantNode() { + type = TYPE_CONSTANT; + } }; struct ArrayNode : public Node { - Vector<Node *> elements; DataType datatype; virtual DataType get_datatype() const { return datatype; } virtual void set_datatype(const DataType &p_datatype) { datatype = p_datatype; } + ArrayNode() { type = TYPE_ARRAY; datatype.has_type = true; @@ -322,9 +314,7 @@ public: }; struct DictionaryNode : public Node { - struct Pair { - Node *key; Node *value; }; @@ -333,6 +323,7 @@ public: DataType datatype; virtual DataType get_datatype() const { return datatype; } virtual void set_datatype(const DataType &p_datatype) { datatype = p_datatype; } + DictionaryNode() { type = TYPE_DICTIONARY; datatype.has_type = true; @@ -342,7 +333,9 @@ public: }; struct SelfNode : public Node { - SelfNode() { type = TYPE_SELF; } + SelfNode() { + type = TYPE_SELF; + } }; struct OperatorNode : public Node { @@ -404,11 +397,12 @@ public: DataType datatype; virtual DataType get_datatype() const { return datatype; } virtual void set_datatype(const DataType &p_datatype) { datatype = p_datatype; } - OperatorNode() { type = TYPE_OPERATOR; } + OperatorNode() { + type = TYPE_OPERATOR; + } }; struct PatternNode : public Node { - enum PatternType { PT_CONSTANT, PT_BIND, @@ -454,19 +448,17 @@ public: CF_MATCH }; - CFType cf_type; + CFType cf_type = CF_IF; Vector<Node *> arguments; - BlockNode *body; - BlockNode *body_else; + BlockNode *body = nullptr; + BlockNode *body_else = nullptr; MatchNode *match; ControlFlowNode *_else; //used for if + ControlFlowNode() { type = TYPE_CONTROL_FLOW; - cf_type = CF_IF; - body = NULL; - body_else = NULL; } }; @@ -476,29 +468,34 @@ public: DataType return_type; virtual DataType get_datatype() const { return return_type; } virtual void set_datatype(const DataType &p_datatype) { return_type = p_datatype; } - CastNode() { type = TYPE_CAST; } + + CastNode() { + type = TYPE_CAST; + } }; struct AssertNode : public Node { - Node *condition; - Node *message; - AssertNode() : - condition(0), - message(0) { + Node *condition = nullptr; + Node *message = nullptr; + + AssertNode() { type = TYPE_ASSERT; } }; struct BreakpointNode : public Node { - BreakpointNode() { type = TYPE_BREAKPOINT; } + BreakpointNode() { + type = TYPE_BREAKPOINT; + } }; struct NewLineNode : public Node { - NewLineNode() { type = TYPE_NEWLINE; } + NewLineNode() { + type = TYPE_NEWLINE; + } }; struct Expression { - bool is_op; union { OperatorNode::Operator op; @@ -553,8 +550,8 @@ private: int pending_newline; struct IndentLevel { - int indent; - int tabs; + int indent = 0; + int tabs = 0; bool is_mixed(IndentLevel other) { return ( @@ -563,9 +560,7 @@ private: (indent < other.indent && tabs > other.tabs)); } - IndentLevel() : - indent(0), - tabs(0) {} + IndentLevel() {} IndentLevel(int p_indent, int p_tabs) : indent(p_indent), @@ -608,11 +603,12 @@ private: bool _recover_from_completion(); bool _parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete = false, bool p_parsing_constant = false); - bool _enter_indent_block(BlockNode *p_block = NULL); + bool _enter_indent_block(BlockNode *p_block = nullptr); bool _parse_newline(); Node *_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign = false, bool p_parsing_constant = false); Node *_reduce_expression(Node *p_node, bool p_to_const = false); Node *_parse_and_reduce_expression(Node *p_parent, bool p_static, bool p_reduce_const = false, bool p_allow_assign = false); + bool _reduce_export_var_type(Variant &p_value, int p_line = 0); PatternNode *_parse_pattern(bool p_static); void _parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode *> &p_branches, bool p_static); @@ -623,6 +619,7 @@ private: void _parse_extends(ClassNode *p_class); void _parse_class(ClassNode *p_class); bool _end_statement(); + void _set_end_statement_error(String p_name); void _determine_inheritance(ClassNode *p_class, bool p_recursive = true); bool _parse_type(DataType &r_type, bool p_can_be_void = false); @@ -633,7 +630,7 @@ private: DataType _get_operation_type(const Variant::Operator p_op, const DataType &p_a, const DataType &p_b, bool &r_valid) const; Variant::Operator _get_variant_operation(const OperatorNode::Operator &p_op) const; bool _get_function_signature(DataType &p_base_type, const StringName &p_function, DataType &r_return_type, List<DataType> &r_arg_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) const; - bool _get_member_type(const DataType &p_base_type, const StringName &p_member, DataType &r_member_type) const; + bool _get_member_type(const DataType &p_base_type, const StringName &p_member, DataType &r_member_type, bool *r_is_const = nullptr) const; bool _is_type_compatible(const DataType &p_container, const DataType &p_expression, bool p_allow_implicit_conversion = false) const; Node *_get_default_value_for_type(const DataType &p_type, int p_line = -1); @@ -646,12 +643,16 @@ private: void _check_block_types(BlockNode *p_block); _FORCE_INLINE_ void _mark_line_as_safe(int p_line) const { #ifdef DEBUG_ENABLED - if (safe_lines) safe_lines->insert(p_line); + if (safe_lines) { + safe_lines->insert(p_line); + } #endif // DEBUG_ENABLED } _FORCE_INLINE_ void _mark_line_as_unsafe(int p_line) const { #ifdef DEBUG_ENABLED - if (safe_lines) safe_lines->erase(p_line); + if (safe_lines) { + safe_lines->erase(p_line); + } #endif // DEBUG_ENABLED } @@ -665,7 +666,7 @@ public: #ifdef DEBUG_ENABLED const List<GDScriptWarning> &get_warnings() const { return warnings; } #endif // DEBUG_ENABLED - Error parse(const String &p_code, const String &p_base_path = "", bool p_just_validate = false, const String &p_self_path = "", bool p_for_completion = false, Set<int> *r_safe_lines = NULL, bool p_dependencies_only = false); + Error parse(const String &p_code, const String &p_base_path = "", bool p_just_validate = false, const String &p_self_path = "", bool p_for_completion = false, Set<int> *r_safe_lines = nullptr, bool p_dependencies_only = false); Error parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &p_base_path = "", const String &p_self_path = ""); bool is_tool_script() const; @@ -682,7 +683,7 @@ public: BlockNode *get_completion_block(); FunctionNode *get_completion_function(); int get_completion_argument_index(); - int get_completion_identifier_is_function(); + bool get_completion_identifier_is_function(); const List<String> &get_dependencies() const { return dependencies; } diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 9064998d32..2db42601c6 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -178,7 +178,7 @@ static const _bit _type_list[] = { { Variant::PACKED_VECTOR2_ARRAY, "PackedVector2Array" }, { Variant::PACKED_VECTOR3_ARRAY, "PackedVector3Array" }, { Variant::PACKED_COLOR_ARRAY, "PackedColorArray" }, - { Variant::VARIANT_MAX, NULL }, + { Variant::VARIANT_MAX, nullptr }, }; struct _kws { @@ -236,11 +236,10 @@ static const _kws _keyword_list[] = { { GDScriptTokenizer::TK_WILDCARD, "_" }, { GDScriptTokenizer::TK_CONST_INF, "INF" }, { GDScriptTokenizer::TK_CONST_NAN, "NAN" }, - { GDScriptTokenizer::TK_ERROR, NULL } + { GDScriptTokenizer::TK_ERROR, nullptr } }; const char *GDScriptTokenizer::get_token_name(Token p_token) { - ERR_FAIL_INDEX_V(p_token, TK_MAX, "<error>"); return token_names[p_token]; } @@ -364,27 +363,22 @@ StringName GDScriptTokenizer::get_token_literal(int p_offset) const { } static bool _is_text_char(CharType c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; } static bool _is_number(CharType c) { - return (c >= '0' && c <= '9'); } static bool _is_hex(CharType c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } static bool _is_bin(CharType c) { - return (c == '0' || c == '1'); } void GDScriptTokenizerText::_make_token(Token p_type) { - TokenData &tk = tk_rb[tk_rb_pos]; tk.type = p_type; @@ -393,8 +387,8 @@ void GDScriptTokenizerText::_make_token(Token p_type) { tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE; } -void GDScriptTokenizerText::_make_identifier(const StringName &p_identifier) { +void GDScriptTokenizerText::_make_identifier(const StringName &p_identifier) { TokenData &tk = tk_rb[tk_rb_pos]; tk.type = TK_IDENTIFIER; @@ -406,7 +400,6 @@ void GDScriptTokenizerText::_make_identifier(const StringName &p_identifier) { } void GDScriptTokenizerText::_make_built_in_func(GDScriptFunctions::Function p_func) { - TokenData &tk = tk_rb[tk_rb_pos]; tk.type = TK_BUILT_IN_FUNC; @@ -416,8 +409,8 @@ void GDScriptTokenizerText::_make_built_in_func(GDScriptFunctions::Function p_fu tk_rb_pos = (tk_rb_pos + 1) % TK_RB_SIZE; } -void GDScriptTokenizerText::_make_constant(const Variant &p_constant) { +void GDScriptTokenizerText::_make_constant(const Variant &p_constant) { TokenData &tk = tk_rb[tk_rb_pos]; tk.type = TK_CONSTANT; @@ -429,7 +422,6 @@ void GDScriptTokenizerText::_make_constant(const Variant &p_constant) { } void GDScriptTokenizerText::_make_type(const Variant::Type &p_type) { - TokenData &tk = tk_rb[tk_rb_pos]; tk.type = TK_BUILT_IN_TYPE; @@ -441,7 +433,6 @@ void GDScriptTokenizerText::_make_type(const Variant::Type &p_type) { } void GDScriptTokenizerText::_make_error(const String &p_error) { - error_flag = true; last_error = p_error; @@ -454,7 +445,6 @@ void GDScriptTokenizerText::_make_error(const String &p_error) { } void GDScriptTokenizerText::_make_newline(int p_indentation, int p_tabs) { - TokenData &tk = tk_rb[tk_rb_pos]; tk.type = TK_NEWLINE; tk.constant = Vector2(p_indentation, p_tabs); @@ -464,7 +454,6 @@ void GDScriptTokenizerText::_make_newline(int p_indentation, int p_tabs) { } void GDScriptTokenizerText::_advance() { - if (error_flag) { //parser broke _make_error(last_error); @@ -482,7 +471,6 @@ void GDScriptTokenizerText::_advance() { column += m_amount; \ } while (true) { - bool is_string_name = false; StringMode string_mode = STRING_DOUBLE_QUOTE; @@ -570,7 +558,6 @@ void GDScriptTokenizerText::_advance() { return; } case '/': { - switch (GETCHAR(1)) { case '=': { // diveq @@ -587,13 +574,13 @@ void GDScriptTokenizerText::_advance() { _make_token(TK_OP_EQUAL); INCPOS(1); - } else + } else { _make_token(TK_OP_ASSIGN); + } } break; case '<': { if (GETCHAR(1) == '=') { - _make_token(TK_OP_LESS_EQUAL); INCPOS(1); } else if (GETCHAR(1) == '<') { @@ -604,8 +591,9 @@ void GDScriptTokenizerText::_advance() { _make_token(TK_OP_SHIFT_LEFT); } INCPOS(1); - } else + } else { _make_token(TK_OP_LESS); + } } break; case '>': { @@ -684,7 +672,6 @@ void GDScriptTokenizerText::_advance() { break; case '&': { if (GETCHAR(1) == '&') { - _make_token(TK_OP_AND); INCPOS(1); } else if (GETCHAR(1) == '=') { @@ -696,7 +683,6 @@ void GDScriptTokenizerText::_advance() { } break; case '|': { if (GETCHAR(1) == '|') { - _make_token(TK_OP_OR); INCPOS(1); } else if (GETCHAR(1) == '=') { @@ -707,7 +693,6 @@ void GDScriptTokenizerText::_advance() { } } break; case '*': { - if (GETCHAR(1) == '=') { _make_token(TK_OP_ASSIGN_MUL); INCPOS(1); @@ -716,7 +701,6 @@ void GDScriptTokenizerText::_advance() { } } break; case '+': { - if (GETCHAR(1) == '=') { _make_token(TK_OP_ASSIGN_ADD); INCPOS(1); @@ -731,7 +715,6 @@ void GDScriptTokenizerText::_advance() { } break; case '-': { - if (GETCHAR(1) == '=') { _make_token(TK_OP_ASSIGN_SUB); INCPOS(1); @@ -743,7 +726,6 @@ void GDScriptTokenizerText::_advance() { } } break; case '%': { - if (GETCHAR(1) == '=') { _make_token(TK_OP_ASSIGN_MOD); INCPOS(1); @@ -761,9 +743,9 @@ void GDScriptTokenizerText::_advance() { [[fallthrough]]; case '\'': case '"': { - - if (GETCHAR(0) == '\'') + if (GETCHAR(0) == '\'') { string_mode = STRING_SINGLE_QUOTE; + } int i = 1; if (string_mode == STRING_DOUBLE_QUOTE && GETCHAR(i) == '"' && GETCHAR(i + 1) == '"') { @@ -774,7 +756,6 @@ void GDScriptTokenizerText::_advance() { String str; while (true) { if (CharType(GETCHAR(i)) == 0) { - _make_error("Unterminated String"); return; } else if (string_mode == STRING_DOUBLE_QUOTE && CharType(GETCHAR(i)) == '"') { @@ -802,20 +783,36 @@ void GDScriptTokenizerText::_advance() { CharType res = 0; switch (next) { - - case 'a': res = 7; break; - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'v': res = 11; break; - case 'f': res = 12; break; - case 'r': res = 13; break; - case '\'': res = '\''; break; - case '\"': res = '\"'; break; - case '\\': res = '\\'; break; - case '/': - res = '/'; - break; //wtf + case 'a': + res = '\a'; + break; + case 'b': + res = '\b'; + break; + case 't': + res = '\t'; + break; + case 'n': + res = '\n'; + break; + case 'v': + res = '\v'; + break; + case 'f': + res = '\f'; + break; + case 'r': + res = '\r'; + break; + case '\'': + res = '\''; + break; + case '\"': + res = '\"'; + break; + case '\\': + res = '\\'; + break; case 'u': { // hex number @@ -847,14 +844,19 @@ void GDScriptTokenizerText::_advance() { i += 3; } break; + case '\n': { + line++; + column = 1; + } break; default: { - _make_error("Invalid escape sequence"); return; } break; } - str += res; + if (next != '\n') { + str += res; + } } else { if (CharType(GETCHAR(i)) == '\n') { @@ -879,7 +881,6 @@ void GDScriptTokenizerText::_advance() { _make_token(TK_CURSOR); } break; default: { - if (_is_number(GETCHAR(0)) || (GETCHAR(0) == '.' && _is_number(GETCHAR(1)))) { // parse number bool period_found = false; @@ -911,7 +912,6 @@ void GDScriptTokenizerText::_advance() { } hexa_found = true; } else if (hexa_found && _is_hex(GETCHAR(i))) { - } else if (!hexa_found && GETCHAR(i) == 'b') { if (bin_found || str.length() != 1 || !((i == 1 && str[0] == '0') || (i == 2 && str[1] == '0' && str[0] == '-'))) { _make_error("Invalid numeric constant at 'b'"); @@ -928,7 +928,6 @@ void GDScriptTokenizerText::_advance() { //all ok } else if (bin_found && _is_bin(GETCHAR(i))) { - } else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) { if (sign_found) { _make_error("Invalid numeric constant at '-'"); @@ -938,8 +937,9 @@ void GDScriptTokenizerText::_advance() { } else if (GETCHAR(i) == '_') { i++; continue; // Included for readability, shouldn't be a part of the string - } else + } else { break; + } str += CharType(GETCHAR(i)); i++; @@ -996,15 +996,12 @@ void GDScriptTokenizerText::_advance() { } else if (str == "false") { _make_constant(false); } else { - bool found = false; { - int idx = 0; while (_type_list[idx].text) { - if (str == _type_list[idx].text) { _make_type(_type_list[idx].type); found = true; @@ -1015,13 +1012,10 @@ void GDScriptTokenizerText::_advance() { } if (!found) { - //built in func? for (int j = 0; j < GDScriptFunctions::FUNC_MAX; j++) { - if (str == GDScriptFunctions::get_func_name(GDScriptFunctions::Function(j))) { - _make_built_in_func(GDScriptFunctions::Function(j)); found = true; break; @@ -1036,7 +1030,6 @@ void GDScriptTokenizerText::_advance() { found = false; while (_keyword_list[idx].text) { - if (str == _keyword_list[idx].text) { _make_token(_keyword_list[idx].token); found = true; @@ -1046,8 +1039,9 @@ void GDScriptTokenizerText::_advance() { } } - if (!found) + if (!found) { identifier = true; + } } if (identifier) { @@ -1069,13 +1063,12 @@ void GDScriptTokenizerText::_advance() { } void GDScriptTokenizerText::set_code(const String &p_code) { - code = p_code; len = p_code.length(); if (len) { _code = &code[0]; } else { - _code = NULL; + _code = nullptr; } code_pos = 0; line = 1; //it is stand-ar-ized that lines begin in 1 in code.. @@ -1086,8 +1079,9 @@ void GDScriptTokenizerText::set_code(const String &p_code) { ignore_warnings = false; #endif // DEBUG_ENABLED last_error = ""; - for (int i = 0; i < MAX_LOOKAHEAD + 1; i++) + for (int i = 0; i < MAX_LOOKAHEAD + 1; i++) { _advance(); + } } GDScriptTokenizerText::Token GDScriptTokenizerText::get_token(int p_offset) const { @@ -1124,7 +1118,6 @@ const Variant &GDScriptTokenizerText::get_token_constant(int p_offset) const { } StringName GDScriptTokenizerText::get_token_identifier(int p_offset) const { - ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, StringName()); ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, StringName()); @@ -1134,7 +1127,6 @@ StringName GDScriptTokenizerText::get_token_identifier(int p_offset) const { } GDScriptFunctions::Function GDScriptTokenizerText::get_token_built_in_func(int p_offset) const { - ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, GDScriptFunctions::FUNC_MAX); ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, GDScriptFunctions::FUNC_MAX); @@ -1144,7 +1136,6 @@ GDScriptFunctions::Function GDScriptTokenizerText::get_token_built_in_func(int p } Variant::Type GDScriptTokenizerText::get_token_type(int p_offset) const { - ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, Variant::NIL); ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, Variant::NIL); @@ -1154,7 +1145,6 @@ Variant::Type GDScriptTokenizerText::get_token_type(int p_offset) const { } int GDScriptTokenizerText::get_token_line_indent(int p_offset) const { - ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, 0); ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, 0); @@ -1164,7 +1154,6 @@ int GDScriptTokenizerText::get_token_line_indent(int p_offset) const { } int GDScriptTokenizerText::get_token_line_tab_indent(int p_offset) const { - ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, 0); ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, 0); @@ -1174,7 +1163,6 @@ int GDScriptTokenizerText::get_token_line_tab_indent(int p_offset) const { } String GDScriptTokenizerText::get_token_error(int p_offset) const { - ERR_FAIL_COND_V(p_offset <= -MAX_LOOKAHEAD, String()); ERR_FAIL_COND_V(p_offset >= MAX_LOOKAHEAD, String()); @@ -1184,10 +1172,10 @@ String GDScriptTokenizerText::get_token_error(int p_offset) const { } void GDScriptTokenizerText::advance(int p_amount) { - ERR_FAIL_COND(p_amount <= 0); - for (int i = 0; i < p_amount; i++) + for (int i = 0; i < p_amount; i++) { _advance(); + } } ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1195,7 +1183,6 @@ void GDScriptTokenizerText::advance(int p_amount) { #define BYTECODE_VERSION 13 Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) { - const uint8_t *buf = p_buffer.ptr(); int total_len = p_buffer.size(); ERR_FAIL_COND_V(p_buffer.size() < 24 || p_buffer[0] != 'G' || p_buffer[1] != 'D' || p_buffer[2] != 'S' || p_buffer[3] != 'C', ERR_INVALID_DATA); @@ -1213,7 +1200,6 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) identifiers.resize(identifier_count); for (int i = 0; i < identifier_count; i++) { - int len = decode_uint32(b); ERR_FAIL_COND_V(len > total_len, ERR_INVALID_DATA); b += 4; @@ -1233,13 +1219,13 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) constants.resize(constant_count); for (int i = 0; i < constant_count; i++) { - Variant v; int len; // An object cannot be constant, never decode objects Error err = decode_variant(v, b, total_len, &len, false); - if (err) + if (err) { return err; + } b += len; total_len -= len; constants.write[i] = v; @@ -1248,7 +1234,6 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) ERR_FAIL_COND_V(line_count * 8 > total_len, ERR_INVALID_DATA); for (int i = 0; i < line_count; i++) { - uint32_t token = decode_uint32(b); b += 4; uint32_t linecol = decode_uint32(b); @@ -1261,7 +1246,6 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) tokens.resize(token_count); for (int i = 0; i < token_count; i++) { - ERR_FAIL_COND_V(total_len < 1, ERR_INVALID_DATA); if ((*b) & TOKEN_BYTE_MASK) { //little endian always @@ -1282,7 +1266,6 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer) } Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) { - Vector<uint8_t> buf; Map<StringName, int> identifier_map; @@ -1295,16 +1278,13 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) int line = -1; while (true) { - if (tt.get_token_line() != line) { - line = tt.get_token_line(); line_map[line] = token_array.size(); } uint32_t token = tt.get_token(); switch (tt.get_token()) { - case TK_IDENTIFIER: { StringName id = tt.get_token_identifier(); if (!identifier_map.has(id)) { @@ -1314,7 +1294,6 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) token |= identifier_map[id] << TOKEN_BITS; } break; case TK_CONSTANT: { - const Variant &c = tt.get_token_constant(); if (!constant_map.has(c)) { int idx = constant_map.size(); @@ -1323,20 +1302,16 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) token |= constant_map[c] << TOKEN_BITS; } break; case TK_BUILT_IN_TYPE: { - token |= tt.get_token_type() << TOKEN_BITS; } break; case TK_BUILT_IN_FUNC: { - token |= tt.get_token_built_in_func() << TOKEN_BITS; } break; case TK_NEWLINE: { - token |= tt.get_token_line_indent() << TOKEN_BITS; } break; case TK_ERROR: { - ERR_FAIL_V(Vector<uint8_t>()); } break; default: { @@ -1345,8 +1320,9 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) token_array.push_back(token); - if (tt.get_token() == TK_EOF) + if (tt.get_token() == TK_EOF) { break; + } tt.advance(); } @@ -1358,7 +1334,7 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) } Map<int, Variant> rev_constant_map; - const Variant *K = NULL; + const Variant *K = nullptr; while ((K = constant_map.next(K))) { rev_constant_map[constant_map[*K]] = *K; } @@ -1383,12 +1359,12 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) //save identifiers for (Map<int, StringName>::Element *E = rev_identifier_map.front(); E; E = E->next()) { - CharString cs = String(E->get()).utf8(); int len = cs.length() + 1; int extra = 4 - (len % 4); - if (extra == 4) + if (extra == 4) { extra = 0; + } uint8_t ibuf[4]; encode_uint32(len + extra, ibuf); @@ -1404,10 +1380,9 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) } for (Map<int, Variant>::Element *E = rev_constant_map.front(); E; E = E->next()) { - int len; // Objects cannot be constant, never encode objects - Error err = encode_variant(E->get(), NULL, len, false); + Error err = encode_variant(E->get(), nullptr, len, false); ERR_FAIL_COND_V_MSG(err != OK, Vector<uint8_t>(), "Error when trying to encode Variant."); int pos = buf.size(); buf.resize(pos + len); @@ -1415,16 +1390,15 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) } for (Map<int, uint32_t>::Element *E = rev_line_map.front(); E; E = E->next()) { - uint8_t ibuf[8]; encode_uint32(E->key(), &ibuf[0]); encode_uint32(E->get(), &ibuf[4]); - for (int i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { buf.push_back(ibuf[i]); + } } for (int i = 0; i < token_array.size(); i++) { - uint32_t token = token_array[i]; if (token & ~TOKEN_MASK) { @@ -1442,17 +1416,16 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code) } GDScriptTokenizerBuffer::Token GDScriptTokenizerBuffer::get_token(int p_offset) const { - int offset = token + p_offset; - if (offset < 0 || offset >= tokens.size()) + if (offset < 0 || offset >= tokens.size()) { return TK_EOF; + } return GDScriptTokenizerBuffer::Token(tokens[offset] & TOKEN_MASK); } StringName GDScriptTokenizerBuffer::get_token_identifier(int p_offset) const { - int offset = token + p_offset; ERR_FAIL_INDEX_V(offset, tokens.size(), StringName()); @@ -1463,14 +1436,12 @@ StringName GDScriptTokenizerBuffer::get_token_identifier(int p_offset) const { } GDScriptFunctions::Function GDScriptTokenizerBuffer::get_token_built_in_func(int p_offset) const { - int offset = token + p_offset; ERR_FAIL_INDEX_V(offset, tokens.size(), GDScriptFunctions::FUNC_MAX); return GDScriptFunctions::Function(tokens[offset] >> TOKEN_BITS); } Variant::Type GDScriptTokenizerBuffer::get_token_type(int p_offset) const { - int offset = token + p_offset; ERR_FAIL_INDEX_V(offset, tokens.size(), Variant::NIL); @@ -1478,55 +1449,57 @@ Variant::Type GDScriptTokenizerBuffer::get_token_type(int p_offset) const { } int GDScriptTokenizerBuffer::get_token_line(int p_offset) const { - int offset = token + p_offset; int pos = lines.find_nearest(offset); - if (pos < 0) + if (pos < 0) { return -1; - if (pos >= lines.size()) + } + if (pos >= lines.size()) { pos = lines.size() - 1; + } uint32_t l = lines.getv(pos); return l & TOKEN_LINE_MASK; } -int GDScriptTokenizerBuffer::get_token_column(int p_offset) const { +int GDScriptTokenizerBuffer::get_token_column(int p_offset) const { int offset = token + p_offset; int pos = lines.find_nearest(offset); - if (pos < 0) + if (pos < 0) { return -1; - if (pos >= lines.size()) + } + if (pos >= lines.size()) { pos = lines.size() - 1; + } uint32_t l = lines.getv(pos); return l >> TOKEN_LINE_BITS; } -int GDScriptTokenizerBuffer::get_token_line_indent(int p_offset) const { +int GDScriptTokenizerBuffer::get_token_line_indent(int p_offset) const { int offset = token + p_offset; ERR_FAIL_INDEX_V(offset, tokens.size(), 0); return tokens[offset] >> TOKEN_BITS; } -const Variant &GDScriptTokenizerBuffer::get_token_constant(int p_offset) const { +const Variant &GDScriptTokenizerBuffer::get_token_constant(int p_offset) const { int offset = token + p_offset; ERR_FAIL_INDEX_V(offset, tokens.size(), nil); uint32_t constant = tokens[offset] >> TOKEN_BITS; ERR_FAIL_UNSIGNED_INDEX_V(constant, (uint32_t)constants.size(), nil); return constants[constant]; } -String GDScriptTokenizerBuffer::get_token_error(int p_offset) const { +String GDScriptTokenizerBuffer::get_token_error(int p_offset) const { ERR_FAIL_V(String()); } void GDScriptTokenizerBuffer::advance(int p_amount) { - ERR_FAIL_INDEX(p_amount + token, tokens.size()); token += p_amount; } -GDScriptTokenizerBuffer::GDScriptTokenizerBuffer() { +GDScriptTokenizerBuffer::GDScriptTokenizerBuffer() { token = 0; } diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index 1b432ae8c1..32603c010f 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -32,6 +32,7 @@ #define GDSCRIPT_TOKENIZER_H #include "core/pair.h" +#include "core/set.h" #include "core/string_name.h" #include "core/ustring.h" #include "core/variant.h" @@ -175,11 +176,10 @@ public: virtual bool is_ignoring_warnings() const = 0; #endif // DEBUG_ENABLED - virtual ~GDScriptTokenizer(){}; + virtual ~GDScriptTokenizer() {} }; class GDScriptTokenizerText : public GDScriptTokenizer { - enum { MAX_LOOKAHEAD = 4, TK_RB_SIZE = MAX_LOOKAHEAD * 2 + 1 @@ -251,7 +251,6 @@ public: }; class GDScriptTokenizerBuffer : public GDScriptTokenizer { - enum { TOKEN_BYTE_MASK = 0x80, diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 0f6f13944b..f87e8687e5 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -35,7 +35,6 @@ #include "gdscript_workspace.h" void ExtendGDScriptParser::update_diagnostics() { - diagnostics.clear(); if (has_error()) { @@ -80,12 +79,10 @@ void ExtendGDScriptParser::update_diagnostics() { } void ExtendGDScriptParser::update_symbols() { - members.clear(); const GDScriptParser::Node *head = get_parse_tree(); if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { - parse_class_symbol(gdclass, class_symbol); for (int i = 0; i < class_symbol.children.size(); i++) { @@ -141,15 +138,15 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) { } void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p_class, lsp::DocumentSymbol &r_symbol) { - const String uri = get_uri(); r_symbol.uri = uri; r_symbol.script_path = path; r_symbol.children.clear(); r_symbol.name = p_class->name; - if (r_symbol.name.empty()) + if (r_symbol.name.empty()) { r_symbol.name = path.get_file(); + } r_symbol.kind = lsp::SymbolKind::Class; r_symbol.deprecated = false; r_symbol.range.start.line = LINE_NUMBER_TO_INDEX(p_class->line); @@ -161,7 +158,6 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p r_symbol.documentation = parse_documentation(is_root_class ? 0 : LINE_NUMBER_TO_INDEX(p_class->line), is_root_class); for (int i = 0; i < p_class->variables.size(); ++i) { - const GDScriptParser::ClassNode::Member &m = p_class->variables[i]; lsp::DocumentSymbol symbol; @@ -289,7 +285,6 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p } void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionNode *p_func, lsp::DocumentSymbol &r_symbol) { - const String uri = get_uri(); r_symbol.name = p_func->name; @@ -327,7 +322,7 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN int default_value_idx = i - (p_func->arguments.size() - p_func->default_values.size()); if (default_value_idx >= 0) { const GDScriptParser::ConstantNode *const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(p_func->default_values[default_value_idx]); - if (const_node == NULL) { + if (const_node == nullptr) { const GDScriptParser::OperatorNode *operator_node = dynamic_cast<const GDScriptParser::OperatorNode *>(p_func->default_values[default_value_idx]); if (operator_node) { const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(operator_node->next); @@ -384,8 +379,9 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) { int step = p_docs_down ? 1 : -1; int start_line = p_docs_down ? p_line : p_line - 1; for (int i = start_line; true; i += step) { - - if (i < 0 || i >= lines.size()) break; + if (i < 0 || i >= lines.size()) { + break; + } String line_comment = lines[i].strip_edges(true, false); if (line_comment.begins_with("#")) { @@ -408,22 +404,20 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) { } String ExtendGDScriptParser::get_text_for_completion(const lsp::Position &p_cursor) const { - String longthing; int len = lines.size(); for (int i = 0; i < len; i++) { - if (i == p_cursor.line) { longthing += lines[i].substr(0, p_cursor.character); longthing += String::chr(0xFFFF); //not unicode, represents the cursor longthing += lines[i].substr(p_cursor.character, lines[i].size()); } else { - longthing += lines[i]; } - if (i != len - 1) + if (i != len - 1) { longthing += "\n"; + } } return longthing; @@ -433,7 +427,6 @@ String ExtendGDScriptParser::get_text_for_lookup_symbol(const lsp::Position &p_c String longthing; int len = lines.size(); for (int i = 0; i < len; i++) { - if (i == p_cursor.line) { String line = lines[i]; String first_part = line.substr(0, p_cursor.character); @@ -457,19 +450,18 @@ String ExtendGDScriptParser::get_text_for_lookup_symbol(const lsp::Position &p_c } longthing += last_part; } else { - longthing += lines[i]; } - if (i != len - 1) + if (i != len - 1) { longthing += "\n"; + } } return longthing; } String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position &p_position, Vector2i &p_offset) const { - ERR_FAIL_INDEX_V(p_position.line, lines.size(), ""); String line = lines[p_position.line]; ERR_FAIL_INDEX_V(p_position.character, line.size(), ""); @@ -507,7 +499,7 @@ String ExtendGDScriptParser::get_uri() const { } const lsp::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(int p_line, const lsp::DocumentSymbol &p_parent) const { - const lsp::DocumentSymbol *ret = NULL; + const lsp::DocumentSymbol *ret = nullptr; if (p_line < p_parent.range.start.line) { return ret; } else if (p_parent.range.start.line == p_line) { @@ -524,7 +516,6 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(i } Error ExtendGDScriptParser::get_left_function_call(const lsp::Position &p_position, lsp::Position &r_func_pos, int &r_arg_index) const { - ERR_FAIL_INDEX_V(p_position.line, lines.size(), ERR_INVALID_PARAMETER); int bracket_stack = 0; @@ -576,7 +567,6 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::get_symbol_defined_at_line(int } const lsp::DocumentSymbol *ExtendGDScriptParser::get_member_symbol(const String &p_name, const String &p_subclass) const { - if (p_subclass.empty()) { const lsp::DocumentSymbol *const *ptr = members.getptr(p_name); if (ptr) { @@ -591,7 +581,7 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::get_member_symbol(const String } } - return NULL; + return nullptr; } const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const { @@ -599,12 +589,9 @@ const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const } const Array &ExtendGDScriptParser::get_member_completions() { - if (member_completions.empty()) { - - const String *name = members.next(NULL); + const String *name = members.next(nullptr); while (name) { - const lsp::DocumentSymbol *symbol = members.get(*name); lsp::CompletionItem item = symbol->make_completion_item(); item.data = JOIN_SYMBOLS(path, *name); @@ -613,11 +600,10 @@ const Array &ExtendGDScriptParser::get_member_completions() { name = members.next(name); } - const String *_class = inner_classes.next(NULL); + const String *_class = inner_classes.next(nullptr); while (_class) { - const ClassMembers *inner_class = inner_classes.getptr(*_class); - const String *member_name = inner_class->next(NULL); + const String *member_name = inner_class->next(nullptr); while (member_name) { const lsp::DocumentSymbol *symbol = inner_class->get(*member_name); lsp::CompletionItem item = symbol->make_completion_item(); @@ -648,7 +634,7 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio int default_value_idx = i - (p_func->arguments.size() - p_func->default_values.size()); if (default_value_idx >= 0) { const GDScriptParser::ConstantNode *const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(p_func->default_values[default_value_idx]); - if (const_node == NULL) { + if (const_node == nullptr) { const GDScriptParser::OperatorNode *operator_node = dynamic_cast<const GDScriptParser::OperatorNode *>(p_func->default_values[default_value_idx]); if (operator_node) { const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(operator_node->next); @@ -696,7 +682,6 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode Array constants; for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_class->constant_expressions.front(); E; E = E->next()) { - const GDScriptParser::ClassNode::Constant &c = E->value(); const GDScriptParser::ConstantNode *node = dynamic_cast<const GDScriptParser::ConstantNode *>(c.expression); ERR_FAIL_COND_V(!node, class_api); @@ -765,7 +750,6 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode } Dictionary ExtendGDScriptParser::generate_api() const { - Dictionary api; const GDScriptParser::Node *head = get_parse_tree(); if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { @@ -778,7 +762,7 @@ Error ExtendGDScriptParser::parse(const String &p_code, const String &p_path) { path = p_path; lines = p_code.split("\n"); - Error err = GDScriptParser::parse(p_code, p_path.get_base_dir(), false, p_path, false, NULL, false); + Error err = GDScriptParser::parse(p_code, p_path.get_base_dir(), false, p_path, false, nullptr, false); update_diagnostics(); update_symbols(); update_document_links(p_code); diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h index 43dfce994b..0c031d7883 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.h +++ b/modules/gdscript/language_server/gdscript_extend_parser.h @@ -50,7 +50,6 @@ typedef HashMap<String, const lsp::DocumentSymbol *> ClassMembers; class ExtendGDScriptParser : public GDScriptParser { - String path; Vector<String> lines; diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index 2243a7b81d..35bf4287b8 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -35,7 +35,7 @@ #include "editor/editor_log.h" #include "editor/editor_node.h" -GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = NULL; +GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = nullptr; Error GDScriptLanguageProtocol::LSPeer::handle_data() { int read = 0; @@ -47,10 +47,11 @@ Error GDScriptLanguageProtocol::LSPeer::handle_data() { ERR_FAIL_COND_V_MSG(true, ERR_OUT_OF_MEMORY, "Response header too big"); } Error err = connection->get_partial_data(&req_buf[req_pos], 1, read); - if (err != OK) + if (err != OK) { return FAILED; - else if (read != 1) // Busy, wait until next poll + } else if (read != 1) { // Busy, wait until next poll return ERR_BUSY; + } char *r = (char *)req_buf; int l = req_pos; @@ -75,10 +76,11 @@ Error GDScriptLanguageProtocol::LSPeer::handle_data() { ERR_FAIL_COND_V_MSG(req_pos >= LSP_MAX_BUFFER_SIZE, ERR_OUT_OF_MEMORY, "Response content too big"); } Error err = connection->get_partial_data(&req_buf[req_pos], 1, read); - if (err != OK) + if (err != OK) { return FAILED; - else if (read != 1) + } else if (read != 1) { return ERR_BUSY; + } req_pos++; } @@ -145,7 +147,6 @@ String GDScriptLanguageProtocol::process_message(const String &p_text) { } String GDScriptLanguageProtocol::format_output(const String &p_text) { - String header = "Content-Length: "; CharString charstr = p_text.utf8(); size_t len = charstr.length(); @@ -168,7 +169,6 @@ void GDScriptLanguageProtocol::_bind_methods() { } Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) { - lsp::InitializeResult ret; String root_uri = p_params["rootUri"]; @@ -183,7 +183,6 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) { if (root_uri.length() && is_same_workspace) { workspace->root_uri = root_uri; } else { - workspace->root_uri = "file://" + workspace->root; Dictionary params; @@ -191,7 +190,7 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) { Dictionary request = make_notification("gdscrip_client/changeWorkspace", params); Ref<LSPeer> peer = clients.get(latest_client_id); - if (peer != NULL) { + if (peer != nullptr) { String msg = JSON::print(request); msg = format_output(msg); (*peer)->res_queue.push_back(msg.utf8()); @@ -208,12 +207,10 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) { } void GDScriptLanguageProtocol::initialized(const Variant &p_params) { - lsp::GodotCapabilities capabilities; DocData *doc = EditorHelp::get_doc_data(); for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) { - lsp::GodotNativeClassInfo gdclass; gdclass.name = E->get().name; gdclass.class_doc = &(E->get()); @@ -230,26 +227,26 @@ void GDScriptLanguageProtocol::poll() { if (server->is_connection_available()) { on_client_connected(); } - const int *id = NULL; + const int *id = nullptr; while ((id = clients.next(id))) { Ref<LSPeer> peer = clients.get(*id); StreamPeerTCP::Status status = peer->connection->get_status(); if (status == StreamPeerTCP::STATUS_NONE || status == StreamPeerTCP::STATUS_ERROR) { on_client_disconnected(*id); - id = NULL; + id = nullptr; } else { if (peer->connection->get_available_bytes() > 0) { latest_client_id = *id; Error err = peer->handle_data(); if (err != OK && err != ERR_BUSY) { on_client_disconnected(*id); - id = NULL; + id = nullptr; } } Error err = peer->send_data(); if (err != OK && err != ERR_BUSY) { on_client_disconnected(*id); - id = NULL; + id = nullptr; } } } @@ -260,7 +257,7 @@ Error GDScriptLanguageProtocol::start(int p_port, const IP_Address &p_bind_ip) { } void GDScriptLanguageProtocol::stop() { - const int *id = NULL; + const int *id = nullptr; while ((id = clients.next(id))) { Ref<LSPeer> peer = clients.get(*id); peer->connection->disconnect_from_host(); @@ -274,7 +271,7 @@ void GDScriptLanguageProtocol::notify_client(const String &p_method, const Varia p_client_id = latest_client_id; } Ref<LSPeer> peer = clients.get(p_client_id); - ERR_FAIL_COND(peer == NULL); + ERR_FAIL_COND(peer == nullptr); Dictionary message = make_notification(p_method, p_params); String msg = JSON::print(message); diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 7170c63058..d53914814f 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -35,7 +35,7 @@ #include "editor/editor_node.h" GDScriptLanguageServer::GDScriptLanguageServer() { - thread = NULL; + thread = nullptr; thread_running = false; started = false; @@ -48,7 +48,6 @@ GDScriptLanguageServer::GDScriptLanguageServer() { } void GDScriptLanguageServer::_notification(int p_what) { - switch (p_what) { case NOTIFICATION_ENTER_TREE: start(); @@ -87,7 +86,7 @@ void GDScriptLanguageServer::start() { if (protocol.start(port, IP_Address("127.0.0.1")) == OK) { EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR); if (use_thread) { - ERR_FAIL_COND(thread != NULL); + ERR_FAIL_COND(thread != nullptr); thread_running = true; thread = Thread::create(GDScriptLanguageServer::thread_main, this); } @@ -98,11 +97,11 @@ void GDScriptLanguageServer::start() { void GDScriptLanguageServer::stop() { if (use_thread) { - ERR_FAIL_COND(NULL == thread); + ERR_FAIL_COND(nullptr == thread); thread_running = false; Thread::wait_to_finish(thread); memdelete(thread); - thread = NULL; + thread = nullptr; } protocol.stop(); started = false; diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index d5723fd20f..778cb4d254 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -35,6 +35,7 @@ #include "editor/plugins/script_text_editor.h" #include "gdscript_extend_parser.h" #include "gdscript_language_protocol.h" +#include "servers/display_server.h" void GDScriptTextDocument::_bind_methods() { ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen); @@ -84,19 +85,15 @@ void GDScriptTextDocument::notify_client_show_symbol(const lsp::DocumentSymbol * } void GDScriptTextDocument::initialize() { - if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { - const HashMap<StringName, ClassMembers> &native_members = GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members; - const StringName *class_ptr = native_members.next(NULL); + const StringName *class_ptr = native_members.next(nullptr); while (class_ptr) { - const ClassMembers &members = native_members.get(*class_ptr); - const String *name = members.next(NULL); + const String *name = members.next(nullptr); while (name) { - const lsp::DocumentSymbol *symbol = members.get(*name); lsp::CompletionItem item = symbol->make_completion_item(); item.data = JOIN_SYMBOLS(String(*class_ptr), *name); @@ -111,7 +108,6 @@ void GDScriptTextDocument::initialize() { } Variant GDScriptTextDocument::nativeSymbol(const Dictionary &p_params) { - Variant ret; lsp::NativeSymbolInspectParams params; @@ -141,7 +137,6 @@ Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) { } Array GDScriptTextDocument::completion(const Dictionary &p_params) { - Array arr; lsp::CompletionParams params; @@ -152,12 +147,10 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { GDScriptLanguageProtocol::get_singleton()->get_workspace()->completion(params, &options); if (!options.empty()) { - int i = 0; arr.resize(options.size()); for (const List<ScriptCodeCompletionOption>::Element *E = options.front(); E; E = E->next()) { - const ScriptCodeCompletionOption &option = E->get(); lsp::CompletionItem item; item.label = option.display; @@ -200,11 +193,9 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { i++; } } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { - arr = native_member_completions.duplicate(); for (Map<String, ExtendGDScriptParser *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.front(); E; E = E->next()) { - ExtendGDScriptParser *script = E->get(); const Array &items = script->get_member_completions(); @@ -219,28 +210,24 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { } Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) { - lsp::CompletionItem item; item.load(p_params); lsp::CompletionParams params; Variant data = p_params["data"]; - const lsp::DocumentSymbol *symbol = NULL; + const lsp::DocumentSymbol *symbol = nullptr; if (data.get_type() == Variant::DICTIONARY) { - params.load(p_params["data"]); symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params, item.label, item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function); } else if (data.get_type() == Variant::STRING) { - String query = data; Vector<String> param_symbols = query.split(SYMBOL_SEPERATOR, false); if (param_symbols.size() >= 2) { - String class_ = param_symbols[0]; StringName class_name = class_; String member_name = param_symbols[param_symbols.size() - 1]; @@ -312,13 +299,11 @@ Array GDScriptTextDocument::colorPresentation(const Dictionary &p_params) { } Variant GDScriptTextDocument::hover(const Dictionary &p_params) { - lsp::TextDocumentPositionParams params; params.load(p_params); const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params); if (symbol) { - lsp::Hover hover; hover.contents = symbol->render(); hover.range.start = params.position; @@ -326,7 +311,6 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) { return hover.to_json(); } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { - Dictionary ret; Array contents; List<const lsp::DocumentSymbol *> list; @@ -419,7 +403,8 @@ void GDScriptTextDocument::sync_script_content(const String &p_path, const Strin void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) { ScriptEditor::get_singleton()->call_deferred("_help_class_goto", p_symbol_id); - OS::get_singleton()->move_window_to_foreground(); + + DisplayServer::get_singleton()->window_move_to_foreground(); } Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams &p_location, List<const lsp::DocumentSymbol *> &r_list) { diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 205257b8f2..9285d88157 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -71,7 +71,6 @@ void GDScriptWorkspace::remove_cache_parser(const String &p_path) { } const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_class, const String &p_member) const { - StringName class_name = p_class; StringName empty; @@ -93,7 +92,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_ class_name = ClassDB::get_parent_class(class_name); } - return NULL; + return nullptr; } const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_path) const { @@ -101,7 +100,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_ if (S) { return &(S->get()->get_symbols()); } - return NULL; + return nullptr; } void GDScriptWorkspace::reload_all_workspace_scripts() { @@ -152,7 +151,7 @@ ExtendGDScriptParser *GDScriptWorkspace::get_parse_successed_script(const String if (S) { return S->get(); } - return NULL; + return nullptr; } ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path) { @@ -164,7 +163,7 @@ ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path) if (S) { return S->get(); } - return NULL; + return nullptr; } Array GDScriptWorkspace::symbol(const Dictionary &p_params) { @@ -185,11 +184,12 @@ Array GDScriptWorkspace::symbol(const Dictionary &p_params) { } Error GDScriptWorkspace::initialize() { - if (initialized) return OK; + if (initialized) { + return OK; + } DocData *doc = EditorHelp::get_doc_data(); for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) { - const DocData::ClassDoc &class_data = E->value(); lsp::DocumentSymbol class_symbol; String class_name = E->key(); @@ -314,14 +314,12 @@ Error GDScriptWorkspace::initialize() { } Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_content) { - ExtendGDScriptParser *parser = memnew(ExtendGDScriptParser); Error err = parser->parse(p_content, p_path); Map<String, ExtendGDScriptParser *>::Element *last_parser = parse_results.find(p_path); Map<String, ExtendGDScriptParser *>::Element *last_script = scripts.find(p_path); if (err == OK) { - remove_cache_parser(p_path); parse_results[p_path] = parser; scripts[p_path] = parser; @@ -377,15 +375,15 @@ void GDScriptWorkspace::publish_diagnostics(const String &p_path) { } void GDScriptWorkspace::_get_owners(EditorFileSystemDirectory *efsd, String p_path, List<String> &owners) { - if (!efsd) + if (!efsd) { return; + } for (int i = 0; i < efsd->get_subdir_count(); i++) { _get_owners(efsd->get_subdir(i), p_path, owners); } for (int i = 0; i < efsd->get_file_count(); i++) { - Vector<String> deps = efsd->get_file_deps(i); bool found = false; for (int j = 0; j < deps.size(); j++) { @@ -394,15 +392,16 @@ void GDScriptWorkspace::_get_owners(EditorFileSystemDirectory *efsd, String p_pa break; } } - if (!found) + if (!found) { continue; + } owners.push_back(efsd->get_file_path(i)); } } Node *GDScriptWorkspace::_get_owner_scene_node(String p_path) { - Node *owner_scene_node = NULL; + Node *owner_scene_node = nullptr; List<String> owners; _get_owners(EditorFileSystem::get_singleton()->get_filesystem(), p_path, owners); @@ -421,7 +420,6 @@ Node *GDScriptWorkspace::_get_owner_scene_node(String p_path) { } void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<ScriptCodeCompletionOption> *r_options) { - String path = get_file_path(p_params.textDocument.uri); String call_hint; bool forced = false; @@ -437,12 +435,10 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S } const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name, bool p_func_requred) { - - const lsp::DocumentSymbol *symbol = NULL; + const lsp::DocumentSymbol *symbol = nullptr; String path = get_file_path(p_doc_pos.textDocument.uri); if (const ExtendGDScriptParser *parser = get_parse_result(path)) { - String symbol_identifier = p_symbol_name; Vector<String> identifier_parts = symbol_identifier.split("("); if (identifier_parts.size()) { @@ -457,19 +453,14 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu } if (!symbol_identifier.empty()) { - if (ScriptServer::is_global_class(symbol_identifier)) { - String class_path = ScriptServer::get_global_class_path(symbol_identifier); symbol = get_script_symbol(class_path); } else { - ScriptLanguage::LookupResult ret; - if (OK == GDScriptLanguage::get_singleton()->lookup_code(parser->get_text_for_lookup_symbol(pos, symbol_identifier, p_func_requred), symbol_identifier, path, NULL, ret)) { - + if (OK == GDScriptLanguage::get_singleton()->lookup_code(parser->get_text_for_lookup_symbol(pos, symbol_identifier, p_func_requred), symbol_identifier, path, nullptr, ret)) { if (ret.type == ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION) { - String target_script_path = path; if (!ret.script.is_null()) { target_script_path = ret.script->get_path(); @@ -480,7 +471,6 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu } } else { - String member = ret.class_member; if (member.empty() && symbol_identifier != ret.class_name) { member = symbol_identifier; @@ -498,15 +488,13 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu } void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionParams &p_doc_pos, List<const lsp::DocumentSymbol *> &r_list) { - String path = get_file_path(p_doc_pos.textDocument.uri); if (const ExtendGDScriptParser *parser = get_parse_result(path)) { - String symbol_identifier; Vector2i offset; symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, offset); - const StringName *class_ptr = native_members.next(NULL); + const StringName *class_ptr = native_members.next(nullptr); while (class_ptr) { const ClassMembers &members = native_members.get(*class_ptr); if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) { @@ -523,9 +511,8 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP } const HashMap<String, ClassMembers> &inner_classes = script->get_inner_classes(); - const String *_class = inner_classes.next(NULL); + const String *_class = inner_classes.next(nullptr); while (_class) { - const ClassMembers *inner_class = inner_classes.getptr(*_class); if (const lsp::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) { r_list.push_back(*symbol); @@ -538,7 +525,6 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP } const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params) { - if (Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(p_params.native_class)) { const lsp::DocumentSymbol &symbol = E->get(); if (p_params.symbol_name.empty() || p_params.symbol_name == symbol.name) { @@ -552,7 +538,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::N } } - return NULL; + return nullptr; } void GDScriptWorkspace::resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list) { @@ -574,12 +560,10 @@ Dictionary GDScriptWorkspace::generate_script_api(const String &p_path) { Error GDScriptWorkspace::resolve_signature(const lsp::TextDocumentPositionParams &p_doc_pos, lsp::SignatureHelp &r_signature) { if (const ExtendGDScriptParser *parser = get_parse_result(get_file_path(p_doc_pos.textDocument.uri))) { - lsp::TextDocumentPositionParams text_pos; text_pos.textDocument = p_doc_pos.textDocument; if (parser->get_left_function_call(p_doc_pos.position, text_pos.position, r_signature.activeParameter) == OK) { - List<const lsp::DocumentSymbol *> symbols; if (const lsp::DocumentSymbol *symbol = resolve_symbol(text_pos)) { @@ -591,7 +575,6 @@ Error GDScriptWorkspace::resolve_signature(const lsp::TextDocumentPositionParams for (List<const lsp::DocumentSymbol *>::Element *E = symbols.front(); E; E = E->next()) { const lsp::DocumentSymbol *symbol = E->get(); if (symbol->kind == lsp::SymbolKind::Method || symbol->kind == lsp::SymbolKind::Function) { - lsp::SignatureInformation signature_info; signature_info.label = symbol->detail; signature_info.documentation = symbol->render(); diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp index a2dcc48820..cf27a1578c 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/lsp.hpp @@ -33,7 +33,7 @@ #include "core/class_db.h" #include "core/list.h" -#include "editor/doc/doc_data.h" +#include "editor/doc_data.h" namespace lsp { @@ -149,14 +149,13 @@ struct Location { * Represents a link between a source and a target location. */ struct LocationLink { - /** * Span of the origin of this link. * * Used as the underlined span for mouse interaction. Defaults to the word range at * the mouse position. */ - Range *originSelectionRange = NULL; + Range *originSelectionRange = nullptr; /** * The target resource identifier of this link. @@ -220,7 +219,6 @@ struct DocumentLinkParams { * text document or a web site. */ struct DocumentLink { - /** * The range this link applies to. */ @@ -282,7 +280,9 @@ struct Command { Dictionary dict; dict["title"] = title; dict["command"] = command; - if (arguments.size()) dict["arguments"] = arguments; + if (arguments.size()) { + dict["arguments"] = arguments; + } return dict; } }; @@ -486,7 +486,7 @@ struct TextDocumentSyncOptions { * If present save notifications are sent to the server. If omitted the notification should not be * sent. */ - SaveOptions save; + bool save = false; Dictionary to_json() { Dictionary dict; @@ -494,7 +494,7 @@ struct TextDocumentSyncOptions { dict["willSave"] = willSave; dict["openClose"] = openClose; dict["change"] = change; - dict["save"] = save.to_json(); + dict["save"] = save; return dict; } }; @@ -946,16 +946,24 @@ struct CompletionItem { dict["preselect"] = preselect; dict["sortText"] = sortText; dict["filterText"] = filterText; - if (commitCharacters.size()) dict["commitCharacters"] = commitCharacters; + if (commitCharacters.size()) { + dict["commitCharacters"] = commitCharacters; + } dict["command"] = command.to_json(); } return dict; } void load(const Dictionary &p_dict) { - if (p_dict.has("label")) label = p_dict["label"]; - if (p_dict.has("kind")) kind = p_dict["kind"]; - if (p_dict.has("detail")) detail = p_dict["detail"]; + if (p_dict.has("label")) { + label = p_dict["label"]; + } + if (p_dict.has("kind")) { + kind = p_dict["kind"]; + } + if (p_dict.has("detail")) { + detail = p_dict["detail"]; + } if (p_dict.has("documentation")) { Variant doc = p_dict["documentation"]; if (doc.get_type() == Variant::STRING) { @@ -965,12 +973,24 @@ struct CompletionItem { documentation.value = v["value"]; } } - if (p_dict.has("deprecated")) deprecated = p_dict["deprecated"]; - if (p_dict.has("preselect")) preselect = p_dict["preselect"]; - if (p_dict.has("sortText")) sortText = p_dict["sortText"]; - if (p_dict.has("filterText")) filterText = p_dict["filterText"]; - if (p_dict.has("insertText")) insertText = p_dict["insertText"]; - if (p_dict.has("data")) data = p_dict["data"]; + if (p_dict.has("deprecated")) { + deprecated = p_dict["deprecated"]; + } + if (p_dict.has("preselect")) { + preselect = p_dict["preselect"]; + } + if (p_dict.has("sortText")) { + sortText = p_dict["sortText"]; + } + if (p_dict.has("filterText")) { + filterText = p_dict["filterText"]; + } + if (p_dict.has("insertText")) { + insertText = p_dict["insertText"]; + } + if (p_dict.has("data")) { + data = p_dict["data"]; + } } }; @@ -1096,7 +1116,6 @@ struct DocumentedSymbolInformation : public SymbolInformation { * e.g. the range of an identifier. */ struct DocumentSymbol { - /** * The name of this symbol. Will be displayed in the user interface and therefore must not be * an empty string or a string only consisting of white spaces. @@ -1205,7 +1224,6 @@ struct DocumentSymbol { } _FORCE_INLINE_ CompletionItem make_completion_item(bool resolved = false) const { - lsp::CompletionItem item; item.label = name; @@ -1249,7 +1267,6 @@ struct DocumentSymbol { }; struct NativeSymbolInspectParams { - String native_class; String symbol_name; @@ -1281,7 +1298,6 @@ static const String Region = "region"; * Represents a folding range. */ struct FoldingRange { - /** * The zero-based line number from where the folded range starts. */ @@ -1364,7 +1380,6 @@ struct CompletionContext { }; struct CompletionParams : public TextDocumentPositionParams { - /** * The completion context. This is only available if the client specifies * to send this using `ClientCapabilities.textDocument.completion.contextSupport === true` @@ -1405,7 +1420,6 @@ struct Hover { * have a label and a doc-comment. */ struct ParameterInformation { - /** * The label of this parameter information. * @@ -1642,7 +1656,7 @@ struct ServerCapabilities { _FORCE_INLINE_ Dictionary to_json() { Dictionary dict; - dict["textDocumentSync"] = (int)textDocumentSync.change; + dict["textDocumentSync"] = textDocumentSync.to_json(); dict["completionProvider"] = completionProvider.to_json(); signatureHelpProvider.triggerCharacters.push_back(","); signatureHelpProvider.triggerCharacters.push_back("("); @@ -1684,10 +1698,9 @@ struct InitializeResult { }; struct GodotNativeClassInfo { - String name; - const DocData::ClassDoc *class_doc = NULL; - const ClassDB::ClassInfo *class_info = NULL; + const DocData::ClassDoc *class_doc = nullptr; + const ClassDB::ClassInfo *class_info = nullptr; Dictionary to_json() { Dictionary dict; @@ -1699,7 +1712,6 @@ struct GodotNativeClassInfo { /** Features not included in the standard lsp specifications */ struct GodotCapabilities { - /** * Native class list */ @@ -1718,7 +1730,6 @@ struct GodotCapabilities { /** Format BBCode documentation from DocData to markdown */ static String marked_documentation(const String &p_bbcode) { - String markdown = p_bbcode.strip_edges(); Vector<String> lines = markdown.split("\n"); diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index b5eb09d6ba..0625123530 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -37,7 +37,7 @@ #include "gdscript.h" #include "gdscript_tokenizer.h" -GDScriptLanguage *script_language_gd = NULL; +GDScriptLanguage *script_language_gd = nullptr; Ref<ResourceFormatLoaderGDScript> resource_loader_gd; Ref<ResourceFormatSaverGDScript> resource_saver_gd; @@ -54,12 +54,10 @@ Ref<ResourceFormatSaverGDScript> resource_saver_gd; #endif // !GDSCRIPT_NO_LSP class EditorExportGDScript : public EditorExportPlugin { - GDCLASS(EditorExportGDScript, EditorExportPlugin); public: virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { - int script_mode = EditorExportPreset::MODE_SCRIPT_COMPILED; String script_key; @@ -70,21 +68,21 @@ public: script_key = preset->get_script_encryption_key().to_lower(); } - if (!p_path.ends_with(".gd") || script_mode == EditorExportPreset::MODE_SCRIPT_TEXT) + if (!p_path.ends_with(".gd") || script_mode == EditorExportPreset::MODE_SCRIPT_TEXT) { return; + } Vector<uint8_t> file = FileAccess::get_file_as_array(p_path); - if (file.empty()) + if (file.empty()) { return; + } String txt; txt.parse_utf8((const char *)file.ptr(), file.size()); file = GDScriptTokenizerBuffer::parse_code_string(txt); if (!file.empty()) { - if (script_mode == EditorExportPreset::MODE_SCRIPT_ENCRYPTED) { - String tmp_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("script.gde"); FileAccess *fa = FileAccess::open(tmp_path, FileAccess::WRITE); @@ -94,19 +92,21 @@ public: int v = 0; if (i * 2 < script_key.length()) { CharType ct = script_key[i * 2]; - if (ct >= '0' && ct <= '9') + if (ct >= '0' && ct <= '9') { ct = ct - '0'; - else if (ct >= 'a' && ct <= 'f') + } else if (ct >= 'a' && ct <= 'f') { ct = 10 + ct - 'a'; + } v |= ct << 4; } if (i * 2 + 1 < script_key.length()) { CharType ct = script_key[i * 2 + 1]; - if (ct >= '0' && ct <= '9') + if (ct >= '0' && ct <= '9') { ct = ct - '0'; - else if (ct >= 'a' && ct <= 'f') + } else if (ct >= 'a' && ct <= 'f') { ct = 10 + ct - 'a'; + } v |= ct; } key.write[i] = v; @@ -127,7 +127,6 @@ public: DirAccess::remove_file_or_error(tmp_path); } else { - add_file(p_path.get_basename() + ".gdc", file, true); } } @@ -135,7 +134,6 @@ public: }; static void _editor_init() { - Ref<EditorExportGDScript> gd_export; gd_export.instance(); EditorExport::get_singleton()->add_export_plugin(gd_export); @@ -151,7 +149,6 @@ static void _editor_init() { #endif // TOOLS_ENABLED void register_gdscript_types() { - ClassDB::register_class<GDScript>(); ClassDB::register_virtual_class<GDScriptFunctionState>(); @@ -171,11 +168,11 @@ void register_gdscript_types() { } void unregister_gdscript_types() { - ScriptServer::unregister_language(script_language_gd); - if (script_language_gd) + if (script_language_gd) { memdelete(script_language_gd); + } ResourceLoader::remove_resource_format_loader(resource_loader_gd); resource_loader_gd.unref(); diff --git a/modules/gdscript/register_types.h b/modules/gdscript/register_types.h index 55920e8b97..18e57c1211 100644 --- a/modules/gdscript/register_types.h +++ b/modules/gdscript/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef GDSCRIPT_REGISTER_TYPES_H +#define GDSCRIPT_REGISTER_TYPES_H + void register_gdscript_types(); void unregister_gdscript_types(); + +#endif // GDSCRIPT_REGISTER_TYPES_H diff --git a/modules/glslang/SCsub b/modules/glslang/SCsub index ae102238f2..c1d23a138b 100644 --- a/modules/glslang/SCsub +++ b/modules/glslang/SCsub @@ -1,12 +1,12 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_glslang = env_modules.Clone() # Thirdparty source files -if env['builtin_glslang']: +if env["builtin_glslang"]: thirdparty_dir = "#thirdparty/glslang/" thirdparty_sources = [ "glslang/MachineIndependent/RemoveTree.cpp", @@ -48,10 +48,10 @@ if env['builtin_glslang']: "SPIRV/doc.cpp", "SPIRV/SPVRemapper.cpp", "SPIRV/SpvPostProcess.cpp", - "SPIRV/Logger.cpp" + "SPIRV/Logger.cpp", ] - if (env["platform"]=="windows"): + if env["platform"] == "windows": thirdparty_sources.append("glslang/OSDependent/Windows/ossource.cpp") else: thirdparty_sources.append("glslang/OSDependent/Unix/ossource.cpp") @@ -60,7 +60,7 @@ if env['builtin_glslang']: # Treat glslang headers as system headers to avoid raising warnings. Not supported on MSVC. if not env.msvc: - env_glslang.Append(CPPFLAGS=['-isystem', Dir(thirdparty_dir).path]) + env_glslang.Append(CPPFLAGS=["-isystem", Dir(thirdparty_dir).path]) else: env_glslang.Prepend(CPPPATH=[thirdparty_dir]) diff --git a/modules/glslang/config.py b/modules/glslang/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/glslang/config.py +++ b/modules/glslang/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp index d2b4a18fc7..dd28c4ad4a 100644 --- a/modules/glslang/register_types.cpp +++ b/modules/glslang/register_types.cpp @@ -30,7 +30,7 @@ #include "register_types.h" -#include "servers/visual/rendering_device.h" +#include "servers/rendering/rendering_device.h" #include <SPIRV/GlslangToSpv.h> #include <glslang/Include/Types.h> @@ -130,20 +130,19 @@ static const TBuiltInResource default_builtin_resource = { /*maxTaskWorkGroupSizeZ_NV*/ 0, /*maxMeshViewCountNV*/ 0, /*limits*/ { - /*nonInductiveForLoops*/ 1, - /*whileLoops*/ 1, - /*doWhileLoops*/ 1, - /*generalUniformIndexing*/ 1, - /*generalAttributeMatrixVectorIndexing*/ 1, - /*generalVaryingIndexing*/ 1, - /*generalSamplerIndexing*/ 1, - /*generalVariableIndexing*/ 1, - /*generalConstantMatrixVectorIndexing*/ 1, + /*nonInductiveForLoops*/ true, + /*whileLoops*/ true, + /*doWhileLoops*/ true, + /*generalUniformIndexing*/ true, + /*generalAttributeMatrixVectorIndexing*/ true, + /*generalVaryingIndexing*/ true, + /*generalSamplerIndexing*/ true, + /*generalVariableIndexing*/ true, + /*generalConstantMatrixVectorIndexing*/ true, } }; static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error) { - Vector<uint8_t> ret; ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret); @@ -177,7 +176,6 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage //preprocess if (!shader.preprocess(&default_builtin_resource, DefaultVersion, ENoProfile, false, false, messages, &pre_processed_code, includer)) { - if (r_error) { (*r_error) = "Failed pre-process:\n"; (*r_error) += shader.getInfoLog(); @@ -240,7 +238,7 @@ void preregister_glslang_types() { void register_glslang_types() { } -void unregister_glslang_types() { +void unregister_glslang_types() { glslang::FinalizeProcess(); } diff --git a/modules/glslang/register_types.h b/modules/glslang/register_types.h index 37a1ef67f2..2437e2b27a 100644 --- a/modules/glslang/register_types.h +++ b/modules/glslang/register_types.h @@ -28,7 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef GLSLANG_REGISTER_TYPES_H +#define GLSLANG_REGISTER_TYPES_H + #define MODULE_GLSLANG_HAS_PREREGISTER + void preregister_glslang_types(); void register_glslang_types(); void unregister_glslang_types(); + +#endif // GLSLANG_REGISTER_TYPES_H diff --git a/modules/gridmap/SCsub b/modules/gridmap/SCsub index 62b8a0ff93..970ce534f0 100644 --- a/modules/gridmap/SCsub +++ b/modules/gridmap/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_gridmap = env_modules.Clone() diff --git a/modules/gridmap/config.py b/modules/gridmap/config.py index 5022116c9b..a6319fe1ea 100644 --- a/modules/gridmap/config.py +++ b/modules/gridmap/config.py @@ -1,13 +1,16 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "GridMap", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index 37ebb3e5d5..a213069e19 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GridMap" inherits="Spatial" version="4.0"> +<class name="GridMap" inherits="Node3D" version="4.0"> <brief_description> Node for 3D tile-based maps. </brief_description> diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 7273a014f0..2975a97bfe 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -32,30 +32,26 @@ #include "core/io/marshalls.h" #include "core/message_queue.h" -#include "scene/3d/light.h" +#include "scene/3d/light_3d.h" #include "scene/resources/mesh_library.h" #include "scene/resources/surface_tool.h" #include "scene/scene_string_names.h" -#include "servers/navigation_server.h" -#include "servers/visual_server.h" +#include "servers/navigation_server_3d.h" +#include "servers/rendering_server.h" bool GridMap::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; if (name == "data") { - Dictionary d = p_value; if (d.has("cells")) { - Vector<int> cells = d["cells"]; int amount = cells.size(); const int *r = cells.ptr(); ERR_FAIL_COND_V(amount % 3, false); // not even cell_map.clear(); for (int i = 0; i < amount / 3; i++) { - IndexKey ik; ik.key = decode_uint64((const uint8_t *)&r[i * 3]); Cell cell; @@ -67,7 +63,6 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) { _recreate_octant_data(); } else if (name == "baked_meshes") { - clear_baked_meshes(); Array meshes = p_value; @@ -76,12 +71,12 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) { BakedMesh bm; bm.mesh = meshes[i]; ERR_CONTINUE(!bm.mesh.is_valid()); - bm.instance = VS::get_singleton()->instance_create(); - VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); - VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); + bm.instance = RS::get_singleton()->instance_create(); + RS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); + RS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); if (is_inside_tree()) { - VS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(bm.instance, get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); } baked_meshes.push_back(bm); } @@ -96,11 +91,9 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) { } bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name; if (name == "data") { - Dictionary d; Vector<int> cells; @@ -109,7 +102,6 @@ bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { int *w = cells.ptrw(); int i = 0; for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next(), i++) { - encode_uint64(E->key().key, (uint8_t *)&w[i * 3]); encode_uint32(E->get().cell, (uint8_t *)&w[i * 3 + 2]); } @@ -119,7 +111,6 @@ bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { r_ret = d; } else if (name == "baked_meshes") { - Array ret; ret.resize(baked_meshes.size()); for (int i = 0; i < baked_meshes.size(); i++) { @@ -127,14 +118,14 @@ bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { } r_ret = ret; - } else + } else { return false; + } return true; } void GridMap::_get_property_list(List<PropertyInfo> *p_list) const { - if (baked_meshes.size()) { p_list->push_back(PropertyInfo(Variant::ARRAY, "baked_meshes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); } @@ -143,71 +134,65 @@ void GridMap::_get_property_list(List<PropertyInfo> *p_list) const { } void GridMap::set_collision_layer(uint32_t p_layer) { - collision_layer = p_layer; _reset_physic_bodies_collision_filters(); } uint32_t GridMap::get_collision_layer() const { - return collision_layer; } void GridMap::set_collision_mask(uint32_t p_mask) { - collision_mask = p_mask; _reset_physic_bodies_collision_filters(); } uint32_t GridMap::get_collision_mask() const { - return collision_mask; } void GridMap::set_collision_mask_bit(int p_bit, bool p_value) { - uint32_t mask = get_collision_mask(); - if (p_value) + if (p_value) { mask |= 1 << p_bit; - else + } else { mask &= ~(1 << p_bit); + } set_collision_mask(mask); } bool GridMap::get_collision_mask_bit(int p_bit) const { - return get_collision_mask() & (1 << p_bit); } void GridMap::set_collision_layer_bit(int p_bit, bool p_value) { - uint32_t mask = get_collision_layer(); - if (p_value) + if (p_value) { mask |= 1 << p_bit; - else + } else { mask &= ~(1 << p_bit); + } set_collision_layer(mask); } bool GridMap::get_collision_layer_bit(int p_bit) const { - return get_collision_layer() & (1 << p_bit); } void GridMap::set_mesh_library(const Ref<MeshLibrary> &p_mesh_library) { - - if (!mesh_library.is_null()) + if (!mesh_library.is_null()) { mesh_library->unregister_owner(this); + } mesh_library = p_mesh_library; - if (!mesh_library.is_null()) + if (!mesh_library.is_null()) { mesh_library->register_owner(this); + } _recreate_octant_data(); _change_notify("mesh_library"); } Ref<MeshLibrary> GridMap::get_mesh_library() const { - return mesh_library; } @@ -217,24 +202,22 @@ void GridMap::set_cell_size(const Vector3 &p_size) { _recreate_octant_data(); emit_signal("cell_size_changed", cell_size); } -Vector3 GridMap::get_cell_size() const { +Vector3 GridMap::get_cell_size() const { return cell_size; } void GridMap::set_octant_size(int p_size) { - ERR_FAIL_COND(p_size == 0); octant_size = p_size; _recreate_octant_data(); } -int GridMap::get_octant_size() const { +int GridMap::get_octant_size() const { return octant_size; } void GridMap::set_center_x(bool p_enable) { - center_x = p_enable; _recreate_octant_data(); } @@ -244,7 +227,6 @@ bool GridMap::get_center_x() const { } void GridMap::set_center_y(bool p_enable) { - center_y = p_enable; _recreate_octant_data(); } @@ -254,7 +236,6 @@ bool GridMap::get_center_y() const { } void GridMap::set_center_z(bool p_enable) { - center_z = p_enable; _recreate_octant_data(); } @@ -264,7 +245,6 @@ bool GridMap::get_center_z() const { } void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { - if (baked_meshes.size() && !recreating_octants) { //if you set a cell item, baked meshes go good bye clear_baked_meshes(); @@ -306,17 +286,16 @@ void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { //create octant because it does not exist Octant *g = memnew(Octant); g->dirty = true; - g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id()); - PhysicsServer::get_singleton()->body_set_collision_layer(g->static_body, collision_layer); - PhysicsServer::get_singleton()->body_set_collision_mask(g->static_body, collision_mask); + g->static_body = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC); + PhysicsServer3D::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id()); + PhysicsServer3D::get_singleton()->body_set_collision_layer(g->static_body, collision_layer); + PhysicsServer3D::get_singleton()->body_set_collision_mask(g->static_body, collision_mask); SceneTree *st = SceneTree::get_singleton(); if (st && st->is_debugging_collisions_hint()) { - - g->collision_debug = VisualServer::get_singleton()->mesh_create(); - g->collision_debug_instance = VisualServer::get_singleton()->instance_create(); - VisualServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug); + g->collision_debug = RenderingServer::get_singleton()->mesh_create(); + g->collision_debug_instance = RenderingServer::get_singleton()->instance_create(); + RenderingServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug); } octant_map[octantkey] = g; @@ -340,7 +319,6 @@ void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { } int GridMap::get_cell_item(int p_x, int p_y, int p_z) const { - ERR_FAIL_INDEX_V(ABS(p_x), 1 << 20, INVALID_CELL_ITEM); ERR_FAIL_INDEX_V(ABS(p_y), 1 << 20, INVALID_CELL_ITEM); ERR_FAIL_INDEX_V(ABS(p_z), 1 << 20, INVALID_CELL_ITEM); @@ -350,13 +328,13 @@ int GridMap::get_cell_item(int p_x, int p_y, int p_z) const { key.y = p_y; key.z = p_z; - if (!cell_map.has(key)) + if (!cell_map.has(key)) { return INVALID_CELL_ITEM; + } return cell_map[key].item; } int GridMap::get_cell_item_orientation(int p_x, int p_y, int p_z) const { - ERR_FAIL_INDEX_V(ABS(p_x), 1 << 20, -1); ERR_FAIL_INDEX_V(ABS(p_y), 1 << 20, -1); ERR_FAIL_INDEX_V(ABS(p_z), 1 << 20, -1); @@ -366,8 +344,9 @@ int GridMap::get_cell_item_orientation(int p_x, int p_y, int p_z) const { key.y = p_y; key.z = p_z; - if (!cell_map.has(key)) + if (!cell_map.has(key)) { return -1; + } return cell_map[key].rot; } @@ -389,47 +368,45 @@ Vector3 GridMap::map_to_world(int p_x, int p_y, int p_z) const { } void GridMap::_octant_transform(const OctantKey &p_key) { - ERR_FAIL_COND(!octant_map.has(p_key)); Octant &g = *octant_map[p_key]; - PhysicsServer::get_singleton()->body_set_state(g.static_body, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); if (g.collision_debug_instance.is_valid()) { - VS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform()); + RS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform()); } for (int i = 0; i < g.multimesh_instances.size(); i++) { - VS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); + RS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); } } bool GridMap::_octant_update(const OctantKey &p_key) { ERR_FAIL_COND_V(!octant_map.has(p_key), false); Octant &g = *octant_map[p_key]; - if (!g.dirty) + if (!g.dirty) { return false; + } //erase body shapes - PhysicsServer::get_singleton()->body_clear_shapes(g.static_body); + PhysicsServer3D::get_singleton()->body_clear_shapes(g.static_body); //erase body shapes debug if (g.collision_debug.is_valid()) { - - VS::get_singleton()->mesh_clear(g.collision_debug); + RS::get_singleton()->mesh_clear(g.collision_debug); } //erase navigation for (Map<IndexKey, Octant::NavMesh>::Element *E = g.navmesh_ids.front(); E; E = E->next()) { - NavigationServer::get_singleton()->free(E->get().region); + NavigationServer3D::get_singleton()->free(E->get().region); } g.navmesh_ids.clear(); //erase multimeshes for (int i = 0; i < g.multimesh_instances.size(); i++) { - - VS::get_singleton()->free(g.multimesh_instances[i].instance); - VS::get_singleton()->free(g.multimesh_instances[i].multimesh); + RS::get_singleton()->free(g.multimesh_instances[i].instance); + RS::get_singleton()->free(g.multimesh_instances[i].multimesh); } g.multimesh_instances.clear(); @@ -450,12 +427,12 @@ bool GridMap::_octant_update(const OctantKey &p_key) { Map<int, List<Pair<Transform, IndexKey>>> multimesh_items; for (Set<IndexKey>::Element *E = g.cells.front(); E; E = E->next()) { - ERR_CONTINUE(!cell_map.has(E->get())); const Cell &c = cell_map[E->get()]; - if (!mesh_library.is_valid() || !mesh_library->has_item(c.item)) + if (!mesh_library.is_valid() || !mesh_library->has_item(c.item)) { continue; + } Vector3 cellpos = Vector3(E->get().x, E->get().y, E->get().z); Vector3 ofs = _get_offset(); @@ -482,9 +459,10 @@ bool GridMap::_octant_update(const OctantKey &p_key) { // add the item's shape at given xform to octant's static_body for (int i = 0; i < shapes.size(); i++) { // add the item's shape - if (!shapes[i].shape.is_valid()) + if (!shapes[i].shape.is_valid()) { continue; - PhysicsServer::get_singleton()->body_add_shape(g.static_body, shapes[i].shape->get_rid(), xform * shapes[i].local_transform); + } + PhysicsServer3D::get_singleton()->body_add_shape(g.static_body, shapes[i].shape->get_rid(), xform * shapes[i].local_transform); if (g.collision_debug.is_valid()) { shapes.write[i].shape->add_vertices_to_array(col_debug, xform * shapes[i].local_transform); } @@ -497,10 +475,10 @@ bool GridMap::_octant_update(const OctantKey &p_key) { nm.xform = xform * mesh_library->get_item_navmesh_transform(c.item); if (navigation) { - RID region = NavigationServer::get_singleton()->region_create(); - NavigationServer::get_singleton()->region_set_navmesh(region, navmesh); - NavigationServer::get_singleton()->region_set_transform(region, navigation->get_global_transform() * nm.xform); - NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + RID region = NavigationServer3D::get_singleton()->region_create(); + NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh); + NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * nm.xform); + NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); nm.region = region; } g.navmesh_ids[E->get()] = nm; @@ -509,17 +487,16 @@ bool GridMap::_octant_update(const OctantKey &p_key) { //update multimeshes, only if not baked if (baked_meshes.size() == 0) { - for (Map<int, List<Pair<Transform, IndexKey>>>::Element *E = multimesh_items.front(); E; E = E->next()) { Octant::MultimeshInstance mmi; - RID mm = VS::get_singleton()->multimesh_create(); - VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D); - VS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid()); + RID mm = RS::get_singleton()->multimesh_create(); + RS::get_singleton()->multimesh_allocate(mm, E->get().size(), RS::MULTIMESH_TRANSFORM_3D); + RS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid()); int idx = 0; for (List<Pair<Transform, IndexKey>>::Element *F = E->get().front(); F; F = F->next()) { - VS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first); + RS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first); #ifdef TOOLS_ENABLED Octant::MultimeshInstance::Item it; @@ -532,12 +509,12 @@ bool GridMap::_octant_update(const OctantKey &p_key) { idx++; } - RID instance = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_base(instance, mm); + RID instance = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_base(instance, mm); if (is_inside_tree()) { - VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(instance, get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_transform(instance, get_global_transform()); } mmi.multimesh = mm; @@ -548,15 +525,14 @@ bool GridMap::_octant_update(const OctantKey &p_key) { } if (col_debug.size()) { - Array arr; - arr.resize(VS::ARRAY_MAX); - arr[VS::ARRAY_VERTEX] = col_debug; + arr.resize(RS::ARRAY_MAX); + arr[RS::ARRAY_VERTEX] = col_debug; - VS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, VS::PRIMITIVE_LINES, arr); + RS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, RS::PRIMITIVE_LINES, arr); SceneTree *st = SceneTree::get_singleton(); if (st) { - VS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid()); + RS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid()); } } @@ -567,38 +543,36 @@ bool GridMap::_octant_update(const OctantKey &p_key) { void GridMap::_reset_physic_bodies_collision_filters() { for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) { - PhysicsServer::get_singleton()->body_set_collision_layer(E->get()->static_body, collision_layer); - PhysicsServer::get_singleton()->body_set_collision_mask(E->get()->static_body, collision_mask); + PhysicsServer3D::get_singleton()->body_set_collision_layer(E->get()->static_body, collision_layer); + PhysicsServer3D::get_singleton()->body_set_collision_mask(E->get()->static_body, collision_mask); } } void GridMap::_octant_enter_world(const OctantKey &p_key) { - ERR_FAIL_COND(!octant_map.has(p_key)); Octant &g = *octant_map[p_key]; - PhysicsServer::get_singleton()->body_set_state(g.static_body, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - PhysicsServer::get_singleton()->body_set_space(g.static_body, get_world()->get_space()); + PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_set_space(g.static_body, get_world_3d()->get_space()); if (g.collision_debug_instance.is_valid()) { - VS::get_singleton()->instance_set_scenario(g.collision_debug_instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(g.collision_debug_instance, get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform()); } for (int i = 0; i < g.multimesh_instances.size(); i++) { - VS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); } if (navigation && mesh_library.is_valid()) { for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) { - if (cell_map.has(F->key()) && F->get().region.is_valid() == false) { Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F->key()].item); if (nm.is_valid()) { - RID region = NavigationServer::get_singleton()->region_create(); - NavigationServer::get_singleton()->region_set_navmesh(region, nm); - NavigationServer::get_singleton()->region_set_transform(region, navigation->get_global_transform() * F->get().xform); - NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + RID region = NavigationServer3D::get_singleton()->region_create(); + NavigationServer3D::get_singleton()->region_set_navmesh(region, nm); + NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * F->get().xform); + NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); F->get().region = region; } } @@ -607,26 +581,23 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) { } void GridMap::_octant_exit_world(const OctantKey &p_key) { - ERR_FAIL_COND(!octant_map.has(p_key)); Octant &g = *octant_map[p_key]; - PhysicsServer::get_singleton()->body_set_state(g.static_body, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - PhysicsServer::get_singleton()->body_set_space(g.static_body, RID()); + PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_set_space(g.static_body, RID()); if (g.collision_debug_instance.is_valid()) { - - VS::get_singleton()->instance_set_scenario(g.collision_debug_instance, RID()); + RS::get_singleton()->instance_set_scenario(g.collision_debug_instance, RID()); } for (int i = 0; i < g.multimesh_instances.size(); i++) { - VS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID()); + RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID()); } if (navigation) { for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) { - if (F->get().region.is_valid()) { - NavigationServer::get_singleton()->free(F->get().region); + NavigationServer3D::get_singleton()->free(F->get().region); F->get().region = RID(); } } @@ -634,47 +605,44 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) { } void GridMap::_octant_clean_up(const OctantKey &p_key) { - ERR_FAIL_COND(!octant_map.has(p_key)); Octant &g = *octant_map[p_key]; - if (g.collision_debug.is_valid()) - VS::get_singleton()->free(g.collision_debug); - if (g.collision_debug_instance.is_valid()) - VS::get_singleton()->free(g.collision_debug_instance); + if (g.collision_debug.is_valid()) { + RS::get_singleton()->free(g.collision_debug); + } + if (g.collision_debug_instance.is_valid()) { + RS::get_singleton()->free(g.collision_debug_instance); + } - PhysicsServer::get_singleton()->free(g.static_body); + PhysicsServer3D::get_singleton()->free(g.static_body); // Erase navigation for (Map<IndexKey, Octant::NavMesh>::Element *E = g.navmesh_ids.front(); E; E = E->next()) { - NavigationServer::get_singleton()->free(E->get().region); + NavigationServer3D::get_singleton()->free(E->get().region); } g.navmesh_ids.clear(); //erase multimeshes for (int i = 0; i < g.multimesh_instances.size(); i++) { - - VS::get_singleton()->free(g.multimesh_instances[i].instance); - VS::get_singleton()->free(g.multimesh_instances[i].multimesh); + RS::get_singleton()->free(g.multimesh_instances[i].instance); + RS::get_singleton()->free(g.multimesh_instances[i].multimesh); } g.multimesh_instances.clear(); } void GridMap::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_WORLD: { - - Spatial *c = this; + Node3D *c = this; while (c) { - navigation = Object::cast_to<Navigation>(c); + navigation = Object::cast_to<Navigation3D>(c); if (navigation) { break; } - c = Object::cast_to<Spatial>(c->get_parent()); + c = Object::cast_to<Node3D>(c->get_parent()); } last_transform = get_global_transform(); @@ -684,16 +652,16 @@ void GridMap::_notification(int p_what) { } for (int i = 0; i < baked_meshes.size(); i++) { - VS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); } } break; case NOTIFICATION_TRANSFORM_CHANGED: { - Transform new_xform = get_global_transform(); - if (new_xform == last_transform) + if (new_xform == last_transform) { break; + } //update run for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) { _octant_transform(E->key()); @@ -702,23 +670,22 @@ void GridMap::_notification(int p_what) { last_transform = new_xform; for (int i = 0; i < baked_meshes.size(); i++) { - VS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); + RS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); } } break; case NOTIFICATION_EXIT_WORLD: { - for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) { _octant_exit_world(E->key()); } - navigation = NULL; + navigation = nullptr; //_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS); //_update_octants_callback(); //_update_area_instances(); for (int i = 0; i < baked_meshes.size(); i++) { - VS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, RID()); + RS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, RID()); } } break; @@ -729,8 +696,9 @@ void GridMap::_notification(int p_what) { } void GridMap::_update_visibility() { - if (!is_inside_tree()) + if (!is_inside_tree()) { return; + } _change_notify("visible"); @@ -738,37 +706,35 @@ void GridMap::_update_visibility() { Octant *octant = e->value(); for (int i = 0; i < octant->multimesh_instances.size(); i++) { const Octant::MultimeshInstance &mi = octant->multimesh_instances[i]; - VS::get_singleton()->instance_set_visible(mi.instance, is_visible()); + RS::get_singleton()->instance_set_visible(mi.instance, is_visible()); } } } void GridMap::_queue_octants_dirty() { - - if (awaiting_update) + if (awaiting_update) { return; + } MessageQueue::get_singleton()->push_call(this, "_update_octants_callback"); awaiting_update = true; } void GridMap::_recreate_octant_data() { - recreating_octants = true; Map<IndexKey, Cell> cell_copy = cell_map; _clear_internal(); for (Map<IndexKey, Cell>::Element *E = cell_copy.front(); E; E = E->next()) { - set_cell_item(E->key().x, E->key().y, E->key().z, E->get().item, E->get().rot); } recreating_octants = false; } void GridMap::_clear_internal() { - for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) { - if (is_inside_world()) + if (is_inside_world()) { _octant_exit_world(E->key()); + } _octant_clean_up(E->key()); memdelete(E->get()); @@ -779,24 +745,21 @@ void GridMap::_clear_internal() { } void GridMap::clear() { - _clear_internal(); clear_baked_meshes(); } void GridMap::resource_changed(const RES &p_res) { - _recreate_octant_data(); } void GridMap::_update_octants_callback() { - - if (!awaiting_update) + if (!awaiting_update) { return; + } List<OctantKey> to_delete; for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) { - if (_octant_update(E->key())) { to_delete.push_back(E->key()); } @@ -812,7 +775,6 @@ void GridMap::_update_octants_callback() { } void GridMap::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &GridMap::set_collision_layer); ClassDB::bind_method(D_METHOD("get_collision_layer"), &GridMap::get_collision_layer); @@ -885,11 +847,12 @@ void GridMap::_bind_methods() { } void GridMap::set_clip(bool p_enabled, bool p_clip_above, int p_floor, Vector3::Axis p_axis) { - - if (!p_enabled && !clip) + if (!p_enabled && !clip) { return; - if (clip && p_enabled && clip_floor == p_floor && p_clip_above == clip_above && p_axis == clip_axis) + } + if (clip && p_enabled && clip_floor == p_floor && p_clip_above == clip_above && p_axis == clip_axis) { return; + } clip = p_enabled; clip_floor = p_floor; @@ -898,7 +861,6 @@ void GridMap::set_clip(bool p_enabled, bool p_clip_above, int p_floor, Vector3:: //make it all update for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) { - Octant *g = E->get(); g->dirty = true; } @@ -907,18 +869,15 @@ void GridMap::set_clip(bool p_enabled, bool p_clip_above, int p_floor, Vector3:: } void GridMap::set_cell_scale(float p_scale) { - cell_scale = p_scale; _recreate_octant_data(); } float GridMap::get_cell_scale() const { - return cell_scale; } Array GridMap::get_used_cells() const { - Array a; a.resize(cell_map.size()); int i = 0; @@ -931,21 +890,22 @@ Array GridMap::get_used_cells() const { } Array GridMap::get_meshes() { - - if (mesh_library.is_null()) + if (mesh_library.is_null()) { return Array(); + } Vector3 ofs = _get_offset(); Array meshes; for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next()) { - int id = E->get().item; - if (!mesh_library->has_item(id)) + if (!mesh_library->has_item(id)) { continue; + } Ref<Mesh> mesh = mesh_library->get_item_mesh(id); - if (mesh.is_null()) + if (mesh.is_null()) { continue; + } IndexKey ik = E->key(); @@ -973,9 +933,8 @@ Vector3 GridMap::_get_offset() const { } void GridMap::clear_baked_meshes() { - for (int i = 0; i < baked_meshes.size(); i++) { - VS::get_singleton()->free(baked_meshes[i].instance); + RS::get_singleton()->free(baked_meshes[i].instance); } baked_meshes.clear(); @@ -983,24 +942,25 @@ void GridMap::clear_baked_meshes() { } void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texel_size) { - - if (!mesh_library.is_valid()) + if (!mesh_library.is_valid()) { return; + } //generate Map<OctantKey, Map<Ref<Material>, Ref<SurfaceTool>>> surface_map; for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next()) { - IndexKey key = E->key(); int item = E->get().item; - if (!mesh_library->has_item(item)) + if (!mesh_library->has_item(item)) { continue; + } Ref<Mesh> mesh = mesh_library->get_item_mesh(item); - if (!mesh.is_valid()) + if (!mesh.is_valid()) { continue; + } Vector3 cellpos = Vector3(key.x, key.y, key.z); Vector3 ofs = _get_offset(); @@ -1023,9 +983,9 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe Map<Ref<Material>, Ref<SurfaceTool>> &mat_map = surface_map[ok]; for (int i = 0; i < mesh->get_surface_count(); i++) { - - if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) + if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { continue; + } Ref<Material> surf_mat = mesh->surface_get_material(i); if (!mat_map.has(surf_mat)) { @@ -1041,7 +1001,6 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe } for (Map<OctantKey, Map<Ref<Material>, Ref<SurfaceTool>>>::Element *E = surface_map.front(); E; E = E->next()) { - Ref<ArrayMesh> mesh; mesh.instance(); for (Map<Ref<Material>, Ref<SurfaceTool>>::Element *F = E->get().front(); F; F = F->next()) { @@ -1050,12 +1009,12 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe BakedMesh bm; bm.mesh = mesh; - bm.instance = VS::get_singleton()->instance_create(); - VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); - VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); + bm.instance = RS::get_singleton()->instance_create(); + RS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); + RS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); if (is_inside_tree()) { - VS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(bm.instance, get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); } if (p_gen_lightmap_uv) { @@ -1068,7 +1027,6 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe } Array GridMap::get_bake_meshes() { - if (!baked_meshes.size()) { make_baked_meshes(true); } @@ -1083,13 +1041,11 @@ Array GridMap::get_bake_meshes() { } RID GridMap::get_bake_mesh_instance(int p_idx) { - ERR_FAIL_INDEX_V(p_idx, baked_meshes.size(), RID()); return baked_meshes[p_idx].instance; } GridMap::GridMap() { - collision_layer = 1; collision_mask = 1; @@ -1107,15 +1063,15 @@ GridMap::GridMap() { clip_above = true; cell_scale = 1.0; - navigation = NULL; + navigation = nullptr; set_notify_transform(true); recreating_octants = false; } GridMap::~GridMap() { - - if (!mesh_library.is_null()) + if (!mesh_library.is_null()) { mesh_library->unregister_owner(this); + } clear(); } diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index cc1c8c2923..9eb9aee7d1 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -31,17 +31,16 @@ #ifndef GRID_MAP_H #define GRID_MAP_H -#include "scene/3d/navigation.h" -#include "scene/3d/spatial.h" +#include "scene/3d/navigation_3d.h" +#include "scene/3d/node_3d.h" #include "scene/resources/mesh_library.h" #include "scene/resources/multimesh.h" //heh heh, godotsphir!! this shares no code and the design is completely different with previous projects i've done.. //should scale better with hardware that supports instancing -class GridMap : public Spatial { - - GDCLASS(GridMap, Spatial); +class GridMap : public Node3D { + GDCLASS(GridMap, Node3D); enum { MAP_DIRTY_TRANSFORMS = 1, @@ -49,7 +48,6 @@ class GridMap : public Spatial { }; union IndexKey { - struct { int16_t x; int16_t y; @@ -58,7 +56,6 @@ class GridMap : public Spatial { uint64_t key; _FORCE_INLINE_ bool operator<(const IndexKey &p_key) const { - return key < p_key.key; } @@ -69,7 +66,6 @@ class GridMap : public Spatial { * @brief A Cell is a single cell in the cube map space; it is defined by its coordinates and the populating Item, identified by int id. */ union Cell { - struct { unsigned int item : 16; unsigned int rot : 5; @@ -89,7 +85,6 @@ class GridMap : public Spatial { * A GridMap can have multiple Octants. */ struct Octant { - struct NavMesh { RID region; Transform xform; @@ -118,7 +113,6 @@ class GridMap : public Spatial { }; union OctantKey { - struct { int16_t x; int16_t y; @@ -129,7 +123,6 @@ class GridMap : public Spatial { uint64_t key; _FORCE_INLINE_ bool operator<(const OctantKey &p_key) const { - return key < p_key.key; } @@ -147,7 +140,7 @@ class GridMap : public Spatial { int octant_size; bool center_x, center_y, center_z; float cell_scale; - Navigation *navigation; + Navigation3D *navigation; bool clip; bool clip_above; @@ -165,15 +158,13 @@ class GridMap : public Spatial { void _recreate_octant_data(); struct BakeLight { - - VS::LightType type; + RS::LightType type; Vector3 pos; Vector3 dir; - float param[VS::LIGHT_PARAM_MAX]; + float param[RS::LIGHT_PARAM_MAX]; }; _FORCE_INLINE_ Vector3 _octant_get_offset(const OctantKey &p_key) const { - return Vector3(p_key.x, p_key.y, p_key.z) * cell_size * octant_size; } diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index a656ee8b63..2bae43510a 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -29,33 +29,32 @@ /*************************************************************************/ #include "grid_map_editor_plugin.h" -#include "core/os/input.h" +#include "core/input/input.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" -#include "editor/plugins/spatial_editor_plugin.h" -#include "scene/3d/camera.h" +#include "editor/plugins/node_3d_editor_plugin.h" +#include "scene/3d/camera_3d.h" #include "core/math/geometry.h" #include "core/os/keyboard.h" +#include "scene/main/window.h" void GridMapEditor::_node_removed(Node *p_node) { - - if (p_node == node) - node = NULL; + if (p_node == node) { + node = nullptr; + } } void GridMapEditor::_configure() { - - if (!node) + if (!node) { return; + } update_grid(); } void GridMapEditor::_menu_option(int p_option) { - switch (p_option) { - case MENU_OPTION_PREV_LEVEL: { floor->set_value(floor->get_value() - 1); } break; @@ -65,7 +64,6 @@ void GridMapEditor::_menu_option(int p_option) { } break; case MENU_OPTION_LOCK_VIEW: { - int index = options->get_popup()->get_item_index(MENU_OPTION_LOCK_VIEW); lock_view = !options->get_popup()->is_item_checked(index); @@ -74,10 +72,8 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_CLIP_DISABLED: case MENU_OPTION_CLIP_ABOVE: case MENU_OPTION_CLIP_BELOW: { - clip_mode = ClipMode(p_option - MENU_OPTION_CLIP_DISABLED); for (int i = 0; i < 3; i++) { - int index = options->get_popup()->get_item_index(MENU_OPTION_CLIP_DISABLED + i); options->get_popup()->set_item_checked(index, i == clip_mode); } @@ -87,7 +83,6 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_X_AXIS: case MENU_OPTION_Y_AXIS: case MENU_OPTION_Z_AXIS: { - int new_axis = p_option - MENU_OPTION_X_AXIS; for (int i = 0; i < 3; i++) { int idx = options->get_popup()->get_item_index(MENU_OPTION_X_AXIS + i); @@ -113,10 +108,8 @@ void GridMapEditor::_menu_option(int p_option) { } break; case MENU_OPTION_CURSOR_ROTATE_Y: { - Basis r; if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(0, 1, 0), -Math_PI / 2.0); paste_indicator.orientation = r.get_orthogonal_index(); @@ -130,10 +123,8 @@ void GridMapEditor::_menu_option(int p_option) { _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_ROTATE_X: { - Basis r; if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(1, 0, 0), -Math_PI / 2.0); paste_indicator.orientation = r.get_orthogonal_index(); @@ -147,10 +138,8 @@ void GridMapEditor::_menu_option(int p_option) { _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_ROTATE_Z: { - Basis r; if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(0, 0, 1), -Math_PI / 2.0); paste_indicator.orientation = r.get_orthogonal_index(); @@ -164,10 +153,8 @@ void GridMapEditor::_menu_option(int p_option) { _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_BACK_ROTATE_Y: { - Basis r; if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(0, 1, 0), Math_PI / 2.0); paste_indicator.orientation = r.get_orthogonal_index(); @@ -181,10 +168,8 @@ void GridMapEditor::_menu_option(int p_option) { _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_BACK_ROTATE_X: { - Basis r; if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(1, 0, 0), Math_PI / 2.0); paste_indicator.orientation = r.get_orthogonal_index(); @@ -198,10 +183,8 @@ void GridMapEditor::_menu_option(int p_option) { _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_BACK_ROTATE_Z: { - Basis r; if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(0, 0, 1), Math_PI / 2.0); paste_indicator.orientation = r.get_orthogonal_index(); @@ -215,9 +198,7 @@ void GridMapEditor::_menu_option(int p_option) { _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_CLEAR_ROTATION: { - if (input_action == INPUT_PASTE) { - paste_indicator.orientation = 0; _update_paste_indicator(); break; @@ -234,8 +215,9 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_SELECTION_DUPLICATE: case MENU_OPTION_SELECTION_CUT: { - if (!(selection.active && input_action == INPUT_NONE)) + if (!(selection.active && input_action == INPUT_NONE)) { break; + } _set_clipboard_data(); @@ -252,15 +234,17 @@ void GridMapEditor::_menu_option(int p_option) { _update_paste_indicator(); } break; case MENU_OPTION_SELECTION_CLEAR: { - if (!selection.active) + if (!selection.active) { break; + } _delete_selection(); } break; case MENU_OPTION_SELECTION_FILL: { - if (!selection.active) + if (!selection.active) { return; + } _fill_selection(); @@ -272,7 +256,6 @@ void GridMapEditor::_menu_option(int p_option) { } void GridMapEditor::_update_cursor_transform() { - cursor_transform = Transform(); cursor_transform.origin = cursor_origin; cursor_transform.basis.set_orthogonal_index(cursor_rot); @@ -280,8 +263,8 @@ void GridMapEditor::_update_cursor_transform() { cursor_transform = node->get_global_transform() * cursor_transform; if (cursor_instance.is_valid()) { - VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); - VisualServer::get_singleton()->instance_set_visible(cursor_instance, cursor_visible); + RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); + RenderingServer::get_singleton()->instance_set_visible(cursor_instance, cursor_visible); } } @@ -290,10 +273,9 @@ void GridMapEditor::_update_selection_transform() { xf_zero.basis.set_zero(); if (!selection.active) { - - VisualServer::get_singleton()->instance_set_transform(selection_instance, xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_instance, xf_zero); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); } return; } @@ -302,13 +284,12 @@ void GridMapEditor::_update_selection_transform() { xf.scale((Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size()); xf.origin = selection.begin * node->get_cell_size(); - VisualServer::get_singleton()->instance_set_transform(selection_instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(selection_instance, node->get_global_transform() * xf); for (int i = 0; i < 3; i++) { if (i != edit_axis || (edit_floor[edit_axis] < selection.begin[edit_axis]) || (edit_floor[edit_axis] > selection.end[edit_axis] + 1)) { - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); } else { - Vector3 scale = (selection.end - selection.begin + Vector3(1, 1, 1)); scale[edit_axis] = 1.0; Vector3 pos = selection.begin; @@ -321,30 +302,32 @@ void GridMapEditor::_update_selection_transform() { xf2.basis.scale(scale); xf2.origin = pos; - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); } } } void GridMapEditor::_validate_selection() { - - if (!selection.active) + if (!selection.active) { return; + } selection.begin = selection.click; selection.end = selection.current; - if (selection.begin.x > selection.end.x) + if (selection.begin.x > selection.end.x) { SWAP(selection.begin.x, selection.end.x); - if (selection.begin.y > selection.end.y) + } + if (selection.begin.y > selection.end.y) { SWAP(selection.begin.y, selection.end.y); - if (selection.begin.z > selection.end.z) + } + if (selection.begin.z > selection.end.z) { SWAP(selection.begin.z, selection.end.z); + } _update_selection_transform(); } void GridMapEditor::_set_selection(bool p_active, const Vector3 &p_begin, const Vector3 &p_end) { - selection.active = p_active; selection.begin = p_begin; selection.end = p_end; @@ -361,20 +344,23 @@ void GridMapEditor::_set_selection(bool p_active, const Vector3 &p_begin, const options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_SELECTION_FILL), !selection.active); } -bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click) { - - if (!spatial_editor) +bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click) { + if (!spatial_editor) { return false; + } - if (selected_palette < 0 && input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE) + if (selected_palette < 0 && input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE) { return false; + } Ref<MeshLibrary> mesh_library = node->get_mesh_library(); - if (mesh_library.is_null()) + if (mesh_library.is_null()) { return false; - if (input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE && !mesh_library->has_item(selected_palette)) + } + if (input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE && !mesh_library->has_item(selected_palette)) { return false; + } - Camera *camera = p_camera; + Camera3D *camera = p_camera; Vector3 from = camera->project_ray_origin(p_point); Vector3 normal = camera->project_ray_normal(p_point); Transform local_xform = node->get_global_transform().affine_inverse(); @@ -387,38 +373,37 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo p.d = edit_floor[edit_axis] * node->get_cell_size()[edit_axis]; Vector3 inters; - if (!p.intersects_segment(from, from + normal * settings_pick_distance->get_value(), &inters)) + if (!p.intersects_segment(from, from + normal * settings_pick_distance->get_value(), &inters)) { return false; + } // Make sure the intersection is inside the frustum planes, to avoid // Painting on invisible regions. for (int i = 0; i < planes.size(); i++) { - Plane fp = local_xform.xform(planes[i]); - if (fp.is_point_over(inters)) + if (fp.is_point_over(inters)) { return false; + } } int cell[3]; float cell_size[3] = { node->get_cell_size().x, node->get_cell_size().y, node->get_cell_size().z }; for (int i = 0; i < 3; i++) { - - if (i == edit_axis) + if (i == edit_axis) { cell[i] = edit_floor[i]; - else { - + } else { cell[i] = inters[i] / node->get_cell_size()[i]; - if (inters[i] < 0) + if (inters[i] < 0) { cell[i] -= 1; // Compensate negative. + } grid_ofs[i] = cell[i] * cell_size[i]; } } - VS::get_singleton()->instance_set_transform(grid_instance[edit_axis], node->get_global_transform() * edit_grid_xform); + RS::get_singleton()->instance_set_transform(grid_instance[edit_axis], node->get_global_transform() * edit_grid_xform); if (cursor_instance.is_valid()) { - cursor_origin = (Vector3(cell[0], cell[1], cell[2]) + Vector3(0.5 * node->get_center_x(), 0.5 * node->get_center_y(), 0.5 * node->get_center_z())) * node->get_cell_size(); cursor_visible = true; @@ -430,21 +415,19 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo } if (input_action == INPUT_PASTE) { - paste_indicator.current = Vector3(cell[0], cell[1], cell[2]); _update_paste_indicator(); } else if (input_action == INPUT_SELECT) { - selection.current = Vector3(cell[0], cell[1], cell[2]); - if (p_click) + if (p_click) { selection.click = selection.current; + } selection.active = true; _validate_selection(); return true; } else if (input_action == INPUT_PICK) { - int item = node->get_cell_item(cell[0], cell[1], cell[2]); if (item >= 0) { selected_palette = item; @@ -480,17 +463,14 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo } void GridMapEditor::_delete_selection() { - - if (!selection.active) + if (!selection.active) { return; + } undo_redo->create_action(TTR("GridMap Delete Selection")); for (int i = selection.begin.x; i <= selection.end.x; i++) { - for (int j = selection.begin.y; j <= selection.end.y; j++) { - for (int k = selection.begin.z; k <= selection.end.z; k++) { - undo_redo->add_do_method(node, "set_cell_item", i, j, k, GridMap::INVALID_CELL_ITEM); undo_redo->add_undo_method(node, "set_cell_item", i, j, k, node->get_cell_item(i, j, k), node->get_cell_item_orientation(i, j, k)); } @@ -502,17 +482,14 @@ void GridMapEditor::_delete_selection() { } void GridMapEditor::_fill_selection() { - - if (!selection.active) + if (!selection.active) { return; + } undo_redo->create_action(TTR("GridMap Fill Selection")); for (int i = selection.begin.x; i <= selection.end.x; i++) { - for (int j = selection.begin.y; j <= selection.end.y; j++) { - for (int k = selection.begin.z; k <= selection.end.z; k++) { - undo_redo->add_do_method(node, "set_cell_item", i, j, k, selected_palette, cursor_rot); undo_redo->add_undo_method(node, "set_cell_item", i, j, k, node->get_cell_item(i, j, k), node->get_cell_item_orientation(i, j, k)); } @@ -524,30 +501,25 @@ void GridMapEditor::_fill_selection() { } void GridMapEditor::_clear_clipboard_data() { - for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) { - - VisualServer::get_singleton()->free(E->get().instance); + RenderingServer::get_singleton()->free(E->get().instance); } clipboard_items.clear(); } void GridMapEditor::_set_clipboard_data() { - _clear_clipboard_data(); Ref<MeshLibrary> meshLibrary = node->get_mesh_library(); for (int i = selection.begin.x; i <= selection.end.x; i++) { - for (int j = selection.begin.y; j <= selection.end.y; j++) { - for (int k = selection.begin.z; k <= selection.end.z; k++) { - int itm = node->get_cell_item(i, j, k); - if (itm == GridMap::INVALID_CELL_ITEM) + if (itm == GridMap::INVALID_CELL_ITEM) { continue; + } Ref<Mesh> mesh = meshLibrary->get_item_mesh(itm); @@ -555,7 +527,7 @@ void GridMapEditor::_set_clipboard_data() { item.cell_item = itm; item.grid_offset = Vector3(i, j, k) - selection.begin; item.orientation = node->get_cell_item_orientation(i, j, k); - item.instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); + item.instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world_3d()->get_scenario()); clipboard_items.push_back(item); } @@ -564,12 +536,10 @@ void GridMapEditor::_set_clipboard_data() { } void GridMapEditor::_update_paste_indicator() { - if (input_action != INPUT_PASTE) { - Transform xf; xf.basis.set_zero(); - VisualServer::get_singleton()->instance_set_transform(paste_instance, xf); + RenderingServer::get_singleton()->instance_set_transform(paste_instance, xf); return; } @@ -583,10 +553,9 @@ void GridMapEditor::_update_paste_indicator() { xf.basis = rot * xf.basis; xf.translate((-center * node->get_cell_size()) / scale); - VisualServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) { - ClipboardItem &item = E->get(); xf = Transform(); @@ -598,12 +567,11 @@ void GridMapEditor::_update_paste_indicator() { item_rot.set_orthogonal_index(item.orientation); xf.basis = item_rot * xf.basis * node->get_cell_scale(); - VisualServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf); } } void GridMapEditor::_do_paste() { - int idx = options->get_popup()->get_item_index(MENU_OPTION_PASTE_SELECTS); bool reselect = options->get_popup()->is_item_checked(idx); @@ -614,7 +582,6 @@ void GridMapEditor::_do_paste() { undo_redo->create_action(TTR("GridMap Paste Selection")); for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) { - ClipboardItem &item = E->get(); Vector3 pos = rot.xform(item.grid_offset) + paste_indicator.begin + ofs; @@ -628,7 +595,6 @@ void GridMapEditor::_do_paste() { } if (reselect) { - undo_redo->add_do_method(this, "_set_selection", true, paste_indicator.begin + ofs, paste_indicator.end + ofs); undo_redo->add_undo_method(this, "_set_selection", selection.active, selection.begin, selection.end); } @@ -638,7 +604,7 @@ void GridMapEditor::_do_paste() { _clear_clipboard_data(); } -bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<InputEvent> &p_event) { +bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<InputEvent> &p_event) { if (!node) { return false; } @@ -646,24 +612,24 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == BUTTON_WHEEL_UP && (mb->get_command() || mb->get_shift())) { - if (mb->is_pressed()) + if (mb->is_pressed()) { floor->set_value(floor->get_value() + mb->get_factor()); + } return true; // Eaten. } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && (mb->get_command() || mb->get_shift())) { - if (mb->is_pressed()) + if (mb->is_pressed()) { floor->set_value(floor->get_value() - mb->get_factor()); + } return true; } if (mb->is_pressed()) { - SpatialEditorViewport::NavigationScheme nav_scheme = (SpatialEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); - if ((nav_scheme == SpatialEditorViewport::NAVIGATION_MAYA || nav_scheme == SpatialEditorViewport::NAVIGATION_MODO) && mb->get_alt()) { + Node3DEditorViewport::NavigationScheme nav_scheme = (Node3DEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); + if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->get_alt()) { input_action = INPUT_NONE; } else if (mb->get_button_index() == BUTTON_LEFT) { - bool can_edit = (node && node->get_mesh_library().is_valid()); if (input_action == INPUT_PASTE) { _do_paste(); @@ -697,18 +663,14 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu return do_input_action(p_camera, Point2(mb->get_position().x, mb->get_position().y), true); } else { - if ((mb->get_button_index() == BUTTON_RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_PAINT)) { - if (set_items.size()) { undo_redo->create_action(TTR("GridMap Paint")); for (List<SetItem>::Element *E = set_items.front(); E; E = E->next()) { - const SetItem &si = E->get(); undo_redo->add_do_method(node, "set_cell_item", si.pos.x, si.pos.y, si.pos.z, si.new_value, si.new_orientation); } for (List<SetItem>::Element *E = set_items.back(); E; E = E->prev()) { - const SetItem &si = E->get(); undo_redo->add_undo_method(node, "set_cell_item", si.pos.x, si.pos.y, si.pos.z, si.old_value, si.old_orientation); } @@ -721,7 +683,6 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu } if (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_SELECT) { - undo_redo->create_action("GridMap Selection"); undo_redo->add_do_method(this, "_set_selection", selection.active, selection.begin, selection.end); undo_redo->add_undo_method(this, "_set_selection", last_selection.active, last_selection.begin, last_selection.end); @@ -729,7 +690,6 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu } if (mb->get_button_index() == BUTTON_LEFT && input_action != INPUT_NONE) { - set_items.clear(); input_action = INPUT_NONE; return true; @@ -744,7 +704,6 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { - return do_input_action(p_camera, mm->get_position(), false); } @@ -753,7 +712,6 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu if (k.is_valid()) { if (k->is_pressed()) { if (k->get_keycode() == KEY_ESCAPE) { - if (input_action == INPUT_PASTE) { _clear_clipboard_data(); input_action = INPUT_NONE; @@ -772,7 +730,6 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu } if (k->get_shift() && selection.active && input_action != INPUT_PASTE) { - if (k->get_keycode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) { selection.click[edit_axis]--; _validate_selection(); @@ -789,7 +746,6 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid()) { - if (pan_gesture->get_alt() && (pan_gesture->get_command() || pan_gesture->get_shift())) { const real_t delta = pan_gesture->get_delta().y * 0.5; accumulated_floor_delta += delta; @@ -810,7 +766,6 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu } struct _CGMEItemSort { - String name; int id; _FORCE_INLINE_ bool operator<(const _CGMEItemSort &r_it) const { return name < r_it.name; } @@ -839,11 +794,9 @@ void GridMapEditor::_text_changed(const String &p_text) { } void GridMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) { - const Ref<InputEventKey> k = p_ie; if (k.is_valid() && (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_PAGEUP || k->get_keycode() == KEY_PAGEDOWN)) { - // Forward the key input to the ItemList so it can be scrolled mesh_library_palette->call("_gui_input", k); search_box->accept_event(); @@ -851,12 +804,10 @@ void GridMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) { } void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) { - const Ref<InputEventMouseButton> mb = p_ie; // Zoom in/out using Ctrl + mouse wheel if (mb.is_valid() && mb->is_pressed() && mb->get_command()) { - if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { size_slider->set_value(size_slider->get_value() + 0.2); } @@ -895,7 +846,7 @@ void GridMapEditor::update_palette() { Ref<MeshLibrary> mesh_library = node->get_mesh_library(); if (mesh_library.is_null()) { - last_mesh_library = NULL; + last_mesh_library = nullptr; search_box->set_text(""); search_box->set_editable(false); info_message->show(); @@ -910,7 +861,6 @@ void GridMapEditor::update_palette() { List<_CGMEItemSort> il; for (int i = 0; i < ids.size(); i++) { - _CGMEItemSort is; is.id = ids[i]; is.name = mesh_library->get_item_name(ids[i]); @@ -931,8 +881,9 @@ void GridMapEditor::update_palette() { name = "#" + itos(id); } - if (filter != "" && !filter.is_subsequence_ofi(name)) + if (filter != "" && !filter.is_subsequence_ofi(name)) { continue; + } mesh_library_palette->add_item(""); if (!preview.is_null()) { @@ -953,8 +904,9 @@ void GridMapEditor::update_palette() { } void GridMapEditor::edit(GridMap *p_gridmap) { - if (!p_gridmap && node) + if (!p_gridmap && node) { node->disconnect("cell_size_changed", callable_mp(this, &GridMapEditor::_draw_grids)); + } node = p_gridmap; @@ -963,16 +915,16 @@ void GridMapEditor::edit(GridMap *p_gridmap) { _update_selection_transform(); _update_paste_indicator(); - spatial_editor = Object::cast_to<SpatialEditorPlugin>(editor->get_editor_plugin_screen()); + spatial_editor = Object::cast_to<Node3DEditorPlugin>(editor->get_editor_plugin_screen()); if (!node) { set_process(false); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], false); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], false); } if (cursor_instance.is_valid()) { - VisualServer::get_singleton()->instance_set_visible(cursor_instance, false); + RenderingServer::get_singleton()->instance_set_visible(cursor_instance, false); } return; @@ -992,16 +944,15 @@ void GridMapEditor::edit(GridMap *p_gridmap) { } void GridMapEditor::_update_clip() { - node->set_meta("_editor_clip_", clip_mode); - if (clip_mode == CLIP_DISABLED) + if (clip_mode == CLIP_DISABLED) { node->set_clip(false); - else + } else { node->set_clip(true, clip_mode == CLIP_ABOVE, edit_floor[edit_axis], edit_axis); + } } void GridMapEditor::update_grid() { - grid_xform.origin.x -= 1; // Force update in hackish way. grid_ofs[edit_axis] = edit_floor[edit_axis] * node->get_cell_size()[edit_axis]; @@ -1010,7 +961,7 @@ void GridMapEditor::update_grid() { edit_grid_xform.basis = Basis(); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], i == edit_axis); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], i == edit_axis); } updating = true; @@ -1022,7 +973,7 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { Vector3 edited_floor = node->has_meta("_editor_floor_") ? node->get_meta("_editor_floor_") : Variant(); for (int i = 0; i < 3; i++) { - VS::get_singleton()->mesh_clear(grid[i]); + RS::get_singleton()->mesh_clear(grid[i]); edit_floor[i] = edited_floor[i]; } @@ -1030,7 +981,6 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { Vector<Color> grid_colors[3]; for (int i = 0; i < 3; i++) { - Vector3 axis; axis[i] = 1; Vector3 axis_n1; @@ -1039,9 +989,7 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { axis_n2[(i + 2) % 3] = cell_size[(i + 2) % 3]; for (int j = -GRID_CURSOR_SIZE; j <= GRID_CURSOR_SIZE; j++) { - for (int k = -GRID_CURSOR_SIZE; k <= GRID_CURSOR_SIZE; k++) { - Vector3 p = axis_n1 * j + axis_n2 * k; float trans = Math::pow(MAX(0, 1.0 - (Vector2(j, k).length() / GRID_CURSOR_SIZE)), 2); @@ -1064,30 +1012,27 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { } Array d; - d.resize(VS::ARRAY_MAX); - d[VS::ARRAY_VERTEX] = grid_points[i]; - d[VS::ARRAY_COLOR] = grid_colors[i]; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], VisualServer::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); + d.resize(RS::ARRAY_MAX); + d[RS::ARRAY_VERTEX] = grid_points[i]; + d[RS::ARRAY_COLOR] = grid_colors[i]; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], RenderingServer::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); } } void GridMapEditor::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { get_tree()->connect("node_removed", callable_mp(this, &GridMapEditor::_node_removed)); mesh_library_palette->connect("item_selected", callable_mp(this, &GridMapEditor::_item_selected_cbk)); for (int i = 0; i < 3; i++) { - - grid[i] = VS::get_singleton()->mesh_create(); - grid_instance[i] = VS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario()); - selection_level_instance[i] = VisualServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world()->get_scenario()); + grid[i] = RS::get_singleton()->mesh_create(); + grid_instance[i] = RS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world_3d()->get_scenario()); + selection_level_instance[i] = RenderingServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world_3d()->get_scenario()); } - selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario()); - paste_instance = VisualServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world()->get_scenario()); + selection_instance = RenderingServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world_3d()->get_scenario()); + paste_instance = RenderingServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world_3d()->get_scenario()); _update_selection_transform(); _update_paste_indicator(); @@ -1098,16 +1043,15 @@ void GridMapEditor::_notification(int p_what) { _clear_clipboard_data(); for (int i = 0; i < 3; i++) { - - VS::get_singleton()->free(grid_instance[i]); - VS::get_singleton()->free(grid[i]); + RS::get_singleton()->free(grid_instance[i]); + RS::get_singleton()->free(grid[i]); grid_instance[i] = RID(); grid[i] = RID(); - VisualServer::get_singleton()->free(selection_level_instance[i]); + RenderingServer::get_singleton()->free(selection_level_instance[i]); } - VisualServer::get_singleton()->free(selection_instance); - VisualServer::get_singleton()->free(paste_instance); + RenderingServer::get_singleton()->free(selection_instance); + RenderingServer::get_singleton()->free(paste_instance); selection_instance = RID(); paste_instance = RID(); } break; @@ -1121,17 +1065,16 @@ void GridMapEditor::_notification(int p_what) { if (xf != grid_xform) { for (int i = 0; i < 3; i++) { - - VS::get_singleton()->instance_set_transform(grid_instance[i], xf * edit_grid_xform); + RS::get_singleton()->instance_set_transform(grid_instance[i], xf * edit_grid_xform); } grid_xform = xf; } Ref<MeshLibrary> cgmt = node->get_mesh_library(); - if (cgmt.operator->() != last_mesh_library) + if (cgmt.operator->() != last_mesh_library) { update_palette(); + } if (lock_view) { - EditorNode *editor = Object::cast_to<EditorNode>(get_tree()->get_root()->get_child(0)); Plane p; @@ -1139,15 +1082,16 @@ void GridMapEditor::_notification(int p_what) { p.d = edit_floor[edit_axis] * node->get_cell_size()[edit_axis]; p = node->get_transform().xform(p); // plane to snap - SpatialEditorPlugin *sep = Object::cast_to<SpatialEditorPlugin>(editor->get_editor_plugin_screen()); - if (sep) + Node3DEditorPlugin *sep = Object::cast_to<Node3DEditorPlugin>(editor->get_editor_plugin_screen()); + if (sep) { sep->snap_cursor_to_plane(p); + } } } break; case NOTIFICATION_THEME_CHANGED: { - options->set_icon(get_icon("GridMap", "EditorIcons")); - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + options->set_icon(get_theme_icon("GridMap", "EditorIcons")); + search_box->set_right_icon(get_theme_icon("Search", "EditorIcons")); } break; } } @@ -1157,18 +1101,17 @@ void GridMapEditor::_update_cursor_instance() { return; } - if (cursor_instance.is_valid()) - VisualServer::get_singleton()->free(cursor_instance); + if (cursor_instance.is_valid()) { + RenderingServer::get_singleton()->free(cursor_instance); + } cursor_instance = RID(); if (selected_palette >= 0) { - if (node && !node->get_mesh_library().is_null()) { Ref<Mesh> mesh = node->get_mesh_library()->get_item_mesh(selected_palette); if (!mesh.is_null() && mesh->get_rid().is_valid()) { - - cursor_instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); - VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); + cursor_instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world_3d()->get_scenario()); + RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); } } } @@ -1181,9 +1124,9 @@ void GridMapEditor::_item_selected_cbk(int idx) { } void GridMapEditor::_floor_changed(float p_value) { - - if (updating) + if (updating) { return; + } edit_floor[edit_axis] = p_value; node->set_meta("_editor_floor_", Vector3(edit_floor[0], edit_floor[1], edit_floor[2])); @@ -1197,13 +1140,11 @@ void GridMapEditor::_floor_mouse_exited() { } void GridMapEditor::_bind_methods() { - ClassDB::bind_method("_configure", &GridMapEditor::_configure); ClassDB::bind_method("_set_selection", &GridMapEditor::_set_selection); } GridMapEditor::GridMapEditor(EditorNode *p_editor) { - input_action = INPUT_NONE; editor = p_editor; undo_redo = p_editor->get_undo_redo(); @@ -1216,7 +1157,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { spatial_editor_hb = memnew(HBoxContainer); spatial_editor_hb->set_h_size_flags(SIZE_EXPAND_FILL); spatial_editor_hb->set_alignment(BoxContainer::ALIGN_END); - SpatialEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); + Node3DEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); spin_box_label = memnew(Label); spin_box_label->set_text(TTR("Floor:")); @@ -1226,7 +1167,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { floor->set_min(-32767); floor->set_max(32767); floor->set_step(1); - floor->get_line_edit()->add_constant_override("minimum_spaces", 16); + floor->get_line_edit()->add_theme_constant_override("minimum_spaces", 16); spatial_editor_hb->add_child(floor); floor->connect("value_changed", callable_mp(this, &GridMapEditor::_floor_changed)); @@ -1304,14 +1245,14 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { mode_thumbnail = memnew(ToolButton); mode_thumbnail->set_toggle_mode(true); mode_thumbnail->set_pressed(true); - mode_thumbnail->set_icon(p_editor->get_gui_base()->get_icon("FileThumbnail", "EditorIcons")); + mode_thumbnail->set_icon(p_editor->get_gui_base()->get_theme_icon("FileThumbnail", "EditorIcons")); hb->add_child(mode_thumbnail); mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_THUMBNAIL)); mode_list = memnew(ToolButton); mode_list->set_toggle_mode(true); mode_list->set_pressed(false); - mode_list->set_icon(p_editor->get_gui_base()->get_icon("FileList", "EditorIcons")); + mode_list->set_icon(p_editor->get_gui_base()->get_theme_icon("FileList", "EditorIcons")); hb->add_child(mode_list); mode_list->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_LIST)); @@ -1352,8 +1293,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { lock_view = false; cursor_rot = 0; - selection_mesh = VisualServer::get_singleton()->mesh_create(); - paste_mesh = VisualServer::get_singleton()->mesh_create(); + selection_mesh = RenderingServer::get_singleton()->mesh_create(); + paste_mesh = RenderingServer::get_singleton()->mesh_create(); { // Selection mesh create. @@ -1363,22 +1304,20 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { Vector<Vector3> square[3]; for (int i = 0; i < 6; i++) { - Vector3 face_points[4]; for (int j = 0; j < 4; j++) { - float v[3]; v[0] = 1.0; v[1] = 1 - 2 * ((j >> 1) & 1); v[2] = v[1] * (1 - 2 * (j & 1)); for (int k = 0; k < 3; k++) { - - if (i < 3) + if (i < 3) { face_points[j][(i + k) % 3] = v[k]; - else + } else { face_points[3 - j][(i + k) % 3] = -v[k]; + } } } @@ -1392,7 +1331,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { } for (int i = 0; i < 12; i++) { - AABB base(Vector3(0, 0, 0), Vector3(1, 1, 1)); Vector3 a, b; base.get_edge(i, a, b); @@ -1403,9 +1341,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { for (int i = 0; i < 3; i++) { Vector3 points[4]; for (int j = 0; j < 4; j++) { - - static const bool orderx[4] = { 0, 1, 1, 0 }; - static const bool ordery[4] = { 0, 0, 1, 1 }; + static const bool orderx[4] = { false, true, true, false }; + static const bool ordery[4] = { false, false, true, true }; Vector3 sp; if (orderx[j]) { @@ -1419,7 +1356,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { } for (int j = 0; j < 4; j++) { - Vector3 ofs; ofs[i] += 0.01; square[i].push_back(points[j] - ofs); @@ -1430,16 +1366,16 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { } Array d; - d.resize(VS::ARRAY_MAX); + d.resize(RS::ARRAY_MAX); inner_mat.instance(); inner_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.2)); inner_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); inner_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); - d[VS::ARRAY_VERTEX] = triangles; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_TRIANGLES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat->get_rid()); + d[RS::ARRAY_VERTEX] = triangles; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, RS::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat->get_rid()); outer_mat.instance(); outer_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.8)); @@ -1453,23 +1389,23 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { selection_floor_mat->set_on_top_of_alpha(); selection_floor_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - d[VS::ARRAY_VERTEX] = lines; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid()); + d[RS::ARRAY_VERTEX] = lines; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, RS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid()); - d[VS::ARRAY_VERTEX] = triangles; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_TRIANGLES, d); - VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 0, inner_mat->get_rid()); + d[RS::ARRAY_VERTEX] = triangles; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, RS::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(paste_mesh, 0, inner_mat->get_rid()); - d[VS::ARRAY_VERTEX] = lines; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 1, outer_mat->get_rid()); + d[RS::ARRAY_VERTEX] = lines; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, RS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(paste_mesh, 1, outer_mat->get_rid()); for (int i = 0; i < 3; i++) { - d[VS::ARRAY_VERTEX] = square[i]; - selection_level_mesh[i] = VS::get_singleton()->mesh_create(); - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_level_mesh[i], VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_level_mesh[i], 0, selection_floor_mat->get_rid()); + d[RS::ARRAY_VERTEX] = square[i]; + selection_level_mesh[i] = RS::get_singleton()->mesh_create(); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_level_mesh[i], RS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_level_mesh[i], 0, selection_floor_mat->get_rid()); } } @@ -1486,74 +1422,72 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { } GridMapEditor::~GridMapEditor() { - _clear_clipboard_data(); for (int i = 0; i < 3; i++) { - - if (grid[i].is_valid()) - VisualServer::get_singleton()->free(grid[i]); - if (grid_instance[i].is_valid()) - VisualServer::get_singleton()->free(grid_instance[i]); - if (cursor_instance.is_valid()) - VisualServer::get_singleton()->free(cursor_instance); - if (selection_level_instance[i].is_valid()) - VisualServer::get_singleton()->free(selection_level_instance[i]); - if (selection_level_mesh[i].is_valid()) - VisualServer::get_singleton()->free(selection_level_mesh[i]); + if (grid[i].is_valid()) { + RenderingServer::get_singleton()->free(grid[i]); + } + if (grid_instance[i].is_valid()) { + RenderingServer::get_singleton()->free(grid_instance[i]); + } + if (cursor_instance.is_valid()) { + RenderingServer::get_singleton()->free(cursor_instance); + } + if (selection_level_instance[i].is_valid()) { + RenderingServer::get_singleton()->free(selection_level_instance[i]); + } + if (selection_level_mesh[i].is_valid()) { + RenderingServer::get_singleton()->free(selection_level_mesh[i]); + } } - VisualServer::get_singleton()->free(selection_mesh); - if (selection_instance.is_valid()) - VisualServer::get_singleton()->free(selection_instance); + RenderingServer::get_singleton()->free(selection_mesh); + if (selection_instance.is_valid()) { + RenderingServer::get_singleton()->free(selection_instance); + } - VisualServer::get_singleton()->free(paste_mesh); - if (paste_instance.is_valid()) - VisualServer::get_singleton()->free(paste_instance); + RenderingServer::get_singleton()->free(paste_mesh); + if (paste_instance.is_valid()) { + RenderingServer::get_singleton()->free(paste_instance); + } } void GridMapEditorPlugin::_notification(int p_what) { - if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - switch ((int)EditorSettings::get_singleton()->get("editors/grid_map/editor_side")) { case 0: { // Left. - SpatialEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 0); + Node3DEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 0); } break; case 1: { // Right. - SpatialEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 1); + Node3DEditor::get_singleton()->get_palette_split()->move_child(grid_map_editor, 1); } break; } } } void GridMapEditorPlugin::edit(Object *p_object) { - grid_map_editor->edit(Object::cast_to<GridMap>(p_object)); } bool GridMapEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("GridMap"); } void GridMapEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { grid_map_editor->show(); grid_map_editor->spatial_editor_hb->show(); grid_map_editor->set_process(true); } else { - grid_map_editor->spatial_editor_hb->hide(); grid_map_editor->hide(); - grid_map_editor->edit(NULL); + grid_map_editor->edit(nullptr); grid_map_editor->set_process(false); } } GridMapEditorPlugin::GridMapEditorPlugin(EditorNode *p_node) { - editor = p_node; EDITOR_DEF("editors/grid_map/editor_side", 1); diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index d6459cee0a..19eea18965 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -36,7 +36,7 @@ #include "editor/pane_drag.h" #include "grid_map.h" -class SpatialEditorPlugin; +class Node3DEditorPlugin; class GridMapEditor : public VBoxContainer { GDCLASS(GridMapEditor, VBoxContainer); @@ -85,7 +85,6 @@ class GridMapEditor : public VBoxContainer { Label *spin_box_label; struct SetItem { - Vector3 pos; int new_value; int new_orientation; @@ -133,7 +132,6 @@ class GridMapEditor : public VBoxContainer { bool updating; struct Selection { - Vector3 click; Vector3 current; Vector3 begin; @@ -143,7 +141,6 @@ class GridMapEditor : public VBoxContainer { Selection last_selection; struct PasteIndicator { - Vector3 click; Vector3 current; Vector3 begin; @@ -188,10 +185,9 @@ class GridMapEditor : public VBoxContainer { }; - SpatialEditorPlugin *spatial_editor; + Node3DEditorPlugin *spatial_editor; struct AreaDisplay { - RID mesh; RID instance; }; @@ -232,7 +228,7 @@ class GridMapEditor : public VBoxContainer { void _delete_selection(); void _fill_selection(); - bool do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click); + bool do_input_action(Camera3D *p_camera, const Point2 &p_point, bool p_click); friend class GridMapEditorPlugin; @@ -242,7 +238,7 @@ protected: static void _bind_methods(); public: - bool forward_spatial_input_event(Camera *p_camera, const Ref<InputEvent> &p_event); + bool forward_spatial_input_event(Camera3D *p_camera, const Ref<InputEvent> &p_event); void edit(GridMap *p_gridmap); GridMapEditor() {} @@ -251,7 +247,6 @@ public: }; class GridMapEditorPlugin : public EditorPlugin { - GDCLASS(GridMapEditorPlugin, EditorPlugin); GridMapEditor *grid_map_editor; @@ -261,7 +256,7 @@ protected: void _notification(int p_what); public: - virtual bool forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event) { return grid_map_editor->forward_spatial_input_event(p_camera, p_event); } + virtual bool forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) { return grid_map_editor->forward_spatial_input_event(p_camera, p_event); } virtual String get_name() const { return "GridMap"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_object); diff --git a/modules/gridmap/register_types.cpp b/modules/gridmap/register_types.cpp index afd51945ab..906e506b62 100644 --- a/modules/gridmap/register_types.cpp +++ b/modules/gridmap/register_types.cpp @@ -36,7 +36,6 @@ #endif void register_gridmap_types() { - #ifndef _3D_DISABLED ClassDB::register_class<GridMap>(); #ifdef TOOLS_ENABLED diff --git a/modules/gridmap/register_types.h b/modules/gridmap/register_types.h index bc720f460c..c0e3c39ca8 100644 --- a/modules/gridmap/register_types.h +++ b/modules/gridmap/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef GRIDMAP_REGISTER_TYPES_H +#define GRIDMAP_REGISTER_TYPES_H + void register_gridmap_types(); void unregister_gridmap_types(); + +#endif // GRIDMAP_REGISTER_TYPES_H diff --git a/modules/hdr/SCsub b/modules/hdr/SCsub index c960e8126b..a709397c9a 100644 --- a/modules/hdr/SCsub +++ b/modules/hdr/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_hdr = env_modules.Clone() diff --git a/modules/hdr/config.py b/modules/hdr/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/hdr/config.py +++ b/modules/hdr/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp index c03ae4ab1f..333b1cf377 100644 --- a/modules/hdr/image_loader_hdr.cpp +++ b/modules/hdr/image_loader_hdr.cpp @@ -34,7 +34,6 @@ #include "core/print_string.h" Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - String header = f->get_token(); ERR_FAIL_COND_V_MSG(header != "#?RADIANCE" && header != "#?RGBE", ERR_FILE_UNRECOGNIZED, "Unsupported header information in HDR: " + header + "."); @@ -42,8 +41,9 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force while (true) { String line = f->get_line(); ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_UNRECOGNIZED); - if (line == "") // empty line indicates end of header + if (line == "") { // empty line indicates end of header break; + } if (line.begins_with("FORMAT=")) { // leave option to implement other commands ERR_FAIL_COND_V_MSG(line != "FORMAT=32-bit_rle_rgbe", ERR_FILE_UNRECOGNIZED, "Only 32-bit_rle_rgbe is supported for HDR files."); } else if (!line.begins_with("#")) { // not comment @@ -68,7 +68,6 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force imgdata.resize(height * width * sizeof(uint32_t)); { - uint8_t *w = imgdata.ptrw(); uint8_t *ptr = (uint8_t *)w; @@ -109,12 +108,14 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force // Run int value = f->get_8(); count -= 128; - for (int z = 0; z < count; ++z) + for (int z = 0; z < count; ++z) { ptr[(j * width + i++) * 4 + k] = uint8_t(value); + } } else { // Dump - for (int z = 0; z < count; ++z) + for (int z = 0; z < count; ++z) { ptr[(j * width + i++) * 4 + k] = f->get_8(); + } } } } @@ -123,7 +124,6 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force //convert for (int i = 0; i < width * height; i++) { - float exp = pow(2.0f, ptr[3] - 128.0f); Color c( @@ -146,7 +146,6 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force } void ImageLoaderHDR::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("hdr"); } diff --git a/modules/hdr/image_loader_hdr.h b/modules/hdr/image_loader_hdr.h index a5f1f9c387..ef8e116616 100644 --- a/modules/hdr/image_loader_hdr.h +++ b/modules/hdr/image_loader_hdr.h @@ -34,7 +34,6 @@ #include "core/io/image_loader.h" class ImageLoaderHDR : public ImageFormatLoader { - public: virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; diff --git a/modules/hdr/register_types.cpp b/modules/hdr/register_types.cpp index 2ef6b7cd07..e749928f60 100644 --- a/modules/hdr/register_types.cpp +++ b/modules/hdr/register_types.cpp @@ -32,15 +32,13 @@ #include "image_loader_hdr.h" -static ImageLoaderHDR *image_loader_hdr = NULL; +static ImageLoaderHDR *image_loader_hdr = nullptr; void register_hdr_types() { - image_loader_hdr = memnew(ImageLoaderHDR); ImageLoader::add_image_format_loader(image_loader_hdr); } void unregister_hdr_types() { - memdelete(image_loader_hdr); } diff --git a/modules/hdr/register_types.h b/modules/hdr/register_types.h index c1c69a1e27..02441516ec 100644 --- a/modules/hdr/register_types.h +++ b/modules/hdr/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef HDR_REGISTER_TYPES_H +#define HDR_REGISTER_TYPES_H + void register_hdr_types(); void unregister_hdr_types(); + +#endif // HDR_REGISTER_TYPES_H diff --git a/modules/jpg/SCsub b/modules/jpg/SCsub index 96e8e704dd..8ee8e6dd6e 100644 --- a/modules/jpg/SCsub +++ b/modules/jpg/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_jpg = env_modules.Clone() diff --git a/modules/jpg/config.py b/modules/jpg/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/jpg/config.py +++ b/modules/jpg/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp index 9e87d11ac1..9c7ace5cf2 100644 --- a/modules/jpg/image_loader_jpegd.cpp +++ b/modules/jpg/image_loader_jpegd.cpp @@ -37,7 +37,6 @@ #include <string.h> Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p_buffer_len) { - jpgd::jpeg_decoder_mem_stream mem_stream(p_buffer, p_buffer_len); jpgd::jpeg_decoder decoder(&mem_stream); @@ -49,11 +48,13 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p const int image_width = decoder.get_width(); const int image_height = decoder.get_height(); const int comps = decoder.get_num_components(); - if (comps != 1 && comps != 3) + if (comps != 1 && comps != 3) { return ERR_FILE_CORRUPT; + } - if (decoder.begin_decoding() != jpgd::JPGD_SUCCESS) + if (decoder.begin_decoding() != jpgd::JPGD_SUCCESS) { return ERR_FILE_CORRUPT; + } const int dst_bpl = image_width * comps; @@ -91,18 +92,18 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p //all good Image::Format fmt; - if (comps == 1) + if (comps == 1) { fmt = Image::FORMAT_L8; - else + } else { fmt = Image::FORMAT_RGB8; + } - p_image->create(image_width, image_height, 0, fmt, data); + p_image->create(image_width, image_height, false, fmt, data); return OK; } Error ImageLoaderJPG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - Vector<uint8_t> src_image; int src_image_len = f->get_len(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); @@ -120,13 +121,11 @@ Error ImageLoaderJPG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force } void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("jpg"); p_extensions->push_back("jpeg"); } static Ref<Image> _jpegd_mem_loader_func(const uint8_t *p_png, int p_size) { - Ref<Image> img; img.instance(); Error err = jpeg_load_image_from_buffer(img.ptr(), p_png, p_size); @@ -135,6 +134,5 @@ static Ref<Image> _jpegd_mem_loader_func(const uint8_t *p_png, int p_size) { } ImageLoaderJPG::ImageLoaderJPG() { - Image::_jpg_mem_loader_func = _jpegd_mem_loader_func; } diff --git a/modules/jpg/image_loader_jpegd.h b/modules/jpg/image_loader_jpegd.h index 9ef37ae303..9aebaad9e3 100644 --- a/modules/jpg/image_loader_jpegd.h +++ b/modules/jpg/image_loader_jpegd.h @@ -34,7 +34,6 @@ #include "core/io/image_loader.h" class ImageLoaderJPG : public ImageFormatLoader { - public: virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; diff --git a/modules/jpg/register_types.cpp b/modules/jpg/register_types.cpp index f6077d5c68..b31746f769 100644 --- a/modules/jpg/register_types.cpp +++ b/modules/jpg/register_types.cpp @@ -32,15 +32,13 @@ #include "image_loader_jpegd.h" -static ImageLoaderJPG *image_loader_jpg = NULL; +static ImageLoaderJPG *image_loader_jpg = nullptr; void register_jpg_types() { - image_loader_jpg = memnew(ImageLoaderJPG); ImageLoader::add_image_format_loader(image_loader_jpg); } void unregister_jpg_types() { - memdelete(image_loader_jpg); } diff --git a/modules/jpg/register_types.h b/modules/jpg/register_types.h index 291098fae2..52cd378b3a 100644 --- a/modules/jpg/register_types.h +++ b/modules/jpg/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef JPG_REGISTER_TYPES_H +#define JPG_REGISTER_TYPES_H + void register_jpg_types(); void unregister_jpg_types(); + +#endif // JPG_REGISTER_TYPES_H diff --git a/modules/jsonrpc/SCsub b/modules/jsonrpc/SCsub index 13c9ffb253..fe5312670a 100644 --- a/modules/jsonrpc/SCsub +++ b/modules/jsonrpc/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_jsonrpc = env_modules.Clone() env_jsonrpc.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/jsonrpc/config.py b/modules/jsonrpc/config.py index 53bc827027..d22f9454ed 100644 --- a/modules/jsonrpc/config.py +++ b/modules/jsonrpc/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return True + return True + def configure(env): - pass + pass diff --git a/modules/jsonrpc/jsonrpc.cpp b/modules/jsonrpc/jsonrpc.cpp index 014b65e3e2..7bb70b098f 100644 --- a/modules/jsonrpc/jsonrpc.cpp +++ b/modules/jsonrpc/jsonrpc.cpp @@ -119,8 +119,8 @@ Variant JSONRPC::process_action(const Variant &p_action, bool p_process_arr_elem id = dict["id"]; } - if (object == NULL || !object->has_method(method)) { - ret = make_response_error(JSONRPC::METHOD_NOT_FOUND, "Method not found", id); + if (object == nullptr || !object->has_method(method)) { + ret = make_response_error(JSONRPC::METHOD_NOT_FOUND, "Method not found: " + method, id); } else { Variant call_ret = object->callv(method, args); if (id.get_type() != Variant::NIL) { @@ -147,8 +147,9 @@ Variant JSONRPC::process_action(const Variant &p_action, bool p_process_arr_elem } String JSONRPC::process_string(const String &p_input) { - - if (p_input.empty()) return String(); + if (p_input.empty()) { + return String(); + } Variant ret; Variant input; diff --git a/modules/jsonrpc/register_types.h b/modules/jsonrpc/register_types.h index 958f16344a..854d73a21f 100644 --- a/modules/jsonrpc/register_types.h +++ b/modules/jsonrpc/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef JSONRPC_REGISTER_TYPES_H +#define JSONRPC_REGISTER_TYPES_H + void register_jsonrpc_types(); void unregister_jsonrpc_types(); + +#endif // JSONRPC_REGISTER_TYPES_H diff --git a/modules/lightmapper_rd/SCsub b/modules/lightmapper_rd/SCsub new file mode 100644 index 0000000000..2f04f1833e --- /dev/null +++ b/modules/lightmapper_rd/SCsub @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_lightmapper_rd = env_modules.Clone() +env_lightmapper_rd.GLSL_HEADER("lm_raster.glsl") +env_lightmapper_rd.GLSL_HEADER("lm_compute.glsl") +env_lightmapper_rd.GLSL_HEADER("lm_blendseams.glsl") + +# Godot source files +env_lightmapper_rd.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/lightmapper_rd/config.py b/modules/lightmapper_rd/config.py new file mode 100644 index 0000000000..d22f9454ed --- /dev/null +++ b/modules/lightmapper_rd/config.py @@ -0,0 +1,6 @@ +def can_build(env, platform): + return True + + +def configure(env): + pass diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp new file mode 100644 index 0000000000..b55c73e9bc --- /dev/null +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -0,0 +1,1752 @@ +/*************************************************************************/ +/* lightmapper_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "lightmapper_rd.h" +#include "core/math/geometry.h" +#include "core/project_settings.h" +#include "lm_blendseams.glsl.gen.h" +#include "lm_compute.glsl.gen.h" +#include "lm_raster.glsl.gen.h" +#include "servers/rendering/rendering_device_binds.h" + +//uncomment this if you want to see textures from all the process saved +//#define DEBUG_TEXTURES + +void LightmapperRD::add_mesh(const MeshData &p_mesh) { + ERR_FAIL_COND(p_mesh.albedo_on_uv2.is_null() || p_mesh.albedo_on_uv2->empty()); + ERR_FAIL_COND(p_mesh.emission_on_uv2.is_null() || p_mesh.emission_on_uv2->empty()); + ERR_FAIL_COND(p_mesh.albedo_on_uv2->get_width() != p_mesh.emission_on_uv2->get_width()); + ERR_FAIL_COND(p_mesh.albedo_on_uv2->get_height() != p_mesh.emission_on_uv2->get_height()); + ERR_FAIL_COND(p_mesh.points.size() == 0); + MeshInstance mi; + mi.data = p_mesh; + mesh_instances.push_back(mi); +} + +void LightmapperRD::add_directional_light(bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_angular_distance) { + Light l; + l.type = LIGHT_TYPE_DIRECTIONAL; + l.direction[0] = p_direction.x; + l.direction[1] = p_direction.y; + l.direction[2] = p_direction.z; + l.color[0] = p_color.r; + l.color[1] = p_color.g; + l.color[2] = p_color.b; + l.energy = p_energy; + l.static_bake = p_static; + l.size = p_angular_distance; + lights.push_back(l); +} + +void LightmapperRD::add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size) { + Light l; + l.type = LIGHT_TYPE_OMNI; + l.position[0] = p_position.x; + l.position[1] = p_position.y; + l.position[2] = p_position.z; + l.range = p_range; + l.attenuation = p_attenuation; + l.color[0] = p_color.r; + l.color[1] = p_color.g; + l.color[2] = p_color.b; + l.energy = p_energy; + l.static_bake = p_static; + l.size = p_size; + lights.push_back(l); +} + +void LightmapperRD::add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) { + Light l; + l.type = LIGHT_TYPE_SPOT; + l.position[0] = p_position.x; + l.position[1] = p_position.y; + l.position[2] = p_position.z; + l.direction[0] = p_direction.x; + l.direction[1] = p_direction.y; + l.direction[2] = p_direction.z; + l.range = p_range; + l.attenuation = p_attenuation; + l.spot_angle = Math::deg2rad(p_spot_angle); + l.spot_attenuation = p_spot_attenuation; + l.color[0] = p_color.r; + l.color[1] = p_color.g; + l.color[2] = p_color.b; + l.energy = p_energy; + l.static_bake = p_static; + l.size = p_size; + lights.push_back(l); +} + +void LightmapperRD::add_probe(const Vector3 &p_position) { + Probe probe; + probe.position[0] = p_position.x; + probe.position[1] = p_position.y; + probe.position[2] = p_position.z; + probe.position[3] = 0; + probe_positions.push_back(probe); +} + +void LightmapperRD::_plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[3], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size) { + int half_size = p_size / 2; + + for (int i = 0; i < 8; i++) { + AABB aabb = p_bounds; + aabb.size *= 0.5; + Vector3i n = p_ofs; + + if (i & 1) { + aabb.position.x += aabb.size.x; + n.x += half_size; + } + if (i & 2) { + aabb.position.y += aabb.size.y; + n.y += half_size; + } + if (i & 4) { + aabb.position.z += aabb.size.z; + n.z += half_size; + } + + { + Vector3 qsize = aabb.size * 0.5; //quarter size, for fast aabb test + + if (!Geometry::triangle_box_overlap(aabb.position + qsize, qsize, p_points)) { + //does not fit in child, go on + continue; + } + } + + if (half_size == 1) { + //got to the end + TriangleSort ts; + ts.cell_index = n.x + (n.y * p_grid_size) + (n.z * p_grid_size * p_grid_size); + ts.triangle_index = p_triangle_index; + triangles.push_back(ts); + } else { + _plot_triangle_into_triangle_index_list(half_size, n, aabb, p_points, p_triangle_index, triangles, p_grid_size); + } + } +} + +Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_size, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata) { + Vector<Size2i> sizes; + + for (int m_i = 0; m_i < mesh_instances.size(); m_i++) { + MeshInstance &mi = mesh_instances.write[m_i]; + Size2i s = Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height()); + sizes.push_back(s); + atlas_size.width = MAX(atlas_size.width, s.width); + atlas_size.height = MAX(atlas_size.height, s.height); + } + + int max = nearest_power_of_2_templated(atlas_size.width); + max = MAX(max, nearest_power_of_2_templated(atlas_size.height)); + + if (max > p_max_texture_size) { + return BAKE_ERROR_LIGHTMAP_TOO_SMALL; + } + + if (p_step_function) { + p_step_function(0.1, TTR("Determining optimal atlas size"), p_bake_userdata, true); + } + + atlas_size = Size2i(max, max); + + Size2i best_atlas_size; + int best_atlas_slices = 0; + int best_atlas_memory = 0x7FFFFFFF; + Vector<Vector3i> best_atlas_offsets; + + //determine best texture array atlas size by bruteforce fitting + while (atlas_size.x <= p_max_texture_size && atlas_size.y <= p_max_texture_size) { + Vector<Vector2i> source_sizes = sizes; + Vector<int> source_indices; + source_indices.resize(source_sizes.size()); + for (int i = 0; i < source_indices.size(); i++) { + source_indices.write[i] = i; + } + Vector<Vector3i> atlas_offsets; + atlas_offsets.resize(source_sizes.size()); + + int slices = 0; + + while (source_sizes.size() > 0) { + Vector<Vector3i> offsets = Geometry::partial_pack_rects(source_sizes, atlas_size); + Vector<int> new_indices; + Vector<Vector2i> new_sources; + for (int i = 0; i < offsets.size(); i++) { + Vector3i ofs = offsets[i]; + int sidx = source_indices[i]; + if (ofs.z > 0) { + //valid + ofs.z = slices; + atlas_offsets.write[sidx] = ofs; + } else { + new_indices.push_back(sidx); + new_sources.push_back(source_sizes[i]); + } + } + + source_sizes = new_sources; + source_indices = new_indices; + slices++; + } + + int mem_used = atlas_size.x * atlas_size.y * slices; + if (mem_used < best_atlas_memory) { + best_atlas_size = atlas_size; + best_atlas_offsets = atlas_offsets; + best_atlas_slices = slices; + best_atlas_memory = mem_used; + } + + if (atlas_size.width == atlas_size.height) { + atlas_size.width *= 2; + } else { + atlas_size.height *= 2; + } + } + atlas_size = best_atlas_size; + atlas_slices = best_atlas_slices; + + // apply the offsets and slice to all images, and also blit albedo and emission + albedo_images.resize(atlas_slices); + emission_images.resize(atlas_slices); + + if (p_step_function) { + p_step_function(0.2, TTR("Blitting albedo and emission"), p_bake_userdata, true); + } + + for (int i = 0; i < atlas_slices; i++) { + Ref<Image> albedo; + albedo.instance(); + albedo->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBA8); + albedo->set_as_black(); + albedo_images.write[i] = albedo; + + Ref<Image> emission; + emission.instance(); + emission->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH); + emission->set_as_black(); + emission_images.write[i] = emission; + } + + //assign uv positions + + for (int m_i = 0; m_i < mesh_instances.size(); m_i++) { + MeshInstance &mi = mesh_instances.write[m_i]; + mi.offset.x = best_atlas_offsets[m_i].x; + mi.offset.y = best_atlas_offsets[m_i].y; + mi.slice = best_atlas_offsets[m_i].z; + albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2(Vector2(), Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height())), mi.offset); + emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2(), Size2i(mi.data.emission_on_uv2->get_width(), mi.data.emission_on_uv2->get_height())), mi.offset); + } + + return BAKE_OK; +} + +void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &box_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &grid_texture_sdf, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata) { + HashMap<Vertex, uint32_t, VertexHash> vertex_map; + + //fill triangles array and vertex array + LocalVector<Triangle> triangles; + LocalVector<Vertex> vertex_array; + LocalVector<Box> box_array; + LocalVector<Seam> seams; + + slice_triangle_count.resize(atlas_slices); + slice_seam_count.resize(atlas_slices); + + for (int i = 0; i < atlas_slices; i++) { + slice_triangle_count.write[i] = 0; + slice_seam_count.write[i] = 0; + } + + bounds = AABB(); + + for (int m_i = 0; m_i < mesh_instances.size(); m_i++) { + if (p_step_function) { + float p = float(m_i + 1) / mesh_instances.size() * 0.1; + p_step_function(0.3 + p, vformat(TTR("Plotting mesh into acceleration structure %d/%d"), m_i + 1, mesh_instances.size()), p_bake_userdata, false); + } + + HashMap<Edge, EdgeUV2, EdgeHash> edges; + + MeshInstance &mi = mesh_instances.write[m_i]; + + Vector2 uv_scale = Vector2(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height()) / Vector2(atlas_size); + Vector2 uv_offset = Vector2(mi.offset) / Vector2(atlas_size); + if (m_i == 0) { + bounds.position = mi.data.points[0]; + } + + for (int i = 0; i < mi.data.points.size(); i += 3) { + Vector3 vtxs[3] = { mi.data.points[i + 0], mi.data.points[i + 1], mi.data.points[i + 2] }; + Vector2 uvs[3] = { mi.data.uv2[i + 0] * uv_scale + uv_offset, mi.data.uv2[i + 1] * uv_scale + uv_offset, mi.data.uv2[i + 2] * uv_scale + uv_offset }; + Vector3 normal[3] = { mi.data.normal[i + 0], mi.data.normal[i + 1], mi.data.normal[i + 2] }; + + AABB taabb; + Triangle t; + t.slice = mi.slice; + for (int k = 0; k < 3; k++) { + bounds.expand_to(vtxs[k]); + + Vertex v; + v.position[0] = vtxs[k].x; + v.position[1] = vtxs[k].y; + v.position[2] = vtxs[k].z; + v.uv[0] = uvs[k].x; + v.uv[1] = uvs[k].y; + v.normal_xy[0] = normal[k].x; + v.normal_xy[1] = normal[k].y; + v.normal_z = normal[k].z; + + uint32_t *indexptr = vertex_map.getptr(v); + + if (indexptr) { + t.indices[k] = *indexptr; + } else { + uint32_t new_index = vertex_map.size(); + t.indices[k] = new_index; + vertex_map[v] = new_index; + vertex_array.push_back(v); + } + + if (k == 0) { + taabb.position = vtxs[k]; + } else { + taabb.expand_to(vtxs[k]); + } + } + + //compute seams that will need to be blended later + for (int k = 0; k < 3; k++) { + int n = (k + 1) % 3; + + Edge edge(vtxs[k], vtxs[n], normal[k], normal[n]); + Vector2i edge_indices(t.indices[k], t.indices[n]); + EdgeUV2 uv2(uvs[k], uvs[n], edge_indices); + + if (edge.b == edge.a) { + continue; //degenerate, somehow + } + if (edge.b < edge.a) { + SWAP(edge.a, edge.b); + SWAP(edge.na, edge.nb); + SWAP(uv2.a, uv2.b); + SWAP(edge_indices.x, edge_indices.y); + } + + EdgeUV2 *euv2 = edges.getptr(edge); + if (!euv2) { + edges[edge] = uv2; + } else { + if (*euv2 == uv2) { + continue; // seam shared UV space, no need to blend + } + if (euv2->seam_found) { + continue; //bad geometry + } + + Seam seam; + seam.a = edge_indices; + seam.b = euv2->indices; + seam.slice = mi.slice; + seams.push_back(seam); + slice_seam_count.write[mi.slice]++; + euv2->seam_found = true; + } + } + + Box box; + box.min_bounds[0] = taabb.position.x; + box.min_bounds[1] = taabb.position.y; + box.min_bounds[2] = taabb.position.z; + box.max_bounds[0] = taabb.position.x + MAX(taabb.size.x, 0.0001); + box.max_bounds[1] = taabb.position.y + MAX(taabb.size.y, 0.0001); + box.max_bounds[2] = taabb.position.z + MAX(taabb.size.z, 0.0001); + box.pad0 = box.pad1 = 0; //make valgrind not complain + box_array.push_back(box); + + triangles.push_back(t); + slice_triangle_count.write[t.slice]++; + } + } + + //also consider probe positions for bounds + for (int i = 0; i < probe_positions.size(); i++) { + Vector3 pp(probe_positions[i].position[0], probe_positions[i].position[1], probe_positions[i].position[2]); + bounds.expand_to(pp); + } + bounds.grow_by(0.1); //grow a bit to avoid numerical error + + triangles.sort(); //sort by slice + seams.sort(); + + if (p_step_function) { + p_step_function(0.4, TTR("Optimizing acceleration structure"), p_bake_userdata, true); + } + + //fill list of triangles in grid + LocalVector<TriangleSort> triangle_sort; + for (uint32_t i = 0; i < triangles.size(); i++) { + const Triangle &t = triangles[i]; + Vector3 face[3] = { + Vector3(vertex_array[t.indices[0]].position[0], vertex_array[t.indices[0]].position[1], vertex_array[t.indices[0]].position[2]), + Vector3(vertex_array[t.indices[1]].position[0], vertex_array[t.indices[1]].position[1], vertex_array[t.indices[1]].position[2]), + Vector3(vertex_array[t.indices[2]].position[0], vertex_array[t.indices[2]].position[1], vertex_array[t.indices[2]].position[2]) + }; + _plot_triangle_into_triangle_index_list(grid_size, Vector3i(), bounds, face, i, triangle_sort, grid_size); + } + //sort it + triangle_sort.sort(); + + Vector<uint32_t> triangle_indices; + triangle_indices.resize(triangle_sort.size()); + Vector<uint32_t> grid_indices; + grid_indices.resize(grid_size * grid_size * grid_size * 2); + zeromem(grid_indices.ptrw(), grid_indices.size() * sizeof(uint32_t)); + Vector<bool> solid; + solid.resize(grid_size * grid_size * grid_size); + zeromem(solid.ptrw(), solid.size() * sizeof(bool)); + + { + uint32_t *tiw = triangle_indices.ptrw(); + uint32_t last_cell = 0xFFFFFFFF; + uint32_t *giw = grid_indices.ptrw(); + bool *solidw = solid.ptrw(); + for (uint32_t i = 0; i < triangle_sort.size(); i++) { + uint32_t cell = triangle_sort[i].cell_index; + if (cell != last_cell) { + //cell changed, update pointer to indices + giw[cell * 2 + 1] = i; + last_cell = cell; + solidw[cell] = true; + } + tiw[i] = triangle_sort[i].triangle_index; + giw[cell * 2]++; //update counter + last_cell = cell; + } + } +#if 0 + for (int i = 0; i < grid_size; i++) { + for (int j = 0; j < grid_size; j++) { + for (int k = 0; k < grid_size; k++) { + uint32_t index = i * (grid_size * grid_size) + j * grid_size + k; + grid_indices.write[index * 2] = float(i) / grid_size * 255; + grid_indices.write[index * 2 + 1] = float(j) / grid_size * 255; + } + } + } +#endif + +#if 0 + for (int i = 0; i < grid_size; i++) { + Vector<uint8_t> grid_usage; + grid_usage.resize(grid_size * grid_size); + for (int j = 0; j < grid_usage.size(); j++) { + uint32_t ofs = i * grid_size * grid_size + j; + uint32_t count = grid_indices[ofs * 2]; + grid_usage.write[j] = count > 0 ? 255 : 0; + } + + Ref<Image> img; + img.instance(); + img->create(grid_size, grid_size, false, Image::FORMAT_L8, grid_usage); + img->save_png("res://grid_layer_" + itos(1000 + i).substr(1, 3) + ".png"); + } +#endif + if (p_step_function) { + p_step_function(0.45, TTR("Generating Signed Distance Field"), p_bake_userdata, true); + } + + //generate SDF for raytracing + Vector<uint32_t> euclidean_pos = Geometry::generate_edf(solid, Vector3i(grid_size, grid_size, grid_size), false); + Vector<uint32_t> euclidean_neg = Geometry::generate_edf(solid, Vector3i(grid_size, grid_size, grid_size), true); + Vector<int8_t> sdf8 = Geometry::generate_sdf8(euclidean_pos, euclidean_neg); + + /*****************************/ + /*** CREATE GPU STRUCTURES ***/ + /*****************************/ + + lights.sort(); + + Vector<Vector2i> seam_buffer_vec; + seam_buffer_vec.resize(seams.size() * 2); + for (uint32_t i = 0; i < seams.size(); i++) { + seam_buffer_vec.write[i * 2 + 0] = seams[i].a; + seam_buffer_vec.write[i * 2 + 1] = seams[i].b; + } + + { //buffers + Vector<uint8_t> vb = vertex_array.to_byte_array(); + vertex_buffer = rd->storage_buffer_create(vb.size(), vb); + + Vector<uint8_t> tb = triangles.to_byte_array(); + triangle_buffer = rd->storage_buffer_create(tb.size(), tb); + + Vector<uint8_t> bb = box_array.to_byte_array(); + box_buffer = rd->storage_buffer_create(bb.size(), bb); + + Vector<uint8_t> tib = triangle_indices.to_byte_array(); + triangle_cell_indices_buffer = rd->storage_buffer_create(tib.size(), tib); + + Vector<uint8_t> lb = lights.to_byte_array(); + if (lb.size() == 0) { + lb.resize(sizeof(Light)); //even if no lights, the buffer must exist + } + lights_buffer = rd->storage_buffer_create(lb.size(), lb); + + Vector<uint8_t> sb = seam_buffer_vec.to_byte_array(); + if (sb.size() == 0) { + sb.resize(sizeof(Vector2i) * 2); //even if no seams, the buffer must exist + } + seams_buffer = rd->storage_buffer_create(sb.size(), sb); + + Vector<uint8_t> pb = probe_positions.to_byte_array(); + if (pb.size() == 0) { + pb.resize(sizeof(Probe)); + } + probe_positions_buffer = rd->storage_buffer_create(pb.size(), pb); + } + + { //grid + + RD::TextureFormat tf; + tf.width = grid_size; + tf.height = grid_size; + tf.depth = grid_size; + tf.type = RD::TEXTURE_TYPE_3D; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + + Vector<Vector<uint8_t>> texdata; + texdata.resize(1); + //grid and indices + tf.format = RD::DATA_FORMAT_R32G32_UINT; + texdata.write[0] = grid_indices.to_byte_array(); + grid_texture = rd->texture_create(tf, RD::TextureView(), texdata); + //sdf + tf.format = RD::DATA_FORMAT_R8_SNORM; + texdata.write[0] = sdf8.to_byte_array(); + grid_texture_sdf = rd->texture_create(tf, RD::TextureView(), texdata); + } +} + +void LightmapperRD::_raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform) { + Vector<RID> framebuffers; + + for (int i = 0; i < atlas_slices; i++) { + RID slice_pos_tex = rd->texture_create_shared_from_slice(RD::TextureView(), position_tex, i, 0); + RID slice_unoc_tex = rd->texture_create_shared_from_slice(RD::TextureView(), unocclude_tex, i, 0); + RID slice_norm_tex = rd->texture_create_shared_from_slice(RD::TextureView(), normal_tex, i, 0); + Vector<RID> fb; + fb.push_back(slice_pos_tex); + fb.push_back(slice_norm_tex); + fb.push_back(slice_unoc_tex); + fb.push_back(raster_depth_buffer); + framebuffers.push_back(rd->framebuffer_create(fb)); + } + + RD::PipelineDepthStencilState ds; + ds.enable_depth_test = true; + ds.enable_depth_write = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS; //so it does render same pixel twice + + RID raster_pipeline = rd->render_pipeline_create(rasterize_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(3), 0); + RID raster_pipeline_wire; + { + RD::PipelineRasterizationState rw; + rw.wireframe = true; + raster_pipeline_wire = rd->render_pipeline_create(rasterize_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, rw, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(3), 0); + } + + uint32_t triangle_offset = 0; + Vector<Color> clear_colors; + clear_colors.push_back(Color(0, 0, 0, 0)); + clear_colors.push_back(Color(0, 0, 0, 0)); + clear_colors.push_back(Color(0, 0, 0, 0)); + + for (int i = 0; i < atlas_slices; i++) { + RasterPushConstant raster_push_constant; + raster_push_constant.atlas_size[0] = atlas_size.x; + raster_push_constant.atlas_size[1] = atlas_size.y; + raster_push_constant.base_triangle = triangle_offset; + raster_push_constant.to_cell_offset[0] = bounds.position.x; + raster_push_constant.to_cell_offset[1] = bounds.position.y; + raster_push_constant.to_cell_offset[2] = bounds.position.z; + raster_push_constant.bias = p_bias; + raster_push_constant.to_cell_size[0] = (1.0 / bounds.size.x) * float(grid_size); + raster_push_constant.to_cell_size[1] = (1.0 / bounds.size.y) * float(grid_size); + raster_push_constant.to_cell_size[2] = (1.0 / bounds.size.z) * float(grid_size); + raster_push_constant.grid_size[0] = grid_size; + raster_push_constant.grid_size[1] = grid_size; + raster_push_constant.grid_size[2] = grid_size; + raster_push_constant.uv_offset[0] = 0; + raster_push_constant.uv_offset[1] = 0; + + RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + //draw opaque + rd->draw_list_bind_render_pipeline(draw_list, raster_pipeline); + rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); + rd->draw_list_set_push_constant(draw_list, &raster_push_constant, sizeof(RasterPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3); + //draw wire + rd->draw_list_bind_render_pipeline(draw_list, raster_pipeline_wire); + rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); + rd->draw_list_set_push_constant(draw_list, &raster_push_constant, sizeof(RasterPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3); + + rd->draw_list_end(); + + triangle_offset += slice_triangle_count[i]; + } +} + +LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata) { + if (p_step_function) { + p_step_function(0.0, TTR("Begin Bake"), p_bake_userdata, true); + } + bake_textures.clear(); + int grid_size = 128; + + /* STEP 1: Fetch material textures and compute the bounds */ + + AABB bounds; + Size2i atlas_size; + int atlas_slices; + Vector<Ref<Image>> albedo_images; + Vector<Ref<Image>> emission_images; + + BakeError bake_error = _blit_meshes_into_atlas(p_max_texture_size, albedo_images, emission_images, bounds, atlas_size, atlas_slices, p_step_function, p_bake_userdata); + if (bake_error != BAKE_OK) { + return bake_error; + } + +#ifdef DEBUG_TEXTURES + for (int i = 0; i < atlas_slices; i++) { + albedo_images[i]->save_png("res://0_albedo_" + itos(i) + ".png"); + emission_images[i]->save_png("res://0_emission_" + itos(i) + ".png"); + } +#endif + + RenderingDevice *rd = RenderingDevice::get_singleton()->create_local_device(); + + RID albedo_array_tex; + RID emission_array_tex; + RID normal_tex; + RID position_tex; + RID unocclude_tex; + RID light_source_tex; + RID light_dest_tex; + RID light_accum_tex; + RID light_accum_tex2; + RID light_primary_dynamic_tex; + RID light_environment_tex; + +#define FREE_TEXTURES \ + rd->free(albedo_array_tex); \ + rd->free(emission_array_tex); \ + rd->free(normal_tex); \ + rd->free(position_tex); \ + rd->free(unocclude_tex); \ + rd->free(light_source_tex); \ + rd->free(light_accum_tex2); \ + rd->free(light_accum_tex); \ + rd->free(light_primary_dynamic_tex); \ + rd->free(light_environment_tex); + + { // create all textures + + Vector<Vector<uint8_t>> albedo_data; + Vector<Vector<uint8_t>> emission_data; + for (int i = 0; i < atlas_slices; i++) { + albedo_data.push_back(albedo_images[i]->get_data()); + emission_data.push_back(emission_images[i]->get_data()); + } + + RD::TextureFormat tf; + tf.width = atlas_size.width; + tf.height = atlas_size.height; + tf.array_layers = atlas_slices; + tf.type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + + albedo_array_tex = rd->texture_create(tf, RD::TextureView(), albedo_data); + + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + + emission_array_tex = rd->texture_create(tf, RD::TextureView(), emission_data); + + //this will be rastered to + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + normal_tex = rd->texture_create(tf, RD::TextureView()); + tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + position_tex = rd->texture_create(tf, RD::TextureView()); + unocclude_tex = rd->texture_create(tf, RD::TextureView()); + + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + + light_source_tex = rd->texture_create(tf, RD::TextureView()); + rd->texture_clear(light_source_tex, Color(0, 0, 0, 0), 0, 1, 0, atlas_slices); + light_primary_dynamic_tex = rd->texture_create(tf, RD::TextureView()); + rd->texture_clear(light_primary_dynamic_tex, Color(0, 0, 0, 0), 0, 1, 0, atlas_slices); + + if (p_bake_sh) { + tf.array_layers *= 4; + } + light_accum_tex = rd->texture_create(tf, RD::TextureView()); + rd->texture_clear(light_accum_tex, Color(0, 0, 0, 0), 0, 1, 0, tf.array_layers); + light_dest_tex = rd->texture_create(tf, RD::TextureView()); + rd->texture_clear(light_dest_tex, Color(0, 0, 0, 0), 0, 1, 0, tf.array_layers); + light_accum_tex2 = light_dest_tex; + + //env + { + Ref<Image> panorama_tex; + if (p_environment_panorama.is_valid()) { + panorama_tex = p_environment_panorama; + panorama_tex->convert(Image::FORMAT_RGBAF); + } else { + panorama_tex.instance(); + panorama_tex->create(8, 8, false, Image::FORMAT_RGBAF); + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + panorama_tex->set_pixel(i, j, Color(0, 0, 0, 1)); + } + } + } + + RD::TextureFormat tfp; + tfp.width = panorama_tex->get_width(); + tfp.height = panorama_tex->get_height(); + tfp.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tfp.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + + Vector<Vector<uint8_t>> tdata; + tdata.push_back(panorama_tex->get_data()); + light_environment_tex = rd->texture_create(tfp, RD::TextureView(), tdata); + +#ifdef DEBUG_TEXTURES + panorama_tex->convert(Image::FORMAT_RGB8); + panorama_tex->save_png("res://0_panorama.png"); +#endif + } + } + + /* STEP 2: create the acceleration structure for the GPU*/ + + Vector<int> slice_triangle_count; + RID vertex_buffer; + RID triangle_buffer; + RID box_buffer; + RID lights_buffer; + RID triangle_cell_indices_buffer; + RID grid_texture; + RID grid_texture_sdf; + RID seams_buffer; + RID probe_positions_buffer; + + Vector<int> slice_seam_count; + +#define FREE_BUFFERS \ + rd->free(vertex_buffer); \ + rd->free(triangle_buffer); \ + rd->free(box_buffer); \ + rd->free(lights_buffer); \ + rd->free(triangle_cell_indices_buffer); \ + rd->free(grid_texture); \ + rd->free(grid_texture_sdf); \ + rd->free(seams_buffer); \ + rd->free(probe_positions_buffer); + + _create_acceleration_structures(rd, atlas_size, atlas_slices, bounds, grid_size, probe_positions, p_generate_probes, slice_triangle_count, slice_seam_count, vertex_buffer, triangle_buffer, box_buffer, lights_buffer, triangle_cell_indices_buffer, probe_positions_buffer, grid_texture, grid_texture_sdf, seams_buffer, p_step_function, p_bake_userdata); + + if (p_step_function) { + p_step_function(0.47, TTR("Preparing shaders"), p_bake_userdata, true); + } + + //shaders + Ref<RDShaderFile> raster_shader; + raster_shader.instance(); + Error err = raster_shader->parse_versions_from_text(lm_raster_shader_glsl); + if (err != OK) { + raster_shader->print_errors("raster_shader"); + + FREE_TEXTURES + FREE_BUFFERS + + memdelete(rd); + } + ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + + RID rasterize_shader = rd->shader_create_from_bytecode(raster_shader->get_bytecode()); + + ERR_FAIL_COND_V(rasterize_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //this is a bug check, though, should not happen + + RID sampler; + { + RD::SamplerState s; + s.mag_filter = RD::SAMPLER_FILTER_LINEAR; + s.min_filter = RD::SAMPLER_FILTER_LINEAR; + s.max_lod = 0; + + sampler = rd->sampler_create(s); + } + + Vector<RD::Uniform> base_uniforms; + { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 1; + u.ids.push_back(vertex_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.ids.push_back(triangle_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 3; + u.ids.push_back(box_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 4; + u.ids.push_back(triangle_cell_indices_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 5; + u.ids.push_back(lights_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 6; + u.ids.push_back(seams_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 7; + u.ids.push_back(probe_positions_buffer); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 8; + u.ids.push_back(grid_texture); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 9; + u.ids.push_back(grid_texture_sdf); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 10; + u.ids.push_back(albedo_array_tex); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 11; + u.ids.push_back(emission_array_tex); + base_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 12; + u.ids.push_back(sampler); + base_uniforms.push_back(u); + } + } + + RID raster_base_uniform = rd->uniform_set_create(base_uniforms, rasterize_shader, 0); + RID raster_depth_buffer; + { + RD::TextureFormat tf; + tf.width = atlas_size.width; + tf.height = atlas_size.height; + tf.depth = 1; + tf.type = RD::TEXTURE_TYPE_2D; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + tf.format = RD::DATA_FORMAT_D32_SFLOAT; + + raster_depth_buffer = rd->texture_create(tf, RD::TextureView()); + } + + rd->submit(); + rd->sync(); + + /* STEP 3: Raster the geometry to UV2 coords in the atlas textures GPU*/ + + _raster_geometry(rd, atlas_size, atlas_slices, grid_size, bounds, p_bias, slice_triangle_count, position_tex, unocclude_tex, normal_tex, raster_depth_buffer, rasterize_shader, raster_base_uniform); + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices; i++) { + Vector<uint8_t> s = rd->texture_get_data(position_tex, i); + Ref<Image> img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAF, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://1_position_" + itos(i) + ".png"); + + s = rd->texture_get_data(normal_tex, i); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://1_normal_" + itos(i) + ".png"); + } +#endif + +#define FREE_RASTER_RESOURCES \ + rd->free(rasterize_shader); \ + rd->free(sampler); \ + rd->free(raster_depth_buffer); + + /* Plot direct light */ + + Ref<RDShaderFile> compute_shader; + compute_shader.instance(); + err = compute_shader->parse_versions_from_text(lm_compute_shader_glsl, p_bake_sh ? "\n#define USE_SH_LIGHTMAPS\n" : ""); + if (err != OK) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + memdelete(rd); + compute_shader->print_errors("compute_shader"); + } + ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + + //unoccluder + RID compute_shader_unocclude = rd->shader_create_from_bytecode(compute_shader->get_bytecode("unocclude")); + ERR_FAIL_COND_V(compute_shader_unocclude.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); // internal check, should not happen + RID compute_shader_unocclude_pipeline = rd->compute_pipeline_create(compute_shader_unocclude); + + //direct light + RID compute_shader_primary = rd->shader_create_from_bytecode(compute_shader->get_bytecode("primary")); + ERR_FAIL_COND_V(compute_shader_primary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); // internal check, should not happen + RID compute_shader_primary_pipeline = rd->compute_pipeline_create(compute_shader_primary); + + //indirect light + RID compute_shader_secondary = rd->shader_create_from_bytecode(compute_shader->get_bytecode("secondary")); + ERR_FAIL_COND_V(compute_shader_secondary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen + RID compute_shader_secondary_pipeline = rd->compute_pipeline_create(compute_shader_secondary); + + //dilate + RID compute_shader_dilate = rd->shader_create_from_bytecode(compute_shader->get_bytecode("dilate")); + ERR_FAIL_COND_V(compute_shader_dilate.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen + RID compute_shader_dilate_pipeline = rd->compute_pipeline_create(compute_shader_dilate); + + //dilate + RID compute_shader_light_probes = rd->shader_create_from_bytecode(compute_shader->get_bytecode("light_probes")); + ERR_FAIL_COND_V(compute_shader_light_probes.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen + RID compute_shader_light_probes_pipeline = rd->compute_pipeline_create(compute_shader_light_probes); + + RID compute_base_uniform_set = rd->uniform_set_create(base_uniforms, compute_shader_primary, 0); + +#define FREE_COMPUTE_RESOURCES \ + rd->free(compute_shader_unocclude); \ + rd->free(compute_shader_primary); \ + rd->free(compute_shader_secondary); \ + rd->free(compute_shader_dilate); \ + rd->free(compute_shader_light_probes); + + PushConstant push_constant; + { + //set defaults + push_constant.atlas_size[0] = atlas_size.width; + push_constant.atlas_size[1] = atlas_size.height; + push_constant.world_size[0] = bounds.size.x; + push_constant.world_size[1] = bounds.size.y; + push_constant.world_size[2] = bounds.size.z; + push_constant.to_cell_offset[0] = bounds.position.x; + push_constant.to_cell_offset[1] = bounds.position.y; + push_constant.to_cell_offset[2] = bounds.position.z; + push_constant.bias = p_bias; + push_constant.to_cell_size[0] = (1.0 / bounds.size.x) * float(grid_size); + push_constant.to_cell_size[1] = (1.0 / bounds.size.y) * float(grid_size); + push_constant.to_cell_size[2] = (1.0 / bounds.size.z) * float(grid_size); + push_constant.light_count = lights.size(); + push_constant.grid_size = grid_size; + push_constant.atlas_slice = 0; + push_constant.region_ofs[0] = 0; + push_constant.region_ofs[1] = 0; + push_constant.environment_xform[0] = p_environment_transform.elements[0][0]; + push_constant.environment_xform[1] = p_environment_transform.elements[1][0]; + push_constant.environment_xform[2] = p_environment_transform.elements[2][0]; + push_constant.environment_xform[3] = 0; + push_constant.environment_xform[4] = p_environment_transform.elements[0][1]; + push_constant.environment_xform[5] = p_environment_transform.elements[1][1]; + push_constant.environment_xform[6] = p_environment_transform.elements[2][1]; + push_constant.environment_xform[7] = 0; + push_constant.environment_xform[8] = p_environment_transform.elements[0][2]; + push_constant.environment_xform[9] = p_environment_transform.elements[1][2]; + push_constant.environment_xform[10] = p_environment_transform.elements[2][2]; + push_constant.environment_xform[11] = 0; + } + + Vector3i group_size((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); + rd->submit(); + rd->sync(); + + if (p_step_function) { + p_step_function(0.49, TTR("Un-occluding geometry"), p_bake_userdata, true); + } + + /* UNOCCLUDE */ + { + Vector<RD::Uniform> uniforms; + { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(position_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(unocclude_tex); //will be unused + uniforms.push_back(u); + } + } + + RID unocclude_uniform_set = rd->uniform_set_create(uniforms, compute_shader_unocclude, 1); + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_unocclude_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, unocclude_uniform_set, 1); + + for (int i = 0; i < atlas_slices; i++) { + push_constant.atlas_slice = i; + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + //no barrier, let them run all together + } + rd->compute_list_end(); //done + } + + if (p_step_function) { + p_step_function(0.5, TTR("Plot direct lighting"), p_bake_userdata, true); + } + + /* PRIMARY (direct) LIGHT PASS */ + { + Vector<RD::Uniform> uniforms; + { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(light_source_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(light_dest_tex); //will be unused + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.ids.push_back(position_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 3; + u.ids.push_back(normal_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 4; + u.ids.push_back(light_accum_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(light_primary_dynamic_tex); + uniforms.push_back(u); + } + } + + RID light_uniform_set = rd->uniform_set_create(uniforms, compute_shader_primary, 1); + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_primary_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, light_uniform_set, 1); + + for (int i = 0; i < atlas_slices; i++) { + push_constant.atlas_slice = i; + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + //no barrier, let them run all together + } + rd->compute_list_end(); //done + } + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices; i++) { + Vector<uint8_t> s = rd->texture_get_data(light_source_tex, i); + Ref<Image> img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://2_light_primary_" + itos(i) + ".png"); + } +#endif + + /* SECONDARY (indirect) LIGHT PASS(ES) */ + if (p_step_function) { + p_step_function(0.6, TTR("Integrate indirect lighting"), p_bake_userdata, true); + } + + if (p_bounces > 0) { + Vector<RD::Uniform> uniforms; + { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(light_dest_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(light_source_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.ids.push_back(position_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 3; + u.ids.push_back(normal_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 4; + u.ids.push_back(light_accum_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(unocclude_tex); //reuse unocclude tex + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 6; + u.ids.push_back(light_environment_tex); //reuse unocclude tex + uniforms.push_back(u); + } + } + + RID secondary_uniform_set[2]; + secondary_uniform_set[0] = rd->uniform_set_create(uniforms, compute_shader_secondary, 1); + uniforms.write[0].ids.write[0] = light_source_tex; + uniforms.write[1].ids.write[0] = light_dest_tex; + secondary_uniform_set[1] = rd->uniform_set_create(uniforms, compute_shader_secondary, 1); + + switch (p_quality) { + case BAKE_QUALITY_LOW: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/low_quality_ray_count"); + } break; + case BAKE_QUALITY_MEDIUM: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/medium_quality_ray_count"); + } break; + case BAKE_QUALITY_HIGH: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/high_quality_ray_count"); + } break; + case BAKE_QUALITY_ULTRA: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/ultra_quality_ray_count"); + } break; + } + + push_constant.ray_count = CLAMP(push_constant.ray_count, 16, 8192); + + int max_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/gpu_lightmapper/performance/region_size"))); + int max_rays = GLOBAL_GET("rendering/gpu_lightmapper/performance/max_rays_per_pass"); + + int x_regions = (atlas_size.width - 1) / max_region_size + 1; + int y_regions = (atlas_size.height - 1) / max_region_size + 1; + int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1; + + rd->submit(); + rd->sync(); + + for (int b = 0; b < p_bounces; b++) { + int count = 0; + if (b > 0) { + SWAP(light_source_tex, light_dest_tex); + SWAP(secondary_uniform_set[0], secondary_uniform_set[1]); + } + + for (int s = 0; s < atlas_slices; s++) { + push_constant.atlas_slice = s; + + for (int i = 0; i < x_regions; i++) { + for (int j = 0; j < y_regions; j++) { + int x = i * max_region_size; + int y = j * max_region_size; + int w = MIN((i + 1) * max_region_size, atlas_size.width) - x; + int h = MIN((j + 1) * max_region_size, atlas_size.height) - y; + + push_constant.region_ofs[0] = x; + push_constant.region_ofs[1] = y; + + group_size = Vector3i((w - 1) / 8 + 1, (h - 1) / 8 + 1, 1); + + for (int k = 0; k < ray_iterations; k++) { + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_secondary_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, secondary_uniform_set[0], 1); + + push_constant.ray_from = k * max_rays; + push_constant.ray_to = MIN((k + 1) * max_rays, int32_t(push_constant.ray_count)); + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + + rd->compute_list_end(); //done + rd->submit(); + rd->sync(); + + count++; + if (p_step_function) { + int total = (atlas_slices * x_regions * y_regions * ray_iterations); + int percent = count * 100 / total; + float p = float(count) / total * 0.1; + p_step_function(0.6 + p, vformat(TTR("Bounce %d/%d: Integrate indirect lighting %d%%"), b + 1, p_bounces, percent), p_bake_userdata, false); + } + } + } + } + } + } + } + + /* LIGHPROBES */ + + RID light_probe_buffer; + + if (probe_positions.size()) { + light_probe_buffer = rd->storage_buffer_create(sizeof(float) * 4 * 9 * probe_positions.size()); + + if (p_step_function) { + p_step_function(0.7, TTR("Baking lightprobes"), p_bake_userdata, true); + } + + Vector<RD::Uniform> uniforms; + { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(light_probe_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(light_dest_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.ids.push_back(light_primary_dynamic_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 3; + u.ids.push_back(light_environment_tex); + uniforms.push_back(u); + } + } + RID light_probe_uniform_set = rd->uniform_set_create(uniforms, compute_shader_light_probes, 1); + + switch (p_quality) { + case BAKE_QUALITY_LOW: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/low_quality_probe_ray_count"); + } break; + case BAKE_QUALITY_MEDIUM: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/medium_quality_probe_ray_count"); + } break; + case BAKE_QUALITY_HIGH: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/high_quality_probe_ray_count"); + } break; + case BAKE_QUALITY_ULTRA: { + push_constant.ray_count = GLOBAL_GET("rendering/gpu_lightmapper/quality/ultra_quality_probe_ray_count"); + } break; + } + + push_constant.atlas_size[0] = probe_positions.size(); + push_constant.ray_count = CLAMP(push_constant.ray_count, 16, 8192); + + int max_rays = GLOBAL_GET("rendering/gpu_lightmapper/performance/max_rays_per_probe_pass"); + int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1; + + for (int i = 0; i < ray_iterations; i++) { + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_light_probes_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, light_probe_uniform_set, 1); + + push_constant.ray_from = i * max_rays; + push_constant.ray_to = MIN((i + 1) * max_rays, int32_t(push_constant.ray_count)); + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, (probe_positions.size() - 1) / 64 + 1, 1, 1); + + rd->compute_list_end(); //done + rd->submit(); + rd->sync(); + + if (p_step_function) { + int percent = i * 100 / ray_iterations; + float p = float(i) / ray_iterations * 0.1; + p_step_function(0.7 + p, vformat(TTR("Integrating light probes %d%%"), percent), p_bake_userdata, false); + } + } + + push_constant.atlas_size[0] = atlas_size.x; //restore + } + +#if 0 + for (int i = 0; i < probe_positions.size(); i++) { + Ref<Image> img; + img.instance(); + img->create(6, 4, false, Image::FORMAT_RGB8); + for (int j = 0; j < 6; j++) { + Vector<uint8_t> s = rd->texture_get_data(lightprobe_tex, i * 6 + j); + Ref<Image> img2; + img2.instance(); + img2->create(2, 2, false, Image::FORMAT_RGBAF, s); + img2->convert(Image::FORMAT_RGB8); + img->blit_rect(img2, Rect2(0, 0, 2, 2), Point2((j % 3) * 2, (j / 3) * 2)); + } + img->save_png("res://3_light_probe_" + itos(i) + ".png"); + } +#endif + + /* DENOISE */ + + if (p_use_denoiser) { + if (p_step_function) { + p_step_function(0.8, TTR("Denoising"), p_bake_userdata, true); + } + + Ref<LightmapDenoiser> denoiser = LightmapDenoiser::create(); + if (denoiser.is_valid()) { + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); + Ref<Image> img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + + Ref<Image> denoised = denoiser->denoise_image(img); + if (denoised != img) { + denoised->convert(Image::FORMAT_RGBAH); + Vector<uint8_t> ds = denoised->get_data(); + denoised.unref(); //avoid copy on write + { //restore alpha + uint32_t count = s.size() / 2; //uint16s + const uint16_t *src = (const uint16_t *)s.ptr(); + uint16_t *dst = (uint16_t *)ds.ptrw(); + for (uint32_t j = 0; j < count; j += 4) { + dst[j + 3] = src[j + 3]; + } + } + rd->texture_update(light_accum_tex, i, ds, true); + } + } + } + } + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); + Ref<Image> img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://4_light_secondary_" + itos(i) + ".png"); + } +#endif + + /* DILATE LIGHTMAP */ + { + SWAP(light_accum_tex, light_accum_tex2); + + Vector<RD::Uniform> uniforms; + { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(light_accum_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(light_accum_tex2); + uniforms.push_back(u); + } + } + + RID dilate_uniform_set = rd->uniform_set_create(uniforms, compute_shader_dilate, 1); + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_dilate_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, dilate_uniform_set, 1); + push_constant.region_ofs[0] = 0; + push_constant.region_ofs[1] = 0; + group_size = Vector3i((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); //restore group size + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + push_constant.atlas_slice = i; + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + //no barrier, let them run all together + } + rd->compute_list_end(); + } + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); + Ref<Image> img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://5_dilated_" + itos(i) + ".png"); + } +#endif + + /* BLEND SEAMS */ + //shaders + Ref<RDShaderFile> blendseams_shader; + blendseams_shader.instance(); + err = blendseams_shader->parse_versions_from_text(lm_blendseams_shader_glsl); + if (err != OK) { + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + memdelete(rd); + blendseams_shader->print_errors("blendseams_shader"); + } + ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + + RID blendseams_line_raster_shader = rd->shader_create_from_bytecode(blendseams_shader->get_bytecode("lines")); + + ERR_FAIL_COND_V(blendseams_line_raster_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + + RID blendseams_triangle_raster_shader = rd->shader_create_from_bytecode(blendseams_shader->get_bytecode("triangles")); + + ERR_FAIL_COND_V(blendseams_triangle_raster_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); + +#define FREE_BLENDSEAMS_RESOURCES \ + rd->free(blendseams_line_raster_shader); \ + rd->free(blendseams_triangle_raster_shader); + + { + //pre copy + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + rd->texture_copy(light_accum_tex, light_accum_tex2, Vector3(), Vector3(), Vector3(atlas_size.width, atlas_size.height, 1), 0, 0, i, i, true); + } + + Vector<RID> framebuffers; + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + RID slice_tex = rd->texture_create_shared_from_slice(RD::TextureView(), light_accum_tex, i, 0); + Vector<RID> fb; + fb.push_back(slice_tex); + fb.push_back(raster_depth_buffer); + framebuffers.push_back(rd->framebuffer_create(fb)); + } + + Vector<RD::Uniform> uniforms; + { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + u.ids.push_back(light_accum_tex2); + uniforms.push_back(u); + } + } + + RID blendseams_raster_uniform = rd->uniform_set_create(uniforms, blendseams_line_raster_shader, 1); + + bool debug = false; + RD::PipelineColorBlendState bs = RD::PipelineColorBlendState::create_blend(1); + bs.attachments.write[0].src_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; + bs.attachments.write[0].dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + + RD::PipelineDepthStencilState ds; + ds.enable_depth_test = true; + ds.enable_depth_write = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS; //so it does not render same pixel twice, this avoids wrong blending + + RID blendseams_line_raster_pipeline = rd->render_pipeline_create(blendseams_line_raster_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_LINES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, bs, 0); + RID blendseams_triangle_raster_pipeline = rd->render_pipeline_create(blendseams_triangle_raster_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, bs, 0); + + uint32_t seam_offset = 0; + uint32_t triangle_offset = 0; + + Vector<Color> clear_colors; + clear_colors.push_back(Color(0, 0, 0, 1)); + for (int i = 0; i < atlas_slices; i++) { + int subslices = (p_bake_sh ? 4 : 1); + for (int k = 0; k < subslices; k++) { + RasterSeamsPushConstant seams_push_constant; + seams_push_constant.slice = uint32_t(i * subslices + k); + seams_push_constant.debug = debug; + + RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + + rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0); + rd->draw_list_bind_uniform_set(draw_list, blendseams_raster_uniform, 1); + + const int uv_offset_count = 9; + static const Vector3 uv_offsets[uv_offset_count] = { + Vector3(0, 0, 0.5), //using zbuffer, so go inwards-outwards + Vector3(0, 1, 0.2), + Vector3(0, -1, 0.2), + Vector3(1, 0, 0.2), + Vector3(-1, 0, 0.2), + Vector3(-1, -1, 0.1), + Vector3(1, -1, 0.1), + Vector3(1, 1, 0.1), + Vector3(-1, 1, 0.1), + }; + + /* step 1 use lines to blend the edges */ + { + seams_push_constant.base_index = seam_offset; + rd->draw_list_bind_render_pipeline(draw_list, blendseams_line_raster_pipeline); + seams_push_constant.uv_offset[0] = uv_offsets[0].x / float(atlas_size.width); + seams_push_constant.uv_offset[1] = uv_offsets[0].y / float(atlas_size.height); + seams_push_constant.blend = uv_offsets[0].z; + + rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_seam_count[i] * 4); + } + + /* step 2 use triangles to mask the interior */ + + { + seams_push_constant.base_index = triangle_offset; + rd->draw_list_bind_render_pipeline(draw_list, blendseams_triangle_raster_pipeline); + seams_push_constant.blend = 0; //do not draw them, just fill the z-buffer so its used as a mask + + rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3); + } + /* step 3 blend around the triangle */ + + rd->draw_list_bind_render_pipeline(draw_list, blendseams_line_raster_pipeline); + + for (int j = 1; j < uv_offset_count; j++) { + seams_push_constant.base_index = seam_offset; + seams_push_constant.uv_offset[0] = uv_offsets[j].x / float(atlas_size.width); + seams_push_constant.uv_offset[1] = uv_offsets[j].y / float(atlas_size.height); + seams_push_constant.blend = uv_offsets[0].z; + + rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant)); + rd->draw_list_draw(draw_list, false, 1, slice_seam_count[i] * 4); + } + rd->draw_list_end(); + } + seam_offset += slice_seam_count[i]; + triangle_offset += slice_triangle_count[i]; + } + } + +#ifdef DEBUG_TEXTURES + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); + Ref<Image> img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://5_blendseams" + itos(i) + ".png"); + } +#endif + if (p_step_function) { + p_step_function(0.9, TTR("Retrieving textures"), p_bake_userdata, true); + } + + for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { + Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); + Ref<Image> img; + img.instance(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBH); //remove alpha + bake_textures.push_back(img); + } + + if (probe_positions.size() > 0) { + probe_values.resize(probe_positions.size() * 9); + Vector<uint8_t> probe_data = rd->buffer_get_data(light_probe_buffer); + copymem(probe_values.ptrw(), probe_data.ptr(), probe_data.size()); + rd->free(light_probe_buffer); + +#ifdef DEBUG_TEXTURES + { + Ref<Image> img2; + img2.instance(); + img2->create(probe_values.size(), 1, false, Image::FORMAT_RGBAF, probe_data); + img2->save_png("res://6_lightprobes.png"); + } +#endif + } + + FREE_TEXTURES + FREE_BUFFERS + FREE_RASTER_RESOURCES + FREE_COMPUTE_RESOURCES + FREE_BLENDSEAMS_RESOURCES + + memdelete(rd); + + return BAKE_OK; +} + +int LightmapperRD::get_bake_texture_count() const { + return bake_textures.size(); +} + +Ref<Image> LightmapperRD::get_bake_texture(int p_index) const { + ERR_FAIL_INDEX_V(p_index, bake_textures.size(), Ref<Image>()); + return bake_textures[p_index]; +} + +int LightmapperRD::get_bake_mesh_count() const { + return mesh_instances.size(); +} + +Variant LightmapperRD::get_bake_mesh_userdata(int p_index) const { + ERR_FAIL_INDEX_V(p_index, mesh_instances.size(), Variant()); + return mesh_instances[p_index].data.userdata; +} + +Rect2 LightmapperRD::get_bake_mesh_uv_scale(int p_index) const { + ERR_FAIL_COND_V(bake_textures.size() == 0, Rect2()); + Rect2 uv_ofs; + Vector2 atlas_size = Vector2(bake_textures[0]->get_width(), bake_textures[0]->get_height()); + uv_ofs.position = Vector2(mesh_instances[p_index].offset) / atlas_size; + uv_ofs.size = Vector2(mesh_instances[p_index].data.albedo_on_uv2->get_width(), mesh_instances[p_index].data.albedo_on_uv2->get_height()) / atlas_size; + return uv_ofs; +} + +int LightmapperRD::get_bake_mesh_texture_slice(int p_index) const { + ERR_FAIL_INDEX_V(p_index, mesh_instances.size(), Variant()); + return mesh_instances[p_index].slice; +} + +int LightmapperRD::get_bake_probe_count() const { + return probe_positions.size(); +} + +Vector3 LightmapperRD::get_bake_probe_point(int p_probe) const { + ERR_FAIL_INDEX_V(p_probe, probe_positions.size(), Variant()); + return Vector3(probe_positions[p_probe].position[0], probe_positions[p_probe].position[1], probe_positions[p_probe].position[2]); +} + +Vector<Color> LightmapperRD::get_bake_probe_sh(int p_probe) const { + ERR_FAIL_INDEX_V(p_probe, probe_positions.size(), Vector<Color>()); + Vector<Color> ret; + ret.resize(9); + copymem(ret.ptrw(), &probe_values[p_probe * 9], sizeof(Color) * 9); + return ret; +} + +LightmapperRD::LightmapperRD() { +} diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h new file mode 100644 index 0000000000..6cb3ecbe9e --- /dev/null +++ b/modules/lightmapper_rd/lightmapper_rd.h @@ -0,0 +1,258 @@ +/*************************************************************************/ +/* lightmapper_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LIGHTMAPPER_RD_H +#define LIGHTMAPPER_RD_H + +#include "core/local_vector.h" +#include "scene/3d/lightmapper.h" +#include "scene/resources/mesh.h" +#include "servers/rendering/rendering_device.h" + +class LightmapperRD : public Lightmapper { + GDCLASS(LightmapperRD, Lightmapper) + + struct MeshInstance { + MeshData data; + int slice = 0; + Vector2i offset; + }; + + struct Light { + float position[3]; + uint32_t type = LIGHT_TYPE_DIRECTIONAL; + float direction[3]; + float energy; + float color[3]; + float size; + float range; + float attenuation; + float spot_angle; + float spot_attenuation; + uint32_t static_bake; + uint32_t pad[3]; + + bool operator<(const Light &p_light) const { + return type < p_light.type; + } + }; + + struct Vertex { + float position[3]; + float normal_z; + float uv[2]; + float normal_xy[2]; + + bool operator==(const Vertex &p_vtx) const { + return (position[0] == p_vtx.position[0]) && + (position[1] == p_vtx.position[1]) && + (position[2] == p_vtx.position[2]) && + (uv[0] == p_vtx.uv[0]) && + (uv[1] == p_vtx.uv[1]) && + (normal_xy[0] == p_vtx.normal_xy[0]) && + (normal_xy[1] == p_vtx.normal_xy[1]) && + (normal_z == p_vtx.normal_z); + } + }; + + struct Edge { + Vector3 a; + Vector3 b; + Vector3 na; + Vector3 nb; + bool operator==(const Edge &p_seam) const { + return a == p_seam.a && b == p_seam.b && na == p_seam.na && nb == p_seam.nb; + } + Edge() { + } + + Edge(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_na, const Vector3 &p_nb) { + a = p_a; + b = p_b; + na = p_na; + nb = p_nb; + } + }; + + struct Probe { + float position[4]; + }; + + Vector<Probe> probe_positions; + + struct EdgeHash { + _FORCE_INLINE_ static uint32_t hash(const Edge &p_edge) { + uint32_t h = hash_djb2_one_float(p_edge.a.x); + h = hash_djb2_one_float(p_edge.a.y, h); + h = hash_djb2_one_float(p_edge.a.z, h); + h = hash_djb2_one_float(p_edge.b.x, h); + h = hash_djb2_one_float(p_edge.b.y, h); + h = hash_djb2_one_float(p_edge.b.z, h); + return h; + } + }; + struct EdgeUV2 { + Vector2 a; + Vector2 b; + Vector2i indices; + bool operator==(const EdgeUV2 &p_uv2) const { + return a == p_uv2.a && b == p_uv2.b; + } + bool seam_found = false; + EdgeUV2(Vector2 p_a, Vector2 p_b, Vector2i p_indices) { + a = p_a; + b = p_b; + indices = p_indices; + } + EdgeUV2() {} + }; + + struct Seam { + Vector2i a; + Vector2i b; + uint32_t slice; + bool operator<(const Seam &p_seam) const { + return slice < p_seam.slice; + } + }; + + struct VertexHash { + _FORCE_INLINE_ static uint32_t hash(const Vertex &p_vtx) { + uint32_t h = hash_djb2_one_float(p_vtx.position[0]); + h = hash_djb2_one_float(p_vtx.position[1], h); + h = hash_djb2_one_float(p_vtx.position[2], h); + h = hash_djb2_one_float(p_vtx.uv[0], h); + h = hash_djb2_one_float(p_vtx.uv[1], h); + h = hash_djb2_one_float(p_vtx.normal_xy[0], h); + h = hash_djb2_one_float(p_vtx.normal_xy[1], h); + h = hash_djb2_one_float(p_vtx.normal_z, h); + return h; + } + }; + + struct Box { + float min_bounds[3]; + float pad0; + float max_bounds[3]; + float pad1; + }; + + struct Triangle { + uint32_t indices[3]; + uint32_t slice; + bool operator<(const Triangle &p_triangle) const { + return slice < p_triangle.slice; + } + }; + + Vector<MeshInstance> mesh_instances; + + Vector<Light> lights; + + struct TriangleSort { + uint32_t cell_index; + uint32_t triangle_index; + bool operator<(const TriangleSort &p_triangle_sort) const { + return cell_index < p_triangle_sort.cell_index; //sorting by triangle index in this case makes no sense + } + }; + + void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size); + + struct RasterPushConstant { + float atlas_size[2]; + float uv_offset[2]; + float to_cell_size[3]; + uint32_t base_triangle; + float to_cell_offset[3]; + float bias; + int32_t grid_size[3]; + uint32_t pad2; + }; + + struct RasterSeamsPushConstant { + uint32_t base_index; + uint32_t slice; + float uv_offset[2]; + uint32_t debug; + float blend; + uint32_t pad[2]; + }; + + struct PushConstant { + int32_t atlas_size[2]; + uint32_t ray_count; + uint32_t ray_to; + + float world_size[3]; + float bias; + + float to_cell_offset[3]; + uint32_t ray_from; + + float to_cell_size[3]; + uint32_t light_count; + + int32_t grid_size; + int32_t atlas_slice; + int32_t region_ofs[2]; + + float environment_xform[12]; + }; + + Vector<Ref<Image>> bake_textures; + Vector<Color> probe_values; + + BakeError _blit_meshes_into_atlas(int p_max_texture_size, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata); + void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &box_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &grid_texture_sdf, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata); + void _raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform); + +public: + virtual void add_mesh(const MeshData &p_mesh); + virtual void add_directional_light(bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_angular_distance); + virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size); + virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size); + virtual void add_probe(const Vector3 &p_position); + virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr); + + int get_bake_texture_count() const; + Ref<Image> get_bake_texture(int p_index) const; + int get_bake_mesh_count() const; + Variant get_bake_mesh_userdata(int p_index) const; + Rect2 get_bake_mesh_uv_scale(int p_index) const; + int get_bake_mesh_texture_slice(int p_index) const; + int get_bake_probe_count() const; + Vector3 get_bake_probe_point(int p_probe) const; + Vector<Color> get_bake_probe_sh(int p_probe) const; + + LightmapperRD(); +}; + +#endif // LIGHTMAPPER_H diff --git a/modules/lightmapper_rd/lm_blendseams.glsl b/modules/lightmapper_rd/lm_blendseams.glsl new file mode 100644 index 0000000000..e47e5fcc51 --- /dev/null +++ b/modules/lightmapper_rd/lm_blendseams.glsl @@ -0,0 +1,108 @@ +#[versions] + +lines = "#define MODE_LINES"; +triangles = "#define MODE_TRIANGLES"; + +#[vertex] + +#version 450 + +VERSION_DEFINES + +#include "lm_common_inc.glsl" + +layout(push_constant, binding = 0, std430) uniform Params { + uint base_index; + uint slice; + vec2 uv_offset; + bool debug; + float blend; + uint pad[2]; +} +params; + +layout(location = 0) out vec3 uv_interp; + +void main() { +#ifdef MODE_TRIANGLES + uint triangle_idx = params.base_index + gl_VertexIndex / 3; + uint triangle_subidx = gl_VertexIndex % 3; + + vec2 uv; + if (triangle_subidx == 0) { + uv = vertices.data[triangles.data[triangle_idx].indices.x].uv; + } else if (triangle_subidx == 1) { + uv = vertices.data[triangles.data[triangle_idx].indices.y].uv; + } else { + uv = vertices.data[triangles.data[triangle_idx].indices.z].uv; + } + + uv_interp = vec3(uv, float(params.slice)); + gl_Position = vec4((uv + params.uv_offset) * 2.0 - 1.0, 0.0001, 1.0); +#endif + +#ifdef MODE_LINES + uint seam_idx = params.base_index + gl_VertexIndex / 4; + uint seam_subidx = gl_VertexIndex % 4; + + uint src_idx; + uint dst_idx; + + if (seam_subidx == 0) { + src_idx = seams.data[seam_idx].b.x; + dst_idx = seams.data[seam_idx].a.x; + } else if (seam_subidx == 1) { + src_idx = seams.data[seam_idx].b.y; + dst_idx = seams.data[seam_idx].a.y; + } else if (seam_subidx == 2) { + src_idx = seams.data[seam_idx].a.x; + dst_idx = seams.data[seam_idx].b.x; + } else if (seam_subidx == 3) { + src_idx = seams.data[seam_idx].a.y; + dst_idx = seams.data[seam_idx].b.y; + } + + vec2 src_uv = vertices.data[src_idx].uv; + vec2 dst_uv = vertices.data[dst_idx].uv + params.uv_offset; + + uv_interp = vec3(src_uv, float(params.slice)); + gl_Position = vec4(dst_uv * 2.0 - 1.0, 0.0001, 1.0); +#endif +} + +#[fragment] + +#version 450 + +VERSION_DEFINES + +#include "lm_common_inc.glsl" + +layout(push_constant, binding = 0, std430) uniform Params { + uint base_index; + uint slice; + vec2 uv_offset; + bool debug; + float blend; + uint pad[2]; +} +params; + +layout(location = 0) in vec3 uv_interp; + +layout(location = 0) out vec4 dst_color; + +layout(set = 1, binding = 0) uniform texture2DArray src_color_tex; + +void main() { + if (params.debug) { +#ifdef MODE_TRIANGLES + dst_color = vec4(1, 0, 1, 1); +#else + dst_color = vec4(1, 1, 0, 1); +#endif + } else { + vec4 src_color = textureLod(sampler2DArray(src_color_tex, linear_sampler), uv_interp, 0.0); + dst_color = vec4(src_color.rgb, params.blend); //mix + } +} diff --git a/modules/lightmapper_rd/lm_common_inc.glsl b/modules/lightmapper_rd/lm_common_inc.glsl new file mode 100644 index 0000000000..0ff455936e --- /dev/null +++ b/modules/lightmapper_rd/lm_common_inc.glsl @@ -0,0 +1,92 @@ + +/* SET 0, static data that does not change between any call */ + +struct Vertex { + vec3 position; + float normal_z; + vec2 uv; + vec2 normal_xy; +}; + +layout(set = 0, binding = 1, std430) restrict readonly buffer Vertices { + Vertex data[]; +} +vertices; + +struct Triangle { + uvec3 indices; + uint slice; +}; + +layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles { + Triangle data[]; +} +triangles; + +struct Box { + vec3 min_bounds; + uint pad0; + vec3 max_bounds; + uint pad1; +}; + +layout(set = 0, binding = 3, std430) restrict readonly buffer Boxes { + Box data[]; +} +boxes; + +layout(set = 0, binding = 4, std430) restrict readonly buffer GridIndices { + uint data[]; +} +grid_indices; + +#define LIGHT_TYPE_DIRECTIONAL 0 +#define LIGHT_TYPE_OMNI 1 +#define LIGHT_TYPE_SPOT 2 + +struct Light { + vec3 position; + uint type; + + vec3 direction; + float energy; + + vec3 color; + float size; + + float range; + float attenuation; + float spot_angle; + float spot_attenuation; + + bool static_bake; + uint pad[3]; +}; + +layout(set = 0, binding = 5, std430) restrict readonly buffer Lights { + Light data[]; +} +lights; + +struct Seam { + uvec2 a; + uvec2 b; +}; + +layout(set = 0, binding = 6, std430) restrict readonly buffer Seams { + Seam data[]; +} +seams; + +layout(set = 0, binding = 7, std430) restrict readonly buffer Probes { + vec4 data[]; +} +probe_positions; + +layout(set = 0, binding = 8) uniform utexture3D grid; +layout(set = 0, binding = 9) uniform texture3D grid_sdf; + +layout(set = 0, binding = 10) uniform texture2DArray albedo_tex; +layout(set = 0, binding = 11) uniform texture2DArray emission_tex; + +layout(set = 0, binding = 12) uniform sampler linear_sampler; diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl new file mode 100644 index 0000000000..56976bd623 --- /dev/null +++ b/modules/lightmapper_rd/lm_compute.glsl @@ -0,0 +1,644 @@ +#[versions] + +primary = "#define MODE_DIRECT_LIGHT"; +secondary = "#define MODE_BOUNCE_LIGHT"; +dilate = "#define MODE_DILATE"; +unocclude = "#define MODE_UNOCCLUDE"; +light_probes = "#define MODE_LIGHT_PROBES"; + +#[compute] + +#version 450 + +VERSION_DEFINES + +// One 2D local group focusing in one layer at a time, though all +// in parallel (no barriers) makes more sense than a 3D local group +// as this can take more advantage of the cache for each group. + +#ifdef MODE_LIGHT_PROBES + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +#else + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#endif + +#include "lm_common_inc.glsl" + +#ifdef MODE_LIGHT_PROBES + +layout(set = 1, binding = 0, std430) restrict buffer LightProbeData { + vec4 data[]; +} +light_probes; + +layout(set = 1, binding = 1) uniform texture2DArray source_light; +layout(set = 1, binding = 2) uniform texture2DArray source_direct_light; //also need the direct light, which was omitted +layout(set = 1, binding = 3) uniform texture2D environment; +#endif + +#ifdef MODE_UNOCCLUDE + +layout(rgba32f, set = 1, binding = 0) uniform restrict image2DArray position; +layout(rgba32f, set = 1, binding = 1) uniform restrict readonly image2DArray unocclude; + +#endif + +#if defined(MODE_DIRECT_LIGHT) || defined(MODE_BOUNCE_LIGHT) + +layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2DArray dest_light; +layout(set = 1, binding = 1) uniform texture2DArray source_light; +layout(set = 1, binding = 2) uniform texture2DArray source_position; +layout(set = 1, binding = 3) uniform texture2DArray source_normal; +layout(rgba16f, set = 1, binding = 4) uniform restrict image2DArray accum_light; + +#endif + +#ifdef MODE_BOUNCE_LIGHT +layout(rgba32f, set = 1, binding = 5) uniform restrict image2DArray bounce_accum; +layout(set = 1, binding = 6) uniform texture2D environment; +#endif +#ifdef MODE_DIRECT_LIGHT +layout(rgba32f, set = 1, binding = 5) uniform restrict writeonly image2DArray primary_dynamic; +#endif + +#ifdef MODE_DILATE +layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2DArray dest_light; +layout(set = 1, binding = 1) uniform texture2DArray source_light; +#endif + +layout(push_constant, binding = 0, std430) uniform Params { + ivec2 atlas_size; // x used for light probe mode total probes + uint ray_count; + uint ray_to; + + vec3 world_size; + float bias; + + vec3 to_cell_offset; + uint ray_from; + + vec3 to_cell_size; + uint light_count; + + int grid_size; + int atlas_slice; + ivec2 region_ofs; + + mat3x4 env_transform; +} +params; + +//check it, but also return distance and barycentric coords (for uv lookup) +bool ray_hits_triangle(vec3 from, vec3 dir, float max_dist, vec3 p0, vec3 p1, vec3 p2, out float r_distance, out vec3 r_barycentric) { + const vec3 e0 = p1 - p0; + const vec3 e1 = p0 - p2; + vec3 triangleNormal = cross(e1, e0); + + const vec3 e2 = (1.0 / dot(triangleNormal, dir)) * (p0 - from); + const vec3 i = cross(dir, e2); + + r_barycentric.y = dot(i, e1); + r_barycentric.z = dot(i, e0); + r_barycentric.x = 1.0 - (r_barycentric.z + r_barycentric.y); + r_distance = dot(triangleNormal, e2); + return (r_distance > params.bias) && (r_distance < max_dist) && all(greaterThanEqual(r_barycentric, vec3(0.0))); +} + +bool trace_ray(vec3 p_from, vec3 p_to +#if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) + , + out uint r_triangle, out vec3 r_barycentric +#endif +#if defined(MODE_UNOCCLUDE) + , + out float r_distance, out vec3 r_normal +#endif +) { + /* world coords */ + + vec3 rel = p_to - p_from; + float rel_len = length(rel); + vec3 dir = normalize(rel); + vec3 inv_dir = 1.0 / dir; + + /* cell coords */ + + vec3 from_cell = (p_from - params.to_cell_offset) * params.to_cell_size; + vec3 to_cell = (p_to - params.to_cell_offset) * params.to_cell_size; + + //prepare DDA + vec3 rel_cell = to_cell - from_cell; + ivec3 icell = ivec3(from_cell); + ivec3 iendcell = ivec3(to_cell); + vec3 dir_cell = normalize(rel_cell); + vec3 delta = abs(1.0 / dir_cell); //vec3(length(rel_cell)) / rel_cell); + ivec3 step = ivec3(sign(rel_cell)); + vec3 side = (sign(rel_cell) * (vec3(icell) - from_cell) + (sign(rel_cell) * 0.5) + 0.5) * delta; + + uint iters = 0; + while (all(greaterThanEqual(icell, ivec3(0))) && all(lessThan(icell, ivec3(params.grid_size))) && iters < 1000) { + uvec2 cell_data = texelFetch(usampler3D(grid, linear_sampler), icell, 0).xy; + if (cell_data.x > 0) { //triangles here + bool hit = false; +#if defined(MODE_UNOCCLUDE) + bool hit_backface = false; +#endif + float best_distance = 1e20; + + for (uint i = 0; i < cell_data.x; i++) { + uint tidx = grid_indices.data[cell_data.y + i]; + + //Ray-Box test + vec3 t0 = (boxes.data[tidx].min_bounds - p_from) * inv_dir; + vec3 t1 = (boxes.data[tidx].max_bounds - p_from) * inv_dir; + vec3 tmin = min(t0, t1), tmax = max(t0, t1); + + if (max(tmin.x, max(tmin.y, tmin.z)) <= min(tmax.x, min(tmax.y, tmax.z))) { + continue; //ray box failed + } + + //prepare triangle vertices + vec3 vtx0 = vertices.data[triangles.data[tidx].indices.x].position; + vec3 vtx1 = vertices.data[triangles.data[tidx].indices.y].position; + vec3 vtx2 = vertices.data[triangles.data[tidx].indices.z].position; +#if defined(MODE_UNOCCLUDE) + vec3 normal = -normalize(cross((vtx0 - vtx1), (vtx0 - vtx2))); + + bool backface = dot(normal, dir) >= 0.0; +#endif + float distance; + vec3 barycentric; + + if (ray_hits_triangle(p_from, dir, rel_len, vtx0, vtx1, vtx2, distance, barycentric)) { +#ifdef MODE_DIRECT_LIGHT + return true; //any hit good +#endif + +#if defined(MODE_UNOCCLUDE) + if (!backface) { + // the case of meshes having both a front and back face in the same plane is more common than + // expected, so if this is a front-face, bias it closer to the ray origin, so it always wins over the back-face + distance = max(params.bias, distance - params.bias); + } + + hit = true; + + if (distance < best_distance) { + hit_backface = backface; + best_distance = distance; + r_distance = distance; + r_normal = normal; + } + +#endif + +#if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) + + hit = true; + if (distance < best_distance) { + best_distance = distance; + r_triangle = tidx; + r_barycentric = barycentric; + } +#endif + } + } +#if defined(MODE_UNOCCLUDE) + + if (hit) { + return hit_backface; + } +#endif +#if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) + if (hit) { + return true; + } +#endif + } + + if (icell == iendcell) { + break; + } + + bvec3 mask = lessThanEqual(side.xyz, min(side.yzx, side.zxy)); + side += vec3(mask) * delta; + icell += ivec3(vec3(mask)) * step; + + iters++; + } + + return false; +} + +const float PI = 3.14159265f; +const float GOLDEN_ANGLE = PI * (3.0 - sqrt(5.0)); + +vec3 vogel_hemisphere(uint p_index, uint p_count, float p_offset) { + float r = sqrt(float(p_index) + 0.5f) / sqrt(float(p_count)); + float theta = float(p_index) * GOLDEN_ANGLE + p_offset; + float y = cos(r * PI * 0.5); + float l = sin(r * PI * 0.5); + return vec3(l * cos(theta), l * sin(theta), y); +} + +float quick_hash(vec2 pos) { + return fract(sin(dot(pos * 19.19, vec2(49.5791, 97.413))) * 49831.189237); +} + +void main() { +#ifdef MODE_LIGHT_PROBES + int probe_index = int(gl_GlobalInvocationID.x); + if (probe_index >= params.atlas_size.x) { //too large, do nothing + return; + } + +#else + ivec2 atlas_pos = ivec2(gl_GlobalInvocationID.xy) + params.region_ofs; + if (any(greaterThanEqual(atlas_pos, params.atlas_size))) { //too large, do nothing + return; + } +#endif + +#ifdef MODE_DIRECT_LIGHT + + vec3 normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz; + if (length(normal) < 0.5) { + return; //empty texel, no process + } + vec3 position = texelFetch(sampler2DArray(source_position, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz; + + //go through all lights + //start by own light (emissive) + vec3 static_light = vec3(0.0); + vec3 dynamic_light = vec3(0.0); + +#ifdef USE_SH_LIGHTMAPS + vec4 sh_accum[4] = vec4[]( + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0)); +#endif + + for (uint i = 0; i < params.light_count; i++) { + vec3 light_pos; + float attenuation; + if (lights.data[i].type == LIGHT_TYPE_DIRECTIONAL) { + vec3 light_vec = lights.data[i].direction; + light_pos = position - light_vec * length(params.world_size); + attenuation = 1.0; + } else { + light_pos = lights.data[i].position; + float d = distance(position, light_pos); + if (d > lights.data[i].range) { + continue; + } + + d /= lights.data[i].range; + + attenuation = pow(max(1.0 - d, 0.0), lights.data[i].attenuation); + + if (lights.data[i].type == LIGHT_TYPE_SPOT) { + vec3 rel = normalize(position - light_pos); + float angle = acos(dot(rel, lights.data[i].direction)); + if (angle > lights.data[i].spot_angle) { + continue; //invisible, dont try + } + + float d = clamp(angle / lights.data[i].spot_angle, 0, 1); + attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation); + } + } + + vec3 light_dir = normalize(light_pos - position); + attenuation *= max(0.0, dot(normal, light_dir)); + + if (attenuation <= 0.0001) { + continue; //no need to do anything + } + + if (!trace_ray(position + light_dir * params.bias, light_pos)) { + vec3 light = lights.data[i].color * lights.data[i].energy * attenuation; + if (lights.data[i].static_bake) { + static_light += light; +#ifdef USE_SH_LIGHTMAPS + + float c[4] = float[]( + 0.282095, //l0 + 0.488603 * light_dir.y, //l1n1 + 0.488603 * light_dir.z, //l1n0 + 0.488603 * light_dir.x //l1p1 + ); + + for (uint j = 0; j < 4; j++) { + sh_accum[j].rgb += light * c[j] * (1.0 / 3.0); + } +#endif + + } else { + dynamic_light += light; + } + } + } + + vec3 albedo = texelFetch(sampler2DArray(albedo_tex, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).rgb; + vec3 emissive = texelFetch(sampler2DArray(emission_tex, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).rgb; + + dynamic_light *= albedo; //if it will bounce, must multiply by albedo + dynamic_light += emissive; + + //keep for lightprobes + imageStore(primary_dynamic, ivec3(atlas_pos, params.atlas_slice), vec4(dynamic_light, 1.0)); + + dynamic_light += static_light * albedo; //send for bounces + imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(dynamic_light, 1.0)); + +#ifdef USE_SH_LIGHTMAPS + //keep for adding at the end + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 0), sh_accum[0]); + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 1), sh_accum[1]); + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 2), sh_accum[2]); + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 3), sh_accum[3]); + +#else + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), vec4(static_light, 1.0)); +#endif + +#endif + +#ifdef MODE_BOUNCE_LIGHT + + vec3 normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz; + if (length(normal) < 0.5) { + return; //empty texel, no process + } + + vec3 position = texelFetch(sampler2DArray(source_position, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz; + + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, normal)); + vec3 bitangent = normalize(cross(tangent, normal)); + mat3 normal_mat = mat3(tangent, bitangent, normal); + +#ifdef USE_SH_LIGHTMAPS + vec4 sh_accum[4] = vec4[]( + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0)); +#endif + vec3 light_average = vec3(0.0); + for (uint i = params.ray_from; i < params.ray_to; i++) { + vec3 ray_dir = normal_mat * vogel_hemisphere(i, params.ray_count, quick_hash(vec2(atlas_pos))); + + uint tidx; + vec3 barycentric; + + vec3 light; + if (trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric)) { + //hit a triangle + vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv; + vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv; + vec2 uv2 = vertices.data[triangles.data[tidx].indices.z].uv; + vec3 uvw = vec3(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2, float(triangles.data[tidx].slice)); + + light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb; + } else { + //did not hit a triangle, reach out for the sky + vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir); + + vec2 st = vec2( + atan(sky_dir.x, sky_dir.z), + acos(sky_dir.y)); + + if (st.x < 0.0) + st.x += PI * 2.0; + + st /= vec2(PI * 2.0, PI); + + light = textureLod(sampler2D(environment, linear_sampler), st, 0.0).rgb; + } + + light_average += light; + +#ifdef USE_SH_LIGHTMAPS + + float c[4] = float[]( + 0.282095, //l0 + 0.488603 * ray_dir.y, //l1n1 + 0.488603 * ray_dir.z, //l1n0 + 0.488603 * ray_dir.x //l1p1 + ); + + for (uint j = 0; j < 4; j++) { + sh_accum[j].rgb += light * c[j] * (8.0 / float(params.ray_count)); + } +#endif + } + + vec3 light_total; + if (params.ray_from == 0) { + light_total = vec3(0.0); + } else { + light_total = imageLoad(bounce_accum, ivec3(atlas_pos, params.atlas_slice)).rgb; + } + + light_total += light_average; + +#ifdef USE_SH_LIGHTMAPS + + for (int i = 0; i < 4; i++) { + vec4 accum = imageLoad(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + i)); + accum.rgb += sh_accum[i].rgb; + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + i), accum); + } + +#endif + if (params.ray_to == params.ray_count) { + light_total /= float(params.ray_count); + imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0)); +#ifndef USE_SH_LIGHTMAPS + vec4 accum = imageLoad(accum_light, ivec3(atlas_pos, params.atlas_slice)); + accum.rgb += light_total; + imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), accum); +#endif + } else { + imageStore(bounce_accum, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0)); + } + +#endif + +#ifdef MODE_UNOCCLUDE + + //texel_size = 0.5; + //compute tangents + + vec4 position_alpha = imageLoad(position, ivec3(atlas_pos, params.atlas_slice)); + if (position_alpha.a < 0.5) { + return; + } + + vec3 vertex_pos = position_alpha.xyz; + vec4 normal_tsize = imageLoad(unocclude, ivec3(atlas_pos, params.atlas_slice)); + + vec3 face_normal = normal_tsize.xyz; + float texel_size = normal_tsize.w; + + vec3 v0 = abs(face_normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, face_normal)); + vec3 bitangent = normalize(cross(tangent, face_normal)); + vec3 base_pos = vertex_pos + face_normal * params.bias; //raise a bit + + vec3 rays[4] = vec3[](tangent, bitangent, -tangent, -bitangent); + float min_d = 1e20; + for (int i = 0; i < 4; i++) { + vec3 ray_to = base_pos + rays[i] * texel_size; + float d; + vec3 norm; + + if (trace_ray(base_pos, ray_to, d, norm)) { + if (d < min_d) { + vertex_pos = base_pos + rays[i] * d + norm * params.bias * 10.0; //this bias needs to be greater than the regular bias, because otherwise later, rays will go the other side when pointing back. + min_d = d; + } + } + } + + position_alpha.xyz = vertex_pos; + + imageStore(position, ivec3(atlas_pos, params.atlas_slice), position_alpha); + +#endif + +#ifdef MODE_LIGHT_PROBES + + vec3 position = probe_positions.data[probe_index].xyz; + + vec4 probe_sh_accum[9] = vec4[]( + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0)); + + for (uint i = params.ray_from; i < params.ray_to; i++) { + vec3 ray_dir = vogel_hemisphere(i, params.ray_count, quick_hash(vec2(float(probe_index), 0.0))); + if (bool(i & 1)) { + //throw to both sides, so alternate them + ray_dir.z *= -1.0; + } + + uint tidx; + vec3 barycentric; + vec3 light; + + if (trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric)) { + vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv; + vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv; + vec2 uv2 = vertices.data[triangles.data[tidx].indices.z].uv; + vec3 uvw = vec3(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2, float(triangles.data[tidx].slice)); + + light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb; + light += textureLod(sampler2DArray(source_direct_light, linear_sampler), uvw, 0.0).rgb; + } else { + //did not hit a triangle, reach out for the sky + vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir); + + vec2 st = vec2( + atan(sky_dir.x, sky_dir.z), + acos(sky_dir.y)); + + if (st.x < 0.0) + st.x += PI * 2.0; + + st /= vec2(PI * 2.0, PI); + + light = textureLod(sampler2D(environment, linear_sampler), st, 0.0).rgb; + } + + { + float c[9] = float[]( + 0.282095, //l0 + 0.488603 * ray_dir.y, //l1n1 + 0.488603 * ray_dir.z, //l1n0 + 0.488603 * ray_dir.x, //l1p1 + 1.092548 * ray_dir.x * ray_dir.y, //l2n2 + 1.092548 * ray_dir.y * ray_dir.z, //l2n1 + //0.315392 * (ray_dir.x * ray_dir.x + ray_dir.y * ray_dir.y + 2.0 * ray_dir.z * ray_dir.z), //l20 + 0.315392 * (3.0 * ray_dir.z * ray_dir.z - 1.0), //l20 + 1.092548 * ray_dir.x * ray_dir.z, //l2p1 + 0.546274 * (ray_dir.x * ray_dir.x - ray_dir.y * ray_dir.y) //l2p2 + ); + + for (uint j = 0; j < 9; j++) { + probe_sh_accum[j].rgb += light * c[j]; + } + } + } + + if (params.ray_from > 0) { + for (uint j = 0; j < 9; j++) { //accum from existing + probe_sh_accum[j] += light_probes.data[probe_index * 9 + j]; + } + } + + if (params.ray_to == params.ray_count) { + for (uint j = 0; j < 9; j++) { //accum from existing + probe_sh_accum[j] *= 4.0 / float(params.ray_count); + } + } + + for (uint j = 0; j < 9; j++) { //accum from existing + light_probes.data[probe_index * 9 + j] = probe_sh_accum[j]; + } + +#endif + +#ifdef MODE_DILATE + + vec4 c = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0); + //sides first, as they are closer + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 0), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, 1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 0), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, -1), params.atlas_slice), 0); + //endpoints second + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, -1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, -1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 1), params.atlas_slice), 0); + + //far sides third + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 0), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, 2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 0), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, -2), params.atlas_slice), 0); + + //far-mid endpoints + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, -1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, -1), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 1), params.atlas_slice), 0); + + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, -2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, -2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 2), params.atlas_slice), 0); + //far endpoints + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, -2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, -2), params.atlas_slice), 0); + c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 2), params.atlas_slice), 0); + + imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), c); + +#endif +} diff --git a/modules/lightmapper_rd/lm_raster.glsl b/modules/lightmapper_rd/lm_raster.glsl new file mode 100644 index 0000000000..6c2904192b --- /dev/null +++ b/modules/lightmapper_rd/lm_raster.glsl @@ -0,0 +1,157 @@ +#[vertex] + +#version 450 + +VERSION_DEFINES + +#include "lm_common_inc.glsl" + +layout(location = 0) out vec3 vertex_interp; +layout(location = 1) out vec3 normal_interp; +layout(location = 2) out vec2 uv_interp; +layout(location = 3) out vec3 barycentric; +layout(location = 4) flat out uvec3 vertex_indices; +layout(location = 5) flat out vec3 face_normal; + +layout(push_constant, binding = 0, std430) uniform Params { + vec2 atlas_size; + vec2 uv_offset; + vec3 to_cell_size; + uint base_triangle; + vec3 to_cell_offset; + float bias; + ivec3 grid_size; + uint pad2; +} +params; + +void main() { + uint triangle_idx = params.base_triangle + gl_VertexIndex / 3; + uint triangle_subidx = gl_VertexIndex % 3; + + vertex_indices = triangles.data[triangle_idx].indices; + + uint vertex_idx; + if (triangle_subidx == 0) { + vertex_idx = vertex_indices.x; + barycentric = vec3(1, 0, 0); + } else if (triangle_subidx == 1) { + vertex_idx = vertex_indices.y; + barycentric = vec3(0, 1, 0); + } else { + vertex_idx = vertex_indices.z; + barycentric = vec3(0, 0, 1); + } + + vertex_interp = vertices.data[vertex_idx].position; + uv_interp = vertices.data[vertex_idx].uv; + normal_interp = vec3(vertices.data[vertex_idx].normal_xy, vertices.data[vertex_idx].normal_z); + + face_normal = -normalize(cross((vertices.data[vertex_indices.x].position - vertices.data[vertex_indices.y].position), (vertices.data[vertex_indices.x].position - vertices.data[vertex_indices.z].position))); + + gl_Position = vec4((uv_interp + params.uv_offset) * 2.0 - 1.0, 0.0001, 1.0); +} + +#[fragment] + +#version 450 + +VERSION_DEFINES + +#include "lm_common_inc.glsl" + +layout(push_constant, binding = 0, std430) uniform Params { + vec2 atlas_size; + vec2 uv_offset; + vec3 to_cell_size; + uint base_triangle; + vec3 to_cell_offset; + float bias; + ivec3 grid_size; + uint pad2; +} +params; + +layout(location = 0) in vec3 vertex_interp; +layout(location = 1) in vec3 normal_interp; +layout(location = 2) in vec2 uv_interp; +layout(location = 3) in vec3 barycentric; +layout(location = 4) in flat uvec3 vertex_indices; +layout(location = 5) in flat vec3 face_normal; + +layout(location = 0) out vec4 position; +layout(location = 1) out vec4 normal; +layout(location = 2) out vec4 unocclude; + +void main() { + vec3 vertex_pos = vertex_interp; + + { + // smooth out vertex position by interpolating its projection in the 3 normal planes (normal plane is created by vertex pos and normal) + // because we don't want to interpolate inwards, normals found pointing inwards are pushed out. + vec3 pos_a = vertices.data[vertex_indices.x].position; + vec3 pos_b = vertices.data[vertex_indices.y].position; + vec3 pos_c = vertices.data[vertex_indices.z].position; + vec3 center = (pos_a + pos_b + pos_c) * 0.3333333; + vec3 norm_a = vec3(vertices.data[vertex_indices.x].normal_xy, vertices.data[vertex_indices.x].normal_z); + vec3 norm_b = vec3(vertices.data[vertex_indices.y].normal_xy, vertices.data[vertex_indices.y].normal_z); + vec3 norm_c = vec3(vertices.data[vertex_indices.z].normal_xy, vertices.data[vertex_indices.z].normal_z); + + { + vec3 dir_a = normalize(pos_a - center); + float d_a = dot(dir_a, norm_a); + if (d_a < 0) { + //pointing inwards + norm_a = normalize(norm_a - dir_a * d_a); + } + } + { + vec3 dir_b = normalize(pos_b - center); + float d_b = dot(dir_b, norm_b); + if (d_b < 0) { + //pointing inwards + norm_b = normalize(norm_b - dir_b * d_b); + } + } + { + vec3 dir_c = normalize(pos_c - center); + float d_c = dot(dir_c, norm_c); + if (d_c < 0) { + //pointing inwards + norm_c = normalize(norm_c - dir_c * d_c); + } + } + + float d_a = dot(norm_a, pos_a); + float d_b = dot(norm_b, pos_b); + float d_c = dot(norm_c, pos_c); + + vec3 proj_a = vertex_pos - norm_a * (dot(norm_a, vertex_pos) - d_a); + vec3 proj_b = vertex_pos - norm_b * (dot(norm_b, vertex_pos) - d_b); + vec3 proj_c = vertex_pos - norm_c * (dot(norm_c, vertex_pos) - d_c); + + vec3 smooth_position = proj_a * barycentric.x + proj_b * barycentric.y + proj_c * barycentric.z; + + if (dot(face_normal, smooth_position) > dot(face_normal, vertex_pos)) { //only project outwards + vertex_pos = smooth_position; + } + } + + { + // unocclusion technique based on: + // https://ndotl.wordpress.com/2018/08/29/baking-artifact-free-lightmaps/ + + /* compute texel size */ + vec3 delta_uv = max(abs(dFdx(vertex_interp)), abs(dFdy(vertex_interp))); + float texel_size = max(delta_uv.x, max(delta_uv.y, delta_uv.z)); + texel_size *= sqrt(2.0); //expand to unit box edge length (again, worst case) + + unocclude.xyz = face_normal; + unocclude.w = texel_size; + + //continued on lm_compute.glsl + } + + position = vec4(vertex_pos, 1.0); + normal = vec4(normalize(normal_interp), 1.0); +} diff --git a/modules/lightmapper_rd/register_types.cpp b/modules/lightmapper_rd/register_types.cpp new file mode 100644 index 0000000000..0e6d7590cc --- /dev/null +++ b/modules/lightmapper_rd/register_types.cpp @@ -0,0 +1,63 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "register_types.h" + +#include "core/project_settings.h" +#include "lightmapper_rd.h" +#include "scene/3d/lightmapper.h" + +#ifndef _3D_DISABLED +static Lightmapper *create_lightmapper_rd() { + return memnew(LightmapperRD); +} +#endif + +void register_lightmapper_rd_types() { + GLOBAL_DEF("rendering/gpu_lightmapper/quality/low_quality_ray_count", 16); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/medium_quality_ray_count", 64); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/high_quality_ray_count", 256); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/ultra_quality_ray_count", 1024); + GLOBAL_DEF("rendering/gpu_lightmapper/performance/max_rays_per_pass", 32); + GLOBAL_DEF("rendering/gpu_lightmapper/performance/region_size", 512); + + GLOBAL_DEF("rendering/gpu_lightmapper/quality/low_quality_probe_ray_count", 64); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/medium_quality_probe_ray_count", 256); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/high_quality_probe_ray_count", 512); + GLOBAL_DEF("rendering/gpu_lightmapper/quality/ultra_quality_probe_ray_count", 2048); + GLOBAL_DEF("rendering/gpu_lightmapper/performance/max_rays_per_probe_pass", 64); +#ifndef _3D_DISABLED + ClassDB::register_class<LightmapperRD>(); + Lightmapper::create_gpu = create_lightmapper_rd; +#endif +} + +void unregister_lightmapper_rd_types() { +} diff --git a/modules/lightmapper_rd/register_types.h b/modules/lightmapper_rd/register_types.h new file mode 100644 index 0000000000..b0e15a927f --- /dev/null +++ b/modules/lightmapper_rd/register_types.h @@ -0,0 +1,37 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LIGHTMAPPER_RD_REGISTER_TYPES_H +#define LIGHTMAPPER_RD_REGISTER_TYPES_H + +void register_lightmapper_rd_types(); +void unregister_lightmapper_rd_types(); + +#endif // XATLAS_UNWRAP_REGISTER_TYPES_H diff --git a/modules/mbedtls/SCsub b/modules/mbedtls/SCsub index 0c6c703e16..5f5d25a3ee 100755 --- a/modules/mbedtls/SCsub +++ b/modules/mbedtls/SCsub @@ -1,11 +1,11 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_mbed_tls = env_modules.Clone() -if env['builtin_mbedtls']: +if env["builtin_mbedtls"]: # Thirdparty source files thirdparty_sources = [ "aes.c", @@ -86,7 +86,7 @@ if env['builtin_mbedtls']: "x509_csr.c", "x509write_crt.c", "x509write_csr.c", - "xtea.c" + "xtea.c", ] thirdparty_dir = "#thirdparty/mbedtls/library/" diff --git a/modules/mbedtls/config.py b/modules/mbedtls/config.py index 1c8cd12a2d..d22f9454ed 100755 --- a/modules/mbedtls/config.py +++ b/modules/mbedtls/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp index c8a8240a19..1f9d8c2aa3 100644 --- a/modules/mbedtls/crypto_mbedtls.cpp +++ b/modules/mbedtls/crypto_mbedtls.cpp @@ -66,7 +66,7 @@ Error CryptoKeyMbedTLS::load(String p_path) { } memdelete(f); - int ret = mbedtls_pk_parse_key(&pkey, out.ptr(), out.size(), NULL, 0); + int ret = mbedtls_pk_parse_key(&pkey, out.ptr(), out.size(), nullptr, 0); // We MUST zeroize the memory for safety! mbedtls_platform_zeroize(out.ptrw(), out.size()); ERR_FAIL_COND_V_MSG(ret, FAILED, "Error parsing private key '" + itos(ret) + "'."); @@ -155,7 +155,6 @@ Crypto *CryptoMbedTLS::create() { } void CryptoMbedTLS::initialize_crypto() { - #ifdef DEBUG_ENABLED mbedtls_debug_set_threshold(1); #endif @@ -167,11 +166,11 @@ void CryptoMbedTLS::initialize_crypto() { } void CryptoMbedTLS::finalize_crypto() { - Crypto::_create = NULL; - Crypto::_load_default_certificates = NULL; + Crypto::_create = nullptr; + Crypto::_load_default_certificates = nullptr; if (default_certs) { memdelete(default_certs); - default_certs = NULL; + default_certs = nullptr; } X509CertificateMbedTLS::finalize(); CryptoKeyMbedTLS::finalize(); @@ -180,7 +179,7 @@ void CryptoMbedTLS::finalize_crypto() { CryptoMbedTLS::CryptoMbedTLS() { mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_entropy_init(&entropy); - int ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0); + int ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, nullptr, 0); if (ret != 0) { ERR_PRINT(" failed\n ! mbedtls_ctr_drbg_seed returned an error" + itos(ret)); } @@ -191,17 +190,17 @@ CryptoMbedTLS::~CryptoMbedTLS() { mbedtls_entropy_free(&entropy); } -X509CertificateMbedTLS *CryptoMbedTLS::default_certs = NULL; +X509CertificateMbedTLS *CryptoMbedTLS::default_certs = nullptr; X509CertificateMbedTLS *CryptoMbedTLS::get_default_certificates() { return default_certs; } void CryptoMbedTLS::load_default_certificates(String p_path) { - ERR_FAIL_COND(default_certs != NULL); + ERR_FAIL_COND(default_certs != nullptr); default_certs = memnew(X509CertificateMbedTLS); - ERR_FAIL_COND(default_certs == NULL); + ERR_FAIL_COND(default_certs == nullptr); if (p_path != "") { // Use certs defined in project settings. @@ -227,15 +226,15 @@ Ref<CryptoKey> CryptoMbedTLS::generate_rsa(int p_bytes) { Ref<CryptoKeyMbedTLS> out; out.instance(); int ret = mbedtls_pk_setup(&(out->pkey), mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); - ERR_FAIL_COND_V(ret != 0, NULL); + ERR_FAIL_COND_V(ret != 0, nullptr); ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(out->pkey), mbedtls_ctr_drbg_random, &ctr_drbg, p_bytes, 65537); - ERR_FAIL_COND_V(ret != 0, NULL); + ERR_FAIL_COND_V(ret != 0, nullptr); return out; } Ref<X509Certificate> CryptoMbedTLS::generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) { Ref<CryptoKeyMbedTLS> key = static_cast<Ref<CryptoKeyMbedTLS>>(p_key); - ERR_FAIL_COND_V_MSG(key.is_null(), NULL, "Invalid private key argument."); + ERR_FAIL_COND_V_MSG(key.is_null(), nullptr, "Invalid private key argument."); mbedtls_x509write_cert crt; mbedtls_x509write_crt_init(&crt); @@ -250,7 +249,7 @@ Ref<X509Certificate> CryptoMbedTLS::generate_self_signed_certificate(Ref<CryptoK mbedtls_mpi_init(&serial); uint8_t rand_serial[20]; mbedtls_ctr_drbg_random(&ctr_drbg, rand_serial, 20); - ERR_FAIL_COND_V(mbedtls_mpi_read_binary(&serial, rand_serial, 20), NULL); + ERR_FAIL_COND_V(mbedtls_mpi_read_binary(&serial, rand_serial, 20), nullptr); mbedtls_x509write_crt_set_serial(&crt, &serial); mbedtls_x509write_crt_set_validity(&crt, p_not_before.utf8().get_data(), p_not_after.utf8().get_data()); @@ -268,7 +267,7 @@ Ref<X509Certificate> CryptoMbedTLS::generate_self_signed_certificate(Ref<CryptoK mbedtls_mpi_free(&serial); mbedtls_x509write_crt_free(&crt); ERR_PRINT("Generated invalid certificate: " + itos(err)); - return NULL; + return nullptr; } mbedtls_mpi_free(&serial); diff --git a/modules/mbedtls/crypto_mbedtls.h b/modules/mbedtls/crypto_mbedtls.h index 6c1c0e255d..48855d082a 100644 --- a/modules/mbedtls/crypto_mbedtls.h +++ b/modules/mbedtls/crypto_mbedtls.h @@ -41,7 +41,6 @@ class CryptoMbedTLS; class SSLContextMbedTLS; class CryptoKeyMbedTLS : public CryptoKey { - private: mbedtls_pk_context pkey; int locks; @@ -49,7 +48,7 @@ private: public: static CryptoKey *create(); static void make_default() { CryptoKey::_create = create; } - static void finalize() { CryptoKey::_create = NULL; } + static void finalize() { CryptoKey::_create = nullptr; } virtual Error load(String p_path); virtual Error save(String p_path); @@ -70,7 +69,6 @@ public: }; class X509CertificateMbedTLS : public X509Certificate { - private: mbedtls_x509_crt cert; int locks; @@ -78,7 +76,7 @@ private: public: static X509Certificate *create(); static void make_default() { X509Certificate::_create = create; } - static void finalize() { X509Certificate::_create = NULL; } + static void finalize() { X509Certificate::_create = nullptr; } virtual Error load(String p_path); virtual Error load_from_memory(const uint8_t *p_buffer, int p_len); @@ -100,7 +98,6 @@ public: }; class CryptoMbedTLS : public Crypto { - private: mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; diff --git a/modules/mbedtls/dtls_server_mbedtls.cpp b/modules/mbedtls/dtls_server_mbedtls.cpp index 215b511758..d9961b026f 100644 --- a/modules/mbedtls/dtls_server_mbedtls.cpp +++ b/modules/mbedtls/dtls_server_mbedtls.cpp @@ -54,18 +54,16 @@ Ref<PacketPeerDTLS> DTLSServerMbedTLS::take_connection(Ref<PacketPeerUDP> p_udp_ } DTLSServer *DTLSServerMbedTLS::_create_func() { - return memnew(DTLSServerMbedTLS); } void DTLSServerMbedTLS::initialize() { - _create = _create_func; available = true; } void DTLSServerMbedTLS::finalize() { - _create = NULL; + _create = nullptr; available = false; } diff --git a/modules/mbedtls/dtls_server_mbedtls.h b/modules/mbedtls/dtls_server_mbedtls.h index d61ab3179e..d93553bf7f 100644 --- a/modules/mbedtls/dtls_server_mbedtls.h +++ b/modules/mbedtls/dtls_server_mbedtls.h @@ -35,7 +35,6 @@ #include "ssl_context_mbedtls.h" class DTLSServerMbedTLS : public DTLSServer { - private: static DTLSServer *_create_func(); Ref<CryptoKey> _key; diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp index bdf36ad1b1..8206d739ae 100755..100644 --- a/modules/mbedtls/packet_peer_mbed_dtls.cpp +++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp @@ -35,12 +35,13 @@ #include "core/os/file_access.h" int PacketPeerMbedDTLS::bio_send(void *ctx, const unsigned char *buf, size_t len) { - - if (buf == NULL || len <= 0) return 0; + if (buf == nullptr || len <= 0) { + return 0; + } PacketPeerMbedDTLS *sp = (PacketPeerMbedDTLS *)ctx; - ERR_FAIL_COND_V(sp == NULL, 0); + ERR_FAIL_COND_V(sp == nullptr, 0); Error err = sp->base->put_packet((const uint8_t *)buf, len); if (err == ERR_BUSY) { @@ -52,12 +53,13 @@ int PacketPeerMbedDTLS::bio_send(void *ctx, const unsigned char *buf, size_t len } int PacketPeerMbedDTLS::bio_recv(void *ctx, unsigned char *buf, size_t len) { - - if (buf == NULL || len <= 0) return 0; + if (buf == nullptr || len <= 0) { + return 0; + } PacketPeerMbedDTLS *sp = (PacketPeerMbedDTLS *)ctx; - ERR_FAIL_COND_V(sp == NULL, 0); + ERR_FAIL_COND_V(sp == nullptr, 0); int pc = sp->base->get_available_packet_count(); if (pc == 0) { @@ -77,7 +79,6 @@ int PacketPeerMbedDTLS::bio_recv(void *ctx, unsigned char *buf, size_t len) { } void PacketPeerMbedDTLS::_cleanup() { - ssl_ctx->clear(); base = Ref<PacketPeer>(); status = STATUS_DISCONNECTED; @@ -114,7 +115,6 @@ Error PacketPeerMbedDTLS::_do_handshake() { } Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_validate_certs, const String &p_for_hostname, Ref<X509Certificate> p_ca_certs) { - ERR_FAIL_COND_V(!p_base.is_valid() || !p_base->is_connected_to_host(), ERR_INVALID_PARAMETER); base = p_base; @@ -125,7 +125,7 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali ERR_FAIL_COND_V(err != OK, err); mbedtls_ssl_set_hostname(ssl_ctx->get_context(), p_for_hostname.utf8().get_data()); - mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, NULL); + mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr); mbedtls_ssl_set_timer_cb(ssl_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); status = STATUS_HANDSHAKING; @@ -139,7 +139,6 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali } Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain, Ref<CookieContextMbedTLS> p_cookies) { - Error err = ssl_ctx->init_server(MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert, p_cookies); ERR_FAIL_COND_V(err != OK, err); @@ -154,7 +153,7 @@ Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey> ERR_FAIL_V_MSG(FAILED, "Error setting DTLS client cookie"); } - mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, NULL); + mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr); mbedtls_ssl_set_timer_cb(ssl_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); status = STATUS_HANDSHAKING; @@ -168,11 +167,11 @@ Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey> } Error PacketPeerMbedDTLS::put_packet(const uint8_t *p_buffer, int p_bytes) { - ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_UNCONFIGURED); - if (p_bytes == 0) + if (p_bytes == 0) { return OK; + } int ret = mbedtls_ssl_write(ssl_ctx->get_context(), p_buffer, p_bytes); if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { @@ -187,7 +186,6 @@ Error PacketPeerMbedDTLS::put_packet(const uint8_t *p_buffer, int p_bytes) { } Error PacketPeerMbedDTLS::get_packet(const uint8_t **r_buffer, int &r_bytes) { - ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_UNCONFIGURED); r_bytes = 0; @@ -213,7 +211,6 @@ Error PacketPeerMbedDTLS::get_packet(const uint8_t **r_buffer, int &r_bytes) { } void PacketPeerMbedDTLS::poll() { - if (status == STATUS_HANDSHAKING) { _do_handshake(); return; @@ -223,7 +220,7 @@ void PacketPeerMbedDTLS::poll() { ERR_FAIL_COND(!base.is_valid()); - int ret = mbedtls_ssl_read(ssl_ctx->get_context(), NULL, 0); + int ret = mbedtls_ssl_read(ssl_ctx->get_context(), nullptr, 0); if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { @@ -238,19 +235,16 @@ void PacketPeerMbedDTLS::poll() { } int PacketPeerMbedDTLS::get_available_packet_count() const { - ERR_FAIL_COND_V(status != STATUS_CONNECTED, 0); return mbedtls_ssl_get_bytes_avail(&(ssl_ctx->ssl)) > 0 ? 1 : 0; } int PacketPeerMbedDTLS::get_max_packet_size() const { - return 488; // 512 (UDP in Godot) - 24 (DTLS header) } PacketPeerMbedDTLS::PacketPeerMbedDTLS() { - ssl_ctx.instance(); status = STATUS_DISCONNECTED; } @@ -260,38 +254,35 @@ PacketPeerMbedDTLS::~PacketPeerMbedDTLS() { } void PacketPeerMbedDTLS::disconnect_from_peer() { - - if (status != STATUS_CONNECTED && status != STATUS_HANDSHAKING) + if (status != STATUS_CONNECTED && status != STATUS_HANDSHAKING) { return; + } if (status == STATUS_CONNECTED) { int ret = 0; // Send SSL close notification, blocking, but ignore other errors. - do + do { ret = mbedtls_ssl_close_notify(ssl_ctx->get_context()); - while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); + } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); } _cleanup(); } PacketPeerMbedDTLS::Status PacketPeerMbedDTLS::get_status() const { - return status; } PacketPeerDTLS *PacketPeerMbedDTLS::_create_func() { - return memnew(PacketPeerMbedDTLS); } void PacketPeerMbedDTLS::initialize_dtls() { - _create = _create_func; available = true; } void PacketPeerMbedDTLS::finalize_dtls() { - _create = NULL; + _create = nullptr; available = false; } diff --git a/modules/mbedtls/register_types.cpp b/modules/mbedtls/register_types.cpp index d39af7fe87..84a27c29bd 100755..100644 --- a/modules/mbedtls/register_types.cpp +++ b/modules/mbedtls/register_types.cpp @@ -36,7 +36,6 @@ #include "stream_peer_mbedtls.h" void register_mbedtls_types() { - CryptoMbedTLS::initialize_crypto(); StreamPeerMbedTLS::initialize_ssl(); PacketPeerMbedDTLS::initialize_dtls(); @@ -44,7 +43,6 @@ void register_mbedtls_types() { } void unregister_mbedtls_types() { - DTLSServerMbedTLS::finalize(); PacketPeerMbedDTLS::finalize_dtls(); StreamPeerMbedTLS::finalize_ssl(); diff --git a/modules/mbedtls/register_types.h b/modules/mbedtls/register_types.h index f179d39438..90c81b1682 100755 --- a/modules/mbedtls/register_types.h +++ b/modules/mbedtls/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef MBEDTLS_REGISTER_TYPES_H +#define MBEDTLS_REGISTER_TYPES_H + void register_mbedtls_types(); void unregister_mbedtls_types(); + +#endif // MBEDTLS_REGISTER_TYPES_H diff --git a/modules/mbedtls/ssl_context_mbedtls.cpp b/modules/mbedtls/ssl_context_mbedtls.cpp index 52630bd98c..a2200e0644 100644 --- a/modules/mbedtls/ssl_context_mbedtls.cpp +++ b/modules/mbedtls/ssl_context_mbedtls.cpp @@ -33,7 +33,6 @@ static void my_debug(void *ctx, int level, const char *file, int line, const char *str) { - printf("%s:%04d: %s", file, line, str); fflush(stdout); } @@ -53,7 +52,7 @@ Error CookieContextMbedTLS::setup() { mbedtls_ssl_cookie_init(&cookie_ctx); inited = true; - int ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0); + int ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, nullptr, 0); if (ret != 0) { clear(); // Never leave unusable resources around. ERR_FAIL_V_MSG(FAILED, "mbedtls_ctr_drbg_seed returned an error " + itos(ret)); @@ -68,8 +67,9 @@ Error CookieContextMbedTLS::setup() { } void CookieContextMbedTLS::clear() { - if (!inited) + if (!inited) { return; + } mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); mbedtls_ssl_cookie_free(&cookie_ctx); @@ -94,7 +94,7 @@ Error SSLContextMbedTLS::_setup(int p_endpoint, int p_transport, int p_authmode) mbedtls_entropy_init(&entropy); inited = true; - int ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0); + int ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, nullptr, 0); if (ret != 0) { clear(); // Never leave unusable resources around. ERR_FAIL_V_MSG(FAILED, "mbedtls_ctr_drbg_seed returned an error " + itos(ret)); @@ -121,10 +121,12 @@ Error SSLContextMbedTLS::init_server(int p_transport, int p_authmode, Ref<Crypto // Locking key and certificate(s) pkey = p_pkey; certs = p_cert; - if (pkey.is_valid()) + if (pkey.is_valid()) { pkey->lock(); - if (certs.is_valid()) + } + if (certs.is_valid()) { certs->lock(); + } // Adding key and certificate int ret = mbedtls_ssl_conf_own_cert(&conf, &(certs->cert), &(pkey->pkey)); @@ -134,7 +136,7 @@ Error SSLContextMbedTLS::init_server(int p_transport, int p_authmode, Ref<Crypto } // Adding CA chain if available. if (certs->cert.next) { - mbedtls_ssl_conf_ca_chain(&conf, certs->cert.next, NULL); + mbedtls_ssl_conf_ca_chain(&conf, certs->cert.next, nullptr); } // DTLS Cookies if (p_transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { @@ -153,7 +155,7 @@ Error SSLContextMbedTLS::init_client(int p_transport, int p_authmode, Ref<X509Ce Error err = _setup(MBEDTLS_SSL_IS_CLIENT, p_transport, p_authmode); ERR_FAIL_COND_V(err != OK, err); - X509CertificateMbedTLS *cas = NULL; + X509CertificateMbedTLS *cas = nullptr; if (p_valid_cas.is_valid()) { // Locking CA certificates @@ -163,39 +165,42 @@ Error SSLContextMbedTLS::init_client(int p_transport, int p_authmode, Ref<X509Ce } else { // Fall back to default certificates (no need to lock those). cas = CryptoMbedTLS::get_default_certificates(); - if (cas == NULL) { + if (cas == nullptr) { clear(); ERR_FAIL_V_MSG(ERR_UNCONFIGURED, "SSL module failed to initialize!"); } } // Set valid CAs - mbedtls_ssl_conf_ca_chain(&conf, &(cas->cert), NULL); + mbedtls_ssl_conf_ca_chain(&conf, &(cas->cert), nullptr); mbedtls_ssl_setup(&ssl, &conf); return OK; } void SSLContextMbedTLS::clear() { - if (!inited) + if (!inited) { return; + } mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); // Unlock and key and certificates - if (certs.is_valid()) + if (certs.is_valid()) { certs->unlock(); + } certs = Ref<X509Certificate>(); - if (pkey.is_valid()) + if (pkey.is_valid()) { pkey->unlock(); + } pkey = Ref<CryptoKeyMbedTLS>(); cookies = Ref<CookieContextMbedTLS>(); inited = false; } mbedtls_ssl_context *SSLContextMbedTLS::get_context() { - ERR_FAIL_COND_V(!inited, NULL); + ERR_FAIL_COND_V(!inited, nullptr); return &ssl; } diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/ssl_context_mbedtls.h index d3e1f87a8e..baaeb6eb85 100644 --- a/modules/mbedtls/ssl_context_mbedtls.h +++ b/modules/mbedtls/ssl_context_mbedtls.h @@ -47,7 +47,6 @@ class SSLContextMbedTLS; class CookieContextMbedTLS : public Reference { - friend class SSLContextMbedTLS; protected: @@ -65,7 +64,6 @@ public: }; class SSLContextMbedTLS : public Reference { - protected: bool inited; diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp index 03c5922267..e9a610b7ee 100755..100644 --- a/modules/mbedtls/stream_peer_mbedtls.cpp +++ b/modules/mbedtls/stream_peer_mbedtls.cpp @@ -34,12 +34,13 @@ #include "core/os/file_access.h" int StreamPeerMbedTLS::bio_send(void *ctx, const unsigned char *buf, size_t len) { - - if (buf == NULL || len <= 0) return 0; + if (buf == nullptr || len <= 0) { + return 0; + } StreamPeerMbedTLS *sp = (StreamPeerMbedTLS *)ctx; - ERR_FAIL_COND_V(sp == NULL, 0); + ERR_FAIL_COND_V(sp == nullptr, 0); int sent; Error err = sp->base->put_partial_data((const uint8_t *)buf, len, sent); @@ -53,12 +54,13 @@ int StreamPeerMbedTLS::bio_send(void *ctx, const unsigned char *buf, size_t len) } int StreamPeerMbedTLS::bio_recv(void *ctx, unsigned char *buf, size_t len) { - - if (buf == NULL || len <= 0) return 0; + if (buf == nullptr || len <= 0) { + return 0; + } StreamPeerMbedTLS *sp = (StreamPeerMbedTLS *)ctx; - ERR_FAIL_COND_V(sp == NULL, 0); + ERR_FAIL_COND_V(sp == nullptr, 0); int got; Error err = sp->base->get_partial_data((uint8_t *)buf, len, got); @@ -72,7 +74,6 @@ int StreamPeerMbedTLS::bio_recv(void *ctx, unsigned char *buf, size_t len) { } void StreamPeerMbedTLS::_cleanup() { - ssl_ctx->clear(); base = Ref<StreamPeer>(); status = STATUS_DISCONNECTED; @@ -102,7 +103,6 @@ Error StreamPeerMbedTLS::_do_handshake() { } Error StreamPeerMbedTLS::connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs, const String &p_for_hostname, Ref<X509Certificate> p_ca_certs) { - ERR_FAIL_COND_V(p_base.is_null(), ERR_INVALID_PARAMETER); base = p_base; @@ -112,7 +112,7 @@ Error StreamPeerMbedTLS::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida ERR_FAIL_COND_V(err != OK, err); mbedtls_ssl_set_hostname(ssl_ctx->get_context(), p_for_hostname.utf8().get_data()); - mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, NULL); + mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr); status = STATUS_HANDSHAKING; @@ -125,7 +125,6 @@ Error StreamPeerMbedTLS::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida } Error StreamPeerMbedTLS::accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain) { - ERR_FAIL_COND_V(p_base.is_null(), ERR_INVALID_PARAMETER); Error err = ssl_ctx->init_server(MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert); @@ -133,7 +132,7 @@ Error StreamPeerMbedTLS::accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_ base = p_base; - mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, NULL); + mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr); status = STATUS_HANDSHAKING; @@ -144,8 +143,8 @@ Error StreamPeerMbedTLS::accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_ status = STATUS_CONNECTED; return OK; } -Error StreamPeerMbedTLS::put_data(const uint8_t *p_data, int p_bytes) { +Error StreamPeerMbedTLS::put_data(const uint8_t *p_data, int p_bytes) { ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_UNCONFIGURED); Error err; @@ -166,13 +165,13 @@ Error StreamPeerMbedTLS::put_data(const uint8_t *p_data, int p_bytes) { } Error StreamPeerMbedTLS::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) { - ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_UNCONFIGURED); r_sent = 0; - if (p_bytes == 0) + if (p_bytes == 0) { return OK; + } int ret = mbedtls_ssl_write(ssl_ctx->get_context(), p_data, p_bytes); if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { @@ -193,14 +192,12 @@ Error StreamPeerMbedTLS::put_partial_data(const uint8_t *p_data, int p_bytes, in } Error StreamPeerMbedTLS::get_data(uint8_t *p_buffer, int p_bytes) { - ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_UNCONFIGURED); Error err; int got = 0; while (p_bytes > 0) { - err = get_partial_data(p_buffer, p_bytes, got); if (err != OK) { @@ -215,7 +212,6 @@ Error StreamPeerMbedTLS::get_data(uint8_t *p_buffer, int p_bytes) { } Error StreamPeerMbedTLS::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) { - ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_UNCONFIGURED); r_received = 0; @@ -238,7 +234,6 @@ Error StreamPeerMbedTLS::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r } void StreamPeerMbedTLS::poll() { - ERR_FAIL_COND(status != STATUS_CONNECTED && status != STATUS_HANDSHAKING); ERR_FAIL_COND(!base.is_valid()); @@ -272,13 +267,12 @@ void StreamPeerMbedTLS::poll() { } int StreamPeerMbedTLS::get_available_bytes() const { - ERR_FAIL_COND_V(status != STATUS_CONNECTED, 0); return mbedtls_ssl_get_bytes_avail(&(ssl_ctx->ssl)); } -StreamPeerMbedTLS::StreamPeerMbedTLS() { +StreamPeerMbedTLS::StreamPeerMbedTLS() { ssl_ctx.instance(); status = STATUS_DISCONNECTED; } @@ -288,9 +282,9 @@ StreamPeerMbedTLS::~StreamPeerMbedTLS() { } void StreamPeerMbedTLS::disconnect_from_stream() { - - if (status != STATUS_CONNECTED && status != STATUS_HANDSHAKING) + if (status != STATUS_CONNECTED && status != STATUS_HANDSHAKING) { return; + } Ref<StreamPeerTCP> tcp = base; if (tcp.is_valid() && tcp->get_status() == StreamPeerTCP::STATUS_CONNECTED) { @@ -302,23 +296,19 @@ void StreamPeerMbedTLS::disconnect_from_stream() { } StreamPeerMbedTLS::Status StreamPeerMbedTLS::get_status() const { - return status; } StreamPeerSSL *StreamPeerMbedTLS::_create_func() { - return memnew(StreamPeerMbedTLS); } void StreamPeerMbedTLS::initialize_ssl() { - _create = _create_func; available = true; } void StreamPeerMbedTLS::finalize_ssl() { - available = false; - _create = NULL; + _create = nullptr; } diff --git a/modules/mobile_vr/SCsub b/modules/mobile_vr/SCsub index 4bd184f025..e6c43228b4 100644 --- a/modules/mobile_vr/SCsub +++ b/modules/mobile_vr/SCsub @@ -1,8 +1,8 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_mobile_vr = env_modules.Clone() -env_mobile_vr.add_source_files(env.modules_sources, '*.cpp') +env_mobile_vr.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py index e85fa631dd..ee401c1a2a 100644 --- a/modules/mobile_vr/config.py +++ b/modules/mobile_vr/config.py @@ -1,13 +1,16 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "MobileVRInterface", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml index 7552abe61d..120535bd41 100644 --- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml +++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MobileVRInterface" inherits="ARVRInterface" version="4.0"> +<class name="MobileVRInterface" inherits="XRInterface" version="4.0"> <brief_description> Generic mobile VR implementation. </brief_description> @@ -8,9 +8,9 @@ Note that even though there is no positional tracking, the camera will assume the headset is at a height of 1.85 meters. You can change this by setting [member eye_height]. You can initialise this interface as follows: [codeblock] - var interface = ARVRServer.find_interface("Native mobile") + var interface = XRServer.find_interface("Native mobile") if interface and interface.initialize(): - get_viewport().arvr = true + get_viewport().xr = true [/codeblock] </description> <tutorials> @@ -25,7 +25,7 @@ The width of the display in centimeters. </member> <member name="eye_height" type="float" setter="set_eye_height" getter="get_eye_height" default="1.85"> - The height at which the camera is placed in relation to the ground (i.e. [ARVROrigin] node). + The height at which the camera is placed in relation to the ground (i.e. [XROrigin3D] node). </member> <member name="iod" type="float" setter="set_iod" getter="get_iod" default="6.0"> The interocular distance, also known as the interpupillary distance. The distance between the pupils of the left and right eye. diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index 2f1d95cd42..a2fb443ef0 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -29,16 +29,18 @@ /*************************************************************************/ #include "mobile_vr_interface.h" -#include "core/os/input.h" + +#include "core/input/input.h" #include "core/os/os.h" -#include "servers/visual/visual_server_globals.h" +#include "servers/display_server.h" +#include "servers/rendering/rendering_server_globals.h" StringName MobileVRInterface::get_name() const { return "Native mobile"; }; int MobileVRInterface::get_capabilities() const { - return ARVRInterface::ARVR_STEREO; + return XRInterface::XR_STEREO; }; Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) { @@ -59,13 +61,25 @@ Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) { }; // adjust our min and max - if (mag_raw.x > mag_next_max.x) mag_next_max.x = mag_raw.x; - if (mag_raw.y > mag_next_max.y) mag_next_max.y = mag_raw.y; - if (mag_raw.z > mag_next_max.z) mag_next_max.z = mag_raw.z; + if (mag_raw.x > mag_next_max.x) { + mag_next_max.x = mag_raw.x; + } + if (mag_raw.y > mag_next_max.y) { + mag_next_max.y = mag_raw.y; + } + if (mag_raw.z > mag_next_max.z) { + mag_next_max.z = mag_raw.z; + } - if (mag_raw.x < mag_next_min.x) mag_next_min.x = mag_raw.x; - if (mag_raw.y < mag_next_min.y) mag_next_min.y = mag_raw.y; - if (mag_raw.z < mag_next_min.z) mag_next_min.z = mag_raw.z; + if (mag_raw.x < mag_next_min.x) { + mag_next_min.x = mag_raw.x; + } + if (mag_raw.y < mag_next_min.y) { + mag_next_min.y = mag_raw.y; + } + if (mag_raw.z < mag_next_min.z) { + mag_next_min.z = mag_raw.z; + } // scale our x, y and z if (!(mag_current_max.x - mag_current_min.x)) { @@ -164,7 +178,7 @@ void MobileVRInterface::set_position_from_sensors() { rotate.rotate(orientation.get_axis(2), gyro.z * delta_time); orientation = rotate * orientation; - tracking_state = ARVRInterface::ARVR_NORMAL_TRACKING; + tracking_state = XRInterface::XR_NORMAL_TRACKING; }; ///@TODO improve this, the magnetometer is very fidgity sometimes flipping the axis for no apparent reason (probably a bug on my part) @@ -176,7 +190,7 @@ void MobileVRInterface::set_position_from_sensors() { transform_quat = transform_quat.slerp(acc_mag_quat, 0.1); orientation = Basis(transform_quat); - tracking_state = ARVRInterface::ARVR_NORMAL_TRACKING; + tracking_state = XRInterface::XR_NORMAL_TRACKING; } else if (has_grav) { // use gravity vector to make sure down is down... // transform gravity into our world space @@ -296,8 +310,8 @@ bool MobileVRInterface::is_initialized() const { }; bool MobileVRInterface::initialize() { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, false); + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, false); if (!initialized) { // reset our sensor data and orientation @@ -313,7 +327,7 @@ bool MobileVRInterface::initialize() { orientation = Basis(); // make this our primary interface - arvr_server->set_primary_interface(this); + xr_server->set_primary_interface(this); last_ticks = OS::get_singleton()->get_ticks_usec(); @@ -325,10 +339,10 @@ bool MobileVRInterface::initialize() { void MobileVRInterface::uninitialize() { if (initialized) { - ARVRServer *arvr_server = ARVRServer::get_singleton(); - if (arvr_server != NULL) { + XRServer *xr_server = XRServer::get_singleton(); + if (xr_server != nullptr) { // no longer our primary interface - arvr_server->clear_primary_interface_if(this); + xr_server->clear_primary_interface_if(this); } initialized = false; @@ -339,7 +353,7 @@ Size2 MobileVRInterface::get_render_targetsize() { _THREAD_SAFE_METHOD_ // we use half our window size - Size2 target_size = OS::get_singleton()->get_window_size(); + Size2 target_size = DisplayServer::get_singleton()->window_get_size(); target_size.x *= 0.5 * oversample; target_size.y *= oversample; @@ -347,22 +361,22 @@ Size2 MobileVRInterface::get_render_targetsize() { return target_size; }; -Transform MobileVRInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) { +Transform MobileVRInterface::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) { _THREAD_SAFE_METHOD_ Transform transform_for_eye; - ARVRServer *arvr_server = ARVRServer::get_singleton(); - ERR_FAIL_NULL_V(arvr_server, transform_for_eye); + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, transform_for_eye); if (initialized) { - float world_scale = arvr_server->get_world_scale(); + float world_scale = xr_server->get_world_scale(); // we don't need to check for the existence of our HMD, doesn't effect our values... // note * 0.01 to convert cm to m and * 0.5 as we're moving half in each direction... - if (p_eye == ARVRInterface::EYE_LEFT) { + if (p_eye == XRInterface::EYE_LEFT) { transform_for_eye.origin.x = -(intraocular_dist * 0.01 * 0.5 * world_scale); - } else if (p_eye == ARVRInterface::EYE_RIGHT) { + } else if (p_eye == XRInterface::EYE_RIGHT) { transform_for_eye.origin.x = intraocular_dist * 0.01 * 0.5 * world_scale; } else { // for mono we don't reposition, we want our center position. @@ -373,7 +387,7 @@ Transform MobileVRInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, co hmd_transform.basis = orientation; hmd_transform.origin = Vector3(0.0, eye_height * world_scale, 0.0); - transform_for_eye = p_cam_transform * (arvr_server->get_reference_frame()) * hmd_transform * transform_for_eye; + transform_for_eye = p_cam_transform * (xr_server->get_reference_frame()) * hmd_transform * transform_for_eye; } else { // huh? well just return what we got.... transform_for_eye = p_cam_transform; @@ -382,12 +396,12 @@ Transform MobileVRInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, co return transform_for_eye; }; -CameraMatrix MobileVRInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { +CameraMatrix MobileVRInterface::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { _THREAD_SAFE_METHOD_ CameraMatrix eye; - if (p_eye == ARVRInterface::EYE_MONO) { + if (p_eye == XRInterface::EYE_MONO) { ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real cameras properties // which probably means implementing a specific class for iOS and Android. For now this is purely here as an example. // Note also that if you use a normal viewport with AR/VR turned off you can still use the tracker output of this interface @@ -395,13 +409,13 @@ CameraMatrix MobileVRInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye // This will make more sense when we implement ARkit on iOS (probably a separate interface). eye.set_perspective(60.0, p_aspect, p_z_near, p_z_far, false); } else { - eye.set_for_hmd(p_eye == ARVRInterface::EYE_LEFT ? 1 : 2, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far); + eye.set_for_hmd(p_eye == XRInterface::EYE_LEFT ? 1 : 2, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far); }; return eye; }; -void MobileVRInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { +void MobileVRInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { _THREAD_SAFE_METHOD_ // We must have a valid render target @@ -416,9 +430,9 @@ void MobileVRInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_t // we output half a screen dest.size.x *= 0.5; - if (p_eye == ARVRInterface::EYE_LEFT) { + if (p_eye == XRInterface::EYE_LEFT) { eye_center.x = ((-intraocular_dist / 2.0) + (display_width / 4.0)) / (display_width / 2.0); - } else if (p_eye == ARVRInterface::EYE_RIGHT) { + } else if (p_eye == XRInterface::EYE_RIGHT) { dest.position.x = dest.size.x; eye_center.x = ((intraocular_dist / 2.0) - (display_width / 4.0)) / (display_width / 2.0); } @@ -434,12 +448,6 @@ void MobileVRInterface::process() { }; }; -void MobileVRInterface::notification(int p_what){ - _THREAD_SAFE_METHOD_ - - // nothing to do here, I guess we could pauze our sensors... -} - MobileVRInterface::MobileVRInterface() { initialized = false; diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h index c762c9b799..e986a4a3de 100644 --- a/modules/mobile_vr/mobile_vr_interface.h +++ b/modules/mobile_vr/mobile_vr_interface.h @@ -31,8 +31,8 @@ #ifndef MOBILE_VR_INTERFACE_H #define MOBILE_VR_INTERFACE_H -#include "servers/arvr/arvr_interface.h" -#include "servers/arvr/arvr_positional_tracker.h" +#include "servers/xr/xr_interface.h" +#include "servers/xr/xr_positional_tracker.h" /** @author Bastiaan Olij <mux213@gmail.com> @@ -47,8 +47,8 @@ more advanced interfaces. */ -class MobileVRInterface : public ARVRInterface { - GDCLASS(MobileVRInterface, ARVRInterface); +class MobileVRInterface : public XRInterface { + GDCLASS(MobileVRInterface, XRInterface); private: bool initialized; @@ -137,12 +137,12 @@ public: virtual Size2 get_render_targetsize(); virtual bool is_stereo(); - virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform); - 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 Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform); + virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far); + virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect); virtual void process(); - virtual void notification(int p_what); + virtual void notification(int p_what) {} MobileVRInterface(); ~MobileVRInterface(); diff --git a/modules/mobile_vr/register_types.cpp b/modules/mobile_vr/register_types.cpp index faf6c3b151..75638d47c4 100644 --- a/modules/mobile_vr/register_types.cpp +++ b/modules/mobile_vr/register_types.cpp @@ -37,7 +37,7 @@ void register_mobile_vr_types() { Ref<MobileVRInterface> mobile_vr; mobile_vr.instance(); - ARVRServer::get_singleton()->add_interface(mobile_vr); + XRServer::get_singleton()->add_interface(mobile_vr); } void unregister_mobile_vr_types() { diff --git a/modules/mobile_vr/register_types.h b/modules/mobile_vr/register_types.h index 602fae1f4e..33f608b6ed 100644 --- a/modules/mobile_vr/register_types.h +++ b/modules/mobile_vr/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef MOBILE_VR_REGISTER_TYPES_H +#define MOBILE_VR_REGISTER_TYPES_H + void register_mobile_vr_types(); void unregister_mobile_vr_types(); + +#endif // MOBILE_VR_REGISTER_TYPES_H diff --git a/modules/modules_builders.py b/modules/modules_builders.py index 0e9cba2b0b..e7be6380d1 100644 --- a/modules/modules_builders.py +++ b/modules/modules_builders.py @@ -7,10 +7,10 @@ from platform_methods import subprocess_main def generate_modules_enabled(target, source, env): - with open(target[0].path, 'w') as f: + with open(target[0].path, "w") as f: for module in env.module_list: - f.write('#define %s\n' % ("MODULE_" + module.upper() + "_ENABLED")) + f.write("#define %s\n" % ("MODULE_" + module.upper() + "_ENABLED")) -if __name__ == '__main__': +if __name__ == "__main__": subprocess_main(globals()) diff --git a/modules/mono/SCsub b/modules/mono/SCsub index 5f03fafdcf..e8f3174a0a 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -2,46 +2,56 @@ import build_scripts.mono_configure as mono_configure -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_mono = env_modules.Clone() -if env_mono['tools']: +if env_mono["tools"]: # NOTE: It is safe to generate this file here, since this is still executed serially import build_scripts.gen_cs_glue_version as gen_cs_glue_version - gen_cs_glue_version.generate_header('glue/GodotSharp', 'glue/cs_glue_version.gen.h') + + gen_cs_glue_version.generate_header("glue/GodotSharp", "glue/cs_glue_version.gen.h") # Glue sources -if env_mono['mono_glue']: - env_mono.Append(CPPDEFINES=['MONO_GLUE_ENABLED']) +if env_mono["mono_glue"]: + env_mono.Append(CPPDEFINES=["MONO_GLUE_ENABLED"]) import os.path - if not os.path.isfile('glue/mono_glue.gen.cpp'): + + if not os.path.isfile("glue/mono_glue.gen.cpp"): raise RuntimeError("Mono glue sources not found. Did you forget to run '--generate-mono-glue'?") -if env_mono['tools'] or env_mono['target'] != 'release': - env_mono.Append(CPPDEFINES=['GD_MONO_HOT_RELOAD']) +if env_mono["tools"] or env_mono["target"] != "release": + env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"]) # Configure Mono mono_configure.configure(env, env_mono) -if env_mono['tools'] and env_mono['mono_glue']: +if env_mono["tools"] and env_mono["mono_glue"] and env_mono["build_cil"]: # Build Godot API solution import build_scripts.api_solution_build as api_solution_build + api_sln_cmd = api_solution_build.build(env_mono) # Build GodotTools import build_scripts.godot_tools_build as godot_tools_build + godot_tools_build.build(env_mono, api_sln_cmd) # Add sources -env_mono.add_source_files(env.modules_sources, '*.cpp') -env_mono.add_source_files(env.modules_sources, 'glue/*.cpp') -env_mono.add_source_files(env.modules_sources, 'mono_gd/*.cpp') -env_mono.add_source_files(env.modules_sources, 'utils/*.cpp') +env_mono.add_source_files(env.modules_sources, "*.cpp") +env_mono.add_source_files(env.modules_sources, "glue/*.cpp") +env_mono.add_source_files(env.modules_sources, "mono_gd/*.cpp") +env_mono.add_source_files(env.modules_sources, "utils/*.cpp") + +env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.cpp") + +if env["platform"] in ["osx", "iphone"]: + env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.mm") + env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.m") -if env['tools']: - env_mono.add_source_files(env.modules_sources, 'editor/*.cpp') +if env["tools"]: + env_mono.add_source_files(env.modules_sources, "editor/*.cpp") diff --git a/modules/mono/build_scripts/api_solution_build.py b/modules/mono/build_scripts/api_solution_build.py index 639197c285..9abac22df6 100644 --- a/modules/mono/build_scripts/api_solution_build.py +++ b/modules/mono/build_scripts/api_solution_build.py @@ -8,21 +8,22 @@ from SCons.Script import Dir def build_api_solution(source, target, env): # source and target elements are of type SCons.Node.FS.File, hence why we convert them to str - module_dir = env['module_dir'] + module_dir = env["module_dir"] - solution_path = os.path.join(module_dir, 'glue/GodotSharp/GodotSharp.sln') + solution_path = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln") - build_config = env['solution_build_config'] + build_config = env["solution_build_config"] - extra_msbuild_args = ['/p:NoWarn=1591'] # Ignore missing documentation warnings + extra_msbuild_args = ["/p:NoWarn=1591"] # Ignore missing documentation warnings from .solution_builder import build_solution + build_solution(env, solution_path, build_config, extra_msbuild_args=extra_msbuild_args) # Copy targets - core_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, 'GodotSharp', 'bin', build_config)) - editor_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, 'GodotSharpEditor', 'bin', build_config)) + core_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, "GodotSharp", "bin", build_config)) + editor_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, "GodotSharpEditor", "bin", build_config)) dst_dir = os.path.abspath(os.path.join(str(target[0]), os.pardir)) @@ -32,6 +33,7 @@ def build_api_solution(source, target, env): def copy_target(target_path): from shutil import copy + filename = os.path.basename(target_path) src_path = os.path.join(core_src_dir, filename) @@ -45,23 +47,28 @@ def build_api_solution(source, target, env): def build(env_mono): - assert env_mono['tools'] + assert env_mono["tools"] target_filenames = [ - 'GodotSharp.dll', 'GodotSharp.pdb', 'GodotSharp.xml', - 'GodotSharpEditor.dll', 'GodotSharpEditor.pdb', 'GodotSharpEditor.xml' + "GodotSharp.dll", + "GodotSharp.pdb", + "GodotSharp.xml", + "GodotSharpEditor.dll", + "GodotSharpEditor.pdb", + "GodotSharpEditor.xml", ] depend_cmd = [] - for build_config in ['Debug', 'Release']: - output_dir = Dir('#bin').abspath - editor_api_dir = os.path.join(output_dir, 'GodotSharp', 'Api', build_config) + for build_config in ["Debug", "Release"]: + output_dir = Dir("#bin").abspath + editor_api_dir = os.path.join(output_dir, "GodotSharp", "Api", build_config) targets = [os.path.join(editor_api_dir, filename) for filename in target_filenames] - cmd = env_mono.CommandNoCache(targets, depend_cmd, build_api_solution, - module_dir=os.getcwd(), solution_build_config=build_config) + cmd = env_mono.CommandNoCache( + targets, depend_cmd, build_api_solution, module_dir=os.getcwd(), solution_build_config=build_config + ) env_mono.AlwaysBuild(cmd) # Make the Release build of the API solution depend on the Debug build. diff --git a/modules/mono/build_scripts/gen_cs_glue_version.py b/modules/mono/build_scripts/gen_cs_glue_version.py index 5d1056c2fc..98bbb4d9be 100644 --- a/modules/mono/build_scripts/gen_cs_glue_version.py +++ b/modules/mono/build_scripts/gen_cs_glue_version.py @@ -1,20 +1,20 @@ - def generate_header(solution_dir, version_header_dst): import os + latest_mtime = 0 for root, dirs, files in os.walk(solution_dir, topdown=True): - dirs[:] = [d for d in dirs if d not in ['Generated']] # Ignored generated files - files = [f for f in files if f.endswith('.cs')] + dirs[:] = [d for d in dirs if d not in ["Generated"]] # Ignored generated files + files = [f for f in files if f.endswith(".cs")] for file in files: filepath = os.path.join(root, file) mtime = os.path.getmtime(filepath) latest_mtime = mtime if mtime > latest_mtime else latest_mtime - glue_version = int(latest_mtime) # The latest modified time will do for now + glue_version = int(latest_mtime) # The latest modified time will do for now - with open(version_header_dst, 'w') as version_header: - version_header.write('/* THIS FILE IS GENERATED DO NOT EDIT */\n') - version_header.write('#ifndef CS_GLUE_VERSION_H\n') - version_header.write('#define CS_GLUE_VERSION_H\n\n') - version_header.write('#define CS_GLUE_VERSION UINT32_C(' + str(glue_version) + ')\n') - version_header.write('\n#endif // CS_GLUE_VERSION_H\n') + with open(version_header_dst, "w") as version_header: + version_header.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + version_header.write("#ifndef CS_GLUE_VERSION_H\n") + version_header.write("#define CS_GLUE_VERSION_H\n\n") + version_header.write("#define CS_GLUE_VERSION UINT32_C(" + str(glue_version) + ")\n") + version_header.write("\n#endif // CS_GLUE_VERSION_H\n") diff --git a/modules/mono/build_scripts/godot_tools_build.py b/modules/mono/build_scripts/godot_tools_build.py index 99341c631e..7391e8790d 100644 --- a/modules/mono/build_scripts/godot_tools_build.py +++ b/modules/mono/build_scripts/godot_tools_build.py @@ -8,30 +8,27 @@ from SCons.Script import Dir def build_godot_tools(source, target, env): # source and target elements are of type SCons.Node.FS.File, hence why we convert them to str - module_dir = env['module_dir'] + module_dir = env["module_dir"] - solution_path = os.path.join(module_dir, 'editor/GodotTools/GodotTools.sln') - build_config = 'Debug' if env['target'] == 'debug' else 'Release' + solution_path = os.path.join(module_dir, "editor/GodotTools/GodotTools.sln") + build_config = "Debug" if env["target"] == "debug" else "Release" - # Custom build target to make sure output is always copied to the data dir. - extra_build_args = ['/Target:Build;GodotTools:BuildAlwaysCopyToDataDir'] + from .solution_builder import build_solution - from . solution_builder import build_solution, nuget_restore - nuget_restore(env, solution_path) - build_solution(env, solution_path, build_config, extra_build_args) + build_solution(env, solution_path, build_config) # No need to copy targets. The GodotTools csproj takes care of copying them. def build(env_mono, api_sln_cmd): - assert env_mono['tools'] + assert env_mono["tools"] - output_dir = Dir('#bin').abspath - editor_tools_dir = os.path.join(output_dir, 'GodotSharp', 'Tools') + output_dir = Dir("#bin").abspath + editor_tools_dir = os.path.join(output_dir, "GodotSharp", "Tools") - target_filenames = ['GodotTools.dll'] + target_filenames = ["GodotTools.dll"] - if env_mono['target'] == 'debug': - target_filenames += ['GodotTools.pdb'] + if env_mono["target"] == "debug": + target_filenames += ["GodotTools.pdb"] targets = [os.path.join(editor_tools_dir, filename) for filename in target_filenames] diff --git a/modules/mono/build_scripts/make_android_mono_config.py b/modules/mono/build_scripts/make_android_mono_config.py index 0afd939c57..d276d7d886 100644 --- a/modules/mono/build_scripts/make_android_mono_config.py +++ b/modules/mono/build_scripts/make_android_mono_config.py @@ -1,24 +1,24 @@ - def generate_compressed_config(config_src, output_dir): import os.path - from compat import byte_to_str # Source file - with open(os.path.join(output_dir, 'android_mono_config.gen.cpp'), 'w') as cpp: - with open(config_src, 'rb') as f: + with open(os.path.join(output_dir, "android_mono_config.gen.cpp"), "w") as cpp: + with open(config_src, "rb") as f: buf = f.read() decompr_size = len(buf) import zlib + buf = zlib.compress(buf) compr_size = len(buf) - bytes_seq_str = '' + bytes_seq_str = "" for i, buf_idx in enumerate(range(compr_size)): if i > 0: - bytes_seq_str += ', ' - bytes_seq_str += byte_to_str(buf[buf_idx]) + bytes_seq_str += ", " + bytes_seq_str += str(buf[buf_idx]) - cpp.write('''/* THIS FILE IS GENERATED DO NOT EDIT */ + cpp.write( + """/* THIS FILE IS GENERATED DO NOT EDIT */ #include "android_mono_config.h" #ifdef ANDROID_ENABLED @@ -49,4 +49,6 @@ String get_godot_android_mono_config() { } #endif // ANDROID_ENABLED -''' % (compr_size, decompr_size, bytes_seq_str)) +""" + % (compr_size, decompr_size, bytes_seq_str) + ) diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 9a6198f13a..23f01b3cca 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -5,178 +5,230 @@ import subprocess from SCons.Script import Dir, Environment -if os.name == 'nt': +if os.name == "nt": from . import mono_reg_utils as monoreg android_arch_dirs = { - 'armv7': 'armeabi-v7a', - 'arm64v8': 'arm64-v8a', - 'x86': 'x86', - 'x86_64': 'x86_64' + "armv7": "armeabi-v7a", + "arm64v8": "arm64-v8a", + "x86": "x86", + "x86_64": "x86_64", } def get_android_out_dir(env): - return os.path.join(Dir('#platform/android/java/lib/libs').abspath, - 'release' if env['target'] == 'release' else 'debug', - android_arch_dirs[env['android_arch']]) - - -def find_file_in_dir(directory, files, prefix='', extension=''): - if not extension.startswith('.'): - extension = '.' + extension - for curfile in files: - if os.path.isfile(os.path.join(directory, prefix + curfile + extension)): - return curfile - return '' - - -def copy_file(src_dir, dst_dir, name): + return os.path.join( + Dir("#platform/android/java/lib/libs").abspath, + "release" if env["target"] == "release" else "debug", + android_arch_dirs[env["android_arch"]], + ) + + +def find_name_in_dir_files(directory, names, prefixes=[""], extensions=[""]): + for extension in extensions: + if extension and not extension.startswith("."): + extension = "." + extension + for prefix in prefixes: + for curname in names: + if os.path.isfile(os.path.join(directory, prefix + curname + extension)): + return curname + return "" + + +def find_file_in_dir(directory, names, prefixes=[""], extensions=[""]): + for extension in extensions: + if extension and not extension.startswith("."): + extension = "." + extension + for prefix in prefixes: + for curname in names: + filename = prefix + curname + extension + if os.path.isfile(os.path.join(directory, filename)): + return filename + return "" + + +def copy_file(src_dir, dst_dir, src_name, dst_name=""): from shutil import copy - src_path = os.path.join(Dir(src_dir).abspath, name) + src_path = os.path.join(Dir(src_dir).abspath, src_name) dst_dir = Dir(dst_dir).abspath if not os.path.isdir(dst_dir): os.makedirs(dst_dir) - copy(src_path, dst_dir) + if dst_name: + copy(src_path, os.path.join(dst_dir, dst_name)) + else: + copy(src_path, dst_dir) def is_desktop(platform): - return platform in ['windows', 'osx', 'x11', 'server', 'uwp', 'haiku'] + return platform in ["windows", "osx", "linuxbsd", "server", "uwp", "haiku"] def is_unix_like(platform): - return platform in ['osx', 'x11', 'server', 'android', 'haiku'] + return platform in ["osx", "linuxbsd", "server", "android", "haiku", "iphone"] def module_supports_tools_on(platform): - return platform not in ['android', 'javascript'] + return platform not in ["android", "javascript", "iphone"] def find_wasm_src_dir(mono_root): hint_dirs = [ - os.path.join(mono_root, 'src'), - os.path.join(mono_root, '../src'), + os.path.join(mono_root, "src"), + os.path.join(mono_root, "../src"), ] for hint_dir in hint_dirs: - if os.path.isfile(os.path.join(hint_dir, 'driver.c')): + if os.path.isfile(os.path.join(hint_dir, "driver.c")): return hint_dir - return '' + return "" def configure(env, env_mono): - bits = env['bits'] - is_android = env['platform'] == 'android' - is_javascript = env['platform'] == 'javascript' + bits = env["bits"] + is_android = env["platform"] == "android" + is_javascript = env["platform"] == "javascript" + is_ios = env["platform"] == "iphone" + is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"] - tools_enabled = env['tools'] - mono_static = env['mono_static'] - copy_mono_root = env['copy_mono_root'] + tools_enabled = env["tools"] + mono_static = env["mono_static"] + copy_mono_root = env["copy_mono_root"] - mono_prefix = env['mono_prefix'] + mono_prefix = env["mono_prefix"] - mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0'] + mono_lib_names = ["mono-2.0-sgen", "monosgen-2.0"] - is_travis = os.environ.get('TRAVIS') == 'true' + is_travis = os.environ.get("TRAVIS") == "true" if is_travis: # Travis CI may have a Mono version lower than 5.12 - env_mono.Append(CPPDEFINES=['NO_PENDING_EXCEPTIONS']) + env_mono.Append(CPPDEFINES=["NO_PENDING_EXCEPTIONS"]) - if is_android and not env['android_arch'] in android_arch_dirs: - raise RuntimeError('This module does not support the specified \'android_arch\': ' + env['android_arch']) + if is_android and not env["android_arch"] in android_arch_dirs: + raise RuntimeError("This module does not support the specified 'android_arch': " + env["android_arch"]) - if tools_enabled and not module_supports_tools_on(env['platform']): + if tools_enabled and not module_supports_tools_on(env["platform"]): # TODO: # Android: We have to add the data directory to the apk, concretely the Api and Tools folders. - raise RuntimeError('This module does not currently support building for this platform with tools enabled') + raise RuntimeError("This module does not currently support building for this platform with tools enabled") if is_android and mono_static: - # Android: When static linking and doing something that requires libmono-native, we get a dlopen error as libmono-native seems to depend on libmonosgen-2.0 - raise RuntimeError('Statically linking Mono is not currently supported on this platform') + # FIXME: When static linking and doing something that requires libmono-native, we get a dlopen error as 'libmono-native' + # seems to depend on 'libmonosgen-2.0'. Could be fixed by re-directing to '__Internal' with a dllmap or in the dlopen hook. + raise RuntimeError("Statically linking Mono is not currently supported for this platform") + + if not mono_static and (is_javascript or is_ios): + raise RuntimeError("Dynamically linking Mono is not currently supported for this platform") + + if not mono_prefix and (os.getenv("MONO32_PREFIX") or os.getenv("MONO64_PREFIX")): + print( + "WARNING: The environment variables 'MONO32_PREFIX' and 'MONO64_PREFIX' are deprecated; use the 'mono_prefix' SCons parameter instead" + ) + + # Although we don't support building with tools for any platform where we currently use static AOT, + # if these are supported in the future, we won't be using static AOT for them as that would be + # too restrictive for the editor. These builds would probably be made to only use the interpreter. + mono_aot_static = (is_ios and not is_ios_sim) and not env["tools"] - if is_javascript: - mono_static = True + # Static AOT is only supported on the root domain + mono_single_appdomain = mono_aot_static - if not mono_prefix and (os.getenv('MONO32_PREFIX') or os.getenv('MONO64_PREFIX')): - print("WARNING: The environment variables 'MONO32_PREFIX' and 'MONO64_PREFIX' are deprecated; use the 'mono_prefix' SCons parameter instead") + if mono_single_appdomain: + env_mono.Append(CPPDEFINES=["GD_MONO_SINGLE_APPDOMAIN"]) - if env['platform'] == 'windows': + if (env["tools"] or env["target"] != "release") and not mono_single_appdomain: + env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"]) + + if env["platform"] == "windows": mono_root = mono_prefix - if not mono_root and os.name == 'nt': + if not mono_root and os.name == "nt": mono_root = monoreg.find_mono_root_dir(bits) if not mono_root: - raise RuntimeError("Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter") + raise RuntimeError( + "Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter" + ) - print('Found Mono root directory: ' + mono_root) + print("Found Mono root directory: " + mono_root) - mono_lib_path = os.path.join(mono_root, 'lib') + mono_lib_path = os.path.join(mono_root, "lib") env.Append(LIBPATH=mono_lib_path) - env_mono.Prepend(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0')) + env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0")) + + lib_suffixes = [".lib"] - lib_suffix = Environment()['LIBSUFFIX'] + if not env.msvc: + # MingW supports both '.a' and '.lib' + lib_suffixes.insert(0, ".a") if mono_static: if env.msvc: - mono_static_lib_name = 'libmono-static-sgen' + mono_static_lib_name = "libmono-static-sgen" else: - mono_static_lib_name = 'libmonosgen-2.0' + mono_static_lib_name = "libmonosgen-2.0" - if not os.path.isfile(os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix)): - raise RuntimeError('Could not find static mono library in: ' + mono_lib_path) + mono_static_lib_file = find_file_in_dir(mono_lib_path, [mono_static_lib_name], extensions=lib_suffixes) + + if not mono_static_lib_file: + raise RuntimeError("Could not find static mono library in: " + mono_lib_path) if env.msvc: - env.Append(LINKFLAGS=mono_static_lib_name + lib_suffix) + env.Append(LINKFLAGS=mono_static_lib_file) - env.Append(LINKFLAGS='Mincore' + lib_suffix) - env.Append(LINKFLAGS='msvcrt' + lib_suffix) - env.Append(LINKFLAGS='LIBCMT' + lib_suffix) - env.Append(LINKFLAGS='Psapi' + lib_suffix) + env.Append(LINKFLAGS="Mincore.lib") + env.Append(LINKFLAGS="msvcrt.lib") + env.Append(LINKFLAGS="LIBCMT.lib") + env.Append(LINKFLAGS="Psapi.lib") else: - env.Append(LINKFLAGS=os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix)) + mono_static_lib_file_path = os.path.join(mono_lib_path, mono_static_lib_file) + env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_static_lib_file_path, "-Wl,-no-whole-archive"]) - env.Append(LIBS=['psapi']) - env.Append(LIBS=['version']) + env.Append(LIBS=["psapi"]) + env.Append(LIBS=["version"]) else: - mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension=lib_suffix) + mono_lib_name = find_name_in_dir_files( + mono_lib_path, mono_lib_names, prefixes=["", "lib"], extensions=lib_suffixes + ) if not mono_lib_name: - raise RuntimeError('Could not find mono library in: ' + mono_lib_path) + raise RuntimeError("Could not find mono library in: " + mono_lib_path) if env.msvc: - env.Append(LINKFLAGS=mono_lib_name + lib_suffix) + env.Append(LINKFLAGS=mono_lib_name + ".lib") else: env.Append(LIBS=[mono_lib_name]) - mono_bin_path = os.path.join(mono_root, 'bin') + mono_bin_path = os.path.join(mono_root, "bin") - mono_dll_name = find_file_in_dir(mono_bin_path, mono_lib_names, extension='.dll') + mono_dll_file = find_file_in_dir(mono_bin_path, mono_lib_names, prefixes=["", "lib"], extensions=[".dll"]) - if not mono_dll_name: - raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path) + if not mono_dll_file: + raise RuntimeError("Could not find mono shared library in: " + mono_bin_path) - copy_file(mono_bin_path, '#bin', mono_dll_name + '.dll') + copy_file(mono_bin_path, "#bin", mono_dll_file) else: - is_apple = env['platform'] in ['osx', 'iphone'] + is_apple = env["platform"] in ["osx", "iphone"] + is_macos = is_apple and not is_ios - sharedlib_ext = '.dylib' if is_apple else '.so' + sharedlib_ext = ".dylib" if is_apple else ".so" mono_root = mono_prefix - mono_lib_path = '' - mono_so_name = '' + mono_lib_path = "" + mono_so_file = "" - if not mono_root and (is_android or is_javascript): - raise RuntimeError("Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter") + if not mono_root and (is_android or is_javascript or is_ios): + raise RuntimeError( + "Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter" + ) - if not mono_root and is_apple: + if not mono_root and is_macos: # Try with some known directories under OSX - hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current', '/usr/local/var/homebrew/linked/mono'] + hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"] for hint_dir in hint_dirs: if os.path.isdir(hint_dir): mono_root = hint_dir @@ -187,126 +239,165 @@ def configure(env, env_mono): if not mono_root and mono_static: mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext) if not mono_root: - raise RuntimeError("Building with mono_static=yes, but failed to find the mono prefix with pkg-config; " + \ - "specify one manually with the 'mono_prefix' SCons parameter") + raise RuntimeError( + "Building with mono_static=yes, but failed to find the mono prefix with pkg-config; " + + "specify one manually with the 'mono_prefix' SCons parameter" + ) + + if is_ios and not is_ios_sim: + env_mono.Append(CPPDEFINES=["IOS_DEVICE"]) if mono_root: - print('Found Mono root directory: ' + mono_root) + print("Found Mono root directory: " + mono_root) - mono_lib_path = os.path.join(mono_root, 'lib') + mono_lib_path = os.path.join(mono_root, "lib") env.Append(LIBPATH=[mono_lib_path]) - env_mono.Prepend(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0')) + env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0")) - mono_lib = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension='.a') + mono_lib = find_name_in_dir_files(mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[".a"]) if not mono_lib: - raise RuntimeError('Could not find mono library in: ' + mono_lib_path) + raise RuntimeError("Could not find mono library in: " + mono_lib_path) - env_mono.Append(CPPDEFINES=['_REENTRANT']) + env_mono.Append(CPPDEFINES=["_REENTRANT"]) if mono_static: - env.Append(LINKFLAGS=['-rdynamic']) + env.Append(LINKFLAGS=["-rdynamic"]) - mono_lib_file = os.path.join(mono_lib_path, 'lib' + mono_lib + '.a') + mono_lib_file = os.path.join(mono_lib_path, "lib" + mono_lib + ".a") if is_apple: - env.Append(LINKFLAGS=['-Wl,-force_load,' + mono_lib_file]) + if is_macos: + env.Append(LINKFLAGS=["-Wl,-force_load," + mono_lib_file]) + else: + arch = env["arch"] + + def copy_mono_lib(libname_wo_ext): + copy_file( + mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.iphone.%s.a" % (libname_wo_ext, arch) + ) + + # Copy Mono libraries to the output folder. These are meant to be bundled with + # the export templates and added to the Xcode project when exporting a game. + copy_mono_lib("lib" + mono_lib) + copy_mono_lib("libmono-native") + copy_mono_lib("libmono-profiler-log") + + if not is_ios_sim: + copy_mono_lib("libmono-ee-interp") + copy_mono_lib("libmono-icall-table") + copy_mono_lib("libmono-ilgen") else: - assert is_desktop(env['platform']) or is_android or is_javascript - env.Append(LINKFLAGS=['-Wl,-whole-archive', mono_lib_file, '-Wl,-no-whole-archive']) + assert is_desktop(env["platform"]) or is_android or is_javascript + env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_lib_file, "-Wl,-no-whole-archive"]) if is_javascript: - env.Append(LIBS=['mono-icall-table', 'mono-native', 'mono-ilgen', 'mono-ee-interp']) + env.Append(LIBS=["mono-icall-table", "mono-native", "mono-ilgen", "mono-ee-interp"]) - wasm_src_dir = os.path.join(mono_root, 'src') + wasm_src_dir = os.path.join(mono_root, "src") if not os.path.isdir(wasm_src_dir): - raise RuntimeError('Could not find mono wasm src directory') + raise RuntimeError("Could not find mono wasm src directory") # Ideally this should be defined only for 'driver.c', but I can't fight scons for another 2 hours - env_mono.Append(CPPDEFINES=['CORE_BINDINGS']) - - env_mono.add_source_files(env.modules_sources, [ - os.path.join(wasm_src_dir, 'driver.c'), - os.path.join(wasm_src_dir, 'zlib-helper.c'), - os.path.join(wasm_src_dir, 'corebindings.c') - ]) - - env.Append(LINKFLAGS=[ - '--js-library', os.path.join(wasm_src_dir, 'library_mono.js'), - '--js-library', os.path.join(wasm_src_dir, 'binding_support.js'), - '--js-library', os.path.join(wasm_src_dir, 'dotnet_support.js') - ]) + env_mono.Append(CPPDEFINES=["CORE_BINDINGS"]) + + env_mono.add_source_files( + env.modules_sources, + [ + os.path.join(wasm_src_dir, "driver.c"), + os.path.join(wasm_src_dir, "zlib-helper.c"), + os.path.join(wasm_src_dir, "corebindings.c"), + ], + ) + + env.Append( + LINKFLAGS=[ + "--js-library", + os.path.join(wasm_src_dir, "library_mono.js"), + "--js-library", + os.path.join(wasm_src_dir, "binding_support.js"), + "--js-library", + os.path.join(wasm_src_dir, "dotnet_support.js"), + ] + ) else: env.Append(LIBS=[mono_lib]) - if is_apple: - env.Append(LIBS=['iconv', 'pthread']) + if is_macos: + env.Append(LIBS=["iconv", "pthread"]) elif is_android: - pass # Nothing + pass # Nothing + elif is_ios: + pass # Nothing, linking is delegated to the exported Xcode project elif is_javascript: - env.Append(LIBS=['m', 'rt', 'dl', 'pthread']) + env.Append(LIBS=["m", "rt", "dl", "pthread"]) else: - env.Append(LIBS=['m', 'rt', 'dl', 'pthread']) + env.Append(LIBS=["m", "rt", "dl", "pthread"]) if not mono_static: - mono_so_name = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension=sharedlib_ext) + mono_so_file = find_file_in_dir( + mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext] + ) - if not mono_so_name: - raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path) - - copy_file(mono_lib_path, '#bin', 'lib' + mono_so_name + sharedlib_ext) + if not mono_so_file: + raise RuntimeError("Could not find mono shared library in: " + mono_lib_path) else: assert not mono_static # TODO: Add option to force using pkg-config - print('Mono root directory not found. Using pkg-config instead') + print("Mono root directory not found. Using pkg-config instead") - env.ParseConfig('pkg-config monosgen-2 --libs') - env_mono.ParseConfig('pkg-config monosgen-2 --cflags') + env.ParseConfig("pkg-config monosgen-2 --libs") + env_mono.ParseConfig("pkg-config monosgen-2 --cflags") tmpenv = Environment() - tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH')) - tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L') + tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) + tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L") - for hint_dir in tmpenv['LIBPATH']: - name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext) - if name_found: + for hint_dir in tmpenv["LIBPATH"]: + file_found = find_file_in_dir(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext]) + if file_found: mono_lib_path = hint_dir - mono_so_name = name_found + mono_so_file = file_found break - if not mono_so_name: - raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH'])) + if not mono_so_file: + raise RuntimeError("Could not find mono shared library in: " + str(tmpenv["LIBPATH"])) if not mono_static: - libs_output_dir = get_android_out_dir(env) if is_android else '#bin' - copy_file(mono_lib_path, libs_output_dir, 'lib' + mono_so_name + sharedlib_ext) + libs_output_dir = get_android_out_dir(env) if is_android else "#bin" + copy_file(mono_lib_path, libs_output_dir, mono_so_file) if not tools_enabled: - if is_desktop(env['platform']): + if is_desktop(env["platform"]): if not mono_root: - mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip() + mono_root = ( + subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip() + ) make_template_dir(env, mono_root) elif is_android: # Compress Android Mono Config from . import make_android_mono_config + module_dir = os.getcwd() - config_file_path = os.path.join(module_dir, 'build_scripts', 'mono_android_config.xml') - make_android_mono_config.generate_compressed_config(config_file_path, 'mono_gd/') + config_file_path = os.path.join(module_dir, "build_scripts", "mono_android_config.xml") + make_android_mono_config.generate_compressed_config(config_file_path, "mono_gd/") # Copy the required shared libraries copy_mono_shared_libs(env, mono_root, None) elif is_javascript: - pass # No data directory for this platform + pass # No data directory for this platform + elif is_ios: + pass # No data directory for this platform if copy_mono_root: if not mono_root: - mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip() + mono_root = subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip() if tools_enabled: - copy_mono_root_files(env, mono_root) + copy_mono_root_files(env, mono_root) else: print("Ignoring option: 'copy_mono_root'; only available for builds with 'tools' enabled.") @@ -314,26 +405,26 @@ def configure(env, env_mono): def make_template_dir(env, mono_root): from shutil import rmtree - platform = env['platform'] - target = env['target'] + platform = env["platform"] + target = env["target"] - template_dir_name = '' + template_dir_name = "" assert is_desktop(platform) - template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target) + template_dir_name = "data.mono.%s.%s.%s" % (platform, env["bits"], target) - output_dir = Dir('#bin').abspath + output_dir = Dir("#bin").abspath template_dir = os.path.join(output_dir, template_dir_name) - template_mono_root_dir = os.path.join(template_dir, 'Mono') + template_mono_root_dir = os.path.join(template_dir, "Mono") if os.path.isdir(template_mono_root_dir): - rmtree(template_mono_root_dir) # Clean first + rmtree(template_mono_root_dir) # Clean first # Copy etc/mono/ - template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono') + template_mono_config_dir = os.path.join(template_mono_root_dir, "etc", "mono") copy_mono_etc_dir(mono_root, template_mono_config_dir, platform) # Copy the required shared libraries @@ -347,18 +438,18 @@ def copy_mono_root_files(env, mono_root): from shutil import rmtree if not mono_root: - raise RuntimeError('Mono installation directory not found') + raise RuntimeError("Mono installation directory not found") - output_dir = Dir('#bin').abspath - editor_mono_root_dir = os.path.join(output_dir, 'GodotSharp', 'Mono') + output_dir = Dir("#bin").abspath + editor_mono_root_dir = os.path.join(output_dir, "GodotSharp", "Mono") if os.path.isdir(editor_mono_root_dir): - rmtree(editor_mono_root_dir) # Clean first + rmtree(editor_mono_root_dir) # Clean first # Copy etc/mono/ - editor_mono_config_dir = os.path.join(editor_mono_root_dir, 'etc', 'mono') - copy_mono_etc_dir(mono_root, editor_mono_config_dir, env['platform']) + editor_mono_config_dir = os.path.join(editor_mono_root_dir, "etc", "mono") + copy_mono_etc_dir(mono_root, editor_mono_config_dir, env["platform"]) # Copy the required shared libraries @@ -366,20 +457,20 @@ def copy_mono_root_files(env, mono_root): # Copy framework assemblies - mono_framework_dir = os.path.join(mono_root, 'lib', 'mono', '4.5') - mono_framework_facades_dir = os.path.join(mono_framework_dir, 'Facades') + mono_framework_dir = os.path.join(mono_root, "lib", "mono", "4.5") + mono_framework_facades_dir = os.path.join(mono_framework_dir, "Facades") - editor_mono_framework_dir = os.path.join(editor_mono_root_dir, 'lib', 'mono', '4.5') - editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, 'Facades') + editor_mono_framework_dir = os.path.join(editor_mono_root_dir, "lib", "mono", "4.5") + editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, "Facades") if not os.path.isdir(editor_mono_framework_dir): os.makedirs(editor_mono_framework_dir) if not os.path.isdir(editor_mono_framework_facades_dir): os.makedirs(editor_mono_framework_facades_dir) - for assembly in glob(os.path.join(mono_framework_dir, '*.dll')): + for assembly in glob(os.path.join(mono_framework_dir, "*.dll")): copy(assembly, editor_mono_framework_dir) - for assembly in glob(os.path.join(mono_framework_facades_dir, '*.dll')): + for assembly in glob(os.path.join(mono_framework_facades_dir, "*.dll")): copy(assembly, editor_mono_framework_facades_dir) @@ -391,28 +482,28 @@ def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform): if not os.path.isdir(target_mono_config_dir): os.makedirs(target_mono_config_dir) - mono_etc_dir = os.path.join(mono_root, 'etc', 'mono') + mono_etc_dir = os.path.join(mono_root, "etc", "mono") if not os.path.isdir(mono_etc_dir): - mono_etc_dir = '' + mono_etc_dir = "" etc_hint_dirs = [] - if platform != 'windows': - etc_hint_dirs += ['/etc/mono', '/usr/local/etc/mono'] - if 'MONO_CFG_DIR' in os.environ: - etc_hint_dirs += [os.path.join(os.environ['MONO_CFG_DIR'], 'mono')] + if platform != "windows": + etc_hint_dirs += ["/etc/mono", "/usr/local/etc/mono"] + if "MONO_CFG_DIR" in os.environ: + etc_hint_dirs += [os.path.join(os.environ["MONO_CFG_DIR"], "mono")] for etc_hint_dir in etc_hint_dirs: if os.path.isdir(etc_hint_dir): mono_etc_dir = etc_hint_dir break if not mono_etc_dir: - raise RuntimeError('Mono installation etc directory not found') + raise RuntimeError("Mono installation etc directory not found") - copy_tree(os.path.join(mono_etc_dir, '2.0'), os.path.join(target_mono_config_dir, '2.0')) - copy_tree(os.path.join(mono_etc_dir, '4.0'), os.path.join(target_mono_config_dir, '4.0')) - copy_tree(os.path.join(mono_etc_dir, '4.5'), os.path.join(target_mono_config_dir, '4.5')) - if os.path.isdir(os.path.join(mono_etc_dir, 'mconfig')): - copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig')) + copy_tree(os.path.join(mono_etc_dir, "2.0"), os.path.join(target_mono_config_dir, "2.0")) + copy_tree(os.path.join(mono_etc_dir, "4.0"), os.path.join(target_mono_config_dir, "4.0")) + copy_tree(os.path.join(mono_etc_dir, "4.5"), os.path.join(target_mono_config_dir, "4.5")) + if os.path.isdir(os.path.join(mono_etc_dir, "mconfig")): + copy_tree(os.path.join(mono_etc_dir, "mconfig"), os.path.join(target_mono_config_dir, "mconfig")) - for file in glob(os.path.join(mono_etc_dir, '*')): + for file in glob(os.path.join(mono_etc_dir, "*")): if os.path.isfile(file): copy(file, target_mono_config_dir) @@ -424,48 +515,66 @@ def copy_mono_shared_libs(env, mono_root, target_mono_root_dir): if os.path.isfile(src): copy(src, dst) - platform = env['platform'] + platform = env["platform"] - if platform == 'windows': - src_mono_bin_dir = os.path.join(mono_root, 'bin') - target_mono_bin_dir = os.path.join(target_mono_root_dir, 'bin') + if platform == "windows": + src_mono_bin_dir = os.path.join(mono_root, "bin") + target_mono_bin_dir = os.path.join(target_mono_root_dir, "bin") if not os.path.isdir(target_mono_bin_dir): os.makedirs(target_mono_bin_dir) - mono_posix_helper_name = find_file_in_dir(src_mono_bin_dir, ['MonoPosixHelper', 'libMonoPosixHelper'], extension='.dll') - copy(os.path.join(src_mono_bin_dir, mono_posix_helper_name + '.dll'), os.path.join(target_mono_bin_dir, 'MonoPosixHelper.dll')) + mono_posix_helper_file = find_file_in_dir( + src_mono_bin_dir, ["MonoPosixHelper"], prefixes=["", "lib"], extensions=[".dll"] + ) + copy( + os.path.join(src_mono_bin_dir, mono_posix_helper_file), + os.path.join(target_mono_bin_dir, "MonoPosixHelper.dll"), + ) # For newer versions - btls_dll_path = os.path.join(src_mono_bin_dir, 'libmono-btls-shared.dll') + btls_dll_path = os.path.join(src_mono_bin_dir, "libmono-btls-shared.dll") if os.path.isfile(btls_dll_path): copy(btls_dll_path, target_mono_bin_dir) else: - target_mono_lib_dir = get_android_out_dir(env) if platform == 'android' else os.path.join(target_mono_root_dir, 'lib') + target_mono_lib_dir = ( + get_android_out_dir(env) if platform == "android" else os.path.join(target_mono_root_dir, "lib") + ) if not os.path.isdir(target_mono_lib_dir): os.makedirs(target_mono_lib_dir) lib_file_names = [] - if platform == 'osx': - lib_file_names = [lib_name + '.dylib' for lib_name in [ - 'libmono-btls-shared', 'libmono-native-compat', 'libMonoPosixHelper' - ]] + if platform == "osx": + lib_file_names = [ + lib_name + ".dylib" + for lib_name in ["libmono-btls-shared", "libmono-native-compat", "libMonoPosixHelper"] + ] elif is_unix_like(platform): - lib_file_names = [lib_name + '.so' for lib_name in [ - 'libmono-btls-shared', 'libmono-ee-interp', 'libmono-native', 'libMonoPosixHelper', - 'libmono-profiler-aot', 'libmono-profiler-coverage', 'libmono-profiler-log', 'libMonoSupportW' - ]] + lib_file_names = [ + lib_name + ".so" + for lib_name in [ + "libmono-btls-shared", + "libmono-ee-interp", + "libmono-native", + "libMonoPosixHelper", + "libmono-profiler-aot", + "libmono-profiler-coverage", + "libmono-profiler-log", + "libMonoSupportW", + ] + ] for lib_file_name in lib_file_names: - copy_if_exists(os.path.join(mono_root, 'lib', lib_file_name), target_mono_lib_dir) + copy_if_exists(os.path.join(mono_root, "lib", lib_file_name), target_mono_lib_dir) + def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext): tmpenv = Environment() - tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH')) - tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L') - for hint_dir in tmpenv['LIBPATH']: - name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext) - if name_found and os.path.isdir(os.path.join(hint_dir, '..', 'include', 'mono-2.0')): - return os.path.join(hint_dir, '..') - return '' + tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) + tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L") + for hint_dir in tmpenv["LIBPATH"]: + name_found = find_name_in_dir_files(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext]) + if name_found and os.path.isdir(os.path.join(hint_dir, "..", "include", "mono-2.0")): + return os.path.join(hint_dir, "..") + return "" diff --git a/modules/mono/build_scripts/mono_reg_utils.py b/modules/mono/build_scripts/mono_reg_utils.py index b2c48f0a61..3090a4759a 100644 --- a/modules/mono/build_scripts/mono_reg_utils.py +++ b/modules/mono/build_scripts/mono_reg_utils.py @@ -1,21 +1,16 @@ import os import platform -from compat import decode_utf8 - -if os.name == 'nt': +if os.name == "nt": import sys - if sys.version_info < (3,): - import _winreg as winreg - else: - import winreg + import winreg def _reg_open_key(key, subkey): try: return winreg.OpenKey(key, subkey) except (WindowsError, OSError): - if platform.architecture()[0] == '32bit': + if platform.architecture()[0] == "32bit": bitness_sam = winreg.KEY_WOW64_64KEY else: bitness_sam = winreg.KEY_WOW64_32KEY @@ -25,12 +20,12 @@ def _reg_open_key(key, subkey): def _reg_open_key_bits(key, subkey, bits): sam = winreg.KEY_READ - if platform.architecture()[0] == '32bit': - if bits == '64': + if platform.architecture()[0] == "32bit": + if bits == "64": # Force 32bit process to search in 64bit registry sam |= winreg.KEY_WOW64_64KEY else: - if bits == '32': + if bits == "32": # Force 64bit process to search in 32bit registry sam |= winreg.KEY_WOW64_32KEY @@ -40,7 +35,7 @@ def _reg_open_key_bits(key, subkey, bits): def _find_mono_in_reg(subkey, bits): try: with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey: - value = winreg.QueryValueEx(hKey, 'SdkInstallRoot')[0] + value = winreg.QueryValueEx(hKey, "SdkInstallRoot")[0] return value except (WindowsError, OSError): return None @@ -49,70 +44,70 @@ def _find_mono_in_reg(subkey, bits): def _find_mono_in_reg_old(subkey, bits): try: with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey: - default_clr = winreg.QueryValueEx(hKey, 'DefaultCLR')[0] + default_clr = winreg.QueryValueEx(hKey, "DefaultCLR")[0] if default_clr: - return _find_mono_in_reg(subkey + '\\' + default_clr, bits) + return _find_mono_in_reg(subkey + "\\" + default_clr, bits) return None except (WindowsError, EnvironmentError): return None def find_mono_root_dir(bits): - root_dir = _find_mono_in_reg(r'SOFTWARE\Mono', bits) + root_dir = _find_mono_in_reg(r"SOFTWARE\Mono", bits) if root_dir is not None: return str(root_dir) - root_dir = _find_mono_in_reg_old(r'SOFTWARE\Novell\Mono', bits) + root_dir = _find_mono_in_reg_old(r"SOFTWARE\Novell\Mono", bits) if root_dir is not None: return str(root_dir) - return '' + return "" def find_msbuild_tools_path_reg(): import subprocess - vswhere = os.getenv('PROGRAMFILES(X86)') + vswhere = os.getenv("PROGRAMFILES(X86)") if not vswhere: - vswhere = os.getenv('PROGRAMFILES') - vswhere += r'\Microsoft Visual Studio\Installer\vswhere.exe' + vswhere = os.getenv("PROGRAMFILES") + vswhere += r"\Microsoft Visual Studio\Installer\vswhere.exe" - vswhere_args = ['-latest', '-products', '*', '-requires', 'Microsoft.Component.MSBuild'] + vswhere_args = ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"] try: lines = subprocess.check_output([vswhere] + vswhere_args).splitlines() for line in lines: - parts = decode_utf8(line).split(':', 1) + parts = line.decode("utf-8").split(":", 1) - if len(parts) < 2 or parts[0] != 'installationPath': + if len(parts) < 2 or parts[0] != "installationPath": continue val = parts[1].strip() if not val: - raise ValueError('Value of `installationPath` entry is empty') + raise ValueError("Value of `installationPath` entry is empty") # Since VS2019, the directory is simply named "Current" - msbuild_dir = os.path.join(val, 'MSBuild\\Current\\Bin') + msbuild_dir = os.path.join(val, "MSBuild\\Current\\Bin") if os.path.isdir(msbuild_dir): return msbuild_dir # Directory name "15.0" is used in VS 2017 - return os.path.join(val, 'MSBuild\\15.0\\Bin') + return os.path.join(val, "MSBuild\\15.0\\Bin") - raise ValueError('Cannot find `installationPath` entry') + raise ValueError("Cannot find `installationPath` entry") except ValueError as e: - print('Error reading output from vswhere: ' + e.message) + print("Error reading output from vswhere: " + e.message) except WindowsError: - pass # Fine, vswhere not found + pass # Fine, vswhere not found except (subprocess.CalledProcessError, OSError): pass # Try to find 14.0 in the Registry try: - subkey = r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0' + subkey = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey: - value = winreg.QueryValueEx(hKey, 'MSBuildToolsPath')[0] + value = winreg.QueryValueEx(hKey, "MSBuildToolsPath")[0] return value except (WindowsError, OSError): - return '' + return "" diff --git a/modules/mono/build_scripts/solution_builder.py b/modules/mono/build_scripts/solution_builder.py index d1529a64d2..371819fd72 100644 --- a/modules/mono/build_scripts/solution_builder.py +++ b/modules/mono/build_scripts/solution_builder.py @@ -1,129 +1,84 @@ - import os verbose = False -def find_nuget_unix(): - import os - - if 'NUGET_PATH' in os.environ: - hint_path = os.environ['NUGET_PATH'] - if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): - return hint_path - hint_path = os.path.join(hint_path, 'nuget') - if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): - return hint_path - +def find_dotnet_cli(): import os.path - import sys - - hint_dirs = ['/opt/novell/mono/bin'] - if sys.platform == 'darwin': - hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin', '/usr/local/var/homebrew/linked/mono/bin'] + hint_dirs - - for hint_dir in hint_dirs: - hint_path = os.path.join(hint_dir, 'nuget') - if os.path.isfile(hint_path): - return hint_path - elif os.path.isfile(hint_path + '.exe'): - return hint_path + '.exe' - for hint_dir in os.environ['PATH'].split(os.pathsep): - hint_dir = hint_dir.strip('"') - hint_path = os.path.join(hint_dir, 'nuget') - if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): - return hint_path - if os.path.isfile(hint_path + '.exe') and os.access(hint_path + '.exe', os.X_OK): - return hint_path + '.exe' - - return None - - -def find_nuget_windows(env): - import os - - if 'NUGET_PATH' in os.environ: - hint_path = os.environ['NUGET_PATH'] - if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): - return hint_path - hint_path = os.path.join(hint_path, 'nuget.exe') - if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): - return hint_path - - from . mono_reg_utils import find_mono_root_dir - - mono_root = env['mono_prefix'] or find_mono_root_dir(env['bits']) - - if mono_root: - mono_bin_dir = os.path.join(mono_root, 'bin') - nuget_mono = os.path.join(mono_bin_dir, 'nuget.bat') - - if os.path.isfile(nuget_mono): - return nuget_mono - - # Standalone NuGet - - for hint_dir in os.environ['PATH'].split(os.pathsep): - hint_dir = hint_dir.strip('"') - hint_path = os.path.join(hint_dir, 'nuget.exe') - if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): - return hint_path - - return None + if os.name == "nt": + windows_exts = os.environ["PATHEXT"] + windows_exts = windows_exts.split(os.pathsep) if windows_exts else [] + + for hint_dir in os.environ["PATH"].split(os.pathsep): + hint_dir = hint_dir.strip('"') + hint_path = os.path.join(hint_dir, "dotnet") + if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): + return hint_path + if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK): + return hint_path + ".exe" + else: + for hint_dir in os.environ["PATH"].split(os.pathsep): + hint_dir = hint_dir.strip('"') + hint_path = os.path.join(hint_dir, "dotnet") + if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): + return hint_path -def find_msbuild_unix(filename): +def find_msbuild_unix(): import os.path import sys - hint_dirs = ['/opt/novell/mono/bin'] - if sys.platform == 'darwin': - hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin', '/usr/local/var/homebrew/linked/mono/bin'] + hint_dirs + hint_dirs = [] + if sys.platform == "darwin": + hint_dirs[:0] = [ + "/Library/Frameworks/Mono.framework/Versions/Current/bin", + "/usr/local/var/homebrew/linked/mono/bin", + ] for hint_dir in hint_dirs: - hint_path = os.path.join(hint_dir, filename) + hint_path = os.path.join(hint_dir, "msbuild") if os.path.isfile(hint_path): return hint_path - elif os.path.isfile(hint_path + '.exe'): - return hint_path + '.exe' + elif os.path.isfile(hint_path + ".exe"): + return hint_path + ".exe" - for hint_dir in os.environ['PATH'].split(os.pathsep): + for hint_dir in os.environ["PATH"].split(os.pathsep): hint_dir = hint_dir.strip('"') - hint_path = os.path.join(hint_dir, filename) + hint_path = os.path.join(hint_dir, "msbuild") if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): return hint_path - if os.path.isfile(hint_path + '.exe') and os.access(hint_path + '.exe', os.X_OK): - return hint_path + '.exe' + if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK): + return hint_path + ".exe" return None def find_msbuild_windows(env): - from . mono_reg_utils import find_mono_root_dir, find_msbuild_tools_path_reg + from .mono_reg_utils import find_mono_root_dir, find_msbuild_tools_path_reg - mono_root = env['mono_prefix'] or find_mono_root_dir(env['bits']) + mono_root = env["mono_prefix"] or find_mono_root_dir(env["bits"]) if not mono_root: - raise RuntimeError('Cannot find mono root directory') + raise RuntimeError("Cannot find mono root directory") - mono_bin_dir = os.path.join(mono_root, 'bin') - msbuild_mono = os.path.join(mono_bin_dir, 'msbuild.bat') + mono_bin_dir = os.path.join(mono_root, "bin") + msbuild_mono = os.path.join(mono_bin_dir, "msbuild.bat") msbuild_tools_path = find_msbuild_tools_path_reg() if msbuild_tools_path: - return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), {}) + return (os.path.join(msbuild_tools_path, "MSBuild.exe"), {}) if os.path.isfile(msbuild_mono): # The (Csc/Vbc/Fsc)ToolExe environment variables are required when # building with Mono's MSBuild. They must point to the batch files # in Mono's bin directory to make sure they are executed with Mono. mono_msbuild_env = { - 'CscToolExe': os.path.join(mono_bin_dir, 'csc.bat'), - 'VbcToolExe': os.path.join(mono_bin_dir, 'vbc.bat'), - 'FscToolExe': os.path.join(mono_bin_dir, 'fsharpc.bat') + "CscToolExe": os.path.join(mono_bin_dir, "csc.bat"), + "VbcToolExe": os.path.join(mono_bin_dir, "vbc.bat"), + "FscToolExe": os.path.join(mono_bin_dir, "fsharpc.bat"), } return (msbuild_mono, mono_msbuild_env) @@ -132,7 +87,7 @@ def find_msbuild_windows(env): def run_command(command, args, env_override=None, name=None): def cmd_args_to_str(cmd_args): - return ' '.join([arg if not ' ' in arg else '"%s"' % arg for arg in cmd_args]) + return " ".join([arg if not " " in arg else '"%s"' % arg for arg in cmd_args]) args = [command] + args @@ -143,6 +98,7 @@ def run_command(command, args, env_override=None, name=None): print("Running '%s': %s" % (name, cmd_args_to_str(args))) import subprocess + try: if env_override is None: subprocess.check_call(args) @@ -152,63 +108,43 @@ def run_command(command, args, env_override=None, name=None): raise RuntimeError("'%s' exited with error code: %s" % (name, e.returncode)) -def nuget_restore(env, *args): - global verbose - verbose = env['verbose'] - - # Find NuGet - nuget_path = find_nuget_windows(env) if os.name == 'nt' else find_nuget_unix() - if nuget_path is None: - raise RuntimeError('Cannot find NuGet executable') - - print('NuGet path: ' + nuget_path) - - # Do NuGet restore - run_command(nuget_path, ['restore'] + list(args), name='nuget restore') - - def build_solution(env, solution_path, build_config, extra_msbuild_args=[]): global verbose - verbose = env['verbose'] + verbose = env["verbose"] msbuild_env = os.environ.copy() # Needed when running from Developer Command Prompt for VS - if 'PLATFORM' in msbuild_env: - del msbuild_env['PLATFORM'] - - # Find MSBuild - if os.name == 'nt': - msbuild_info = find_msbuild_windows(env) - if msbuild_info is None: - raise RuntimeError('Cannot find MSBuild executable') - msbuild_path = msbuild_info[0] - msbuild_env.update(msbuild_info[1]) - else: - msbuild_path = find_msbuild_unix('msbuild') - if msbuild_path is None: - xbuild_fallback = env['xbuild_fallback'] - - if xbuild_fallback and os.name == 'nt': - print('Option \'xbuild_fallback\' not supported on Windows') - xbuild_fallback = False + if "PLATFORM" in msbuild_env: + del msbuild_env["PLATFORM"] - if xbuild_fallback: - print('Cannot find MSBuild executable, trying with xbuild') - print('Warning: xbuild is deprecated') + msbuild_args = [] - msbuild_path = find_msbuild_unix('xbuild') + dotnet_cli = find_dotnet_cli() - if msbuild_path is None: - raise RuntimeError('Cannot find xbuild executable') - else: - raise RuntimeError('Cannot find MSBuild executable') + if dotnet_cli: + msbuild_path = dotnet_cli + msbuild_args += ["msbuild"] # `dotnet msbuild` command + else: + # Find MSBuild + if os.name == "nt": + msbuild_info = find_msbuild_windows(env) + if msbuild_info is None: + raise RuntimeError("Cannot find MSBuild executable") + msbuild_path = msbuild_info[0] + msbuild_env.update(msbuild_info[1]) + else: + msbuild_path = find_msbuild_unix() + if msbuild_path is None: + raise RuntimeError("Cannot find MSBuild executable") - print('MSBuild path: ' + msbuild_path) + print("MSBuild path: " + msbuild_path) # Build solution - msbuild_args = [solution_path, '/p:Configuration=' + build_config] + targets = ["Restore", "Build"] + + msbuild_args += [solution_path, "/t:%s" % ",".join(targets), "/p:Configuration=" + build_config] msbuild_args += extra_msbuild_args - run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name='msbuild') + run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild") diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp index b04e53bd81..39e3a95afa 100644 --- a/modules/mono/class_db_api_json.cpp +++ b/modules/mono/class_db_api_json.cpp @@ -42,17 +42,15 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> names; - const StringName *k = NULL; + const StringName *k = nullptr; while ((k = ClassDB::classes.next(k))) { - names.push_back(*k); } //must be alphabetically sorted for hash to compute names.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - ClassDB::ClassInfo *t = ClassDB::classes.getptr(E->get()); ERR_FAIL_COND(!t); if (t->api != p_api || !t->exposed) @@ -67,10 +65,9 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = NULL; + k = nullptr; while ((k = t->method_map.next(k))) { - String name = k->operator String(); ERR_CONTINUE(name.empty()); @@ -132,10 +129,9 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = NULL; + k = nullptr; while ((k = t->constant_map.next(k))) { - snames.push_back(*k); } @@ -160,10 +156,9 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = NULL; + k = nullptr; while ((k = t->signal_map.next(k))) { - snames.push_back(*k); } @@ -196,10 +191,9 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { List<StringName> snames; - k = NULL; + k = nullptr; while ((k = t->property_setget.next(k))) { - snames.push_back(*k); } diff --git a/modules/mono/config.py b/modules/mono/config.py index a5d3059ecc..7980a86cb3 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -1,43 +1,70 @@ +supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"] + + def can_build(env, platform): return True def configure(env): - if env['platform'] not in ['windows', 'osx', 'x11', 'server', 'android', 'haiku', 'javascript']: - raise RuntimeError('This module does not currently support building for this platform') + platform = env["platform"] + + if platform not in supported_platforms: + raise RuntimeError("This module does not currently support building for this platform") env.use_ptrcall = True - env.add_module_version_string('mono') + env.add_module_version_string("mono") from SCons.Script import BoolVariable, PathVariable, Variables, Help + default_mono_static = platform in ["iphone", "javascript"] + default_mono_bundles_zlib = platform in ["javascript"] + envvars = Variables() - envvars.Add(PathVariable('mono_prefix', 'Path to the mono installation directory for the target platform and architecture', '', PathVariable.PathAccept)) - envvars.Add(BoolVariable('mono_static', 'Statically link mono', False)) - envvars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True)) - envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False)) - envvars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False)) + envvars.Add( + PathVariable( + "mono_prefix", + "Path to the mono installation directory for the target platform and architecture", + "", + PathVariable.PathAccept, + ) + ) + envvars.Add(BoolVariable("mono_static", "Statically link mono", default_mono_static)) + envvars.Add(BoolVariable("mono_glue", "Build with the mono glue sources", True)) + envvars.Add(BoolVariable("build_cil", "Build C# solutions", True)) + envvars.Add( + BoolVariable( + "copy_mono_root", "Make a copy of the mono installation directory to bundle with the editor", False + ) + ) + + # TODO: It would be great if this could be detected automatically instead + envvars.Add( + BoolVariable( + "mono_bundles_zlib", "Specify if the Mono runtime was built with bundled zlib", default_mono_bundles_zlib + ) + ) + envvars.Update(env) Help(envvars.GenerateHelpText(env)) - if env['platform'] == 'javascript': - # Mono wasm already has zlib builtin, so we need this workaround to avoid symbol collisions - print('Compiling with Mono wasm disables \'builtin_zlib\'') - env['builtin_zlib'] = False + if env["mono_bundles_zlib"]: + # Mono may come with zlib bundled for WASM or on newer version when built with MinGW. + print("This Mono runtime comes with zlib bundled. Disabling 'builtin_zlib'...") + env["builtin_zlib"] = False thirdparty_zlib_dir = "#thirdparty/zlib/" env.Prepend(CPPPATH=[thirdparty_zlib_dir]) def get_doc_classes(): return [ - '@C#', - 'CSharpScript', - 'GodotSharp', + "@C#", + "CSharpScript", + "GodotSharp", ] def get_doc_path(): - return 'doc_classes' + return "doc_classes" def is_enabled(): diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 28bacbd0f0..958d72adb1 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -67,7 +67,6 @@ #ifdef TOOLS_ENABLED static bool _create_project_solution_if_needed() { - String sln_path = GodotSharpDirs::get_project_sln_path(); String csproj_path = GodotSharpDirs::get_project_csproj_path(); @@ -85,28 +84,23 @@ static bool _create_project_solution_if_needed() { CSharpLanguage *CSharpLanguage::singleton = nullptr; String CSharpLanguage::get_name() const { - return "C#"; } String CSharpLanguage::get_type() const { - return "CSharpScript"; } String CSharpLanguage::get_extension() const { - return "cs"; } Error CSharpLanguage::execute_file(const String &p_path) { - // ?? return OK; } void CSharpLanguage::init() { - #ifdef DEBUG_METHODS_ENABLED if (OS::get_singleton()->get_cmdline_args().find("--class-db-json")) { class_db_api_to_json("user://class_db_api.json", ClassDB::API_CORE); @@ -140,7 +134,6 @@ void CSharpLanguage::init() { } void CSharpLanguage::finish() { - if (finalized) return; @@ -158,7 +151,7 @@ void CSharpLanguage::finish() { if (gdmono) { memdelete(gdmono); - gdmono = NULL; + gdmono = nullptr; } // Clear here, after finalizing all domains to make sure there is nothing else referencing the elements. @@ -184,7 +177,6 @@ void CSharpLanguage::finish() { } void CSharpLanguage::get_reserved_words(List<String> *p_words) const { - static const char *_reserved_words[] = { // Reserved keywords "abstract", @@ -295,7 +287,7 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const { "when", "where", "yield", - 0 + nullptr }; const char **w = _reserved_words; @@ -307,20 +299,18 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const { } void CSharpLanguage::get_comment_delimiters(List<String> *p_delimiters) const { - p_delimiters->push_back("//"); // single-line comment p_delimiters->push_back("/* */"); // delimited comment } void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const { - p_delimiters->push_back("' '"); // character literal p_delimiters->push_back("\" \""); // regular string literal - p_delimiters->push_back("@\" \""); // verbatim string literal + // Verbatim string literals (`@" "`) don't render correctly, so don't highlight them. + // Generic string highlighting suffices as a workaround for now. } static String get_base_class_name(const String &p_base_class_name, const String p_class_name) { - String base_class = p_base_class_name; if (p_class_name == base_class) { base_class = "Godot." + base_class; @@ -329,7 +319,6 @@ static String get_base_class_name(const String &p_base_class_name, const String } Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { - String script_template = "using " BINDINGS_NAMESPACE ";\n" "using System;\n" "\n" @@ -365,12 +354,10 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin } bool CSharpLanguage::is_using_templates() { - return true; } void CSharpLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) { - String src = p_script->get_source_code(); String base_class_name = get_base_class_name(p_base_class_name, p_class_name); src = src.replace("%BASE%", base_class_name) @@ -380,7 +367,6 @@ void CSharpLanguage::make_template(const String &p_class_name, const String &p_b } String CSharpLanguage::validate_path(const String &p_path) const { - String class_name = p_path.get_file().get_basename(); List<String> keywords; get_reserved_words(&keywords); @@ -391,23 +377,19 @@ String CSharpLanguage::validate_path(const String &p_path) const { } Script *CSharpLanguage::create_script() const { - return memnew(CSharpScript); } bool CSharpLanguage::has_named_classes() const { - return false; } bool CSharpLanguage::supports_builtin_mode() const { - return false; } #ifdef TOOLS_ENABLED static String variant_type_to_managed_name(const String &p_var_type_name) { - if (p_var_type_name.empty()) return "object"; @@ -530,12 +512,10 @@ String CSharpLanguage::_get_indentation() const { } String CSharpLanguage::debug_get_error() const { - return _debug_error; } int CSharpLanguage::debug_get_stack_level_count() const { - if (_debug_parse_err_line >= 0) return 1; @@ -544,7 +524,6 @@ int CSharpLanguage::debug_get_stack_level_count() const { } int CSharpLanguage::debug_get_stack_level_line(int p_level) const { - if (_debug_parse_err_line >= 0) return _debug_parse_err_line; @@ -553,7 +532,6 @@ int CSharpLanguage::debug_get_stack_level_line(int p_level) const { } String CSharpLanguage::debug_get_stack_level_function(int p_level) const { - if (_debug_parse_err_line >= 0) return String(); @@ -562,7 +540,6 @@ String CSharpLanguage::debug_get_stack_level_function(int p_level) const { } String CSharpLanguage::debug_get_stack_level_source(int p_level) const { - if (_debug_parse_err_line >= 0) return _debug_parse_err_file; @@ -571,7 +548,6 @@ String CSharpLanguage::debug_get_stack_level_source(int p_level) const { } Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() { - #ifdef DEBUG_ENABLED // Printing an error here will result in endless recursion, so we must be careful static thread_local bool _recursion_flag_ = false; @@ -603,7 +579,6 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() #ifdef DEBUG_ENABLED Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) { - // Printing an error here will result in endless recursion, so we must be careful static thread_local bool _recursion_flag_ = false; if (_recursion_flag_) @@ -613,7 +588,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec GD_MONO_SCOPE_THREAD_ATTACH; - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoArray *frames = CACHED_METHOD_THUNK(System_Diagnostics_StackTrace, GetFrames).invoke(p_stack_trace, &exc); @@ -677,15 +652,14 @@ void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) { } void CSharpLanguage::frame() { - - if (gdmono && gdmono->is_runtime_initialized() && gdmono->get_core_api_assembly() != NULL) { + if (gdmono && gdmono->is_runtime_initialized() && gdmono->get_core_api_assembly() != nullptr) { const Ref<MonoGCHandleRef> &task_scheduler_handle = GDMonoCache::cached_data.task_scheduler_handle; if (task_scheduler_handle.is_valid()) { MonoObject *task_scheduler = task_scheduler_handle->get_target(); if (task_scheduler) { - MonoException *exc = NULL; + MonoException *exc = nullptr; CACHED_METHOD_THUNK(GodotTaskScheduler, Activate).invoke(task_scheduler, &exc); if (exc) { @@ -697,7 +671,6 @@ void CSharpLanguage::frame() { } struct CSharpScriptDepSort { - // must support sorting so inheritance works properly (parent must be reloaded first) bool operator()(const Ref<CSharpScript> &A, const Ref<CSharpScript> &B) const { if (A == B) @@ -717,7 +690,6 @@ struct CSharpScriptDepSort { }; void CSharpLanguage::reload_all_scripts() { - #ifdef GD_MONO_HOT_RELOAD if (is_assembly_reloading_needed()) { GD_MONO_SCOPE_THREAD_ATTACH; @@ -727,7 +699,6 @@ void CSharpLanguage::reload_all_scripts() { } void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { - (void)p_script; // UNUSED CRASH_COND(!Engine::get_singleton()->is_editor_hint()); @@ -746,7 +717,6 @@ void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft #ifdef GD_MONO_HOT_RELOAD bool CSharpLanguage::is_assembly_reloading_needed() { - if (!gdmono->is_runtime_initialized()) return false; @@ -763,7 +733,7 @@ bool CSharpLanguage::is_assembly_reloading_needed() { if (proj_assembly) { String proj_asm_path = proj_assembly->get_path(); - if (!FileAccess::exists(proj_assembly->get_path())) { + if (!FileAccess::exists(proj_asm_path)) { // Maybe it wasn't loaded from the default path, so check this as well proj_asm_path = GodotSharpDirs::get_res_temp_assemblies_dir().plus_file(appname_safe); if (!FileAccess::exists(proj_asm_path)) @@ -781,7 +751,6 @@ bool CSharpLanguage::is_assembly_reloading_needed() { } void CSharpLanguage::reload_assemblies(bool p_soft_reload) { - if (!gdmono->is_runtime_initialized()) return; @@ -812,7 +781,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { Array serialized_data; MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data); - MonoException *exc = NULL; + MonoException *exc = nullptr; bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TrySerializeDelegate).invoke(delegate, managed_serialized_data, &exc); if (exc) { @@ -849,7 +818,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { to_reload.push_back(script); if (script->get_path().empty()) { - script->tied_class_name_for_reload = script->script_class->get_name(); + script->tied_class_name_for_reload = script->script_class->get_name_for_lookup(); script->tied_class_namespace_for_reload = script->script_class->get_namespace(); } @@ -945,7 +914,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // Restore Variant properties state, it will be kept by the placeholder until the next script reloading for (List<Pair<StringName, Variant>>::Element *G = scr->pending_reload_state[obj_id].properties.front(); G; G = G->next()) { - placeholder->property_set_fallback(G->get().first, G->get().second, NULL); + placeholder->property_set_fallback(G->get().first, G->get().second, nullptr); } scr->pending_reload_state.erase(obj_id); @@ -979,12 +948,12 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { GDMonoAssembly *project_assembly = gdmono->get_project_assembly(); // Search in project and tools assemblies first as those are the most likely to have the class - GDMonoClass *script_class = (project_assembly ? project_assembly->get_class(class_namespace, class_name) : NULL); + GDMonoClass *script_class = (project_assembly ? project_assembly->get_class(class_namespace, class_name) : nullptr); #ifdef TOOLS_ENABLED if (!script_class) { GDMonoAssembly *tools_assembly = gdmono->get_tools_assembly(); - script_class = (tools_assembly ? tools_assembly->get_class(class_namespace, class_name) : NULL); + script_class = (tools_assembly ? tools_assembly->get_class(class_namespace, class_name) : nullptr); } #endif @@ -1055,7 +1024,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { continue; } #else - CRASH_COND(si != NULL); + CRASH_COND(si != nullptr); #endif // Re-create script instance obj->set_script(script); // will create the script instance as well @@ -1104,9 +1073,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { const CSharpScript::EventSignal &event_signal = match->value(); MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data); - MonoDelegate *delegate = NULL; + MonoDelegate *delegate = nullptr; - MonoException *exc = NULL; + MonoException *exc = nullptr; bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TryDeserializeDelegate).invoke(managed_serialized_data, &delegate, &exc); if (exc) { @@ -1115,7 +1084,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } if (success) { - ERR_CONTINUE(delegate == NULL); + ERR_CONTINUE(delegate == nullptr); event_signal.field->set_value(csi->get_mono_object(), (MonoObject *)delegate); } else if (OS::get_singleton()->is_stdout_verbose()) { OS::get_singleton()->print("Failed to deserialize event signal delegate\n"); @@ -1140,9 +1109,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { const Array &serialized_data = elem->value(); MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data); - MonoDelegate *delegate = NULL; + MonoDelegate *delegate = nullptr; - MonoException *exc = NULL; + MonoException *exc = nullptr; bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TryDeserializeDelegate).invoke(managed_serialized_data, &delegate, &exc); if (exc) { @@ -1151,7 +1120,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } if (success) { - ERR_CONTINUE(delegate == NULL); + ERR_CONTINUE(delegate == nullptr); managed_callable->set_delegate(delegate); } else if (OS::get_singleton()->is_stdout_verbose()) { OS::get_singleton()->print("Failed to deserialize delegate\n"); @@ -1172,7 +1141,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { #endif void CSharpLanguage::_load_scripts_metadata() { - scripts_metadata.clear(); String scripts_metadata_filename = "scripts_metadata."; @@ -1217,24 +1185,20 @@ void CSharpLanguage::_load_scripts_metadata() { } void CSharpLanguage::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("cs"); } #ifdef TOOLS_ENABLED Error CSharpLanguage::open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { - return (Error)(int)get_godotsharp_editor()->call("OpenInExternalEditor", p_script, p_line, p_col); } bool CSharpLanguage::overrides_external_editor() { - return get_godotsharp_editor()->call("OverridesExternalEditor"); } #endif void CSharpLanguage::thread_enter() { - #if 0 if (gdmono->is_runtime_initialized()) { GDMonoUtils::attach_current_thread(); @@ -1243,7 +1207,6 @@ void CSharpLanguage::thread_enter() { } void CSharpLanguage::thread_exit() { - #if 0 if (gdmono->is_runtime_initialized()) { GDMonoUtils::detach_current_thread(); @@ -1252,7 +1215,6 @@ void CSharpLanguage::thread_exit() { } bool CSharpLanguage::debug_break_parse(const String &p_file, int p_line, const String &p_error) { - // Not a parser error in our case, but it's still used for other type of errors if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { _debug_parse_err_line = p_line; @@ -1266,7 +1228,6 @@ bool CSharpLanguage::debug_break_parse(const String &p_file, int p_line, const S } bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) { - if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { _debug_parse_err_line = -1; _debug_parse_err_file = ""; @@ -1291,7 +1252,7 @@ void CSharpLanguage::_on_scripts_domain_unloaded() { for (SelfList<ManagedCallable> *elem = ManagedCallable::instances.first(); elem; elem = elem->next()) { ManagedCallable *managed_callable = elem->self(); managed_callable->delegate_handle.release(); - managed_callable->delegate_invoke = NULL; + managed_callable->delegate_invoke = nullptr; } } @@ -1300,23 +1261,22 @@ void CSharpLanguage::_on_scripts_domain_unloaded() { #ifdef TOOLS_ENABLED void CSharpLanguage::_editor_init_callback() { - register_editor_internal_calls(); // Initialize GodotSharpEditor GDMonoClass *editor_klass = GDMono::get_singleton()->get_tools_assembly()->get_class("GodotTools", "GodotSharpEditor"); - CRASH_COND(editor_klass == NULL); + CRASH_COND(editor_klass == nullptr); MonoObject *mono_object = mono_object_new(mono_domain_get(), editor_klass->get_mono_ptr()); - CRASH_COND(mono_object == NULL); + CRASH_COND(mono_object == nullptr); - MonoException *exc = NULL; + MonoException *exc = nullptr; GDMonoUtils::runtime_object_init(mono_object, editor_klass, &exc); UNHANDLED_EXCEPTION(exc); EditorPlugin *godotsharp_editor = Object::cast_to<EditorPlugin>(GDMonoMarshal::mono_object_to_variant(mono_object)); - CRASH_COND(godotsharp_editor == NULL); + CRASH_COND(godotsharp_editor == nullptr); // Enable it as a plugin EditorNode::add_editor_plugin(godotsharp_editor); @@ -1327,13 +1287,11 @@ void CSharpLanguage::_editor_init_callback() { #endif void CSharpLanguage::set_language_index(int p_idx) { - ERR_FAIL_COND(lang_idx != -1); lang_idx = p_idx; } void CSharpLanguage::release_script_gchandle(MonoGCHandleData &p_gchandle) { - if (!p_gchandle.is_released()) { // Do not lock unnecessarily MutexLock lock(get_singleton()->script_gchandle_release_mutex); p_gchandle.release(); @@ -1341,7 +1299,6 @@ void CSharpLanguage::release_script_gchandle(MonoGCHandleData &p_gchandle) { } void CSharpLanguage::release_script_gchandle(MonoObject *p_expected_obj, MonoGCHandleData &p_gchandle) { - uint32_t pinned_gchandle = GDMonoUtils::new_strong_gchandle_pinned(p_expected_obj); // We might lock after this, so pin it if (!p_gchandle.is_released()) { // Do not lock unnecessarily @@ -1353,7 +1310,7 @@ void CSharpLanguage::release_script_gchandle(MonoObject *p_expected_obj, MonoGCH // already released and could have been replaced) or if we can't get its target MonoObject* // (which doesn't necessarily mean it was released, and we want it released in order to // avoid locking other threads unnecessarily). - if (target == p_expected_obj || target == NULL) { + if (target == p_expected_obj || target == nullptr) { p_gchandle.release(); } } @@ -1362,24 +1319,21 @@ void CSharpLanguage::release_script_gchandle(MonoObject *p_expected_obj, MonoGCH } CSharpLanguage::CSharpLanguage() { - ERR_FAIL_COND_MSG(singleton, "C# singleton already exist."); singleton = this; } CSharpLanguage::~CSharpLanguage() { - finish(); singleton = nullptr; } bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object) { - #ifdef DEBUG_ENABLED // I don't trust you if (p_object->get_script_instance()) { CSharpInstance *csharp_instance = CAST_CSHARP_INSTANCE(p_object->get_script_instance()); - CRASH_COND(csharp_instance != NULL && !csharp_instance->is_destructing_script_instance()); + CRASH_COND(csharp_instance != nullptr && !csharp_instance->is_destructing_script_instance()); } #endif @@ -1423,7 +1377,6 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b } void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { - MutexLock lock(language_bind_mutex); Map<Object *, CSharpScriptBinding>::Element *match = script_bindings.find(p_object); @@ -1433,19 +1386,17 @@ void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { CSharpScriptBinding script_binding; if (!setup_csharp_script_binding(script_binding, p_object)) - return NULL; + return nullptr; return (void *)insert_script_binding(p_object, script_binding); } Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) { - return script_bindings.insert(p_object, p_script_binding); } void CSharpLanguage::free_instance_binding_data(void *p_data) { - - if (GDMono::get_singleton() == NULL) { + if (GDMono::get_singleton() == nullptr) { #ifdef DEBUG_ENABLED CRASH_COND(!script_bindings.empty()); #endif @@ -1470,7 +1421,7 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) { // This is done to avoid trying to dispose the native instance from Dispose(bool). MonoObject *mono_object = script_binding.gchandle.get_target(); if (mono_object) { - CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, NULL); + CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, nullptr); } script_binding.gchandle.release(); } @@ -1480,7 +1431,6 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) { } void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) { - Reference *ref_owner = Object::cast_to<Reference>(p_object); #ifdef DEBUG_ENABLED @@ -1516,7 +1466,6 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) { } bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { - Reference *ref_owner = Object::cast_to<Reference>(p_object); #ifdef DEBUG_ENABLED @@ -1557,12 +1506,11 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { } CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle) { - CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(p_script))); Reference *ref = Object::cast_to<Reference>(p_owner); - instance->base_ref = ref != NULL; + instance->base_ref = ref != nullptr; instance->owner = p_owner; instance->gchandle = p_gchandle; @@ -1575,8 +1523,7 @@ CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpS } MonoObject *CSharpInstance::get_mono_object() const { - - ERR_FAIL_COND_V(gchandle.is_released(), NULL); + ERR_FAIL_COND_V(gchandle.is_released(), nullptr); return gchandle.get_target(); } @@ -1585,7 +1532,6 @@ Object *CSharpInstance::get_owner() { } bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) { - ERR_FAIL_COND_V(!script.is_valid(), false); GD_MONO_SCOPE_THREAD_ATTACH; @@ -1639,7 +1585,6 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) { } bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const { - ERR_FAIL_COND_V(!script.is_valid(), false); GD_MONO_SCOPE_THREAD_ATTACH; @@ -1661,7 +1606,7 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const { GDMonoProperty *property = top->get_property(p_name); if (property) { - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoObject *value = property->get_value(mono_object, &exc); if (exc) { r_ret = Variant(); @@ -1703,7 +1648,6 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const { } void CSharpInstance::get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state) { - List<PropertyInfo> pinfo; get_property_list(&pinfo); @@ -1728,7 +1672,6 @@ void CSharpInstance::get_properties_state_for_reloading(List<Pair<StringName, Va } void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, Array>> &r_state) { - MonoObject *owner_managed = get_mono_object(); ERR_FAIL_NULL(owner_managed); @@ -1742,7 +1685,7 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, Array serialized_data; MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data); - MonoException *exc = NULL; + MonoException *exc = nullptr; bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TrySerializeDelegate).invoke(delegate_field_value, managed_serialized_data, &exc); if (exc) { @@ -1759,7 +1702,6 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, } void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { - for (Map<StringName, PropertyInfo>::Element *E = script->member_info.front(); E; E = E->next()) { p_properties->push_back(E->value()); } @@ -1796,7 +1738,6 @@ void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { } Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { - if (script->member_info.has(p_name)) { if (r_is_valid) *r_is_valid = true; @@ -1810,7 +1751,6 @@ Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool * } bool CSharpInstance::has_method(const StringName &p_method) const { - if (!script.is_valid()) return false; @@ -1830,7 +1770,6 @@ bool CSharpInstance::has_method(const StringName &p_method) const { } Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - ERR_FAIL_COND_V(!script.is_valid(), Variant()); GD_MONO_SCOPE_THREAD_ATTACH; @@ -1868,7 +1807,6 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, } void CSharpInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) { - GD_MONO_SCOPE_THREAD_ATTACH; if (script.is_valid()) { @@ -1881,7 +1819,6 @@ void CSharpInstance::call_multilevel(const StringName &p_method, const Variant * } void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount) { - GD_MONO_ASSERT_THREAD_ATTACHED; GDMonoClass *top = script->script_class; @@ -1899,17 +1836,15 @@ void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringNam } void CSharpInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) { - // Sorry, the method is the one that controls the call order call_multilevel(p_method, p_args, p_argcount); } bool CSharpInstance::_reference_owner_unsafe() { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); - CRASH_COND(owner == NULL); + CRASH_COND(owner == nullptr); CRASH_COND(unsafe_referenced); // already referenced #endif @@ -1928,10 +1863,9 @@ bool CSharpInstance::_reference_owner_unsafe() { } bool CSharpInstance::_unreference_owner_unsafe() { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); - CRASH_COND(owner == NULL); + CRASH_COND(owner == nullptr); #endif if (!unsafe_referenced) @@ -1952,13 +1886,13 @@ bool CSharpInstance::_unreference_owner_unsafe() { MonoObject *CSharpInstance::_internal_new_managed() { // Search the constructor first, to fail with an error if it's not found before allocating anything else. GDMonoMethod *ctor = script->script_class->get_method(CACHED_STRING_NAME(dotctor), 0); - ERR_FAIL_NULL_V_MSG(ctor, NULL, + ERR_FAIL_NULL_V_MSG(ctor, nullptr, "Cannot create script instance because the class does not define a parameterless constructor: '" + script->get_path() + "'."); CSharpLanguage::get_singleton()->release_script_gchandle(gchandle); - ERR_FAIL_NULL_V(owner, NULL); - ERR_FAIL_COND_V(script.is_null(), NULL); + ERR_FAIL_NULL_V(owner, nullptr); + ERR_FAIL_COND_V(script.is_null(), nullptr); MonoObject *mono_object = mono_object_new(mono_domain_get(), script->script_class->get_mono_ptr()); @@ -1970,9 +1904,9 @@ MonoObject *CSharpInstance::_internal_new_managed() { // Not ok for the owner to die here. If there is a situation where this can happen, it will be considered a bug. CRASH_COND(die == true); - owner = NULL; + owner = nullptr; - ERR_FAIL_V_MSG(NULL, "Failed to allocate memory for the object."); + ERR_FAIL_V_MSG(nullptr, "Failed to allocate memory for the object."); } // Tie managed to unmanaged @@ -1984,13 +1918,12 @@ MonoObject *CSharpInstance::_internal_new_managed() { CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, owner); // Construct - ctor->invoke_raw(mono_object, NULL); + ctor->invoke_raw(mono_object, nullptr); return mono_object; } void CSharpInstance::mono_object_disposed(MonoObject *p_obj) { - disconnect_event_signals(); #ifdef DEBUG_ENABLED @@ -2001,7 +1934,6 @@ void CSharpInstance::mono_object_disposed(MonoObject *p_obj) { } void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance) { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); CRASH_COND(gchandle.is_released()); @@ -2062,10 +1994,9 @@ void CSharpInstance::disconnect_event_signals() { } void CSharpInstance::refcount_incremented() { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); - CRASH_COND(owner == NULL); + CRASH_COND(owner == nullptr); #endif Reference *ref_owner = Object::cast_to<Reference>(owner); @@ -2085,10 +2016,9 @@ void CSharpInstance::refcount_incremented() { } bool CSharpInstance::refcount_decremented() { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); - CRASH_COND(owner == NULL); + CRASH_COND(owner == nullptr); #endif Reference *ref_owner = Object::cast_to<Reference>(owner); @@ -2155,7 +2085,6 @@ MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab } void CSharpInstance::notification(int p_notification) { - GD_MONO_SCOPE_THREAD_ATTACH; if (p_notification == Object::NOTIFICATION_PREDELETE) { @@ -2180,7 +2109,7 @@ void CSharpInstance::notification(int p_notification) { MonoObject *mono_object = get_mono_object(); ERR_FAIL_NULL(mono_object); - MonoException *exc = NULL; + MonoException *exc = nullptr; GDMonoUtils::dispose(mono_object, &exc); if (exc) { @@ -2194,7 +2123,6 @@ void CSharpInstance::notification(int p_notification) { } void CSharpInstance::_call_notification(int p_notification) { - GD_MONO_ASSERT_THREAD_ATTACHED; MonoObject *mono_object = get_mono_object(); @@ -2225,13 +2153,13 @@ String CSharpInstance::to_string(bool *r_valid) { MonoObject *mono_object = get_mono_object(); - if (mono_object == NULL) { + if (mono_object == nullptr) { if (r_valid) *r_valid = false; return String(); } - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoString *result = GDMonoUtils::object_to_string(mono_object, &exc); if (exc) { @@ -2241,7 +2169,7 @@ String CSharpInstance::to_string(bool *r_valid) { return String(); } - if (result == NULL) { + if (result == nullptr) { if (r_valid) *r_valid = false; return String(); @@ -2251,12 +2179,10 @@ String CSharpInstance::to_string(bool *r_valid) { } Ref<Script> CSharpInstance::get_script() const { - return script; } ScriptLanguage *CSharpInstance::get_language() { - return CSharpLanguage::get_singleton(); } @@ -2265,7 +2191,6 @@ CSharpInstance::CSharpInstance(const Ref<CSharpScript> &p_script) : } CSharpInstance::~CSharpInstance() { - GD_MONO_SCOPE_THREAD_ATTACH; destructing_script_instance = true; @@ -2275,13 +2200,13 @@ CSharpInstance::~CSharpInstance() { // This destructor is not called from the owners destructor. // This could be being called from the owner's set_script_instance method, // meaning this script is being replaced with another one. If this is the case, - // we must call Dispose here, because Dispose calls owner->set_script_instance(NULL) + // we must call Dispose here, because Dispose calls owner->set_script_instance(nullptr) // and that would mess up with the new script instance if called later. MonoObject *mono_object = gchandle.get_target(); if (mono_object) { - MonoException *exc = NULL; + MonoException *exc = nullptr; GDMonoUtils::dispose(mono_object, &exc); if (exc) { @@ -2311,7 +2236,7 @@ CSharpInstance::~CSharpInstance() { CRASH_COND(die == true); // `owner_keep_alive` holds a reference, so it can't die void *data = owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); - CRASH_COND(data == NULL); + CRASH_COND(data == nullptr); CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); @@ -2347,14 +2272,12 @@ CSharpInstance::~CSharpInstance() { #ifdef TOOLS_ENABLED void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { - placeholders.erase(p_placeholder); } #endif #ifdef TOOLS_ENABLED void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) { - if (base_cache.is_valid()) { base_cache->_update_exports_values(values, propnames); } @@ -2369,7 +2292,6 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List } void CSharpScript::_update_member_info_no_exports() { - if (exports_invalidated) { GD_MONO_ASSERT_THREAD_ATTACHED; @@ -2418,60 +2340,69 @@ void CSharpScript::_update_member_info_no_exports() { #endif bool CSharpScript::_update_exports() { - #ifdef TOOLS_ENABLED - if (!Engine::get_singleton()->is_editor_hint()) - return false; - - placeholder_fallback_enabled = true; // until proven otherwise - + bool is_editor = Engine::get_singleton()->is_editor_hint(); + if (is_editor) + placeholder_fallback_enabled = true; // until proven otherwise +#endif if (!valid) return false; bool changed = false; - if (exports_invalidated) { +#ifdef TOOLS_ENABLED + if (exports_invalidated) +#endif + { GD_MONO_SCOPE_THREAD_ATTACH; - exports_invalidated = false; - changed = true; member_info.clear(); - exported_members_cache.clear(); - exported_members_defval_cache.clear(); - // Here we create a temporary managed instance of the class to get the initial values +#ifdef TOOLS_ENABLED + MonoObject *tmp_object = nullptr; + Object *tmp_native = nullptr; + uint32_t tmp_pinned_gchandle = 0; + + if (is_editor) { + exports_invalidated = false; - MonoObject *tmp_object = mono_object_new(mono_domain_get(), script_class->get_mono_ptr()); + exported_members_cache.clear(); + exported_members_defval_cache.clear(); - if (!tmp_object) { - ERR_PRINT("Failed to allocate temporary MonoObject."); - return false; - } + // Here we create a temporary managed instance of the class to get the initial values + tmp_object = mono_object_new(mono_domain_get(), script_class->get_mono_ptr()); - uint32_t tmp_pinned_gchandle = GDMonoUtils::new_strong_gchandle_pinned(tmp_object); // pin it (not sure if needed) + if (!tmp_object) { + ERR_PRINT("Failed to allocate temporary MonoObject."); + return false; + } - GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0); + tmp_pinned_gchandle = GDMonoUtils::new_strong_gchandle_pinned(tmp_object); // pin it (not sure if needed) - ERR_FAIL_NULL_V_MSG(ctor, NULL, - "Cannot construct temporary MonoObject because the class does not define a parameterless constructor: '" + get_path() + "'."); + GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0); - MonoException *ctor_exc = NULL; - ctor->invoke(tmp_object, NULL, &ctor_exc); + ERR_FAIL_NULL_V_MSG(ctor, false, + "Cannot construct temporary MonoObject because the class does not define a parameterless constructor: '" + get_path() + "'."); - Object *tmp_native = GDMonoMarshal::unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(tmp_object)); + MonoException *ctor_exc = nullptr; + ctor->invoke(tmp_object, nullptr, &ctor_exc); - if (ctor_exc) { - // TODO: Should we free 'tmp_native' if the exception was thrown after its creation? + tmp_native = GDMonoMarshal::unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(tmp_object)); - GDMonoUtils::free_gchandle(tmp_pinned_gchandle); - tmp_object = NULL; + if (ctor_exc) { + // TODO: Should we free 'tmp_native' if the exception was thrown after its creation? - ERR_PRINT("Exception thrown from constructor of temporary MonoObject:"); - GDMonoUtils::debug_print_unhandled_exception(ctor_exc); - return false; + GDMonoUtils::free_gchandle(tmp_pinned_gchandle); + tmp_object = nullptr; + + ERR_PRINT("Exception thrown from constructor of temporary MonoObject:"); + GDMonoUtils::debug_print_unhandled_exception(ctor_exc); + return false; + } } +#endif GDMonoClass *top = script_class; @@ -2487,15 +2418,22 @@ bool CSharpScript::_update_exports() { if (_get_member_export(field, /* inspect export: */ true, prop_info, exported)) { StringName member_name = field->get_name(); + member_info[member_name] = prop_info; + if (exported) { - member_info[member_name] = prop_info; - exported_members_cache.push_front(prop_info); +#ifdef TOOLS_ENABLED + if (is_editor) { + exported_members_cache.push_front(prop_info); - if (tmp_object) { - exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); + if (tmp_object) { + exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); + } } - } else { - member_info[member_name] = prop_info; +#endif + +#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) + exported_members_names.insert(member_name); +#endif } } } @@ -2508,22 +2446,28 @@ bool CSharpScript::_update_exports() { if (_get_member_export(property, /* inspect export: */ true, prop_info, exported)) { StringName member_name = property->get_name(); + member_info[member_name] = prop_info; + if (exported) { - member_info[member_name] = prop_info; - exported_members_cache.push_front(prop_info); - - if (tmp_object) { - MonoException *exc = NULL; - MonoObject *ret = property->get_value(tmp_object, &exc); - if (exc) { - exported_members_defval_cache[member_name] = Variant(); - GDMonoUtils::debug_print_unhandled_exception(exc); - } else { - exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(ret); +#ifdef TOOLS_ENABLED + if (is_editor) { + exported_members_cache.push_front(prop_info); + if (tmp_object) { + MonoException *exc = nullptr; + MonoObject *ret = property->get_value(tmp_object, &exc); + if (exc) { + exported_members_defval_cache[member_name] = Variant(); + GDMonoUtils::debug_print_unhandled_exception(exc); + } else { + exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(ret); + } } } - } else { - member_info[member_name] = prop_info; +#endif + +#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) + exported_members_names.insert(member_name); +#endif } } } @@ -2531,52 +2475,57 @@ bool CSharpScript::_update_exports() { top = top->get_parent_class(); } - // Need to check this here, before disposal - bool base_ref = Object::cast_to<Reference>(tmp_native) != NULL; - - // Dispose the temporary managed instance +#ifdef TOOLS_ENABLED + if (is_editor) { + // Need to check this here, before disposal + bool base_ref = Object::cast_to<Reference>(tmp_native) != nullptr; - MonoException *exc = NULL; - GDMonoUtils::dispose(tmp_object, &exc); + // Dispose the temporary managed instance - if (exc) { - ERR_PRINT("Exception thrown from method Dispose() of temporary MonoObject:"); - GDMonoUtils::debug_print_unhandled_exception(exc); - } + MonoException *exc = nullptr; + GDMonoUtils::dispose(tmp_object, &exc); - GDMonoUtils::free_gchandle(tmp_pinned_gchandle); - tmp_object = NULL; + if (exc) { + ERR_PRINT("Exception thrown from method Dispose() of temporary MonoObject:"); + GDMonoUtils::debug_print_unhandled_exception(exc); + } - if (tmp_native && !base_ref) { - Node *node = Object::cast_to<Node>(tmp_native); - if (node && node->is_inside_tree()) { - ERR_PRINT("Temporary instance was added to the scene tree."); - } else { - memdelete(tmp_native); + GDMonoUtils::free_gchandle(tmp_pinned_gchandle); + tmp_object = nullptr; + + if (tmp_native && !base_ref) { + Node *node = Object::cast_to<Node>(tmp_native); + if (node && node->is_inside_tree()) { + ERR_PRINT("Temporary instance was added to the scene tree."); + } else { + memdelete(tmp_native); + } } } +#endif } - placeholder_fallback_enabled = false; +#ifdef TOOLS_ENABLED + if (is_editor) { + placeholder_fallback_enabled = false; - if (placeholders.size()) { - // Update placeholders if any - Map<StringName, Variant> values; - List<PropertyInfo> propnames; - _update_exports_values(values, propnames); + if (placeholders.size()) { + // Update placeholders if any + Map<StringName, Variant> values; + List<PropertyInfo> propnames; + _update_exports_values(values, propnames); - for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { - E->get()->update(propnames, values); + for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { + E->get()->update(propnames, values); + } } } +#endif return changed; -#endif - return false; } void CSharpScript::load_script_signals(GDMonoClass *p_class, GDMonoClass *p_native_class) { - // no need to load the script's signals more than once if (!signals_invalidated) { return; @@ -2608,9 +2557,9 @@ void CSharpScript::load_script_signals(GDMonoClass *p_class, GDMonoClass *p_nati List<StringName> found_event_signals; - void *iter = NULL; - MonoEvent *raw_event = NULL; - while ((raw_event = mono_class_get_events(top->get_mono_ptr(), &iter)) != NULL) { + void *iter = nullptr; + MonoEvent *raw_event = nullptr; + while ((raw_event = mono_class_get_events(top->get_mono_ptr(), &iter)) != nullptr) { MonoCustomAttrInfo *event_attrs = mono_custom_attrs_from_event(top->get_mono_ptr(), raw_event); if (event_attrs) { if (mono_custom_attrs_has_attr(event_attrs, CACHED_CLASS(SignalAttribute)->get_mono_ptr())) { @@ -2678,13 +2627,11 @@ bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoMethod *p_delegate_in return true; } -#ifdef TOOLS_ENABLED /** * Returns false if there was an error, otherwise true. * If there was an error, r_prop_info and r_exported are not assigned any value. */ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported) { - GD_MONO_ASSERT_THREAD_ATTACHED; // Goddammit, C++. All I wanted was some nested functions. @@ -2692,8 +2639,10 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect (m_member->get_enclosing_class()->get_full_name() + "." + (String)m_member->get_name()) if (p_member->is_static()) { +#ifdef TOOLS_ENABLED if (p_member->has_attribute(CACHED_CLASS(ExportAttribute))) ERR_PRINT("Cannot export member because it is static: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); +#endif return false; } @@ -2715,13 +2664,17 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect if (p_member->get_member_type() == IMonoClassMember::MEMBER_TYPE_PROPERTY) { GDMonoProperty *property = static_cast<GDMonoProperty *>(p_member); if (!property->has_getter()) { +#ifdef TOOLS_ENABLED if (exported) ERR_PRINT("Read-only property cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); +#endif return false; } if (!property->has_setter()) { +#ifdef TOOLS_ENABLED if (exported) ERR_PRINT("Write-only property (without getter) cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); +#endif return false; } } @@ -2741,10 +2694,13 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect String hint_string; if (variant_type == Variant::NIL && !nil_is_variant) { +#ifdef TOOLS_ENABLED ERR_PRINT("Unknown exported member type: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); +#endif return false; } +#ifdef TOOLS_ENABLED int hint_res = _try_get_member_export_hint(p_member, type, variant_type, /* allow_generics: */ true, hint, hint_string); ERR_FAIL_COND_V_MSG(hint_res == -1, false, @@ -2755,6 +2711,7 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)); hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr); } +#endif uint32_t prop_usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE; @@ -2771,8 +2728,8 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect #undef MEMBER_FULL_QUALIFIED_NAME } +#ifdef TOOLS_ENABLED int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string) { - if (p_variant_type == Variant::NIL) { // System.Object (Variant) return 1; @@ -2810,7 +2767,7 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage // Instead of using mono_field_get_value_object, we can do this without boxing. Check the // internal mono functions: ves_icall_System_Enum_GetEnumValuesAndNames and the get_enum_field. - MonoObject *val_obj = mono_field_get_value_object(mono_domain_get(), field, NULL); + MonoObject *val_obj = mono_field_get_value_object(mono_domain_get(), field, nullptr); ERR_FAIL_NULL_V_MSG(val_obj, -1, "Failed to get '" + enum_field_name + "' constant enum value."); @@ -2834,7 +2791,7 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage } } else if (p_variant_type == Variant::OBJECT && CACHED_CLASS(GodotResource)->is_assignable_from(p_type.type_class)) { GDMonoClass *field_native_class = GDMonoUtils::get_class_native_base(p_type.type_class); - CRASH_COND(field_native_class == NULL); + CRASH_COND(field_native_class == nullptr); r_hint = PROPERTY_HINT_RESOURCE_TYPE; r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class)); @@ -2872,18 +2829,16 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage #endif void CSharpScript::_clear() { - tool = false; valid = false; - base = NULL; - native = NULL; - script_class = NULL; + base = nullptr; + native = nullptr; + script_class = nullptr; } Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - - if (unlikely(GDMono::get_singleton() == NULL)) { + if (unlikely(GDMono::get_singleton() == nullptr)) { // Probably not the best error but eh. r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; return Variant(); @@ -2897,7 +2852,7 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i GDMonoMethod *method = top->get_method(p_method, p_argcount); if (method && method->is_static()) { - MonoObject *result = method->invoke(NULL, p_args); + MonoObject *result = method->invoke(nullptr, p_args); if (result) { return GDMonoMarshal::mono_object_to_variant(result); @@ -2914,7 +2869,6 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i } void CSharpScript::_resource_path_changed() { - String path = get_path(); if (!path.empty()) { @@ -2923,9 +2877,7 @@ void CSharpScript::_resource_path_changed() { } bool CSharpScript::_get(const StringName &p_name, Variant &r_ret) const { - if (p_name == CSharpLanguage::singleton->string_names._script_source) { - r_ret = get_source_code(); return true; } @@ -2934,9 +2886,7 @@ bool CSharpScript::_get(const StringName &p_name, Variant &r_ret) const { } bool CSharpScript::_set(const StringName &p_name, const Variant &p_value) { - if (p_name == CSharpLanguage::singleton->string_names._script_source) { - set_source_code(p_value); reload(); return true; @@ -2946,20 +2896,17 @@ bool CSharpScript::_set(const StringName &p_name, const Variant &p_value) { } void CSharpScript::_get_property_list(List<PropertyInfo> *p_properties) const { - p_properties->push_back(PropertyInfo(Variant::STRING, CSharpLanguage::singleton->string_names._script_source, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); } void CSharpScript::_bind_methods() { - ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &CSharpScript::_new, MethodInfo("new")); } Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native) { - // This method should not fail, only assertions allowed - CRASH_COND(p_class == NULL); + CRASH_COND(p_class == nullptr); // TODO OPTIMIZE: Cache the 'CSharpScript' associated with this 'p_class' instead of allocating a new one every time Ref<CSharpScript> script = memnew(CSharpScript); @@ -2970,16 +2917,15 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GD } void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native) { - // This method should not fail, only assertions allowed - CRASH_COND(p_class == NULL); + CRASH_COND(p_class == nullptr); p_script->name = p_class->get_name(); p_script->script_class = p_class; p_script->native = p_native; - CRASH_COND(p_script->native == NULL); + CRASH_COND(p_script->native == nullptr); GDMonoClass *base = p_script->script_class->get_parent_class(); @@ -3034,7 +2980,6 @@ void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMon } bool CSharpScript::can_instance() const { - #ifdef TOOLS_ENABLED bool extra_cond = tool || ScriptServer::is_scripting_enabled(); #else @@ -3045,12 +2990,12 @@ bool CSharpScript::can_instance() const { // For tool scripts, this will never fire if the class is not found. That's because we // don't know if it's a tool script if we can't find the class to access the attributes. if (extra_cond && !script_class) { - if (GDMono::get_singleton()->get_project_assembly() == NULL) { + if (GDMono::get_singleton()->get_project_assembly() == nullptr) { // The project assembly is not loaded - ERR_FAIL_V_MSG(NULL, "Cannot instance script because the project assembly is not loaded. Script: '" + get_path() + "'."); + ERR_FAIL_V_MSG(false, "Cannot instance script because the project assembly is not loaded. Script: '" + get_path() + "'."); } else { // The project assembly is loaded, but the class could not found - ERR_FAIL_V_MSG(NULL, "Cannot instance script because the class '" + name + "' could not be found. Script: '" + get_path() + "'."); + ERR_FAIL_V_MSG(false, "Cannot instance script because the class '" + name + "' could not be found. Script: '" + get_path() + "'."); } } @@ -3058,7 +3003,6 @@ bool CSharpScript::can_instance() const { } StringName CSharpScript::get_instance_base_type() const { - if (native) return native->get_name(); else @@ -3066,20 +3010,19 @@ StringName CSharpScript::get_instance_base_type() const { } CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error) { - GD_MONO_ASSERT_THREAD_ATTACHED; /* STEP 1, CREATE */ // Search the constructor first, to fail with an error if it's not found before allocating anything else. GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), p_argcount); - if (ctor == NULL) { - ERR_FAIL_COND_V_MSG(p_argcount == 0, NULL, + if (ctor == nullptr) { + ERR_FAIL_COND_V_MSG(p_argcount == 0, nullptr, "Cannot create script instance. The class '" + script_class->get_full_name() + "' does not define a parameterless constructor." + (get_path().empty() ? String() : " Path: '" + get_path() + "'.")); - ERR_FAIL_V_MSG(NULL, "Constructor not found."); + ERR_FAIL_V_MSG(nullptr, "Constructor not found."); } Ref<Reference> ref; @@ -3091,13 +3034,13 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg // If the object had a script instance binding, dispose it before adding the CSharpInstance if (p_owner->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index())) { void *data = p_owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); - CRASH_COND(data == NULL); + CRASH_COND(data == nullptr); CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); if (script_binding.inited && !script_binding.gchandle.is_released()) { MonoObject *mono_object = script_binding.gchandle.get_target(); if (mono_object) { - MonoException *exc = NULL; + MonoException *exc = nullptr; GDMonoUtils::dispose(mono_object, &exc); if (exc) { @@ -3122,15 +3065,15 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg if (!mono_object) { // Important to clear this before destroying the script instance here instance->script = Ref<CSharpScript>(); - instance->owner = NULL; + instance->owner = nullptr; bool die = instance->_unreference_owner_unsafe(); // Not ok for the owner to die here. If there is a situation where this can happen, it will be considered a bug. CRASH_COND(die == true); - p_owner->set_script_instance(NULL); + p_owner->set_script_instance(nullptr); r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; - ERR_FAIL_V_MSG(NULL, "Failed to allocate memory for the object."); + ERR_FAIL_V_MSG(nullptr, "Failed to allocate memory for the object."); } // Tie managed to unmanaged @@ -3156,7 +3099,6 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg } Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (!valid) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); @@ -3176,7 +3118,7 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal ref = REF(r); } - CSharpInstance *instance = _create_instance(p_args, p_argcount, owner, r != NULL, r_error); + CSharpInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error); if (!instance) { if (ref.is_null()) { memdelete(owner); //no owner, sorry @@ -3192,7 +3134,6 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal } ScriptInstance *CSharpScript::instance_create(Object *p_this) { - #ifdef DEBUG_ENABLED CRASH_COND(!valid); #endif @@ -3205,47 +3146,42 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) { "Script inherits from native type '" + String(native_name) + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'"); } - ERR_FAIL_V_MSG(NULL, "Script inherits from native type '" + String(native_name) + - "', so it can't be instanced in object of type: '" + p_this->get_class() + "'."); + ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(native_name) + + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'."); } } GD_MONO_SCOPE_THREAD_ATTACH; Callable::CallError unchecked_error; - return _create_instance(NULL, 0, p_this, Object::cast_to<Reference>(p_this) != NULL, unchecked_error); + return _create_instance(nullptr, 0, p_this, Object::cast_to<Reference>(p_this) != nullptr, unchecked_error); } PlaceHolderScriptInstance *CSharpScript::placeholder_instance_create(Object *p_this) { - #ifdef TOOLS_ENABLED PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(CSharpLanguage::get_singleton(), Ref<Script>(this), p_this)); placeholders.insert(si); _update_exports(); return si; #else - return NULL; + return nullptr; #endif } bool CSharpScript::instance_has(const Object *p_this) const { - MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex); return instances.has((Object *)p_this); } bool CSharpScript::has_source_code() const { - return !source.empty(); } String CSharpScript::get_source_code() const { - return source; } void CSharpScript::set_source_code(const String &p_code) { - if (source == p_code) return; source = p_code; @@ -3255,7 +3191,6 @@ void CSharpScript::set_source_code(const String &p_code) { } void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const { - if (!script_class) return; @@ -3269,7 +3204,6 @@ void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const { } bool CSharpScript::has_method(const StringName &p_method) const { - if (!script_class) return false; @@ -3279,7 +3213,6 @@ bool CSharpScript::has_method(const StringName &p_method) const { } MethodInfo CSharpScript::get_method_info(const StringName &p_method) const { - if (!script_class) return MethodInfo(); @@ -3300,7 +3233,6 @@ MethodInfo CSharpScript::get_method_info(const StringName &p_method) const { } Error CSharpScript::reload(bool p_keep_state) { - bool has_instances; { MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex); @@ -3322,9 +3254,7 @@ Error CSharpScript::reload(bool p_keep_state) { ERR_FAIL_NULL_V(namespace_, ERR_BUG); ERR_FAIL_NULL_V(class_name, ERR_BUG); GDMonoClass *klass = project_assembly->get_class(namespace_->operator String(), class_name->operator String()); - if (klass) { - bool obj_type = CACHED_CLASS(GodotObject)->is_assignable_from(klass); - ERR_FAIL_COND_V(!obj_type, ERR_BUG); + if (klass && CACHED_CLASS(GodotObject)->is_assignable_from(klass)) { script_class = klass; } } else { @@ -3332,7 +3262,7 @@ Error CSharpScript::reload(bool p_keep_state) { script_class = project_assembly->get_object_derived_class(name); } - valid = script_class != NULL; + valid = script_class != nullptr; if (script_class) { #ifdef DEBUG_ENABLED @@ -3354,7 +3284,7 @@ Error CSharpScript::reload(bool p_keep_state) { native = GDMonoUtils::get_class_native_base(script_class); - CRASH_COND(native == NULL); + CRASH_COND(native == nullptr); GDMonoClass *base_class = script_class->get_parent_class(); @@ -3462,12 +3392,10 @@ Error CSharpScript::reload(bool p_keep_state) { } ScriptLanguage *CSharpScript::get_language() const { - return CSharpLanguage::get_singleton(); } bool CSharpScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { - #ifdef TOOLS_ENABLED const Map<StringName, Variant>::Element *E = exported_members_defval_cache.find(p_property); @@ -3485,7 +3413,6 @@ bool CSharpScript::get_property_default_value(const StringName &p_property, Vari } void CSharpScript::update_exports() { - #ifdef TOOLS_ENABLED _update_exports(); #endif @@ -3496,7 +3423,6 @@ bool CSharpScript::has_script_signal(const StringName &p_signal) const { } void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const { - for (const Map<StringName, Vector<SignalParameter>>::Element *E = _signals.front(); E; E = E->next()) { MethodInfo mi; mi.name = E->key(); @@ -3535,27 +3461,40 @@ void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const { } } -Ref<Script> CSharpScript::get_base_script() const { +bool CSharpScript::inherits_script(const Ref<Script> &p_script) const { + Ref<CSharpScript> cs = p_script; + if (cs.is_null()) { + return false; + } + + if (script_class == nullptr || cs->script_class == nullptr) { + return false; + } + if (script_class == cs->script_class) { + return true; + } + + return cs->script_class->is_assignable_from(script_class); +} + +Ref<Script> CSharpScript::get_base_script() const { // TODO search in metadata file once we have it, not important any way? return Ref<Script>(); } void CSharpScript::get_script_property_list(List<PropertyInfo> *p_list) const { - for (Map<StringName, PropertyInfo>::Element *E = member_info.front(); E; E = E->next()) { p_list->push_back(E->value()); } } int CSharpScript::get_member_line(const StringName &p_member) const { - // TODO omnisharp return -1; } MultiplayerAPI::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const { - if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) return MultiplayerAPI::RPC_MODE_REMOTE; if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) @@ -3627,7 +3566,6 @@ MultiplayerAPI::RPCMode CSharpScript::get_rset_mode(const StringName &p_variable } Error CSharpScript::load_source_code(const String &p_path) { - Error ferr = read_all_file_utf8(p_path, source); ERR_FAIL_COND_V_MSG(ferr != OK, ferr, @@ -3644,12 +3582,10 @@ Error CSharpScript::load_source_code(const String &p_path) { } StringName CSharpScript::get_script_name() const { - return name; } CSharpScript::CSharpScript() { - _clear(); _resource_path_changed(); @@ -3663,17 +3599,25 @@ CSharpScript::CSharpScript() { } CSharpScript::~CSharpScript() { - #ifdef DEBUG_ENABLED MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex); CSharpLanguage::get_singleton()->script_list.remove(&this->script_list); #endif } -/*************** RESOURCE ***************/ +void CSharpScript::get_members(Set<StringName> *p_members) { +#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) + if (p_members) { + for (Set<StringName>::Element *E = exported_members_names.front(); E; E = E->next()) { + p_members->insert(E->get()); + } + } +#endif +} -RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { +/*************** RESOURCE ***************/ +RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { if (r_error) *r_error = ERR_FILE_CANT_OPEN; @@ -3699,22 +3643,18 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p } void ResourceFormatLoaderCSharpScript::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("cs"); } bool ResourceFormatLoaderCSharpScript::handles_type(const String &p_type) const { - return p_type == "Script" || p_type == CSharpLanguage::get_singleton()->get_type(); } String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path) const { - return p_path.get_extension().to_lower() == "cs" ? CSharpLanguage::get_singleton()->get_type() : ""; } Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref<CSharpScript> sqscr = p_resource; ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); @@ -3758,19 +3698,16 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r } void ResourceFormatSaverCSharpScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (Object::cast_to<CSharpScript>(p_resource.ptr())) { p_extensions->push_back("cs"); } } bool ResourceFormatSaverCSharpScript::recognize(const RES &p_resource) const { - - return Object::cast_to<CSharpScript>(p_resource.ptr()) != NULL; + return Object::cast_to<CSharpScript>(p_resource.ptr()) != nullptr; } CSharpLanguage::StringNameCache::StringNameCache() { - _signal_callback = StaticCString::create("_signal_callback"); _set = StaticCString::create("_set"); _get = StaticCString::create("_get"); diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 53b4aa6c20..0bf08ceafd 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -66,7 +66,6 @@ TScriptInstance *cast_script_instance(ScriptInstance *p_inst) { #define CAST_CSHARP_INSTANCE(m_inst) (cast_script_instance<CSharpInstance, CSharpLanguage>(m_inst)) class CSharpScript : public Script { - GDCLASS(CSharpScript, Script); public: @@ -77,8 +76,8 @@ public: }; struct EventSignal { - GDMonoField *field = NULL; - GDMonoMethod *invoke_method = NULL; + GDMonoField *field = nullptr; + GDMonoMethod *invoke_method = nullptr; Vector<SignalParameter> parameters; }; @@ -139,6 +138,10 @@ private: virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); #endif +#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) + Set<StringName> exported_members_names; +#endif + Map<StringName, PropertyInfo> member_info; void _clear(); @@ -147,8 +150,9 @@ private: bool _get_signal(GDMonoClass *p_class, GDMonoMethod *p_delegate_invoke, Vector<SignalParameter> ¶ms); bool _update_exports(); -#ifdef TOOLS_ENABLED + bool _get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported); +#ifdef TOOLS_ENABLED static int _try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string); #endif @@ -191,9 +195,13 @@ public: virtual void get_script_property_list(List<PropertyInfo> *p_list) const; virtual void update_exports(); + void get_members(Set<StringName> *p_members) override; + virtual bool is_tool() const { return tool; } virtual bool is_valid() const { return valid; } + bool inherits_script(const Ref<Script> &p_script) const; + virtual Ref<Script> get_base_script() const; virtual ScriptLanguage *get_language() const; @@ -228,7 +236,6 @@ public: }; class CSharpInstance : public ScriptInstance { - friend class CSharpScript; friend class CSharpLanguage; @@ -323,17 +330,13 @@ public: }; struct CSharpScriptBinding { - bool inited; + bool inited = false; StringName type_name; - GDMonoClass *wrapper_class; + GDMonoClass *wrapper_class = nullptr; MonoGCHandleData gchandle; - Object *owner; + Object *owner = nullptr; - CSharpScriptBinding() : - inited(false), - wrapper_class(NULL), - owner(NULL) { - } + CSharpScriptBinding() {} }; class ManagedCallableMiddleman : public Object { @@ -341,7 +344,6 @@ class ManagedCallableMiddleman : public Object { }; class CSharpLanguage : public ScriptLanguage { - friend class CSharpScript; friend class CSharpInstance; @@ -368,7 +370,6 @@ class CSharpLanguage : public ScriptLanguage { ManagedCallableMiddleman *managed_callable_middleman = memnew(ManagedCallableMiddleman); struct StringNameCache { - StringName _signal_callback; StringName _set; StringName _get; @@ -530,7 +531,7 @@ public: class ResourceFormatLoaderCSharpScript : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs index 6015cb22b6..c2549b4ad5 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs @@ -2,7 +2,6 @@ using System; using System.IO; using System.Security; using Microsoft.Build.Framework; -using GodotTools.Core; namespace GodotTools.BuildLogger { @@ -183,4 +182,17 @@ namespace GodotTools.BuildLogger private StreamWriter issuesStreamWriter; private int indent; } + + internal static class StringExtensions + { + public static string CsvEscape(this string value, char delimiter = ',') + { + bool hasSpecialChar = value.IndexOfAny(new[] { '\"', '\n', '\r', delimiter }) != -1; + + if (hasSpecialChar) + return "\"" + value.Replace("\"", "\"\"") + "\""; + + return value; + } + } } diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj index 8fdd485209..0afec970c6 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj @@ -1,60 +1,10 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProjectGuid>{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}</ProjectGuid> - <OutputType>Library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>GodotTools.BuildLogger</RootNamespace> - <AssemblyName>GodotTools.BuildLogger</AssemblyName> - <TargetFrameworkVersion>v4.7</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <LangVersion>7</LangVersion> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>7.2</LangVersion> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> - <DebugSymbols>true</DebugSymbols> - <DebugType>portable</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> - <DebugType>portable</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <ItemGroup> - <Reference Include="Microsoft.Build.Framework" /> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="System.Data" /> - <Reference Include="System.Xml" /> - </ItemGroup> - <ItemGroup> - <Compile Include="GodotBuildLogger.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - </ItemGroup> <ItemGroup> - <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj"> - <Project>{639e48bd-44e5-4091-8edd-22d36dc0768d}</Project> - <Name>GodotTools.Core</Name> - </ProjectReference> + <PackageReference Include="Microsoft.Build.Framework" Version="16.5.0" /> </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/Properties/AssemblyInfo.cs b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/Properties/AssemblyInfo.cs deleted file mode 100644 index 4374f21cfa..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("GodotTools.BuildLogger")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Godot Engine contributors")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("6CE9A984-37B1-4F8A-8FE9-609F05F071B3")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs b/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs new file mode 100644 index 0000000000..85760a3705 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs @@ -0,0 +1,27 @@ +using System.IO; + +namespace GodotTools.Core +{ + public static class FileUtils + { + public static void SaveBackupCopy(string filePath) + { + string backupPathBase = filePath + ".old"; + string backupPath = backupPathBase; + + const int maxAttempts = 5; + int attempt = 1; + + while (File.Exists(backupPath) && attempt <= maxAttempts) + { + backupPath = backupPathBase + "." + (attempt); + attempt++; + } + + if (attempt > maxAttempts + 1) + return; + + File.Copy(filePath, backupPath, overwrite: true); + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj index 2c35ef540a..d6d8962f90 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj @@ -1,39 +1,7 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid> - <OutputType>Library</OutputType> - <RootNamespace>GodotTools.Core</RootNamespace> - <AssemblyName>GodotTools.Core</AssemblyName> - <TargetFrameworkVersion>v4.7</TargetFrameworkVersion> - <LangVersion>7</LangVersion> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>7.2</LangVersion> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug</OutputPath> - <DefineConstants>DEBUG;</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <ConsolePause>false</ConsolePause> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <Optimize>true</Optimize> - <OutputPath>bin\Release</OutputPath> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <ConsolePause>false</ConsolePause> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - </ItemGroup> - <ItemGroup> - <Compile Include="ProcessExtensions.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="StringExtensions.cs" /> - </ItemGroup> - <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/Properties/AssemblyInfo.cs b/modules/mono/editor/GodotTools/GodotTools.Core/Properties/AssemblyInfo.cs deleted file mode 100644 index 699ae6e741..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.Core/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("GodotTools.Core")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Godot Engine contributors")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs index 326c49f096..7ab5c5fc59 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs @@ -33,23 +33,13 @@ namespace GodotTools.Core return rooted ? Path.DirectorySeparatorChar + path : path; } - private static readonly string driveRoot = Path.GetPathRoot(Environment.CurrentDirectory); + private static readonly string DriveRoot = Path.GetPathRoot(Environment.CurrentDirectory); public static bool IsAbsolutePath(this string path) { return path.StartsWith("/", StringComparison.Ordinal) || path.StartsWith("\\", StringComparison.Ordinal) || - path.StartsWith(driveRoot, StringComparison.Ordinal); - } - - public static string CsvEscape(this string value, char delimiter = ',') - { - bool hasSpecialChar = value.IndexOfAny(new char[] { '\"', '\n', '\r', delimiter }) != -1; - - if (hasSpecialChar) - return "\"" + value.Replace("\"", "\"\"") + "\""; - - return value; + path.StartsWith(DriveRoot, StringComparison.Ordinal); } public static string ToSafeDirName(this string dirName, bool allowDirSeparator) diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/ConsoleLogger.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/ConsoleLogger.cs deleted file mode 100644 index 7a2ff2ca56..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/ConsoleLogger.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; - -namespace GodotTools.IdeConnection -{ - public class ConsoleLogger : ILogger - { - public void LogDebug(string message) - { - Console.WriteLine("DEBUG: " + message); - } - - public void LogInfo(string message) - { - Console.WriteLine("INFO: " + message); - } - - public void LogWarning(string message) - { - Console.WriteLine("WARN: " + message); - } - - public void LogError(string message) - { - Console.WriteLine("ERROR: " + message); - } - - public void LogError(string message, Exception e) - { - Console.WriteLine("EXCEPTION: " + message); - Console.WriteLine(e); - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeBase.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeBase.cs deleted file mode 100644 index be89638241..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeBase.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using Path = System.IO.Path; - -namespace GodotTools.IdeConnection -{ - public class GodotIdeBase : IDisposable - { - private ILogger logger; - - public ILogger Logger - { - get => logger ?? (logger = new ConsoleLogger()); - set => logger = value; - } - - private readonly string projectMetadataDir; - - protected const string MetaFileName = "ide_server_meta.txt"; - protected string MetaFilePath => Path.Combine(projectMetadataDir, MetaFileName); - - private GodotIdeConnection connection; - protected readonly object ConnectionLock = new object(); - - public bool IsDisposed { get; private set; } = false; - - public bool IsConnected => connection != null && !connection.IsDisposed && connection.IsConnected; - - public event Action Connected - { - add - { - if (connection != null && !connection.IsDisposed) - connection.Connected += value; - } - remove - { - if (connection != null && !connection.IsDisposed) - connection.Connected -= value; - } - } - - protected GodotIdeConnection Connection - { - get => connection; - set - { - connection?.Dispose(); - connection = value; - } - } - - protected GodotIdeBase(string projectMetadataDir) - { - this.projectMetadataDir = projectMetadataDir; - } - - protected void DisposeConnection() - { - lock (ConnectionLock) - { - connection?.Dispose(); - } - } - - ~GodotIdeBase() - { - Dispose(disposing: false); - } - - public void Dispose() - { - if (IsDisposed) - return; - - lock (ConnectionLock) - { - if (IsDisposed) // lock may not be fair - return; - IsDisposed = true; - } - - Dispose(disposing: true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - connection?.Dispose(); - } - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeClient.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeClient.cs deleted file mode 100644 index 2bf3b83c75..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeClient.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Threading; - -namespace GodotTools.IdeConnection -{ - public abstract class GodotIdeClient : GodotIdeBase - { - protected GodotIdeMetadata GodotIdeMetadata; - - private readonly FileSystemWatcher fsWatcher; - - protected GodotIdeClient(string projectMetadataDir) : base(projectMetadataDir) - { - messageHandlers = InitializeMessageHandlers(); - - // FileSystemWatcher requires an existing directory - if (!File.Exists(projectMetadataDir)) - Directory.CreateDirectory(projectMetadataDir); - - fsWatcher = new FileSystemWatcher(projectMetadataDir, MetaFileName); - } - - private void OnMetaFileChanged(object sender, FileSystemEventArgs e) - { - if (IsDisposed) - return; - - lock (ConnectionLock) - { - if (IsDisposed) - return; - - if (!File.Exists(MetaFilePath)) - return; - - var metadata = ReadMetadataFile(); - - if (metadata != null && metadata != GodotIdeMetadata) - { - GodotIdeMetadata = metadata.Value; - ConnectToServer(); - } - } - } - - private void OnMetaFileDeleted(object sender, FileSystemEventArgs e) - { - if (IsDisposed) - return; - - if (IsConnected) - DisposeConnection(); - - // The file may have been re-created - - lock (ConnectionLock) - { - if (IsDisposed) - return; - - if (IsConnected || !File.Exists(MetaFilePath)) - return; - - var metadata = ReadMetadataFile(); - - if (metadata != null) - { - GodotIdeMetadata = metadata.Value; - ConnectToServer(); - } - } - } - - private GodotIdeMetadata? ReadMetadataFile() - { - using (var reader = File.OpenText(MetaFilePath)) - { - string portStr = reader.ReadLine(); - - if (portStr == null) - return null; - - string editorExecutablePath = reader.ReadLine(); - - if (editorExecutablePath == null) - return null; - - if (!int.TryParse(portStr, out int port)) - return null; - - return new GodotIdeMetadata(port, editorExecutablePath); - } - } - - private void ConnectToServer() - { - var tcpClient = new TcpClient(); - - Connection = new GodotIdeConnectionClient(tcpClient, HandleMessage); - Connection.Logger = Logger; - - try - { - Logger.LogInfo("Connecting to Godot Ide Server"); - - tcpClient.Connect(IPAddress.Loopback, GodotIdeMetadata.Port); - - Logger.LogInfo("Connection open with Godot Ide Server"); - - var clientThread = new Thread(Connection.Start) - { - IsBackground = true, - Name = "Godot Ide Connection Client" - }; - clientThread.Start(); - } - catch (SocketException e) - { - if (e.SocketErrorCode == SocketError.ConnectionRefused) - Logger.LogError("The connection to the Godot Ide Server was refused"); - else - throw; - } - } - - public void Start() - { - Logger.LogInfo("Starting Godot Ide Client"); - - fsWatcher.Changed += OnMetaFileChanged; - fsWatcher.Deleted += OnMetaFileDeleted; - fsWatcher.EnableRaisingEvents = true; - - lock (ConnectionLock) - { - if (IsDisposed) - return; - - if (!File.Exists(MetaFilePath)) - { - Logger.LogInfo("There is no Godot Ide Server running"); - return; - } - - var metadata = ReadMetadataFile(); - - if (metadata != null) - { - GodotIdeMetadata = metadata.Value; - ConnectToServer(); - } - else - { - Logger.LogError("Failed to read Godot Ide metadata file"); - } - } - } - - public bool WriteMessage(Message message) - { - return Connection.WriteMessage(message); - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - if (disposing) - { - fsWatcher?.Dispose(); - } - } - - protected virtual bool HandleMessage(Message message) - { - if (messageHandlers.TryGetValue(message.Id, out var action)) - { - action(message.Arguments); - return true; - } - - return false; - } - - private readonly Dictionary<string, Action<string[]>> messageHandlers; - - private Dictionary<string, Action<string[]>> InitializeMessageHandlers() - { - return new Dictionary<string, Action<string[]>> - { - ["OpenFile"] = args => - { - switch (args.Length) - { - case 1: - OpenFile(file: args[0]); - return; - case 2: - OpenFile(file: args[0], line: int.Parse(args[1])); - return; - case 3: - OpenFile(file: args[0], line: int.Parse(args[1]), column: int.Parse(args[2])); - return; - default: - throw new ArgumentException(); - } - } - }; - } - - protected abstract void OpenFile(string file); - protected abstract void OpenFile(string file, int line); - protected abstract void OpenFile(string file, int line, int column); - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnection.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnection.cs deleted file mode 100644 index 6441be8d6e..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnection.cs +++ /dev/null @@ -1,207 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Net.Sockets; -using System.Text; - -namespace GodotTools.IdeConnection -{ - public abstract class GodotIdeConnection : IDisposable - { - protected const string Version = "1.0"; - - protected static readonly string ClientHandshake = $"Godot Ide Client Version {Version}"; - protected static readonly string ServerHandshake = $"Godot Ide Server Version {Version}"; - - private const int ClientWriteTimeout = 8000; - private readonly TcpClient tcpClient; - - private TextReader clientReader; - private TextWriter clientWriter; - - private readonly object writeLock = new object(); - - private readonly Func<Message, bool> messageHandler; - - public event Action Connected; - - private ILogger logger; - - public ILogger Logger - { - get => logger ?? (logger = new ConsoleLogger()); - set => logger = value; - } - - public bool IsDisposed { get; private set; } = false; - - public bool IsConnected => tcpClient.Client != null && tcpClient.Client.Connected; - - protected GodotIdeConnection(TcpClient tcpClient, Func<Message, bool> messageHandler) - { - this.tcpClient = tcpClient; - this.messageHandler = messageHandler; - } - - public void Start() - { - try - { - if (!StartConnection()) - return; - - string messageLine; - while ((messageLine = ReadLine()) != null) - { - if (!MessageParser.TryParse(messageLine, out Message msg)) - { - Logger.LogError($"Received message with invalid format: {messageLine}"); - continue; - } - - Logger.LogDebug($"Received message: {msg}"); - - if (msg.Id == "close") - { - Logger.LogInfo("Closing connection"); - return; - } - - try - { - try - { - Debug.Assert(messageHandler != null); - - if (!messageHandler(msg)) - Logger.LogError($"Received unknown message: {msg}"); - } - catch (Exception e) - { - Logger.LogError($"Message handler for '{msg}' failed with exception", e); - } - } - catch (Exception e) - { - Logger.LogError($"Exception thrown from message handler. Message: {msg}", e); - } - } - } - catch (Exception e) - { - Logger.LogError($"Unhandled exception in the Godot Ide Connection thread", e); - } - finally - { - Dispose(); - } - } - - private bool StartConnection() - { - NetworkStream clientStream = tcpClient.GetStream(); - - clientReader = new StreamReader(clientStream, Encoding.UTF8); - - lock (writeLock) - clientWriter = new StreamWriter(clientStream, Encoding.UTF8); - - clientStream.WriteTimeout = ClientWriteTimeout; - - if (!WriteHandshake()) - { - Logger.LogError("Could not write handshake"); - return false; - } - - if (!IsValidResponseHandshake(ReadLine())) - { - Logger.LogError("Received invalid handshake"); - return false; - } - - Connected?.Invoke(); - - Logger.LogInfo("Godot Ide connection started"); - - return true; - } - - private string ReadLine() - { - try - { - return clientReader?.ReadLine(); - } - catch (Exception e) - { - if (IsDisposed) - { - var se = e as SocketException ?? e.InnerException as SocketException; - if (se != null && se.SocketErrorCode == SocketError.Interrupted) - return null; - } - - throw; - } - } - - public bool WriteMessage(Message message) - { - Logger.LogDebug($"Sending message {message}"); - - var messageComposer = new MessageComposer(); - - messageComposer.AddArgument(message.Id); - foreach (string argument in message.Arguments) - messageComposer.AddArgument(argument); - - return WriteLine(messageComposer.ToString()); - } - - protected bool WriteLine(string text) - { - if (clientWriter == null || IsDisposed || !IsConnected) - return false; - - lock (writeLock) - { - try - { - clientWriter.WriteLine(text); - clientWriter.Flush(); - } - catch (Exception e) - { - if (!IsDisposed) - { - var se = e as SocketException ?? e.InnerException as SocketException; - if (se != null && se.SocketErrorCode == SocketError.Shutdown) - Logger.LogInfo("Client disconnected ungracefully"); - else - Logger.LogError("Exception thrown when trying to write to client", e); - - Dispose(); - } - } - } - - return true; - } - - protected abstract bool WriteHandshake(); - protected abstract bool IsValidResponseHandshake(string handshakeLine); - - public void Dispose() - { - if (IsDisposed) - return; - - IsDisposed = true; - - clientReader?.Dispose(); - clientWriter?.Dispose(); - ((IDisposable)tcpClient)?.Dispose(); - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnectionClient.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnectionClient.cs deleted file mode 100644 index 1b11a14358..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnectionClient.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace GodotTools.IdeConnection -{ - public class GodotIdeConnectionClient : GodotIdeConnection - { - public GodotIdeConnectionClient(TcpClient tcpClient, Func<Message, bool> messageHandler) - : base(tcpClient, messageHandler) - { - } - - protected override bool WriteHandshake() - { - return WriteLine(ClientHandshake); - } - - protected override bool IsValidResponseHandshake(string handshakeLine) - { - return handshakeLine == ServerHandshake; - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnectionServer.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnectionServer.cs deleted file mode 100644 index aa98dc7ca3..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeConnectionServer.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace GodotTools.IdeConnection -{ - public class GodotIdeConnectionServer : GodotIdeConnection - { - public GodotIdeConnectionServer(TcpClient tcpClient, Func<Message, bool> messageHandler) - : base(tcpClient, messageHandler) - { - } - - protected override bool WriteHandshake() - { - return WriteLine(ServerHandshake); - } - - protected override bool IsValidResponseHandshake(string handshakeLine) - { - return handshakeLine == ClientHandshake; - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotTools.IdeConnection.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotTools.IdeConnection.csproj deleted file mode 100644 index 8454535fba..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotTools.IdeConnection.csproj +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{92600954-25F0-4291-8E11-1FEE9FC4BE20}</ProjectGuid> - <OutputType>Library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>GodotTools.IdeConnection</RootNamespace> - <AssemblyName>GodotTools.IdeConnection</AssemblyName> - <TargetFrameworkVersion>v4.7</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <LangVersion>7</LangVersion> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> - <DebugSymbols>true</DebugSymbols> - <DebugType>portable</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> - <DebugType>portable</DebugType> - <Optimize>true</Optimize> - <OutputPath>bin\Release\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - </ItemGroup> - <ItemGroup> - <Compile Include="ConsoleLogger.cs" /> - <Compile Include="GodotIdeMetadata.cs" /> - <Compile Include="GodotIdeBase.cs" /> - <Compile Include="GodotIdeClient.cs" /> - <Compile Include="GodotIdeConnection.cs" /> - <Compile Include="GodotIdeConnectionClient.cs" /> - <Compile Include="GodotIdeConnectionServer.cs" /> - <Compile Include="ILogger.cs" /> - <Compile Include="Message.cs" /> - <Compile Include="MessageComposer.cs" /> - <Compile Include="MessageParser.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> -</Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/Message.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/Message.cs deleted file mode 100644 index f24d324ae3..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/Message.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Linq; - -namespace GodotTools.IdeConnection -{ - public struct Message - { - public string Id { get; set; } - public string[] Arguments { get; set; } - - public Message(string id, params string[] arguments) - { - Id = id; - Arguments = arguments; - } - - public override string ToString() - { - return $"(Id: '{Id}', Arguments: '{string.Join(",", Arguments)}')"; - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/MessageComposer.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/MessageComposer.cs deleted file mode 100644 index 30ffe7a06e..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/MessageComposer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Linq; -using System.Text; - -namespace GodotTools.IdeConnection -{ - public class MessageComposer - { - private readonly StringBuilder stringBuilder = new StringBuilder(); - - private static readonly char[] CharsToEscape = { '\\', '"' }; - - public void AddArgument(string argument) - { - AddArgument(argument, quoted: argument.Contains(",")); - } - - public void AddArgument(string argument, bool quoted) - { - if (stringBuilder.Length > 0) - stringBuilder.Append(','); - - if (quoted) - { - stringBuilder.Append('"'); - - foreach (char @char in argument) - { - if (CharsToEscape.Contains(@char)) - stringBuilder.Append('\\'); - stringBuilder.Append(@char); - } - - stringBuilder.Append('"'); - } - else - { - stringBuilder.Append(argument); - } - } - - public override string ToString() - { - return stringBuilder.ToString(); - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/MessageParser.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/MessageParser.cs deleted file mode 100644 index 4365d69989..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/MessageParser.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace GodotTools.IdeConnection -{ - public static class MessageParser - { - public static bool TryParse(string messageLine, out Message message) - { - var arguments = new List<string>(); - var stringBuilder = new StringBuilder(); - - bool expectingArgument = true; - - for (int i = 0; i < messageLine.Length; i++) - { - char @char = messageLine[i]; - - if (@char == ',') - { - if (expectingArgument) - arguments.Add(string.Empty); - - expectingArgument = true; - continue; - } - - bool quoted = false; - - if (messageLine[i] == '"') - { - quoted = true; - i++; - } - - while (i < messageLine.Length) - { - @char = messageLine[i]; - - if (quoted && @char == '"') - { - i++; - break; - } - - if (@char == '\\') - { - i++; - if (i < messageLine.Length) - break; - - stringBuilder.Append(messageLine[i]); - } - else if (!quoted && @char == ',') - { - break; // We don't increment the counter to allow the colon to be parsed after this - } - else - { - stringBuilder.Append(@char); - } - - i++; - } - - arguments.Add(stringBuilder.ToString()); - stringBuilder.Clear(); - - expectingArgument = false; - } - - if (arguments.Count == 0) - { - message = new Message(); - return false; - } - - message = new Message - { - Id = arguments[0], - Arguments = arguments.Skip(1).ToArray() - }; - - return true; - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/Properties/AssemblyInfo.cs b/modules/mono/editor/GodotTools/GodotTools.IdeConnection/Properties/AssemblyInfo.cs deleted file mode 100644 index 0806d02ca0..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("GodotTools.IdeConnection")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Godot Engine contributors")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("92600954-25F0-4291-8E11-1FEE9FC4BE20")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/ForwarderMessageHandler.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/ForwarderMessageHandler.cs new file mode 100644 index 0000000000..3cb6a6687e --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/ForwarderMessageHandler.cs @@ -0,0 +1,57 @@ +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using GodotTools.IdeMessaging.Utils; + +namespace GodotTools.IdeMessaging.CLI +{ + public class ForwarderMessageHandler : IMessageHandler + { + private readonly StreamWriter outputWriter; + private readonly SemaphoreSlim outputWriteSem = new SemaphoreSlim(1); + + public ForwarderMessageHandler(StreamWriter outputWriter) + { + this.outputWriter = outputWriter; + } + + public async Task<MessageContent> HandleRequest(Peer peer, string id, MessageContent content, ILogger logger) + { + await WriteRequestToOutput(id, content); + return new MessageContent(MessageStatus.RequestNotSupported, "null"); + } + + private async Task WriteRequestToOutput(string id, MessageContent content) + { + using (await outputWriteSem.UseAsync()) + { + await outputWriter.WriteLineAsync("======= Request ======="); + await outputWriter.WriteLineAsync(id); + await outputWriter.WriteLineAsync(content.Body.Count(c => c == '\n').ToString()); + await outputWriter.WriteLineAsync(content.Body); + await outputWriter.WriteLineAsync("======================="); + await outputWriter.FlushAsync(); + } + } + + public async Task WriteResponseToOutput(string id, MessageContent content) + { + using (await outputWriteSem.UseAsync()) + { + await outputWriter.WriteLineAsync("======= Response ======="); + await outputWriter.WriteLineAsync(id); + await outputWriter.WriteLineAsync(content.Body.Count(c => c == '\n').ToString()); + await outputWriter.WriteLineAsync(content.Body); + await outputWriter.WriteLineAsync("========================"); + await outputWriter.FlushAsync(); + } + } + + public async Task WriteLineToOutput(string eventName) + { + using (await outputWriteSem.UseAsync()) + await outputWriter.WriteLineAsync($"======= {eventName} ======="); + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj new file mode 100644 index 0000000000..ae78da27bc --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj @@ -0,0 +1,17 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <ProjectGuid>{B06C2951-C8E3-4F28-80B2-717CF327EB19}</ProjectGuid> + <OutputType>Exe</OutputType> + <TargetFramework>net472</TargetFramework> + <LangVersion>7.2</LangVersion> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> + </ItemGroup> +</Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs new file mode 100644 index 0000000000..99a55c471b --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using GodotTools.IdeMessaging.Requests; +using Newtonsoft.Json; + +namespace GodotTools.IdeMessaging.CLI +{ + internal static class Program + { + private static readonly ILogger Logger = new CustomLogger(); + + public static int Main(string[] args) + { + try + { + var mainTask = StartAsync(args, Console.OpenStandardInput(), Console.OpenStandardOutput()); + mainTask.Wait(); + return mainTask.Result; + } + catch (Exception ex) + { + Logger.LogError("Unhandled exception: ", ex); + return 1; + } + } + + private static async Task<int> StartAsync(string[] args, Stream inputStream, Stream outputStream) + { + var inputReader = new StreamReader(inputStream, Encoding.UTF8); + var outputWriter = new StreamWriter(outputStream, Encoding.UTF8); + + try + { + if (args.Length == 0) + { + Logger.LogError("Expected at least 1 argument"); + return 1; + } + + string godotProjectDir = args[0]; + + if (!Directory.Exists(godotProjectDir)) + { + Logger.LogError($"The specified Godot project directory does not exist: {godotProjectDir}"); + return 1; + } + + var forwarder = new ForwarderMessageHandler(outputWriter); + + using (var fwdClient = new Client("VisualStudioCode", godotProjectDir, forwarder, Logger)) + { + fwdClient.Start(); + + // ReSharper disable AccessToDisposedClosure + fwdClient.Connected += async () => await forwarder.WriteLineToOutput("Event=Connected"); + fwdClient.Disconnected += async () => await forwarder.WriteLineToOutput("Event=Disconnected"); + // ReSharper restore AccessToDisposedClosure + + // TODO: Await connected with timeout + + while (!fwdClient.IsDisposed) + { + string firstLine = await inputReader.ReadLineAsync(); + + if (firstLine == null || firstLine == "QUIT") + goto ExitMainLoop; + + string messageId = firstLine; + + string messageArgcLine = await inputReader.ReadLineAsync(); + + if (messageArgcLine == null) + { + Logger.LogInfo("EOF when expecting argument count"); + goto ExitMainLoop; + } + + if (!int.TryParse(messageArgcLine, out int messageArgc)) + { + Logger.LogError("Received invalid line for argument count: " + firstLine); + continue; + } + + var body = new StringBuilder(); + + for (int i = 0; i < messageArgc; i++) + { + string bodyLine = await inputReader.ReadLineAsync(); + + if (bodyLine == null) + { + Logger.LogInfo($"EOF when expecting body line #{i + 1}"); + goto ExitMainLoop; + } + + body.AppendLine(bodyLine); + } + + var response = await SendRequest(fwdClient, messageId, new MessageContent(MessageStatus.Ok, body.ToString())); + + if (response == null) + { + Logger.LogError($"Failed to write message to the server: {messageId}"); + } + else + { + var content = new MessageContent(response.Status, JsonConvert.SerializeObject(response)); + await forwarder.WriteResponseToOutput(messageId, content); + } + } + + ExitMainLoop: + + await forwarder.WriteLineToOutput("Event=Quit"); + } + + return 0; + } + catch (Exception e) + { + Logger.LogError("Unhandled exception", e); + return 1; + } + } + + private static async Task<Response> SendRequest(Client client, string id, MessageContent content) + { + var handlers = new Dictionary<string, Func<Task<Response>>> + { + [PlayRequest.Id] = async () => + { + var request = JsonConvert.DeserializeObject<PlayRequest>(content.Body); + return await client.SendRequest<PlayResponse>(request); + }, + [DebugPlayRequest.Id] = async () => + { + var request = JsonConvert.DeserializeObject<DebugPlayRequest>(content.Body); + return await client.SendRequest<DebugPlayResponse>(request); + }, + [ReloadScriptsRequest.Id] = async () => + { + var request = JsonConvert.DeserializeObject<ReloadScriptsRequest>(content.Body); + return await client.SendRequest<ReloadScriptsResponse>(request); + }, + [CodeCompletionRequest.Id] = async () => + { + var request = JsonConvert.DeserializeObject<CodeCompletionRequest>(content.Body); + return await client.SendRequest<CodeCompletionResponse>(request); + } + }; + + if (handlers.TryGetValue(id, out var handler)) + return await handler(); + + Console.WriteLine("INVALID REQUEST"); + return null; + } + + private class CustomLogger : ILogger + { + private static string ThisAppPath => Assembly.GetExecutingAssembly().Location; + private static string ThisAppPathWithoutExtension => Path.ChangeExtension(ThisAppPath, null); + + private static readonly string LogPath = $"{ThisAppPathWithoutExtension}.log"; + + private static StreamWriter NewWriter() => new StreamWriter(LogPath, append: true, encoding: Encoding.UTF8); + + private static void Log(StreamWriter writer, string message) + { + writer.WriteLine($"{DateTime.Now:HH:mm:ss.ffffff}: {message}"); + } + + public void LogDebug(string message) + { + using (var writer = NewWriter()) + { + Log(writer, "DEBUG: " + message); + } + } + + public void LogInfo(string message) + { + using (var writer = NewWriter()) + { + Log(writer, "INFO: " + message); + } + } + + public void LogWarning(string message) + { + using (var writer = NewWriter()) + { + Log(writer, "WARN: " + message); + } + } + + public void LogError(string message) + { + using (var writer = NewWriter()) + { + Log(writer, "ERROR: " + message); + } + } + + public void LogError(string message, Exception e) + { + using (var writer = NewWriter()) + { + Log(writer, "EXCEPTION: " + message + '\n' + e); + } + } + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs new file mode 100644 index 0000000000..d069651dd3 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs @@ -0,0 +1,332 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using Newtonsoft.Json; +using System.Threading; +using System.Threading.Tasks; +using GodotTools.IdeMessaging.Requests; +using GodotTools.IdeMessaging.Utils; + +namespace GodotTools.IdeMessaging +{ + // ReSharper disable once UnusedType.Global + public sealed class Client : IDisposable + { + private readonly ILogger logger; + + private readonly string identity; + + private string MetaFilePath { get; } + private GodotIdeMetadata godotIdeMetadata; + private readonly FileSystemWatcher fsWatcher; + + private readonly IMessageHandler messageHandler; + + private Peer peer; + private readonly SemaphoreSlim connectionSem = new SemaphoreSlim(1); + + private readonly Queue<NotifyAwaiter<bool>> clientConnectedAwaiters = new Queue<NotifyAwaiter<bool>>(); + private readonly Queue<NotifyAwaiter<bool>> clientDisconnectedAwaiters = new Queue<NotifyAwaiter<bool>>(); + + // ReSharper disable once UnusedMember.Global + public async Task<bool> AwaitConnected() + { + var awaiter = new NotifyAwaiter<bool>(); + clientConnectedAwaiters.Enqueue(awaiter); + return await awaiter; + } + + // ReSharper disable once UnusedMember.Global + public async Task<bool> AwaitDisconnected() + { + var awaiter = new NotifyAwaiter<bool>(); + clientDisconnectedAwaiters.Enqueue(awaiter); + return await awaiter; + } + + // ReSharper disable once MemberCanBePrivate.Global + public bool IsDisposed { get; private set; } + + // ReSharper disable once MemberCanBePrivate.Global + public bool IsConnected => peer != null && !peer.IsDisposed && peer.IsTcpClientConnected; + + // ReSharper disable once EventNeverSubscribedTo.Global + public event Action Connected + { + add + { + if (peer != null && !peer.IsDisposed) + peer.Connected += value; + } + remove + { + if (peer != null && !peer.IsDisposed) + peer.Connected -= value; + } + } + + // ReSharper disable once EventNeverSubscribedTo.Global + public event Action Disconnected + { + add + { + if (peer != null && !peer.IsDisposed) + peer.Disconnected += value; + } + remove + { + if (peer != null && !peer.IsDisposed) + peer.Disconnected -= value; + } + } + + ~Client() + { + Dispose(disposing: false); + } + + public async void Dispose() + { + if (IsDisposed) + return; + + using (await connectionSem.UseAsync()) + { + if (IsDisposed) // lock may not be fair + return; + IsDisposed = true; + } + + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + peer?.Dispose(); + fsWatcher?.Dispose(); + } + } + + public Client(string identity, string godotProjectDir, IMessageHandler messageHandler, ILogger logger) + { + this.identity = identity; + this.messageHandler = messageHandler; + this.logger = logger; + + string projectMetadataDir = Path.Combine(godotProjectDir, ".mono", "metadata"); + + MetaFilePath = Path.Combine(projectMetadataDir, GodotIdeMetadata.DefaultFileName); + + // FileSystemWatcher requires an existing directory + if (!File.Exists(projectMetadataDir)) + Directory.CreateDirectory(projectMetadataDir); + + fsWatcher = new FileSystemWatcher(projectMetadataDir, GodotIdeMetadata.DefaultFileName); + } + + private async void OnMetaFileChanged(object sender, FileSystemEventArgs e) + { + if (IsDisposed) + return; + + using (await connectionSem.UseAsync()) + { + if (IsDisposed) + return; + + if (!File.Exists(MetaFilePath)) + return; + + var metadata = ReadMetadataFile(); + + if (metadata != null && metadata != godotIdeMetadata) + { + godotIdeMetadata = metadata.Value; + _ = Task.Run(ConnectToServer); + } + } + } + + private async void OnMetaFileDeleted(object sender, FileSystemEventArgs e) + { + if (IsDisposed) + return; + + if (IsConnected) + { + using (await connectionSem.UseAsync()) + peer?.Dispose(); + } + + // The file may have been re-created + + using (await connectionSem.UseAsync()) + { + if (IsDisposed) + return; + + if (IsConnected || !File.Exists(MetaFilePath)) + return; + + var metadata = ReadMetadataFile(); + + if (metadata != null) + { + godotIdeMetadata = metadata.Value; + _ = Task.Run(ConnectToServer); + } + } + } + + private GodotIdeMetadata? ReadMetadataFile() + { + using (var reader = File.OpenText(MetaFilePath)) + { + string portStr = reader.ReadLine(); + + if (portStr == null) + return null; + + string editorExecutablePath = reader.ReadLine(); + + if (editorExecutablePath == null) + return null; + + if (!int.TryParse(portStr, out int port)) + return null; + + return new GodotIdeMetadata(port, editorExecutablePath); + } + } + + private async Task AcceptClient(TcpClient tcpClient) + { + logger.LogDebug("Accept client..."); + + using (peer = new Peer(tcpClient, new ClientHandshake(), messageHandler, logger)) + { + // ReSharper disable AccessToDisposedClosure + peer.Connected += () => + { + logger.LogInfo("Connection open with Ide Client"); + + while (clientConnectedAwaiters.Count > 0) + clientConnectedAwaiters.Dequeue().SetResult(true); + }; + + peer.Disconnected += () => + { + while (clientDisconnectedAwaiters.Count > 0) + clientDisconnectedAwaiters.Dequeue().SetResult(true); + }; + // ReSharper restore AccessToDisposedClosure + + try + { + if (!await peer.DoHandshake(identity)) + { + logger.LogError("Handshake failed"); + return; + } + } + catch (Exception e) + { + logger.LogError("Handshake failed with unhandled exception: ", e); + return; + } + + await peer.Process(); + + logger.LogInfo("Connection closed with Ide Client"); + } + } + + private async Task ConnectToServer() + { + var tcpClient = new TcpClient(); + + try + { + logger.LogInfo("Connecting to Godot Ide Server"); + + await tcpClient.ConnectAsync(IPAddress.Loopback, godotIdeMetadata.Port); + + logger.LogInfo("Connection open with Godot Ide Server"); + + await AcceptClient(tcpClient); + } + catch (SocketException e) + { + if (e.SocketErrorCode == SocketError.ConnectionRefused) + logger.LogError("The connection to the Godot Ide Server was refused"); + else + throw; + } + } + + // ReSharper disable once UnusedMember.Global + public async void Start() + { + fsWatcher.Changed += OnMetaFileChanged; + fsWatcher.Deleted += OnMetaFileDeleted; + fsWatcher.EnableRaisingEvents = true; + + using (await connectionSem.UseAsync()) + { + if (IsDisposed) + return; + + if (IsConnected) + return; + + if (!File.Exists(MetaFilePath)) + { + logger.LogInfo("There is no Godot Ide Server running"); + return; + } + + var metadata = ReadMetadataFile(); + + if (metadata != null) + { + godotIdeMetadata = metadata.Value; + _ = Task.Run(ConnectToServer); + } + else + { + logger.LogError("Failed to read Godot Ide metadata file"); + } + } + } + + public async Task<TResponse> SendRequest<TResponse>(Request request) + where TResponse : Response, new() + { + if (!IsConnected) + { + logger.LogError("Cannot write request. Not connected to the Godot Ide Server."); + return null; + } + + string body = JsonConvert.SerializeObject(request); + return await peer.SendRequest<TResponse>(request.Id, body); + } + + public async Task<TResponse> SendRequest<TResponse>(string id, string body) + where TResponse : Response, new() + { + if (!IsConnected) + { + logger.LogError("Cannot write request. Not connected to the Godot Ide Server."); + return null; + } + + return await peer.SendRequest<TResponse>(id, body); + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientHandshake.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientHandshake.cs new file mode 100644 index 0000000000..43041be7be --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientHandshake.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; + +namespace GodotTools.IdeMessaging +{ + public class ClientHandshake : IHandshake + { + private static readonly string ClientHandshakeBase = $"{Peer.ClientHandshakeName},Version={Peer.ProtocolVersionMajor}.{Peer.ProtocolVersionMinor}.{Peer.ProtocolVersionRevision}"; + private static readonly string ServerHandshakePattern = $@"{Regex.Escape(Peer.ServerHandshakeName)},Version=([0-9]+)\.([0-9]+)\.([0-9]+),([_a-zA-Z][_a-zA-Z0-9]{{0,63}})"; + + public string GetHandshakeLine(string identity) => $"{ClientHandshakeBase},{identity}"; + + public bool IsValidPeerHandshake(string handshake, out string identity, ILogger logger) + { + identity = null; + + var match = Regex.Match(handshake, ServerHandshakePattern); + + if (!match.Success) + return false; + + if (!uint.TryParse(match.Groups[1].Value, out uint serverMajor) || Peer.ProtocolVersionMajor != serverMajor) + { + logger.LogDebug("Incompatible major version: " + match.Groups[1].Value); + return false; + } + + if (!uint.TryParse(match.Groups[2].Value, out uint serverMinor) || Peer.ProtocolVersionMinor < serverMinor) + { + logger.LogDebug("Incompatible minor version: " + match.Groups[2].Value); + return false; + } + + if (!uint.TryParse(match.Groups[3].Value, out uint _)) // Revision + { + logger.LogDebug("Incompatible revision build: " + match.Groups[3].Value); + return false; + } + + identity = match.Groups[4].Value; + + return true; + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientMessageHandler.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientMessageHandler.cs new file mode 100644 index 0000000000..64bcfd824c --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientMessageHandler.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using GodotTools.IdeMessaging.Requests; +using Newtonsoft.Json; + +namespace GodotTools.IdeMessaging +{ + // ReSharper disable once UnusedType.Global + public abstract class ClientMessageHandler : IMessageHandler + { + private readonly Dictionary<string, Peer.RequestHandler> requestHandlers; + + protected ClientMessageHandler() + { + requestHandlers = InitializeRequestHandlers(); + } + + public async Task<MessageContent> HandleRequest(Peer peer, string id, MessageContent content, ILogger logger) + { + if (!requestHandlers.TryGetValue(id, out var handler)) + { + logger.LogError($"Received unknown request: {id}"); + return new MessageContent(MessageStatus.RequestNotSupported, "null"); + } + + try + { + var response = await handler(peer, content); + return new MessageContent(response.Status, JsonConvert.SerializeObject(response)); + } + catch (JsonException) + { + logger.LogError($"Received request with invalid body: {id}"); + return new MessageContent(MessageStatus.InvalidRequestBody, "null"); + } + } + + private Dictionary<string, Peer.RequestHandler> InitializeRequestHandlers() + { + return new Dictionary<string, Peer.RequestHandler> + { + [OpenFileRequest.Id] = async (peer, content) => + { + var request = JsonConvert.DeserializeObject<OpenFileRequest>(content.Body); + return await HandleOpenFile(request); + } + }; + } + + protected abstract Task<Response> HandleOpenFile(OpenFileRequest request); + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeMetadata.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs index d16daba0e2..686202e81e 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/GodotIdeMetadata.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs @@ -1,10 +1,12 @@ -namespace GodotTools.IdeConnection +namespace GodotTools.IdeMessaging { - public struct GodotIdeMetadata + public readonly struct GodotIdeMetadata { public int Port { get; } public string EditorExecutablePath { get; } + public const string DefaultFileName = "ide_messaging_meta.txt"; + public GodotIdeMetadata(int port, string editorExecutablePath) { Port = port; diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj new file mode 100644 index 0000000000..67815959a6 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj @@ -0,0 +1,24 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <ProjectGuid>{92600954-25F0-4291-8E11-1FEE9FC4BE20}</ProjectGuid> + <TargetFramework>netstandard2.0</TargetFramework> + <LangVersion>7.2</LangVersion> + <PackageId>GodotTools.IdeMessaging</PackageId> + <Version>1.1.0</Version> + <AssemblyVersion>$(Version)</AssemblyVersion> + <Authors>Godot Engine contributors</Authors> + <Company /> + <PackageTags>godot</PackageTags> + <RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/GodotTools/GodotTools.IdeMessaging</RepositoryUrl> + <PackageLicenseExpression>MIT</PackageLicenseExpression> + <Description> +This library enables communication with the Godot Engine editor (the version with .NET support). +It's intended for use in IDEs/editors plugins for a better experience working with Godot C# projects. + +A client using this library is only compatible with servers of the same major version and of a lower or equal minor version. + </Description> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> + </ItemGroup> +</Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IHandshake.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IHandshake.cs new file mode 100644 index 0000000000..6387145a28 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IHandshake.cs @@ -0,0 +1,8 @@ +namespace GodotTools.IdeMessaging +{ + public interface IHandshake + { + string GetHandshakeLine(string identity); + bool IsValidPeerHandshake(string handshake, out string identity, ILogger logger); + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/ILogger.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ILogger.cs index 614bb30271..d2855f93a1 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeConnection/ILogger.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ILogger.cs @@ -1,6 +1,6 @@ using System; -namespace GodotTools.IdeConnection +namespace GodotTools.IdeMessaging { public interface ILogger { diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IMessageHandler.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IMessageHandler.cs new file mode 100644 index 0000000000..9622fcc96d --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IMessageHandler.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace GodotTools.IdeMessaging +{ + public interface IMessageHandler + { + Task<MessageContent> HandleRequest(Peer peer, string id, MessageContent content, ILogger logger); + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Message.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Message.cs new file mode 100644 index 0000000000..6903ec197b --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Message.cs @@ -0,0 +1,52 @@ +namespace GodotTools.IdeMessaging +{ + public class Message + { + public MessageKind Kind { get; } + public string Id { get; } + public MessageContent Content { get; } + + public Message(MessageKind kind, string id, MessageContent content) + { + Kind = kind; + Id = id; + Content = content; + } + + public override string ToString() + { + return $"{Kind} | {Id}"; + } + } + + public enum MessageKind + { + Request, + Response + } + + public enum MessageStatus + { + Ok, + RequestNotSupported, + InvalidRequestBody + } + + public readonly struct MessageContent + { + public MessageStatus Status { get; } + public string Body { get; } + + public MessageContent(string body) + { + Status = MessageStatus.Ok; + Body = body; + } + + public MessageContent(MessageStatus status, string body) + { + Status = status; + Body = body; + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/MessageDecoder.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/MessageDecoder.cs new file mode 100644 index 0000000000..a00575a2a1 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/MessageDecoder.cs @@ -0,0 +1,100 @@ +using System; +using System.Text; + +namespace GodotTools.IdeMessaging +{ + public class MessageDecoder + { + private class DecodedMessage + { + public MessageKind? Kind; + public string Id; + public MessageStatus? Status; + public readonly StringBuilder Body = new StringBuilder(); + public uint? PendingBodyLines; + + public void Clear() + { + Kind = null; + Id = null; + Status = null; + Body.Clear(); + PendingBodyLines = null; + } + + public Message ToMessage() + { + if (!Kind.HasValue || Id == null || !Status.HasValue || + !PendingBodyLines.HasValue || PendingBodyLines.Value > 0) + throw new InvalidOperationException(); + + return new Message(Kind.Value, Id, new MessageContent(Status.Value, Body.ToString())); + } + } + + public enum State + { + Decoding, + Decoded, + Errored + } + + private readonly DecodedMessage decodingMessage = new DecodedMessage(); + + public State Decode(string messageLine, out Message decodedMessage) + { + decodedMessage = null; + + if (!decodingMessage.Kind.HasValue) + { + if (!Enum.TryParse(messageLine, ignoreCase: true, out MessageKind kind)) + { + decodingMessage.Clear(); + return State.Errored; + } + + decodingMessage.Kind = kind; + } + else if (decodingMessage.Id == null) + { + decodingMessage.Id = messageLine; + } + else if (decodingMessage.Status == null) + { + if (!Enum.TryParse(messageLine, ignoreCase: true, out MessageStatus status)) + { + decodingMessage.Clear(); + return State.Errored; + } + + decodingMessage.Status = status; + } + else if (decodingMessage.PendingBodyLines == null) + { + if (!uint.TryParse(messageLine, out uint pendingBodyLines)) + { + decodingMessage.Clear(); + return State.Errored; + } + + decodingMessage.PendingBodyLines = pendingBodyLines; + } + else + { + if (decodingMessage.PendingBodyLines > 0) + { + decodingMessage.Body.AppendLine(messageLine); + decodingMessage.PendingBodyLines -= 1; + } + else + { + decodedMessage = decodingMessage.ToMessage(); + decodingMessage.Clear(); + return State.Decoded; + } + } + + return State.Decoding; + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs new file mode 100644 index 0000000000..a4e86d6177 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs @@ -0,0 +1,302 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using GodotTools.IdeMessaging.Requests; +using GodotTools.IdeMessaging.Utils; + +namespace GodotTools.IdeMessaging +{ + public sealed class Peer : IDisposable + { + /// <summary> + /// Major version. + /// There is no forward nor backward compatibility between different major versions. + /// Connection is refused if client and server have different major versions. + /// </summary> + public static readonly int ProtocolVersionMajor = Assembly.GetAssembly(typeof(Peer)).GetName().Version.Major; + + /// <summary> + /// Minor version, which clients must be backward compatible with. + /// Connection is refused if the client's minor version is lower than the server's. + /// </summary> + public static readonly int ProtocolVersionMinor = Assembly.GetAssembly(typeof(Peer)).GetName().Version.Minor; + + /// <summary> + /// Revision, which doesn't affect compatibility. + /// </summary> + public static readonly int ProtocolVersionRevision = Assembly.GetAssembly(typeof(Peer)).GetName().Version.Revision; + + public const string ClientHandshakeName = "GodotIdeClient"; + public const string ServerHandshakeName = "GodotIdeServer"; + + private const int ClientWriteTimeout = 8000; + + public delegate Task<Response> RequestHandler(Peer peer, MessageContent content); + + private readonly TcpClient tcpClient; + + private readonly TextReader clientReader; + private readonly TextWriter clientWriter; + + private readonly SemaphoreSlim writeSem = new SemaphoreSlim(1); + + private string remoteIdentity = string.Empty; + public string RemoteIdentity => remoteIdentity; + + public event Action Connected; + public event Action Disconnected; + + private ILogger Logger { get; } + + public bool IsDisposed { get; private set; } + + public bool IsTcpClientConnected => tcpClient.Client != null && tcpClient.Client.Connected; + + private bool IsConnected { get; set; } + + private readonly IHandshake handshake; + private readonly IMessageHandler messageHandler; + + private readonly Dictionary<string, Queue<ResponseAwaiter>> requestAwaiterQueues = new Dictionary<string, Queue<ResponseAwaiter>>(); + private readonly SemaphoreSlim requestsSem = new SemaphoreSlim(1); + + public Peer(TcpClient tcpClient, IHandshake handshake, IMessageHandler messageHandler, ILogger logger) + { + this.tcpClient = tcpClient; + this.handshake = handshake; + this.messageHandler = messageHandler; + + Logger = logger; + + NetworkStream clientStream = tcpClient.GetStream(); + clientStream.WriteTimeout = ClientWriteTimeout; + + clientReader = new StreamReader(clientStream, Encoding.UTF8); + clientWriter = new StreamWriter(clientStream, Encoding.UTF8) {NewLine = "\n"}; + } + + public async Task Process() + { + try + { + var decoder = new MessageDecoder(); + + string messageLine; + while ((messageLine = await ReadLine()) != null) + { + var state = decoder.Decode(messageLine, out var msg); + + if (state == MessageDecoder.State.Decoding) + continue; // Not finished decoding yet + + if (state == MessageDecoder.State.Errored) + { + Logger.LogError($"Received message line with invalid format: {messageLine}"); + continue; + } + + Logger.LogDebug($"Received message: {msg}"); + + try + { + try + { + if (msg.Kind == MessageKind.Request) + { + var responseContent = await messageHandler.HandleRequest(this, msg.Id, msg.Content, Logger); + await WriteMessage(new Message(MessageKind.Response, msg.Id, responseContent)); + } + else if (msg.Kind == MessageKind.Response) + { + ResponseAwaiter responseAwaiter; + + using (await requestsSem.UseAsync()) + { + if (!requestAwaiterQueues.TryGetValue(msg.Id, out var queue) || queue.Count <= 0) + { + Logger.LogError($"Received unexpected response: {msg.Id}"); + return; + } + + responseAwaiter = queue.Dequeue(); + } + + responseAwaiter.SetResult(msg.Content); + } + else + { + throw new IndexOutOfRangeException($"Invalid message kind {msg.Kind}"); + } + } + catch (Exception e) + { + Logger.LogError($"Message handler for '{msg}' failed with exception", e); + } + } + catch (Exception e) + { + Logger.LogError($"Exception thrown from message handler. Message: {msg}", e); + } + } + } + catch (Exception e) + { + Logger.LogError("Unhandled exception in the peer loop", e); + } + } + + public async Task<bool> DoHandshake(string identity) + { + if (!await WriteLine(handshake.GetHandshakeLine(identity))) + { + Logger.LogError("Could not write handshake"); + return false; + } + + var readHandshakeTask = ReadLine(); + + if (await Task.WhenAny(readHandshakeTask, Task.Delay(8000)) != readHandshakeTask) + { + Logger.LogError("Timeout waiting for the client handshake"); + return false; + } + + string peerHandshake = await readHandshakeTask; + + if (handshake == null || !handshake.IsValidPeerHandshake(peerHandshake, out remoteIdentity, Logger)) + { + Logger.LogError("Received invalid handshake: " + peerHandshake); + return false; + } + + IsConnected = true; + Connected?.Invoke(); + + Logger.LogInfo("Peer connection started"); + + return true; + } + + private async Task<string> ReadLine() + { + try + { + return await clientReader.ReadLineAsync(); + } + catch (Exception e) + { + if (IsDisposed) + { + var se = e as SocketException ?? e.InnerException as SocketException; + if (se != null && se.SocketErrorCode == SocketError.Interrupted) + return null; + } + + throw; + } + } + + private Task<bool> WriteMessage(Message message) + { + Logger.LogDebug($"Sending message: {message}"); + int bodyLineCount = message.Content.Body.Count(c => c == '\n'); + + bodyLineCount += 1; // Extra line break at the end + + var builder = new StringBuilder(); + + builder.AppendLine(message.Kind.ToString()); + builder.AppendLine(message.Id); + builder.AppendLine(message.Content.Status.ToString()); + builder.AppendLine(bodyLineCount.ToString()); + builder.AppendLine(message.Content.Body); + + return WriteLine(builder.ToString()); + } + + public async Task<TResponse> SendRequest<TResponse>(string id, string body) + where TResponse : Response, new() + { + ResponseAwaiter responseAwaiter; + + using (await requestsSem.UseAsync()) + { + bool written = await WriteMessage(new Message(MessageKind.Request, id, new MessageContent(body))); + + if (!written) + return null; + + if (!requestAwaiterQueues.TryGetValue(id, out var queue)) + { + queue = new Queue<ResponseAwaiter>(); + requestAwaiterQueues.Add(id, queue); + } + + responseAwaiter = new ResponseAwaiter<TResponse>(); + queue.Enqueue(responseAwaiter); + } + + return (TResponse)await responseAwaiter; + } + + private async Task<bool> WriteLine(string text) + { + if (clientWriter == null || IsDisposed || !IsTcpClientConnected) + return false; + + using (await writeSem.UseAsync()) + { + try + { + await clientWriter.WriteLineAsync(text); + await clientWriter.FlushAsync(); + } + catch (Exception e) + { + if (!IsDisposed) + { + var se = e as SocketException ?? e.InnerException as SocketException; + if (se != null && se.SocketErrorCode == SocketError.Shutdown) + Logger.LogInfo("Client disconnected ungracefully"); + else + Logger.LogError("Exception thrown when trying to write to client", e); + + Dispose(); + } + } + } + + return true; + } + + // ReSharper disable once UnusedMember.Global + public void ShutdownSocketSend() + { + tcpClient.Client.Shutdown(SocketShutdown.Send); + } + + public void Dispose() + { + if (IsDisposed) + return; + + IsDisposed = true; + + if (IsTcpClientConnected) + { + if (IsConnected) + Disconnected?.Invoke(); + } + + clientReader?.Dispose(); + clientWriter?.Dispose(); + ((IDisposable)tcpClient)?.Dispose(); + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs new file mode 100644 index 0000000000..1dd4f852e5 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs @@ -0,0 +1,116 @@ +// ReSharper disable ClassNeverInstantiated.Global +// ReSharper disable UnusedMember.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +using Newtonsoft.Json; + +namespace GodotTools.IdeMessaging.Requests +{ + public abstract class Request + { + [JsonIgnore] public string Id { get; } + + protected Request(string id) + { + Id = id; + } + } + + public abstract class Response + { + [JsonIgnore] public MessageStatus Status { get; set; } = MessageStatus.Ok; + } + + public sealed class CodeCompletionRequest : Request + { + public enum CompletionKind + { + InputActions = 0, + NodePaths, + ResourcePaths, + ScenePaths, + ShaderParams, + Signals, + ThemeColors, + ThemeConstants, + ThemeFonts, + ThemeStyles + } + + public CompletionKind Kind { get; set; } + public string ScriptFile { get; set; } + + public new const string Id = "CodeCompletion"; + + public CodeCompletionRequest() : base(Id) + { + } + } + + public sealed class CodeCompletionResponse : Response + { + public CodeCompletionRequest.CompletionKind Kind; + public string ScriptFile { get; set; } + public string[] Suggestions { get; set; } + } + + public sealed class PlayRequest : Request + { + public new const string Id = "Play"; + + public PlayRequest() : base(Id) + { + } + } + + public sealed class PlayResponse : Response + { + } + + public sealed class DebugPlayRequest : Request + { + public string DebuggerHost { get; set; } + public int DebuggerPort { get; set; } + public bool? BuildBeforePlaying { get; set; } + + public new const string Id = "DebugPlay"; + + public DebugPlayRequest() : base(Id) + { + } + } + + public sealed class DebugPlayResponse : Response + { + } + + public sealed class OpenFileRequest : Request + { + public string File { get; set; } + public int? Line { get; set; } + public int? Column { get; set; } + + public new const string Id = "OpenFile"; + + public OpenFileRequest() : base(Id) + { + } + } + + public sealed class OpenFileResponse : Response + { + } + + public sealed class ReloadScriptsRequest : Request + { + public new const string Id = "ReloadScripts"; + + public ReloadScriptsRequest() : base(Id) + { + } + } + + public sealed class ReloadScriptsResponse : Response + { + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ResponseAwaiter.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ResponseAwaiter.cs new file mode 100644 index 0000000000..548e7f06ee --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ResponseAwaiter.cs @@ -0,0 +1,23 @@ +using GodotTools.IdeMessaging.Requests; +using GodotTools.IdeMessaging.Utils; +using Newtonsoft.Json; + +namespace GodotTools.IdeMessaging +{ + public abstract class ResponseAwaiter : NotifyAwaiter<Response> + { + public abstract void SetResult(MessageContent content); + } + + public class ResponseAwaiter<T> : ResponseAwaiter + where T : Response, new() + { + public override void SetResult(MessageContent content) + { + if (content.Status == MessageStatus.Ok) + SetResult(JsonConvert.DeserializeObject<T>(content.Body)); + else + SetResult(new T {Status = content.Status}); + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/NotifyAwaiter.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/NotifyAwaiter.cs index 700b786752..d84a63c83c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/NotifyAwaiter.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/NotifyAwaiter.cs @@ -1,9 +1,9 @@ using System; using System.Runtime.CompilerServices; -namespace GodotTools.Utils +namespace GodotTools.IdeMessaging.Utils { - public sealed class NotifyAwaiter<T> : INotifyCompletion + public class NotifyAwaiter<T> : INotifyCompletion { private Action continuation; private Exception exception; diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs new file mode 100644 index 0000000000..9d593fbf8a --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/SemaphoreExtensions.cs @@ -0,0 +1,32 @@ +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace GodotTools.IdeMessaging.Utils +{ + public static class SemaphoreExtensions + { + public static ConfiguredTaskAwaitable<IDisposable> UseAsync(this SemaphoreSlim semaphoreSlim, CancellationToken cancellationToken = default(CancellationToken)) + { + var wrapper = new SemaphoreSlimWaitReleaseWrapper(semaphoreSlim, out Task waitAsyncTask, cancellationToken); + return waitAsyncTask.ContinueWith<IDisposable>(t => wrapper, cancellationToken).ConfigureAwait(false); + } + + private struct SemaphoreSlimWaitReleaseWrapper : IDisposable + { + private readonly SemaphoreSlim semaphoreSlim; + + public SemaphoreSlimWaitReleaseWrapper(SemaphoreSlim semaphoreSlim, out Task waitAsyncTask, CancellationToken cancellationToken = default(CancellationToken)) + { + this.semaphoreSlim = semaphoreSlim; + waitAsyncTask = this.semaphoreSlim.WaitAsync(cancellationToken); + } + + public void Dispose() + { + semaphoreSlim.Release(); + } + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs index 9afd9adeb1..6f318aab4a 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs @@ -153,7 +153,12 @@ EndProject"; var result = regex.Replace(input,m => dict[m.Value]); if (result != input) + { + // Save a copy of the solution before replacing it + FileUtils.SaveBackupCopy(slnPath); + File.WriteAllText(slnPath, result); + } } } } diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj index b60e501beb..9cb50014b0 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj @@ -1,57 +1,23 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid> - <OutputType>Library</OutputType> - <RootNamespace>GodotTools.ProjectEditor</RootNamespace> - <AssemblyName>GodotTools.ProjectEditor</AssemblyName> - <TargetFrameworkVersion>v4.7</TargetFrameworkVersion> - <BaseIntermediateOutputPath>obj</BaseIntermediateOutputPath> - <LangVersion>7</LangVersion> + <TargetFramework>net472</TargetFramework> + <LangVersion>7.2</LangVersion> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>portable</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug</OutputPath> - <DefineConstants>DEBUG;</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <ConsolePause>false</ConsolePause> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <Optimize>true</Optimize> - <OutputPath>bin\Release</OutputPath> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <ConsolePause>false</ConsolePause> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - <Reference Include="Microsoft.Build" /> - <Reference Include="DotNet.Glob, Version=2.1.1.0, Culture=neutral, PublicKeyToken=b68cc888b4f632d1, processorArchitecture=MSIL"> - <HintPath>$(SolutionDir)\packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll</HintPath> - </Reference> - </ItemGroup> <ItemGroup> - <Compile Include="ApiAssembliesInfo.cs" /> - <Compile Include="DotNetSolution.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="IdentifierUtils.cs" /> - <Compile Include="ProjectExtensions.cs" /> - <Compile Include="ProjectGenerator.cs" /> - <Compile Include="ProjectUtils.cs" /> + <PackageReference Include="Microsoft.Build" Version="16.5.0" /> + <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> </ItemGroup> <ItemGroup> - <None Include="packages.config" /> + <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj"> - <Project>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</Project> - <Name>GodotTools.Core</Name> - </ProjectReference> + <!-- + The Microsoft.Build.Runtime package is too problematic so we create a MSBuild.exe stub. The workaround described + here doesn't work with Microsoft.NETFramework.ReferenceAssemblies: https://github.com/microsoft/msbuild/issues/3486 + We need a MSBuild.exe file as there's an issue in Microsoft.Build where it executes platform dependent code when + searching for MSBuild.exe before the fallback to not using it. A stub is fine as it should never be executed. + --> + <None Include="MSBuild.exe" CopyToOutputDirectory="Always" /> </ItemGroup> - <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/MSBuild.exe b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/MSBuild.exe new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/MSBuild.exe diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs index f0e0d1b33d..704f2ec194 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectExtensions.cs @@ -2,8 +2,8 @@ using GodotTools.Core; using System; using System.Collections.Generic; using System.IO; -using DotNet.Globbing; using Microsoft.Build.Construction; +using Microsoft.Build.Globbing; namespace GodotTools.ProjectEditor { @@ -11,8 +11,6 @@ namespace GodotTools.ProjectEditor { public static ProjectItemElement FindItemOrNull(this ProjectRootElement root, string itemType, string include, bool noCondition = false) { - GlobOptions globOptions = new GlobOptions {Evaluation = {CaseInsensitive = false}}; - string normalizedInclude = include.NormalizePath(); foreach (var itemGroup in root.ItemGroups) @@ -25,7 +23,8 @@ namespace GodotTools.ProjectEditor if (item.ItemType != itemType) continue; - var glob = Glob.Parse(item.Include.NormalizePath(), globOptions); + //var glob = Glob.Parse(item.Include.NormalizePath(), globOptions); + var glob = MSBuildGlob.Parse(item.Include.NormalizePath()); if (glob.IsMatch(normalizedInclude)) return item; @@ -36,8 +35,6 @@ namespace GodotTools.ProjectEditor } public static ProjectItemElement FindItemOrNullAbs(this ProjectRootElement root, string itemType, string include, bool noCondition = false) { - GlobOptions globOptions = new GlobOptions {Evaluation = {CaseInsensitive = false}}; - string normalizedInclude = Path.GetFullPath(include).NormalizePath(); foreach (var itemGroup in root.ItemGroups) @@ -50,7 +47,7 @@ namespace GodotTools.ProjectEditor if (item.ItemType != itemType) continue; - var glob = Glob.Parse(Path.GetFullPath(item.Include).NormalizePath(), globOptions); + var glob = MSBuildGlob.Parse(Path.GetFullPath(item.Include).NormalizePath()); if (glob.IsMatch(normalizedInclude)) return item; diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs index cbe3afaedd..fb2beb6995 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs @@ -125,6 +125,12 @@ namespace GodotTools.ProjectEditor // References var referenceGroup = root.AddItemGroup(); referenceGroup.AddItem("Reference", "System"); + var frameworkRefAssembliesItem = referenceGroup.AddItem("PackageReference", "Microsoft.NETFramework.ReferenceAssemblies"); + + // Use metadata (child nodes) instead of attributes for the PackageReference. + // This is for compatibility with 3.2, where GodotTools uses an old Microsoft.Build. + frameworkRefAssembliesItem.AddMetadata("Version", "1.0.0"); + frameworkRefAssembliesItem.AddMetadata("PrivateAssets", "All"); root.AddImport(Path.Combine("$(MSBuildBinPath)", "Microsoft.CSharp.targets").Replace("/", "\\")); diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs index 1776b46e6a..069a1edaa3 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs @@ -4,13 +4,33 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; -using DotNet.Globbing; using Microsoft.Build.Construction; +using Microsoft.Build.Globbing; namespace GodotTools.ProjectEditor { + public sealed class MSBuildProject + { + public ProjectRootElement Root { get; } + + public bool HasUnsavedChanges { get; set; } + + public void Save() => Root.Save(); + + public MSBuildProject(ProjectRootElement root) + { + Root = root; + } + } + public static class ProjectUtils { + public static MSBuildProject Open(string path) + { + var root = ProjectRootElement.Open(path); + return root != null ? new MSBuildProject(root) : null; + } + public static void AddItemToProjectChecked(string projectPath, string itemType, string include) { var dir = Directory.GetParent(projectPath).FullName; @@ -43,7 +63,6 @@ namespace GodotTools.ProjectEditor public static void RemoveItemFromProjectChecked(string projectPath, string itemType, string include) { - var dir = Directory.GetParent(projectPath).FullName; var root = ProjectRootElement.Open(projectPath); Debug.Assert(root != null); @@ -114,9 +133,6 @@ namespace GodotTools.ProjectEditor var result = new List<string>(); var existingFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs"); - var globOptions = new GlobOptions(); - globOptions.Evaluation.CaseInsensitive = false; - var root = ProjectRootElement.Open(projectPath); Debug.Assert(root != null); @@ -132,7 +148,7 @@ namespace GodotTools.ProjectEditor string normalizedInclude = item.Include.NormalizePath(); - var glob = Glob.Parse(normalizedInclude, globOptions); + var glob = MSBuildGlob.Parse(normalizedInclude); // TODO Check somehow if path has no blob to avoid the following loop... @@ -150,17 +166,14 @@ namespace GodotTools.ProjectEditor } /// Simple function to make sure the Api assembly references are configured correctly - public static void FixApiHintPath(string projectPath) + public static void FixApiHintPath(MSBuildProject project) { - var root = ProjectRootElement.Open(projectPath); - Debug.Assert(root != null); - - bool dirty = false; + var root = project.Root; void AddPropertyIfNotPresent(string name, string condition, string value) { if (root.PropertyGroups - .Any(g => (g.Condition == string.Empty || g.Condition.Trim() == condition) && + .Any(g => (string.IsNullOrEmpty(g.Condition) || g.Condition.Trim() == condition) && g.Properties .Any(p => p.Name == name && p.Value == value && @@ -170,7 +183,7 @@ namespace GodotTools.ProjectEditor } root.AddProperty(name, value).Condition = " " + condition + " "; - dirty = true; + project.HasUnsavedChanges = true; } AddPropertyIfNotPresent(name: "ApiConfiguration", @@ -212,7 +225,7 @@ namespace GodotTools.ProjectEditor } referenceWithHintPath.AddMetadata("HintPath", hintPath); - dirty = true; + project.HasUnsavedChanges = true; return; } @@ -221,14 +234,14 @@ namespace GodotTools.ProjectEditor { // Found a Reference item without a HintPath referenceWithoutHintPath.AddMetadata("HintPath", hintPath); - dirty = true; + project.HasUnsavedChanges = true; return; } } // Found no Reference item at all. Add it. root.AddItem("Reference", referenceName).Condition = " " + condition + " "; - dirty = true; + project.HasUnsavedChanges = true; } const string coreProjectName = "GodotSharp"; @@ -242,22 +255,16 @@ namespace GodotTools.ProjectEditor SetReferenceHintPath(coreProjectName, coreCondition, coreHintPath); SetReferenceHintPath(editorProjectName, editorCondition, editorHintPath); - - if (dirty) - root.Save(); } - public static void MigrateFromOldConfigNames(string projectPath) + public static void MigrateFromOldConfigNames(MSBuildProject project) { - var root = ProjectRootElement.Open(projectPath); - Debug.Assert(root != null); - - bool dirty = false; + var root = project.Root; bool hasGodotProjectGeneratorVersion = false; bool foundOldConfiguration = false; - foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition == string.Empty)) + foreach (var propertyGroup in root.PropertyGroups.Where(g => string.IsNullOrEmpty(g.Condition))) { if (!hasGodotProjectGeneratorVersion && propertyGroup.Properties.Any(p => p.Name == "GodotProjectGeneratorVersion")) hasGodotProjectGeneratorVersion = true; @@ -267,15 +274,15 @@ namespace GodotTools.ProjectEditor { configItem.Value = "Debug"; foundOldConfiguration = true; - dirty = true; + project.HasUnsavedChanges = true; } } if (!hasGodotProjectGeneratorVersion) { - root.PropertyGroups.First(g => g.Condition == string.Empty)? + root.PropertyGroups.First(g => string.IsNullOrEmpty(g.Condition))? .AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString()); - dirty = true; + project.HasUnsavedChanges = true; } if (!foundOldConfiguration) @@ -301,7 +308,7 @@ namespace GodotTools.ProjectEditor foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition.Trim() == oldCondition)) { propertyGroup.Condition = " " + newCondition + " "; - dirty = true; + project.HasUnsavedChanges = true; } foreach (var propertyGroup in root.PropertyGroups) @@ -309,14 +316,14 @@ namespace GodotTools.ProjectEditor foreach (var prop in propertyGroup.Properties.Where(p => p.Condition.Trim() == oldCondition)) { prop.Condition = " " + newCondition + " "; - dirty = true; + project.HasUnsavedChanges = true; } } foreach (var itemGroup in root.ItemGroups.Where(g => g.Condition.Trim() == oldCondition)) { itemGroup.Condition = " " + newCondition + " "; - dirty = true; + project.HasUnsavedChanges = true; } foreach (var itemGroup in root.ItemGroups) @@ -324,7 +331,7 @@ namespace GodotTools.ProjectEditor foreach (var item in itemGroup.Items.Where(item => item.Condition.Trim() == oldCondition)) { item.Condition = " " + newCondition + " "; - dirty = true; + project.HasUnsavedChanges = true; } } } @@ -340,10 +347,26 @@ namespace GodotTools.ProjectEditor MigrateConfigurationConditions("Release", "ExportRelease"); MigrateConfigurationConditions("Tools", "Debug"); // Must be last } + } + public static void EnsureHasNugetNetFrameworkRefAssemblies(MSBuildProject project) + { + var root = project.Root; - if (dirty) - root.Save(); + bool found = root.ItemGroups.Any(g => string.IsNullOrEmpty(g.Condition) && g.Items.Any( + item => item.ItemType == "PackageReference" && item.Include == "Microsoft.NETFramework.ReferenceAssemblies")); + + if (found) + return; + + var frameworkRefAssembliesItem = root.AddItem("PackageReference", "Microsoft.NETFramework.ReferenceAssemblies"); + + // Use metadata (child nodes) instead of attributes for the PackageReference. + // This is for compatibility with 3.2, where GodotTools uses an old Microsoft.Build. + frameworkRefAssembliesItem.AddMetadata("Version", "1.0.0"); + frameworkRefAssembliesItem.AddMetadata("PrivateAssets", "All"); + + project.HasUnsavedChanges = true; } } } diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/Properties/AssemblyInfo.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/Properties/AssemblyInfo.cs deleted file mode 100644 index 3a0464c9bc..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("GodotTools.ProjectEditor")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Godot Engine contributors")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] - diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/packages.config b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/packages.config deleted file mode 100644 index 2db030f9d8..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/packages.config +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<packages> - <package id="DotNet.Glob" version="2.1.1" targetFramework="net45" /> -</packages> diff --git a/modules/mono/editor/GodotTools/GodotTools.sln b/modules/mono/editor/GodotTools/GodotTools.sln index a3438ea5f3..f6147eb5bb 100644 --- a/modules/mono/editor/GodotTools/GodotTools.sln +++ b/modules/mono/editor/GodotTools/GodotTools.sln @@ -9,7 +9,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.Core", "GodotToo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.BuildLogger", "GodotTools.BuildLogger\GodotTools.BuildLogger.csproj", "{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.IdeConnection", "GodotTools.IdeConnection\GodotTools.IdeConnection.csproj", "{92600954-25F0-4291-8E11-1FEE9FC4BE20}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.IdeMessaging", "GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj", "{92600954-25F0-4291-8E11-1FEE9FC4BE20}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs b/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs index e4c8759802..3cf495f025 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs @@ -205,9 +205,9 @@ namespace GodotTools if (what == EditorSettings.NotificationEditorSettingsChanged) { var editorBaseControl = editorInterface.GetBaseControl(); - panelTabs.AddStyleboxOverride("panel", editorBaseControl.GetStylebox("DebuggerPanel", "EditorStyles")); - panelTabs.AddStyleboxOverride("tab_fg", editorBaseControl.GetStylebox("DebuggerTabFG", "EditorStyles")); - panelTabs.AddStyleboxOverride("tab_bg", editorBaseControl.GetStylebox("DebuggerTabBG", "EditorStyles")); + panelTabs.AddThemeStyleboxOverride("panel", editorBaseControl.GetThemeStylebox("DebuggerPanel", "EditorStyles")); + panelTabs.AddThemeStyleboxOverride("tab_fg", editorBaseControl.GetThemeStylebox("DebuggerTabFG", "EditorStyles")); + panelTabs.AddThemeStyleboxOverride("tab_bg", editorBaseControl.GetThemeStylebox("DebuggerTabBG", "EditorStyles")); } } @@ -258,9 +258,9 @@ namespace GodotTools RectMinSize = new Vector2(0, 228) * EditorScale, SizeFlagsVertical = (int)SizeFlags.ExpandFill }; - panelTabs.AddStyleboxOverride("panel", editorBaseControl.GetStylebox("DebuggerPanel", "EditorStyles")); - panelTabs.AddStyleboxOverride("tab_fg", editorBaseControl.GetStylebox("DebuggerTabFG", "EditorStyles")); - panelTabs.AddStyleboxOverride("tab_bg", editorBaseControl.GetStylebox("DebuggerTabBG", "EditorStyles")); + panelTabs.AddThemeStyleboxOverride("panel", editorBaseControl.GetThemeStylebox("DebuggerPanel", "EditorStyles")); + panelTabs.AddThemeStyleboxOverride("tab_fg", editorBaseControl.GetThemeStylebox("DebuggerTabFG", "EditorStyles")); + panelTabs.AddThemeStyleboxOverride("tab_bg", editorBaseControl.GetThemeStylebox("DebuggerTabBG", "EditorStyles")); AddChild(panelTabs); { diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs index 43c96d2e30..e55558c100 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs @@ -14,16 +14,6 @@ namespace GodotTools.Build { public static class BuildSystem { - private static string GetMsBuildPath() - { - string msbuildPath = MsBuildFinder.FindMsBuild(); - - if (msbuildPath == null) - throw new FileNotFoundException("Cannot find the MSBuild executable."); - - return msbuildPath; - } - private static string MonoWindowsBinDir { get @@ -46,8 +36,8 @@ namespace GodotTools.Build { if (OS.IsWindows) { - return (BuildManager.BuildTool)EditorSettings.GetSetting("mono/builds/build_tool") - == BuildManager.BuildTool.MsBuildMono; + return (BuildTool)EditorSettings.GetSetting("mono/builds/build_tool") + == BuildTool.MsBuildMono; } return false; @@ -57,16 +47,21 @@ namespace GodotTools.Build private static bool PrintBuildOutput => (bool)EditorSettings.GetSetting("mono/builds/print_build_output"); - private static Process LaunchBuild(string solution, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) + private static Process LaunchBuild(string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) { + (string msbuildPath, BuildTool buildTool) = MsBuildFinder.FindMsBuild(); + + if (msbuildPath == null) + throw new FileNotFoundException("Cannot find the MSBuild executable."); + var customPropertiesList = new List<string>(); if (customProperties != null) customPropertiesList.AddRange(customProperties); - string compilerArgs = BuildArguments(solution, config, loggerOutputDir, customPropertiesList); + string compilerArgs = BuildArguments(buildTool, solution, targets, config, loggerOutputDir, customPropertiesList); - var startInfo = new ProcessStartInfo(GetMsBuildPath(), compilerArgs); + var startInfo = new ProcessStartInfo(msbuildPath, compilerArgs); bool redirectOutput = !IsDebugMsBuildRequested() && !PrintBuildOutput; @@ -90,7 +85,7 @@ namespace GodotTools.Build // Needed when running from Developer Command Prompt for VS RemovePlatformVariable(startInfo.EnvironmentVariables); - var process = new Process { StartInfo = startInfo }; + var process = new Process {StartInfo = startInfo}; process.Start(); @@ -105,19 +100,19 @@ namespace GodotTools.Build public static int Build(BuildInfo buildInfo) { - return Build(buildInfo.Solution, buildInfo.Configuration, + return Build(buildInfo.Solution, buildInfo.Targets, buildInfo.Configuration, buildInfo.LogsDirPath, buildInfo.CustomProperties); } - public static async Task<int> BuildAsync(BuildInfo buildInfo) + public static Task<int> BuildAsync(BuildInfo buildInfo) { - return await BuildAsync(buildInfo.Solution, buildInfo.Configuration, + return BuildAsync(buildInfo.Solution, buildInfo.Targets, buildInfo.Configuration, buildInfo.LogsDirPath, buildInfo.CustomProperties); } - public static int Build(string solution, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) + public static int Build(string solution, string[] targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) { - using (var process = LaunchBuild(solution, config, loggerOutputDir, customProperties)) + using (var process = LaunchBuild(solution, targets, config, loggerOutputDir, customProperties)) { process.WaitForExit(); @@ -125,9 +120,9 @@ namespace GodotTools.Build } } - public static async Task<int> BuildAsync(string solution, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) + public static async Task<int> BuildAsync(string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) { - using (var process = LaunchBuild(solution, config, loggerOutputDir, customProperties)) + using (var process = LaunchBuild(solution, targets, config, loggerOutputDir, customProperties)) { await process.WaitForExitAsync(); @@ -135,10 +130,15 @@ namespace GodotTools.Build } } - private static string BuildArguments(string solution, string config, string loggerOutputDir, List<string> customProperties) + private static string BuildArguments(BuildTool buildTool, string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties) { - string arguments = $@"""{solution}"" /v:normal /t:Build ""/p:{"Configuration=" + config}"" " + - $@"""/l:{typeof(GodotBuildLogger).FullName},{GodotBuildLogger.AssemblyPath};{loggerOutputDir}"""; + string arguments = string.Empty; + + if (buildTool == BuildTool.DotnetCli) + arguments += "msbuild "; // `dotnet msbuild` command + + arguments += $@"""{solution}"" /v:normal /t:{string.Join(",", targets)} ""/p:{"Configuration=" + config}"" " + + $@"""/l:{typeof(GodotBuildLogger).FullName},{GodotBuildLogger.AssemblyPath};{loggerOutputDir}"""; foreach (string customProperty in customProperties) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs new file mode 100644 index 0000000000..a1a69334e3 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs @@ -0,0 +1,10 @@ +namespace GodotTools.Build +{ + public enum BuildTool + { + MsBuildMono, + MsBuildVs, + JetBrainsMsBuild, + DotnetCli + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs index af8d070cbd..f36e581a5f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs @@ -17,75 +17,96 @@ namespace GodotTools.Build private static string _msbuildToolsPath = string.Empty; private static string _msbuildUnixPath = string.Empty; - public static string FindMsBuild() + public static (string, BuildTool) FindMsBuild() { var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings(); - var buildTool = (BuildManager.BuildTool)editorSettings.GetSetting("mono/builds/build_tool"); + var buildTool = (BuildTool)editorSettings.GetSetting("mono/builds/build_tool"); if (OS.IsWindows) { switch (buildTool) { - case BuildManager.BuildTool.MsBuildVs: + case BuildTool.DotnetCli: { - if (_msbuildToolsPath.Empty() || !File.Exists(_msbuildToolsPath)) + string dotnetCliPath = OS.PathWhich("dotnet"); + if (!string.IsNullOrEmpty(dotnetCliPath)) + return (dotnetCliPath, BuildTool.DotnetCli); + GD.PushError("Cannot find dotnet CLI executable. Fallback to MSBuild from Visual Studio."); + goto case BuildTool.MsBuildVs; + } + case BuildTool.MsBuildVs: + { + if (string.IsNullOrEmpty(_msbuildToolsPath) || !File.Exists(_msbuildToolsPath)) { // Try to search it again if it wasn't found last time or if it was removed from its location _msbuildToolsPath = FindMsBuildToolsPathOnWindows(); - if (_msbuildToolsPath.Empty()) - { - throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMsbuildVs}'."); - } + if (string.IsNullOrEmpty(_msbuildToolsPath)) + throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildVs}'."); } if (!_msbuildToolsPath.EndsWith("\\")) _msbuildToolsPath += "\\"; - return Path.Combine(_msbuildToolsPath, "MSBuild.exe"); + return (Path.Combine(_msbuildToolsPath, "MSBuild.exe"), BuildTool.MsBuildVs); } - case BuildManager.BuildTool.MsBuildMono: + case BuildTool.MsBuildMono: { string msbuildPath = Path.Combine(Internal.MonoWindowsInstallRoot, "bin", "msbuild.bat"); if (!File.Exists(msbuildPath)) - { - throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMsbuildMono}'. Tried with path: {msbuildPath}"); - } + throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildMono}'. Tried with path: {msbuildPath}"); - return msbuildPath; + return (msbuildPath, BuildTool.MsBuildMono); } - case BuildManager.BuildTool.JetBrainsMsBuild: + case BuildTool.JetBrainsMsBuild: + { var editorPath = (string)editorSettings.GetSetting(RiderPathManager.EditorPathSettingName); + if (!File.Exists(editorPath)) throw new FileNotFoundException($"Cannot find Rider executable. Tried with path: {editorPath}"); - var riderDir = new FileInfo(editorPath).Directory.Parent; - return Path.Combine(riderDir.FullName, @"tools\MSBuild\Current\Bin\MSBuild.exe"); + + var riderDir = new FileInfo(editorPath).Directory?.Parent; + + string msbuildPath = Path.Combine(riderDir.FullName, @"tools\MSBuild\Current\Bin\MSBuild.exe"); + + if (!File.Exists(msbuildPath)) + throw new FileNotFoundException($"Cannot find executable for '{BuildManager.PropNameMSBuildJetBrains}'. Tried with path: {msbuildPath}"); + + return (msbuildPath, BuildTool.JetBrainsMsBuild); + } default: throw new IndexOutOfRangeException("Invalid build tool in editor settings"); } } - if (OS.IsUnixLike()) + if (OS.IsUnixLike) { - if (buildTool == BuildManager.BuildTool.MsBuildMono) + switch (buildTool) { - if (_msbuildUnixPath.Empty() || !File.Exists(_msbuildUnixPath)) + case BuildTool.DotnetCli: { - // Try to search it again if it wasn't found last time or if it was removed from its location - _msbuildUnixPath = FindBuildEngineOnUnix("msbuild"); + string dotnetCliPath = OS.PathWhich("dotnet"); + if (!string.IsNullOrEmpty(dotnetCliPath)) + return (dotnetCliPath, BuildTool.DotnetCli); + GD.PushError("Cannot find dotnet CLI executable. Fallback to MSBuild from Mono."); + goto case BuildTool.MsBuildMono; } - - if (_msbuildUnixPath.Empty()) + case BuildTool.MsBuildMono: { - throw new FileNotFoundException($"Cannot find binary for '{BuildManager.PropNameMsbuildMono}'"); - } + if (string.IsNullOrEmpty(_msbuildUnixPath) || !File.Exists(_msbuildUnixPath)) + { + // Try to search it again if it wasn't found last time or if it was removed from its location + _msbuildUnixPath = FindBuildEngineOnUnix("msbuild"); + } - return _msbuildUnixPath; - } - else - { - throw new IndexOutOfRangeException("Invalid build tool in editor settings"); + if (string.IsNullOrEmpty(_msbuildUnixPath)) + throw new FileNotFoundException($"Cannot find binary for '{BuildManager.PropNameMSBuildMono}'"); + + return (_msbuildUnixPath, BuildTool.MsBuildMono); + } + default: + throw new IndexOutOfRangeException("Invalid build tool in editor settings"); } } @@ -114,12 +135,12 @@ namespace GodotTools.Build { string ret = OS.PathWhich(name); - if (!ret.Empty()) + if (!string.IsNullOrEmpty(ret)) return ret; string retFallback = OS.PathWhich($"{name}.exe"); - if (!retFallback.Empty()) + if (!string.IsNullOrEmpty(retFallback)) return retFallback; foreach (string hintDir in MsBuildHintDirs) @@ -143,7 +164,7 @@ namespace GodotTools.Build string vsWherePath = Environment.GetEnvironmentVariable(Internal.GodotIs32Bits() ? "ProgramFiles" : "ProgramFiles(x86)"); vsWherePath += "\\Microsoft Visual Studio\\Installer\\vswhere.exe"; - var vsWhereArgs = new[] { "-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild" }; + var vsWhereArgs = new[] {"-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"}; var outputArray = new Godot.Collections.Array<string>(); int exitCode = Godot.OS.Execute(vsWherePath, vsWhereArgs, @@ -171,7 +192,7 @@ namespace GodotTools.Build string value = line.Substring(sepIdx + 1).StripEdges(); - if (value.Empty()) + if (string.IsNullOrEmpty(value)) throw new FormatException("installationPath value is empty"); if (!value.EndsWith("\\")) diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs index 70bd552f2f..cca0983c01 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs @@ -10,6 +10,7 @@ namespace GodotTools public sealed class BuildInfo : Reference // TODO Remove Reference once we have proper serialization { public string Solution { get; } + public string[] Targets { get; } public string Configuration { get; } public Array<string> CustomProperties { get; } = new Array<string>(); // TODO Use List once we have proper serialization @@ -38,9 +39,10 @@ namespace GodotTools { } - public BuildInfo(string solution, string configuration) + public BuildInfo(string solution, string[] targets, string configuration) { Solution = solution; + Targets = targets; Configuration = configuration; } } diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs index 520e665595..598787ba03 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs @@ -15,20 +15,14 @@ namespace GodotTools { private static readonly List<BuildInfo> BuildsInProgress = new List<BuildInfo>(); - public const string PropNameMsbuildMono = "MSBuild (Mono)"; - public const string PropNameMsbuildVs = "MSBuild (VS Build Tools)"; - public const string PropNameMsbuildJetBrains = "MSBuild (JetBrains Rider)"; + public const string PropNameMSBuildMono = "MSBuild (Mono)"; + public const string PropNameMSBuildVs = "MSBuild (VS Build Tools)"; + public const string PropNameMSBuildJetBrains = "MSBuild (JetBrains Rider)"; + public const string PropNameDotnetCli = "dotnet CLI"; public const string MsBuildIssuesFileName = "msbuild_issues.csv"; public const string MsBuildLogFileName = "msbuild_log.txt"; - public enum BuildTool - { - MsBuildMono, - MsBuildVs, - JetBrainsMsBuild - } - private static void RemoveOldIssuesFile(BuildInfo buildInfo) { var issuesFile = GetIssuesFilePath(buildInfo); @@ -181,10 +175,12 @@ namespace GodotTools { pr.Step("Building project solution", 0); - var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, config); + var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets: new[] {"Restore", "Build"}, config); + + bool escapeNeedsDoubleBackslash = buildTool == BuildTool.MsBuildMono || buildTool == BuildTool.DotnetCli; // Add Godot defines - string constants = buildTool != BuildTool.MsBuildMono ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\""; + string constants = !escapeNeedsDoubleBackslash ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\""; foreach (var godotDefine in godotDefines) constants += $"GODOT_{godotDefine.ToUpper().Replace("-", "_").Replace(" ", "_").Replace(";", "_")};"; @@ -192,7 +188,7 @@ namespace GodotTools if (Internal.GodotIsRealTDouble()) constants += "GODOT_REAL_T_IS_DOUBLE;"; - constants += buildTool != BuildTool.MsBuildMono ? "\"" : "\\\""; + constants += !escapeNeedsDoubleBackslash ? "\"" : "\\\""; buildInfo.CustomProperties.Add(constants); @@ -219,7 +215,7 @@ namespace GodotTools if (File.Exists(editorScriptsMetadataPath)) File.Copy(editorScriptsMetadataPath, playerScriptsMetadataPath); - var currentPlayRequest = GodotSharpEditor.Instance.GodotIdeManager.GodotIdeServer.CurrentPlayRequest; + var currentPlayRequest = GodotSharpEditor.Instance.CurrentPlaySettings; if (currentPlayRequest != null) { @@ -233,7 +229,8 @@ namespace GodotTools ",server=n"); } - return true; // Requested play from an external editor/IDE which already built the project + if (!currentPlayRequest.Value.BuildBeforePlaying) + return true; // Requested play from an external editor/IDE which already built the project } var godotDefines = new[] @@ -249,22 +246,44 @@ namespace GodotTools { // Build tool settings var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings(); - var msbuild = BuildTool.MsBuildMono; + + BuildTool msbuildDefault; + if (OS.IsWindows) - msbuild = RiderPathManager.IsExternalEditorSetToRider(editorSettings) - ? BuildTool.JetBrainsMsBuild - : BuildTool.MsBuildVs; + { + if (RiderPathManager.IsExternalEditorSetToRider(editorSettings)) + msbuildDefault = BuildTool.JetBrainsMsBuild; + else + msbuildDefault = !string.IsNullOrEmpty(OS.PathWhich("dotnet")) ? BuildTool.DotnetCli : BuildTool.MsBuildVs; + } + else + { + msbuildDefault = !string.IsNullOrEmpty(OS.PathWhich("dotnet")) ? BuildTool.DotnetCli : BuildTool.MsBuildMono; + } + + EditorDef("mono/builds/build_tool", msbuildDefault); - EditorDef("mono/builds/build_tool", msbuild); + string hintString; + + if (OS.IsWindows) + { + hintString = $"{PropNameMSBuildMono}:{(int)BuildTool.MsBuildMono}," + + $"{PropNameMSBuildVs}:{(int)BuildTool.MsBuildVs}," + + $"{PropNameMSBuildJetBrains}:{(int)BuildTool.JetBrainsMsBuild}," + + $"{PropNameDotnetCli}:{(int)BuildTool.DotnetCli}"; + } + else + { + hintString = $"{PropNameMSBuildMono}:{(int)BuildTool.MsBuildMono}," + + $"{PropNameDotnetCli}:{(int)BuildTool.DotnetCli}"; + } editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary { ["type"] = Godot.Variant.Type.Int, ["name"] = "mono/builds/build_tool", ["hint"] = Godot.PropertyHint.Enum, - ["hint_string"] = OS.IsWindows ? - $"{PropNameMsbuildMono},{PropNameMsbuildVs},{PropNameMsbuildJetBrains}" : - $"{PropNameMsbuildMono}" + ["hint_string"] = hintString }); EditorDef("mono/builds/print_build_output", false); diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs b/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs index b2459b69ad..0106e1f1ac 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs @@ -46,12 +46,12 @@ namespace GodotTools get { if (!BuildExited) - return GetIcon("Stop", "EditorIcons"); + return GetThemeIcon("Stop", "EditorIcons"); if (BuildResult == BuildResults.Error) - return GetIcon("StatusError", "EditorIcons"); + return GetThemeIcon("StatusError", "EditorIcons"); - return GetIcon("StatusSuccess", "EditorIcons"); + return GetThemeIcon("StatusSuccess", "EditorIcons"); } } @@ -72,7 +72,7 @@ namespace GodotTools { string[] csvColumns = file.GetCsvLine(); - if (csvColumns.Length == 1 && csvColumns[0].Empty()) + if (csvColumns.Length == 1 && string.IsNullOrEmpty(csvColumns[0])) return; if (csvColumns.Length != 7) @@ -115,12 +115,12 @@ namespace GodotTools // Get correct issue idx from issue list int issueIndex = (int)issuesList.GetItemMetadata(idx); - if (idx < 0 || idx >= issues.Count) + if (issueIndex < 0 || issueIndex >= issues.Count) throw new IndexOutOfRangeException("Issue index out of range"); BuildIssue issue = issues[issueIndex]; - if (issue.ProjectFile.Empty() && issue.File.Empty()) + if (string.IsNullOrEmpty(issue.ProjectFile) && string.IsNullOrEmpty(issue.File)) return; string projectDir = issue.ProjectFile.Length > 0 ? issue.ProjectFile.GetBaseDir() : BuildInfo.Solution.GetBaseDir(); @@ -145,8 +145,8 @@ namespace GodotTools { issuesList.Clear(); - using (var warningIcon = GetIcon("Warning", "EditorIcons")) - using (var errorIcon = GetIcon("Error", "EditorIcons")) + using (var warningIcon = GetThemeIcon("Warning", "EditorIcons")) + using (var errorIcon = GetThemeIcon("Error", "EditorIcons")) { for (int i = 0; i < issues.Count; i++) { @@ -158,14 +158,14 @@ namespace GodotTools string tooltip = string.Empty; tooltip += $"Message: {issue.Message}"; - if (!issue.Code.Empty()) + if (!string.IsNullOrEmpty(issue.Code)) tooltip += $"\nCode: {issue.Code}"; tooltip += $"\nType: {(issue.Warning ? "warning" : "error")}"; string text = string.Empty; - if (!issue.File.Empty()) + if (!string.IsNullOrEmpty(issue.File)) { text += $"{issue.File}({issue.Line},{issue.Column}): "; @@ -174,7 +174,7 @@ namespace GodotTools tooltip += $"\nColumn: {issue.Column}"; } - if (!issue.ProjectFile.Empty()) + if (!string.IsNullOrEmpty(issue.ProjectFile)) tooltip += $"\nProject: {issue.ProjectFile}"; text += issue.Message; diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs new file mode 100755 index 0000000000..f60e469503 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -0,0 +1,618 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using GodotTools.Internals; +using Directory = GodotTools.Utils.Directory; +using File = GodotTools.Utils.File; +using OS = GodotTools.Utils.OS; +using Path = System.IO.Path; + +namespace GodotTools.Export +{ + public struct AotOptions + { + public bool EnableLLVM; + public bool LLVMOnly; + public string LLVMPath; + public string LLVMOutputPath; + + public bool FullAot; + + private bool _useInterpreter; + public bool UseInterpreter { get => _useInterpreter && !LLVMOnly; set => _useInterpreter = value; } + + public string[] ExtraAotOptions; + public string[] ExtraOptimizerOptions; + + public string ToolchainPath; + } + + public static class AotBuilder + { + public static void CompileAssemblies(ExportPlugin exporter, AotOptions aotOpts, string[] features, string platform, bool isDebug, string bclDir, string outputDir, string outputDataDir, IDictionary<string, string> assemblies) + { + // TODO: WASM + + string aotTempDir = Path.Combine(Path.GetTempPath(), $"godot-aot-{Process.GetCurrentProcess().Id}"); + + if (!Directory.Exists(aotTempDir)) + Directory.CreateDirectory(aotTempDir); + + var assembliesPrepared = new Dictionary<string, string>(); + + foreach (var dependency in assemblies) + { + string assemblyName = dependency.Key; + string assemblyPath = dependency.Value; + + string assemblyPathInBcl = Path.Combine(bclDir, assemblyName + ".dll"); + + if (File.Exists(assemblyPathInBcl)) + { + // Don't create teporaries for assemblies from the BCL + assembliesPrepared.Add(assemblyName, assemblyPathInBcl); + } + else + { + string tempAssemblyPath = Path.Combine(aotTempDir, assemblyName + ".dll"); + File.Copy(assemblyPath, tempAssemblyPath); + assembliesPrepared.Add(assemblyName, tempAssemblyPath); + } + } + + if (platform == OS.Platforms.iOS) + { + var architectures = GetEnablediOSArchs(features).ToArray(); + CompileAssembliesForiOS(exporter, isDebug, architectures, aotOpts, aotTempDir, assembliesPrepared, bclDir); + } + else if (platform == OS.Platforms.Android) + { + var abis = GetEnabledAndroidAbis(features).ToArray(); + CompileAssembliesForAndroid(exporter, isDebug, abis, aotOpts, aotTempDir, assembliesPrepared, bclDir); + } + else + { + string bits = features.Contains("64") ? "64" : features.Contains("32") ? "32" : null; + CompileAssembliesForDesktop(exporter, platform, isDebug, bits, aotOpts, aotTempDir, outputDataDir, assembliesPrepared, bclDir); + } + } + + public static void CompileAssembliesForAndroid(ExportPlugin exporter, bool isDebug, string[] abis, AotOptions aotOpts, string aotTempDir, IDictionary<string, string> assemblies, string bclDir) + { + + foreach (var assembly in assemblies) + { + string assemblyName = assembly.Key; + string assemblyPath = assembly.Value; + + // Not sure if the 'lib' prefix is an Android thing or just Godot being picky, + // but we use '-aot-' as well just in case to avoid conflicts with other libs. + string outputFileName = "lib-aot-" + assemblyName + ".dll.so"; + + foreach (string abi in abis) + { + string aotAbiTempDir = Path.Combine(aotTempDir, abi); + string soFilePath = Path.Combine(aotAbiTempDir, outputFileName); + + var compilerArgs = GetAotCompilerArgs(OS.Platforms.Android, isDebug, abi, aotOpts, assemblyPath, soFilePath); + + // Make sure the output directory exists + Directory.CreateDirectory(aotAbiTempDir); + + string compilerDirPath = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "aot-compilers", $"{OS.Platforms.Android}-{abi}"); + + ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir); + + // The Godot exporter expects us to pass the abi in the tags parameter + exporter.AddSharedObject(soFilePath, tags: new[] { abi }); + } + } + } + + public static void CompileAssembliesForDesktop(ExportPlugin exporter, string platform, bool isDebug, string bits, AotOptions aotOpts, string aotTempDir, string outputDataDir, IDictionary<string, string> assemblies, string bclDir) + { + foreach (var assembly in assemblies) + { + string assemblyName = assembly.Key; + string assemblyPath = assembly.Value; + + string outputFileExtension = platform == OS.Platforms.Windows ? ".dll" : + platform == OS.Platforms.OSX ? ".dylib" : + ".so"; + + string outputFileName = assemblyName + ".dll" + outputFileExtension; + string tempOutputFilePath = Path.Combine(aotTempDir, outputFileName); + + var compilerArgs = GetAotCompilerArgs(platform, isDebug, bits, aotOpts, assemblyPath, tempOutputFilePath); + + string compilerDirPath = GetMonoCrossDesktopDirName(platform, bits); + + ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir); + + if (platform == OS.Platforms.OSX) + { + exporter.AddSharedObject(tempOutputFilePath, tags: null); + } + else + { + string outputDataLibDir = Path.Combine(outputDataDir, "Mono", platform == OS.Platforms.Windows ? "bin" : "lib"); + File.Copy(tempOutputFilePath, Path.Combine(outputDataLibDir, outputFileName)); + } + } + } + + public static void CompileAssembliesForiOS(ExportPlugin exporter, bool isDebug, string[] architectures, AotOptions aotOpts, string aotTempDir, IDictionary<string, string> assemblies, string bclDir) + { + var cppCode = new StringBuilder(); + var aotModuleInfoSymbols = new List<string>(assemblies.Count); + + // {arch: paths} + var objFilePathsForiOSArch = architectures.ToDictionary(arch => arch, arch => new List<string>(assemblies.Count)); + + foreach (var assembly in assemblies) + { + string assemblyName = assembly.Key; + string assemblyPath = assembly.Value; + + string asmFileName = assemblyName + ".dll.S"; + string objFileName = assemblyName + ".dll.o"; + + foreach (string arch in architectures) + { + string aotArchTempDir = Path.Combine(aotTempDir, arch); + string asmFilePath = Path.Combine(aotArchTempDir, asmFileName); + + var compilerArgs = GetAotCompilerArgs(OS.Platforms.iOS, isDebug, arch, aotOpts, assemblyPath, asmFilePath); + + // Make sure the output directory exists + Directory.CreateDirectory(aotArchTempDir); + + string compilerDirPath = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "aot-compilers", $"{OS.Platforms.iOS}-{arch}"); + + ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir); + + // Assembling + bool isSim = arch == "i386" || arch == "x86_64"; // Shouldn't really happen as we don't do AOT for the simulator + string versionMinName = isSim ? "iphonesimulator" : "iphoneos"; + string iOSPlatformName = isSim ? "iPhoneSimulator" : "iPhoneOS"; + const string versionMin = "10.0"; // TODO: Turn this hard-coded version into an exporter setting + string iOSSdkPath = Path.Combine(XcodeHelper.XcodePath, + $"Contents/Developer/Platforms/{iOSPlatformName}.platform/Developer/SDKs/{iOSPlatformName}.sdk"); + + string objFilePath = Path.Combine(aotArchTempDir, objFileName); + + var clangArgs = new List<string>() + { + "-isysroot", iOSSdkPath, + "-Qunused-arguments", + $"-m{versionMinName}-version-min={versionMin}", + "-arch", arch, + "-c", + "-o", objFilePath, + "-x", "assembler" + }; + + if (isDebug) + clangArgs.Add("-DDEBUG"); + + clangArgs.Add(asmFilePath); + + int clangExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("clang"), clangArgs); + if (clangExitCode != 0) + throw new Exception($"Command 'clang' exited with code: {clangExitCode}"); + + objFilePathsForiOSArch[arch].Add(objFilePath); + } + + aotModuleInfoSymbols.Add($"mono_aot_module_{AssemblyNameToAotSymbol(assemblyName)}_info"); + } + + // Generate driver code + cppCode.AppendLine("#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)"); + cppCode.AppendLine("#define IOS_DEVICE"); + cppCode.AppendLine("#endif"); + + cppCode.AppendLine("#ifdef IOS_DEVICE"); + cppCode.AppendLine("extern \"C\" {"); + cppCode.AppendLine("// Mono API"); + cppCode.AppendLine(@" +typedef enum { +MONO_AOT_MODE_NONE, +MONO_AOT_MODE_NORMAL, +MONO_AOT_MODE_HYBRID, +MONO_AOT_MODE_FULL, +MONO_AOT_MODE_LLVMONLY, +MONO_AOT_MODE_INTERP, +MONO_AOT_MODE_INTERP_LLVMONLY, +MONO_AOT_MODE_LLVMONLY_INTERP, +MONO_AOT_MODE_LAST = 1000, +} MonoAotMode;"); + cppCode.AppendLine("void mono_jit_set_aot_mode(MonoAotMode);"); + cppCode.AppendLine("void mono_aot_register_module(void *);"); + + if (aotOpts.UseInterpreter) + { + cppCode.AppendLine("void mono_ee_interp_init(const char *);"); + cppCode.AppendLine("void mono_icall_table_init();"); + cppCode.AppendLine("void mono_marshal_ilgen_init();"); + cppCode.AppendLine("void mono_method_builder_ilgen_init();"); + cppCode.AppendLine("void mono_sgen_mono_ilgen_init();"); + } + + foreach (string symbol in aotModuleInfoSymbols) + cppCode.AppendLine($"extern void *{symbol};"); + + cppCode.AppendLine("void gd_mono_setup_aot() {"); + + foreach (string symbol in aotModuleInfoSymbols) + cppCode.AppendLine($"\tmono_aot_register_module({symbol});"); + + if (aotOpts.UseInterpreter) + { + cppCode.AppendLine("\tmono_icall_table_init();"); + cppCode.AppendLine("\tmono_marshal_ilgen_init();"); + cppCode.AppendLine("\tmono_method_builder_ilgen_init();"); + cppCode.AppendLine("\tmono_sgen_mono_ilgen_init();"); + cppCode.AppendLine("\tmono_ee_interp_init(0);"); + } + + string aotModeStr = null; + + if (aotOpts.LLVMOnly) + { + aotModeStr = "MONO_AOT_MODE_LLVMONLY"; // --aot=llvmonly + } + else + { + if (aotOpts.UseInterpreter) + aotModeStr = "MONO_AOT_MODE_INTERP"; // --aot=interp or --aot=interp,full + else if (aotOpts.FullAot) + aotModeStr = "MONO_AOT_MODE_FULL"; // --aot=full + } + + // One of the options above is always set for iOS + Debug.Assert(aotModeStr != null); + + cppCode.AppendLine($"\tmono_jit_set_aot_mode({aotModeStr});"); + + cppCode.AppendLine("} // gd_mono_setup_aot"); + cppCode.AppendLine("} // extern \"C\""); + cppCode.AppendLine("#endif // IOS_DEVICE"); + + // Add the driver code to the Xcode project + exporter.AddIosCppCode(cppCode.ToString()); + + // Archive the AOT object files into a static library + + var arFilePathsForAllArchs = new List<string>(); + string projectAssemblyName = GodotSharpEditor.ProjectAssemblyName; + + foreach (var archPathsPair in objFilePathsForiOSArch) + { + string arch = archPathsPair.Key; + var objFilePaths = archPathsPair.Value; + + string arOutputFilePath = Path.Combine(aotTempDir, $"lib-aot-{projectAssemblyName}.{arch}.a"); + + var arArgs = new List<string>() + { + "cr", + arOutputFilePath + }; + + foreach (string objFilePath in objFilePaths) + arArgs.Add(objFilePath); + + int arExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("ar"), arArgs); + if (arExitCode != 0) + throw new Exception($"Command 'ar' exited with code: {arExitCode}"); + + arFilePathsForAllArchs.Add(arOutputFilePath); + } + + // It's lipo time + + string fatOutputFileName = $"lib-aot-{projectAssemblyName}.fat.a"; + string fatOutputFilePath = Path.Combine(aotTempDir, fatOutputFileName); + + var lipoArgs = new List<string>(); + lipoArgs.Add("-create"); + lipoArgs.AddRange(arFilePathsForAllArchs); + lipoArgs.Add("-output"); + lipoArgs.Add(fatOutputFilePath); + + int lipoExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("lipo"), lipoArgs); + if (lipoExitCode != 0) + throw new Exception($"Command 'lipo' exited with code: {lipoExitCode}"); + + // TODO: Add the AOT lib and interpreter libs as device only to supress warnings when targeting the simulator + + // Add the fat AOT static library to the Xcode project + exporter.AddIosProjectStaticLib(fatOutputFilePath); + + // Add the required Mono libraries to the Xcode project + + string MonoLibFile(string libFileName) => libFileName + ".iphone.fat.a"; + + string MonoLibFromTemplate(string libFileName) => + Path.Combine(Internal.FullTemplatesDir, "iphone-mono-libs", MonoLibFile(libFileName)); + + exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmonosgen-2.0")); + + exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-native")); + + if (aotOpts.UseInterpreter) + { + exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-ee-interp")); + exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-icall-table")); + exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-ilgen")); + } + + // TODO: Turn into an exporter option + bool enableProfiling = false; + if (enableProfiling) + exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmono-profiler-log")); + + // Add frameworks required by Mono to the Xcode project + exporter.AddIosFramework("libiconv.tbd"); + exporter.AddIosFramework("GSS.framework"); + exporter.AddIosFramework("CFNetwork.framework"); + + // Force load and export dynamic are needed for the linker to not strip required symbols. + // In theory we shouldn't be relying on this for P/Invoked functions (as is the case with + // functions in System.Native/libmono-native). Instead, we should use cecil to search for + // DllImports in assemblies and pass them to 'ld' as '-u/--undefined {pinvoke_symbol}'. + exporter.AddIosLinkerFlags("-rdynamic"); + exporter.AddIosLinkerFlags($"-force_load \"$(SRCROOT)/{MonoLibFile("libmono-native")}\""); + } + + /// Converts an assembly name to a valid symbol name in the same way the AOT compiler does + private static string AssemblyNameToAotSymbol(string assemblyName) + { + var builder = new StringBuilder(); + + foreach (var charByte in Encoding.UTF8.GetBytes(assemblyName)) + { + char @char = (char)charByte; + builder.Append(Char.IsLetterOrDigit(@char) || @char == '_' ? @char : '_'); + } + + return builder.ToString(); + } + + private static IEnumerable<string> GetAotCompilerArgs(string platform, bool isDebug, string target, AotOptions aotOpts, string assemblyPath, string outputFilePath) + { + // TODO: LLVM + + bool aotSoftDebug = isDebug && !aotOpts.EnableLLVM; + bool aotDwarfDebug = platform == OS.Platforms.iOS; + + var aotOptions = new List<string>(); + var optimizerOptions = new List<string>(); + + if (aotOpts.LLVMOnly) + { + aotOptions.Add("llvmonly"); + } + else + { + // Can be both 'interp' and 'full' + if (aotOpts.UseInterpreter) + aotOptions.Add("interp"); + if (aotOpts.FullAot) + aotOptions.Add("full"); + } + + aotOptions.Add(aotSoftDebug ? "soft-debug" : "nodebug"); + + if (aotDwarfDebug) + aotOptions.Add("dwarfdebug"); + + if (platform == OS.Platforms.Android) + { + string abi = target; + + string androidToolchain = aotOpts.ToolchainPath; + + if (string.IsNullOrEmpty(androidToolchain)) + { + androidToolchain = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "android-toolchains", $"{abi}"); // TODO: $"{abi}-{apiLevel}{(clang?"clang":"")}" + + if (!Directory.Exists(androidToolchain)) + throw new FileNotFoundException("Missing android toolchain. Specify one in the AOT export settings."); + } + else if (!Directory.Exists(androidToolchain)) + { + throw new FileNotFoundException("Android toolchain not found: " + androidToolchain); + } + + var androidToolPrefixes = new Dictionary<string, string> + { + ["armeabi-v7a"] = "arm-linux-androideabi-", + ["arm64-v8a"] = "aarch64-linux-android-", + ["x86"] = "i686-linux-android-", + ["x86_64"] = "x86_64-linux-android-" + }; + + aotOptions.Add("tool-prefix=" + Path.Combine(androidToolchain, "bin", androidToolPrefixes[abi])); + + string triple = GetAndroidTriple(abi); + aotOptions.Add($"mtriple={triple}"); + } + else if (platform == OS.Platforms.iOS) + { + if (!aotOpts.LLVMOnly && !aotOpts.UseInterpreter) + optimizerOptions.Add("gsharedvt"); + + aotOptions.Add("static"); + + // I couldn't get the Mono cross-compiler to do assembling, so we'll have to do it ourselves + aotOptions.Add("asmonly"); + + aotOptions.Add("direct-icalls"); + + if (aotSoftDebug) + aotOptions.Add("no-direct-calls"); + + if (aotOpts.LLVMOnly || !aotOpts.UseInterpreter) + aotOptions.Add("direct-pinvoke"); + + string arch = target; + aotOptions.Add($"mtriple={arch}-ios"); + } + + aotOptions.Add($"outfile={outputFilePath}"); + + if (aotOpts.EnableLLVM) + { + aotOptions.Add($"llvm-path={aotOpts.LLVMPath}"); + aotOptions.Add($"llvm-outfile={aotOpts.LLVMOutputPath}"); + } + + if (aotOpts.ExtraAotOptions.Length > 0) + aotOptions.AddRange(aotOpts.ExtraAotOptions); + + if (aotOpts.ExtraOptimizerOptions.Length > 0) + optimizerOptions.AddRange(aotOpts.ExtraOptimizerOptions); + + string EscapeOption(string option) => option.Contains(',') ? $"\"{option}\"" : option; + string OptionsToString(IEnumerable<string> options) => string.Join(",", options.Select(EscapeOption)); + + var runtimeArgs = new List<string>(); + + // The '--debug' runtime option is required when using the 'soft-debug' and 'dwarfdebug' AOT options + if (aotSoftDebug || aotDwarfDebug) + runtimeArgs.Add("--debug"); + + if (aotOpts.EnableLLVM) + runtimeArgs.Add("--llvm"); + + runtimeArgs.Add(aotOptions.Count > 0 ? $"--aot={OptionsToString(aotOptions)}" : "--aot"); + + if (optimizerOptions.Count > 0) + runtimeArgs.Add($"-O={OptionsToString(optimizerOptions)}"); + + runtimeArgs.Add(assemblyPath); + + return runtimeArgs; + } + + private static void ExecuteCompiler(string compiler, IEnumerable<string> compilerArgs, string bclDir) + { + // TODO: Once we move to .NET Standard 2.1 we can use ProcessStartInfo.ArgumentList instead + string CmdLineArgsToString(IEnumerable<string> args) + { + // Not perfect, but as long as we are careful... + return string.Join(" ", args.Select(arg => arg.Contains(" ") ? $@"""{arg}""" : arg)); + } + + using (var process = new Process()) + { + process.StartInfo = new ProcessStartInfo(compiler, CmdLineArgsToString(compilerArgs)) + { + UseShellExecute = false + }; + + process.StartInfo.EnvironmentVariables.Remove("MONO_ENV_OPTIONS"); + process.StartInfo.EnvironmentVariables.Remove("MONO_THREADS_SUSPEND"); + process.StartInfo.EnvironmentVariables.Add("MONO_PATH", bclDir); + + Console.WriteLine($"Running: \"{process.StartInfo.FileName}\" {process.StartInfo.Arguments}"); + + if (!process.Start()) + throw new Exception("Failed to start process for Mono AOT compiler"); + + process.WaitForExit(); + + if (process.ExitCode != 0) + throw new Exception($"Mono AOT compiler exited with code: {process.ExitCode}"); + } + } + + private static IEnumerable<string> GetEnablediOSArchs(string[] features) + { + var iosArchs = new[] + { + "armv7", + "arm64" + }; + + return iosArchs.Where(features.Contains); + } + + private static IEnumerable<string> GetEnabledAndroidAbis(string[] features) + { + var androidAbis = new[] + { + "armeabi-v7a", + "arm64-v8a", + "x86", + "x86_64" + }; + + return androidAbis.Where(features.Contains); + } + + private static string GetAndroidTriple(string abi) + { + var abiArchs = new Dictionary<string, string> + { + ["armeabi-v7a"] = "armv7", + ["arm64-v8a"] = "aarch64-v8a", + ["x86"] = "i686", + ["x86_64"] = "x86_64" + }; + + string arch = abiArchs[abi]; + + return $"{arch}-linux-android"; + } + + private static string GetMonoCrossDesktopDirName(string platform, string bits) + { + switch (platform) + { + case OS.Platforms.Windows: + case OS.Platforms.UWP: + { + string arch = bits == "64" ? "x86_64" : "i686"; + return $"windows-{arch}"; + } + case OS.Platforms.OSX: + { + Debug.Assert(bits == null || bits == "64"); + string arch = "x86_64"; + return $"{platform}-{arch}"; + } + case OS.Platforms.LinuxBSD: + case OS.Platforms.Server: + { + string arch = bits == "64" ? "x86_64" : "i686"; + return $"linux-{arch}"; + } + case OS.Platforms.Haiku: + { + string arch = bits == "64" ? "x86_64" : "i686"; + return $"{platform}-{arch}"; + } + default: + throw new NotSupportedException($"Platform not supported: {platform}"); + } + } + + // TODO: Replace this for a specific path for each platform + private static string FindCrossCompiler(string monoCrossBin) + { + string exeExt = OS.IsWindows ? ".exe" : string.Empty; + + var files = new DirectoryInfo(monoCrossBin).GetFiles($"*mono-sgen{exeExt}", SearchOption.TopDirectoryOnly); + if (files.Length > 0) + return Path.Combine(monoCrossBin, files[0].Name); + + throw new FileNotFoundException($"Cannot find the mono runtime executable in {monoCrossBin}"); + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index 022005ad0b..6bfbc62f3b 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -29,15 +29,13 @@ namespace GodotTools.Export All = CJK | MidEast | Other | Rare | West } - private void AddI18NAssemblies(Godot.Collections.Dictionary<string, string> assemblies, string platform) + private void AddI18NAssemblies(Godot.Collections.Dictionary<string, string> assemblies, string bclDir) { - var codesets = (I18NCodesets) ProjectSettings.GetSetting("mono/export/i18n_codesets"); + var codesets = (I18NCodesets)ProjectSettings.GetSetting("mono/export/i18n_codesets"); if (codesets == I18NCodesets.None) return; - string bclDir = DeterminePlatformBclDir(platform) ?? typeof(object).Assembly.Location.GetBaseDir(); - void AddI18NAssembly(string name) => assemblies.Add(name, Path.Combine(bclDir, $"{name}.dll")); AddI18NAssembly("I18N"); @@ -73,6 +71,7 @@ namespace GodotTools.Export GlobalDef("mono/export/aot/enabled", false); GlobalDef("mono/export/aot/full_aot", false); + GlobalDef("mono/export/aot/use_interpreter", true); // --aot or --aot=opt1,opt2 (use 'mono --aot=help AuxAssembly.dll' to list AOT options) GlobalDef("mono/export/aot/extra_aot_options", new string[] { }); @@ -86,9 +85,11 @@ namespace GodotTools.Export private void AddFile(string srcPath, string dstPath, bool remap = false) { + // Add file to the PCK AddFile(dstPath.Replace("\\", "/"), File.ReadAllBytes(srcPath), remap); } + // With this method we can override how a file is exported in the PCK public override void _ExportFile(string path, string type, string[] features) { base._ExportFile(path, type, features); @@ -110,6 +111,8 @@ namespace GodotTools.Export // Sadly, Godot prints errors when adding an empty file (nothing goes wrong, it's just noise). // Because of this, we add a file which contains a line break. AddFile(path, System.Text.Encoding.UTF8.GetBytes("\n"), remap: false); + + // Tell the Godot exporter that we already took care of the file Skip(); } } @@ -165,18 +168,13 @@ namespace GodotTools.Export // Add dependency assemblies - var dependencies = new Godot.Collections.Dictionary<string, string>(); - - var projectDllName = (string)ProjectSettings.GetSetting("application/config/name"); - if (projectDllName.Empty()) - { - projectDllName = "UnnamedProject"; - } + var assemblies = new Godot.Collections.Dictionary<string, string>(); + string projectDllName = GodotSharpEditor.ProjectAssemblyName; string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig); string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll"); - dependencies[projectDllName] = projectDllSrcPath; + assemblies[projectDllName] = projectDllSrcPath; if (platform == OS.Platforms.Android) { @@ -186,13 +184,15 @@ namespace GodotTools.Export if (!File.Exists(monoAndroidAssemblyPath)) throw new FileNotFoundException("Assembly not found: 'Mono.Android'", monoAndroidAssemblyPath); - dependencies["Mono.Android"] = monoAndroidAssemblyPath; + assemblies["Mono.Android"] = monoAndroidAssemblyPath; } - var initialDependencies = dependencies.Duplicate(); - internal_GetExportedAssemblyDependencies(initialDependencies, buildConfig, DeterminePlatformBclDir(platform), dependencies); + string bclDir = DeterminePlatformBclDir(platform); + + var initialAssemblies = assemblies.Duplicate(); + internal_GetExportedAssemblyDependencies(initialAssemblies, buildConfig, bclDir, assemblies); - AddI18NAssemblies(dependencies, platform); + AddI18NAssemblies(assemblies, bclDir); string outputDataDir = null; @@ -211,27 +211,62 @@ namespace GodotTools.Export Directory.CreateDirectory(outputDataGameAssembliesDir); } - foreach (var dependency in dependencies) + foreach (var assembly in assemblies) { - string dependSrcPath = dependency.Value; - - if (assembliesInsidePck) - { - string dependDstPath = Path.Combine(resAssembliesDir, dependSrcPath.GetFile()); - AddFile(dependSrcPath, dependDstPath); - } - else + void AddToAssembliesDir(string fileSrcPath) { - string dependDstPath = Path.Combine(outputDataDir, "Assemblies", dependSrcPath.GetFile()); - File.Copy(dependSrcPath, dependDstPath); + if (assembliesInsidePck) + { + string fileDstPath = Path.Combine(resAssembliesDir, fileSrcPath.GetFile()); + AddFile(fileSrcPath, fileDstPath); + } + else + { + Debug.Assert(outputDataDir != null); + string fileDstPath = Path.Combine(outputDataDir, "Assemblies", fileSrcPath.GetFile()); + File.Copy(fileSrcPath, fileDstPath); + } } + + string assemblySrcPath = assembly.Value; + + string assemblyPathWithoutExtension = Path.ChangeExtension(assemblySrcPath, null); + string pdbSrcPath = assemblyPathWithoutExtension + ".pdb"; + + AddToAssembliesDir(assemblySrcPath); + + if (File.Exists(pdbSrcPath)) + AddToAssembliesDir(pdbSrcPath); } - // AOT + // AOT compilation + bool aotEnabled = platform == OS.Platforms.iOS || (bool)ProjectSettings.GetSetting("mono/export/aot/enabled"); - if ((bool)ProjectSettings.GetSetting("mono/export/aot/enabled")) + if (aotEnabled) { - AotCompileDependencies(features, platform, isDebug, outputDir, outputDataDir, dependencies); + string aotToolchainPath = null; + + if (platform == OS.Platforms.Android) + aotToolchainPath = (string)ProjectSettings.GetSetting("mono/export/aot/android_toolchain_path"); + + if (aotToolchainPath == string.Empty) + aotToolchainPath = null; // Don't risk it being used as current working dir + + // TODO: LLVM settings are hard-coded and disabled for now + var aotOpts = new AotOptions + { + EnableLLVM = false, + LLVMOnly = false, + LLVMPath = "", + LLVMOutputPath = "", + FullAot = platform == OS.Platforms.iOS || (bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false), + UseInterpreter = (bool)ProjectSettings.GetSetting("mono/export/aot/use_interpreter"), + ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? new string[] { }, + ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? new string[] { }, + ToolchainPath = aotToolchainPath + }; + + AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, assemblies); } } @@ -258,7 +293,8 @@ namespace GodotTools.Export { string target = isDebug ? "release_debug" : "release"; - // NOTE: Bits is ok for now as all platforms with a data directory have it, but that may change in the future. + // NOTE: Bits is ok for now as all platforms with a data directory only have one or two architectures. + // However, this may change in the future if we add arm linux or windows desktop templates. string bits = features.Contains("64") ? "64" : "32"; string TemplateDirName() => $"data.mono.{platform}.{bits}.{target}"; @@ -284,7 +320,7 @@ namespace GodotTools.Export if (!validTemplatePathFound) throw new FileNotFoundException("Data template directory not found", templateDirPath); - string outputDataDir = Path.Combine(outputDir, DataDirName); + string outputDataDir = Path.Combine(outputDir, DetermineDataDirNameForProject()); if (Directory.Exists(outputDataDir)) Directory.Delete(outputDataDir, recursive: true); // Clean first @@ -304,333 +340,10 @@ namespace GodotTools.Export return outputDataDir; } - private void AotCompileDependencies(string[] features, string platform, bool isDebug, string outputDir, string outputDataDir, IDictionary<string, string> dependencies) - { - // TODO: WASM - - string bclDir = DeterminePlatformBclDir(platform) ?? typeof(object).Assembly.Location.GetBaseDir(); - - string aotTempDir = Path.Combine(Path.GetTempPath(), $"godot-aot-{Process.GetCurrentProcess().Id}"); - - if (!Directory.Exists(aotTempDir)) - Directory.CreateDirectory(aotTempDir); - - var assemblies = new Dictionary<string, string>(); - - foreach (var dependency in dependencies) - { - string assemblyName = dependency.Key; - string assemblyPath = dependency.Value; - - string assemblyPathInBcl = Path.Combine(bclDir, assemblyName + ".dll"); - - if (File.Exists(assemblyPathInBcl)) - { - // Don't create teporaries for assemblies from the BCL - assemblies.Add(assemblyName, assemblyPathInBcl); - } - else - { - string tempAssemblyPath = Path.Combine(aotTempDir, assemblyName + ".dll"); - File.Copy(assemblyPath, tempAssemblyPath); - assemblies.Add(assemblyName, tempAssemblyPath); - } - } - - foreach (var assembly in assemblies) - { - string assemblyName = assembly.Key; - string assemblyPath = assembly.Value; - - string sharedLibExtension = platform == OS.Platforms.Windows ? ".dll" : - platform == OS.Platforms.OSX ? ".dylib" : - platform == OS.Platforms.HTML5 ? ".wasm" : - ".so"; - - string outputFileName = assemblyName + ".dll" + sharedLibExtension; - - if (platform == OS.Platforms.Android) - { - // Not sure if the 'lib' prefix is an Android thing or just Godot being picky, - // but we use '-aot-' as well just in case to avoid conflicts with other libs. - outputFileName = "lib-aot-" + outputFileName; - } - - string outputFilePath = null; - string tempOutputFilePath; - - switch (platform) - { - case OS.Platforms.OSX: - tempOutputFilePath = Path.Combine(aotTempDir, outputFileName); - break; - case OS.Platforms.Android: - tempOutputFilePath = Path.Combine(aotTempDir, "%%ANDROID_ABI%%", outputFileName); - break; - case OS.Platforms.HTML5: - tempOutputFilePath = Path.Combine(aotTempDir, outputFileName); - outputFilePath = Path.Combine(outputDir, outputFileName); - break; - default: - tempOutputFilePath = Path.Combine(aotTempDir, outputFileName); - outputFilePath = Path.Combine(outputDataDir, "Mono", platform == OS.Platforms.Windows ? "bin" : "lib", outputFileName); - break; - } - - var data = new Dictionary<string, string>(); - var enabledAndroidAbis = platform == OS.Platforms.Android ? GetEnabledAndroidAbis(features).ToArray() : null; - - if (platform == OS.Platforms.Android) - { - Debug.Assert(enabledAndroidAbis != null); - - foreach (var abi in enabledAndroidAbis) - { - data["abi"] = abi; - var outputFilePathForThisAbi = tempOutputFilePath.Replace("%%ANDROID_ABI%%", abi); - - AotCompileAssembly(platform, isDebug, data, assemblyPath, outputFilePathForThisAbi); - - AddSharedObject(outputFilePathForThisAbi, tags: new[] { abi }); - } - } - else - { - string bits = features.Contains("64") ? "64" : features.Contains("64") ? "32" : null; - - if (bits != null) - data["bits"] = bits; - - AotCompileAssembly(platform, isDebug, data, assemblyPath, tempOutputFilePath); - - if (platform == OS.Platforms.OSX) - { - AddSharedObject(tempOutputFilePath, tags: null); - } - else - { - Debug.Assert(outputFilePath != null); - File.Copy(tempOutputFilePath, outputFilePath); - } - } - } - } - - private static void AotCompileAssembly(string platform, bool isDebug, Dictionary<string, string> data, string assemblyPath, string outputFilePath) - { - // Make sure the output directory exists - Directory.CreateDirectory(outputFilePath.GetBaseDir()); - - string exeExt = OS.IsWindows ? ".exe" : string.Empty; - - string monoCrossDirName = DetermineMonoCrossDirName(platform, data); - string monoCrossRoot = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "aot-compilers", monoCrossDirName); - string monoCrossBin = Path.Combine(monoCrossRoot, "bin"); - - string toolPrefix = DetermineToolPrefix(monoCrossBin); - string monoExeName = System.IO.File.Exists(Path.Combine(monoCrossBin, $"{toolPrefix}mono{exeExt}")) ? "mono" : "mono-sgen"; - - string compilerCommand = Path.Combine(monoCrossBin, $"{toolPrefix}{monoExeName}{exeExt}"); - - bool fullAot = (bool)ProjectSettings.GetSetting("mono/export/aot/full_aot"); - - string EscapeOption(string option) => option.Contains(',') ? $"\"{option}\"" : option; - string OptionsToString(IEnumerable<string> options) => string.Join(",", options.Select(EscapeOption)); - - var aotOptions = new List<string>(); - var optimizerOptions = new List<string>(); - - if (fullAot) - aotOptions.Add("full"); - - aotOptions.Add(isDebug ? "soft-debug" : "nodebug"); - - if (platform == OS.Platforms.Android) - { - string abi = data["abi"]; - - string androidToolchain = (string)ProjectSettings.GetSetting("mono/export/aot/android_toolchain_path"); - - if (string.IsNullOrEmpty(androidToolchain)) - { - androidToolchain = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "android-toolchains", $"{abi}"); // TODO: $"{abi}-{apiLevel}{(clang?"clang":"")}" - - if (!Directory.Exists(androidToolchain)) - throw new FileNotFoundException("Missing android toolchain. Specify one in the AOT export settings."); - } - else if (!Directory.Exists(androidToolchain)) - { - throw new FileNotFoundException("Android toolchain not found: " + androidToolchain); - } - - var androidToolPrefixes = new Dictionary<string, string> - { - ["armeabi-v7a"] = "arm-linux-androideabi-", - ["arm64-v8a"] = "aarch64-linux-android-", - ["x86"] = "i686-linux-android-", - ["x86_64"] = "x86_64-linux-android-" - }; - - aotOptions.Add("tool-prefix=" + Path.Combine(androidToolchain, "bin", androidToolPrefixes[abi])); - - string triple = GetAndroidTriple(abi); - aotOptions.Add($"mtriple={triple}"); - } - - aotOptions.Add($"outfile={outputFilePath}"); - - var extraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options"); - var extraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options"); - - if (extraAotOptions.Length > 0) - aotOptions.AddRange(extraAotOptions); - - if (extraOptimizerOptions.Length > 0) - optimizerOptions.AddRange(extraOptimizerOptions); - - var compilerArgs = new List<string>(); - - if (isDebug) - compilerArgs.Add("--debug"); // Required for --aot=soft-debug - - compilerArgs.Add(aotOptions.Count > 0 ? $"--aot={OptionsToString(aotOptions)}" : "--aot"); - - if (optimizerOptions.Count > 0) - compilerArgs.Add($"-O={OptionsToString(optimizerOptions)}"); - - compilerArgs.Add(ProjectSettings.GlobalizePath(assemblyPath)); - - // TODO: Once we move to .NET Standard 2.1 we can use ProcessStartInfo.ArgumentList instead - string CmdLineArgsToString(IEnumerable<string> args) - { - // Not perfect, but as long as we are careful... - return string.Join(" ", args.Select(arg => arg.Contains(" ") ? $@"""{arg}""" : arg)); - } - - using (var process = new Process()) - { - process.StartInfo = new ProcessStartInfo(compilerCommand, CmdLineArgsToString(compilerArgs)) - { - UseShellExecute = false - }; - - string platformBclDir = DeterminePlatformBclDir(platform); - process.StartInfo.EnvironmentVariables.Add("MONO_PATH", string.IsNullOrEmpty(platformBclDir) ? - typeof(object).Assembly.Location.GetBaseDir() : - platformBclDir); - - Console.WriteLine($"Running: \"{process.StartInfo.FileName}\" {process.StartInfo.Arguments}"); - - if (!process.Start()) - throw new Exception("Failed to start process for Mono AOT compiler"); - - process.WaitForExit(); - - if (process.ExitCode != 0) - throw new Exception($"Mono AOT compiler exited with error code: {process.ExitCode}"); - - if (!System.IO.File.Exists(outputFilePath)) - throw new Exception("Mono AOT compiler finished successfully but the output file is missing"); - } - } - - private static string DetermineMonoCrossDirName(string platform, IReadOnlyDictionary<string, string> data) - { - switch (platform) - { - case OS.Platforms.Windows: - case OS.Platforms.UWP: - { - string arch = data["bits"] == "64" ? "x86_64" : "i686"; - return $"windows-{arch}"; - } - case OS.Platforms.OSX: - { - string arch = "x86_64"; - return $"{platform}-{arch}"; - } - case OS.Platforms.X11: - case OS.Platforms.Server: - { - string arch = data["bits"] == "64" ? "x86_64" : "i686"; - return $"linux-{arch}"; - } - case OS.Platforms.Haiku: - { - string arch = data["bits"] == "64" ? "x86_64" : "i686"; - return $"{platform}-{arch}"; - } - case OS.Platforms.Android: - { - string abi = data["abi"]; - return $"{platform}-{abi}"; - } - case OS.Platforms.HTML5: - return "wasm-wasm32"; - default: - throw new NotSupportedException($"Platform not supported: {platform}"); - } - } - - private static string DetermineToolPrefix(string monoCrossBin) - { - string exeExt = OS.IsWindows ? ".exe" : string.Empty; - - if (System.IO.File.Exists(Path.Combine(monoCrossBin, $"mono{exeExt}"))) - return string.Empty; - - if (System.IO.File.Exists(Path.Combine(monoCrossBin, $"mono-sgen{exeExt}" + exeExt))) - return string.Empty; - - var files = new DirectoryInfo(monoCrossBin).GetFiles($"*mono{exeExt}" + exeExt, SearchOption.TopDirectoryOnly); - if (files.Length > 0) - { - string fileName = files[0].Name; - return fileName.Substring(0, fileName.Length - $"mono{exeExt}".Length); - } - - files = new DirectoryInfo(monoCrossBin).GetFiles($"*mono-sgen{exeExt}" + exeExt, SearchOption.TopDirectoryOnly); - if (files.Length > 0) - { - string fileName = files[0].Name; - return fileName.Substring(0, fileName.Length - $"mono-sgen{exeExt}".Length); - } - - throw new FileNotFoundException($"Cannot find the mono runtime executable in {monoCrossBin}"); - } - - private static IEnumerable<string> GetEnabledAndroidAbis(string[] features) - { - var androidAbis = new[] - { - "armeabi-v7a", - "arm64-v8a", - "x86", - "x86_64" - }; - - return androidAbis.Where(features.Contains); - } - - private static string GetAndroidTriple(string abi) - { - var abiArchs = new Dictionary<string, string> - { - ["armeabi-v7a"] = "armv7", - ["arm64-v8a"] = "aarch64-v8a", - ["x86"] = "i686", - ["x86_64"] = "x86_64" - }; - - string arch = abiArchs[abi]; - - return $"{arch}-linux-android"; - } - private static bool PlatformHasTemplateDir(string platform) { // OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest. - return !new[] { OS.Platforms.OSX, OS.Platforms.Android, OS.Platforms.HTML5 }.Contains(platform); + return !new[] { OS.Platforms.OSX, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform); } private static string DeterminePlatformFromFeatures(IEnumerable<string> features) @@ -665,7 +378,7 @@ namespace GodotTools.Export if (PlatformRequiresCustomBcl(platform)) throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}"); - platformBclDir = null; // Use the one we're running on + platformBclDir = typeof(object).Assembly.Location.GetBaseDir(); // Use the one we're running on } } @@ -678,7 +391,7 @@ namespace GodotTools.Export /// </summary> private static bool PlatformRequiresCustomBcl(string platform) { - if (new[] { OS.Platforms.Android, OS.Platforms.HTML5 }.Contains(platform)) + if (new[] { OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform)) return true; // The 'net_4_x' BCL is not compatible between Windows and the other platforms. @@ -701,12 +414,14 @@ namespace GodotTools.Export case OS.Platforms.UWP: return "net_4_x_win"; case OS.Platforms.OSX: - case OS.Platforms.X11: + case OS.Platforms.LinuxBSD: case OS.Platforms.Server: case OS.Platforms.Haiku: return "net_4_x"; case OS.Platforms.Android: return "monodroid"; + case OS.Platforms.iOS: + return "monotouch"; case OS.Platforms.HTML5: return "wasm"; default: @@ -714,18 +429,15 @@ namespace GodotTools.Export } } - private static string DataDirName + private static string DetermineDataDirNameForProject() { - get - { - var appName = (string)ProjectSettings.GetSetting("application/config/name"); - string appNameSafe = appName.ToSafeDirName(allowDirSeparator: false); - return $"data_{appNameSafe}"; - } + var appName = (string)ProjectSettings.GetSetting("application/config/name"); + string appNameSafe = appName.ToSafeDirName(allowDirSeparator: false); + return $"data_{appNameSafe}"; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialDependencies, - string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencies); + private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialAssemblies, + string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencyAssemblies); } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/XcodeHelper.cs b/modules/mono/editor/GodotTools/GodotTools/Export/XcodeHelper.cs new file mode 100755 index 0000000000..219b7a698a --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools/Export/XcodeHelper.cs @@ -0,0 +1,93 @@ +using System; +using System.IO; + +namespace GodotTools.Export +{ + public static class XcodeHelper + { + private static string _XcodePath = null; + + public static string XcodePath + { + get + { + if (_XcodePath == null) + { + _XcodePath = FindXcode(); + + if (_XcodePath == null) + throw new Exception("Could not find Xcode"); + } + + return _XcodePath; + } + } + + private static string FindSelectedXcode() + { + var outputWrapper = new Godot.Collections.Array(); + + int exitCode = Godot.OS.Execute("xcode-select", new string[] { "--print-path" }, blocking: true, output: outputWrapper); + + if (exitCode == 0) + { + string output = (string)outputWrapper[0]; + return output.Trim(); + } + + Console.Error.WriteLine($"'xcode-select --print-path' exited with code: {exitCode}"); + + return null; + } + + public static string FindXcode() + { + string selectedXcode = FindSelectedXcode(); + if (selectedXcode != null) + { + if (Directory.Exists(Path.Combine(selectedXcode, "Contents", "Developer"))) + return selectedXcode; + + // The path already pointed to Contents/Developer + var dirInfo = new DirectoryInfo(selectedXcode); + if (dirInfo.Name != "Developer" || dirInfo.Parent.Name != "Contents") + { + Console.WriteLine(Path.GetDirectoryName(selectedXcode)); + Console.WriteLine(System.IO.Directory.GetParent(selectedXcode).Name); + Console.Error.WriteLine("Unrecognized path for selected Xcode"); + } + else + { + return System.IO.Path.GetFullPath($"{selectedXcode}/../.."); + } + } + else + { + Console.Error.WriteLine("Could not find the selected Xcode; trying with a hint path"); + } + + const string XcodeHintPath = "/Applications/Xcode.app"; + + if (Directory.Exists(XcodeHintPath)) + { + if (Directory.Exists(Path.Combine(XcodeHintPath, "Contents", "Developer"))) + return XcodeHintPath; + + Console.Error.WriteLine($"Found Xcode at '{XcodeHintPath}' but it's missing the 'Contents/Developer' sub-directory"); + } + + return null; + } + + public static string FindXcodeTool(string toolName) + { + string XcodeDefaultToolchain = Path.Combine(XcodePath, "Contents", "Developer", "Toolchains", "XcodeDefault.xctoolchain"); + + string path = Path.Combine(XcodeDefaultToolchain, "usr", "bin", toolName); + if (File.Exists(path)) + return path; + + throw new FileNotFoundException($"Cannot find Xcode tool: {toolName}"); + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index e6d5dd9895..eb7696685f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -1,4 +1,5 @@ using Godot; +using GodotTools.Core; using GodotTools.Export; using GodotTools.Utils; using System; @@ -36,6 +37,19 @@ namespace GodotTools public BottomPanel BottomPanel { get; private set; } + public PlaySettings? CurrentPlaySettings { get; set; } + + public static string ProjectAssemblyName + { + get + { + var projectAssemblyName = (string)ProjectSettings.GetSetting("application/config/name"); + if (string.IsNullOrEmpty(projectAssemblyName)) + projectAssemblyName = "UnnamedProject"; + return projectAssemblyName; + } + } + private bool CreateProjectSolution() { using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 3)) @@ -45,9 +59,7 @@ namespace GodotTools string resourceDir = ProjectSettings.GlobalizePath("res://"); string path = resourceDir; - string name = (string)ProjectSettings.GetSetting("application/config/name"); - if (name.Empty()) - name = "UnnamedProject"; + string name = ProjectAssemblyName; string guid = CsProjOperations.GenerateGameProject(path, name); @@ -119,7 +131,7 @@ namespace GodotTools { bool showOnStart = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start"); aboutDialogCheckBox.Pressed = showOnStart; - aboutDialog.PopupCenteredMinsize(); + aboutDialog.PopupCentered(); } private void _MenuOptionPressed(int id) @@ -157,10 +169,10 @@ namespace GodotTools bool showInfoDialog = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start"); if (showInfoDialog) { - aboutDialog.PopupExclusive = true; + aboutDialog.Exclusive = true; _ShowAboutDialog(); // Once shown a first time, it can be seen again via the Mono menu - it doesn't have to be exclusive from that time on. - aboutDialog.PopupExclusive = false; + aboutDialog.Exclusive = false; } var fileSystemDock = GetEditorInterface().GetFileSystemDock(); @@ -203,9 +215,9 @@ namespace GodotTools public void ShowErrorDialog(string message, string title = "Error") { - errorDialog.WindowTitle = title; + errorDialog.Title = title; errorDialog.DialogText = message; - errorDialog.PopupCenteredMinsize(); + errorDialog.PopupCentered(); } private static string _vsCodePath = string.Empty; @@ -218,12 +230,12 @@ namespace GodotTools [UsedImplicitly] public Error OpenInExternalEditor(Script script, int line, int col) { - var editor = (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor"); + var editorId = (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor"); - switch (editor) + switch (editorId) { case ExternalEditorId.None: - // Tells the caller to fallback to the global external editor settings or the built-in editor + // Not an error. Tells the caller to fallback to the global external editor settings or the built-in editor. return Error.Unavailable; case ExternalEditorId.VisualStudio: throw new NotSupportedException(); @@ -239,17 +251,20 @@ namespace GodotTools { string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath); - if (line >= 0) - GodotIdeManager.SendOpenFile(scriptPath, line + 1, col); - else - GodotIdeManager.SendOpenFile(scriptPath); + GodotIdeManager.LaunchIdeAsync().ContinueWith(launchTask => + { + var editorPick = launchTask.Result; + if (line >= 0) + editorPick?.SendOpenFile(scriptPath, line + 1, col); + else + editorPick?.SendOpenFile(scriptPath); + }); break; } - case ExternalEditorId.VsCode: { - if (_vsCodePath.Empty() || !File.Exists(_vsCodePath)) + if (string.IsNullOrEmpty(_vsCodePath) || !File.Exists(_vsCodePath)) { // Try to search it again if it wasn't found last time or if it was removed from its location _vsCodePath = VsCodeNames.SelectFirstNotNull(OS.PathWhich, orElse: string.Empty); @@ -290,7 +305,7 @@ namespace GodotTools if (line >= 0) { args.Add("-g"); - args.Add($"{scriptPath}:{line + 1}:{col}"); + args.Add($"{scriptPath}:{line}:{col}"); } else { @@ -301,7 +316,7 @@ namespace GodotTools if (OS.IsOSX) { - if (!osxAppBundleInstalled && _vsCodePath.Empty()) + if (!osxAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) { GD.PushError("Cannot find code editor: VSCode"); return Error.FileNotFound; @@ -311,7 +326,7 @@ namespace GodotTools } else { - if (_vsCodePath.Empty()) + if (string.IsNullOrEmpty(_vsCodePath)) { GD.PushError("Cannot find code editor: VSCode"); return Error.FileNotFound; @@ -331,7 +346,6 @@ namespace GodotTools break; } - default: throw new ArgumentOutOfRangeException(); } @@ -374,7 +388,6 @@ namespace GodotTools menuPopup = new PopupMenu(); menuPopup.Hide(); - menuPopup.SetAsToplevel(true); AddToolSubmenuItem("Mono", menuPopup); @@ -383,7 +396,7 @@ namespace GodotTools menuPopup.AddItem("About C# support".TTR(), (int)MenuOptions.AboutCSharp); aboutDialog = new AcceptDialog(); editorBaseControl.AddChild(aboutDialog); - aboutDialog.WindowTitle = "Important: C# support is not feature-complete"; + aboutDialog.Title = "Important: C# support is not feature-complete"; // We don't use DialogText as the default AcceptDialog Label doesn't play well with the TextureRect and CheckBox // we'll add. Instead we add containers and a new autowrapped Label inside. @@ -397,7 +410,7 @@ namespace GodotTools aboutVBox.AddChild(aboutHBox); var aboutIcon = new TextureRect(); - aboutIcon.Texture = aboutIcon.GetIcon("NodeWarning", "EditorIcons"); + aboutIcon.Texture = aboutIcon.GetThemeIcon("NodeWarning", "EditorIcons"); aboutHBox.AddChild(aboutIcon); var aboutLabel = new Label(); @@ -434,13 +447,30 @@ namespace GodotTools { // Migrate solution from old configuration names to: Debug, ExportDebug and ExportRelease DotNetSolution.MigrateFromOldConfigNames(GodotSharpDirs.ProjectSlnPath); + + var msbuildProject = ProjectUtils.Open(GodotSharpDirs.ProjectCsProjPath) + ?? throw new Exception("Cannot open C# project"); + + // NOTE: The order in which changes are made to the project is important + // Migrate csproj from old configuration names to: Debug, ExportDebug and ExportRelease - ProjectUtils.MigrateFromOldConfigNames(GodotSharpDirs.ProjectCsProjPath); + ProjectUtils.MigrateFromOldConfigNames(msbuildProject); - // Apply the other fixes after configurations are migrated + // Apply the other fixes only after configurations have been migrated // Make sure the existing project has Api assembly references configured correctly - ProjectUtils.FixApiHintPath(GodotSharpDirs.ProjectCsProjPath); + ProjectUtils.FixApiHintPath(msbuildProject); + + // Make sure the existing project references the Microsoft.NETFramework.ReferenceAssemblies nuget package + ProjectUtils.EnsureHasNugetNetFrameworkRefAssemblies(msbuildProject); + + if (msbuildProject.HasUnsavedChanges) + { + // Save a copy of the project before replacing it + FileUtils.SaveBackupCopy(GodotSharpDirs.ProjectCsProjPath); + + msbuildProject.Save(); + } } catch (Exception e) { @@ -482,7 +512,7 @@ namespace GodotTools $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" + $",JetBrains Rider:{(int)ExternalEditorId.Rider}"; } - else if (OS.IsUnixLike()) + else if (OS.IsUnixLike) { settingsHintStr += $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" + $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" + diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index 379dfd9f7d..ba527ca3b5 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -1,121 +1,37 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid> - <OutputType>Library</OutputType> - <RootNamespace>GodotTools</RootNamespace> - <AssemblyName>GodotTools</AssemblyName> - <TargetFrameworkVersion>v4.7</TargetFrameworkVersion> + <TargetFramework>net472</TargetFramework> + <LangVersion>7.2</LangVersion> + <GodotApiConfiguration>Debug</GodotApiConfiguration> <!-- The Godot editor uses the Debug Godot API assemblies --> <GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath> - <DataDirToolsOutputPath>$(GodotSourceRootPath)/bin/GodotSharp/Tools</DataDirToolsOutputPath> - <GodotApiConfiguration>Debug</GodotApiConfiguration> - <LangVersion>7</LangVersion> + <GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir> + <GodotApiAssembliesDir>$(GodotOutputDataDir)/Api/$(GodotApiConfiguration)</GodotApiAssembliesDir> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>portable</DebugType> - <Optimize>false</Optimize> - <OutputPath>bin\Debug</OutputPath> - <DefineConstants>DEBUG;</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <ConsolePause>false</ConsolePause> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <Optimize>true</Optimize> - <OutputPath>bin\Release</OutputPath> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <ConsolePause>false</ConsolePause> + <PropertyGroup Condition=" Exists('$(GodotApiAssembliesDir)/GodotSharp.dll') "> + <!-- The project is part of the Godot source tree --> + <!-- Use the Godot source tree output folder instead of '$(ProjectDir)/bin' --> + <OutputPath>$(GodotOutputDataDir)/Tools</OutputPath> + <!-- Must not append '$(TargetFramework)' to the output path in this case --> + <AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath> </PropertyGroup> <ItemGroup> - <Reference Include="JetBrains.Annotations, Version=2019.1.3.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325"> - <HintPath>..\packages\JetBrains.Annotations.2019.1.3\lib\net20\JetBrains.Annotations.dll</HintPath> - <Private>True</Private> - </Reference> - <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"> - <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> - <Private>True</Private> - </Reference> - <Reference Include="System" /> + <PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" /> + <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> + <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <Reference Include="GodotSharp"> - <HintPath>$(GodotSourceRootPath)/bin/GodotSharp/Api/$(GodotApiConfiguration)/GodotSharp.dll</HintPath> + <HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath> <Private>False</Private> </Reference> <Reference Include="GodotSharpEditor"> - <HintPath>$(GodotSourceRootPath)/bin/GodotSharp/Api/$(GodotApiConfiguration)/GodotSharpEditor.dll</HintPath> + <HintPath>$(GodotApiAssembliesDir)/GodotSharpEditor.dll</HintPath> <Private>False</Private> </Reference> </ItemGroup> <ItemGroup> - <Compile Include="Build\MsBuildFinder.cs" /> - <Compile Include="Export\ExportPlugin.cs" /> - <Compile Include="ExternalEditorId.cs" /> - <Compile Include="Ides\GodotIdeManager.cs" /> - <Compile Include="Ides\GodotIdeServer.cs" /> - <Compile Include="Ides\MonoDevelop\EditorId.cs" /> - <Compile Include="Ides\MonoDevelop\Instance.cs" /> - <Compile Include="Ides\Rider\RiderPathLocator.cs" /> - <Compile Include="Ides\Rider\RiderPathManager.cs" /> - <Compile Include="Internals\EditorProgress.cs" /> - <Compile Include="Internals\GodotSharpDirs.cs" /> - <Compile Include="Internals\Internal.cs" /> - <Compile Include="Internals\ScriptClassParser.cs" /> - <Compile Include="Internals\Globals.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="Build\BuildSystem.cs" /> - <Compile Include="Utils\Directory.cs" /> - <Compile Include="Utils\File.cs" /> - <Compile Include="Utils\NotifyAwaiter.cs" /> - <Compile Include="Utils\OS.cs" /> - <Compile Include="GodotSharpEditor.cs" /> - <Compile Include="BuildManager.cs" /> - <Compile Include="HotReloadAssemblyWatcher.cs" /> - <Compile Include="BuildInfo.cs" /> - <Compile Include="BuildTab.cs" /> - <Compile Include="BottomPanel.cs" /> - <Compile Include="CsProjOperations.cs" /> - <Compile Include="Utils\CollectionExtensions.cs" /> - <Compile Include="Utils\User32Dll.cs" /> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\GodotTools.BuildLogger\GodotTools.BuildLogger.csproj"> - <Project>{6ce9a984-37b1-4f8a-8fe9-609f05f071b3}</Project> - <Name>GodotTools.BuildLogger</Name> - </ProjectReference> - <ProjectReference Include="..\GodotTools.IdeConnection\GodotTools.IdeConnection.csproj"> - <Project>{92600954-25f0-4291-8e11-1fee9fc4be20}</Project> - <Name>GodotTools.IdeConnection</Name> - </ProjectReference> - <ProjectReference Include="..\GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj"> - <Project>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</Project> - <Name>GodotTools.ProjectEditor</Name> - </ProjectReference> - <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj"> - <Project>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</Project> - <Name>GodotTools.Core</Name> - </ProjectReference> - </ItemGroup> - <ItemGroup> - <None Include="packages.config" /> + <ProjectReference Include="..\GodotTools.BuildLogger\GodotTools.BuildLogger.csproj" /> + <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" /> + <ProjectReference Include="..\GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj" /> + <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" /> </ItemGroup> - <Target Name="CopyToDataDir" AfterTargets="Build"> - <ItemGroup> - <GodotToolsCopy Include="$(OutputPath)\GodotTools*.dll" /> - <GodotToolsCopy Include="$(OutputPath)\Newtonsoft.Json.dll" /> - <GodotToolsCopy Include="$(OutputPath)\DotNet.Glob.dll" /> - </ItemGroup> - <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> - <GodotToolsCopy Include="$(OutputPath)\GodotTools*.pdb" /> - </ItemGroup> - <Copy SourceFiles="@(GodotToolsCopy)" DestinationFolder="$(DataDirToolsOutputPath)" ContinueOnError="false" /> - </Target> - <Target Name="BuildAlwaysCopyToDataDir"> - <!-- Custom target run by SCons to make sure the CopyToDataDir target is always executed, without having to use DisableFastUpToDateCheck --> - <CallTarget Targets="Build" /> - <CallTarget Targets="CopyToDataDir" /> - </Target> - <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs index 1d19fab706..ae05710f4f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs +++ b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs @@ -10,7 +10,7 @@ namespace GodotTools public override void _Notification(int what) { - if (what == MainLoop.NotificationWmFocusIn) + if (what == Node.NotificationWmFocusIn) { RestartTimer(); diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs index 54f0ffab96..e4932ca217 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs @@ -1,73 +1,104 @@ using System; using System.IO; +using System.Threading.Tasks; using Godot; -using GodotTools.IdeConnection; +using GodotTools.IdeMessaging; +using GodotTools.IdeMessaging.Requests; using GodotTools.Internals; namespace GodotTools.Ides { - public class GodotIdeManager : Node, ISerializationListener + public sealed class GodotIdeManager : Node, ISerializationListener { - public GodotIdeServer GodotIdeServer { get; private set; } + private MessagingServer MessagingServer { get; set; } private MonoDevelop.Instance monoDevelInstance; private MonoDevelop.Instance vsForMacInstance; - private GodotIdeServer GetRunningServer() + private MessagingServer GetRunningOrNewServer() { - if (GodotIdeServer != null && !GodotIdeServer.IsDisposed) - return GodotIdeServer; - StartServer(); - return GodotIdeServer; + if (MessagingServer != null && !MessagingServer.IsDisposed) + return MessagingServer; + + MessagingServer?.Dispose(); + MessagingServer = new MessagingServer(OS.GetExecutablePath(), ProjectSettings.GlobalizePath(GodotSharpDirs.ResMetadataDir), new GodotLogger()); + + _ = MessagingServer.Listen(); + + return MessagingServer; } public override void _Ready() { - StartServer(); + _ = GetRunningOrNewServer(); } public void OnBeforeSerialize() { - GodotIdeServer?.Dispose(); } public void OnAfterDeserialize() { - StartServer(); + _ = GetRunningOrNewServer(); } - private ILogger logger; + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); - protected ILogger Logger + if (disposing) + { + MessagingServer?.Dispose(); + } + } + + private string GetExternalEditorIdentity(ExternalEditorId editorId) { - get => logger ?? (logger = new GodotLogger()); + // Manually convert to string to avoid breaking compatibility in case we rename the enum fields. + switch (editorId) + { + case ExternalEditorId.None: + return null; + case ExternalEditorId.VisualStudio: + return "VisualStudio"; + case ExternalEditorId.VsCode: + return "VisualStudioCode"; + case ExternalEditorId.Rider: + return "Rider"; + case ExternalEditorId.VisualStudioForMac: + return "VisualStudioForMac"; + case ExternalEditorId.MonoDevelop: + return "MonoDevelop"; + default: + throw new NotImplementedException(); + } } - private void StartServer() + public async Task<EditorPick?> LaunchIdeAsync(int millisecondsTimeout = 10000) { - GodotIdeServer?.Dispose(); - GodotIdeServer = new GodotIdeServer(LaunchIde, - OS.GetExecutablePath(), - ProjectSettings.GlobalizePath(GodotSharpDirs.ResMetadataDir)); + var editorId = (ExternalEditorId)GodotSharpEditor.Instance.GetEditorInterface() + .GetEditorSettings().GetSetting("mono/editor/external_editor"); + string editorIdentity = GetExternalEditorIdentity(editorId); - GodotIdeServer.Logger = Logger; + var runningServer = GetRunningOrNewServer(); - GodotIdeServer.StartServer(); - } + if (runningServer.IsAnyConnected(editorIdentity)) + return new EditorPick(editorIdentity); - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); + LaunchIde(editorId, editorIdentity); + + var timeoutTask = Task.Delay(millisecondsTimeout); + var completedTask = await Task.WhenAny(timeoutTask, runningServer.AwaitClientConnected(editorIdentity)); + + if (completedTask != timeoutTask) + return new EditorPick(editorIdentity); - GodotIdeServer?.Dispose(); + return null; } - private void LaunchIde() + private void LaunchIde(ExternalEditorId editorId, string editorIdentity) { - var editor = (ExternalEditorId)GodotSharpEditor.Instance.GetEditorInterface() - .GetEditorSettings().GetSetting("mono/editor/external_editor"); - - switch (editor) + switch (editorId) { case ExternalEditorId.None: case ExternalEditorId.VisualStudio: @@ -80,14 +111,14 @@ namespace GodotTools.Ides { MonoDevelop.Instance GetMonoDevelopInstance(string solutionPath) { - if (Utils.OS.IsOSX && editor == ExternalEditorId.VisualStudioForMac) + if (Utils.OS.IsOSX && editorId == ExternalEditorId.VisualStudioForMac) { - vsForMacInstance = vsForMacInstance ?? + vsForMacInstance = (vsForMacInstance?.IsDisposed ?? true ? null : vsForMacInstance) ?? new MonoDevelop.Instance(solutionPath, MonoDevelop.EditorId.VisualStudioForMac); return vsForMacInstance; } - monoDevelInstance = monoDevelInstance ?? + monoDevelInstance = (monoDevelInstance?.IsDisposed ?? true ? null : monoDevelInstance) ?? new MonoDevelop.Instance(solutionPath, MonoDevelop.EditorId.MonoDevelop); return monoDevelInstance; } @@ -96,12 +127,25 @@ namespace GodotTools.Ides { var instance = GetMonoDevelopInstance(GodotSharpDirs.ProjectSlnPath); - if (!instance.IsRunning) + if (instance.IsRunning && !GetRunningOrNewServer().IsAnyConnected(editorIdentity)) + { + // After launch we wait up to 30 seconds for the IDE to connect to our messaging server. + var waitAfterLaunch = TimeSpan.FromSeconds(30); + var timeSinceLaunch = DateTime.Now - instance.LaunchTime; + if (timeSinceLaunch > waitAfterLaunch) + { + instance.Dispose(); + instance.Execute(); + } + } + else if (!instance.IsRunning) + { instance.Execute(); + } } catch (FileNotFoundException) { - string editorName = editor == ExternalEditorId.VisualStudioForMac ? "Visual Studio" : "MonoDevelop"; + string editorName = editorId == ExternalEditorId.VisualStudioForMac ? "Visual Studio" : "MonoDevelop"; GD.PushError($"Cannot find code editor: {editorName}"); } @@ -113,26 +157,45 @@ namespace GodotTools.Ides } } - private void WriteMessage(string id, params string[] arguments) + public readonly struct EditorPick { - GetRunningServer().WriteMessage(new Message(id, arguments)); - } + private readonly string identity; - public void SendOpenFile(string file) - { - WriteMessage("OpenFile", file); - } + public EditorPick(string identity) + { + this.identity = identity; + } - public void SendOpenFile(string file, int line) - { - WriteMessage("OpenFile", file, line.ToString()); - } + public bool IsAnyConnected() => + GodotSharpEditor.Instance.GodotIdeManager.GetRunningOrNewServer().IsAnyConnected(identity); - public void SendOpenFile(string file, int line, int column) - { - WriteMessage("OpenFile", file, line.ToString(), column.ToString()); + private void SendRequest<TResponse>(Request request) + where TResponse : Response, new() + { + // Logs an error if no client is connected with the specified identity + GodotSharpEditor.Instance.GodotIdeManager + .GetRunningOrNewServer() + .BroadcastRequest<TResponse>(identity, request); + } + + public void SendOpenFile(string file) + { + SendRequest<OpenFileResponse>(new OpenFileRequest {File = file}); + } + + public void SendOpenFile(string file, int line) + { + SendRequest<OpenFileResponse>(new OpenFileRequest {File = file, Line = line}); + } + + public void SendOpenFile(string file, int line, int column) + { + SendRequest<OpenFileResponse>(new OpenFileRequest {File = file, Line = line, Column = column}); + } } + public EditorPick PickEditor(ExternalEditorId editorId) => new EditorPick(GetExternalEditorIdentity(editorId)); + private class GodotLogger : ILogger { public void LogDebug(string message) diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeServer.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeServer.cs deleted file mode 100644 index 72676a8b24..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeServer.cs +++ /dev/null @@ -1,212 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using GodotTools.IdeConnection; -using GodotTools.Internals; -using GodotTools.Utils; -using Directory = System.IO.Directory; -using File = System.IO.File; -using Thread = System.Threading.Thread; - -namespace GodotTools.Ides -{ - public class GodotIdeServer : GodotIdeBase - { - private readonly TcpListener listener; - private readonly FileStream metaFile; - private readonly Action launchIdeAction; - private readonly NotifyAwaiter<bool> clientConnectedAwaiter = new NotifyAwaiter<bool>(); - - private async Task<bool> AwaitClientConnected() - { - return await clientConnectedAwaiter.Reset(); - } - - public GodotIdeServer(Action launchIdeAction, string editorExecutablePath, string projectMetadataDir) - : base(projectMetadataDir) - { - messageHandlers = InitializeMessageHandlers(); - - this.launchIdeAction = launchIdeAction; - - // Make sure the directory exists - Directory.CreateDirectory(projectMetadataDir); - - // The Godot editor's file system thread can keep the file open for writing, so we are forced to allow write sharing... - const FileShare metaFileShare = FileShare.ReadWrite; - - metaFile = File.Open(MetaFilePath, FileMode.Create, FileAccess.Write, metaFileShare); - - listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, port: 0)); - listener.Start(); - - int port = ((IPEndPoint)listener.Server.LocalEndPoint).Port; - using (var metaFileWriter = new StreamWriter(metaFile, Encoding.UTF8)) - { - metaFileWriter.WriteLine(port); - metaFileWriter.WriteLine(editorExecutablePath); - } - - StartServer(); - } - - public void StartServer() - { - var serverThread = new Thread(RunServerThread) { Name = "Godot Ide Connection Server" }; - serverThread.Start(); - } - - private void RunServerThread() - { - SynchronizationContext.SetSynchronizationContext(Godot.Dispatcher.SynchronizationContext); - - try - { - while (!IsDisposed) - { - TcpClient tcpClient = listener.AcceptTcpClient(); - - Logger.LogInfo("Connection open with Ide Client"); - - lock (ConnectionLock) - { - Connection = new GodotIdeConnectionServer(tcpClient, HandleMessage); - Connection.Logger = Logger; - } - - Connected += () => clientConnectedAwaiter.SetResult(true); - - Connection.Start(); - } - } - catch (Exception e) - { - if (!IsDisposed && !(e is SocketException se && se.SocketErrorCode == SocketError.Interrupted)) - throw; - } - } - - public async void WriteMessage(Message message) - { - async Task LaunchIde() - { - if (IsConnected) - return; - - launchIdeAction(); - await Task.WhenAny(Task.Delay(10000), AwaitClientConnected()); - } - - await LaunchIde(); - - if (!IsConnected) - { - Logger.LogError("Cannot write message: Godot Ide Server not connected"); - return; - } - - Connection.WriteMessage(message); - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - if (disposing) - { - listener?.Stop(); - - metaFile?.Dispose(); - - File.Delete(MetaFilePath); - } - } - - protected virtual bool HandleMessage(Message message) - { - if (messageHandlers.TryGetValue(message.Id, out var action)) - { - action(message.Arguments); - return true; - } - - return false; - } - - private readonly Dictionary<string, Action<string[]>> messageHandlers; - - private Dictionary<string, Action<string[]>> InitializeMessageHandlers() - { - return new Dictionary<string, Action<string[]>> - { - ["Play"] = args => - { - switch (args.Length) - { - case 0: - Play(); - return; - case 2: - Play(debuggerHost: args[0], debuggerPort: int.Parse(args[1])); - return; - default: - throw new ArgumentException(); - } - }, - ["ReloadScripts"] = args => ReloadScripts() - }; - } - - private void DispatchToMainThread(Action action) - { - var d = new SendOrPostCallback(state => action()); - Godot.Dispatcher.SynchronizationContext.Post(d, null); - } - - private void Play() - { - DispatchToMainThread(() => - { - CurrentPlayRequest = new PlayRequest(); - Internal.EditorRunPlay(); - CurrentPlayRequest = null; - }); - } - - private void Play(string debuggerHost, int debuggerPort) - { - DispatchToMainThread(() => - { - CurrentPlayRequest = new PlayRequest(debuggerHost, debuggerPort); - Internal.EditorRunPlay(); - CurrentPlayRequest = null; - }); - } - - private void ReloadScripts() - { - DispatchToMainThread(Internal.ScriptEditorDebugger_ReloadScripts); - } - - public PlayRequest? CurrentPlayRequest { get; private set; } - - public struct PlayRequest - { - public bool HasDebugger { get; } - public string DebuggerHost { get; } - public int DebuggerPort { get; } - - public PlayRequest(string debuggerHost, int debuggerPort) - { - HasDebugger = true; - DebuggerHost = debuggerHost; - DebuggerPort = debuggerPort; - } - } - } -} diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs new file mode 100644 index 0000000000..32f264d100 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs @@ -0,0 +1,360 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using GodotTools.IdeMessaging; +using GodotTools.IdeMessaging.Requests; +using GodotTools.IdeMessaging.Utils; +using GodotTools.Internals; +using Newtonsoft.Json; +using Directory = System.IO.Directory; +using File = System.IO.File; + +namespace GodotTools.Ides +{ + public sealed class MessagingServer : IDisposable + { + private readonly ILogger logger; + + private readonly FileStream metaFile; + private string MetaFilePath { get; } + + private readonly SemaphoreSlim peersSem = new SemaphoreSlim(1); + + private readonly TcpListener listener; + + private readonly Dictionary<string, Queue<NotifyAwaiter<bool>>> clientConnectedAwaiters = new Dictionary<string, Queue<NotifyAwaiter<bool>>>(); + private readonly Dictionary<string, Queue<NotifyAwaiter<bool>>> clientDisconnectedAwaiters = new Dictionary<string, Queue<NotifyAwaiter<bool>>>(); + + public async Task<bool> AwaitClientConnected(string identity) + { + if (!clientConnectedAwaiters.TryGetValue(identity, out var queue)) + { + queue = new Queue<NotifyAwaiter<bool>>(); + clientConnectedAwaiters.Add(identity, queue); + } + + var awaiter = new NotifyAwaiter<bool>(); + queue.Enqueue(awaiter); + return await awaiter; + } + + public async Task<bool> AwaitClientDisconnected(string identity) + { + if (!clientDisconnectedAwaiters.TryGetValue(identity, out var queue)) + { + queue = new Queue<NotifyAwaiter<bool>>(); + clientDisconnectedAwaiters.Add(identity, queue); + } + + var awaiter = new NotifyAwaiter<bool>(); + queue.Enqueue(awaiter); + return await awaiter; + } + + public bool IsDisposed { get; private set; } + + public bool IsAnyConnected(string identity) => string.IsNullOrEmpty(identity) ? + Peers.Count > 0 : + Peers.Any(c => c.RemoteIdentity == identity); + + private List<Peer> Peers { get; } = new List<Peer>(); + + ~MessagingServer() + { + Dispose(disposing: false); + } + + public async void Dispose() + { + if (IsDisposed) + return; + + using (await peersSem.UseAsync()) + { + if (IsDisposed) // lock may not be fair + return; + IsDisposed = true; + } + + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + foreach (var connection in Peers) + connection.Dispose(); + Peers.Clear(); + listener?.Stop(); + + metaFile?.Dispose(); + + File.Delete(MetaFilePath); + } + } + + public MessagingServer(string editorExecutablePath, string projectMetadataDir, ILogger logger) + { + this.logger = logger; + + MetaFilePath = Path.Combine(projectMetadataDir, GodotIdeMetadata.DefaultFileName); + + // Make sure the directory exists + Directory.CreateDirectory(projectMetadataDir); + + // The Godot editor's file system thread can keep the file open for writing, so we are forced to allow write sharing... + const FileShare metaFileShare = FileShare.ReadWrite; + + metaFile = File.Open(MetaFilePath, FileMode.Create, FileAccess.Write, metaFileShare); + + listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, port: 0)); + listener.Start(); + + int port = ((IPEndPoint)listener.Server.LocalEndPoint).Port; + using (var metaFileWriter = new StreamWriter(metaFile, Encoding.UTF8)) + { + metaFileWriter.WriteLine(port); + metaFileWriter.WriteLine(editorExecutablePath); + } + } + + private async Task AcceptClient(TcpClient tcpClient) + { + logger.LogDebug("Accept client..."); + + using (var peer = new Peer(tcpClient, new ServerHandshake(), new ServerMessageHandler(), logger)) + { + // ReSharper disable AccessToDisposedClosure + peer.Connected += () => + { + logger.LogInfo("Connection open with Ide Client"); + + if (clientConnectedAwaiters.TryGetValue(peer.RemoteIdentity, out var queue)) + { + while (queue.Count > 0) + queue.Dequeue().SetResult(true); + clientConnectedAwaiters.Remove(peer.RemoteIdentity); + } + }; + + peer.Disconnected += () => + { + if (clientDisconnectedAwaiters.TryGetValue(peer.RemoteIdentity, out var queue)) + { + while (queue.Count > 0) + queue.Dequeue().SetResult(true); + clientDisconnectedAwaiters.Remove(peer.RemoteIdentity); + } + }; + // ReSharper restore AccessToDisposedClosure + + try + { + if (!await peer.DoHandshake("server")) + { + logger.LogError("Handshake failed"); + return; + } + } + catch (Exception e) + { + logger.LogError("Handshake failed with unhandled exception: ", e); + return; + } + + using (await peersSem.UseAsync()) + Peers.Add(peer); + + try + { + await peer.Process(); + } + finally + { + using (await peersSem.UseAsync()) + Peers.Remove(peer); + } + } + } + + public async Task Listen() + { + try + { + while (!IsDisposed) + _ = AcceptClient(await listener.AcceptTcpClientAsync()); + } + catch (Exception e) + { + if (!IsDisposed && !(e is SocketException se && se.SocketErrorCode == SocketError.Interrupted)) + throw; + } + } + + public async void BroadcastRequest<TResponse>(string identity, Request request) + where TResponse : Response, new() + { + using (await peersSem.UseAsync()) + { + if (!IsAnyConnected(identity)) + { + logger.LogError("Cannot write request. No client connected to the Godot Ide Server."); + return; + } + + var selectedConnections = string.IsNullOrEmpty(identity) ? + Peers : + Peers.Where(c => c.RemoteIdentity == identity); + + string body = JsonConvert.SerializeObject(request); + + foreach (var connection in selectedConnections) + _ = connection.SendRequest<TResponse>(request.Id, body); + } + } + + private class ServerHandshake : IHandshake + { + private static readonly string ServerHandshakeBase = $"{Peer.ServerHandshakeName},Version={Peer.ProtocolVersionMajor}.{Peer.ProtocolVersionMinor}.{Peer.ProtocolVersionRevision}"; + private static readonly string ClientHandshakePattern = $@"{Regex.Escape(Peer.ClientHandshakeName)},Version=([0-9]+)\.([0-9]+)\.([0-9]+),([_a-zA-Z][_a-zA-Z0-9]{{0,63}})"; + + public string GetHandshakeLine(string identity) => $"{ServerHandshakeBase},{identity}"; + + public bool IsValidPeerHandshake(string handshake, out string identity, ILogger logger) + { + identity = null; + + var match = Regex.Match(handshake, ClientHandshakePattern); + + if (!match.Success) + return false; + + if (!uint.TryParse(match.Groups[1].Value, out uint clientMajor) || Peer.ProtocolVersionMajor != clientMajor) + { + logger.LogDebug("Incompatible major version: " + match.Groups[1].Value); + return false; + } + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (!uint.TryParse(match.Groups[2].Value, out uint clientMinor) || Peer.ProtocolVersionMinor > clientMinor) + { + logger.LogDebug("Incompatible minor version: " + match.Groups[2].Value); + return false; + } + + if (!uint.TryParse(match.Groups[3].Value, out uint _)) // Revision + { + logger.LogDebug("Incompatible revision build: " + match.Groups[3].Value); + return false; + } + + identity = match.Groups[4].Value; + + return true; + } + } + + private class ServerMessageHandler : IMessageHandler + { + private static void DispatchToMainThread(Action action) + { + var d = new SendOrPostCallback(state => action()); + Godot.Dispatcher.SynchronizationContext.Post(d, null); + } + + private readonly Dictionary<string, Peer.RequestHandler> requestHandlers = InitializeRequestHandlers(); + + public async Task<MessageContent> HandleRequest(Peer peer, string id, MessageContent content, ILogger logger) + { + if (!requestHandlers.TryGetValue(id, out var handler)) + { + logger.LogError($"Received unknown request: {id}"); + return new MessageContent(MessageStatus.RequestNotSupported, "null"); + } + + try + { + var response = await handler(peer, content); + return new MessageContent(response.Status, JsonConvert.SerializeObject(response)); + } + catch (JsonException) + { + logger.LogError($"Received request with invalid body: {id}"); + return new MessageContent(MessageStatus.InvalidRequestBody, "null"); + } + } + + private static Dictionary<string, Peer.RequestHandler> InitializeRequestHandlers() + { + return new Dictionary<string, Peer.RequestHandler> + { + [PlayRequest.Id] = async (peer, content) => + { + _ = JsonConvert.DeserializeObject<PlayRequest>(content.Body); + return await HandlePlay(); + }, + [DebugPlayRequest.Id] = async (peer, content) => + { + var request = JsonConvert.DeserializeObject<DebugPlayRequest>(content.Body); + return await HandleDebugPlay(request); + }, + [ReloadScriptsRequest.Id] = async (peer, content) => + { + _ = JsonConvert.DeserializeObject<ReloadScriptsRequest>(content.Body); + return await HandleReloadScripts(); + }, + [CodeCompletionRequest.Id] = async (peer, content) => + { + var request = JsonConvert.DeserializeObject<CodeCompletionRequest>(content.Body); + return await HandleCodeCompletionRequest(request); + } + }; + } + + private static Task<Response> HandlePlay() + { + DispatchToMainThread(() => + { + GodotSharpEditor.Instance.CurrentPlaySettings = new PlaySettings(); + Internal.EditorRunPlay(); + GodotSharpEditor.Instance.CurrentPlaySettings = null; + }); + return Task.FromResult<Response>(new PlayResponse()); + } + + private static Task<Response> HandleDebugPlay(DebugPlayRequest request) + { + DispatchToMainThread(() => + { + GodotSharpEditor.Instance.CurrentPlaySettings = + new PlaySettings(request.DebuggerHost, request.DebuggerPort, request.BuildBeforePlaying ?? true); + Internal.EditorRunPlay(); + GodotSharpEditor.Instance.CurrentPlaySettings = null; + }); + return Task.FromResult<Response>(new DebugPlayResponse()); + } + + private static Task<Response> HandleReloadScripts() + { + DispatchToMainThread(Internal.ScriptEditorDebugger_ReloadScripts); + return Task.FromResult<Response>(new ReloadScriptsResponse()); + } + + private static async Task<Response> HandleCodeCompletionRequest(CodeCompletionRequest request) + { + var response = new CodeCompletionResponse {Kind = request.Kind, ScriptFile = request.ScriptFile}; + response.Suggestions = await Task.Run(() => Internal.CodeCompletionRequest(response.Kind, response.ScriptFile)); + return response; + } + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs index 6026c109ad..d6fa2eeba7 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs @@ -7,14 +7,16 @@ using GodotTools.Utils; namespace GodotTools.Ides.MonoDevelop { - public class Instance + public class Instance : IDisposable { + public DateTime LaunchTime { get; private set; } private readonly string solutionFile; private readonly EditorId editorId; private Process process; public bool IsRunning => process != null && !process.HasExited; + public bool IsDisposed { get; private set; } public void Execute() { @@ -59,6 +61,8 @@ namespace GodotTools.Ides.MonoDevelop if (command == null) throw new FileNotFoundException(); + LaunchTime = DateTime.Now; + if (newWindow) { process = Process.Start(new ProcessStartInfo @@ -88,6 +92,12 @@ namespace GodotTools.Ides.MonoDevelop this.editorId = editorId; } + public void Dispose() + { + IsDisposed = true; + process?.Dispose(); + } + private static readonly IReadOnlyDictionary<EditorId, string> ExecutableNames; private static readonly IReadOnlyDictionary<EditorId, string> BundleIds; @@ -118,7 +128,7 @@ namespace GodotTools.Ides.MonoDevelop {EditorId.MonoDevelop, "MonoDevelop.exe"} }; } - else if (OS.IsUnixLike()) + else if (OS.IsUnixLike) { ExecutableNames = new Dictionary<EditorId, string> { diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs index e3a4fa7b45..e22e9af919 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs @@ -36,7 +36,7 @@ namespace GodotTools.Ides.Rider { return CollectRiderInfosMac(); } - if (OS.IsUnixLike()) + if (OS.IsUnixLike) { return CollectAllRiderPathsLinux(); } @@ -141,16 +141,16 @@ namespace GodotTools.Ides.Rider if (OS.IsOSX) { var home = Environment.GetEnvironmentVariable("HOME"); - if (string.IsNullOrEmpty(home)) + if (string.IsNullOrEmpty(home)) return string.Empty; var localAppData = Path.Combine(home, @"Library/Application Support"); return GetToolboxRiderRootPath(localAppData); } - if (OS.IsUnixLike()) + if (OS.IsUnixLike) { var home = Environment.GetEnvironmentVariable("HOME"); - if (string.IsNullOrEmpty(home)) + if (string.IsNullOrEmpty(home)) return string.Empty; var localAppData = Path.Combine(home, @".local/share"); return GetToolboxRiderRootPath(localAppData); @@ -209,7 +209,7 @@ namespace GodotTools.Ides.Rider private static string GetRelativePathToBuildTxt() { - if (OS.IsWindows || OS.IsUnixLike()) + if (OS.IsWindows || OS.IsUnixLike) return "../../build.txt"; if (OS.IsOSX) return "Contents/Resources/build.txt"; @@ -322,7 +322,7 @@ namespace GodotTools.Ides.Rider class SettingsJson { public string install_location; - + [CanBeNull] public static string GetInstallLocationFromJson(string json) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs index 026a7db89c..7e5049e4b7 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs @@ -2,6 +2,7 @@ using System; using System.Runtime.CompilerServices; using Godot; using Godot.Collections; +using GodotTools.IdeMessaging.Requests; namespace GodotTools.Internals { @@ -52,6 +53,9 @@ namespace GodotTools.Internals public static void ScriptEditorDebugger_ReloadScripts() => internal_ScriptEditorDebugger_ReloadScripts(); + public static string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKind kind, string scriptFile) => + internal_CodeCompletionRequest((int)kind, scriptFile); + #region Internal [MethodImpl(MethodImplOptions.InternalCall)] @@ -111,6 +115,9 @@ namespace GodotTools.Internals [MethodImpl(MethodImplOptions.InternalCall)] private static extern void internal_ScriptEditorDebugger_ReloadScripts(); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern string[] internal_CodeCompletionRequest(int kind, string scriptFile); + #endregion } } diff --git a/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs new file mode 100644 index 0000000000..820d0c0b83 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools/PlaySettings.cs @@ -0,0 +1,19 @@ +namespace GodotTools +{ + public struct PlaySettings + { + public bool HasDebugger { get; } + public string DebuggerHost { get; } + public int DebuggerPort { get; } + + public bool BuildBeforePlaying { get; } + + public PlaySettings(string debuggerHost, int debuggerPort, bool buildBeforePlaying) + { + HasDebugger = true; + DebuggerHost = debuggerHost; + DebuggerPort = debuggerPort; + BuildBeforePlaying = buildBeforePlaying; + } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools/Properties/AssemblyInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Properties/AssemblyInfo.cs deleted file mode 100644 index f5fe85c722..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("GodotTools")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Godot Engine contributors")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 279e67b3eb..6c05891f2c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Runtime.CompilerServices; +using JetBrains.Annotations; namespace GodotTools.Utils { @@ -21,11 +22,15 @@ namespace GodotTools.Utils { public const string Windows = "Windows"; public const string OSX = "OSX"; - public const string X11 = "X11"; + public const string Linux = "Linux"; + public const string FreeBSD = "FreeBSD"; + public const string NetBSD = "NetBSD"; + public const string BSD = "BSD"; public const string Server = "Server"; public const string UWP = "UWP"; public const string Haiku = "Haiku"; public const string Android = "Android"; + public const string iOS = "iOS"; public const string HTML5 = "HTML5"; } @@ -33,11 +38,12 @@ namespace GodotTools.Utils { public const string Windows = "windows"; public const string OSX = "osx"; - public const string X11 = "x11"; + public const string LinuxBSD = "linuxbsd"; public const string Server = "server"; public const string UWP = "uwp"; public const string Haiku = "haiku"; public const string Android = "android"; + public const string iOS = "iphone"; public const string HTML5 = "javascript"; } @@ -45,11 +51,15 @@ namespace GodotTools.Utils { [Names.Windows] = Platforms.Windows, [Names.OSX] = Platforms.OSX, - [Names.X11] = Platforms.X11, + [Names.Linux] = Platforms.LinuxBSD, + [Names.FreeBSD] = Platforms.LinuxBSD, + [Names.NetBSD] = Platforms.LinuxBSD, + [Names.BSD] = Platforms.LinuxBSD, [Names.Server] = Platforms.Server, [Names.UWP] = Platforms.UWP, [Names.Haiku] = Platforms.Haiku, [Names.Android] = Platforms.Android, + [Names.iOS] = Platforms.iOS, [Names.HTML5] = Platforms.HTML5 }; @@ -58,45 +68,48 @@ namespace GodotTools.Utils return name.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase); } + private static bool IsAnyOS(IEnumerable<string> names) + { + return names.Any(p => p.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase)); + } + + private static readonly IEnumerable<string> LinuxBSDPlatforms = + new[] {Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD}; + + private static readonly IEnumerable<string> UnixLikePlatforms = + new[] {Names.OSX, Names.Server, Names.Haiku, Names.Android, Names.iOS} + .Concat(LinuxBSDPlatforms).ToArray(); + private static readonly Lazy<bool> _isWindows = new Lazy<bool>(() => IsOS(Names.Windows)); private static readonly Lazy<bool> _isOSX = new Lazy<bool>(() => IsOS(Names.OSX)); - private static readonly Lazy<bool> _isX11 = new Lazy<bool>(() => IsOS(Names.X11)); + private static readonly Lazy<bool> _isLinuxBSD = new Lazy<bool>(() => IsAnyOS(LinuxBSDPlatforms)); private static readonly Lazy<bool> _isServer = new Lazy<bool>(() => IsOS(Names.Server)); private static readonly Lazy<bool> _isUWP = new Lazy<bool>(() => IsOS(Names.UWP)); private static readonly Lazy<bool> _isHaiku = new Lazy<bool>(() => IsOS(Names.Haiku)); private static readonly Lazy<bool> _isAndroid = new Lazy<bool>(() => IsOS(Names.Android)); + private static readonly Lazy<bool> _isiOS = new Lazy<bool>(() => IsOS(Names.iOS)); private static readonly Lazy<bool> _isHTML5 = new Lazy<bool>(() => IsOS(Names.HTML5)); + private static readonly Lazy<bool> _isUnixLike = new Lazy<bool>(() => IsAnyOS(UnixLikePlatforms)); public static bool IsWindows => _isWindows.Value || IsUWP; public static bool IsOSX => _isOSX.Value; - public static bool IsX11 => _isX11.Value; + public static bool IsLinuxBSD => _isLinuxBSD.Value; public static bool IsServer => _isServer.Value; public static bool IsUWP => _isUWP.Value; public static bool IsHaiku => _isHaiku.Value; public static bool IsAndroid => _isAndroid.Value; + public static bool IsiOS => _isiOS.Value; public static bool IsHTML5 => _isHTML5.Value; - - private static bool? _isUnixCache; - private static readonly string[] UnixLikePlatforms = { Names.OSX, Names.X11, Names.Server, Names.Haiku, Names.Android }; - - public static bool IsUnixLike() - { - if (_isUnixCache.HasValue) - return _isUnixCache.Value; - - string osName = GetPlatformName(); - _isUnixCache = UnixLikePlatforms.Any(p => p.Equals(osName, StringComparison.OrdinalIgnoreCase)); - return _isUnixCache.Value; - } + public static bool IsUnixLike => _isUnixLike.Value; public static char PathSep => IsWindows ? ';' : ':'; - public static string PathWhich(string name) + public static string PathWhich([NotNull] string name) { return IsWindows ? PathWhichWindows(name) : PathWhichUnix(name); } - private static string PathWhichWindows(string name) + private static string PathWhichWindows([NotNull] string name) { string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? new string[] { }; string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); @@ -115,13 +128,13 @@ namespace GodotTools.Utils return searchDirs.Select(dir => Path.Combine(dir, name)).FirstOrDefault(File.Exists); return (from dir in searchDirs - select Path.Combine(dir, name) + select Path.Combine(dir, name) into path - from ext in windowsExts - select path + ext).FirstOrDefault(File.Exists); + from ext in windowsExts + select path + ext).FirstOrDefault(File.Exists); } - private static string PathWhichUnix(string name) + private static string PathWhichUnix([NotNull] string name) { string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); @@ -163,5 +176,33 @@ namespace GodotTools.Utils User32Dll.AllowSetForegroundWindow(process.Id); // allows application to focus itself } } + + public static int ExecuteCommand(string command, IEnumerable<string> arguments) + { + // TODO: Once we move to .NET Standard 2.1 we can use ProcessStartInfo.ArgumentList instead + string CmdLineArgsToString(IEnumerable<string> args) + { + // Not perfect, but as long as we are careful... + return string.Join(" ", args.Select(arg => arg.Contains(" ") ? $@"""{arg}""" : arg)); + } + + var startInfo = new ProcessStartInfo(command, CmdLineArgsToString(arguments)); + + Console.WriteLine($"Executing: \"{startInfo.FileName}\" {startInfo.Arguments}"); + + // Print the output + startInfo.RedirectStandardOutput = false; + startInfo.RedirectStandardError = false; + + startInfo.UseShellExecute = false; + + using (var process = new Process {StartInfo = startInfo}) + { + process.Start(); + process.WaitForExit(); + + return process.ExitCode; + } + } } } diff --git a/modules/mono/editor/GodotTools/GodotTools/packages.config b/modules/mono/editor/GodotTools/GodotTools/packages.config deleted file mode 100644 index dd3de2865a..0000000000 --- a/modules/mono/editor/GodotTools/GodotTools/packages.config +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<packages> - <package id="JetBrains.Annotations" version="2019.1.3" targetFramework="net45" /> - <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net45" /> -</packages> diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 9a5de6db16..730ffcb945 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -105,7 +105,6 @@ const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n"); static String fix_doc_description(const String &p_bbcode) { - // This seems to be the correct way to do this. It's the same EditorHelp does. return p_bbcode.dedent() @@ -115,7 +114,6 @@ static String fix_doc_description(const String &p_bbcode) { } static String snake_to_pascal_case(const String &p_identifier, bool p_input_is_upper = false) { - String ret; Vector<String> parts = p_identifier.split("_", true); @@ -125,8 +123,9 @@ static String snake_to_pascal_case(const String &p_identifier, bool p_input_is_u if (part.length()) { part[0] = _find_upper(part[0]); if (p_input_is_upper) { - for (int j = 1; j < part.length(); j++) + for (int j = 1; j < part.length(); j++) { part[j] = _find_lower(part[j]); + } } ret += part; } else { @@ -148,7 +147,6 @@ static String snake_to_pascal_case(const String &p_identifier, bool p_input_is_u } static String snake_to_camel_case(const String &p_identifier, bool p_input_is_upper = false) { - String ret; Vector<String> parts = p_identifier.split("_", true); @@ -160,8 +158,9 @@ static String snake_to_camel_case(const String &p_identifier, bool p_input_is_up part[0] = _find_upper(part[0]); } if (p_input_is_upper) { - for (int j = i != 0 ? 1 : 0; j < part.length(); j++) + for (int j = i != 0 ? 1 : 0; j < part.length(); j++) { part[j] = _find_lower(part[j]); + } } ret += part; } else { @@ -183,11 +182,11 @@ static String snake_to_camel_case(const String &p_identifier, bool p_input_is_up } String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype) { - // Based on the version in EditorHelp - if (p_bbcode.empty()) + if (p_bbcode.empty()) { return String(); + } DocData *doc = EditorHelp::get_doc_data(); @@ -204,8 +203,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf while (pos < bbcode.length()) { int brk_pos = bbcode.find("[", pos); - if (brk_pos < 0) + if (brk_pos < 0) { brk_pos = bbcode.length(); + } if (brk_pos > pos) { String text = bbcode.substr(pos, brk_pos - pos); @@ -214,19 +214,22 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf } else { Vector<String> lines = text.split("\n"); for (int i = 0; i < lines.size(); i++) { - if (i != 0) + if (i != 0) { xml_output.append("<para>"); + } xml_output.append(lines[i].xml_escape()); - if (i != lines.size() - 1) + if (i != lines.size() - 1) { xml_output.append("</para>\n"); + } } } } - if (brk_pos == bbcode.length()) + if (brk_pos == bbcode.length()) { break; // nothing else to add + } int brk_end = bbcode.find("]", brk_pos + 1); @@ -237,13 +240,15 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf } else { Vector<String> lines = text.split("\n"); for (int i = 0; i < lines.size(); i++) { - if (i != 0) + if (i != 0) { xml_output.append("<para>"); + } xml_output.append(lines[i].xml_escape()); - if (i != lines.size() - 1) + if (i != lines.size() - 1) { xml_output.append("</para>\n"); + } } } @@ -411,13 +416,14 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append("\"/>"); } else { // Try to find as global enum constant - const EnumInterface *target_ienum = NULL; + const EnumInterface *target_ienum = nullptr; for (const List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) { target_ienum = &E->get(); target_iconst = find_constant_by_name(target_name, target_ienum->constants); - if (target_iconst) + if (target_iconst) { break; + } } if (target_iconst) { @@ -449,13 +455,14 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append("\"/>"); } else { // Try to find as enum constant in the current class - const EnumInterface *target_ienum = NULL; + const EnumInterface *target_ienum = nullptr; for (const List<EnumInterface>::Element *E = target_itype->enums.front(); E; E = E->next()) { target_ienum = &E->get(); target_iconst = find_constant_by_name(target_name, target_ienum->constants); - if (target_iconst) + if (target_iconst) { break; + } } if (target_iconst) { @@ -566,8 +573,12 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf code_tag = true; pos = brk_end + 1; tag_stack.push_front(tag); + } else if (tag == "kbd") { + // keyboard combinations are not supported in xml comments + pos = brk_end + 1; + tag_stack.push_front(tag); } else if (tag == "center") { - // center is alignment not supported in xml comments + // center alignment is not supported in xml comments pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "br") { @@ -583,8 +594,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf tag_stack.push_front(tag); } else if (tag == "url") { int end = bbcode.find("[", brk_end); - if (end == -1) + if (end == -1) { end = bbcode.length(); + } String url = bbcode.substr(brk_end + 1, end - brk_end - 1); xml_output.append("<a href=\""); xml_output.append(url); @@ -603,8 +615,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf tag_stack.push_front("url"); } else if (tag == "img") { int end = bbcode.find("[", brk_end); - if (end == -1) + if (end == -1) { end = bbcode.length(); + } String image = bbcode.substr(brk_end + 1, end - brk_end - 1); // Not supported. Just append the bbcode. @@ -634,15 +647,15 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf } int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) { - CRASH_COND(p_ienum.constants.empty()); const ConstantInterface &front_iconstant = p_ienum.constants.front()->get(); Vector<String> front_parts = front_iconstant.name.split("_", /* p_allow_empty: */ true); int candidate_len = front_parts.size() - 1; - if (candidate_len == 0) + if (candidate_len == 0) { return 0; + } for (const List<ConstantInterface>::Element *E = p_ienum.constants.front()->next(); E; E = E->next()) { const ConstantInterface &iconstant = E->get(); @@ -654,21 +667,22 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) { if (front_parts[i] != parts[i]) { // HARDCODED: Some Flag enums have the prefix 'FLAG_' for everything except 'FLAGS_DEFAULT' (same for 'METHOD_FLAG_' and'METHOD_FLAGS_DEFAULT'). bool hardcoded_exc = (i == candidate_len - 1 && ((front_parts[i] == "FLAGS" && parts[i] == "FLAG") || (front_parts[i] == "FLAG" && parts[i] == "FLAGS"))); - if (!hardcoded_exc) + if (!hardcoded_exc) { break; + } } } candidate_len = i; - if (candidate_len == 0) + if (candidate_len == 0) { return 0; + } } return candidate_len; } void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumInterface &p_ienum, int p_prefix_length) { - if (p_prefix_length > 0) { for (List<ConstantInterface>::Element *E = p_ienum.constants.front(); E; E = E->next()) { int curr_prefix_length = p_prefix_length; @@ -679,22 +693,25 @@ void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumI Vector<String> parts = constant_name.split("_", /* p_allow_empty: */ true); - if (parts.size() <= curr_prefix_length) + if (parts.size() <= curr_prefix_length) { continue; + } if (parts[curr_prefix_length][0] >= '0' && parts[curr_prefix_length][0] <= '9') { // The name of enum constants may begin with a numeric digit when strip from the enum prefix, // so we make the prefix for this constant one word shorter in those cases. for (curr_prefix_length = curr_prefix_length - 1; curr_prefix_length > 0; curr_prefix_length--) { - if (parts[curr_prefix_length][0] < '0' || parts[curr_prefix_length][0] > '9') + if (parts[curr_prefix_length][0] < '0' || parts[curr_prefix_length][0] > '9') { break; + } } } constant_name = ""; for (int i = curr_prefix_length; i < parts.size(); i++) { - if (i > curr_prefix_length) + if (i > curr_prefix_length) { constant_name += "_"; + } constant_name += parts[i]; } @@ -704,12 +721,12 @@ void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumI } void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { - for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) { const MethodInterface &imethod = E->get(); - if (imethod.is_virtual) + if (imethod.is_virtual) { continue; + } const TypeInterface *return_type = _get_type_or_placeholder(imethod.return_type); @@ -758,8 +775,9 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { List<InternalCall>::Element *match = method_icalls.find(im_icall); if (match) { - if (p_itype.api_type != ClassDB::API_EDITOR) + if (p_itype.api_type != ClassDB::API_EDITOR) { match->get().editor_only = false; + } method_icalls_map.insert(&E->get(), &match->get()); } else { List<InternalCall>::Element *added = method_icalls.push_back(im_icall); @@ -769,7 +787,6 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { } void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { - // Constants (in partial GD class) p_output.append("\n#pragma warning disable CS1591 // Disable warning: " @@ -782,7 +799,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { const ConstantInterface &iconstant = E->get(); if (iconstant.const_doc && iconstant.const_doc->description.size()) { - String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), NULL); + String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), nullptr); Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); if (summary_lines.size()) { @@ -805,8 +822,9 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { p_output.append(";"); } - if (!global_constants.empty()) + if (!global_constants.empty()) { p_output.append("\n"); + } p_output.append(INDENT1 CLOSE_BLOCK); // end of GD class @@ -843,7 +861,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { const ConstantInterface &iconstant = F->get(); if (iconstant.const_doc && iconstant.const_doc->description.size()) { - String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), NULL); + String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), nullptr); Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); if (summary_lines.size()) { @@ -868,8 +886,9 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { p_output.append(INDENT1 CLOSE_BLOCK); - if (enum_in_static_class) + if (enum_in_static_class) { p_output.append(INDENT1 CLOSE_BLOCK); + } } p_output.append(CLOSE_BLOCK); // end of namespace @@ -878,7 +897,6 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { } Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { - ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -904,8 +922,9 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { _generate_global_constants(constants_source); String output_file = path::join(base_gen_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs"); Error save_err = _save_file(output_file, constants_source); - if (save_err != OK) + if (save_err != OK) { return save_err; + } compile_items.push_back(output_file); } @@ -913,17 +932,20 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { const TypeInterface &itype = E.get(); - if (itype.api_type == ClassDB::API_EDITOR) + if (itype.api_type == ClassDB::API_EDITOR) { continue; + } String output_file = path::join(godot_objects_gen_dir, itype.proxy_name + ".cs"); Error err = _generate_cs_type(itype, output_file); - if (err == ERR_SKIP) + if (err == ERR_SKIP) { continue; + } - if (err != OK) + if (err != OK) { return err; + } compile_items.push_back(output_file); } @@ -954,10 +976,12 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { cs_icalls_content.append(m_icall.im_sig + ");\n"); \ } - for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) + for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) { ADD_INTERNAL_CALL(E->get()); - for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) + } + for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) { ADD_INTERNAL_CALL(E->get()); + } #undef ADD_INTERNAL_CALL @@ -966,8 +990,9 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { String internal_methods_file = path::join(base_gen_dir, BINDINGS_CLASS_NATIVECALLS ".cs"); Error err = _save_file(internal_methods_file, cs_icalls_content); - if (err != OK) + if (err != OK) { return err; + } compile_items.push_back(internal_methods_file); @@ -986,14 +1011,14 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { String includes_props_file = path::join(base_gen_dir, "GeneratedIncludes.props"); err = _save_file(includes_props_file, includes_props_content); - if (err != OK) + if (err != OK) { return err; + } return OK; } Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { - ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -1016,17 +1041,20 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { const TypeInterface &itype = E.get(); - if (itype.api_type != ClassDB::API_EDITOR) + if (itype.api_type != ClassDB::API_EDITOR) { continue; + } String output_file = path::join(godot_objects_gen_dir, itype.proxy_name + ".cs"); Error err = _generate_cs_type(itype, output_file); - if (err == ERR_SKIP) + if (err == ERR_SKIP) { continue; + } - if (err != OK) + if (err != OK) { return err; + } compile_items.push_back(output_file); } @@ -1056,10 +1084,12 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { cs_icalls_content.append(m_icall.im_sig + ");\n"); \ } - for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next()) + for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next()) { ADD_INTERNAL_CALL(E->get()); - for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) + } + for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) { ADD_INTERNAL_CALL(E->get()); + } #undef ADD_INTERNAL_CALL @@ -1068,8 +1098,9 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { String internal_methods_file = path::join(base_gen_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs"); Error err = _save_file(internal_methods_file, cs_icalls_content); - if (err != OK) + if (err != OK) { return err; + } compile_items.push_back(internal_methods_file); @@ -1088,14 +1119,14 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { String includes_props_file = path::join(base_gen_dir, "GeneratedIncludes.props"); err = _save_file(includes_props_file, includes_props_content); - if (err != OK) + if (err != OK) { return err; + } return OK; } Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { - ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); String output_dir = path::abspath(path::realpath(p_output_dir)); @@ -1143,7 +1174,6 @@ Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { // - Csc warning e.g.: // ObjectType/LineEdit.cs(140,38): warning CS0108: 'LineEdit.FocusMode' hides inherited member 'Control.FocusMode'. Use the new keyword if hiding was intended. Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const String &p_output_file) { - CRASH_COND(!itype.is_object_type); bool is_derived_type = itype.base_name != StringName(); @@ -1218,93 +1248,89 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.append(INDENT1 "{"); - if (class_doc) { + // Add constants - // Add constants - - for (const List<ConstantInterface>::Element *E = itype.constants.front(); E; E = E->next()) { - const ConstantInterface &iconstant = E->get(); - - if (iconstant.const_doc && iconstant.const_doc->description.size()) { - String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype); - Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); + for (const List<ConstantInterface>::Element *E = itype.constants.front(); E; E = E->next()) { + const ConstantInterface &iconstant = E->get(); - if (summary_lines.size()) { - output.append(MEMBER_BEGIN "/// <summary>\n"); + if (iconstant.const_doc && iconstant.const_doc->description.size()) { + String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype); + Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); - for (int i = 0; i < summary_lines.size(); i++) { - output.append(INDENT2 "/// "); - output.append(summary_lines[i]); - output.append("\n"); - } + if (summary_lines.size()) { + output.append(MEMBER_BEGIN "/// <summary>\n"); - output.append(INDENT2 "/// </summary>"); + for (int i = 0; i < summary_lines.size(); i++) { + output.append(INDENT2 "/// "); + output.append(summary_lines[i]); + output.append("\n"); } - } - output.append(MEMBER_BEGIN "public const int "); - output.append(iconstant.proxy_name); - output.append(" = "); - output.append(itos(iconstant.value)); - output.append(";"); + output.append(INDENT2 "/// </summary>"); + } } - if (itype.constants.size()) - output.append("\n"); + output.append(MEMBER_BEGIN "public const int "); + output.append(iconstant.proxy_name); + output.append(" = "); + output.append(itos(iconstant.value)); + output.append(";"); + } - // Add enums + if (itype.constants.size()) { + output.append("\n"); + } - for (const List<EnumInterface>::Element *E = itype.enums.front(); E; E = E->next()) { - const EnumInterface &ienum = E->get(); + // Add enums - ERR_FAIL_COND_V(ienum.constants.empty(), ERR_BUG); + for (const List<EnumInterface>::Element *E = itype.enums.front(); E; E = E->next()) { + const EnumInterface &ienum = E->get(); - output.append(MEMBER_BEGIN "public enum "); - output.append(ienum.cname.operator String()); - output.append(MEMBER_BEGIN OPEN_BLOCK); + ERR_FAIL_COND_V(ienum.constants.empty(), ERR_BUG); - for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) { - const ConstantInterface &iconstant = F->get(); + output.append(MEMBER_BEGIN "public enum "); + output.append(ienum.cname.operator String()); + output.append(MEMBER_BEGIN OPEN_BLOCK); - if (iconstant.const_doc && iconstant.const_doc->description.size()) { - String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype); - Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); + for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) { + const ConstantInterface &iconstant = F->get(); - if (summary_lines.size()) { - output.append(INDENT3 "/// <summary>\n"); + if (iconstant.const_doc && iconstant.const_doc->description.size()) { + String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype); + Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); - for (int i = 0; i < summary_lines.size(); i++) { - output.append(INDENT3 "/// "); - output.append(summary_lines[i]); - output.append("\n"); - } + if (summary_lines.size()) { + output.append(INDENT3 "/// <summary>\n"); - output.append(INDENT3 "/// </summary>\n"); + for (int i = 0; i < summary_lines.size(); i++) { + output.append(INDENT3 "/// "); + output.append(summary_lines[i]); + output.append("\n"); } - } - output.append(INDENT3); - output.append(iconstant.proxy_name); - output.append(" = "); - output.append(itos(iconstant.value)); - output.append(F != ienum.constants.back() ? ",\n" : "\n"); + output.append(INDENT3 "/// </summary>\n"); + } } - output.append(INDENT2 CLOSE_BLOCK); + output.append(INDENT3); + output.append(iconstant.proxy_name); + output.append(" = "); + output.append(itos(iconstant.value)); + output.append(F != ienum.constants.back() ? ",\n" : "\n"); } - // Add properties - - for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) { - const PropertyInterface &iprop = E->get(); - Error prop_err = _generate_cs_property(itype, iprop, output); - ERR_FAIL_COND_V_MSG(prop_err != OK, prop_err, - "Failed to generate property '" + iprop.cname.operator String() + - "' for class '" + itype.name + "'."); - } + output.append(INDENT2 CLOSE_BLOCK); } - // TODO: BINDINGS_NATIVE_NAME_FIELD should be StringName, once we support it in C# + // Add properties + + for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) { + const PropertyInterface &iprop = E->get(); + Error prop_err = _generate_cs_property(itype, iprop, output); + ERR_FAIL_COND_V_MSG(prop_err != OK, prop_err, + "Failed to generate property '" + iprop.cname.operator String() + + "' for class '" + itype.name + "'."); + } if (itype.is_singleton) { // Add the type name and the singleton pointer as static fields @@ -1377,15 +1403,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str if (itype.is_singleton) { InternalCall singleton_icall = InternalCall(itype.api_type, ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX, "IntPtr"); - if (!find_icall_by_name(singleton_icall.name, custom_icalls)) + if (!find_icall_by_name(singleton_icall.name, custom_icalls)) { custom_icalls.push_back(singleton_icall); + } } if (is_derived_type && itype.is_instantiable) { InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj"); - if (!find_icall_by_name(ctor_icall.name, custom_icalls)) + if (!find_icall_by_name(ctor_icall.name, custom_icalls)) { custom_icalls.push_back(ctor_icall); + } } output.append(INDENT1 CLOSE_BLOCK /* class */ @@ -1399,14 +1427,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output) { - const MethodInterface *setter = p_itype.find_method_by_name(p_iprop.setter); // Search it in base types too const TypeInterface *current_type = &p_itype; while (!setter && current_type->base_name != StringName()) { OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); - ERR_FAIL_COND_V(!base_match, ERR_BUG); + ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'."); current_type = &base_match.get(); setter = current_type->find_method_by_name(p_iprop.setter); } @@ -1417,7 +1444,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte current_type = &p_itype; while (!getter && current_type->base_name != StringName()) { OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); - ERR_FAIL_COND_V(!base_match, ERR_BUG); + ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'."); current_type = &base_match.get(); getter = current_type->find_method_by_name(p_iprop.getter); } @@ -1452,6 +1479,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte const TypeInterface *prop_itype = _get_type_or_null(proptype_name); ERR_FAIL_NULL_V(prop_itype, ERR_BUG); // Property type not found + ERR_FAIL_COND_V_MSG(prop_itype->is_singleton, ERR_BUG, + "Property type is a singleton: '" + p_itype.name + "." + String(p_iprop.cname) + "'."); + if (p_iprop.prop_doc && p_iprop.prop_doc->description.size()) { String xml_summary = bbcode_to_xml(fix_doc_description(p_iprop.prop_doc->description), &p_itype); Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); @@ -1471,8 +1501,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte p_output.append(MEMBER_BEGIN "public "); - if (p_itype.is_singleton) + if (p_itype.is_singleton) { p_output.append("static "); + } p_output.append(prop_itype->cs_type); p_output.append(" "); @@ -1494,7 +1525,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte if (idx_arg.type.cname != name_cache.type_int) { // Assume the index parameter is an enum const TypeInterface *idx_arg_type = _get_type_or_null(idx_arg.type); - CRASH_COND(idx_arg_type == NULL); + CRASH_COND(idx_arg_type == nullptr); p_output.append("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index)); } else { p_output.append(itos(p_iprop.index)); @@ -1522,7 +1553,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte if (idx_arg.type.cname != name_cache.type_int) { // Assume the index parameter is an enum const TypeInterface *idx_arg_type = _get_type_or_null(idx_arg.type); - CRASH_COND(idx_arg_type == NULL); + CRASH_COND(idx_arg_type == nullptr); p_output.append("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index) + ", "); } else { p_output.append(itos(p_iprop.index) + ", "); @@ -1542,9 +1573,11 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte } Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output) { - const TypeInterface *return_type = _get_type_or_placeholder(p_imethod.return_type); + ERR_FAIL_COND_V_MSG(return_type->is_singleton, ERR_BUG, + "Method return type is a singleton: '" + p_itype.name + "." + p_imethod.name + "'."); + String method_bind_field = "__method_bind_" + itos(p_method_bind_count); String arguments_sig; @@ -1560,29 +1593,41 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf const ArgumentInterface &iarg = F->get(); const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type); + ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG, + "Argument type is a singleton: '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "'."); + + if (iarg.default_argument.size()) { + CRASH_COND_MSG(!_arg_default_value_is_assignable_to_type(iarg.def_param_value, *arg_type), + "Invalid default value for parameter '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "'."); + } + // Add the current arguments to the signature // If the argument has a default value which is not a constant, we will make it Nullable { - if (F != p_imethod.arguments.front()) + if (F != p_imethod.arguments.front()) { arguments_sig += ", "; + } - if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) + if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) { arguments_sig += "Nullable<"; + } arguments_sig += arg_type->cs_type; - if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) + if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) { arguments_sig += "> "; - else + } else { arguments_sig += " "; + } arguments_sig += iarg.name; if (iarg.default_argument.size()) { - if (iarg.def_param_mode != ArgumentInterface::CONSTANT) + if (iarg.def_param_mode != ArgumentInterface::CONSTANT) { arguments_sig += " = null"; - else + } else { arguments_sig += " = " + sformat(iarg.default_argument, arg_type->cs_type); + } } } @@ -1600,17 +1645,19 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf cs_in_statements += " = "; cs_in_statements += iarg.name; - if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) + if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) { cs_in_statements += ".HasValue ? "; - else + } else { cs_in_statements += " != null ? "; + } cs_in_statements += iarg.name; - if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) + if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) { cs_in_statements += ".Value : "; - else + } else { cs_in_statements += " : "; + } String def_arg = sformat(iarg.default_argument, arg_type->cs_type); @@ -1631,7 +1678,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf // Generate method { if (!p_imethod.is_virtual && !p_imethod.requires_object_call) { - p_output.append(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static IntPtr "); + p_output.append(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static readonly IntPtr "); p_output.append(method_bind_field); p_output.append(" = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); p_output.append(p_imethod.name); @@ -1660,14 +1707,19 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf } if (!p_imethod.is_internal) { + // TODO: This alone adds ~0.2 MB of bloat to the core API assembly. It would be + // better to generate a table in the C++ glue instead. That way the strings wouldn't + // add that much extra bloat as they're already used in engine code. Also, it would + // probably be much faster than looking up the attributes when fetching methods. p_output.append(MEMBER_BEGIN "[GodotMethod(\""); p_output.append(p_imethod.name); p_output.append("\")]"); } if (p_imethod.is_deprecated) { - if (p_imethod.deprecation_message.empty()) + if (p_imethod.deprecation_message.empty()) { WARN_PRINT("An empty deprecation message is discouraged. Method: '" + p_imethod.proxy_name + "'."); + } p_output.append(MEMBER_BEGIN "[Obsolete(\""); p_output.append(p_imethod.deprecation_message); @@ -1727,8 +1779,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf im_call += "."; im_call += im_icall->name; - if (p_imethod.arguments.size()) + if (p_imethod.arguments.size()) { p_output.append(cs_in_statements); + } if (return_type->cname == name_cache.type_void) { p_output.append(im_call + "(" + icall_params + ");\n"); @@ -1755,10 +1808,14 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf const ArgumentInterface &iarg = F->get(); const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type); + ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG, + "Argument type is a singleton: '" + iarg.name + "' of signal" + p_itype.name + "." + p_isignal.name + "'."); + // Add the current arguments to the signature - if (F != p_isignal.arguments.front()) + if (F != p_isignal.arguments.front()) { arguments_sig += ", "; + } arguments_sig += arg_type->cs_type; arguments_sig += " "; @@ -1785,8 +1842,9 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf } if (p_isignal.is_deprecated) { - if (p_isignal.deprecation_message.empty()) + if (p_isignal.deprecation_message.empty()) { WARN_PRINT("An empty deprecation message is discouraged. Signal: '" + p_isignal.proxy_name + "'."); + } p_output.append(MEMBER_BEGIN "[Obsolete(\""); p_output.append(p_isignal.deprecation_message); @@ -1817,8 +1875,9 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf // Generate event p_output.append(MEMBER_BEGIN "[Signal]" MEMBER_BEGIN "public "); - if (p_itype.is_singleton) + if (p_itype.is_singleton) { p_output.append("static "); + } p_output.append("event "); p_output.append(delegate_name); @@ -1826,18 +1885,20 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf p_output.append(p_isignal.proxy_name); p_output.append("\n" OPEN_BLOCK_L2); - if (p_itype.is_singleton) + if (p_itype.is_singleton) { p_output.append("add => Singleton.Connect(__signal_name_"); - else + } else { p_output.append("add => Connect(__signal_name_"); + } p_output.append(p_isignal.name); p_output.append(", new Callable(value));\n"); - if (p_itype.is_singleton) + if (p_itype.is_singleton) { p_output.append(INDENT3 "remove => Singleton.Disconnect(__signal_name_"); - else + } else { p_output.append(INDENT3 "remove => Disconnect(__signal_name_"); + } p_output.append(p_isignal.name); p_output.append(", new Callable(value));\n"); @@ -1848,7 +1909,6 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf } Error BindingsGenerator::generate_glue(const String &p_output_dir) { - ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED); bool dir_exists = DirAccess::exists(p_output_dir); @@ -1872,7 +1932,6 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { CRASH_COND(itype.cname != name_cache.type_Object); CRASH_COND(!itype.is_instantiable); CRASH_COND(itype.api_type != ClassDB::API_CORE); - CRASH_COND(itype.is_reference); CRASH_COND(itype.is_singleton); } @@ -1893,8 +1952,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { String singleton_icall_name = ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX; InternalCall singleton_icall = InternalCall(itype.api_type, singleton_icall_name, "IntPtr"); - if (!find_icall_by_name(singleton_icall.name, custom_icalls)) + if (!find_icall_by_name(singleton_icall.name, custom_icalls)) { custom_icalls.push_back(singleton_icall); + } output.append("Object* "); output.append(singleton_icall_name); @@ -1906,8 +1966,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { if (is_derived_type && itype.is_instantiable) { InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj"); - if (!find_icall_by_name(ctor_icall.name, custom_icalls)) + if (!find_icall_by_name(ctor_icall.name, custom_icalls)) { custom_icalls.push_back(ctor_icall); + } output.append("Object* "); output.append(ctor_method); @@ -1953,7 +2014,6 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { bool tools_sequence = false; for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) { - if (tools_sequence) { if (!E->get().editor_only) { tools_sequence = false; @@ -2007,8 +2067,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.append("\n#endif // MONO_GLUE_ENABLED\n"); Error save_err = _save_file(path::join(p_output_dir, "mono_glue.gen.cpp"), output); - if (save_err != OK) + if (save_err != OK) { return save_err; + } OS::get_singleton()->print("Mono glue generated successfully\n"); @@ -2020,7 +2081,6 @@ uint32_t BindingsGenerator::get_version() { } Error BindingsGenerator::_save_file(const String &p_path, const StringBuilder &p_content) { - FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE); ERR_FAIL_COND_V_MSG(!file, ERR_FILE_CANT_WRITE, "Cannot open file: '" + p_path + "'."); @@ -2032,9 +2092,9 @@ Error BindingsGenerator::_save_file(const String &p_path, const StringBuilder &p } Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, StringBuilder &p_output) { - - if (p_imethod.is_virtual) + if (p_imethod.is_virtual) { return OK; // Ignore + } bool ret_void = p_imethod.return_type.cname == name_cache.type_void; @@ -2062,10 +2122,12 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte c_in_statements += sformat(", &%s_in);\n", c_param_name); } } else { - if (i > 0) + if (i > 0) { c_args_var_content += ", "; - if (arg_type->c_in.size()) + } + if (arg_type->c_in.size()) { c_in_statements += sformat(arg_type->c_in, arg_type->c_type, c_param_name); + } c_args_var_content += sformat(arg_type->c_arg_in, c_param_name); } @@ -2095,8 +2157,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte if (!generated_icall_funcs.find(im_icall)) { generated_icall_funcs.push_back(im_icall); - if (im_icall->editor_only) + if (im_icall->editor_only) { p_output.append("#ifdef TOOLS_ENABLED\n"); + } // Generate icall function @@ -2121,7 +2184,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte if (return_type->is_object_type) { ptrcall_return_type = return_type->is_reference ? "Ref<Reference>" : return_type->c_type; - initialization = return_type->is_reference ? "" : " = NULL"; + initialization = return_type->is_reference ? "" : " = nullptr"; } else { ptrcall_return_type = return_type->c_type; } @@ -2130,12 +2193,12 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte p_output.append(" " C_LOCAL_RET); p_output.append(initialization + ";\n"); - String fail_ret = return_type->c_type_out.ends_with("*") && !return_type->ret_as_byref_arg ? "NULL" : return_type->c_type_out + "()"; + String fail_ret = return_type->c_type_out.ends_with("*") && !return_type->ret_as_byref_arg ? "nullptr" : return_type->c_type_out + "()"; if (return_type->ret_as_byref_arg) { - p_output.append("\tif (" CS_PARAM_INSTANCE " == NULL) { *arg_ret = "); + p_output.append("\tif (" CS_PARAM_INSTANCE " == nullptr) { *arg_ret = "); p_output.append(fail_ret); - p_output.append("; ERR_FAIL_MSG(\"Parameter ' arg_ret ' is null.\"); }\n"); + p_output.append("; ERR_FAIL_MSG(\"Parameter ' " CS_PARAM_INSTANCE " ' is null.\"); }\n"); } else { p_output.append("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE ", "); p_output.append(fail_ret); @@ -2187,7 +2250,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte } p_output.append(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", "); - p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL"); + p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "nullptr"); p_output.append(", total_length, vcall_error);\n"); if (!ret_void) { @@ -2198,8 +2261,8 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte } } else { p_output.append("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", "); - p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, "); - p_output.append(!ret_void ? "&" C_LOCAL_RET ");\n" : "NULL);\n"); + p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "nullptr, "); + p_output.append(!ret_void ? "&" C_LOCAL_RET ");\n" : "nullptr);\n"); } if (!ret_void) { @@ -2214,53 +2277,57 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte p_output.append(CLOSE_BLOCK "\n"); - if (im_icall->editor_only) + if (im_icall->editor_only) { p_output.append("#endif // TOOLS_ENABLED\n"); + } } return OK; } const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_null(const TypeReference &p_typeref) { - const Map<StringName, TypeInterface>::Element *builtin_type_match = builtin_types.find(p_typeref.cname); - if (builtin_type_match) + if (builtin_type_match) { return &builtin_type_match->get(); + } const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_typeref.cname); - if (obj_type_match) + if (obj_type_match) { return &obj_type_match.get(); + } if (p_typeref.is_enum) { const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(p_typeref.cname); - if (enum_match) + if (enum_match) { return &enum_match->get(); + } // Enum not found. Most likely because none of its constants were bound, so it's empty. That's fine. Use int instead. const Map<StringName, TypeInterface>::Element *int_match = builtin_types.find(name_cache.type_int); - ERR_FAIL_NULL_V(int_match, NULL); + ERR_FAIL_NULL_V(int_match, nullptr); return &int_match->get(); } - return NULL; + return nullptr; } const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placeholder(const TypeReference &p_typeref) { - const TypeInterface *found = _get_type_or_null(p_typeref); - if (found) + if (found) { return found; + } ERR_PRINT(String() + "Type not found. Creating placeholder: '" + p_typeref.cname.operator String() + "'."); const Map<StringName, TypeInterface>::Element *match = placeholder_types.find(p_typeref.cname); - if (match) + if (match) { return &match->get(); + } TypeInterface placeholder; TypeInterface::create_placeholder_type(placeholder, p_typeref.cname); @@ -2269,7 +2336,6 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol } StringName BindingsGenerator::_get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta) { - switch (p_meta) { case GodotTypeInfo::METADATA_INT_IS_INT8: return "sbyte"; @@ -2302,7 +2368,6 @@ StringName BindingsGenerator::_get_int_type_name_from_meta(GodotTypeInfo::Metada } StringName BindingsGenerator::_get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta) { - switch (p_meta) { case GodotTypeInfo::METADATA_REAL_IS_FLOAT: return "float"; @@ -2320,8 +2385,85 @@ StringName BindingsGenerator::_get_float_type_name_from_meta(GodotTypeInfo::Meta } } -bool BindingsGenerator::_populate_object_type_interfaces() { +bool BindingsGenerator::_arg_default_value_is_assignable_to_type(const Variant &p_val, const TypeInterface &p_arg_type) { + if (p_arg_type.name == name_cache.type_Variant) { + // Variant can take anything + return true; + } + + switch (p_val.get_type()) { + case Variant::NIL: + return p_arg_type.is_object_type || + name_cache.is_nullable_type(p_arg_type.name); + case Variant::BOOL: + return p_arg_type.name == name_cache.type_bool; + case Variant::INT: + return p_arg_type.name == name_cache.type_sbyte || + p_arg_type.name == name_cache.type_short || + p_arg_type.name == name_cache.type_int || + p_arg_type.name == name_cache.type_byte || + p_arg_type.name == name_cache.type_ushort || + p_arg_type.name == name_cache.type_uint || + p_arg_type.name == name_cache.type_long || + p_arg_type.name == name_cache.type_ulong || + p_arg_type.name == name_cache.type_float || + p_arg_type.name == name_cache.type_double || + p_arg_type.is_enum; + case Variant::FLOAT: + return p_arg_type.name == name_cache.type_float || + p_arg_type.name == name_cache.type_double; + case Variant::STRING: + case Variant::STRING_NAME: + return p_arg_type.name == name_cache.type_String || + p_arg_type.name == name_cache.type_StringName || + p_arg_type.name == name_cache.type_NodePath; + case Variant::NODE_PATH: + return p_arg_type.name == name_cache.type_NodePath; + case Variant::TRANSFORM: + case Variant::TRANSFORM2D: + case Variant::BASIS: + case Variant::QUAT: + case Variant::PLANE: + case Variant::AABB: + case Variant::COLOR: + case Variant::VECTOR2: + case Variant::RECT2: + case Variant::VECTOR3: + case Variant::_RID: + case Variant::ARRAY: + case Variant::DICTIONARY: + case Variant::PACKED_BYTE_ARRAY: + case Variant::PACKED_INT32_ARRAY: + case Variant::PACKED_INT64_ARRAY: + case Variant::PACKED_FLOAT32_ARRAY: + case Variant::PACKED_FLOAT64_ARRAY: + case Variant::PACKED_STRING_ARRAY: + case Variant::PACKED_VECTOR2_ARRAY: + case Variant::PACKED_VECTOR3_ARRAY: + case Variant::PACKED_COLOR_ARRAY: + case Variant::CALLABLE: + case Variant::SIGNAL: + return p_arg_type.name == Variant::get_type_name(p_val.get_type()); + case Variant::OBJECT: + return p_arg_type.is_object_type; + case Variant::VECTOR2I: + return p_arg_type.name == name_cache.type_Vector2 || + p_arg_type.name == Variant::get_type_name(p_val.get_type()); + case Variant::RECT2I: + return p_arg_type.name == name_cache.type_Rect2 || + p_arg_type.name == Variant::get_type_name(p_val.get_type()); + case Variant::VECTOR3I: + return p_arg_type.name == name_cache.type_Vector3 || + p_arg_type.name == Variant::get_type_name(p_val.get_type()); + default: + CRASH_NOW_MSG("Unexpected Variant type: " + itos(p_val.get_type())); + break; + } + return false; +} + +bool BindingsGenerator::_populate_object_type_interfaces() { obj_types.clear(); List<StringName> class_list; @@ -2383,22 +2525,30 @@ bool BindingsGenerator::_populate_object_type_interfaces() { for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) { const PropertyInfo &property = E->get(); - if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_CATEGORY) + if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY) { continue; + } + + if (property.name.find("/") >= 0) { + // Ignore properties with '/' (slash) in the name. These are only meant for use in the inspector. + continue; + } PropertyInterface iprop; iprop.cname = property.name; iprop.setter = ClassDB::get_property_setter(type_cname, iprop.cname); iprop.getter = ClassDB::get_property_getter(type_cname, iprop.cname); - if (iprop.setter != StringName()) + if (iprop.setter != StringName()) { accessor_methods[iprop.setter] = iprop.cname; - if (iprop.getter != StringName()) + } + if (iprop.getter != StringName()) { accessor_methods[iprop.getter] = iprop.cname; + } bool valid = false; iprop.index = ClassDB::get_property_index(type_cname, iprop.cname, &valid); - ERR_FAIL_COND_V(!valid, false); + ERR_FAIL_COND_V_MSG(!valid, false, "Invalid property: '" + itype.name + "." + String(iprop.cname) + "'."); iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname)); @@ -2410,9 +2560,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { iprop.proxy_name += "_"; } - iprop.proxy_name = iprop.proxy_name.replace("/", "__"); // Some members have a slash... - - iprop.prop_doc = NULL; + iprop.prop_doc = nullptr; for (int i = 0; i < itype.class_doc->properties.size(); i++) { const DocData::PropertyDoc &prop_doc = itype.class_doc->properties[i]; @@ -2440,24 +2588,27 @@ bool BindingsGenerator::_populate_object_type_interfaces() { int argc = method_info.arguments.size(); - if (method_info.name.empty()) + if (method_info.name.empty()) { continue; + } String cname = method_info.name; - if (blacklisted_methods.find(itype.cname) && blacklisted_methods[itype.cname].find(cname)) + if (blacklisted_methods.find(itype.cname) && blacklisted_methods[itype.cname].find(cname)) { continue; + } MethodInterface imethod; imethod.name = method_info.name; imethod.cname = cname; - if (method_info.flags & METHOD_FLAG_VIRTUAL) + if (method_info.flags & METHOD_FLAG_VIRTUAL) { imethod.is_virtual = true; + } PropertyInfo return_info = method_info.return_val; - MethodBind *m = imethod.is_virtual ? NULL : ClassDB::get_method(type_cname, method_info.name); + MethodBind *m = imethod.is_virtual ? nullptr : ClassDB::get_method(type_cname, method_info.name); imethod.is_vararg = m && m->is_vararg(); @@ -2475,9 +2626,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() { // We assume the return type is void. imethod.return_type.cname = name_cache.type_void; - // Actually, more methods like this may be added in the future, - // which could actually will return something different. - // Let's put this to notify us if that ever happens. + // Actually, more methods like this may be added in the future, which could return + // something different. Let's put this check to notify us if that ever happens. if (itype.cname != name_cache.type_Object || imethod.name != "free") { WARN_PRINT("Notification: New unexpected virtual non-overridable method found." " We only expected Object.free, but found '" + @@ -2488,13 +2638,12 @@ bool BindingsGenerator::_populate_object_type_interfaces() { imethod.return_type.is_enum = true; } else if (return_info.class_name != StringName()) { imethod.return_type.cname = return_info.class_name; - if (!imethod.is_virtual && ClassDB::is_parent_class(return_info.class_name, name_cache.type_Reference) && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE) { - /* clang-format off */ - ERR_PRINT("Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." - " Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'."); - /* clang-format on */ - ERR_FAIL_V(false); - } + + bool bad_reference_hint = !imethod.is_virtual && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE && + ClassDB::is_parent_class(return_info.class_name, name_cache.type_Reference); + ERR_FAIL_COND_V_MSG(bad_reference_hint, false, + String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." + + " Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'."); } else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) { imethod.return_type.cname = return_info.hint_string; } else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { @@ -2585,6 +2734,10 @@ bool BindingsGenerator::_populate_object_type_interfaces() { } } + ERR_FAIL_COND_V_MSG(itype.find_property_by_name(imethod.cname), false, + "Method name conflicts with property: '" + itype.name + "." + imethod.name + "'."); + + // Classes starting with an underscore are ignored unless they're used as a property setter or getter if (!imethod.is_virtual && imethod.name[0] == '_') { for (const List<PropertyInterface>::Element *F = itype.properties.front(); F; F = F->next()) { const PropertyInterface &iprop = F->get(); @@ -2603,7 +2756,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { // Populate signals const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map; - const StringName *k = NULL; + const StringName *k = nullptr; while ((k = signal_map.next(k))) { SignalInterface isignal; @@ -2685,7 +2838,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ClassDB::get_integer_constant_list(type_cname, &constants, true); const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map; - k = NULL; + k = nullptr; while ((k = enum_map.next(k))) { StringName enum_proxy_cname = *k; @@ -2707,7 +2860,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value); - iconstant.const_doc = NULL; + iconstant.const_doc = nullptr; for (int i = 0; i < itype.class_doc->constants.size(); i++) { const DocData::ConstantDoc &const_doc = itype.class_doc->constants[i]; @@ -2742,7 +2895,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value); - iconstant.const_doc = NULL; + iconstant.const_doc = nullptr; for (int i = 0; i < itype.class_doc->constants.size(); i++) { const DocData::ConstantDoc &const_doc = itype.class_doc->constants[i]; @@ -2764,8 +2917,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() { } bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, ArgumentInterface &r_iarg) { - - r_iarg.default_argument = p_val; + r_iarg.def_param_value = p_val; + r_iarg.default_argument = p_val.operator String(); switch (p_val.get_type()) { case Variant::NIL: @@ -2798,8 +2951,9 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar } break; case Variant::TRANSFORM: - if (p_val.operator Transform() == Transform()) + if (p_val.operator Transform() == Transform()) { r_iarg.default_argument.clear(); + } r_iarg.default_argument = "new %s(" + r_iarg.default_argument + ")"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; break; @@ -2865,14 +3019,14 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar break; } - if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "null") + if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "null") { r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + } return true; } void BindingsGenerator::_populate_builtin_type_interfaces() { - builtin_types.clear(); TypeInterface itype; @@ -3248,7 +3402,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { } void BindingsGenerator::_populate_global_constants() { - int global_constants_count = GlobalConstants::get_global_constant_count(); if (global_constants_count > 0) { @@ -3259,10 +3412,9 @@ void BindingsGenerator::_populate_global_constants() { const DocData::ClassDoc &global_scope_doc = match->value(); for (int i = 0; i < global_constants_count; i++) { - String constant_name = GlobalConstants::get_global_constant_name(i); - const DocData::ConstantDoc *const_doc = NULL; + const DocData::ConstantDoc *const_doc = nullptr; for (int j = 0; j < global_scope_doc.constants.size(); j++) { const DocData::ConstantDoc &curr_const_doc = global_scope_doc.constants[j]; @@ -3338,14 +3490,12 @@ void BindingsGenerator::_populate_global_constants() { } void BindingsGenerator::_initialize_blacklisted_methods() { - blacklisted_methods["Object"].push_back("to_string"); // there is already ToString blacklisted_methods["Object"].push_back("_to_string"); // override ToString instead blacklisted_methods["Object"].push_back("_init"); // never called in C# (TODO: implement it) } void BindingsGenerator::_log(const char *p_format, ...) { - if (log_print_enabled) { va_list list; @@ -3356,7 +3506,6 @@ void BindingsGenerator::_log(const char *p_format, ...) { } void BindingsGenerator::_initialize() { - initialized = false; EditorHelp::generate_doc(); @@ -3377,14 +3526,14 @@ void BindingsGenerator::_initialize() { core_custom_icalls.clear(); editor_custom_icalls.clear(); - for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) + for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { _generate_method_icalls(E.get()); + } initialized = true; } void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) { - const int NUM_OPTIONS = 2; String generate_all_glue_option = "--generate-mono-glue"; String generate_cs_glue_option = "--generate-mono-cs-glue"; @@ -3447,21 +3596,25 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) } if (glue_dir_path.length()) { - if (bindings_generator.generate_glue(glue_dir_path) != OK) + if (bindings_generator.generate_glue(glue_dir_path) != OK) { ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue."); + } - if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) + if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) { ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API."); + } } if (cs_dir_path.length()) { - if (bindings_generator.generate_cs_api(cs_dir_path) != OK) + if (bindings_generator.generate_cs_api(cs_dir_path) != OK) { ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API."); + } } if (cpp_dir_path.length()) { - if (bindings_generator.generate_glue(cpp_dir_path) != OK) + if (bindings_generator.generate_glue(cpp_dir_path) != OK) { ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue."); + } } // Exit once done diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index b133923c25..90c1c9f3ee 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -33,7 +33,7 @@ #include "core/class_db.h" #include "core/string_builder.h" -#include "editor/doc/doc_data.h" +#include "editor/doc_data.h" #include "editor/editor_help.h" #if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) @@ -41,7 +41,6 @@ #include "core/ustring.h" class BindingsGenerator { - struct ConstantInterface { String name; String proxy_name; @@ -85,16 +84,12 @@ class BindingsGenerator { struct TypeReference { StringName cname; - bool is_enum; + bool is_enum = false; - TypeReference() : - is_enum(false) { - } + TypeReference() {} TypeReference(const StringName &p_cname) : - cname(p_cname), - is_enum(false) { - } + cname(p_cname) {} }; struct ArgumentInterface { @@ -107,7 +102,9 @@ class BindingsGenerator { TypeReference type; String name; - DefaultParamMode def_param_mode; + + Variant def_param_value; + DefaultParamMode def_param_mode = CONSTANT; /** * Determines the expression for the parameter default value. @@ -116,9 +113,7 @@ class BindingsGenerator { */ String default_argument; - ArgumentInterface() { - def_param_mode = CONSTANT; - } + ArgumentInterface() {} }; struct MethodInterface { @@ -138,19 +133,19 @@ class BindingsGenerator { /** * Determines if the method has a variable number of arguments (VarArg) */ - bool is_vararg; + bool is_vararg = false; /** * Virtual methods ("virtual" as defined by the Godot API) are methods that by default do nothing, * but can be overridden by the user to add custom functionality. * e.g.: _ready, _process, etc. */ - bool is_virtual; + bool is_virtual = false; /** * Determines if the call should fallback to Godot's object.Call(string, params) in C#. */ - bool requires_object_call; + bool requires_object_call = false; /** * Determines if the method visibility is 'internal' (visible only to files in the same assembly). @@ -158,27 +153,20 @@ class BindingsGenerator { * but are required by properties as getters or setters. * Methods that are not meant to be exposed are those that begin with underscore and are not virtual. */ - bool is_internal; + bool is_internal = false; List<ArgumentInterface> arguments; - const DocData::MethodDoc *method_doc; + const DocData::MethodDoc *method_doc = nullptr; - bool is_deprecated; + bool is_deprecated = false; String deprecation_message; void add_argument(const ArgumentInterface &argument) { arguments.push_back(argument); } - MethodInterface() { - is_vararg = false; - is_virtual = false; - requires_object_call = false; - is_internal = false; - method_doc = NULL; - is_deprecated = false; - } + MethodInterface() {} }; struct SignalInterface { @@ -192,19 +180,16 @@ class BindingsGenerator { List<ArgumentInterface> arguments; - const DocData::MethodDoc *method_doc; + const DocData::MethodDoc *method_doc = nullptr; - bool is_deprecated; + bool is_deprecated = false; String deprecation_message; void add_argument(const ArgumentInterface &argument) { arguments.push_back(argument); } - SignalInterface() { - method_doc = NULL; - is_deprecated = false; - } + SignalInterface() {} }; struct TypeInterface { @@ -225,26 +210,26 @@ class BindingsGenerator { */ String proxy_name; - ClassDB::APIType api_type; + ClassDB::APIType api_type = ClassDB::API_NONE; - bool is_enum; - bool is_object_type; - bool is_singleton; - bool is_reference; + bool is_enum = false; + bool is_object_type = false; + bool is_singleton = false; + bool is_reference = false; /** * Used only by Object-derived types. * Determines if this type is not abstract (incomplete). * e.g.: CanvasItem cannot be instantiated. */ - bool is_instantiable; + bool is_instantiable = false; /** * Used only by Object-derived types. * Determines if the C# class owns the native handle and must free it somehow when disposed. * e.g.: Reference types must notify when the C# instance is disposed, for proper refcounting. */ - bool memory_own; + bool memory_own = false; /** * This must be set to true for any struct bigger than 32-bits. Those cannot be passed/returned by value @@ -252,7 +237,7 @@ class BindingsGenerator { * In this case, [c_out] and [cs_out] must have a different format, explained below. * The Mono IL interpreter icall trampolines don't support passing structs bigger than 32-bits by value (at least not on WASM). */ - bool ret_as_byref_arg; + bool ret_as_byref_arg = false; // !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name] // !! When renaming those fields, make sure to rename their references in the comments @@ -279,7 +264,7 @@ class BindingsGenerator { * Formatting elements: * %0 or %s: name of the parameter */ - String c_arg_in; + String c_arg_in = "%s"; /** * One or more statements that determine how a variable of this type is returned from a function. @@ -362,7 +347,7 @@ class BindingsGenerator { */ String im_type_out; - const DocData::ClassDoc *class_doc; + const DocData::ClassDoc *class_doc = nullptr; List<ConstantInterface> constants; List<EnumInterface> enums; @@ -372,38 +357,42 @@ class BindingsGenerator { const MethodInterface *find_method_by_name(const StringName &p_cname) const { for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) { - if (E->get().cname == p_cname) + if (E->get().cname == p_cname) { return &E->get(); + } } - return NULL; + return nullptr; } const PropertyInterface *find_property_by_name(const StringName &p_cname) const { for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) { - if (E->get().cname == p_cname) + if (E->get().cname == p_cname) { return &E->get(); + } } - return NULL; + return nullptr; } const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const { for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) { - if (E->get().proxy_name == p_proxy_name) + if (E->get().proxy_name == p_proxy_name) { return &E->get(); + } } - return NULL; + return nullptr; } const MethodInterface *find_method_by_proxy_name(const String &p_proxy_name) const { for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) { - if (E->get().proxy_name == p_proxy_name) + if (E->get().proxy_name == p_proxy_name) { return &E->get(); + } } - return NULL; + return nullptr; } private: @@ -482,24 +471,7 @@ class BindingsGenerator { r_enum_itype.class_doc = &EditorHelp::get_doc_data()->class_list[r_enum_itype.proxy_name]; } - TypeInterface() { - - api_type = ClassDB::API_NONE; - - is_enum = false; - is_object_type = false; - is_singleton = false; - is_reference = false; - is_instantiable = false; - - memory_own = false; - - ret_as_byref_arg = false; - - c_arg_in = "%s"; - - class_doc = NULL; - } + TypeInterface() {} }; struct InternalCall { @@ -532,8 +504,8 @@ class BindingsGenerator { } }; - bool log_print_enabled; - bool initialized; + bool log_print_enabled = true; + bool initialized = false; OrderedHashMap<StringName, TypeInterface> obj_types; @@ -557,58 +529,70 @@ class BindingsGenerator { void _initialize_blacklisted_methods(); struct NameCache { - StringName type_void; - StringName type_Array; - StringName type_Dictionary; - StringName type_Variant; - StringName type_VarArg; - StringName type_Object; - StringName type_Reference; - StringName type_RID; - StringName type_String; - StringName type_StringName; - StringName type_NodePath; - StringName type_at_GlobalScope; - StringName enum_Error; - - StringName type_sbyte; - StringName type_short; - StringName type_int; - StringName type_long; - StringName type_byte; - StringName type_ushort; - StringName type_uint; - StringName type_ulong; - StringName type_float; - StringName type_double; - - NameCache() { - type_void = StaticCString::create("void"); - type_Array = StaticCString::create("Array"); - type_Dictionary = StaticCString::create("Dictionary"); - type_Variant = StaticCString::create("Variant"); - type_VarArg = StaticCString::create("VarArg"); - type_Object = StaticCString::create("Object"); - type_Reference = StaticCString::create("Reference"); - type_RID = StaticCString::create("RID"); - type_String = StaticCString::create("String"); - type_StringName = StaticCString::create("StringName"); - type_NodePath = StaticCString::create("NodePath"); - type_at_GlobalScope = StaticCString::create("@GlobalScope"); - enum_Error = StaticCString::create("Error"); - - type_sbyte = StaticCString::create("sbyte"); - type_short = StaticCString::create("short"); - type_int = StaticCString::create("int"); - type_long = StaticCString::create("long"); - type_byte = StaticCString::create("byte"); - type_ushort = StaticCString::create("ushort"); - type_uint = StaticCString::create("uint"); - type_ulong = StaticCString::create("ulong"); - type_float = StaticCString::create("float"); - type_double = StaticCString::create("double"); + StringName type_void = StaticCString::create("void"); + StringName type_Variant = StaticCString::create("Variant"); + StringName type_VarArg = StaticCString::create("VarArg"); + StringName type_Object = StaticCString::create("Object"); + StringName type_Reference = StaticCString::create("Reference"); + StringName type_RID = StaticCString::create("RID"); + StringName type_String = StaticCString::create("String"); + StringName type_StringName = StaticCString::create("StringName"); + StringName type_NodePath = StaticCString::create("NodePath"); + StringName type_at_GlobalScope = StaticCString::create("@GlobalScope"); + StringName enum_Error = StaticCString::create("Error"); + + StringName type_sbyte = StaticCString::create("sbyte"); + StringName type_short = StaticCString::create("short"); + StringName type_int = StaticCString::create("int"); + StringName type_byte = StaticCString::create("byte"); + StringName type_ushort = StaticCString::create("ushort"); + StringName type_uint = StaticCString::create("uint"); + StringName type_long = StaticCString::create("long"); + StringName type_ulong = StaticCString::create("ulong"); + + StringName type_bool = StaticCString::create("bool"); + StringName type_float = StaticCString::create("float"); + StringName type_double = StaticCString::create("double"); + + StringName type_Vector2 = StaticCString::create("Vector2"); + StringName type_Rect2 = StaticCString::create("Rect2"); + StringName type_Vector3 = StaticCString::create("Vector3"); + + // Object not included as it must be checked for all derived classes + static constexpr int nullable_types_count = 17; + StringName nullable_types[nullable_types_count] = { + type_String, + type_StringName, + type_NodePath, + + StaticCString::create(_STR(Array)), + StaticCString::create(_STR(Dictionary)), + StaticCString::create(_STR(Callable)), + StaticCString::create(_STR(Signal)), + + StaticCString::create(_STR(PackedByteArray)), + StaticCString::create(_STR(PackedInt32Array)), + StaticCString::create(_STR(PackedInt64rray)), + StaticCString::create(_STR(PackedFloat32Array)), + StaticCString::create(_STR(PackedFloat64Array)), + StaticCString::create(_STR(PackedStringArray)), + StaticCString::create(_STR(PackedVector2Array)), + StaticCString::create(_STR(PackedVector3Array)), + StaticCString::create(_STR(PackedColorArray)), + }; + + bool is_nullable_type(const StringName &p_type) const { + for (int i = 0; i < nullable_types_count; i++) { + if (p_type == nullable_types[i]) { + return true; + } + } + + return false; } + NameCache() {} + private: NameCache(const NameCache &); NameCache &operator=(const NameCache &); @@ -619,28 +603,32 @@ class BindingsGenerator { const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) { const List<InternalCall>::Element *it = p_list.front(); while (it) { - if (it->get().name == p_name) return it; + if (it->get().name == p_name) { + return it; + } it = it->next(); } - return NULL; + return nullptr; } const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const { for (const List<ConstantInterface>::Element *E = p_constants.front(); E; E = E->next()) { - if (E->get().name == p_name) + if (E->get().name == p_name) { return &E->get(); + } } - return NULL; + return nullptr; } inline String get_unique_sig(const TypeInterface &p_type) { - if (p_type.is_reference) + if (p_type.is_reference) { return "Ref"; - else if (p_type.is_object_type) + } else if (p_type.is_object_type) { return "Obj"; - else if (p_type.is_enum) + } else if (p_type.is_enum) { return "int"; + } return p_type.name; } @@ -659,6 +647,7 @@ class BindingsGenerator { StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta); bool _arg_default_value_from_variant(const Variant &p_val, ArgumentInterface &r_iarg); + bool _arg_default_value_is_assignable_to_type(const Variant &p_val, const TypeInterface &p_arg_type); bool _populate_object_type_interfaces(); void _populate_builtin_type_interfaces(); @@ -696,9 +685,7 @@ public: static void handle_cmdline_args(const List<String> &p_cmdline_args); - BindingsGenerator() : - log_print_enabled(true), - initialized(false) { + BindingsGenerator() { _initialize(); } }; diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp new file mode 100644 index 0000000000..7a5e465e7a --- /dev/null +++ b/modules/mono/editor/code_completion.cpp @@ -0,0 +1,249 @@ +/*************************************************************************/ +/* code_completion.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "code_completion.h" + +#include "core/project_settings.h" +#include "editor/editor_file_system.h" +#include "editor/editor_settings.h" +#include "scene/gui/control.h" +#include "scene/main/node.h" + +namespace gdmono { + +// Almost everything here is taken from functions used by GDScript for code completion, adapted for C#. + +_FORCE_INLINE_ String quoted(const String &p_str) { + return "\"" + p_str + "\""; +} + +void _add_nodes_suggestions(const Node *p_base, const Node *p_node, PackedStringArray &r_suggestions) { + if (p_node != p_base && !p_node->get_owner()) + return; + + String path_relative_to_orig = p_base->get_path_to(p_node); + + r_suggestions.push_back(quoted(path_relative_to_orig)); + + for (int i = 0; i < p_node->get_child_count(); i++) { + _add_nodes_suggestions(p_base, p_node->get_child(i), r_suggestions); + } +} + +Node *_find_node_for_script(Node *p_base, Node *p_current, const Ref<Script> &p_script) { + if (p_current->get_owner() != p_base && p_base != p_current) + return nullptr; + + Ref<Script> c = p_current->get_script(); + + if (c == p_script) + return p_current; + + for (int i = 0; i < p_current->get_child_count(); i++) { + Node *found = _find_node_for_script(p_base, p_current->get_child(i), p_script); + if (found) + return found; + } + + return nullptr; +} + +void _get_directory_contents(EditorFileSystemDirectory *p_dir, PackedStringArray &r_suggestions) { + for (int i = 0; i < p_dir->get_file_count(); i++) { + r_suggestions.push_back(quoted(p_dir->get_file_path(i))); + } + + for (int i = 0; i < p_dir->get_subdir_count(); i++) { + _get_directory_contents(p_dir->get_subdir(i), r_suggestions); + } +} + +Node *_try_find_owner_node_in_tree(const Ref<Script> p_script) { + SceneTree *tree = SceneTree::get_singleton(); + if (!tree) + return nullptr; + Node *base = tree->get_edited_scene_root(); + if (base) { + base = _find_node_for_script(base, base, p_script); + } + return base; +} + +PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_script_file) { + PackedStringArray suggestions; + + switch (p_kind) { + case CompletionKind::INPUT_ACTIONS: { + List<PropertyInfo> project_props; + ProjectSettings::get_singleton()->get_property_list(&project_props); + + for (List<PropertyInfo>::Element *E = project_props.front(); E; E = E->next()) { + const PropertyInfo &prop = E->get(); + + if (!prop.name.begins_with("input/")) + continue; + + String name = prop.name.substr(prop.name.find("/") + 1, prop.name.length()); + suggestions.push_back(quoted(name)); + } + } break; + case CompletionKind::NODE_PATHS: { + { + // AutoLoads + List<PropertyInfo> props; + ProjectSettings::get_singleton()->get_property_list(&props); + + for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { + String s = E->get().name; + if (!s.begins_with("autoload/")) { + continue; + } + String name = s.get_slice("/", 1); + suggestions.push_back(quoted("/root/" + name)); + } + } + + { + // Current edited scene tree + Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path()); + Node *base = _try_find_owner_node_in_tree(script); + if (base) { + _add_nodes_suggestions(base, base, suggestions); + } + } + } break; + case CompletionKind::RESOURCE_PATHS: { + if (bool(EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))) { + _get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), suggestions); + } + } break; + case CompletionKind::SCENE_PATHS: { + DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); + List<String> directories; + directories.push_back(dir_access->get_current_dir()); + + while (!directories.empty()) { + dir_access->change_dir(directories.back()->get()); + directories.pop_back(); + + dir_access->list_dir_begin(); + String filename = dir_access->get_next(); + + while (filename != "") { + if (filename == "." || filename == "..") { + filename = dir_access->get_next(); + continue; + } + + if (dir_access->dir_exists(filename)) { + directories.push_back(dir_access->get_current_dir().plus_file(filename)); + } else if (filename.ends_with(".tscn") || filename.ends_with(".scn")) { + suggestions.push_back(quoted(dir_access->get_current_dir().plus_file(filename))); + } + + filename = dir_access->get_next(); + } + } + } break; + case CompletionKind::SHADER_PARAMS: { + print_verbose("Shared params completion for C# not implemented."); + } break; + case CompletionKind::SIGNALS: { + Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path()); + + List<MethodInfo> signals; + script->get_script_signal_list(&signals); + + StringName native = script->get_instance_base_type(); + if (native != StringName()) { + ClassDB::get_signal_list(native, &signals, /* p_no_inheritance: */ false); + } + + for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) { + const String &signal = E->get().name; + suggestions.push_back(quoted(signal)); + } + } break; + case CompletionKind::THEME_COLORS: { + Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path()); + Node *base = _try_find_owner_node_in_tree(script); + if (base && Object::cast_to<Control>(base)) { + List<StringName> sn; + Theme::get_default()->get_color_list(base->get_class(), &sn); + + for (List<StringName>::Element *E = sn.front(); E; E = E->next()) { + suggestions.push_back(quoted(E->get())); + } + } + } break; + case CompletionKind::THEME_CONSTANTS: { + Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path()); + Node *base = _try_find_owner_node_in_tree(script); + if (base && Object::cast_to<Control>(base)) { + List<StringName> sn; + Theme::get_default()->get_constant_list(base->get_class(), &sn); + + for (List<StringName>::Element *E = sn.front(); E; E = E->next()) { + suggestions.push_back(quoted(E->get())); + } + } + } break; + case CompletionKind::THEME_FONTS: { + Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path()); + Node *base = _try_find_owner_node_in_tree(script); + if (base && Object::cast_to<Control>(base)) { + List<StringName> sn; + Theme::get_default()->get_font_list(base->get_class(), &sn); + + for (List<StringName>::Element *E = sn.front(); E; E = E->next()) { + suggestions.push_back(quoted(E->get())); + } + } + } break; + case CompletionKind::THEME_STYLES: { + Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path()); + Node *base = _try_find_owner_node_in_tree(script); + if (base && Object::cast_to<Control>(base)) { + List<StringName> sn; + Theme::get_default()->get_stylebox_list(base->get_class(), &sn); + + for (List<StringName>::Element *E = sn.front(); E; E = E->next()) { + suggestions.push_back(quoted(E->get())); + } + } + } break; + default: + ERR_FAIL_V_MSG(suggestions, "Invalid completion kind."); + } + + return suggestions; +} + +} // namespace gdmono diff --git a/modules/mono/editor/code_completion.h b/modules/mono/editor/code_completion.h new file mode 100644 index 0000000000..77673b766f --- /dev/null +++ b/modules/mono/editor/code_completion.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* code_completion.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CODE_COMPLETION_H +#define CODE_COMPLETION_H + +#include "core/ustring.h" +#include "core/variant.h" + +namespace gdmono { + +enum class CompletionKind { + INPUT_ACTIONS = 0, + NODE_PATHS, + RESOURCE_PATHS, + SCENE_PATHS, + SHADER_PARAMS, + SIGNALS, + THEME_COLORS, + THEME_CONSTANTS, + THEME_FONTS, + THEME_STYLES +}; + +PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_script_file); + +} // namespace gdmono + +#endif // CODE_COMPLETION_H diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp index 872f45ba91..3a30f3106c 100644 --- a/modules/mono/editor/csharp_project.cpp +++ b/modules/mono/editor/csharp_project.cpp @@ -45,7 +45,6 @@ namespace CSharpProject { void add_item(const String &p_project_path, const String &p_item_type, const String &p_include) { - if (!GLOBAL_DEF("mono/project/auto_update_project", true)) return; @@ -57,8 +56,8 @@ void add_item(const String &p_project_path, const String &p_item_type, const Str Variant item_type = p_item_type; Variant include = p_include; const Variant *args[3] = { &project_path, &item_type, &include }; - MonoException *exc = NULL; - klass->get_method("AddItemToProjectChecked", 3)->invoke(NULL, args, &exc); + MonoException *exc = nullptr; + klass->get_method("AddItemToProjectChecked", 3)->invoke(nullptr, args, &exc); if (exc) { GDMonoUtils::debug_print_unhandled_exception(exc); diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp index 31996a03d0..b183787618 100644 --- a/modules/mono/editor/editor_internal_calls.cpp +++ b/modules/mono/editor/editor_internal_calls.cpp @@ -48,6 +48,7 @@ #include "../mono_gd/gd_mono_marshal.h" #include "../utils/osx_utils.h" #include "bindings_generator.h" +#include "code_completion.h" #include "godotsharp_export.h" #include "script_class_parser.h" @@ -95,7 +96,7 @@ MonoString *godot_icall_GodotSharpDirs_MonoSolutionsDir() { #ifdef TOOLS_ENABLED return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_mono_solutions_dir()); #else - return NULL; + return nullptr; #endif } @@ -103,7 +104,7 @@ MonoString *godot_icall_GodotSharpDirs_BuildLogsDirs() { #ifdef TOOLS_ENABLED return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_build_logs_dir()); #else - return NULL; + return nullptr; #endif } @@ -111,7 +112,7 @@ MonoString *godot_icall_GodotSharpDirs_ProjectSlnPath() { #ifdef TOOLS_ENABLED return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_project_sln_path()); #else - return NULL; + return nullptr; #endif } @@ -119,7 +120,7 @@ MonoString *godot_icall_GodotSharpDirs_ProjectCsProjPath() { #ifdef TOOLS_ENABLED return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_project_csproj_path()); #else - return NULL; + return nullptr; #endif } @@ -127,7 +128,7 @@ MonoString *godot_icall_GodotSharpDirs_DataEditorToolsDir() { #ifdef TOOLS_ENABLED return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_editor_tools_dir()); #else - return NULL; + return nullptr; #endif } @@ -135,7 +136,7 @@ MonoString *godot_icall_GodotSharpDirs_DataEditorPrebuiltApiDir() { #ifdef TOOLS_ENABLED return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_editor_prebuilt_api_dir()); #else - return NULL; + return nullptr; #endif } @@ -151,7 +152,7 @@ MonoString *godot_icall_GodotSharpDirs_DataMonoBinDir() { #ifdef WINDOWS_ENABLED return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_mono_bin_dir()); #else - return NULL; + return nullptr; #endif } @@ -202,7 +203,7 @@ uint32_t godot_icall_BindingsGenerator_CsGlueVersion() { } int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObject *p_classes, MonoString **r_error_str) { - *r_error_str = NULL; + *r_error_str = nullptr; String filepath = GDMonoMarshal::mono_string_to_godot(p_filepath); @@ -231,14 +232,14 @@ int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObje return err; } -uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_dependencies, - MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_dependencies) { - Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_dependencies); +uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies, + MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_assembly_dependencies) { + Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_assemblies); String build_config = GDMonoMarshal::mono_string_to_godot(p_build_config); String custom_bcl_dir = GDMonoMarshal::mono_string_to_godot(p_custom_bcl_dir); - Dictionary dependencies = GDMonoMarshal::mono_object_to_variant(r_dependencies); + Dictionary assembly_dependencies = GDMonoMarshal::mono_object_to_variant(r_assembly_dependencies); - return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, dependencies); + return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, assembly_dependencies); } MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) { @@ -335,7 +336,7 @@ MonoString *godot_icall_Internal_MonoWindowsInstallRoot() { String install_root_dir = GDMono::get_singleton()->get_mono_reg_info().install_root_dir; return GDMonoMarshal::mono_string_from_godot(install_root_dir); #else - return NULL; + return nullptr; #endif } @@ -354,6 +355,12 @@ void godot_icall_Internal_ScriptEditorDebugger_ReloadScripts() { } } +MonoArray *godot_icall_Internal_CodeCompletionRequest(int32_t p_kind, MonoString *p_script_file) { + String script_file = GDMonoMarshal::mono_string_to_godot(p_script_file); + PackedStringArray suggestions = gdmono::get_code_completion((gdmono::CompletionKind)p_kind, script_file); + return GDMonoMarshal::PackedStringArray_to_mono_array(suggestions); +} + float godot_icall_Globals_EditorScale() { return EDSCALE; } @@ -392,7 +399,6 @@ MonoBoolean godot_icall_Utils_OS_UnixFileHasExecutableAccess(MonoString *p_file_ } void register_editor_internal_calls() { - // GodotSharpDirs mono_add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResDataDir", (void *)godot_icall_GodotSharpDirs_ResDataDir); mono_add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResMetadataDir", (void *)godot_icall_GodotSharpDirs_ResMetadataDir); @@ -454,6 +460,7 @@ void register_editor_internal_calls() { mono_add_internal_call("GodotTools.Internals.Internal::internal_EditorRunPlay", (void *)godot_icall_Internal_EditorRunPlay); mono_add_internal_call("GodotTools.Internals.Internal::internal_EditorRunStop", (void *)godot_icall_Internal_EditorRunStop); mono_add_internal_call("GodotTools.Internals.Internal::internal_ScriptEditorDebugger_ReloadScripts", (void *)godot_icall_Internal_ScriptEditorDebugger_ReloadScripts); + mono_add_internal_call("GodotTools.Internals.Internal::internal_CodeCompletionRequest", (void *)godot_icall_Internal_CodeCompletionRequest); // Globals mono_add_internal_call("GodotTools.Internals.Globals::internal_EditorScale", (void *)godot_icall_Globals_EditorScale); diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp index ce0b6ad0e6..1cdb08d50e 100644 --- a/modules/mono/editor/godotsharp_export.cpp +++ b/modules/mono/editor/godotsharp_export.cpp @@ -32,77 +32,80 @@ #include <mono/metadata/image.h> +#include "core/io/file_access_pack.h" #include "core/os/os.h" +#include "core/project_settings.h" #include "../mono_gd/gd_mono.h" #include "../mono_gd/gd_mono_assembly.h" #include "../mono_gd/gd_mono_cache.h" +#include "../utils/macros.h" namespace GodotSharpExport { -String get_assemblyref_name(MonoImage *p_image, int index) { +struct AssemblyRefInfo { + String name; + uint16_t major; + uint16_t minor; + uint16_t build; + uint16_t revision; +}; + +AssemblyRefInfo get_assemblyref_name(MonoImage *p_image, int index) { const MonoTableInfo *table_info = mono_image_get_table_info(p_image, MONO_TABLE_ASSEMBLYREF); uint32_t cols[MONO_ASSEMBLYREF_SIZE]; mono_metadata_decode_row(table_info, index, cols, MONO_ASSEMBLYREF_SIZE); - return String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME])); + return { + String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME])), + (uint16_t)cols[MONO_ASSEMBLYREF_MAJOR_VERSION], + (uint16_t)cols[MONO_ASSEMBLYREF_MINOR_VERSION], + (uint16_t)cols[MONO_ASSEMBLYREF_BUILD_NUMBER], + (uint16_t)cols[MONO_ASSEMBLYREF_REV_NUMBER] + }; } -Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies) { +Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_assembly_dependencies) { MonoImage *image = p_assembly->get_image(); for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) { - String ref_name = get_assemblyref_name(image, i); + AssemblyRefInfo ref_info = get_assemblyref_name(image, i); + + const String &ref_name = ref_info.name; - if (r_dependencies.has(ref_name)) + if (r_assembly_dependencies.has(ref_name)) continue; - GDMonoAssembly *ref_assembly = NULL; - String path; - bool has_extension = ref_name.ends_with(".dll") || ref_name.ends_with(".exe"); - - for (int j = 0; j < p_search_dirs.size(); j++) { - const String &search_dir = p_search_dirs[j]; - - if (has_extension) { - path = search_dir.plus_file(ref_name); - if (FileAccess::exists(path)) { - GDMono::get_singleton()->load_assembly_from(ref_name.get_basename(), path, &ref_assembly, true); - if (ref_assembly != NULL) - break; - } - } else { - path = search_dir.plus_file(ref_name + ".dll"); - if (FileAccess::exists(path)) { - GDMono::get_singleton()->load_assembly_from(ref_name, path, &ref_assembly, true); - if (ref_assembly != NULL) - break; - } - - path = search_dir.plus_file(ref_name + ".exe"); - if (FileAccess::exists(path)) { - GDMono::get_singleton()->load_assembly_from(ref_name, path, &ref_assembly, true); - if (ref_assembly != NULL) - break; - } - } - } + GDMonoAssembly *ref_assembly = nullptr; + + { + MonoAssemblyName *ref_aname = mono_assembly_name_new("A"); // We can't allocate an empty MonoAssemblyName, hence "A" + CRASH_COND(ref_aname == nullptr); + SCOPE_EXIT { + mono_assembly_name_free(ref_aname); + mono_free(ref_aname); + }; - ERR_FAIL_COND_V_MSG(!ref_assembly, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'."); + mono_assembly_get_assemblyref(image, i, ref_aname); - r_dependencies[ref_name] = ref_assembly->get_path(); + if (!GDMono::get_singleton()->load_assembly(ref_name, ref_aname, &ref_assembly, /* refonly: */ true, p_search_dirs)) { + ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'."); + } + + r_assembly_dependencies[ref_name] = ref_assembly->get_path(); + } - Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies); + Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_assembly_dependencies); ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'."); } return OK; } -Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies, - const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_dependencies) { +Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies, + const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_assembly_dependencies) { MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport"); ERR_FAIL_NULL_V(export_domain, FAILED); _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain); @@ -112,16 +115,21 @@ Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencie Vector<String> search_dirs; GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir); - for (const Variant *key = p_initial_dependencies.next(); key; key = p_initial_dependencies.next(key)) { + if (p_custom_bcl_dir.length()) { + // Only one mscorlib can be loaded. We need this workaround to make sure we get it from the right BCL directory. + r_assembly_dependencies["mscorlib"] = p_custom_bcl_dir.plus_file("mscorlib.dll").simplify_path(); + } + + for (const Variant *key = p_initial_assemblies.next(); key; key = p_initial_assemblies.next(key)) { String assembly_name = *key; - String assembly_path = p_initial_dependencies[*key]; + String assembly_path = p_initial_assemblies[*key]; - GDMonoAssembly *assembly = NULL; + GDMonoAssembly *assembly = nullptr; bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true); ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'."); - Error err = get_assembly_dependencies(assembly, search_dirs, r_dependencies); + Error err = get_assembly_dependencies(assembly, search_dirs, r_assembly_dependencies); if (err != OK) return err; } diff --git a/modules/mono/editor/godotsharp_export.h b/modules/mono/editor/godotsharp_export.h index 36138f81b7..9ab57755de 100644 --- a/modules/mono/editor/godotsharp_export.h +++ b/modules/mono/editor/godotsharp_export.h @@ -41,8 +41,8 @@ namespace GodotSharpExport { Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies); -Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies, - const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_dependencies); +Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies, + const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_assembly_dependencies); } // namespace GodotSharpExport diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp index bece23c9a6..7276612230 100644 --- a/modules/mono/editor/script_class_parser.cpp +++ b/modules/mono/editor/script_class_parser.cpp @@ -54,13 +54,11 @@ const char *ScriptClassParser::token_names[ScriptClassParser::TK_MAX] = { }; String ScriptClassParser::get_token_name(ScriptClassParser::Token p_token) { - ERR_FAIL_INDEX_V(p_token, TK_MAX, "<error>"); return token_names[p_token]; } ScriptClassParser::Token ScriptClassParser::get_token() { - while (true) { switch (code[idx]) { case '\n': { @@ -181,14 +179,24 @@ ScriptClassParser::Token ScriptClassParser::get_token() { CharType res = 0; switch (next) { - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; + case 'b': + res = 8; + break; + case 't': + res = 9; + break; + case 'n': + res = 10; + break; + case 'f': + res = 12; + break; case 'r': res = 13; break; - case '\"': res = '\"'; break; + case '\"': + res = '\"'; + break; case '\\': res = '\\'; break; @@ -258,7 +266,6 @@ ScriptClassParser::Token ScriptClassParser::get_token() { } Error ScriptClassParser::_skip_generic_type_params() { - Token tk; while (true) { @@ -327,7 +334,6 @@ Error ScriptClassParser::_skip_generic_type_params() { } Error ScriptClassParser::_parse_type_full_name(String &r_full_name) { - Token tk = get_token(); if (tk != TK_IDENTIFIER) { @@ -360,7 +366,6 @@ Error ScriptClassParser::_parse_type_full_name(String &r_full_name) { } Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) { - String name; Error err = _parse_type_full_name(name); @@ -460,7 +465,6 @@ Error ScriptClassParser::_parse_type_constraints() { } Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stack) { - Token tk = get_token(); if (tk == TK_IDENTIFIER) { @@ -487,7 +491,6 @@ Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stac } Error ScriptClassParser::parse(const String &p_code) { - code = p_code; idx = 0; line = 0; @@ -643,7 +646,6 @@ static String get_preprocessor_directive(const String &p_line, int p_from) { } static void run_dummy_preprocessor(String &r_source, const String &p_filepath) { - Vector<String> lines = r_source.split("\n", /* p_allow_empty: */ true); bool *include_lines = memnew_arr(bool, lines.size()); @@ -710,7 +712,6 @@ static void run_dummy_preprocessor(String &r_source, const String &p_filepath) { } Error ScriptClassParser::parse_file(const String &p_filepath) { - String source; Error ferr = read_all_file_utf8(p_filepath, source); diff --git a/modules/mono/editor/script_class_parser.h b/modules/mono/editor/script_class_parser.h index a76a3a50a9..c194ed1422 100644 --- a/modules/mono/editor/script_class_parser.h +++ b/modules/mono/editor/script_class_parser.h @@ -36,7 +36,6 @@ #include "core/vector.h" class ScriptClassParser { - public: struct NameDecl { enum Type { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs index aba1065498..a963810d63 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs @@ -15,10 +15,7 @@ namespace Godot.Collections public override bool IsInvalid { - get - { - return handle == IntPtr.Zero; - } + get { return handle == IntPtr.Zero; } } protected override bool ReleaseHandle() @@ -43,7 +40,8 @@ namespace Godot.Collections if (collection == null) throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'"); - MarshalUtils.EnumerableToArray(collection, GetPtr()); + foreach (object element in collection) + Add(element); } internal Array(ArraySafeHandle handle) @@ -272,14 +270,8 @@ namespace Godot.Collections public T this[int index] { - get - { - return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); - } - set - { - objectArray[index] = value; - } + get { return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); } + set { objectArray[index] = value; } } public int IndexOf(T item) @@ -301,18 +293,12 @@ namespace Godot.Collections public int Count { - get - { - return objectArray.Count; - } + get { return objectArray.Count; } } public bool IsReadOnly { - get - { - return objectArray.IsReadOnly; - } + get { return objectArray.IsReadOnly; } } public void Add(T item) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index 1d1a49945f..6030b72a44 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -306,16 +306,26 @@ namespace Godot return res; } - public Color LinearInterpolate(Color c, float t) - { - var res = this; - - res.r += t * (c.r - r); - res.g += t * (c.g - g); - res.b += t * (c.b - b); - res.a += t * (c.a - a); + public Color Lerp(Color to, float weight) + { + return new Color + ( + Mathf.Lerp(r, to.r, weight), + Mathf.Lerp(g, to.g, weight), + Mathf.Lerp(b, to.b, weight), + Mathf.Lerp(a, to.a, weight) + ); + } - return res; + public Color Lerp(Color to, Color weight) + { + return new Color + ( + Mathf.Lerp(r, to.r, weight.r), + Mathf.Lerp(g, to.g, weight.g), + Mathf.Lerp(b, to.b, weight.b), + Mathf.Lerp(a, to.a, weight.a) + ); } public uint ToAbgr32() @@ -410,7 +420,7 @@ namespace Godot return txt; } - // Constructors + // Constructors public Color(float r, float g, float b, float a = 1.0f) { this.r = r; @@ -419,6 +429,14 @@ namespace Godot this.a = a; } + public Color(Color c, float a = 1.0f) + { + r = c.r; + g = c.g; + b = c.b; + this.a = a; + } + public Color(uint rgba) { a = (rgba & 0xFF) / 255.0f; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs index d72109de92..213fc181c1 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs @@ -15,10 +15,7 @@ namespace Godot.Collections public override bool IsInvalid { - get - { - return handle == IntPtr.Zero; - } + get { return handle == IntPtr.Zero; } } protected override bool ReleaseHandle() @@ -45,7 +42,8 @@ namespace Godot.Collections if (dictionary == null) throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'"); - MarshalUtils.IDictionaryToDictionary(dictionary, GetPtr()); + foreach (DictionaryEntry entry in dictionary) + Add(entry.Key, entry.Value); } internal Dictionary(DictionarySafeHandle handle) @@ -330,14 +328,8 @@ namespace Godot.Collections public TValue this[TKey key] { - get - { - return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(objectDict.GetPtr(), key, valTypeEncoding, valTypeClass); - } - set - { - objectDict[key] = value; - } + get { return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(objectDict.GetPtr(), key, valTypeEncoding, valTypeClass); } + set { objectDict[key] = value; } } public ICollection<TKey> Keys @@ -385,18 +377,12 @@ namespace Godot.Collections public int Count { - get - { - return objectDict.Count; - } + get { return objectDict.Count; } } public bool IsReadOnly { - get - { - return objectDict.IsReadOnly; - } + get { return objectDict.IsReadOnly; } } public void Add(KeyValuePair<TKey, TValue> item) @@ -440,7 +426,8 @@ namespace Godot.Collections public bool Remove(KeyValuePair<TKey, TValue> item) { - return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value); ; + return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value); + ; } // IEnumerable<KeyValuePair<TKey, TValue>> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs index a0f105d55e..c4c911b863 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs @@ -23,7 +23,7 @@ namespace Godot /// <example> /// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the engine members of a <see cref="Godot.Object"/>. /// <code> - /// dynamic sprite = GetNode("Sprite").DynamicGodotObject; + /// dynamic sprite = GetNode("Sprite2D").DynamicGodotObject; /// sprite.add_child(this); /// /// if ((sprite.hframes * sprite.vframes) > 0) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs index a1d63a62ef..c59d083080 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs @@ -16,10 +16,8 @@ namespace Godot /// <exception cref="System.InvalidOperationException"> /// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false. /// </exception> - static bool TypeIsGenericArray(Type type) - { - return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>); - } + static bool TypeIsGenericArray(Type type) => + type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>); /// <summary> /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/> @@ -28,10 +26,20 @@ namespace Godot /// <exception cref="System.InvalidOperationException"> /// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false. /// </exception> - static bool TypeIsGenericDictionary(Type type) - { - return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>); - } + static bool TypeIsGenericDictionary(Type type) => + type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>); + + static bool TypeIsSystemGenericList(Type type) => + type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>); + + static bool TypeIsSystemGenericDictionary(Type type) => + type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.Dictionary<,>); + + static bool TypeIsGenericIEnumerable(Type type) => type.GetGenericTypeDefinition() == typeof(IEnumerable<>); + + static bool TypeIsGenericICollection(Type type) => type.GetGenericTypeDefinition() == typeof(ICollection<>); + + static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>); static void ArrayGetElementType(Type arrayType, out Type elementType) { @@ -45,105 +53,6 @@ namespace Godot valueType = genericArgs[1]; } - static bool GenericIEnumerableIsAssignableFromType(Type type) - { - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - return true; - - foreach (var interfaceType in type.GetInterfaces()) - { - if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - return true; - } - - Type baseType = type.BaseType; - - if (baseType == null) - return false; - - return GenericIEnumerableIsAssignableFromType(baseType); - } - - static bool GenericIDictionaryIsAssignableFromType(Type type) - { - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>)) - return true; - - foreach (var interfaceType in type.GetInterfaces()) - { - if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>)) - return true; - } - - Type baseType = type.BaseType; - - if (baseType == null) - return false; - - return GenericIDictionaryIsAssignableFromType(baseType); - } - - static bool GenericIEnumerableIsAssignableFromType(Type type, out Type elementType) - { - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - { - elementType = type.GetGenericArguments()[0]; - return true; - } - - foreach (var interfaceType in type.GetInterfaces()) - { - if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - { - elementType = interfaceType.GetGenericArguments()[0]; - return true; - } - } - - Type baseType = type.BaseType; - - if (baseType == null) - { - elementType = null; - return false; - } - - return GenericIEnumerableIsAssignableFromType(baseType, out elementType); - } - - static bool GenericIDictionaryIsAssignableFromType(Type type, out Type keyType, out Type valueType) - { - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>)) - { - var genericArgs = type.GetGenericArguments(); - keyType = genericArgs[0]; - valueType = genericArgs[1]; - return true; - } - - foreach (var interfaceType in type.GetInterfaces()) - { - if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>)) - { - var genericArgs = interfaceType.GetGenericArguments(); - keyType = genericArgs[0]; - valueType = genericArgs[1]; - return true; - } - } - - Type baseType = type.BaseType; - - if (baseType == null) - { - keyType = null; - valueType = null; - return false; - } - - return GenericIDictionaryIsAssignableFromType(baseType, out keyType, out valueType); - } - static Type MakeGenericArrayType(Type elemType) { return typeof(Godot.Collections.Array<>).MakeGenericType(elemType); @@ -153,60 +62,5 @@ namespace Godot { return typeof(Godot.Collections.Dictionary<,>).MakeGenericType(keyType, valueType); } - - // TODO Add support for IEnumerable<T> and IDictionary<TKey, TValue> - // TODO: EnumerableToArray and IDictionaryToDictionary can be optimized - - internal static void EnumerableToArray(IEnumerable enumerable, IntPtr godotArrayPtr) - { - if (enumerable is ICollection collection) - { - int count = collection.Count; - - object[] tempArray = new object[count]; - collection.CopyTo(tempArray, 0); - - for (int i = 0; i < count; i++) - { - Array.godot_icall_Array_Add(godotArrayPtr, tempArray[i]); - } - } - else - { - foreach (object element in enumerable) - { - Array.godot_icall_Array_Add(godotArrayPtr, element); - } - } - } - - internal static void IDictionaryToDictionary(IDictionary dictionary, IntPtr godotDictionaryPtr) - { - foreach (DictionaryEntry entry in dictionary) - { - Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, entry.Key, entry.Value); - } - } - - internal static void GenericIDictionaryToDictionary(object dictionary, IntPtr godotDictionaryPtr) - { -#if DEBUG - if (!GenericIDictionaryIsAssignableFromType(dictionary.GetType())) - throw new InvalidOperationException("The type does not implement IDictionary<,>"); -#endif - - // TODO: Can we optimize this? - - var keys = ((IEnumerable)dictionary.GetType().GetProperty("Keys").GetValue(dictionary)).GetEnumerator(); - var values = ((IEnumerable)dictionary.GetType().GetProperty("Values").GetValue(dictionary)).GetEnumerator(); - - while (keys.MoveNext() && values.MoveNext()) - { - object key = keys.Current; - object value = values.Current; - - Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, key, value); - } - } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs index 91e614dc7b..1098ffe4e5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs @@ -127,7 +127,7 @@ namespace Godot { var g = this; - g.GrowIndividual(Margin.Left == margin ? by : 0, + g = g.GrowIndividual(Margin.Left == margin ? by : 0, Margin.Top == margin ? by : 0, Margin.Right == margin ? by : 0, Margin.Bottom == margin ? by : 0); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs index bc2cad8713..c0b236c524 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs @@ -122,7 +122,7 @@ namespace Godot { var g = this; - g.GrowIndividual(Margin.Left == margin ? by : 0, + g = g.GrowIndividual(Margin.Left == margin ? by : 0, Margin.Top == margin ? by : 0, Margin.Right == margin ? by : 0, Margin.Bottom == margin ? by : 0); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index 099eacd7dd..41b4e9367f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -12,7 +12,7 @@ namespace Godot { private static int GetSliceCount(this string instance, string splitter) { - if (instance.Empty() || splitter.Empty()) + if (string.IsNullOrEmpty(instance) || string.IsNullOrEmpty(splitter)) return 0; int pos = 0; @@ -29,7 +29,7 @@ namespace Godot private static string GetSliceCharacter(this string instance, char splitter, int slice) { - if (!instance.Empty() && slice >= 0) + if (!string.IsNullOrEmpty(instance) && slice >= 0) { int i = 0; int prev = 0; @@ -237,10 +237,10 @@ namespace Godot // </summary> public static int CompareTo(this string instance, string to, bool caseSensitive = true) { - if (instance.Empty()) - return to.Empty() ? 0 : -1; + if (string.IsNullOrEmpty(instance)) + return string.IsNullOrEmpty(to) ? 0 : -1; - if (to.Empty()) + if (string.IsNullOrEmpty(to)) return 1; int instanceIndex = 0; @@ -287,14 +287,6 @@ namespace Godot } // <summary> - // Return true if the string is empty. - // </summary> - public static bool Empty(this string instance) - { - return string.IsNullOrEmpty(instance); - } - - // <summary> // Return true if the strings ends with the given string. // </summary> public static bool EndsWith(this string instance, string text) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs index aa8815d1aa..6a58b90561 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs @@ -104,8 +104,8 @@ namespace Godot Vector3 destinationLocation = transform.origin; var interpolated = new Transform(); - interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.LinearInterpolate(destinationScale, c)); - interpolated.origin = sourceLocation.LinearInterpolate(destinationLocation, c); + interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.Lerp(destinationScale, c)); + interpolated.origin = sourceLocation.Lerp(destinationLocation, c); return interpolated; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index e72a44809a..3ae96d4922 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -172,7 +172,7 @@ namespace Godot if (dot > 0.9995f) { // Linearly interpolate to avoid numerical precision issues - v = v1.LinearInterpolate(v2, c).Normalized(); + v = v1.Lerp(v2, c).Normalized(); } else { @@ -186,8 +186,8 @@ namespace Godot Vector2 p2 = m.origin; // Construct matrix - var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.LinearInterpolate(p2, c)); - Vector2 scale = s1.LinearInterpolate(s2, c); + var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.Lerp(p2, c)); + Vector2 scale = s1.Lerp(s2, c); res.x *= scale; res.y *= scale; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index f7b13198f8..7e4804f9fd 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -186,14 +186,22 @@ namespace Godot return x * x + y * y; } - public Vector2 LinearInterpolate(Vector2 b, real_t t) + public Vector2 Lerp(Vector2 to, real_t weight) { - var res = this; - - res.x += t * (b.x - x); - res.y += t * (b.y - y); + return new Vector2 + ( + Mathf.Lerp(x, to.x, weight), + Mathf.Lerp(y, to.y, weight) + ); + } - return res; + public Vector2 Lerp(Vector2 to, Vector2 weight) + { + return new Vector2 + ( + Mathf.Lerp(x, to.x, weight.x), + Mathf.Lerp(y, to.y, weight.y) + ); } public Vector2 MoveToward(Vector2 to, real_t delta) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index a43836e985..b26e17ecba 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -184,13 +184,23 @@ namespace Godot return x2 + y2 + z2; } - public Vector3 LinearInterpolate(Vector3 b, real_t t) + public Vector3 Lerp(Vector3 to, real_t weight) { return new Vector3 ( - x + t * (b.x - x), - y + t * (b.y - y), - z + t * (b.z - z) + Mathf.Lerp(x, to.x, weight), + Mathf.Lerp(y, to.y, weight), + Mathf.Lerp(z, to.z, weight) + ); + } + + public Vector3 Lerp(Vector3 to, Vector3 weight) + { + return new Vector3 + ( + Mathf.Lerp(x, to.x, weight.x), + Mathf.Lerp(y, to.y, weight.y), + Mathf.Lerp(z, to.z, weight.z) ); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index ba0bbd7630..b5ac124c9a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -30,6 +30,7 @@ <ConsolePause>false</ConsolePause> </PropertyGroup> <ItemGroup> + <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> <Reference Include="System" /> </ItemGroup> <ItemGroup> diff --git a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj index 22853797c1..8785931312 100644 --- a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj @@ -30,6 +30,7 @@ <ConsolePause>false</ConsolePause> </PropertyGroup> <ItemGroup> + <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> <Reference Include="System" /> </ItemGroup> <ItemGroup> diff --git a/modules/mono/glue/arguments_vector.h b/modules/mono/glue/arguments_vector.h index aeb466ba72..4ee553fc11 100644 --- a/modules/mono/glue/arguments_vector.h +++ b/modules/mono/glue/arguments_vector.h @@ -35,7 +35,6 @@ template <typename T, int POOL_SIZE = 5> struct ArgumentsVector { - private: T pool[POOL_SIZE]; T *_ptr; diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp index 120668d1ef..f370883320 100644 --- a/modules/mono/glue/base_object_glue.cpp +++ b/modules/mono/glue/base_object_glue.cpp @@ -51,7 +51,7 @@ Object *godot_icall_Object_Ctor(MonoObject *p_obj) { void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) { #ifdef DEBUG_ENABLED - CRASH_COND(p_ptr == NULL); + CRASH_COND(p_ptr == nullptr); #endif if (p_ptr->get_script_instance()) { @@ -59,7 +59,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) { if (cs_instance) { if (!cs_instance->is_destructing_script_instance()) { cs_instance->mono_object_disposed(p_obj); - p_ptr->set_script_instance(NULL); + p_ptr->set_script_instance(nullptr); } return; } @@ -80,7 +80,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) { void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) { #ifdef DEBUG_ENABLED - CRASH_COND(p_ptr == NULL); + CRASH_COND(p_ptr == nullptr); // This is only called with Reference derived classes CRASH_COND(!Object::cast_to<Reference>(p_ptr)); #endif @@ -99,7 +99,7 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolea if (delete_owner) { memdelete(ref); } else if (remove_script_instance) { - ref->set_script_instance(NULL); + ref->set_script_instance(nullptr); } } return; @@ -141,7 +141,7 @@ MethodBind *godot_icall_Object_ClassDB_get_method(StringName *p_type, MonoString MonoObject *godot_icall_Object_weakref(Object *p_ptr) { if (!p_ptr) - return NULL; + return nullptr; Ref<WeakRef> wref; Reference *ref = Object::cast_to<Reference>(p_ptr); @@ -149,7 +149,7 @@ MonoObject *godot_icall_Object_weakref(Object *p_ptr) { if (ref) { REF r = ref; if (!r.is_valid()) - return NULL; + return nullptr; wref.instance(); wref->set_ref(r); @@ -230,7 +230,7 @@ MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString * MonoString *godot_icall_Object_ToString(Object *p_ptr) { #ifdef DEBUG_ENABLED // Cannot happen in C#; would get an ObjectDisposedException instead. - CRASH_COND(p_ptr == NULL); + CRASH_COND(p_ptr == nullptr); #endif // Can't call 'Object::to_string()' here, as that can end up calling 'ToString' again resulting in an endless circular loop. String result = "[" + p_ptr->get_class() + ":" + itos(p_ptr->get_instance_id()) + "]"; diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp index b7fa7fcab2..4e3dc9c4ea 100644 --- a/modules/mono/glue/collections_glue.cpp +++ b/modules/mono/glue/collections_glue.cpp @@ -49,7 +49,7 @@ void godot_icall_Array_Dtor(Array *ptr) { MonoObject *godot_icall_Array_At(Array *ptr, int index) { if (index < 0 || index >= ptr->size()) { GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range()); - return NULL; + return nullptr; } return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index)); } @@ -57,7 +57,7 @@ MonoObject *godot_icall_Array_At(Array *ptr, int index) { MonoObject *godot_icall_Array_At_Generic(Array *ptr, int index, uint32_t type_encoding, GDMonoClass *type_class) { if (index < 0 || index >= ptr->size()) { GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range()); - return NULL; + return nullptr; } return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index), ManagedType(type_encoding, type_class)); } @@ -162,28 +162,28 @@ void godot_icall_Dictionary_Dtor(Dictionary *ptr) { MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) { Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key)); - if (ret == NULL) { + if (ret == nullptr) { MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr()); #ifdef DEBUG_ENABLED CRASH_COND(!exc); #endif GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException)); GDMonoUtils::set_pending_exception((MonoException *)exc); - return NULL; + return nullptr; } return GDMonoMarshal::variant_to_mono_object(ret); } MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject *key, uint32_t type_encoding, GDMonoClass *type_class) { Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key)); - if (ret == NULL) { + if (ret == nullptr) { MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr()); #ifdef DEBUG_ENABLED CRASH_COND(!exc); #endif GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException)); GDMonoUtils::set_pending_exception((MonoException *)exc); - return NULL; + return nullptr; } return GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class)); } @@ -207,7 +207,7 @@ int godot_icall_Dictionary_Count(Dictionary *ptr) { void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) { Variant varKey = GDMonoMarshal::mono_object_to_variant(key); Variant *ret = ptr->getptr(varKey); - if (ret != NULL) { + if (ret != nullptr) { GDMonoUtils::set_pending_exception(mono_get_exception_argument("key", "An element with the same key already exists")); return; } @@ -221,7 +221,7 @@ void godot_icall_Dictionary_Clear(Dictionary *ptr) { MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) { // no dupes Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key)); - return ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value); + return ret != nullptr && *ret == GDMonoMarshal::mono_object_to_variant(value); } MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) { @@ -241,7 +241,7 @@ MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, Mono // no dupes Variant *ret = ptr->getptr(varKey); - if (ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value)) { + if (ret != nullptr && *ret == GDMonoMarshal::mono_object_to_variant(value)) { ptr->erase(varKey); return true; } @@ -251,8 +251,8 @@ MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, Mono MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) { Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key)); - if (ret == NULL) { - *value = NULL; + if (ret == nullptr) { + *value = nullptr; return false; } *value = GDMonoMarshal::variant_to_mono_object(ret); @@ -261,8 +261,8 @@ MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) { Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key)); - if (ret == NULL) { - *value = NULL; + if (ret == nullptr) { + *value = nullptr; return false; } *value = GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class)); diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp index 1576d31a3b..e43b06d18e 100644 --- a/modules/mono/glue/gd_glue.cpp +++ b/modules/mono/glue/gd_glue.cpp @@ -45,7 +45,7 @@ MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes, MonoBoolean p_allow_objects) { Variant ret; PackedByteArray varr = GDMonoMarshal::mono_array_to_PackedByteArray(p_bytes); - Error err = decode_variant(ret, varr.ptr(), varr.size(), NULL, p_allow_objects); + Error err = decode_variant(ret, varr.ptr(), varr.size(), nullptr, p_allow_objects); if (err != OK) { ret = RTR("Not enough bytes for decoding bytes, or invalid format."); } @@ -57,7 +57,7 @@ MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type) { const Variant *args[1] = { &what }; Callable::CallError ce; Variant ret = Variant::construct(Variant::Type(p_type), args, 1, ce); - ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, NULL); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); return GDMonoMarshal::variant_to_mono_object(ret); } @@ -76,7 +76,7 @@ void godot_icall_GD_print(MonoArray *p_what) { for (int i = 0; i < length; i++) { MonoObject *elem = mono_array_get(p_what, MonoObject *, i); - MonoException *exc = NULL; + MonoException *exc = nullptr; String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc); if (exc) { @@ -91,14 +91,13 @@ void godot_icall_GD_print(MonoArray *p_what) { } void godot_icall_GD_printerr(MonoArray *p_what) { - String str; int length = mono_array_length(p_what); for (int i = 0; i < length; i++) { MonoObject *elem = mono_array_get(p_what, MonoObject *, i); - MonoException *exc = NULL; + MonoException *exc = nullptr; String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc); if (exc) { @@ -119,7 +118,7 @@ void godot_icall_GD_printraw(MonoArray *p_what) { for (int i = 0; i < length; i++) { MonoObject *elem = mono_array_get(p_what, MonoObject *, i); - MonoException *exc = NULL; + MonoException *exc = nullptr; String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc); if (exc) { @@ -140,7 +139,7 @@ void godot_icall_GD_prints(MonoArray *p_what) { for (int i = 0; i < length; i++) { MonoObject *elem = mono_array_get(p_what, MonoObject *, i); - MonoException *exc = NULL; + MonoException *exc = nullptr; String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc); if (exc) { @@ -164,7 +163,7 @@ void godot_icall_GD_printt(MonoArray *p_what) { for (int i = 0; i < length; i++) { MonoObject *elem = mono_array_get(p_what, MonoObject *, i); - MonoException *exc = NULL; + MonoException *exc = nullptr; String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc); if (exc) { @@ -259,8 +258,8 @@ MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_object PackedByteArray barr; int len; - Error err = encode_variant(var, NULL, len, p_full_objects); - ERR_FAIL_COND_V_MSG(err != OK, NULL, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."); + Error err = encode_variant(var, nullptr, len, p_full_objects); + ERR_FAIL_COND_V_MSG(err != OK, nullptr, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."); barr.resize(len); encode_variant(var, barr.ptrw(), len, p_full_objects); diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index 8130b0cc39..ee99a300b9 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -70,7 +70,7 @@ void godot_register_glue_header_icalls() { #include "../mono_gd/gd_mono_utils.h" #define GODOTSHARP_INSTANCE_OBJECT(m_instance, m_type) \ - static ClassDB::ClassInfo *ci = NULL; \ + static ClassDB::ClassInfo *ci = nullptr; \ if (!ci) { \ ci = ClassDB::classes.getptr(m_type); \ } \ diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index 828ab73c82..692da991c7 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -40,7 +40,7 @@ #endif #ifdef ANDROID_ENABLED -#include "mono_gd/gd_mono_android.h" +#include "mono_gd/support/android_support.h" #endif #include "mono_gd/gd_mono.h" @@ -86,7 +86,6 @@ String _get_mono_user_dir() { } class _GodotSharpDirs { - public: String res_data_dir; String res_metadata_dir; @@ -169,7 +168,7 @@ private: data_mono_etc_dir = data_mono_root_dir.plus_file("etc"); #ifdef ANDROID_ENABLED - data_mono_lib_dir = GDMonoAndroid::get_app_native_lib_dir(); + data_mono_lib_dir = gdmono::android::support::get_app_native_lib_dir(); #else data_mono_lib_dir = data_mono_root_dir.plus_file("lib"); #endif @@ -206,7 +205,7 @@ private: data_mono_etc_dir = data_mono_root_dir.plus_file("etc"); #ifdef ANDROID_ENABLED - data_mono_lib_dir = GDMonoAndroid::get_app_native_lib_dir(); + data_mono_lib_dir = gdmono::android::support::get_app_native_lib_dir(); #else data_mono_lib_dir = data_mono_root_dir.plus_file("lib"); data_game_assemblies_dir = data_dir_root.plus_file("Assemblies"); diff --git a/modules/mono/managed_callable.cpp b/modules/mono/managed_callable.cpp index a9cf64d1cc..26347e9162 100644 --- a/modules/mono/managed_callable.cpp +++ b/modules/mono/managed_callable.cpp @@ -82,6 +82,7 @@ CallableCustom::CompareLessFunc ManagedCallable::get_compare_less_func() const { } ObjectID ManagedCallable::get_object() const { + // TODO: If the delegate target extends Godot.Object, use that instead! return CSharpLanguage::get_singleton()->get_managed_callable_middleman()->get_instance_id(); } @@ -99,7 +100,7 @@ void ManagedCallable::call(const Variant **p_arguments, int p_argcount, Variant MonoObject *delegate = delegate_handle.get_target(); - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoObject *ret = delegate_invoke->invoke(delegate, p_arguments, &exc); if (exc) { @@ -119,7 +120,7 @@ void ManagedCallable::set_delegate(MonoDelegate *p_delegate) { ManagedCallable::ManagedCallable(MonoDelegate *p_delegate) { #ifdef DEBUG_ENABLED - CRASH_COND(p_delegate == NULL); + CRASH_COND(p_delegate == nullptr); #endif set_delegate(p_delegate); diff --git a/modules/mono/mono_gc_handle.cpp b/modules/mono/mono_gc_handle.cpp index 4b6d7269e9..16a6875406 100644 --- a/modules/mono/mono_gc_handle.cpp +++ b/modules/mono/mono_gc_handle.cpp @@ -34,7 +34,7 @@ void MonoGCHandleData::release() { #ifdef DEBUG_ENABLED - CRASH_COND(handle && GDMono::get_singleton() == NULL); + CRASH_COND(handle && GDMono::get_singleton() == nullptr); #endif if (handle && GDMono::get_singleton()->is_runtime_initialized()) { @@ -56,11 +56,9 @@ MonoGCHandleData MonoGCHandleData::new_weak_handle(MonoObject *p_object) { } Ref<MonoGCHandleRef> MonoGCHandleRef::create_strong(MonoObject *p_object) { - return memnew(MonoGCHandleRef(MonoGCHandleData::new_strong_handle(p_object))); } Ref<MonoGCHandleRef> MonoGCHandleRef::create_weak(MonoObject *p_object) { - return memnew(MonoGCHandleRef(MonoGCHandleData::new_weak_handle(p_object))); } diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h index 705b2265ba..13cfad4654 100644 --- a/modules/mono/mono_gc_handle.h +++ b/modules/mono/mono_gc_handle.h @@ -47,13 +47,13 @@ enum class GCHandleType : char { // Manual release of the GC handle must be done when using this struct struct MonoGCHandleData { - uint32_t handle; - gdmono::GCHandleType type; + uint32_t handle = 0; + gdmono::GCHandleType type = gdmono::GCHandleType::NIL; _FORCE_INLINE_ bool is_released() const { return !handle; } _FORCE_INLINE_ bool is_weak() const { return type == gdmono::GCHandleType::WEAK_HANDLE; } - _FORCE_INLINE_ MonoObject *get_target() const { return handle ? mono_gchandle_get_target(handle) : NULL; } + _FORCE_INLINE_ MonoObject *get_target() const { return handle ? mono_gchandle_get_target(handle) : nullptr; } void release(); @@ -68,10 +68,7 @@ struct MonoGCHandleData { MonoGCHandleData(const MonoGCHandleData &) = default; - MonoGCHandleData() : - handle(0), - type(gdmono::GCHandleType::NIL) { - } + MonoGCHandleData() {} MonoGCHandleData(uint32_t p_handle, gdmono::GCHandleType p_type) : handle(p_handle), @@ -84,7 +81,6 @@ struct MonoGCHandleData { }; class MonoGCHandleRef : public Reference { - GDCLASS(MonoGCHandleRef, Reference); MonoGCHandleData data; diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index eb4c263745..5f518d0613 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -58,14 +58,25 @@ #ifdef ANDROID_ENABLED #include "android_mono_config.h" -#include "gd_mono_android.h" +#include "support/android_support.h" +#elif defined(IPHONE_ENABLED) +#include "support/ios_support.h" +#endif + +#if defined(TOOL_ENABLED) && defined(GD_MONO_SINGLE_APPDOMAIN) +// This will no longer be the case if we replace appdomains with AssemblyLoadContext +#error "Editor build requires support for multiple appdomains" +#endif + +#if defined(GD_MONO_HOT_RELOAD) && defined(GD_MONO_SINGLE_APPDOMAIN) +#error "Hot reloading requires multiple appdomains" #endif // TODO: // This has turn into a gigantic mess. There's too much going on here. Too much #ifdef as well. // It's just painful to read... It needs to be re-structured. Please, clean this up, future me. -GDMono *GDMono::singleton = NULL; +GDMono *GDMono::singleton = nullptr; namespace { @@ -118,14 +129,13 @@ void gd_mono_profiler_init() { } } -#if defined(DEBUG_ENABLED) - void gd_mono_debug_init() { - - mono_debug_init(MONO_DEBUG_FORMAT_MONO); - CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8(); + if (da_args.length()) { + OS::get_singleton()->set_environment("GODOT_MONO_DEBUGGER_AGENT", String()); + } + #ifdef TOOLS_ENABLED int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685); bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false); @@ -148,6 +158,10 @@ void gd_mono_debug_init() { return; // Exported games don't use the project settings to setup the debugger agent #endif + // Debugging enabled + + mono_debug_init(MONO_DEBUG_FORMAT_MONO); + // --debugger-agent=help const char *options[] = { "--soft-breakpoints", @@ -156,7 +170,6 @@ void gd_mono_debug_init() { mono_jit_parse_options(2, (char **)options); } -#endif // defined(DEBUG_ENABLED) #endif // !defined(JAVASCRIPT_ENABLED) #if defined(JAVASCRIPT_ENABLED) @@ -164,6 +177,7 @@ MonoDomain *gd_initialize_mono_runtime() { const char *vfs_prefix = "managed"; int enable_debugging = 0; + // TODO: Provide a way to enable debugging on WASM release builds. #ifdef DEBUG_ENABLED enable_debugging = 1; #endif @@ -174,11 +188,16 @@ MonoDomain *gd_initialize_mono_runtime() { } #else MonoDomain *gd_initialize_mono_runtime() { -#ifdef DEBUG_ENABLED gd_mono_debug_init(); + +#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED) + // I don't know whether this actually matters or not + const char *runtime_version = "mobile"; +#else + const char *runtime_version = "v4.0.30319"; #endif - return mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319"); + return mono_jit_init_version("GodotEngine.RootDomain", runtime_version); } #endif @@ -231,7 +250,6 @@ void GDMono::add_mono_shared_libs_dir_to_path() { } void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_dir) { - String bundled_assembly_rootdir = GodotSharpDirs::get_data_mono_lib_dir(); String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir(); @@ -294,7 +312,6 @@ void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_di } void GDMono::initialize() { - ERR_FAIL_NULL(Engine::get_singleton()); print_verbose("Mono: Initializing module..."); @@ -314,14 +331,22 @@ void GDMono::initialize() { determine_mono_dirs(assembly_rootdir, config_dir); // Leak if we call mono_set_dirs more than once - mono_set_dirs(assembly_rootdir.length() ? assembly_rootdir.utf8().get_data() : NULL, - config_dir.length() ? config_dir.utf8().get_data() : NULL); + mono_set_dirs(assembly_rootdir.length() ? assembly_rootdir.utf8().get_data() : nullptr, + config_dir.length() ? config_dir.utf8().get_data() : nullptr); add_mono_shared_libs_dir_to_path(); #endif +#ifdef ANDROID_ENABLED + mono_config_parse_memory(get_godot_android_mono_config().utf8().get_data()); +#else + mono_config_parse(nullptr); +#endif + #if defined(ANDROID_ENABLED) - GDMonoAndroid::initialize(); + gdmono::android::support::initialize(); +#elif defined(IPHONE_ENABLED) + gdmono::ios::support::initialize(); #endif GDMonoAssembly::initialize(); @@ -330,13 +355,7 @@ void GDMono::initialize() { gd_mono_profiler_init(); #endif -#ifdef ANDROID_ENABLED - mono_config_parse_memory(get_godot_android_mono_config().utf8().get_data()); -#else - mono_config_parse(NULL); -#endif - - mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL); + mono_install_unhandled_exception_hook(&unhandled_exception_hook, nullptr); #ifndef TOOLS_ENABLED // Exported games that don't use C# must still work. They likely don't ship with mscorlib. @@ -355,7 +374,7 @@ void GDMono::initialize() { #endif // NOTE: Internal calls must be registered after the Mono runtime initialization. - // Otherwise registration fails with the error: 'assertion 'hash != NULL' failed'. + // Otherwise registration fails with the error: 'assertion 'hash != nullptr' failed'. root_domain = gd_initialize_mono_runtime(); ERR_FAIL_NULL_MSG(root_domain, "Mono: Failed to initialize runtime."); @@ -371,15 +390,19 @@ void GDMono::initialize() { print_verbose("Mono: Runtime initialized"); #if defined(ANDROID_ENABLED) - GDMonoAndroid::register_internal_calls(); + gdmono::android::support::register_internal_calls(); #endif // mscorlib assembly MUST be present at initialization bool corlib_loaded = _load_corlib_assembly(); ERR_FAIL_COND_MSG(!corlib_loaded, "Mono: Failed to load mscorlib assembly."); +#ifndef GD_MONO_SINGLE_APPDOMAIN Error domain_load_err = _load_scripts_domain(); ERR_FAIL_COND_MSG(domain_load_err != OK, "Mono: Failed to load scripts domain."); +#else + scripts_domain = root_domain; +#endif _register_internal_calls(); @@ -387,7 +410,6 @@ void GDMono::initialize() { } void GDMono::initialize_load_assemblies() { - #ifndef MONO_GLUE_ENABLED CRASH_NOW_MSG("Mono: This binary was built with 'mono_glue=no'; cannot load assemblies."); #endif @@ -402,6 +424,9 @@ void GDMono::initialize_load_assemblies() { CRASH_COND_MSG(!tool_assemblies_loaded, "Mono: Failed to load '" TOOLS_ASM_NAME "' assemblies."); #endif + if (Main::is_project_manager()) + return; + // Load the project's main assembly. This doesn't necessarily need to succeed. // The game may not be using .NET at all, or if the project does use .NET and // we're running in the editor, it may just happen to be it wasn't built yet. @@ -445,6 +470,7 @@ uint64_t get_editor_api_hash() { uint32_t get_bindings_version() { GD_UNREACHABLE(); } + uint32_t get_cs_glue_version() { GD_UNREACHABLE(); } @@ -487,20 +513,23 @@ void GDMono::_init_exception_policy() { } void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) { - assemblies[p_domain_id][p_assembly->get_name()] = p_assembly; } -GDMonoAssembly **GDMono::get_loaded_assembly(const String &p_name) { +GDMonoAssembly *GDMono::get_loaded_assembly(const String &p_name) { + if (p_name == "mscorlib" && corlib_assembly) + return corlib_assembly; MonoDomain *domain = mono_domain_get(); uint32_t domain_id = domain ? mono_domain_get_id(domain) : 0; - return assemblies[domain_id].getptr(p_name); + GDMonoAssembly **result = assemblies[domain_id].getptr(p_name); + return result ? *result : nullptr; } bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) { - +#ifdef DEBUG_ENABLED CRASH_COND(!r_assembly); +#endif MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); bool result = load_assembly(p_name, aname, r_assembly, p_refonly); @@ -511,27 +540,26 @@ bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bo } bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { +#ifdef DEBUG_ENABLED + CRASH_COND(!r_assembly); +#endif + return load_assembly(p_name, p_aname, r_assembly, p_refonly, GDMonoAssembly::get_default_search_dirs()); +} + +bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly, const Vector<String> &p_search_dirs) { +#ifdef DEBUG_ENABLED CRASH_COND(!r_assembly); +#endif print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); - MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssembly *assembly = mono_assembly_load_full(p_aname, NULL, &status, p_refonly); + GDMonoAssembly *assembly = GDMonoAssembly::load(p_name, p_aname, p_refonly, p_search_dirs); if (!assembly) return false; - ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); - - uint32_t domain_id = mono_domain_get_id(mono_domain_get()); - - GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name); - - ERR_FAIL_COND_V(stored_assembly == NULL, false); - ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false); - - *r_assembly = *stored_assembly; + *r_assembly = assembly; print_verbose("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path()); @@ -539,7 +567,6 @@ bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMo } bool GDMono::load_assembly_from(const String &p_name, const String &p_path, GDMonoAssembly **r_assembly, bool p_refonly) { - CRASH_COND(!r_assembly); print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); @@ -549,14 +576,6 @@ bool GDMono::load_assembly_from(const String &p_name, const String &p_path, GDMo if (!assembly) return false; -#ifdef DEBUG_ENABLED - uint32_t domain_id = mono_domain_get_id(mono_domain_get()); - GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name); - - ERR_FAIL_COND_V(stored_assembly == NULL, false); - ERR_FAIL_COND_V(*stored_assembly != assembly, false); -#endif - *r_assembly = assembly; print_verbose("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path()); @@ -576,15 +595,15 @@ ApiAssemblyInfo::Version ApiAssemblyInfo::Version::get_from_loaded_assembly(GDMo if (nativecalls_klass) { GDMonoField *api_hash_field = nativecalls_klass->get_field("godot_api_hash"); if (api_hash_field) - api_assembly_version.godot_api_hash = GDMonoMarshal::unbox<uint64_t>(api_hash_field->get_value(NULL)); + api_assembly_version.godot_api_hash = GDMonoMarshal::unbox<uint64_t>(api_hash_field->get_value(nullptr)); GDMonoField *binds_ver_field = nativecalls_klass->get_field("bindings_version"); if (binds_ver_field) - api_assembly_version.bindings_version = GDMonoMarshal::unbox<uint32_t>(binds_ver_field->get_value(NULL)); + api_assembly_version.bindings_version = GDMonoMarshal::unbox<uint32_t>(binds_ver_field->get_value(nullptr)); GDMonoField *cs_glue_ver_field = nativecalls_klass->get_field("cs_glue_version"); if (cs_glue_ver_field) - api_assembly_version.cs_glue_version = GDMonoMarshal::unbox<uint32_t>(cs_glue_ver_field->get_value(NULL)); + api_assembly_version.cs_glue_version = GDMonoMarshal::unbox<uint32_t>(cs_glue_ver_field->get_value(nullptr)); } return api_assembly_version; @@ -595,7 +614,6 @@ String ApiAssemblyInfo::to_string(ApiAssemblyInfo::Type p_type) { } bool GDMono::_load_corlib_assembly() { - if (corlib_assembly) return true; @@ -609,7 +627,6 @@ bool GDMono::_load_corlib_assembly() { #ifdef TOOLS_ENABLED bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const String &p_config) { - String src_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file(p_config); String dst_dir = GodotSharpDirs::get_res_assemblies_base_dir().plus_file(p_config); @@ -680,7 +697,6 @@ static bool try_get_cached_api_hash_for(const String &p_api_assemblies_dir, bool } static void create_cached_api_hash_for(const String &p_api_assemblies_dir) { - String core_api_assembly_path = p_api_assemblies_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll"); String editor_api_assembly_path = p_api_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); String cached_api_hash_path = p_api_assemblies_dir.plus_file("api_hash_cache.cfg"); @@ -715,7 +731,7 @@ bool GDMono::_temp_domain_load_are_assemblies_out_of_sync(const String &p_config GDMono::LoadedApiAssembly temp_editor_api_assembly; if (!_try_load_api_assemblies(temp_core_api_assembly, temp_editor_api_assembly, - p_config, /* refonly: */ true, /* loaded_callback: */ NULL)) { + p_config, /* refonly: */ true, /* loaded_callback: */ nullptr)) { return temp_core_api_assembly.out_of_sync || temp_editor_api_assembly.out_of_sync; } @@ -723,7 +739,6 @@ bool GDMono::_temp_domain_load_are_assemblies_out_of_sync(const String &p_config } String GDMono::update_api_assemblies_from_prebuilt(const String &p_config, const bool *p_core_api_out_of_sync, const bool *p_editor_api_out_of_sync) { - #define FAIL_REASON(m_out_of_sync, m_prebuilt_exists) \ ( \ (m_out_of_sync ? \ @@ -780,7 +795,6 @@ String GDMono::update_api_assemblies_from_prebuilt(const String &p_config, const #endif bool GDMono::_load_core_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, const String &p_config, bool p_refonly) { - if (r_loaded_api_assembly.assembly) return true; @@ -814,7 +828,6 @@ bool GDMono::_load_core_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, c #ifdef TOOLS_ENABLED bool GDMono::_load_editor_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, const String &p_config, bool p_refonly) { - if (r_loaded_api_assembly.assembly) return true; @@ -891,11 +904,10 @@ bool GDMono::_try_load_api_assemblies_preset() { } void GDMono::_load_api_assemblies() { - bool api_assemblies_loaded = _try_load_api_assemblies_preset(); +#if defined(TOOLS_ENABLED) && !defined(GD_MONO_SINGLE_APPDOMAIN) if (!api_assemblies_loaded) { -#ifdef TOOLS_ENABLED // The API assemblies are out of sync or some other error happened. Fine, try one more time, but // this time update them from the prebuilt assemblies directory before trying to load them again. @@ -916,8 +928,8 @@ void GDMono::_load_api_assemblies() { // 4. Try loading the updated assemblies api_assemblies_loaded = _try_load_api_assemblies_preset(); -#endif } +#endif if (!api_assemblies_loaded) { // welp... too bad @@ -944,7 +956,6 @@ void GDMono::_load_api_assemblies() { #ifdef TOOLS_ENABLED bool GDMono::_load_tools_assemblies() { - if (tools_assembly && tools_project_editor_assembly) return true; @@ -956,7 +967,6 @@ bool GDMono::_load_tools_assemblies() { #endif bool GDMono::_load_project_assembly() { - if (project_assembly) return true; @@ -976,14 +986,13 @@ bool GDMono::_load_project_assembly() { } void GDMono::_install_trace_listener() { - #ifdef DEBUG_ENABLED // Install the trace listener now before the project assembly is loaded GDMonoClass *debug_utils = get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, "DebuggingUtils"); GDMonoMethod *install_func = debug_utils->get_method("InstallTraceListener"); - MonoException *exc = NULL; - install_func->invoke_raw(NULL, NULL, &exc); + MonoException *exc = nullptr; + install_func->invoke_raw(nullptr, nullptr, &exc); if (exc) { GDMonoUtils::debug_print_unhandled_exception(exc); ERR_PRINT("Failed to install 'System.Diagnostics.Trace' listener."); @@ -991,9 +1000,9 @@ void GDMono::_install_trace_listener() { #endif } +#ifndef GD_MONO_SINGLE_APPDOMAIN Error GDMono::_load_scripts_domain() { - - ERR_FAIL_COND_V(scripts_domain != NULL, ERR_BUG); + ERR_FAIL_COND_V(scripts_domain != nullptr, ERR_BUG); print_verbose("Mono: Loading scripts domain..."); @@ -1007,10 +1016,9 @@ Error GDMono::_load_scripts_domain() { } Error GDMono::_unload_scripts_domain() { - ERR_FAIL_NULL_V(scripts_domain, ERR_BUG); - print_verbose("Mono: Unloading scripts domain..."); + print_verbose("Mono: Finalizing scripts domain..."); if (mono_domain_get() != root_domain) mono_domain_set(root_domain, true); @@ -1029,21 +1037,23 @@ Error GDMono::_unload_scripts_domain() { _domain_assemblies_cleanup(mono_domain_get_id(scripts_domain)); - core_api_assembly.assembly = NULL; + core_api_assembly.assembly = nullptr; #ifdef TOOLS_ENABLED - editor_api_assembly.assembly = NULL; + editor_api_assembly.assembly = nullptr; #endif - project_assembly = NULL; + project_assembly = nullptr; #ifdef TOOLS_ENABLED - tools_assembly = NULL; - tools_project_editor_assembly = NULL; + tools_assembly = nullptr; + tools_project_editor_assembly = nullptr; #endif MonoDomain *domain = scripts_domain; - scripts_domain = NULL; + scripts_domain = nullptr; + + print_verbose("Mono: Unloading scripts domain..."); - MonoException *exc = NULL; + MonoException *exc = nullptr; mono_domain_try_unload(domain, (MonoObject **)&exc); if (exc) { @@ -1054,10 +1064,10 @@ Error GDMono::_unload_scripts_domain() { return OK; } +#endif #ifdef GD_MONO_HOT_RELOAD Error GDMono::reload_scripts_domain() { - ERR_FAIL_COND_V(!runtime_initialized, ERR_BUG); if (scripts_domain) { @@ -1092,9 +1102,9 @@ Error GDMono::reload_scripts_domain() { } #endif +#ifndef GD_MONO_SINGLE_APPDOMAIN Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { - - CRASH_COND(p_domain == NULL); + CRASH_COND(p_domain == nullptr); CRASH_COND(p_domain == GDMono::get_singleton()->get_scripts_domain()); // Should use _unload_scripts_domain() instead String domain_name = mono_domain_get_friendly_name(p_domain); @@ -1112,7 +1122,7 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { _domain_assemblies_cleanup(mono_domain_get_id(p_domain)); - MonoException *exc = NULL; + MonoException *exc = nullptr; mono_domain_try_unload(p_domain, (MonoObject **)&exc); if (exc) { @@ -1123,9 +1133,9 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { return OK; } +#endif GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { - MonoImage *image = mono_class_get_image(p_raw_class); if (image == corlib_assembly->get_image()) @@ -1134,7 +1144,7 @@ GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { uint32_t domain_id = mono_domain_get_id(mono_domain_get()); HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; - const String *k = NULL; + const String *k = nullptr; while ((k = domain_assemblies.next(k))) { GDMonoAssembly *assembly = domain_assemblies.get(*k); if (assembly->get_image() == image) { @@ -1145,30 +1155,32 @@ GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { } } - return NULL; + return nullptr; } GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName &p_name) { + GDMonoClass *klass = corlib_assembly->get_class(p_namespace, p_name); + if (klass) + return klass; uint32_t domain_id = mono_domain_get_id(mono_domain_get()); HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id]; - const String *k = NULL; + const String *k = nullptr; while ((k = domain_assemblies.next(k))) { GDMonoAssembly *assembly = domain_assemblies.get(*k); - GDMonoClass *klass = assembly->get_class(p_namespace, p_name); + klass = assembly->get_class(p_namespace, p_name); if (klass) return klass; } - return NULL; + return nullptr; } void GDMono::_domain_assemblies_cleanup(uint32_t p_domain_id) { - HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id]; - const String *k = NULL; + const String *k = nullptr; while ((k = domain_assemblies.next(k))) { memdelete(domain_assemblies.get(*k)); } @@ -1177,7 +1189,6 @@ void GDMono::_domain_assemblies_cleanup(uint32_t p_domain_id) { } void GDMono::unhandled_exception_hook(MonoObject *p_exc, void *) { - // This method will be called by the runtime when a thrown exception is not handled. // It won't be called when we manually treat a thrown exception as unhandled. // We assume the exception was already printed before calling this hook. @@ -1194,7 +1205,6 @@ void GDMono::unhandled_exception_hook(MonoObject *p_exc, void *) { } GDMono::GDMono() { - singleton = this; gdmono_log = memnew(GDMonoLog); @@ -1202,14 +1212,14 @@ GDMono::GDMono() { runtime_initialized = false; finalizing_scripts_domain = false; - root_domain = NULL; - scripts_domain = NULL; + root_domain = nullptr; + scripts_domain = nullptr; - corlib_assembly = NULL; - project_assembly = NULL; + corlib_assembly = nullptr; + project_assembly = nullptr; #ifdef TOOLS_ENABLED - tools_assembly = NULL; - tools_project_editor_assembly = NULL; + tools_assembly = nullptr; + tools_project_editor_assembly = nullptr; #endif api_core_hash = 0; @@ -1221,20 +1231,51 @@ GDMono::GDMono() { } GDMono::~GDMono() { - if (is_runtime_initialized()) { +#ifndef GD_MONO_SINGLE_APPDOMAIN if (scripts_domain) { Error err = _unload_scripts_domain(); if (err != OK) { ERR_PRINT("Mono: Failed to unload scripts domain."); } } +#else + CRASH_COND(scripts_domain != root_domain); + + print_verbose("Mono: Finalizing scripts domain..."); + + if (mono_domain_get() != root_domain) + mono_domain_set(root_domain, true); + + finalizing_scripts_domain = true; + + if (!mono_domain_finalize(root_domain, 2000)) { + ERR_PRINT("Mono: Domain finalization timeout."); + } - const uint32_t *k = NULL; + finalizing_scripts_domain = false; + + mono_gc_collect(mono_gc_max_generation()); + + GDMonoCache::clear_godot_api_cache(); + + _domain_assemblies_cleanup(mono_domain_get_id(root_domain)); + + core_api_assembly.assembly = nullptr; + + project_assembly = nullptr; + + root_domain = nullptr; + scripts_domain = nullptr; + + // Leave the rest to 'mono_jit_cleanup' +#endif + + const uint32_t *k = nullptr; while ((k = assemblies.next(k))) { HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies.get(*k); - const String *kk = NULL; + const String *kk = nullptr; while ((kk = domain_assemblies.next(kk))) { memdelete(domain_assemblies.get(*kk)); } @@ -1245,69 +1286,60 @@ GDMono::~GDMono() { mono_jit_cleanup(root_domain); -#if defined(ANDROID_ENABLED) - GDMonoAndroid::cleanup(); -#endif - print_verbose("Mono: Finalized"); runtime_initialized = false; } +#if defined(ANDROID_ENABLED) + gdmono::android::support::cleanup(); +#endif + if (gdmono_log) memdelete(gdmono_log); - singleton = NULL; + singleton = nullptr; } -_GodotSharp *_GodotSharp::singleton = NULL; +_GodotSharp *_GodotSharp::singleton = nullptr; void _GodotSharp::attach_thread() { - GDMonoUtils::attach_current_thread(); } void _GodotSharp::detach_thread() { - GDMonoUtils::detach_current_thread(); } int32_t _GodotSharp::get_domain_id() { - MonoDomain *domain = mono_domain_get(); CRASH_COND(!domain); // User must check if runtime is initialized before calling this method return mono_domain_get_id(domain); } int32_t _GodotSharp::get_scripts_domain_id() { - MonoDomain *domain = GDMono::get_singleton()->get_scripts_domain(); CRASH_COND(!domain); // User must check if scripts domain is loaded before calling this method return mono_domain_get_id(domain); } bool _GodotSharp::is_scripts_domain_loaded() { - - return GDMono::get_singleton()->is_runtime_initialized() && GDMono::get_singleton()->get_scripts_domain() != NULL; + return GDMono::get_singleton()->is_runtime_initialized() && GDMono::get_singleton()->get_scripts_domain() != nullptr; } bool _GodotSharp::_is_domain_finalizing_for_unload(int32_t p_domain_id) { - return is_domain_finalizing_for_unload(p_domain_id); } bool _GodotSharp::is_domain_finalizing_for_unload() { - return is_domain_finalizing_for_unload(mono_domain_get()); } bool _GodotSharp::is_domain_finalizing_for_unload(int32_t p_domain_id) { - return is_domain_finalizing_for_unload(mono_domain_get_by_id(p_domain_id)); } bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) { - if (!p_domain) return true; if (p_domain == GDMono::get_singleton()->get_scripts_domain() && GDMono::get_singleton()->is_finalizing_scripts_domain()) @@ -1316,23 +1348,23 @@ bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) { } bool _GodotSharp::is_runtime_shutting_down() { - return mono_runtime_is_shutting_down(); } bool _GodotSharp::is_runtime_initialized() { - return GDMono::get_singleton()->is_runtime_initialized(); } void _GodotSharp::_reload_assemblies(bool p_soft_reload) { #ifdef GD_MONO_HOT_RELOAD - CSharpLanguage::get_singleton()->reload_assemblies(p_soft_reload); + // This method may be called more than once with `call_deferred`, so we need to check + // again if reloading is needed to avoid reloading multiple times unnecessarily. + if (CSharpLanguage::get_singleton()->is_assembly_reloading_needed()) + CSharpLanguage::get_singleton()->reload_assemblies(p_soft_reload); #endif } void _GodotSharp::_bind_methods() { - ClassDB::bind_method(D_METHOD("attach_thread"), &_GodotSharp::attach_thread); ClassDB::bind_method(D_METHOD("detach_thread"), &_GodotSharp::detach_thread); @@ -1347,11 +1379,9 @@ void _GodotSharp::_bind_methods() { } _GodotSharp::_GodotSharp() { - singleton = this; } _GodotSharp::~_GodotSharp() { - - singleton = NULL; + singleton = nullptr; } diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index 9528c64f8d..833855b371 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -48,9 +48,9 @@ enum Type { }; struct Version { - uint64_t godot_api_hash; - uint32_t bindings_version; - uint32_t cs_glue_version; + uint64_t godot_api_hash = 0; + uint32_t bindings_version = 0; + uint32_t cs_glue_version = 0; bool operator==(const Version &p_other) const { return godot_api_hash == p_other.godot_api_hash && @@ -58,11 +58,7 @@ struct Version { cs_glue_version == p_other.cs_glue_version; } - Version() : - godot_api_hash(0), - bindings_version(0), - cs_glue_version(0) { - } + Version() {} Version(uint64_t p_godot_api_hash, uint32_t p_bindings_version, @@ -79,7 +75,6 @@ String to_string(Type p_type); } // namespace ApiAssemblyInfo class GDMono { - public: enum UnhandledExceptionPolicy { POLICY_TERMINATE_APP, @@ -87,13 +82,10 @@ public: }; struct LoadedApiAssembly { - GDMonoAssembly *assembly; - bool out_of_sync; + GDMonoAssembly *assembly = nullptr; + bool out_of_sync = false; - LoadedApiAssembly() : - assembly(NULL), - out_of_sync(false) { - } + LoadedApiAssembly() {} }; private: @@ -144,8 +136,10 @@ private: void _register_internal_calls(); +#ifndef GD_MONO_SINGLE_APPDOMAIN Error _load_scripts_domain(); Error _unload_scripts_domain(); +#endif void _domain_assemblies_cleanup(uint32_t p_domain_id); @@ -198,7 +192,7 @@ public: #ifdef TOOLS_ENABLED bool copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const String &p_config); - String update_api_assemblies_from_prebuilt(const String &p_config, const bool *p_core_api_out_of_sync = NULL, const bool *p_editor_api_out_of_sync = NULL); + String update_api_assemblies_from_prebuilt(const String &p_config, const bool *p_core_api_out_of_sync = nullptr, const bool *p_editor_api_out_of_sync = nullptr); #endif static GDMono *get_singleton() { return singleton; } @@ -209,7 +203,7 @@ public: // Do not use these, unless you know what you're doing void add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly); - GDMonoAssembly **get_loaded_assembly(const String &p_name); + GDMonoAssembly *get_loaded_assembly(const String &p_name); _FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized && !mono_runtime_is_shutting_down() /* stays true after shutdown finished */; } @@ -239,6 +233,7 @@ public: bool load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly = false); bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly = false); + bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly, const Vector<String> &p_search_dirs); bool load_assembly_from(const String &p_name, const String &p_path, GDMonoAssembly **r_assembly, bool p_refonly = false); Error finalize_and_unload_domain(MonoDomain *p_domain); @@ -253,7 +248,6 @@ public: namespace gdmono { class ScopeDomain { - MonoDomain *prev_domain; public: @@ -263,7 +257,7 @@ public: this->prev_domain = prev_domain; mono_domain_set(p_domain, false); } else { - this->prev_domain = NULL; + this->prev_domain = nullptr; } } diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 6da1db249c..073c9a5214 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -33,6 +33,7 @@ #include <mono/metadata/mono-debug.h> #include <mono/metadata/tokentype.h> +#include "core/io/file_access_pack.h" #include "core/list.h" #include "core/os/file_access.h" #include "core/os/os.h" @@ -42,13 +43,9 @@ #include "gd_mono_cache.h" #include "gd_mono_class.h" -bool GDMonoAssembly::no_search = false; -bool GDMonoAssembly::in_preload = false; - Vector<String> GDMonoAssembly::search_dirs; void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config, const String &p_custom_bcl_dir) { - String framework_dir; if (!p_custom_bcl_dir.empty()) { @@ -94,19 +91,29 @@ void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const Strin #endif } -void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, void *user_data) { +// This is how these assembly loading hooks work: +// +// - The 'search' hook checks if the assembly has already been loaded, to avoid loading again. +// - The 'preload' hook does the actual loading and is only called if the +// 'search' hook didn't find the assembly in the list of loaded assemblies. +// - The 'load' hook is called after the assembly has been loaded. Its job is to add the +// assembly to the list of loaded assemblies so that the 'search' hook can look it up. + +void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, [[maybe_unused]] void *user_data) { + String name = String::utf8(mono_assembly_name_get_name(mono_assembly_get_name(assembly))); + + MonoImage *image = mono_assembly_get_image(assembly); + + GDMonoAssembly *gdassembly = memnew(GDMonoAssembly(name, image, assembly)); - if (no_search) - return; +#ifdef GD_MONO_HOT_RELOAD + const char *path = mono_image_get_filename(image); + if (FileAccess::exists(path)) + gdassembly->modified_time = FileAccess::get_modified_time(path); +#endif - // If our search and preload hooks fail to load the assembly themselves, the mono runtime still might. - // Just do Assembly.LoadFrom("/Full/Path/On/Disk.dll"); - // In this case, we wouldn't have the assembly known in GDMono, which causes crashes - // if any class inside the assembly is looked up by Godot. - // And causing a lookup like that is as easy as throwing an exception defined in it... - // No, we can't make the assembly load hooks smart enough because they get passed a MonoAssemblyName* only, - // not the disk path passed to say Assembly.LoadFrom(). - _wrap_mono_assembly(assembly); + MonoDomain *domain = mono_domain_get(); + GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, gdassembly); } MonoAssembly *GDMonoAssembly::assembly_search_hook(MonoAssemblyName *aname, void *user_data) { @@ -125,78 +132,24 @@ MonoAssembly *GDMonoAssembly::assembly_refonly_preload_hook(MonoAssemblyName *an return GDMonoAssembly::_preload_hook(aname, assemblies_path, user_data, true); } -MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly) { - - (void)user_data; // UNUSED - +MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, [[maybe_unused]] void *user_data, bool refonly) { String name = String::utf8(mono_assembly_name_get_name(aname)); bool has_extension = name.ends_with(".dll") || name.ends_with(".exe"); - if (no_search) - return NULL; - - GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); + GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); if (loaded_asm) - return (*loaded_asm)->get_assembly(); - - no_search = true; // Avoid the recursion madness - - GDMonoAssembly *res = _load_assembly_search(name, search_dirs, refonly); + return loaded_asm->get_assembly(); - no_search = false; - - return res ? res->get_assembly() : NULL; + return nullptr; } -static thread_local MonoImage *image_corlib_loading = NULL; - -MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, void *user_data, bool refonly) { - - (void)user_data; // UNUSED - - { - // If we find the assembly here, we load it with 'mono_assembly_load_from_full', - // which in turn invokes load hooks before returning the MonoAssembly to us. - // One of the load hooks is 'load_aot_module'. This hook can end up calling preload hooks - // again for the same assembly in certain in certain circumstances (the 'do_load_image' part). - // If this is the case and we return NULL due to the no_search condition below, - // it will result in an internal crash later on. Therefore we need to return the assembly we didn't - // get yet from 'mono_assembly_load_from_full'. Luckily we have the image, which already got it. - // This must be done here. If done in search hooks, it would cause 'mono_assembly_load_from_full' - // to think another MonoAssembly for this assembly was already loaded, making it delete its own, - // when in fact both pointers were the same... This hooks thing is confusing. - if (image_corlib_loading) { - return mono_image_get_assembly(image_corlib_loading); - } - } - - if (no_search) - return NULL; - - no_search = true; - in_preload = true; - +MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, [[maybe_unused]] void *user_data, bool refonly) { String name = String::utf8(mono_assembly_name_get_name(aname)); - bool has_extension = name.ends_with(".dll"); - - GDMonoAssembly *res = NULL; - if (has_extension ? name == "mscorlib.dll" : name == "mscorlib") { - GDMonoAssembly **stored_assembly = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); - if (stored_assembly) - return (*stored_assembly)->get_assembly(); - - res = _load_assembly_search("mscorlib.dll", search_dirs, refonly); - } - - no_search = false; - in_preload = false; - - return res ? res->get_assembly() : NULL; + return _load_assembly_search(name, aname, refonly, search_dirs); } -GDMonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly) { - - GDMonoAssembly *res = NULL; +MonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs) { + MonoAssembly *res = nullptr; String path; bool has_extension = p_name.ends_with(".dll") || p_name.ends_with(".exe"); @@ -207,32 +160,31 @@ GDMonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, cons if (has_extension) { path = search_dir.plus_file(p_name); if (FileAccess::exists(path)) { - res = _load_assembly_from(p_name.get_basename(), path, p_refonly); - if (res != NULL) + res = _real_load_assembly_from(path, p_refonly, p_aname); + if (res != nullptr) return res; } } else { path = search_dir.plus_file(p_name + ".dll"); if (FileAccess::exists(path)) { - res = _load_assembly_from(p_name, path, p_refonly); - if (res != NULL) + res = _real_load_assembly_from(path, p_refonly, p_aname); + if (res != nullptr) return res; } path = search_dir.plus_file(p_name + ".exe"); if (FileAccess::exists(path)) { - res = _load_assembly_from(p_name, path, p_refonly); - if (res != NULL) + res = _real_load_assembly_from(path, p_refonly, p_aname); + if (res != nullptr) return res; } } } - return NULL; + return nullptr; } String GDMonoAssembly::find_assembly(const String &p_name) { - String path; bool has_extension = p_name.ends_with(".dll") || p_name.ends_with(".exe"); @@ -258,91 +210,74 @@ String GDMonoAssembly::find_assembly(const String &p_name) { return String(); } -GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly) { - - GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path)); - - Error err = assembly->load(p_refonly); - - if (err != OK) { - memdelete(assembly); - ERR_FAIL_V(NULL); - } - - MonoDomain *domain = mono_domain_get(); - GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, assembly); - - return assembly; -} - -void GDMonoAssembly::_wrap_mono_assembly(MonoAssembly *assembly) { - String name = String::utf8(mono_assembly_name_get_name(mono_assembly_get_name(assembly))); - - MonoImage *image = mono_assembly_get_image(assembly); - - GDMonoAssembly *gdassembly = memnew(GDMonoAssembly(name, mono_image_get_filename(image))); - Error err = gdassembly->wrapper_for_image(image); - - if (err != OK) { - memdelete(gdassembly); - ERR_FAIL(); - } - - MonoDomain *domain = mono_domain_get(); - GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, gdassembly); -} - void GDMonoAssembly::initialize() { - fill_search_dirs(search_dirs); - mono_install_assembly_search_hook(&assembly_search_hook, NULL); - mono_install_assembly_refonly_search_hook(&assembly_refonly_search_hook, NULL); - mono_install_assembly_preload_hook(&assembly_preload_hook, NULL); - mono_install_assembly_refonly_preload_hook(&assembly_refonly_preload_hook, NULL); - mono_install_assembly_load_hook(&assembly_load_hook, NULL); + mono_install_assembly_search_hook(&assembly_search_hook, nullptr); + mono_install_assembly_refonly_search_hook(&assembly_refonly_search_hook, nullptr); + mono_install_assembly_preload_hook(&assembly_preload_hook, nullptr); + mono_install_assembly_refonly_preload_hook(&assembly_refonly_preload_hook, nullptr); + mono_install_assembly_load_hook(&assembly_load_hook, nullptr); } -Error GDMonoAssembly::load(bool p_refonly) { - - ERR_FAIL_COND_V(loaded, ERR_FILE_ALREADY_IN_USE); - - refonly = p_refonly; - - uint64_t last_modified_time = FileAccess::get_modified_time(path); - - Vector<uint8_t> data = FileAccess::get_file_as_array(path); - ERR_FAIL_COND_V(data.empty(), ERR_FILE_CANT_READ); +MonoAssembly *GDMonoAssembly::_real_load_assembly_from(const String &p_path, bool p_refonly, MonoAssemblyName *p_aname) { + Vector<uint8_t> data = FileAccess::get_file_as_array(p_path); + ERR_FAIL_COND_V_MSG(data.empty(), nullptr, "Could read the assembly in the specified location"); String image_filename; #ifdef ANDROID_ENABLED - if (path.begins_with("res://")) { - image_filename = path.substr(6, path.length()); + if (p_path.begins_with("res://")) { + image_filename = p_path.substr(6, p_path.length()); } else { - image_filename = ProjectSettings::get_singleton()->globalize_path(path); + image_filename = ProjectSettings::get_singleton()->globalize_path(p_path); } #else // FIXME: globalize_path does not work on exported games - image_filename = ProjectSettings::get_singleton()->globalize_path(path); + image_filename = ProjectSettings::get_singleton()->globalize_path(p_path); #endif MonoImageOpenStatus status = MONO_IMAGE_OK; - image = mono_image_open_from_data_with_name( + MonoImage *image = mono_image_open_from_data_with_name( (char *)&data[0], data.size(), - true, &status, refonly, - image_filename.utf8().get_data()); + true, &status, p_refonly, + image_filename.utf8()); + + ERR_FAIL_COND_V_MSG(status != MONO_IMAGE_OK || !image, nullptr, "Failed to open assembly image from memory: '" + p_path + "'."); + + if (p_aname != nullptr) { + // Check assembly version + const MonoTableInfo *table = mono_image_get_table_info(image, MONO_TABLE_ASSEMBLY); + + ERR_FAIL_NULL_V(table, nullptr); + + if (mono_table_info_get_rows(table)) { + uint32_t cols[MONO_ASSEMBLY_SIZE]; + mono_metadata_decode_row(table, 0, cols, MONO_ASSEMBLY_SIZE); - ERR_FAIL_COND_V(status != MONO_IMAGE_OK, ERR_FILE_CANT_OPEN); - ERR_FAIL_NULL_V(image, ERR_FILE_CANT_OPEN); + // Not sure about .NET's policy. We will only ensure major and minor are equal, and ignore build and revision. + uint16_t major = cols[MONO_ASSEMBLY_MAJOR_VERSION]; + uint16_t minor = cols[MONO_ASSEMBLY_MINOR_VERSION]; + + uint16_t required_minor; + uint16_t required_major = mono_assembly_name_get_version(p_aname, &required_minor, nullptr, nullptr); + + if (required_major != 0) { + if (major != required_major && minor != required_minor) { + mono_image_close(image); + return nullptr; + } + } + } + } #ifdef DEBUG_ENABLED Vector<uint8_t> pdb_data; - String pdb_path(path + ".pdb"); + String pdb_path(p_path + ".pdb"); if (!FileAccess::exists(pdb_path)) { - pdb_path = path.get_basename() + ".pdb"; // without .dll + pdb_path = p_path.get_basename() + ".pdb"; // without .dll if (!FileAccess::exists(pdb_path)) goto no_pdb; @@ -357,44 +292,33 @@ no_pdb: #endif - bool is_corlib_preload = in_preload && name == "mscorlib"; + bool need_manual_load_hook = mono_image_get_assembly(image) != nullptr; // Re-using an existing image with an assembly loaded - if (is_corlib_preload) - image_corlib_loading = image; + status = MONO_IMAGE_OK; - assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, refonly); + MonoAssembly *assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, p_refonly); - if (is_corlib_preload) - image_corlib_loading = NULL; + ERR_FAIL_COND_V_MSG(status != MONO_IMAGE_OK || !assembly, nullptr, "Failed to load assembly for image"); - ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN); + if (need_manual_load_hook) { + // For some reason if an assembly survived domain reloading (maybe because it's referenced somewhere else), + // the mono internal search hook don't detect it, yet mono_image_open_from_data_with_name re-uses the image + // and assembly, and mono_assembly_load_from_full doesn't call the load hook. We need to call it manually. + String name = String::utf8(mono_assembly_name_get_name(mono_assembly_get_name(assembly))); + bool has_extension = name.ends_with(".dll") || name.ends_with(".exe"); + GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); + if (!loaded_asm) + assembly_load_hook(assembly, nullptr); + } // Decrement refcount which was previously incremented by mono_image_open_from_data_with_name mono_image_close(image); - loaded = true; - modified_time = last_modified_time; - - return OK; -} - -Error GDMonoAssembly::wrapper_for_image(MonoImage *p_image) { - - ERR_FAIL_COND_V(loaded, ERR_FILE_ALREADY_IN_USE); - - assembly = mono_image_get_assembly(p_image); - ERR_FAIL_NULL_V(assembly, FAILED); - - image = p_image; - - loaded = true; - - return OK; + return assembly; } void GDMonoAssembly::unload() { - - ERR_FAIL_COND(!loaded); + ERR_FAIL_NULL(image); // Should not be called if already unloaded for (Map<MonoClass *, GDMonoClass *>::Element *E = cached_raw.front(); E; E = E->next()) { memdelete(E->value()); @@ -403,14 +327,16 @@ void GDMonoAssembly::unload() { cached_classes.clear(); cached_raw.clear(); - assembly = NULL; - image = NULL; - loaded = false; + assembly = nullptr; + image = nullptr; } -GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const StringName &p_name) { +String GDMonoAssembly::get_path() const { + return String::utf8(mono_image_get_filename(image)); +} - ERR_FAIL_COND_V(!loaded, NULL); +GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const StringName &p_name) { + ERR_FAIL_NULL_V(image, nullptr); ClassKey key(p_namespace, p_name); @@ -422,7 +348,7 @@ GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const Stri MonoClass *mono_class = mono_class_from_name(image, String(p_namespace).utf8(), String(p_name).utf8()); if (!mono_class) - return NULL; + return nullptr; GDMonoClass *wrapped_class = memnew(GDMonoClass(p_namespace, p_name, mono_class, this)); @@ -433,8 +359,7 @@ GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const Stri } GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) { - - ERR_FAIL_COND_V(!loaded, NULL); + ERR_FAIL_NULL_V(image, nullptr); Map<MonoClass *, GDMonoClass *>::Element *match = cached_raw.find(p_mono_class); @@ -453,8 +378,7 @@ GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) { } GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) { - - GDMonoClass *match = NULL; + GDMonoClass *match = nullptr; if (gdobject_class_cache_updated) { Map<StringName, GDMonoClass *>::Element *result = gdobject_class_cache.find(p_class); @@ -486,7 +410,7 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) GDMonoClass *current_nested = nested_classes.front()->get(); nested_classes.pop_back(); - void *iter = NULL; + void *iter = nullptr; while (true) { MonoClass *raw_nested = mono_class_get_nested_types(current_nested->get_mono_ptr(), &iter); @@ -512,34 +436,47 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) return match; } -GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_path, bool p_refonly) { +GDMonoAssembly *GDMonoAssembly::load(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs) { + if (GDMono::get_singleton()->get_corlib_assembly() && (p_name == "mscorlib" || p_name == "mscorlib.dll")) + return GDMono::get_singleton()->get_corlib_assembly(); - GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); - if (loaded_asm) - return *loaded_asm; -#ifdef DEBUG_ENABLED - CRASH_COND(!FileAccess::exists(p_path)); -#endif - no_search = true; - GDMonoAssembly *res = _load_assembly_from(p_name, p_path, p_refonly); - no_search = false; - return res; + // We need to manually call the search hook in this case, as it won't be called in the next step + MonoAssembly *assembly = mono_assembly_invoke_search_hook(p_aname); + + if (!assembly) { + assembly = _load_assembly_search(p_name, p_aname, p_refonly, p_search_dirs); + ERR_FAIL_NULL_V(assembly, nullptr); + } + + GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); + ERR_FAIL_NULL_V_MSG(loaded_asm, nullptr, "Loaded assembly missing from table. Did we not receive the load hook?"); + ERR_FAIL_COND_V(loaded_asm->get_assembly() != assembly, nullptr); + + return loaded_asm; } -GDMonoAssembly::GDMonoAssembly(const String &p_name, const String &p_path) { +GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_path, bool p_refonly) { + if (p_name == "mscorlib" || p_name == "mscorlib.dll") + return GDMono::get_singleton()->get_corlib_assembly(); + + // We need to manually call the search hook in this case, as it won't be called in the next step + MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); + MonoAssembly *assembly = mono_assembly_invoke_search_hook(aname); + mono_assembly_name_free(aname); + mono_free(aname); + + if (!assembly) { + assembly = _real_load_assembly_from(p_path, p_refonly); + ERR_FAIL_NULL_V(assembly, nullptr); + } - loaded = false; - gdobject_class_cache_updated = false; - name = p_name; - path = p_path; - refonly = false; - modified_time = 0; - assembly = NULL; - image = NULL; + GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); + ERR_FAIL_NULL_V_MSG(loaded_asm, nullptr, "Loaded assembly missing from table. Did we not receive the load hook?"); + + return loaded_asm; } GDMonoAssembly::~GDMonoAssembly() { - - if (loaded) + if (image) unload(); } diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 4740e10339..63899dc9be 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -40,7 +40,6 @@ #include "gd_mono_utils.h" class GDMonoAssembly { - struct ClassKey { struct Hasher { static _FORCE_INLINE_ uint32_t hash(const ClassKey &p_key) { @@ -68,24 +67,20 @@ class GDMonoAssembly { StringName class_name; }; - MonoAssembly *assembly; + String name; MonoImage *image; + MonoAssembly *assembly; - bool refonly; - bool loaded; +#ifdef GD_MONO_HOT_RELOAD + uint64_t modified_time = 0; +#endif - String name; - String path; - uint64_t modified_time; + bool gdobject_class_cache_updated = false; + Map<StringName, GDMonoClass *> gdobject_class_cache; HashMap<ClassKey, GDMonoClass *, ClassKey::Hasher> cached_classes; Map<MonoClass *, GDMonoClass *> cached_raw; - bool gdobject_class_cache_updated; - Map<StringName, GDMonoClass *> gdobject_class_cache; - - static bool no_search; - static bool in_preload; static Vector<String> search_dirs; static void assembly_load_hook(MonoAssembly *assembly, void *user_data); @@ -97,25 +92,24 @@ class GDMonoAssembly { static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly); static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly); - static GDMonoAssembly *_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly); - static GDMonoAssembly *_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly); - static void _wrap_mono_assembly(MonoAssembly *assembly); + static MonoAssembly *_real_load_assembly_from(const String &p_path, bool p_refonly, MonoAssemblyName *p_aname = nullptr); + static MonoAssembly *_load_assembly_search(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs); friend class GDMono; static void initialize(); public: - Error load(bool p_refonly); - Error wrapper_for_image(MonoImage *p_image); void unload(); - _FORCE_INLINE_ bool is_refonly() const { return refonly; } - _FORCE_INLINE_ bool is_loaded() const { return loaded; } _FORCE_INLINE_ MonoImage *get_image() const { return image; } _FORCE_INLINE_ MonoAssembly *get_assembly() const { return assembly; } _FORCE_INLINE_ String get_name() const { return name; } - _FORCE_INLINE_ String get_path() const { return path; } + +#ifdef GD_MONO_HOT_RELOAD _FORCE_INLINE_ uint64_t get_modified_time() const { return modified_time; } +#endif + + String get_path() const; GDMonoClass *get_class(const StringName &p_namespace, const StringName &p_name); GDMonoClass *get_class(MonoClass *p_mono_class); @@ -125,10 +119,16 @@ public: static String find_assembly(const String &p_name); static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String(), const String &p_custom_bcl_dir = String()); + static const Vector<String> &get_default_search_dirs() { return search_dirs; } + static GDMonoAssembly *load(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs); static GDMonoAssembly *load_from(const String &p_name, const String &p_path, bool p_refonly); - GDMonoAssembly(const String &p_name, const String &p_path = String()); + GDMonoAssembly(const String &p_name, MonoImage *p_image, MonoAssembly *p_assembly) : + name(p_name), + image(p_image), + assembly(p_assembly) { + } ~GDMonoAssembly(); }; diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index be0b846702..c002ad2139 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -40,11 +40,11 @@ namespace GDMonoCache { CachedData cached_data; -#define CACHE_AND_CHECK(m_var, m_val) \ - { \ - CRASH_COND(m_var != NULL); \ - m_var = m_val; \ - ERR_FAIL_COND_MSG(m_var == NULL, "Mono Cache: Member " #m_var " is null."); \ +#define CACHE_AND_CHECK(m_var, m_val) \ + { \ + CRASH_COND(m_var != nullptr); \ + m_var = m_val; \ + ERR_FAIL_COND_MSG(m_var == nullptr, "Mono Cache: Member " #m_var " is null."); \ } #define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(cached_data.class_##m_class, m_val) @@ -54,107 +54,106 @@ CachedData cached_data; #define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(cached_data.method_##m_class##_##m_method, m_val) #define CACHE_PROPERTY_AND_CHECK(m_class, m_property, m_val) CACHE_AND_CHECK(cached_data.property_##m_class##_##m_property, m_val) -#define CACHE_METHOD_THUNK_AND_CHECK_IMPL(m_var, m_val) \ - { \ - CRASH_COND(!m_var.is_null()); \ - ERR_FAIL_COND_MSG(m_val == NULL, "Mono Cache: Method for member " #m_var " is null."); \ - m_var.set_from_method(m_val); \ - ERR_FAIL_COND_MSG(m_var.is_null(), "Mono Cache: Member " #m_var " is null."); \ +#define CACHE_METHOD_THUNK_AND_CHECK_IMPL(m_var, m_val) \ + { \ + CRASH_COND(!m_var.is_null()); \ + ERR_FAIL_COND_MSG(m_val == nullptr, "Mono Cache: Method for member " #m_var " is null."); \ + m_var.set_from_method(m_val); \ + ERR_FAIL_COND_MSG(m_var.is_null(), "Mono Cache: Member " #m_var " is null."); \ } #define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_METHOD_THUNK_AND_CHECK_IMPL(cached_data.methodthunk_##m_class##_##m_method, m_val) void CachedData::clear_corlib_cache() { - corlib_cache_updated = false; - class_MonoObject = NULL; - class_bool = NULL; - class_int8_t = NULL; - class_int16_t = NULL; - class_int32_t = NULL; - class_int64_t = NULL; - class_uint8_t = NULL; - class_uint16_t = NULL; - class_uint32_t = NULL; - class_uint64_t = NULL; - class_float = NULL; - class_double = NULL; - class_String = NULL; - class_IntPtr = NULL; - - class_System_Collections_IEnumerable = NULL; - class_System_Collections_IDictionary = NULL; + class_MonoObject = nullptr; + class_bool = nullptr; + class_int8_t = nullptr; + class_int16_t = nullptr; + class_int32_t = nullptr; + class_int64_t = nullptr; + class_uint8_t = nullptr; + class_uint16_t = nullptr; + class_uint32_t = nullptr; + class_uint64_t = nullptr; + class_float = nullptr; + class_double = nullptr; + class_String = nullptr; + class_IntPtr = nullptr; + + class_System_Collections_IEnumerable = nullptr; + class_System_Collections_ICollection = nullptr; + class_System_Collections_IDictionary = nullptr; #ifdef DEBUG_ENABLED - class_System_Diagnostics_StackTrace = NULL; + class_System_Diagnostics_StackTrace = nullptr; methodthunk_System_Diagnostics_StackTrace_GetFrames.nullify(); - method_System_Diagnostics_StackTrace_ctor_bool = NULL; - method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL; + method_System_Diagnostics_StackTrace_ctor_bool = nullptr; + method_System_Diagnostics_StackTrace_ctor_Exception_bool = nullptr; #endif - class_KeyNotFoundException = NULL; + class_KeyNotFoundException = nullptr; } void CachedData::clear_godot_api_cache() { - godot_api_cache_updated = false; - rawclass_Dictionary = NULL; - - class_Vector2 = NULL; - class_Vector2i = NULL; - class_Rect2 = NULL; - class_Rect2i = NULL; - class_Transform2D = NULL; - class_Vector3 = NULL; - class_Vector3i = NULL; - class_Basis = NULL; - class_Quat = NULL; - class_Transform = NULL; - class_AABB = NULL; - class_Color = NULL; - class_Plane = NULL; - class_StringName = NULL; - class_NodePath = NULL; - class_RID = NULL; - class_GodotObject = NULL; - class_GodotResource = NULL; - class_Node = NULL; - class_Control = NULL; - class_Spatial = NULL; - class_WeakRef = NULL; - class_Callable = NULL; - class_SignalInfo = NULL; - class_Array = NULL; - class_Dictionary = NULL; - class_MarshalUtils = NULL; - class_ISerializationListener = NULL; + rawclass_Dictionary = nullptr; + + class_Vector2 = nullptr; + class_Vector2i = nullptr; + class_Rect2 = nullptr; + class_Rect2i = nullptr; + class_Transform2D = nullptr; + class_Vector3 = nullptr; + class_Vector3i = nullptr; + class_Basis = nullptr; + class_Quat = nullptr; + class_Transform = nullptr; + class_AABB = nullptr; + class_Color = nullptr; + class_Plane = nullptr; + class_StringName = nullptr; + class_NodePath = nullptr; + class_RID = nullptr; + class_GodotObject = nullptr; + class_GodotResource = nullptr; + class_Node = nullptr; + class_Control = nullptr; + class_Node3D = nullptr; + class_WeakRef = nullptr; + class_Callable = nullptr; + class_SignalInfo = nullptr; + class_Array = nullptr; + class_Dictionary = nullptr; + class_MarshalUtils = nullptr; + class_ISerializationListener = nullptr; #ifdef DEBUG_ENABLED - class_DebuggingUtils = NULL; + class_DebuggingUtils = nullptr; methodthunk_DebuggingUtils_GetStackFrameInfo.nullify(); #endif - class_ExportAttribute = NULL; - field_ExportAttribute_hint = NULL; - field_ExportAttribute_hintString = NULL; - class_SignalAttribute = NULL; - class_ToolAttribute = NULL; - class_RemoteAttribute = NULL; - class_MasterAttribute = NULL; - class_PuppetAttribute = NULL; - class_RemoteSyncAttribute = NULL; - class_MasterSyncAttribute = NULL; - class_PuppetSyncAttribute = NULL; - class_GodotMethodAttribute = NULL; - field_GodotMethodAttribute_methodName = NULL; - - field_GodotObject_ptr = NULL; - field_StringName_ptr = NULL; - field_NodePath_ptr = NULL; - field_Image_ptr = NULL; - field_RID_ptr = NULL; + class_ExportAttribute = nullptr; + field_ExportAttribute_hint = nullptr; + field_ExportAttribute_hintString = nullptr; + class_SignalAttribute = nullptr; + class_ToolAttribute = nullptr; + class_RemoteAttribute = nullptr; + class_MasterAttribute = nullptr; + class_PuppetAttribute = nullptr; + class_RemoteSyncAttribute = nullptr; + class_MasterSyncAttribute = nullptr; + class_PuppetSyncAttribute = nullptr; + class_GodotMethodAttribute = nullptr; + field_GodotMethodAttribute_methodName = nullptr; + + field_GodotObject_ptr = nullptr; + field_StringName_ptr = nullptr; + field_NodePath_ptr = nullptr; + field_Image_ptr = nullptr; + field_RID_ptr = nullptr; methodthunk_GodotObject_Dispose.nullify(); methodthunk_Array_GetPtr.nullify(); @@ -171,22 +170,18 @@ void CachedData::clear_godot_api_cache() { methodthunk_MarshalUtils_TypeIsGenericArray.nullify(); methodthunk_MarshalUtils_TypeIsGenericDictionary.nullify(); + methodthunk_MarshalUtils_TypeIsSystemGenericList.nullify(); + methodthunk_MarshalUtils_TypeIsSystemGenericDictionary.nullify(); + methodthunk_MarshalUtils_TypeIsGenericIEnumerable.nullify(); + methodthunk_MarshalUtils_TypeIsGenericICollection.nullify(); + methodthunk_MarshalUtils_TypeIsGenericIDictionary.nullify(); methodthunk_MarshalUtils_ArrayGetElementType.nullify(); methodthunk_MarshalUtils_DictionaryGetKeyValueTypes.nullify(); - methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType.nullify(); - methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType.nullify(); - methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info.nullify(); - methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info.nullify(); - methodthunk_MarshalUtils_MakeGenericArrayType.nullify(); methodthunk_MarshalUtils_MakeGenericDictionaryType.nullify(); - methodthunk_MarshalUtils_EnumerableToArray.nullify(); - methodthunk_MarshalUtils_IDictionaryToDictionary.nullify(); - methodthunk_MarshalUtils_GenericIDictionaryToDictionary.nullify(); - // End of MarshalUtils methods task_scheduler_handle = Ref<MonoGCHandleRef>(); @@ -196,7 +191,6 @@ void CachedData::clear_godot_api_cache() { #define GODOT_API_NS_CLASS(m_ns, m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(m_ns, #m_class)) void update_corlib_cache() { - CACHE_CLASS_AND_CHECK(MonoObject, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_object_class())); CACHE_CLASS_AND_CHECK(bool, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_boolean_class())); CACHE_CLASS_AND_CHECK(int8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_sbyte_class())); @@ -213,6 +207,7 @@ void update_corlib_cache() { CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class())); CACHE_CLASS_AND_CHECK(System_Collections_IEnumerable, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IEnumerable")); + CACHE_CLASS_AND_CHECK(System_Collections_ICollection, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "ICollection")); CACHE_CLASS_AND_CHECK(System_Collections_IDictionary, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IDictionary")); #ifdef DEBUG_ENABLED @@ -230,7 +225,6 @@ void update_corlib_cache() { } void update_godot_api_cache() { - CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2)); CACHE_CLASS_AND_CHECK(Vector2i, GODOT_API_CLASS(Vector2i)); CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2)); @@ -251,7 +245,7 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(GodotResource, GODOT_API_CLASS(Resource)); CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node)); CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control)); - CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial)); + CACHE_CLASS_AND_CHECK(Node3D, GODOT_API_CLASS(Node3D)); CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef)); CACHE_CLASS_AND_CHECK(Callable, GODOT_API_CLASS(Callable)); CACHE_CLASS_AND_CHECK(SignalInfo, GODOT_API_CLASS(SignalInfo)); @@ -297,22 +291,18 @@ void update_godot_api_cache() { CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericArray, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericArray", 1)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericDictionary", 1)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsSystemGenericList, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsSystemGenericList", 1)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsSystemGenericDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsSystemGenericDictionary", 1)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIEnumerable, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIEnumerable", 1)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericICollection, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericICollection", 1)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIDictionary", 1)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, GODOT_API_CLASS(MarshalUtils)->get_method("ArrayGetElementType", 2)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, GODOT_API_CLASS(MarshalUtils)->get_method("DictionaryGetKeyValueTypes", 3)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIEnumerableIsAssignableFromType", 1)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIDictionaryIsAssignableFromType", 1)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIEnumerableIsAssignableFromType", 2)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIDictionaryIsAssignableFromType", 3)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericArrayType, GODOT_API_CLASS(MarshalUtils)->get_method("MakeGenericArrayType", 1)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericDictionaryType, GODOT_API_CLASS(MarshalUtils)->get_method("MakeGenericDictionaryType", 2)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, EnumerableToArray, GODOT_API_CLASS(MarshalUtils)->get_method("EnumerableToArray", 2)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IDictionaryToDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("IDictionaryToDictionary", 2)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryToDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIDictionaryToDictionary", 2)); - // End of MarshalUtils methods #ifdef DEBUG_ENABLED diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index b2dacee67c..a7bbc763a7 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -37,7 +37,6 @@ namespace GDMonoCache { struct CachedData { - // ----------------------------------------------- // corlib classes @@ -58,6 +57,7 @@ struct CachedData { GDMonoClass *class_IntPtr; // System.IntPtr GDMonoClass *class_System_Collections_IEnumerable; + GDMonoClass *class_System_Collections_ICollection; GDMonoClass *class_System_Collections_IDictionary; #ifdef DEBUG_ENABLED @@ -92,7 +92,7 @@ struct CachedData { GDMonoClass *class_GodotResource; GDMonoClass *class_Node; GDMonoClass *class_Control; - GDMonoClass *class_Spatial; + GDMonoClass *class_Node3D; GDMonoClass *class_WeakRef; GDMonoClass *class_Callable; GDMonoClass *class_SignalInfo; @@ -141,22 +141,18 @@ struct CachedData { GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericArray; GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericDictionary; + GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsSystemGenericList; + GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsSystemGenericDictionary; + GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIEnumerable; + GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericICollection; + GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIDictionary; GDMonoMethodThunk<MonoReflectionType *, MonoReflectionType **> methodthunk_MarshalUtils_ArrayGetElementType; GDMonoMethodThunk<MonoReflectionType *, MonoReflectionType **, MonoReflectionType **> methodthunk_MarshalUtils_DictionaryGetKeyValueTypes; - GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType; - GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType; - GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *, MonoReflectionType **> methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info; - GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *, MonoReflectionType **, MonoReflectionType **> methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info; - GDMonoMethodThunkR<MonoReflectionType *, MonoReflectionType *> methodthunk_MarshalUtils_MakeGenericArrayType; GDMonoMethodThunkR<MonoReflectionType *, MonoReflectionType *, MonoReflectionType *> methodthunk_MarshalUtils_MakeGenericDictionaryType; - GDMonoMethodThunk<MonoObject *, Array *> methodthunk_MarshalUtils_EnumerableToArray; - GDMonoMethodThunk<MonoObject *, Dictionary *> methodthunk_MarshalUtils_IDictionaryToDictionary; - GDMonoMethodThunk<MonoObject *, Dictionary *> methodthunk_MarshalUtils_GenericIDictionaryToDictionary; - // End of MarshalUtils methods Ref<MonoGCHandleRef> task_scheduler_handle; @@ -186,14 +182,6 @@ inline void clear_godot_api_cache() { cached_data.clear_godot_api_cache(); } -_FORCE_INLINE_ bool tools_godot_api_check() { -#ifdef TOOLS_ENABLED - return cached_data.godot_api_cache_updated; -#else - return true; // Assume it's updated if this was called, otherwise it's a bug -#endif -} - } // namespace GDMonoCache #define CACHED_CLASS(m_class) (GDMonoCache::cached_data.class_##m_class) diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index 648f5f6c6b..691da55b10 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -31,6 +31,7 @@ #include "gd_mono_class.h" #include <mono/metadata/attrdefs.h> +#include <mono/metadata/debug-helpers.h> #include "gd_mono_assembly.h" #include "gd_mono_cache.h" @@ -40,7 +41,7 @@ String GDMonoClass::get_full_name(MonoClass *p_mono_class) { // mono_type_get_full_name is not exposed to embedders, but this seems to do the job MonoReflectionType *type_obj = mono_type_get_object(mono_domain_get(), get_mono_type(p_mono_class)); - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoString *str = GDMonoUtils::object_to_string((MonoObject *)type_obj, &exc); UNHANDLED_EXCEPTION(exc); @@ -55,7 +56,11 @@ String GDMonoClass::get_full_name() const { return get_full_name(mono_class); } -MonoType *GDMonoClass::get_mono_type() { +String GDMonoClass::get_type_desc() const { + return GDMonoUtils::get_type_desc(get_mono_type()); +} + +MonoType *GDMonoClass::get_mono_type() const { // Careful, you cannot compare two MonoType*. // There is mono_metadata_type_equal, how is this different from comparing two MonoClass*? return get_mono_type(mono_class); @@ -74,27 +79,40 @@ bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const { return mono_class_is_assignable_from(mono_class, p_from->mono_class); } -GDMonoClass *GDMonoClass::get_parent_class() { +StringName GDMonoClass::get_namespace() const { + GDMonoClass *nesting_class = get_nesting_class(); + if (!nesting_class) + return namespace_name; + return nesting_class->get_namespace(); +} + +String GDMonoClass::get_name_for_lookup() const { + GDMonoClass *nesting_class = get_nesting_class(); + if (!nesting_class) + return class_name; + return nesting_class->get_name_for_lookup() + "/" + class_name; +} + +GDMonoClass *GDMonoClass::get_parent_class() const { MonoClass *parent_mono_class = mono_class_get_parent(mono_class); - return parent_mono_class ? GDMono::get_singleton()->get_class(parent_mono_class) : NULL; + return parent_mono_class ? GDMono::get_singleton()->get_class(parent_mono_class) : nullptr; } -GDMonoClass *GDMonoClass::get_nesting_class() { +GDMonoClass *GDMonoClass::get_nesting_class() const { MonoClass *nesting_type = mono_class_get_nesting_type(mono_class); - return nesting_type ? GDMono::get_singleton()->get_class(nesting_type) : NULL; + return nesting_type ? GDMono::get_singleton()->get_class(nesting_type) : nullptr; } #ifdef TOOLS_ENABLED Vector<MonoClassField *> GDMonoClass::get_enum_fields() { - bool class_is_enum = mono_class_is_enum(mono_class); ERR_FAIL_COND_V(!class_is_enum, Vector<MonoClassField *>()); Vector<MonoClassField *> enum_fields; - void *iter = NULL; - MonoClassField *raw_field = NULL; - while ((raw_field = mono_class_get_fields(get_mono_ptr(), &iter)) != NULL) { + void *iter = nullptr; + MonoClassField *raw_field = nullptr; + while ((raw_field = mono_class_get_fields(get_mono_ptr(), &iter)) != nullptr) { uint32_t field_flags = mono_field_get_flags(raw_field); // Enums have an instance field named value__ which holds the value of the enum. @@ -109,7 +127,6 @@ Vector<MonoClassField *> GDMonoClass::get_enum_fields() { #endif bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) { - #ifdef DEBUG_ENABLED ERR_FAIL_NULL_V(p_attr_class, false); #endif @@ -124,38 +141,35 @@ bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) { } MonoObject *GDMonoClass::get_attribute(GDMonoClass *p_attr_class) { - #ifdef DEBUG_ENABLED - ERR_FAIL_NULL_V(p_attr_class, NULL); + ERR_FAIL_NULL_V(p_attr_class, nullptr); #endif if (!attrs_fetched) fetch_attributes(); if (!attributes) - return NULL; + return nullptr; return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } void GDMonoClass::fetch_attributes() { - - ERR_FAIL_COND(attributes != NULL); + ERR_FAIL_COND(attributes != nullptr); attributes = mono_custom_attrs_from_class(get_mono_ptr()); attrs_fetched = true; } void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base) { - CRASH_COND(!CACHED_CLASS(GodotObject)->is_assignable_from(this)); if (methods_fetched) return; - void *iter = NULL; - MonoMethod *raw_method = NULL; - while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) { + void *iter = nullptr; + MonoMethod *raw_method = nullptr; + while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != nullptr) { StringName name = mono_method_get_name(raw_method); // get_method implicitly fetches methods and adds them to this->methods @@ -163,7 +177,6 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base ERR_CONTINUE(!method); if (method->get_name() != name) { - #ifdef DEBUG_ENABLED String fullname = method->get_ret_type_full_name() + " " + name + "(" + method->get_signature_desc(true) + ")"; WARN_PRINT("Method '" + fullname + "' is hidden by Godot API method. Should be '" + @@ -177,7 +190,6 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base // This allows us to warn the user here if he is using snake_case by mistake. if (p_native_base != this) { - GDMonoClass *native_top = p_native_base; while (native_top) { GDMonoMethod *m = native_top->get_method(name, method->get_parameters_count()); @@ -198,7 +210,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base } #endif - uint32_t flags = mono_method_get_flags(method->mono_method, NULL); + uint32_t flags = mono_method_get_flags(method->mono_method, nullptr); if (!(flags & MONO_METHOD_ATTR_VIRTUAL)) continue; @@ -241,31 +253,32 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base } GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) { + ERR_FAIL_COND_V(!methods_fetched, nullptr); - ERR_FAIL_COND_V(!methods_fetched, NULL); - - const MethodKey *k = NULL; + const MethodKey *k = nullptr; while ((k = methods.next(k))) { if (k->name == p_name) return methods.get(*k); } - return NULL; + return nullptr; } bool GDMonoClass::has_fetched_method_unknown_params(const StringName &p_name) { - - return get_fetched_method_unknown_params(p_name) != NULL; + return get_fetched_method_unknown_params(p_name) != nullptr; } bool GDMonoClass::implements_interface(GDMonoClass *p_interface) { - return mono_class_implements_interface(mono_class, p_interface->get_mono_ptr()); } -GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) { +bool GDMonoClass::has_public_parameterless_ctor() { + GDMonoMethod *ctor = get_method(".ctor", 0); + return ctor && ctor->get_visibility() == IMonoClassMember::PUBLIC; +} +GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) { MethodKey key = MethodKey(p_name, p_params_count); GDMonoMethod **match = methods.getptr(key); @@ -274,7 +287,7 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_cou return *match; if (methods_fetched) - return NULL; + return nullptr; MonoMethod *raw_method = mono_class_get_method_from_name(mono_class, String(p_name).utf8().get_data(), p_params_count); @@ -285,11 +298,10 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_cou return method; } - return NULL; + return nullptr; } GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method) { - MonoMethodSignature *sig = mono_method_signature(p_raw_method); int params_count = mono_signature_get_param_count(sig); @@ -299,15 +311,13 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method) { } GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name) { - MonoMethodSignature *sig = mono_method_signature(p_raw_method); int params_count = mono_signature_get_param_count(sig); return get_method(p_raw_method, p_name, params_count); } GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count) { - - ERR_FAIL_NULL_V(p_raw_method, NULL); + ERR_FAIL_NULL_V(p_raw_method, nullptr); MethodKey key = MethodKey(p_name, p_params_count); @@ -323,25 +333,26 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName } GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, bool p_include_namespace) { - MonoMethodDesc *desc = mono_method_desc_new(p_description.utf8().get_data(), p_include_namespace); MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class); mono_method_desc_free(desc); - ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, NULL); + if (!method) + return nullptr; + + ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, nullptr); return get_method(method); } GDMonoField *GDMonoClass::get_field(const StringName &p_name) { - Map<StringName, GDMonoField *>::Element *result = fields.find(p_name); if (result) return result->value(); if (fields_fetched) - return NULL; + return nullptr; MonoClassField *raw_field = mono_class_get_field_from_name(mono_class, String(p_name).utf8().get_data()); @@ -352,17 +363,16 @@ GDMonoField *GDMonoClass::get_field(const StringName &p_name) { return field; } - return NULL; + return nullptr; } const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { - if (fields_fetched) return fields_list; - void *iter = NULL; - MonoClassField *raw_field = NULL; - while ((raw_field = mono_class_get_fields(mono_class, &iter)) != NULL) { + void *iter = nullptr; + MonoClassField *raw_field = nullptr; + while ((raw_field = mono_class_get_fields(mono_class, &iter)) != nullptr) { StringName name = mono_field_get_name(raw_field); Map<StringName, GDMonoField *>::Element *match = fields.find(name); @@ -382,14 +392,13 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() { } GDMonoProperty *GDMonoClass::get_property(const StringName &p_name) { - Map<StringName, GDMonoProperty *>::Element *result = properties.find(p_name); if (result) return result->value(); if (properties_fetched) - return NULL; + return nullptr; MonoProperty *raw_property = mono_class_get_property_from_name(mono_class, String(p_name).utf8().get_data()); @@ -400,17 +409,16 @@ GDMonoProperty *GDMonoClass::get_property(const StringName &p_name) { return property; } - return NULL; + return nullptr; } const Vector<GDMonoProperty *> &GDMonoClass::get_all_properties() { - if (properties_fetched) return properties_list; - void *iter = NULL; - MonoProperty *raw_property = NULL; - while ((raw_property = mono_class_get_properties(mono_class, &iter)) != NULL) { + void *iter = nullptr; + MonoProperty *raw_property = nullptr; + while ((raw_property = mono_class_get_properties(mono_class, &iter)) != nullptr) { StringName name = mono_property_get_name(raw_property); Map<StringName, GDMonoProperty *>::Element *match = properties.find(name); @@ -433,9 +441,9 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() { if (delegates_fetched) return delegates_list; - void *iter = NULL; - MonoClass *raw_class = NULL; - while ((raw_class = mono_class_get_nested_types(mono_class, &iter)) != NULL) { + void *iter = nullptr; + MonoClass *raw_class = nullptr; + while ((raw_class = mono_class_get_nested_types(mono_class, &iter)) != nullptr) { if (mono_class_is_delegate(raw_class)) { StringName name = mono_class_get_name(raw_class); @@ -457,11 +465,10 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() { } const Vector<GDMonoMethod *> &GDMonoClass::get_all_methods() { - if (!method_list_fetched) { - void *iter = NULL; - MonoMethod *raw_method = NULL; - while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) { + void *iter = nullptr; + MonoMethod *raw_method = nullptr; + while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != nullptr) { method_list.push_back(memnew(GDMonoMethod(mono_method_get_name(raw_method), raw_method))); } @@ -472,14 +479,13 @@ const Vector<GDMonoMethod *> &GDMonoClass::get_all_methods() { } GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly) { - namespace_name = p_namespace; class_name = p_name; mono_class = p_class; assembly = p_assembly; attrs_fetched = false; - attributes = NULL; + attributes = nullptr; methods_fetched = false; method_list_fetched = false; @@ -489,7 +495,6 @@ GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name } GDMonoClass::~GDMonoClass() { - if (attributes) { mono_custom_attrs_free(attributes); } @@ -512,7 +517,7 @@ GDMonoClass::~GDMonoClass() { Vector<GDMonoMethod *> deleted_methods; deleted_methods.resize(methods.size()); - const MethodKey *k = NULL; + const MethodKey *k = nullptr; while ((k = methods.next(k))) { GDMonoMethod *method = methods.get(*k); diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index 0c9a8cdafe..44b146b87c 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -31,8 +31,6 @@ #ifndef GD_MONO_CLASS_H #define GD_MONO_CLASS_H -#include <mono/metadata/debug-helpers.h> - #include "core/map.h" #include "core/ustring.h" @@ -107,21 +105,23 @@ public: static MonoType *get_mono_type(MonoClass *p_mono_class); String get_full_name() const; - MonoType *get_mono_type(); + String get_type_desc() const; + MonoType *get_mono_type() const; uint32_t get_flags() const; bool is_static() const; bool is_assignable_from(GDMonoClass *p_from) const; - _FORCE_INLINE_ StringName get_namespace() const { return namespace_name; } + StringName get_namespace() const; _FORCE_INLINE_ StringName get_name() const { return class_name; } + String get_name_for_lookup() const; _FORCE_INLINE_ MonoClass *get_mono_ptr() const { return mono_class; } _FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; } - GDMonoClass *get_parent_class(); - GDMonoClass *get_nesting_class(); + GDMonoClass *get_parent_class() const; + GDMonoClass *get_nesting_class() const; #ifdef TOOLS_ENABLED Vector<MonoClassField *> get_enum_fields(); @@ -137,6 +137,7 @@ public: void fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base); bool implements_interface(GDMonoClass *p_interface); + bool has_public_parameterless_ctor(); GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0); GDMonoMethod *get_method(MonoMethod *p_raw_method); diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index 11942c47d9..948170f51c 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -116,7 +116,7 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ case MONO_TYPE_STRING: { if (p_value.get_type() == Variant::NIL) { // Otherwise, Variant -> String would return the string "Null" - MonoString *mono_string = NULL; + MonoString *mono_string = nullptr; mono_field_set_value(p_object, mono_field, mono_string); } else { MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value); @@ -322,6 +322,13 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) { + MonoArray *managed = GDMonoMarshal::Array_to_mono_array(p_value.operator ::Array(), array_type_class); + mono_field_set_value(p_object, mono_field, managed); + break; + } + ERR_FAIL_MSG("Attempted to convert Variant to a managed array of unmarshallable element type."); } break; @@ -353,56 +360,22 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } - if (CACHED_CLASS(Dictionary) == type_class) { + // Godot.Collections.Dictionary or IDictionary + if (CACHED_CLASS(Dictionary) == type_class || type_class == CACHED_CLASS(System_Collections_IDictionary)) { MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary)); mono_field_set_value(p_object, mono_field, managed); break; } - if (CACHED_CLASS(Array) == type_class) { + // Godot.Collections.Array or ICollection or IEnumerable + if (CACHED_CLASS(Array) == type_class || + type_class == CACHED_CLASS(System_Collections_ICollection) || + type_class == CACHED_CLASS(System_Collections_IEnumerable)) { MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array)); mono_field_set_value(p_object, mono_field, managed); break; } - // The order in which we check the following interfaces is very important (dictionaries and generics first) - - MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type_class->get_mono_type()); - - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) { - MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), - GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype)); - mono_field_set_value(p_object, mono_field, managed); - break; - } - - if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { - MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary)); - mono_field_set_value(p_object, mono_field, managed); - break; - } - - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) { - MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), - GDMonoUtils::Marshal::make_generic_array_type(elem_reftype)); - mono_field_set_value(p_object, mono_field, managed); - break; - } - - if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { - if (GDMonoCache::tools_godot_api_check()) { - MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array)); - mono_field_set_value(p_object, mono_field, managed); - break; - } else { - MonoObject *managed = (MonoObject *)GDMonoMarshal::Array_to_mono_array(p_value.operator Array()); - mono_field_set_value(p_object, mono_field, managed); - break; - } - } - ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + type_class->get_name() + "'."); } break; @@ -528,59 +501,70 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ case Variant::PACKED_COLOR_ARRAY: { SET_FROM_ARRAY(PackedColorArray); } break; - default: break; + default: + break; } } break; case MONO_TYPE_GENERICINST: { MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type.type_class->get_mono_type()); + // Godot.Collections.Dictionary<TKey, TValue> if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) { MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), type.type_class); mono_field_set_value(p_object, mono_field, managed); break; } + // Godot.Collections.Array<T> if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) { MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), type.type_class); mono_field_set_value(p_object, mono_field, managed); break; } - // The order in which we check the following interfaces is very important (dictionaries and generics first) - - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) { - MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), - GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype)); + // System.Collections.Generic.Dictionary<TKey, TValue> + if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) { + MonoReflectionType *key_reftype = nullptr; + MonoReflectionType *value_reftype = nullptr; + GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype); + MonoObject *managed = GDMonoMarshal::Dictionary_to_system_generic_dict(p_value.operator Dictionary(), + type.type_class, key_reftype, value_reftype); mono_field_set_value(p_object, mono_field, managed); break; } - if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { - MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary)); + // System.Collections.Generic.List<T> + if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) { + MonoReflectionType *elem_reftype = nullptr; + GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype); + MonoObject *managed = GDMonoMarshal::Array_to_system_generic_list(p_value.operator Array(), + type.type_class, elem_reftype); mono_field_set_value(p_object, mono_field, managed); break; } - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) { - MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), - GDMonoUtils::Marshal::make_generic_array_type(elem_reftype)); + // IDictionary<TKey, TValue> + if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) { + MonoReflectionType *key_reftype; + MonoReflectionType *value_reftype; + GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype); + GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype); + + MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), godot_dict_class); mono_field_set_value(p_object, mono_field, managed); break; } - if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { - if (GDMonoCache::tools_godot_api_check()) { - MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array)); - mono_field_set_value(p_object, mono_field, managed); - break; - } else { - MonoObject *managed = (MonoObject *)GDMonoMarshal::Array_to_mono_array(p_value.operator Array()); - mono_field_set_value(p_object, mono_field, managed); - break; - } + // ICollection<T> or IEnumerable<T> + if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) { + MonoReflectionType *elem_reftype; + GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype); + GDMonoClass *godot_array_class = GDMonoUtils::Marshal::make_generic_array_type(elem_reftype); + + MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), godot_array_class); + mono_field_set_value(p_object, mono_field, managed); + break; } } break; @@ -623,19 +607,19 @@ bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) { } MonoObject *GDMonoField::get_attribute(GDMonoClass *p_attr_class) { - ERR_FAIL_NULL_V(p_attr_class, NULL); + ERR_FAIL_NULL_V(p_attr_class, nullptr); if (!attrs_fetched) fetch_attributes(); if (!attributes) - return NULL; + return nullptr; return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } void GDMonoField::fetch_attributes() { - ERR_FAIL_COND(attributes != NULL); + ERR_FAIL_COND(attributes != nullptr); attributes = mono_custom_attrs_from_field(owner->get_mono_ptr(), mono_field); attrs_fetched = true; } @@ -671,7 +655,7 @@ GDMonoField::GDMonoField(MonoClassField *p_mono_field, GDMonoClass *p_owner) { type.type_class = GDMono::get_singleton()->get_class(field_type_class); attrs_fetched = false; - attributes = NULL; + attributes = nullptr; } GDMonoField::~GDMonoField() { diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h index 61f2c8f071..5b40b439f9 100644 --- a/modules/mono/mono_gd/gd_mono_field.h +++ b/modules/mono/mono_gd/gd_mono_field.h @@ -36,7 +36,6 @@ #include "i_mono_class_member.h" class GDMonoField : public IMonoClassMember { - GDMonoClass *owner; MonoClassField *mono_field; diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index 53e642f317..27e402d777 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -45,7 +45,6 @@ namespace GDMonoInternals { void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { - // This method should not fail CRASH_COND(!unmanaged); @@ -61,7 +60,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { GDMonoClass *native = GDMonoUtils::get_class_native_base(klass); - CRASH_COND(native == NULL); + CRASH_COND(native == nullptr); if (native == klass) { // If it's just a wrapper Godot class and not a custom inheriting class, then attach a @@ -119,7 +118,7 @@ void unhandled_exception(MonoException *p_exc) { if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) { // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders - GDMono::unhandled_exception_hook((MonoObject *)p_exc, NULL); + GDMono::unhandled_exception_hook((MonoObject *)p_exc, nullptr); GD_UNREACHABLE(); } else { #ifdef DEBUG_ENABLED diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index 76828a66e0..04728be725 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -46,13 +46,12 @@ static CharString get_default_log_level() { #endif } -GDMonoLog *GDMonoLog::singleton = NULL; +GDMonoLog *GDMonoLog::singleton = nullptr; -#if !defined(JAVASCRIPT_ENABLED) +#ifdef GD_MONO_LOG_ENABLED static int get_log_level_id(const char *p_log_level) { - - const char *valid_log_levels[] = { "error", "critical", "warning", "message", "info", "debug", NULL }; + const char *valid_log_levels[] = { "error", "critical", "warning", "message", "info", "debug", nullptr }; int i = 0; while (valid_log_levels[i]) { @@ -65,7 +64,6 @@ static int get_log_level_id(const char *p_log_level) { } void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *) { - FileAccess *f = GDMonoLog::get_singleton()->log_file; if (GDMonoLog::get_singleton()->log_level_id >= get_log_level_id(log_level)) { @@ -94,7 +92,6 @@ void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, } bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) { - if (!DirAccess::exists(p_logs_dir)) { DirAccessRef diraccess = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); ERR_FAIL_COND_V(!diraccess, false); @@ -106,7 +103,6 @@ bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) { } void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) { - static const uint64_t MAX_SECS = 5 * 86400; // 5 days DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -135,7 +131,6 @@ void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) { } void GDMonoLog::initialize() { - CharString log_level = OS::get_singleton()->get_environment("GODOT_MONO_LOG_LEVEL").utf8(); if (log_level.length() != 0 && get_log_level_id(log_level.get_data()) == -1) { @@ -175,7 +170,7 @@ void GDMonoLog::initialize() { log_level_id = get_log_level_id(log_level.get_data()); if (log_file) { - OS::get_singleton()->print("Mono: Logfile is: %s\n", log_file_path.utf8().get_data()); + OS::get_singleton()->print("Mono: Log file is: '%s'\n", log_file_path.utf8().get_data()); mono_trace_set_log_handler(mono_log_callback, this); } else { OS::get_singleton()->printerr("Mono: No log file, using default log handler\n"); @@ -183,15 +178,13 @@ void GDMonoLog::initialize() { } GDMonoLog::GDMonoLog() { - singleton = this; log_level_id = -1; } GDMonoLog::~GDMonoLog() { - - singleton = NULL; + singleton = nullptr; if (log_file) { log_file->close(); @@ -207,13 +200,11 @@ void GDMonoLog::initialize() { } GDMonoLog::GDMonoLog() { - singleton = this; } GDMonoLog::~GDMonoLog() { - - singleton = NULL; + singleton = nullptr; } #endif // !defined(JAVASCRIPT_ENABLED) diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h index ecf4c78b1a..3a52316060 100644 --- a/modules/mono/mono_gd/gd_mono_log.h +++ b/modules/mono/mono_gd/gd_mono_log.h @@ -35,13 +35,17 @@ #include "core/typedefs.h" -#if !defined(JAVASCRIPT_ENABLED) +#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED) +// We have custom mono log callbacks for WASM and iOS +#define GD_MONO_LOG_ENABLED +#endif + +#ifdef GD_MONO_LOG_ENABLED #include "core/os/file_access.h" #endif class GDMonoLog { - -#if !defined(JAVASCRIPT_ENABLED) +#ifdef GD_MONO_LOG_ENABLED int log_level_id; FileAccess *log_file; diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 0de5352752..085062261d 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -154,6 +154,10 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ if (array_type->eklass == CACHED_CLASS_RAW(Color)) return Variant::PACKED_COLOR_ARRAY; + + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + return Variant::ARRAY; } break; case MONO_TYPE_CLASS: { @@ -184,23 +188,14 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ return Variant::ARRAY; } - // The order in which we check the following interfaces is very important (dictionaries and generics first) - - MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type_class->get_mono_type()); - - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) { - return Variant::DICTIONARY; - } - - if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { + // IDictionary + if (p_type.type_class == CACHED_CLASS(System_Collections_IDictionary)) { return Variant::DICTIONARY; } - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) { - return Variant::ARRAY; - } - - if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { + // ICollection or IEnumerable + if (p_type.type_class == CACHED_CLASS(System_Collections_ICollection) || + p_type.type_class == CACHED_CLASS(System_Collections_IEnumerable)) { return Variant::ARRAY; } } break; @@ -214,27 +209,33 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ case MONO_TYPE_GENERICINST: { MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type()); + // Godot.Collections.Dictionary<TKey, TValue> if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) { return Variant::DICTIONARY; } + // Godot.Collections.Array<T> if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) { return Variant::ARRAY; } - // The order in which we check the following interfaces is very important (dictionaries and generics first) - - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) - return Variant::DICTIONARY; - - if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { + // System.Collections.Generic.Dictionary<TKey, TValue> + if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) { return Variant::DICTIONARY; } - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) + // System.Collections.Generic.List<T> + if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) { return Variant::ARRAY; + } - if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { + // IDictionary<TKey, TValue> + if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) { + return Variant::DICTIONARY; + } + + // ICollection<T> or IEnumerable<T> + if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) { return Variant::ARRAY; } } break; @@ -252,10 +253,20 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_elem_type) { switch (p_array_type.type_encoding) { + case MONO_TYPE_ARRAY: + case MONO_TYPE_SZARRAY: { + MonoArrayType *array_type = mono_type_get_array_type(p_array_type.type_class->get_mono_type()); + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + r_elem_type = ManagedType::from_class(array_type_class); + return true; + } break; case MONO_TYPE_GENERICINST: { MonoReflectionType *array_reftype = mono_type_get_object(mono_domain_get(), p_array_type.type_class->get_mono_type()); - if (GDMonoUtils::Marshal::type_is_generic_array(array_reftype)) { + if (GDMonoUtils::Marshal::type_is_generic_array(array_reftype) || + GDMonoUtils::Marshal::type_is_system_generic_list(array_reftype) || + GDMonoUtils::Marshal::type_is_generic_icollection(array_reftype) || + GDMonoUtils::Marshal::type_is_generic_ienumerable(array_reftype)) { MonoReflectionType *elem_reftype; GDMonoUtils::Marshal::array_get_element_type(array_reftype, &elem_reftype); @@ -263,12 +274,6 @@ bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_ r_elem_type = ManagedType::from_reftype(elem_reftype); return true; } - - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(array_reftype, &elem_reftype)) { - r_elem_type = ManagedType::from_reftype(elem_reftype); - return true; - } } break; default: { } break; @@ -282,7 +287,9 @@ bool try_get_dictionary_key_value_types(const ManagedType &p_dictionary_type, Ma case MONO_TYPE_GENERICINST: { MonoReflectionType *dict_reftype = mono_type_get_object(mono_domain_get(), p_dictionary_type.type_class->get_mono_type()); - if (GDMonoUtils::Marshal::type_is_generic_dictionary(dict_reftype)) { + if (GDMonoUtils::Marshal::type_is_generic_dictionary(dict_reftype) || + GDMonoUtils::Marshal::type_is_system_generic_dictionary(dict_reftype) || + GDMonoUtils::Marshal::type_is_generic_idictionary(dict_reftype)) { MonoReflectionType *key_reftype; MonoReflectionType *value_reftype; @@ -292,13 +299,6 @@ bool try_get_dictionary_key_value_types(const ManagedType &p_dictionary_type, Ma r_value_type = ManagedType::from_reftype(value_reftype); return true; } - - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(dict_reftype, &key_reftype, &value_reftype)) { - r_key_type = ManagedType::from_reftype(key_reftype); - r_value_type = ManagedType::from_reftype(value_reftype); - return true; - } } break; default: { } break; @@ -410,7 +410,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty case MONO_TYPE_STRING: { if (p_var->get_type() == Variant::NIL) - return NULL; // Otherwise, Variant -> String would return the string "Null" + return nullptr; // Otherwise, Variant -> String would return the string "Null" return (MonoObject *)mono_string_from_godot(p_var->operator String()); } break; @@ -537,7 +537,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return BOX_ENUM(enum_baseclass, val); } default: { - ERR_FAIL_V_MSG(NULL, "Attempted to convert Variant to a managed enum value of unmarshallable base type."); + ERR_FAIL_V_MSG(nullptr, "Attempted to convert Variant to a managed enum value of unmarshallable base type."); } } } @@ -577,7 +577,11 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty if (array_type->eklass == CACHED_CLASS_RAW(Color)) return (MonoObject *)PackedColorArray_to_mono_array(p_var->operator PackedColorArray()); - ERR_FAIL_V_MSG(NULL, "Attempted to convert Variant to a managed array of unmarshallable element type."); + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + return (MonoObject *)Array_to_mono_array(p_var->operator Array(), array_type_class); + + ERR_FAIL_V_MSG(nullptr, "Attempted to convert Variant to a managed array of unmarshallable element type."); } break; case MONO_TYPE_CLASS: { @@ -600,41 +604,17 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return GDMonoUtils::create_managed_from(p_var->operator RID()); } - if (CACHED_CLASS(Dictionary) == type_class) { + // Godot.Collections.Dictionary or IDictionary + if (CACHED_CLASS(Dictionary) == type_class || CACHED_CLASS(System_Collections_IDictionary) == type_class) { return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary)); } - if (CACHED_CLASS(Array) == type_class) { + // Godot.Collections.Array or ICollection or IEnumerable + if (CACHED_CLASS(Array) == type_class || + CACHED_CLASS(System_Collections_ICollection) == type_class || + CACHED_CLASS(System_Collections_IEnumerable) == type_class) { return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array)); } - - // The order in which we check the following interfaces is very important (dictionaries and generics first) - - MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type_class->get_mono_type()); - - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) { - return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), - GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype)); - } - - if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { - return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary)); - } - - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) { - return GDMonoUtils::create_managed_from(p_var->operator Array(), - GDMonoUtils::Marshal::make_generic_array_type(elem_reftype)); - } - - if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { - if (GDMonoCache::tools_godot_api_check()) { - return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array)); - } else { - return (MonoObject *)GDMonoMarshal::Array_to_mono_array(p_var->operator Array()); - } - } } break; case MONO_TYPE_OBJECT: { // Variant @@ -749,55 +729,64 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty case Variant::PACKED_COLOR_ARRAY: return (MonoObject *)PackedColorArray_to_mono_array(p_var->operator PackedColorArray()); default: - return NULL; + return nullptr; } break; case MONO_TYPE_GENERICINST: { MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type()); + // Godot.Collections.Dictionary<TKey, TValue> if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) { return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), p_type.type_class); } + // Godot.Collections.Array<T> if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) { return GDMonoUtils::create_managed_from(p_var->operator Array(), p_type.type_class); } - // The order in which we check the following interfaces is very important (dictionaries and generics first) - - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) { - return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), - GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype)); + // System.Collections.Generic.Dictionary<TKey, TValue> + if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) { + MonoReflectionType *key_reftype = nullptr; + MonoReflectionType *value_reftype = nullptr; + GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype); + return Dictionary_to_system_generic_dict(p_var->operator Dictionary(), p_type.type_class, key_reftype, value_reftype); } - if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { - return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary)); + // System.Collections.Generic.List<T> + if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) { + MonoReflectionType *elem_reftype = nullptr; + GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype); + return Array_to_system_generic_list(p_var->operator Array(), p_type.type_class, elem_reftype); } - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) { - return GDMonoUtils::create_managed_from(p_var->operator Array(), - GDMonoUtils::Marshal::make_generic_array_type(elem_reftype)); + // IDictionary<TKey, TValue> + if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) { + MonoReflectionType *key_reftype; + MonoReflectionType *value_reftype; + GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype); + GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype); + + return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), godot_dict_class); } - if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { - if (GDMonoCache::tools_godot_api_check()) { - return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array)); - } else { - return (MonoObject *)GDMonoMarshal::Array_to_mono_array(p_var->operator Array()); - } + // ICollection<T> or IEnumerable<T> + if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) { + MonoReflectionType *elem_reftype; + GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype); + GDMonoClass *godot_array_class = GDMonoUtils::Marshal::make_generic_array_type(elem_reftype); + + return GDMonoUtils::create_managed_from(p_var->operator Array(), godot_array_class); } } break; } break; } - ERR_FAIL_V_MSG(NULL, "Attempted to convert Variant to an unmarshallable managed type. Name: '" + - p_type.type_class->get_name() + "' Encoding: " + itos(p_type.type_encoding) + "."); + ERR_FAIL_V_MSG(nullptr, "Attempted to convert Variant to an unmarshallable managed type. Name: '" + + p_type.type_class->get_name() + "' Encoding: " + itos(p_type.type_encoding) + "."); } Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type, bool p_fail_with_err = true) { - ERR_FAIL_COND_V(!p_type.type_class, Variant()); switch (p_type.type_encoding) { @@ -831,7 +820,7 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type return unbox<double>(p_obj); case MONO_TYPE_STRING: { - if (p_obj == NULL) + if (p_obj == nullptr) return Variant(); // NIL return mono_string_to_godot_not_null((MonoString *)p_obj); } break; @@ -922,6 +911,10 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type if (array_type->eklass == CACHED_CLASS_RAW(Color)) return mono_array_to_PackedColorArray((MonoArray *)p_obj); + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + return mono_array_to_Array((MonoArray *)p_obj); + if (p_fail_with_err) { ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant."); } else { @@ -935,7 +928,7 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type // GodotObject if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) { Object *ptr = unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_obj)); - if (ptr != NULL) { + if (ptr != nullptr) { Reference *ref = Object::cast_to<Reference>(ptr); return ref ? Variant(Ref<Reference>(ref)) : Variant(ptr); } @@ -957,74 +950,55 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type return ptr ? Variant(*ptr) : Variant(); } - if (CACHED_CLASS(Array) == type_class) { - MonoException *exc = NULL; - Array *ptr = CACHED_METHOD_THUNK(Array, GetPtr).invoke(p_obj, &exc); - UNHANDLED_EXCEPTION(exc); - return ptr ? Variant(*ptr) : Variant(); - } - + // Godot.Collections.Dictionary if (CACHED_CLASS(Dictionary) == type_class) { - MonoException *exc = NULL; + MonoException *exc = nullptr; Dictionary *ptr = CACHED_METHOD_THUNK(Dictionary, GetPtr).invoke(p_obj, &exc); UNHANDLED_EXCEPTION(exc); return ptr ? Variant(*ptr) : Variant(); } - // The order in which we check the following interfaces is very important (dictionaries and generics first) - - MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type_class->get_mono_type()); - - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) { - return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj); - } - - if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { - return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj); - } - - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) { - return GDMonoUtils::Marshal::enumerable_to_array(p_obj); - } - - if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { - return GDMonoUtils::Marshal::enumerable_to_array(p_obj); + // Godot.Collections.Array + if (CACHED_CLASS(Array) == type_class) { + MonoException *exc = nullptr; + Array *ptr = CACHED_METHOD_THUNK(Array, GetPtr).invoke(p_obj, &exc); + UNHANDLED_EXCEPTION(exc); + return ptr ? Variant(*ptr) : Variant(); } } break; case MONO_TYPE_GENERICINST: { MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type()); + // Godot.Collections.Dictionary<TKey, TValue> if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) { - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoObject *ret = p_type.type_class->get_method("GetPtr")->invoke(p_obj, &exc); UNHANDLED_EXCEPTION(exc); return *unbox<Dictionary *>(ret); } + // Godot.Collections.Array<T> if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) { - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoObject *ret = p_type.type_class->get_method("GetPtr")->invoke(p_obj, &exc); UNHANDLED_EXCEPTION(exc); return *unbox<Array *>(ret); } - // The order in which we check the following interfaces is very important (dictionaries and generics first) - - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) { - return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj); - } - - if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { - return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj); - } - - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) { - return GDMonoUtils::Marshal::enumerable_to_array(p_obj); + // System.Collections.Generic.Dictionary<TKey, TValue> + if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) { + MonoReflectionType *key_reftype = nullptr; + MonoReflectionType *value_reftype = nullptr; + GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype); + return system_generic_dict_to_Dictionary(p_obj, p_type.type_class, key_reftype, value_reftype); } - if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { - return GDMonoUtils::Marshal::enumerable_to_array(p_obj); + // System.Collections.Generic.List<T> + if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) { + MonoReflectionType *elem_reftype = nullptr; + GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype); + return system_generic_list_to_Array(p_obj, p_type.type_class, elem_reftype); } } break; } @@ -1064,9 +1038,9 @@ String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) { ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj)); Variant var = GDMonoMarshal::mono_object_to_variant_no_err(p_obj, type); - if (var.get_type() == Variant::NIL && p_obj != NULL) { + if (var.get_type() == Variant::NIL && p_obj != nullptr) { // Cannot convert MonoObject* to Variant; fallback to 'ToString()'. - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoString *mono_str = GDMonoUtils::object_to_string(p_obj, &exc); if (exc) { @@ -1081,6 +1055,80 @@ String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) { } } +MonoObject *Dictionary_to_system_generic_dict(const Dictionary &p_dict, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) { + String ctor_desc = ":.ctor(System.Collections.Generic.IDictionary`2<" + GDMonoUtils::get_type_desc(p_key_reftype) + + ", " + GDMonoUtils::get_type_desc(p_value_reftype) + ">)"; + GDMonoMethod *ctor = p_class->get_method_with_desc(ctor_desc, true); + CRASH_COND(ctor == nullptr); + + MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr()); + ERR_FAIL_NULL_V(mono_object, nullptr); + + GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(p_key_reftype, p_value_reftype); + MonoObject *godot_dict = GDMonoUtils::create_managed_from(p_dict, godot_dict_class); + + void *ctor_args[1] = { godot_dict }; + + MonoException *exc = nullptr; + ctor->invoke_raw(mono_object, ctor_args, &exc); + UNHANDLED_EXCEPTION(exc); + + return mono_object; +} + +Dictionary system_generic_dict_to_Dictionary(MonoObject *p_obj, [[maybe_unused]] GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) { + GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(p_key_reftype, p_value_reftype); + String ctor_desc = ":.ctor(System.Collections.Generic.IDictionary`2<" + GDMonoUtils::get_type_desc(p_key_reftype) + + ", " + GDMonoUtils::get_type_desc(p_value_reftype) + ">)"; + GDMonoMethod *godot_dict_ctor = godot_dict_class->get_method_with_desc(ctor_desc, true); + CRASH_COND(godot_dict_ctor == nullptr); + + MonoObject *godot_dict = mono_object_new(mono_domain_get(), godot_dict_class->get_mono_ptr()); + ERR_FAIL_NULL_V(godot_dict, Dictionary()); + + void *ctor_args[1] = { p_obj }; + + MonoException *exc = nullptr; + godot_dict_ctor->invoke_raw(godot_dict, ctor_args, &exc); + UNHANDLED_EXCEPTION(exc); + + exc = nullptr; + MonoObject *ret = godot_dict_class->get_method("GetPtr")->invoke(godot_dict, &exc); + UNHANDLED_EXCEPTION(exc); + + return *unbox<Dictionary *>(ret); +} + +MonoObject *Array_to_system_generic_list(const Array &p_array, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype) { + GDMonoClass *elem_class = ManagedType::from_reftype(p_elem_reftype).type_class; + + String ctor_desc = ":.ctor(System.Collections.Generic.IEnumerable`1<" + elem_class->get_type_desc() + ">)"; + GDMonoMethod *ctor = p_class->get_method_with_desc(ctor_desc, true); + CRASH_COND(ctor == nullptr); + + MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr()); + ERR_FAIL_NULL_V(mono_object, nullptr); + + void *ctor_args[1] = { Array_to_mono_array(p_array, elem_class) }; + + MonoException *exc = nullptr; + ctor->invoke_raw(mono_object, ctor_args, &exc); + UNHANDLED_EXCEPTION(exc); + + return mono_object; +} + +Array system_generic_list_to_Array(MonoObject *p_obj, GDMonoClass *p_class, [[maybe_unused]] MonoReflectionType *p_elem_reftype) { + GDMonoMethod *to_array = p_class->get_method("ToArray", 0); + CRASH_COND(to_array == nullptr); + + MonoException *exc = nullptr; + MonoArray *mono_array = (MonoArray *)to_array->invoke_raw(p_obj, nullptr, &exc); + UNHANDLED_EXCEPTION(exc); + + return mono_array_to_Array(mono_array); +} + MonoArray *Array_to_mono_array(const Array &p_array) { int length = p_array.size(); MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), length); @@ -1093,6 +1141,18 @@ MonoArray *Array_to_mono_array(const Array &p_array) { return ret; } +MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class) { + int length = p_array.size(); + MonoArray *ret = mono_array_new(mono_domain_get(), p_array_type_class->get_mono_ptr(), length); + + for (int i = 0; i < length; i++) { + MonoObject *boxed = variant_to_mono_object(p_array[i]); + mono_array_setref(ret, i, boxed); + } + + return ret; +} + Array mono_array_to_Array(MonoArray *p_array) { Array ret; if (!p_array) @@ -1393,7 +1453,7 @@ Callable managed_to_callable(const M_Callable &p_managed_callable) { } else { Object *target = p_managed_callable.target ? unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_managed_callable.target)) : - NULL; + nullptr; StringName *method_ptr = unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_managed_callable.method_string_name)); StringName method = method_ptr ? *method_ptr : StringName(); return Callable(target, method); @@ -1408,7 +1468,7 @@ M_Callable callable_to_managed(const Callable &p_callable) { if (compare_equal_func == ManagedCallable::compare_equal_func_ptr) { ManagedCallable *managed_callable = static_cast<ManagedCallable *>(custom); return { - NULL, NULL, + nullptr, nullptr, managed_callable->get_delegate() }; } else if (compare_equal_func == SignalAwaiterCallable::compare_equal_func_ptr) { @@ -1416,30 +1476,30 @@ M_Callable callable_to_managed(const Callable &p_callable) { return { GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(signal_awaiter_callable->get_object())), GDMonoUtils::create_managed_from(signal_awaiter_callable->get_signal()), - NULL + nullptr }; } else if (compare_equal_func == EventSignalCallable::compare_equal_func_ptr) { EventSignalCallable *event_signal_callable = static_cast<EventSignalCallable *>(custom); return { GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(event_signal_callable->get_object())), GDMonoUtils::create_managed_from(event_signal_callable->get_signal()), - NULL + nullptr }; } // Some other CallableCustom. We only support ManagedCallable. - return { NULL, NULL, NULL }; + return { nullptr, nullptr, nullptr }; } else { MonoObject *target_managed = GDMonoUtils::unmanaged_get_managed(p_callable.get_object()); MonoObject *method_string_name_managed = GDMonoUtils::create_managed_from(p_callable.get_method()); - return { target_managed, method_string_name_managed, NULL }; + return { target_managed, method_string_name_managed, nullptr }; } } Signal managed_to_signal_info(const M_SignalInfo &p_managed_signal) { Object *owner = p_managed_signal.owner ? unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_managed_signal.owner)) : - NULL; + nullptr; StringName *name_ptr = unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(p_managed_signal.name_string_name)); StringName name = name_ptr ? *name_ptr : StringName(); return Signal(owner, name); diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 7d09f46b00..f2d887e6d6 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -63,7 +63,7 @@ T *unbox_addr(MonoObject *p_obj) { #define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x) #define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x) -Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_variant = NULL); +Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_variant = nullptr); bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_elem_type); bool try_get_dictionary_key_value_types(const ManagedType &p_dictionary_type, ManagedType &r_key_type, ManagedType &r_value_type); @@ -81,7 +81,7 @@ _FORCE_INLINE_ String mono_string_to_godot_not_null(MonoString *p_mono_string) { } _FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) { - if (p_mono_string == NULL) + if (p_mono_string == nullptr) return String(); return mono_string_to_godot_not_null(p_mono_string); @@ -123,9 +123,18 @@ Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_ty /// If the MonoObject* cannot be converted to Variant, then 'ToString()' is called instead. String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc); +// System.Collections.Generic + +MonoObject *Dictionary_to_system_generic_dict(const Dictionary &p_dict, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype); +Dictionary system_generic_dict_to_Dictionary(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype); + +MonoObject *Array_to_system_generic_list(const Array &p_array, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype); +Array system_generic_list_to_Array(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype); + // Array MonoArray *Array_to_mono_array(const Array &p_array); +MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class); Array mono_array_to_Array(MonoArray *p_array); // PackedInt32Array diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp index e6a1ec2697..e601bb12ad 100644 --- a/modules/mono/mono_gd/gd_mono_method.cpp +++ b/modules/mono/mono_gd/gd_mono_method.cpp @@ -30,13 +30,14 @@ #include "gd_mono_method.h" +#include <mono/metadata/attrdefs.h> +#include <mono/metadata/debug-helpers.h> + #include "gd_mono_cache.h" #include "gd_mono_class.h" #include "gd_mono_marshal.h" #include "gd_mono_utils.h" -#include <mono/metadata/attrdefs.h> - void GDMonoMethod::_update_signature() { // Apparently MonoMethodSignature needs not to be freed. // mono_method_signature caches the result, we don't need to cache it ourselves. @@ -58,9 +59,9 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) { } } - void *iter = NULL; + void *iter = nullptr; MonoType *param_raw_type; - while ((param_raw_type = mono_signature_get_params(p_method_sig, &iter)) != NULL) { + while ((param_raw_type = mono_signature_get_params(p_method_sig, &iter)) != nullptr) { ManagedType param_type; param_type.type_encoding = mono_type_get_type(param_raw_type); @@ -81,11 +82,11 @@ GDMonoClass *GDMonoMethod::get_enclosing_class() const { } bool GDMonoMethod::is_static() { - return mono_method_get_flags(mono_method, NULL) & MONO_METHOD_ATTR_STATIC; + return mono_method_get_flags(mono_method, nullptr) & MONO_METHOD_ATTR_STATIC; } IMonoClassMember::Visibility GDMonoMethod::get_visibility() { - switch (mono_method_get_flags(mono_method, NULL) & MONO_METHOD_ATTR_ACCESS_MASK) { + switch (mono_method_get_flags(mono_method, nullptr) & MONO_METHOD_ATTR_ACCESS_MASK) { case MONO_METHOD_ATTR_PRIVATE: return IMonoClassMember::PRIVATE; case MONO_METHOD_ATTR_FAM_AND_ASSEM: @@ -102,7 +103,7 @@ IMonoClassMember::Visibility GDMonoMethod::get_visibility() { } MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params, MonoException **r_exc) const { - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoObject *ret; if (params_count > 0) { @@ -115,11 +116,11 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params, ret = GDMonoUtils::runtime_invoke_array(mono_method, p_object, params, &exc); } else { - ret = GDMonoUtils::runtime_invoke(mono_method, p_object, NULL, &exc); + ret = GDMonoUtils::runtime_invoke(mono_method, p_object, nullptr, &exc); } if (exc) { - ret = NULL; + ret = nullptr; if (r_exc) { *r_exc = exc; } else { @@ -131,16 +132,16 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params, } MonoObject *GDMonoMethod::invoke(MonoObject *p_object, MonoException **r_exc) const { - ERR_FAIL_COND_V(get_parameters_count() > 0, NULL); - return invoke_raw(p_object, NULL, r_exc); + ERR_FAIL_COND_V(get_parameters_count() > 0, nullptr); + return invoke_raw(p_object, nullptr, r_exc); } MonoObject *GDMonoMethod::invoke_raw(MonoObject *p_object, void **p_params, MonoException **r_exc) const { - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoObject *ret = GDMonoUtils::runtime_invoke(mono_method, p_object, p_params, &exc); if (exc) { - ret = NULL; + ret = nullptr; if (r_exc) { *r_exc = exc; } else { @@ -164,19 +165,19 @@ bool GDMonoMethod::has_attribute(GDMonoClass *p_attr_class) { } MonoObject *GDMonoMethod::get_attribute(GDMonoClass *p_attr_class) { - ERR_FAIL_NULL_V(p_attr_class, NULL); + ERR_FAIL_NULL_V(p_attr_class, nullptr); if (!attrs_fetched) fetch_attributes(); if (!attributes) - return NULL; + return nullptr; return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } void GDMonoMethod::fetch_attributes() { - ERR_FAIL_COND(attributes != NULL); + ERR_FAIL_COND(attributes != nullptr); attributes = mono_custom_attrs_from_method(mono_method); attrs_fetched = true; } @@ -244,7 +245,6 @@ void GDMonoMethod::get_parameter_types(Vector<ManagedType> &types) const { } const MethodInfo &GDMonoMethod::get_method_info() { - if (!method_info_fetched) { method_info.name = name; @@ -281,7 +281,7 @@ GDMonoMethod::GDMonoMethod(StringName p_name, MonoMethod *p_method) { method_info_fetched = false; attrs_fetched = false; - attributes = NULL; + attributes = nullptr; _update_signature(); } diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h index d4379f41fe..f78f57dca0 100644 --- a/modules/mono/mono_gd/gd_mono_method.h +++ b/modules/mono/mono_gd/gd_mono_method.h @@ -36,7 +36,6 @@ #include "i_mono_class_member.h" class GDMonoMethod : public IMonoClassMember { - StringName name; int params_count; @@ -76,9 +75,9 @@ public: _FORCE_INLINE_ int get_parameters_count() const { return params_count; } _FORCE_INLINE_ ManagedType get_return_type() const { return return_type; } - MonoObject *invoke(MonoObject *p_object, const Variant **p_params, MonoException **r_exc = NULL) const; - MonoObject *invoke(MonoObject *p_object, MonoException **r_exc = NULL) const; - MonoObject *invoke_raw(MonoObject *p_object, void **p_params, MonoException **r_exc = NULL) const; + MonoObject *invoke(MonoObject *p_object, const Variant **p_params, MonoException **r_exc = nullptr) const; + MonoObject *invoke(MonoObject *p_object, MonoException **r_exc = nullptr) const; + MonoObject *invoke_raw(MonoObject *p_object, void **p_params, MonoException **r_exc = nullptr) const; String get_full_name(bool p_signature = false) const; String get_full_name_no_class() const; diff --git a/modules/mono/mono_gd/gd_mono_method_thunk.h b/modules/mono/mono_gd/gd_mono_method_thunk.h index d8c9a5eb02..01f3ae342a 100644 --- a/modules/mono/mono_gd/gd_mono_method_thunk.h +++ b/modules/mono/mono_gd/gd_mono_method_thunk.h @@ -39,7 +39,7 @@ #include "gd_mono_method.h" #include "gd_mono_utils.h" -#if !defined(JAVASCRIPT_ENABLED) +#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED) #define HAVE_METHOD_THUNKS #endif @@ -47,10 +47,9 @@ template <class... ParamTypes> struct GDMonoMethodThunk { - typedef void(GD_MONO_STDCALL *M)(ParamTypes... p_args, MonoException **); - M mono_method_thunk; + M mono_method_thunk = nullptr; public: _FORCE_INLINE_ void invoke(ParamTypes... p_args, MonoException **r_exc) { @@ -60,16 +59,16 @@ public: } _FORCE_INLINE_ bool is_null() { - return mono_method_thunk == NULL; + return mono_method_thunk == nullptr; } _FORCE_INLINE_ void nullify() { - mono_method_thunk = NULL; + mono_method_thunk = nullptr; } _FORCE_INLINE_ void set_from_method(GDMonoMethod *p_mono_method) { #ifdef DEBUG_ENABLED - CRASH_COND(p_mono_method == NULL); + CRASH_COND(p_mono_method == nullptr); CRASH_COND(p_mono_method->get_return_type().type_encoding != MONO_TYPE_VOID); if (p_mono_method->is_static()) { @@ -81,9 +80,7 @@ public: mono_method_thunk = (M)mono_method_get_unmanaged_thunk(p_mono_method->get_mono_ptr()); } - GDMonoMethodThunk() : - mono_method_thunk(NULL) { - } + GDMonoMethodThunk() {} explicit GDMonoMethodThunk(GDMonoMethod *p_mono_method) { set_from_method(p_mono_method); @@ -92,10 +89,9 @@ public: template <class R, class... ParamTypes> struct GDMonoMethodThunkR { - typedef R(GD_MONO_STDCALL *M)(ParamTypes... p_args, MonoException **); - M mono_method_thunk; + M mono_method_thunk = nullptr; public: _FORCE_INLINE_ R invoke(ParamTypes... p_args, MonoException **r_exc) { @@ -106,16 +102,16 @@ public: } _FORCE_INLINE_ bool is_null() { - return mono_method_thunk == NULL; + return mono_method_thunk == nullptr; } _FORCE_INLINE_ void nullify() { - mono_method_thunk = NULL; + mono_method_thunk = nullptr; } _FORCE_INLINE_ void set_from_method(GDMonoMethod *p_mono_method) { #ifdef DEBUG_ENABLED - CRASH_COND(p_mono_method == NULL); + CRASH_COND(p_mono_method == nullptr); CRASH_COND(p_mono_method->get_return_type().type_encoding == MONO_TYPE_VOID); if (p_mono_method->is_static()) { @@ -127,13 +123,11 @@ public: mono_method_thunk = (M)mono_method_get_unmanaged_thunk(p_mono_method->get_mono_ptr()); } - GDMonoMethodThunkR() : - mono_method_thunk(NULL) { - } + GDMonoMethodThunkR() {} explicit GDMonoMethodThunkR(GDMonoMethod *p_mono_method) { #ifdef DEBUG_ENABLED - CRASH_COND(p_mono_method == NULL); + CRASH_COND(p_mono_method == nullptr); #endif mono_method_thunk = (M)mono_method_get_unmanaged_thunk(p_mono_method->get_mono_ptr()); } @@ -146,7 +140,7 @@ struct VariadicInvokeMonoMethodImpl { static void invoke(GDMonoMethod *p_mono_method, P1 p_arg1, ParamTypes... p_args, MonoException **r_exc) { if (p_mono_method->is_static()) { void *args[ThunkParamCount] = { p_arg1, p_args... }; - p_mono_method->invoke_raw(NULL, args, r_exc); + p_mono_method->invoke_raw(nullptr, args, r_exc); } else { void *args[ThunkParamCount] = { p_args... }; p_mono_method->invoke_raw((MonoObject *)p_arg1, args, r_exc); @@ -167,7 +161,7 @@ struct VariadicInvokeMonoMethod<0> { #ifdef DEBUG_ENABLED CRASH_COND(!p_mono_method->is_static()); #endif - p_mono_method->invoke_raw(NULL, NULL, r_exc); + p_mono_method->invoke_raw(nullptr, nullptr, r_exc); } }; @@ -176,9 +170,9 @@ struct VariadicInvokeMonoMethod<1, P1> { static void invoke(GDMonoMethod *p_mono_method, P1 p_arg1, MonoException **r_exc) { if (p_mono_method->is_static()) { void *args[1] = { p_arg1 }; - p_mono_method->invoke_raw(NULL, args, r_exc); + p_mono_method->invoke_raw(nullptr, args, r_exc); } else { - p_mono_method->invoke_raw((MonoObject *)p_arg1, NULL, r_exc); + p_mono_method->invoke_raw((MonoObject *)p_arg1, nullptr, r_exc); } } }; @@ -203,7 +197,7 @@ struct VariadicInvokeMonoMethodRImpl { static R invoke(GDMonoMethod *p_mono_method, P1 p_arg1, ParamTypes... p_args, MonoException **r_exc) { if (p_mono_method->is_static()) { void *args[ThunkParamCount] = { p_arg1, p_args... }; - MonoObject *r = p_mono_method->invoke_raw(NULL, args, r_exc); + MonoObject *r = p_mono_method->invoke_raw(nullptr, args, r_exc); return unbox_if_needed<R>(r, p_mono_method->get_return_type()); } else { void *args[ThunkParamCount] = { p_args... }; @@ -226,7 +220,7 @@ struct VariadicInvokeMonoMethodR<0, R> { #ifdef DEBUG_ENABLED CRASH_COND(!p_mono_method->is_static()); #endif - MonoObject *r = p_mono_method->invoke_raw(NULL, NULL, r_exc); + MonoObject *r = p_mono_method->invoke_raw(nullptr, nullptr, r_exc); return unbox_if_needed<R>(r, p_mono_method->get_return_type()); } }; @@ -236,10 +230,10 @@ struct VariadicInvokeMonoMethodR<1, R, P1> { static R invoke(GDMonoMethod *p_mono_method, P1 p_arg1, MonoException **r_exc) { if (p_mono_method->is_static()) { void *args[1] = { p_arg1 }; - MonoObject *r = p_mono_method->invoke_raw(NULL, args, r_exc); + MonoObject *r = p_mono_method->invoke_raw(nullptr, args, r_exc); return unbox_if_needed<R>(r, p_mono_method->get_return_type()); } else { - MonoObject *r = p_mono_method->invoke_raw((MonoObject *)p_arg1, NULL, r_exc); + MonoObject *r = p_mono_method->invoke_raw((MonoObject *)p_arg1, nullptr, r_exc); return unbox_if_needed<R>(r, p_mono_method->get_return_type()); } } @@ -247,8 +241,7 @@ struct VariadicInvokeMonoMethodR<1, R, P1> { template <class... ParamTypes> struct GDMonoMethodThunk { - - GDMonoMethod *mono_method; + GDMonoMethod *mono_method = nullptr; public: _FORCE_INLINE_ void invoke(ParamTypes... p_args, MonoException **r_exc) { @@ -256,16 +249,16 @@ public: } _FORCE_INLINE_ bool is_null() { - return mono_method == NULL; + return mono_method == nullptr; } _FORCE_INLINE_ void nullify() { - mono_method = NULL; + mono_method = nullptr; } _FORCE_INLINE_ void set_from_method(GDMonoMethod *p_mono_method) { #ifdef DEBUG_ENABLED - CRASH_COND(p_mono_method == NULL); + CRASH_COND(p_mono_method == nullptr); CRASH_COND(p_mono_method->get_return_type().type_encoding != MONO_TYPE_VOID); if (p_mono_method->is_static()) { @@ -277,9 +270,7 @@ public: mono_method = p_mono_method; } - GDMonoMethodThunk() : - mono_method(NULL) { - } + GDMonoMethodThunk() {} explicit GDMonoMethodThunk(GDMonoMethod *p_mono_method) { set_from_method(p_mono_method); @@ -288,8 +279,7 @@ public: template <class R, class... ParamTypes> struct GDMonoMethodThunkR { - - GDMonoMethod *mono_method; + GDMonoMethod *mono_method = nullptr; public: _FORCE_INLINE_ R invoke(ParamTypes... p_args, MonoException **r_exc) { @@ -297,16 +287,16 @@ public: } _FORCE_INLINE_ bool is_null() { - return mono_method == NULL; + return mono_method == nullptr; } _FORCE_INLINE_ void nullify() { - mono_method = NULL; + mono_method = nullptr; } _FORCE_INLINE_ void set_from_method(GDMonoMethod *p_mono_method) { #ifdef DEBUG_ENABLED - CRASH_COND(p_mono_method == NULL); + CRASH_COND(p_mono_method == nullptr); CRASH_COND(p_mono_method->get_return_type().type_encoding == MONO_TYPE_VOID); if (p_mono_method->is_static()) { @@ -318,9 +308,7 @@ public: mono_method = p_mono_method; } - GDMonoMethodThunkR() : - mono_method(NULL) { - } + GDMonoMethodThunkR() {} explicit GDMonoMethodThunkR(GDMonoMethod *p_mono_method) { set_from_method(p_mono_method); diff --git a/modules/mono/mono_gd/gd_mono_property.cpp b/modules/mono/mono_gd/gd_mono_property.cpp index 3b5ce58d80..c3e7598f2d 100644 --- a/modules/mono/mono_gd/gd_mono_property.cpp +++ b/modules/mono/mono_gd/gd_mono_property.cpp @@ -57,7 +57,7 @@ GDMonoProperty::GDMonoProperty(MonoProperty *p_mono_property, GDMonoClass *p_own MonoMethodSignature *setter_sig = mono_method_signature(prop_method); - void *iter = NULL; + void *iter = nullptr; MonoType *param_raw_type = mono_signature_get_params(setter_sig, &iter); type.type_encoding = mono_type_get_type(param_raw_type); @@ -66,7 +66,7 @@ GDMonoProperty::GDMonoProperty(MonoProperty *p_mono_property, GDMonoClass *p_own } attrs_fetched = false; - attributes = NULL; + attributes = nullptr; } GDMonoProperty::~GDMonoProperty() { @@ -77,17 +77,17 @@ GDMonoProperty::~GDMonoProperty() { bool GDMonoProperty::is_static() { MonoMethod *prop_method = mono_property_get_get_method(mono_property); - if (prop_method == NULL) + if (prop_method == nullptr) prop_method = mono_property_get_set_method(mono_property); - return mono_method_get_flags(prop_method, NULL) & MONO_METHOD_ATTR_STATIC; + return mono_method_get_flags(prop_method, nullptr) & MONO_METHOD_ATTR_STATIC; } IMonoClassMember::Visibility GDMonoProperty::get_visibility() { MonoMethod *prop_method = mono_property_get_get_method(mono_property); - if (prop_method == NULL) + if (prop_method == nullptr) prop_method = mono_property_get_set_method(mono_property); - switch (mono_method_get_flags(prop_method, NULL) & MONO_METHOD_ATTR_ACCESS_MASK) { + switch (mono_method_get_flags(prop_method, nullptr) & MONO_METHOD_ATTR_ACCESS_MASK) { case MONO_METHOD_ATTR_PRIVATE: return IMonoClassMember::PRIVATE; case MONO_METHOD_ATTR_FAM_AND_ASSEM: @@ -116,36 +116,36 @@ bool GDMonoProperty::has_attribute(GDMonoClass *p_attr_class) { } MonoObject *GDMonoProperty::get_attribute(GDMonoClass *p_attr_class) { - ERR_FAIL_NULL_V(p_attr_class, NULL); + ERR_FAIL_NULL_V(p_attr_class, nullptr); if (!attrs_fetched) fetch_attributes(); if (!attributes) - return NULL; + return nullptr; return mono_custom_attrs_get_attr(attributes, p_attr_class->get_mono_ptr()); } void GDMonoProperty::fetch_attributes() { - ERR_FAIL_COND(attributes != NULL); + ERR_FAIL_COND(attributes != nullptr); attributes = mono_custom_attrs_from_property(owner->get_mono_ptr(), mono_property); attrs_fetched = true; } bool GDMonoProperty::has_getter() { - return mono_property_get_get_method(mono_property) != NULL; + return mono_property_get_get_method(mono_property) != nullptr; } bool GDMonoProperty::has_setter() { - return mono_property_get_set_method(mono_property) != NULL; + return mono_property_get_set_method(mono_property) != nullptr; } void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) { MonoMethod *prop_method = mono_property_get_set_method(mono_property); MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), 1); mono_array_setref(params, 0, p_value); - MonoException *exc = NULL; + MonoException *exc = nullptr; GDMonoUtils::runtime_invoke_array(prop_method, p_object, params, &exc); if (exc) { if (r_exc) { @@ -157,7 +157,7 @@ void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoEx } void GDMonoProperty::set_value(MonoObject *p_object, void **p_params, MonoException **r_exc) { - MonoException *exc = NULL; + MonoException *exc = nullptr; GDMonoUtils::property_set_value(mono_property, p_object, p_params, &exc); if (exc) { @@ -170,11 +170,11 @@ void GDMonoProperty::set_value(MonoObject *p_object, void **p_params, MonoExcept } MonoObject *GDMonoProperty::get_value(MonoObject *p_object, MonoException **r_exc) { - MonoException *exc = NULL; - MonoObject *ret = GDMonoUtils::property_get_value(mono_property, p_object, NULL, &exc); + MonoException *exc = nullptr; + MonoObject *ret = GDMonoUtils::property_get_value(mono_property, p_object, nullptr, &exc); if (exc) { - ret = NULL; + ret = nullptr; if (r_exc) { *r_exc = exc; } else { diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h index 2aec64f565..611ac293e4 100644 --- a/modules/mono/mono_gd/gd_mono_property.h +++ b/modules/mono/mono_gd/gd_mono_property.h @@ -36,7 +36,6 @@ #include "i_mono_class_member.h" class GDMonoProperty : public IMonoClassMember { - GDMonoClass *owner; MonoProperty *mono_property; @@ -65,9 +64,9 @@ public: _FORCE_INLINE_ ManagedType get_type() const { return type; } - void set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc = NULL); - void set_value(MonoObject *p_object, void **p_params, MonoException **r_exc = NULL); - MonoObject *get_value(MonoObject *p_object, MonoException **r_exc = NULL); + void set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc = nullptr); + void set_value(MonoObject *p_object, void **p_params, MonoException **r_exc = nullptr); + MonoObject *get_value(MonoObject *p_object, MonoException **r_exc = nullptr); bool get_bool_value(MonoObject *p_object); int get_int_value(MonoObject *p_object); diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index cdb26ae61b..332744ae6e 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -30,6 +30,7 @@ #include "gd_mono_utils.h" +#include <mono/metadata/debug-helpers.h> #include <mono/metadata/exception.h> #include "core/debugger/engine_debugger.h" @@ -55,9 +56,8 @@ namespace GDMonoUtils { MonoObject *unmanaged_get_managed(Object *unmanaged) { - if (!unmanaged) - return NULL; + return nullptr; if (unmanaged->get_script_instance()) { CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance()); @@ -71,7 +71,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); - ERR_FAIL_NULL_V(data, NULL); + ERR_FAIL_NULL_V(data, nullptr); CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value(); @@ -82,7 +82,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { // Already had a binding that needs to be setup CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged); - ERR_FAIL_COND_V(!script_binding.inited, NULL); + ERR_FAIL_COND_V(!script_binding.inited, nullptr); } } @@ -99,11 +99,11 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { #ifdef DEBUG_ENABLED CRASH_COND(script_binding.type_name == StringName()); - CRASH_COND(script_binding.wrapper_class == NULL); + CRASH_COND(script_binding.wrapper_class == nullptr); #endif MonoObject *mono_object = GDMonoUtils::create_managed_for_godot_object(script_binding.wrapper_class, script_binding.type_name, unmanaged); - ERR_FAIL_NULL_V(mono_object, NULL); + ERR_FAIL_NULL_V(mono_object, nullptr); gchandle = MonoGCHandleData::new_strong_handle(mono_object); @@ -127,10 +127,15 @@ void set_main_thread(MonoThread *p_thread) { } MonoThread *attach_current_thread() { - ERR_FAIL_COND_V(!GDMono::get_singleton()->is_runtime_initialized(), NULL); + ERR_FAIL_COND_V(!GDMono::get_singleton()->is_runtime_initialized(), nullptr); MonoDomain *scripts_domain = GDMono::get_singleton()->get_scripts_domain(); +#ifndef GD_MONO_SINGLE_APPDOMAIN MonoThread *mono_thread = mono_thread_attach(scripts_domain ? scripts_domain : mono_get_root_domain()); - ERR_FAIL_NULL_V(mono_thread, NULL); +#else + // The scripts domain is the root domain + MonoThread *mono_thread = mono_thread_attach(scripts_domain); +#endif + ERR_FAIL_NULL_V(mono_thread, nullptr); return mono_thread; } @@ -152,7 +157,7 @@ MonoThread *get_current_thread() { } bool is_thread_attached() { - return mono_domain_get() != NULL; + return mono_domain_get() != nullptr; } uint32_t new_strong_gchandle(MonoObject *p_object) { @@ -174,11 +179,11 @@ void free_gchandle(uint32_t p_gchandle) { void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) { GDMonoMethod *ctor = p_class->get_method(".ctor", 0); ERR_FAIL_NULL(ctor); - ctor->invoke_raw(p_this_obj, NULL, r_exc); + ctor->invoke_raw(p_this_obj, nullptr, r_exc); } bool mono_delegate_equal(MonoDelegate *p_a, MonoDelegate *p_b) { - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoBoolean res = CACHED_METHOD_THUNK(Delegate, Equals).invoke((MonoObject *)p_a, (MonoObject *)p_b, &exc); UNHANDLED_EXCEPTION(exc); return (bool)res; @@ -221,18 +226,18 @@ GDMonoClass *get_class_native_base(GDMonoClass *p_class) { if (assembly == GDMono::get_singleton()->get_editor_api_assembly()) return klass; #endif - } while ((klass = klass->get_parent_class()) != NULL); + } while ((klass = klass->get_parent_class()) != nullptr); - return NULL; + return nullptr; } MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) { bool parent_is_object_class = ClassDB::is_parent_class(p_object->get_class_name(), p_native); - ERR_FAIL_COND_V_MSG(!parent_is_object_class, NULL, + ERR_FAIL_COND_V_MSG(!parent_is_object_class, nullptr, "Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'."); MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr()); - ERR_FAIL_NULL_V(mono_object, NULL); + ERR_FAIL_NULL_V(mono_object, nullptr); CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object); @@ -244,7 +249,7 @@ MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringNa MonoObject *create_managed_from(const StringName &p_from) { MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(StringName)); - ERR_FAIL_NULL_V(mono_object, NULL); + ERR_FAIL_NULL_V(mono_object, nullptr); // Construct GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(StringName)); @@ -256,7 +261,7 @@ MonoObject *create_managed_from(const StringName &p_from) { MonoObject *create_managed_from(const NodePath &p_from) { MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(NodePath)); - ERR_FAIL_NULL_V(mono_object, NULL); + ERR_FAIL_NULL_V(mono_object, nullptr); // Construct GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(NodePath)); @@ -268,7 +273,7 @@ MonoObject *create_managed_from(const NodePath &p_from) { MonoObject *create_managed_from(const RID &p_from) { MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(RID)); - ERR_FAIL_NULL_V(mono_object, NULL); + ERR_FAIL_NULL_V(mono_object, nullptr); // Construct GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(RID)); @@ -280,15 +285,15 @@ MonoObject *create_managed_from(const RID &p_from) { MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) { MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr()); - ERR_FAIL_NULL_V(mono_object, NULL); + ERR_FAIL_NULL_V(mono_object, nullptr); // Search constructor that takes a pointer as parameter MonoMethod *m; - void *iter = NULL; + void *iter = nullptr; while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) { if (strcmp(mono_method_get_name(m), ".ctor") == 0) { MonoMethodSignature *sig = mono_method_signature(m); - void *front = NULL; + void *front = nullptr; if (mono_signature_get_param_count(sig) == 1 && mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) { break; @@ -296,12 +301,12 @@ MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) { } } - CRASH_COND(m == NULL); + CRASH_COND(m == nullptr); Array *new_array = memnew(Array(p_from)); void *args[1] = { &new_array }; - MonoException *exc = NULL; + MonoException *exc = nullptr; GDMonoUtils::runtime_invoke(m, mono_object, args, &exc); UNHANDLED_EXCEPTION(exc); @@ -310,15 +315,15 @@ MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) { MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) { MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr()); - ERR_FAIL_NULL_V(mono_object, NULL); + ERR_FAIL_NULL_V(mono_object, nullptr); // Search constructor that takes a pointer as parameter MonoMethod *m; - void *iter = NULL; + void *iter = nullptr; while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) { if (strcmp(mono_method_get_name(m), ".ctor") == 0) { MonoMethodSignature *sig = mono_method_signature(m); - void *front = NULL; + void *front = nullptr; if (mono_signature_get_param_count(sig) == 1 && mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) { break; @@ -326,12 +331,12 @@ MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) } } - CRASH_COND(m == NULL); + CRASH_COND(m == nullptr); Dictionary *new_dict = memnew(Dictionary(p_from)); void *args[1] = { &new_dict }; - MonoException *exc = NULL; + MonoException *exc = nullptr; GDMonoUtils::runtime_invoke(m, mono_object, args, &exc); UNHANDLED_EXCEPTION(exc); @@ -341,7 +346,7 @@ MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) MonoDomain *create_domain(const String &p_friendly_name) { print_verbose("Mono: Creating domain '" + p_friendly_name + "'..."); - MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), NULL); + MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), nullptr); if (domain) { // Workaround to avoid this exception: @@ -353,6 +358,14 @@ MonoDomain *create_domain(const String &p_friendly_name) { return domain; } +String get_type_desc(MonoType *p_type) { + return mono_type_full_name(p_type); +} + +String get_type_desc(MonoReflectionType *p_reftype) { + return get_type_desc(mono_reflection_type_get_type(p_reftype)); +} + String get_exception_name_and_message(MonoException *p_exc) { String res; @@ -366,7 +379,7 @@ String get_exception_name_and_message(MonoException *p_exc) { res += ": "; MonoProperty *prop = mono_class_get_property_from_name(klass, "Message"); - MonoString *msg = (MonoString *)property_get_value(prop, (MonoObject *)p_exc, NULL, NULL); + MonoString *msg = (MonoString *)property_get_value(prop, (MonoObject *)p_exc, nullptr, nullptr); res += GDMonoMarshal::mono_string_to_godot(msg); return res; @@ -377,7 +390,7 @@ void set_exception_message(MonoException *p_exc, String message) { MonoProperty *prop = mono_class_get_property_from_name(klass, "Message"); MonoString *msg = GDMonoMarshal::mono_string_from_godot(message); void *params[1] = { msg }; - property_set_value(prop, (MonoObject *)p_exc, params, NULL); + property_set_value(prop, (MonoObject *)p_exc, params, nullptr); } void debug_print_unhandled_exception(MonoException *p_exc) { @@ -410,14 +423,14 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) { Vector<ScriptLanguage::StackInfo> si; String exc_msg; - while (p_exc != NULL) { + while (p_exc != nullptr) { GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); MonoBoolean need_file_info = true; void *ctor_args[2] = { p_exc, &need_file_info }; - MonoException *unexpected_exc = NULL; + MonoException *unexpected_exc = nullptr; CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc); if (unexpected_exc) { @@ -426,7 +439,7 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) { } Vector<ScriptLanguage::StackInfo> _si; - if (stack_trace != NULL) { + if (stack_trace != nullptr) { _si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); for (int i = _si.size() - 1; i >= 0; i--) si.insert(0, _si[i]); @@ -436,10 +449,10 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) { GDMonoClass *exc_class = GDMono::get_singleton()->get_class(mono_get_exception_class()); GDMonoProperty *inner_exc_prop = exc_class->get_property("InnerException"); - CRASH_COND(inner_exc_prop == NULL); + CRASH_COND(inner_exc_prop == nullptr); MonoObject *inner_exc = inner_exc_prop->get_value((MonoObject *)p_exc); - if (inner_exc != NULL) + if (inner_exc != nullptr) si.insert(0, separator); p_exc = (MonoException *)inner_exc; @@ -550,9 +563,10 @@ namespace Marshal { #ifdef MONO_GLUE_ENABLED #ifdef TOOLS_ENABLED -#define NO_GLUE_RET(m_ret) \ - { \ - if (!GDMonoCache::cached_data.godot_api_cache_updated) return m_ret; \ +#define NO_GLUE_RET(m_ret) \ + { \ + if (!GDMonoCache::cached_data.godot_api_cache_updated) \ + return m_ret; \ } #else #define NO_GLUE_RET(m_ret) \ @@ -565,7 +579,7 @@ namespace Marshal { bool type_is_generic_array(MonoReflectionType *p_reftype) { NO_GLUE_RET(false); - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray).invoke(p_reftype, &exc); UNHANDLED_EXCEPTION(exc); return (bool)res; @@ -573,94 +587,75 @@ bool type_is_generic_array(MonoReflectionType *p_reftype) { bool type_is_generic_dictionary(MonoReflectionType *p_reftype) { NO_GLUE_RET(false); - MonoException *exc = NULL; + MonoException *exc = nullptr; MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary).invoke(p_reftype, &exc); UNHANDLED_EXCEPTION(exc); return (bool)res; } -void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype) { - MonoException *exc = NULL; - CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType).invoke(p_array_reftype, r_elem_reftype, &exc); - UNHANDLED_EXCEPTION(exc); -} - -void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) { - MonoException *exc = NULL; - CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes).invoke(p_dict_reftype, r_key_reftype, r_value_reftype, &exc); - UNHANDLED_EXCEPTION(exc); -} - -bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype) { +bool type_is_system_generic_list(MonoReflectionType *p_reftype) { NO_GLUE_RET(false); - MonoException *exc = NULL; - MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType).invoke(p_reftype, &exc); + MonoException *exc = nullptr; + MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsSystemGenericList).invoke(p_reftype, &exc); UNHANDLED_EXCEPTION(exc); return (bool)res; } -bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype) { +bool type_is_system_generic_dictionary(MonoReflectionType *p_reftype) { NO_GLUE_RET(false); - MonoException *exc = NULL; - MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType).invoke(p_reftype, &exc); + MonoException *exc = nullptr; + MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsSystemGenericDictionary).invoke(p_reftype, &exc); UNHANDLED_EXCEPTION(exc); return (bool)res; } -bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) { +bool type_is_generic_ienumerable(MonoReflectionType *p_reftype) { NO_GLUE_RET(false); - MonoException *exc = NULL; - MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info).invoke(p_reftype, r_elem_reftype, &exc); + MonoException *exc = nullptr; + MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericIEnumerable).invoke(p_reftype, &exc); UNHANDLED_EXCEPTION(exc); return (bool)res; } -bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) { +bool type_is_generic_icollection(MonoReflectionType *p_reftype) { NO_GLUE_RET(false); - MonoException *exc = NULL; - MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info).invoke(p_reftype, r_key_reftype, r_value_reftype, &exc); + MonoException *exc = nullptr; + MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericICollection).invoke(p_reftype, &exc); UNHANDLED_EXCEPTION(exc); return (bool)res; } -Array enumerable_to_array(MonoObject *p_enumerable) { - NO_GLUE_RET(Array()); - Array result; - MonoException *exc = NULL; - CACHED_METHOD_THUNK(MarshalUtils, EnumerableToArray).invoke(p_enumerable, &result, &exc); +bool type_is_generic_idictionary(MonoReflectionType *p_reftype) { + NO_GLUE_RET(false); + MonoException *exc = nullptr; + MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericIDictionary).invoke(p_reftype, &exc); UNHANDLED_EXCEPTION(exc); - return result; + return (bool)res; } -Dictionary idictionary_to_dictionary(MonoObject *p_idictionary) { - NO_GLUE_RET(Dictionary()); - Dictionary result; - MonoException *exc = NULL; - CACHED_METHOD_THUNK(MarshalUtils, IDictionaryToDictionary).invoke(p_idictionary, &result, &exc); +void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype) { + MonoException *exc = nullptr; + CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType).invoke(p_array_reftype, r_elem_reftype, &exc); UNHANDLED_EXCEPTION(exc); - return result; } -Dictionary generic_idictionary_to_dictionary(MonoObject *p_generic_idictionary) { - NO_GLUE_RET(Dictionary()); - Dictionary result; - MonoException *exc = NULL; - CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryToDictionary).invoke(p_generic_idictionary, &result, &exc); +void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) { + MonoException *exc = nullptr; + CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes).invoke(p_dict_reftype, r_key_reftype, r_value_reftype, &exc); UNHANDLED_EXCEPTION(exc); - return result; } GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype) { - NO_GLUE_RET(NULL); - MonoException *exc = NULL; + NO_GLUE_RET(nullptr); + MonoException *exc = nullptr; MonoReflectionType *reftype = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericArrayType).invoke(p_elem_reftype, &exc); UNHANDLED_EXCEPTION(exc); return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype))); } GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) { - NO_GLUE_RET(NULL); - MonoException *exc = NULL; + NO_GLUE_RET(nullptr); + MonoException *exc = nullptr; MonoReflectionType *reftype = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericDictionaryType).invoke(p_key_reftype, p_value_reftype, &exc); UNHANDLED_EXCEPTION(exc); return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype))); @@ -668,8 +663,7 @@ GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, Mon } // namespace Marshal -ScopeThreadAttach::ScopeThreadAttach() : - mono_thread(NULL) { +ScopeThreadAttach::ScopeThreadAttach() { if (likely(GDMono::get_singleton()->is_runtime_initialized()) && unlikely(!mono_domain_get())) { mono_thread = GDMonoUtils::attach_current_thread(); } @@ -682,7 +676,7 @@ ScopeThreadAttach::~ScopeThreadAttach() { } StringName get_native_godot_class_name(GDMonoClass *p_class) { - MonoObject *native_name_obj = p_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL); + MonoObject *native_name_obj = p_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(nullptr); StringName *ptr = GDMonoMarshal::unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(native_name_obj)); return ptr ? *ptr : StringName(); } diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index fd02907d87..a7ca46f012 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -41,7 +41,7 @@ #include "core/reference.h" #define UNHANDLED_EXCEPTION(m_exc) \ - if (unlikely(m_exc != NULL)) { \ + if (unlikely(m_exc != nullptr)) { \ GDMonoUtils::debug_unhandled_exception(m_exc); \ GD_UNREACHABLE(); \ } @@ -52,22 +52,18 @@ namespace Marshal { bool type_is_generic_array(MonoReflectionType *p_reftype); bool type_is_generic_dictionary(MonoReflectionType *p_reftype); +bool type_is_system_generic_list(MonoReflectionType *p_reftype); +bool type_is_system_generic_dictionary(MonoReflectionType *p_reftype); +bool type_is_generic_ienumerable(MonoReflectionType *p_reftype); +bool type_is_generic_icollection(MonoReflectionType *p_reftype); +bool type_is_generic_idictionary(MonoReflectionType *p_reftype); void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype); void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype); -bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype); -bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype); -bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype); -bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype); - GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype); GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype); -Array enumerable_to_array(MonoObject *p_enumerable); -Dictionary idictionary_to_dictionary(MonoObject *p_idictionary); -Dictionary generic_idictionary_to_dictionary(MonoObject *p_generic_idictionary); - } // namespace Marshal _FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash) { @@ -77,7 +73,7 @@ _FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash) /** * If the object has a csharp script, returns the target of the gchandle stored in the script instance * Otherwise returns a newly constructed MonoObject* which is attached to the object - * Returns NULL on error + * Returns nullptr on error */ MonoObject *unmanaged_get_managed(Object *unmanaged); @@ -89,7 +85,7 @@ MonoThread *get_current_thread(); bool is_thread_attached(); _FORCE_INLINE_ bool is_main_thread() { - return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current(); + return mono_domain_get() != nullptr && mono_thread_get_main() == mono_thread_current(); } uint32_t new_strong_gchandle(MonoObject *p_object); @@ -97,7 +93,7 @@ uint32_t new_strong_gchandle_pinned(MonoObject *p_object); uint32_t new_weak_gchandle(MonoObject *p_object); void free_gchandle(uint32_t p_gchandle); -void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc = NULL); +void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc = nullptr); bool mono_delegate_equal(MonoDelegate *p_a, MonoDelegate *p_b); @@ -115,6 +111,9 @@ MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class); MonoDomain *create_domain(const String &p_friendly_name); +String get_type_desc(MonoType *p_type); +String get_type_desc(MonoReflectionType *p_reftype); + String get_exception_name_and_message(MonoException *p_exc); void set_exception_message(MonoException *p_exc, String message); @@ -135,6 +134,7 @@ extern thread_local int current_invoke_count; _FORCE_INLINE_ int get_runtime_invoke_count() { return current_invoke_count; } + _FORCE_INLINE_ int &get_runtime_invoke_count_ref() { return current_invoke_count; } @@ -156,7 +156,7 @@ struct ScopeThreadAttach { ~ScopeThreadAttach(); private: - MonoThread *mono_thread; + MonoThread *mono_thread = nullptr; }; StringName get_native_godot_class_name(GDMonoClass *p_class); diff --git a/modules/mono/mono_gd/managed_type.h b/modules/mono/mono_gd/managed_type.h index 11b832d0cc..491a2f3d20 100644 --- a/modules/mono/mono_gd/managed_type.h +++ b/modules/mono/mono_gd/managed_type.h @@ -36,18 +36,15 @@ #include "gd_mono_header.h" struct ManagedType { - int type_encoding; - GDMonoClass *type_class; + int type_encoding = 0; + GDMonoClass *type_class = nullptr; static ManagedType from_class(GDMonoClass *p_class); static ManagedType from_class(MonoClass *p_mono_class); static ManagedType from_type(MonoType *p_mono_type); static ManagedType from_reftype(MonoReflectionType *p_mono_reftype); - ManagedType() : - type_encoding(0), - type_class(NULL) { - } + ManagedType() {} ManagedType(int p_type_encoding, GDMonoClass *p_type_class) : type_encoding(p_type_encoding), diff --git a/modules/mono/mono_gd/gd_mono_android.cpp b/modules/mono/mono_gd/support/android_support.cpp index 761368878f..8bcdeec9dd 100644 --- a/modules/mono/mono_gd/gd_mono_android.cpp +++ b/modules/mono/mono_gd/support/android_support.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gd_mono_android.cpp */ +/* android_support.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "gd_mono_android.h" +#include "android_support.h" #if defined(ANDROID_ENABLED) @@ -49,14 +49,16 @@ #include "platform/android/os_android.h" #include "platform/android/thread_jandroid.h" -#include "../utils/path_utils.h" -#include "../utils/string_utils.h" -#include "gd_mono_cache.h" -#include "gd_mono_marshal.h" +#include "../../utils/path_utils.h" +#include "../../utils/string_utils.h" +#include "../gd_mono_cache.h" +#include "../gd_mono_marshal.h" // Warning: JNI boilerplate ahead... continue at your own risk -namespace GDMonoAndroid { +namespace gdmono { +namespace android { +namespace support { template <typename T> struct ScopedLocalRef { @@ -67,7 +69,7 @@ struct ScopedLocalRef { _FORCE_INLINE_ operator T() const { return local_ref; } _FORCE_INLINE_ operator jvalue() const { return (jvalue)local_ref; } - _FORCE_INLINE_ operator bool() const { return local_ref != NULL; } + _FORCE_INLINE_ operator bool() const { return local_ref != nullptr; } _FORCE_INLINE_ bool operator==(std::nullptr_t) const { return local_ref == nullptr; @@ -122,7 +124,7 @@ String determine_app_native_lib_dir() { String result; - const char *const nativeLibraryDirUtf8 = env->GetStringUTFChars(nativeLibraryDir, NULL); + const char *const nativeLibraryDirUtf8 = env->GetStringUTFChars(nativeLibraryDir, nullptr); if (nativeLibraryDirUtf8) { result.parse_utf8(nativeLibraryDirUtf8); env->ReleaseStringUTFChars(nativeLibraryDir, nativeLibraryDirUtf8); @@ -150,21 +152,21 @@ int gd_mono_convert_dl_flags(int flags) { return lflags; } -#ifndef GD_MONO_ANDROID_SO_NAME -#define GD_MONO_ANDROID_SO_NAME "libmonosgen-2.0.so" +#ifndef GD_MONO_SO_NAME +#define GD_MONO_SO_NAME "libmonosgen-2.0.so" #endif -const char *mono_so_name = GD_MONO_ANDROID_SO_NAME; +const char *mono_so_name = GD_MONO_SO_NAME; const char *godot_so_name = "libgodot_android.so"; -void *mono_dl_handle = NULL; -void *godot_dl_handle = NULL; +void *mono_dl_handle = nullptr; +void *godot_dl_handle = nullptr; void *try_dlopen(const String &p_so_path, int p_flags) { if (!FileAccess::exists(p_so_path)) { if (OS::get_singleton()->is_stdout_verbose()) OS::get_singleton()->print("Cannot find shared library: '%s'\n", p_so_path.utf8().get_data()); - return NULL; + return nullptr; } int lflags = gd_mono_convert_dl_flags(p_flags); @@ -174,7 +176,7 @@ void *try_dlopen(const String &p_so_path, int p_flags) { if (!handle) { if (OS::get_singleton()->is_stdout_verbose()) OS::get_singleton()->print("Failed to open shared library: '%s'. Error: '%s'\n", p_so_path.utf8().get_data(), dlerror()); - return NULL; + return nullptr; } if (OS::get_singleton()->is_stdout_verbose()) @@ -184,7 +186,7 @@ void *try_dlopen(const String &p_so_path, int p_flags) { } void *gd_mono_android_dlopen(const char *p_name, int p_flags, char **r_err, void *p_user_data) { - if (p_name == NULL) { + if (p_name == nullptr) { // __Internal if (!mono_dl_handle) { @@ -209,7 +211,7 @@ void *gd_mono_android_dlopen(const char *p_name, int p_flags, char **r_err, void return try_dlopen(so_path, p_flags); } - return NULL; + return nullptr; } void *gd_mono_android_dlsym(void *p_handle, const char *p_name, char **r_err, void *p_user_data) { @@ -230,7 +232,7 @@ void *gd_mono_android_dlsym(void *p_handle, const char *p_name, char **r_err, vo if (r_err) *r_err = str_format_new("%s\n", dlerror()); - return NULL; + return nullptr; } void *gd_mono_android_dlclose(void *p_handle, void *p_user_data) { @@ -238,9 +240,9 @@ void *gd_mono_android_dlclose(void *p_handle, void *p_user_data) { // Not sure if this ever happens. Does Mono close the handle for the main module? if (p_handle == mono_dl_handle) - mono_dl_handle = NULL; + mono_dl_handle = nullptr; - return NULL; + return nullptr; } int32_t build_version_sdk_int = 0; @@ -265,7 +267,7 @@ int32_t get_build_version_sdk_int() { return build_version_sdk_int; } -jobject certStore = NULL; // KeyStore +jobject certStore = nullptr; // KeyStore MonoBoolean _gd_mono_init_cert_store() { // The JNI code is the equivalent of: @@ -293,7 +295,7 @@ MonoBoolean _gd_mono_init_cert_store() { if (jni_exception_check(env)) return 0; - env->CallVoidMethod(certStoreLocal, load, NULL); + env->CallVoidMethod(certStoreLocal, load, nullptr); if (jni_exception_check(env)) return 0; @@ -317,7 +319,7 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) { if (!mono_error_ok(&mono_error)) { ERR_PRINT(String() + "Failed to convert MonoString* to UTF-8: '" + mono_error_get_message(&mono_error) + "'."); mono_error_cleanup(&mono_error); - return NULL; + return nullptr; } JNIEnv *env = ThreadAndroid::get_env(); @@ -326,20 +328,20 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) { mono_free(alias_utf8); ScopedLocalRef<jclass> keyStoreClass(env, env->FindClass("java/security/KeyStore")); - ERR_FAIL_NULL_V(keyStoreClass, NULL); + ERR_FAIL_NULL_V(keyStoreClass, nullptr); ScopedLocalRef<jclass> certificateClass(env, env->FindClass("java/security/cert/Certificate")); - ERR_FAIL_NULL_V(certificateClass, NULL); + ERR_FAIL_NULL_V(certificateClass, nullptr); jmethodID getCertificate = env->GetMethodID(keyStoreClass, "getCertificate", "(Ljava/lang/String;)Ljava/security/cert/Certificate;"); - ERR_FAIL_NULL_V(getCertificate, NULL); + ERR_FAIL_NULL_V(getCertificate, nullptr); jmethodID getEncoded = env->GetMethodID(certificateClass, "getEncoded", "()[B"); - ERR_FAIL_NULL_V(getEncoded, NULL); + ERR_FAIL_NULL_V(getEncoded, nullptr); ScopedLocalRef<jobject> certificate(env, env->CallObjectMethod(certStore, getCertificate, js_alias.get())); if (!certificate) - return NULL; + return nullptr; ScopedLocalRef<jbyteArray> encoded(env, (jbyteArray)env->CallObjectMethod(certificate, getEncoded)); jsize encodedLength = env->GetArrayLength(encoded); @@ -352,11 +354,16 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) { return encoded_ret; } +void register_internal_calls() { + mono_add_internal_call("Android.Runtime.AndroidEnvironment::_gd_mono_init_cert_store", (void *)_gd_mono_init_cert_store); + mono_add_internal_call("Android.Runtime.AndroidEnvironment::_gd_mono_android_cert_store_lookup", (void *)_gd_mono_android_cert_store_lookup); +} + void initialize() { // We need to set this environment variable to make the monodroid BCL use btls instead of legacy as the default provider OS::get_singleton()->set_environment("XA_TLS_PROVIDER", "btls"); - mono_dl_fallback_register(gd_mono_android_dlopen, gd_mono_android_dlsym, gd_mono_android_dlclose, NULL); + mono_dl_fallback_register(gd_mono_android_dlopen, gd_mono_android_dlsym, gd_mono_android_dlclose, nullptr); String app_native_lib_dir = get_app_native_lib_dir(); String so_path = path::join(app_native_lib_dir, godot_so_name); @@ -364,31 +371,28 @@ void initialize() { godot_dl_handle = try_dlopen(so_path, gd_mono_convert_dl_flags(MONO_DL_LAZY)); } -void register_internal_calls() { - mono_add_internal_call("Android.Runtime.AndroidEnvironment::_gd_mono_init_cert_store", (void *)_gd_mono_init_cert_store); - mono_add_internal_call("Android.Runtime.AndroidEnvironment::_gd_mono_android_cert_store_lookup", (void *)_gd_mono_android_cert_store_lookup); -} - void cleanup() { // This is called after shutting down the Mono runtime if (mono_dl_handle) - gd_mono_android_dlclose(mono_dl_handle, NULL); + gd_mono_android_dlclose(mono_dl_handle, nullptr); if (godot_dl_handle) - gd_mono_android_dlclose(godot_dl_handle, NULL); + gd_mono_android_dlclose(godot_dl_handle, nullptr); JNIEnv *env = ThreadAndroid::get_env(); if (certStore) { env->DeleteGlobalRef(certStore); - certStore = NULL; + certStore = nullptr; } } -} // namespace GDMonoAndroid +} // namespace support +} // namespace android +} // namespace gdmono -using namespace GDMonoAndroid; +using namespace gdmono::android::support; // The following are P/Invoke functions required by the monodroid profile of the BCL. // These are P/Invoke functions and not internal calls, hence why they use @@ -417,7 +421,7 @@ GD_PINVOKE_EXPORT int32_t monodroid_get_system_property(const char *p_name, char memcpy(*r_value, prop_value_str, len); (*r_value)[len] = '\0'; } else { - *r_value = NULL; + *r_value = nullptr; } } @@ -604,7 +608,7 @@ GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array) if (!r_dns_servers_array) return -1; - *r_dns_servers_array = NULL; + *r_dns_servers_array = nullptr; char *dns_servers[dns_servers_len]; int dns_servers_count = 0; @@ -648,23 +652,23 @@ GD_PINVOKE_EXPORT const char *_monodroid_timezone_get_default_id() { JNIEnv *env = ThreadAndroid::get_env(); ScopedLocalRef<jclass> timeZoneClass(env, env->FindClass("java/util/TimeZone")); - ERR_FAIL_NULL_V(timeZoneClass, NULL); + ERR_FAIL_NULL_V(timeZoneClass, nullptr); jmethodID getDefault = env->GetStaticMethodID(timeZoneClass, "getDefault", "()Ljava/util/TimeZone;"); - ERR_FAIL_NULL_V(getDefault, NULL); + ERR_FAIL_NULL_V(getDefault, nullptr); jmethodID getID = env->GetMethodID(timeZoneClass, "getID", "()Ljava/lang/String;"); - ERR_FAIL_NULL_V(getID, NULL); + ERR_FAIL_NULL_V(getID, nullptr); ScopedLocalRef<jobject> defaultTimeZone(env, env->CallStaticObjectMethod(timeZoneClass, getDefault)); if (!defaultTimeZone) - return NULL; + return nullptr; ScopedLocalRef<jstring> defaultTimeZoneID(env, (jstring)env->CallObjectMethod(defaultTimeZone, getID)); if (!defaultTimeZoneID) - return NULL; + return nullptr; const char *default_time_zone_id = env->GetStringUTFChars(defaultTimeZoneID, 0); diff --git a/modules/mono/mono_gd/gd_mono_android.h b/modules/mono/mono_gd/support/android_support.h index 0e04847924..dc2e6c95ed 100644..100755 --- a/modules/mono/mono_gd/gd_mono_android.h +++ b/modules/mono/mono_gd/support/android_support.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gd_mono_android.h */ +/* android_support.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,25 +28,28 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GD_MONO_ANDROID_H -#define GD_MONO_ANDROID_H +#ifndef ANDROID_SUPPORT_H +#define ANDROID_SUPPORT_H #if defined(ANDROID_ENABLED) #include "core/ustring.h" -namespace GDMonoAndroid { +namespace gdmono { +namespace android { +namespace support { String get_app_native_lib_dir(); void initialize(); +void cleanup(); void register_internal_calls(); -void cleanup(); - -} // namespace GDMonoAndroid +} // namespace support +} // namespace android +} // namespace gdmono #endif // ANDROID_ENABLED -#endif // GD_MONO_ANDROID_H +#endif // ANDROID_SUPPORT_H diff --git a/modules/mono/mono_gd/support/ios_support.h b/modules/mono/mono_gd/support/ios_support.h new file mode 100755 index 0000000000..e28af120e3 --- /dev/null +++ b/modules/mono/mono_gd/support/ios_support.h @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* ios_support.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef IOS_SUPPORT_H +#define IOS_SUPPORT_H + +#if defined(IPHONE_ENABLED) + +#include "core/ustring.h" + +namespace gdmono { +namespace ios { +namespace support { + +void initialize(); +void cleanup(); + +} // namespace support +} // namespace ios +} // namespace gdmono + +#endif // IPHONE_ENABLED + +#endif // IOS_SUPPORT_H diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm new file mode 100644 index 0000000000..e3d1a647fd --- /dev/null +++ b/modules/mono/mono_gd/support/ios_support.mm @@ -0,0 +1,151 @@ +/*************************************************************************/ +/* ios_support.mm */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "ios_support.h" + +#if defined(IPHONE_ENABLED) + +#import <Foundation/Foundation.h> +#include <os/log.h> + +#include "core/ustring.h" + +#include "../gd_mono_marshal.h" + +// Implemented mostly following: https://github.com/mono/mono/blob/master/sdks/ios/app/runtime.m + +// Definition generated by the Godot exporter +extern "C" void gd_mono_setup_aot(); + +namespace gdmono { +namespace ios { +namespace support { + +void ios_mono_log_callback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data) { + os_log_info(OS_LOG_DEFAULT, "(%s %s) %s", log_domain, log_level, message); + if (fatal) { + os_log_info(OS_LOG_DEFAULT, "Exit code: %d.", 1); + exit(1); + } +} + +void initialize() { + mono_dllmap_insert(NULL, "System.Native", NULL, "__Internal", NULL); + mono_dllmap_insert(NULL, "System.IO.Compression.Native", NULL, "__Internal", NULL); + mono_dllmap_insert(NULL, "System.Security.Cryptography.Native.Apple", NULL, "__Internal", NULL); + +#ifdef IOS_DEVICE + // This function is defined in an auto-generated source file + gd_mono_setup_aot(); +#endif + + mono_set_signal_chaining(true); + mono_set_crash_chaining(true); +} + +void cleanup() { +} + +} // namespace support +} // namespace ios +} // namespace gdmono + +// The following are P/Invoke functions required by the monotouch profile of the BCL. +// These are P/Invoke functions and not internal calls, hence why they use +// 'mono_bool' and 'const char*' instead of 'MonoBoolean' and 'MonoString*'. + +#define GD_PINVOKE_EXPORT extern "C" __attribute__((visibility("default"))) + +GD_PINVOKE_EXPORT const char *xamarin_get_locale_country_code() { + NSLocale *locale = [NSLocale currentLocale]; + NSString *countryCode = [locale objectForKey:NSLocaleCountryCode]; + if (countryCode == NULL) { + return strdup("US"); + } + return strdup([countryCode UTF8String]); +} + +GD_PINVOKE_EXPORT void xamarin_log(const uint16_t *p_unicode_message) { + int length = 0; + const uint16_t *ptr = p_unicode_message; + while (*ptr++) + length += sizeof(uint16_t); + NSString *msg = [[NSString alloc] initWithBytes:p_unicode_message length:length encoding:NSUTF16LittleEndianStringEncoding]; + + os_log_info(OS_LOG_DEFAULT, "%{public}@", msg); +} + +GD_PINVOKE_EXPORT const char *xamarin_GetFolderPath(int p_folder) { + NSSearchPathDirectory dd = (NSSearchPathDirectory)p_folder; + NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:dd inDomains:NSUserDomainMask] lastObject]; + NSString *path = [url path]; + return strdup([path UTF8String]); +} + +GD_PINVOKE_EXPORT char *xamarin_timezone_get_local_name() { + NSTimeZone *tz = nil; + tz = [NSTimeZone localTimeZone]; + NSString *name = [tz name]; + return (name != nil) ? strdup([name UTF8String]) : strdup("Local"); +} + +GD_PINVOKE_EXPORT char **xamarin_timezone_get_names(uint32_t *p_count) { + NSArray *array = [NSTimeZone knownTimeZoneNames]; + *p_count = array.count; + char **result = (char **)malloc(sizeof(char *) * (*p_count)); + for (uint32_t i = 0; i < *p_count; i++) { + NSString *s = [array objectAtIndex:i]; + result[i] = strdup(s.UTF8String); + } + return result; +} + +GD_PINVOKE_EXPORT void *xamarin_timezone_get_data(const char *p_name, uint32_t *p_size) { // FIXME: uint32_t since Dec 2019, unsigned long before + NSTimeZone *tz = nil; + if (p_name) { + NSString *n = [[NSString alloc] initWithUTF8String:p_name]; + tz = [[[NSTimeZone alloc] initWithName:n] autorelease]; + [n release]; + } else { + tz = [NSTimeZone localTimeZone]; + } + NSData *data = [tz data]; + *p_size = [data length]; + void *result = malloc(*p_size); + memcpy(result, data.bytes, *p_size); + return result; +} + +GD_PINVOKE_EXPORT void xamarin_start_wwan(const char *p_uri) { + // FIXME: What's this for? No idea how to implement. + os_log_error(OS_LOG_DEFAULT, "Not implemented: 'xamarin_start_wwan'"); +} + +#endif // IPHONE_ENABLED diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp index 4823ba3679..94431e7c30 100644 --- a/modules/mono/register_types.cpp +++ b/modules/mono/register_types.cpp @@ -34,11 +34,11 @@ #include "csharp_script.h" -CSharpLanguage *script_language_cs = NULL; +CSharpLanguage *script_language_cs = nullptr; Ref<ResourceFormatLoaderCSharpScript> resource_loader_cs; Ref<ResourceFormatSaverCSharpScript> resource_saver_cs; -_GodotSharp *_godotsharp = NULL; +_GodotSharp *_godotsharp = nullptr; void register_mono_types() { ClassDB::register_class<CSharpScript>(); diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index 25e5a41215..ed0dc5cc28 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -77,7 +77,6 @@ String SignalAwaiterCallable::get_as_text() const { String class_name = base->get_class(); Ref<Script> script = base->get_script(); if (script.is_valid() && script->get_path().is_resource_file()) { - class_name += "(" + script->get_path().get_file() + ")"; } return class_name + "::SignalAwaiterMiddleman::" + String(signal); @@ -121,7 +120,7 @@ void SignalAwaiterCallable::call(const Variant **p_arguments, int p_argcount, Va return; } - MonoException *exc = NULL; + MonoException *exc = nullptr; CACHED_METHOD_THUNK(SignalAwaiter, SignalCallback).invoke(awaiter, signal_args, &exc); if (exc) { @@ -210,7 +209,7 @@ void EventSignalCallable::call(const Variant **p_arguments, int p_argcount, Vari return; } - MonoException *exc = NULL; + MonoException *exc = nullptr; event_signal->invoke_method->invoke(delegate_field_value, p_arguments, &exc); if (exc) { diff --git a/modules/mono/utils/macros.h b/modules/mono/utils/macros.h index 8650d6cc09..dc542477f5 100644 --- a/modules/mono/utils/macros.h +++ b/modules/mono/utils/macros.h @@ -68,6 +68,6 @@ public: } // namespace gdmono #define SCOPE_EXIT \ - auto GD_UNIQUE_NAME(gd_scope_exit) = gdmono::ScopeExitAux() + [=]() + auto GD_UNIQUE_NAME(gd_scope_exit) = gdmono::ScopeExitAux() + [=]() -> void #endif // UTIL_MACROS_H diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp index c1cd5f1db4..1b4fe68582 100644 --- a/modules/mono/utils/mono_reg_utils.cpp +++ b/modules/mono/utils/mono_reg_utils.cpp @@ -58,7 +58,6 @@ REGSAM _get_bitness_sam() { } LONG _RegOpenKey(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult) { - LONG res = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ, phkResult); if (res != ERROR_SUCCESS) @@ -68,18 +67,17 @@ LONG _RegOpenKey(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult) { } LONG _RegKeyQueryString(HKEY hKey, const String &p_value_name, String &r_value) { - Vector<WCHAR> buffer; buffer.resize(512); DWORD dwBufferSize = buffer.size(); - LONG res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, NULL, (LPBYTE)buffer.ptr(), &dwBufferSize); + LONG res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize); if (res == ERROR_MORE_DATA) { // dwBufferSize now contains the actual size Vector<WCHAR> buffer; buffer.resize(dwBufferSize); - res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, NULL, (LPBYTE)buffer.ptr(), &dwBufferSize); + res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize); } if (res == ERROR_SUCCESS) { @@ -92,7 +90,6 @@ LONG _RegKeyQueryString(HKEY hKey, const String &p_value_name, String &r_value) } LONG _find_mono_in_reg(const String &p_subkey, MonoRegInfo &r_info, bool p_old_reg = false) { - HKEY hKey; LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, p_subkey.c_str(), &hKey); @@ -128,7 +125,6 @@ cleanup: } LONG _find_mono_in_reg_old(const String &p_subkey, MonoRegInfo &r_info) { - String default_clr; HKEY hKey; @@ -150,7 +146,6 @@ cleanup: } MonoRegInfo find_mono() { - MonoRegInfo info; if (_find_mono_in_reg("Software\\Mono", info) == ERROR_SUCCESS) @@ -163,7 +158,6 @@ MonoRegInfo find_mono() { } String find_msbuild_tools_path() { - String msbuild_tools_path; // Try to find 15.0 with vswhere @@ -180,7 +174,7 @@ String find_msbuild_tools_path() { String output; int exit_code; - OS::get_singleton()->execute(vswhere_path, vswhere_args, true, NULL, &output, &exit_code); + OS::get_singleton()->execute(vswhere_path, vswhere_args, true, nullptr, &output, &exit_code); if (exit_code == 0) { Vector<String> lines = output.split("\n"); @@ -232,6 +226,7 @@ cleanup: return msbuild_tools_path; } + } // namespace MonoRegUtils #endif // WINDOWS_ENABLED diff --git a/modules/mono/utils/mono_reg_utils.h b/modules/mono/utils/mono_reg_utils.h index f844a7233a..4ef876f2b6 100644 --- a/modules/mono/utils/mono_reg_utils.h +++ b/modules/mono/utils/mono_reg_utils.h @@ -36,7 +36,6 @@ #include "core/ustring.h" struct MonoRegInfo { - String version; String install_root_dir; String assembly_dir; diff --git a/modules/mono/utils/osx_utils.cpp b/modules/mono/utils/osx_utils.cpp index 432b306414..8e3e51e688 100644 --- a/modules/mono/utils/osx_utils.cpp +++ b/modules/mono/utils/osx_utils.cpp @@ -38,10 +38,9 @@ #include <CoreServices/CoreServices.h> bool osx_is_app_bundle_installed(const String &p_bundle_id) { - - CFURLRef app_url = NULL; - CFStringRef bundle_id = CFStringCreateWithCString(NULL, p_bundle_id.utf8(), kCFStringEncodingUTF8); - OSStatus result = LSFindApplicationForInfo(kLSUnknownCreator, bundle_id, NULL, NULL, &app_url); + CFURLRef app_url = nullptr; + CFStringRef bundle_id = CFStringCreateWithCString(nullptr, p_bundle_id.utf8(), kCFStringEncodingUTF8); + OSStatus result = LSFindApplicationForInfo(kLSUnknownCreator, bundle_id, nullptr, nullptr, &app_url); CFRelease(bundle_id); if (app_url) diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index 545da6c79e..973375a471 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -80,7 +80,7 @@ String find_executable(const String &p_name) { String cwd() { #ifdef WINDOWS_ENABLED - const DWORD expected_size = ::GetCurrentDirectoryW(0, NULL); + const DWORD expected_size = ::GetCurrentDirectoryW(0, nullptr); String buffer; buffer.resize((int)expected_size); @@ -90,7 +90,7 @@ String cwd() { return buffer.simplify_path(); #else char buffer[PATH_MAX]; - if (::getcwd(buffer, sizeof(buffer)) == NULL) + if (::getcwd(buffer, sizeof(buffer)) == nullptr) return "."; String result; @@ -114,12 +114,12 @@ String realpath(const String &p_path) { // Open file without read/write access HANDLE hFile = ::CreateFileW(p_path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile == INVALID_HANDLE_VALUE) return p_path; - const DWORD expected_size = ::GetFinalPathNameByHandleW(hFile, NULL, 0, FILE_NAME_NORMALIZED); + const DWORD expected_size = ::GetFinalPathNameByHandleW(hFile, nullptr, 0, FILE_NAME_NORMALIZED); if (expected_size == 0) { ::CloseHandle(hFile); @@ -133,7 +133,7 @@ String realpath(const String &p_path) { ::CloseHandle(hFile); return buffer.simplify_path(); #elif UNIX_ENABLED - char *resolved_path = ::realpath(p_path.utf8().get_data(), NULL); + char *resolved_path = ::realpath(p_path.utf8().get_data(), nullptr); if (!resolved_path) return p_path; diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index 49c4fb3f73..da1b719d99 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -81,6 +81,7 @@ int sfind(const String &p_text, int p_from) { return -1; } + } // namespace String sformat(const String &p_text, const Variant &p1, const Variant &p2, const Variant &p3, const Variant &p4, const Variant &p5) { @@ -132,7 +133,6 @@ String sformat(const String &p_text, const Variant &p1, const Variant &p2, const #ifdef TOOLS_ENABLED bool is_csharp_keyword(const String &p_name) { - // Reserved keywords return p_name == "abstract" || p_name == "as" || p_name == "base" || p_name == "bool" || @@ -196,23 +196,13 @@ String str_format(const char *p_format, ...) { return res; } -// va_copy was defined in the C99, but not in C++ standards before C++11. -// When you compile C++ without --std=c++<XX> option, compilers still define -// va_copy, otherwise you have to use the internal version (__va_copy). -#if !defined(va_copy) -#if defined(__GNUC__) -#define va_copy(d, s) __va_copy((d), (s)) -#else -#define va_copy(d, s) ((d) = (s)) -#endif -#endif #if defined(MINGW_ENABLED) || defined(_MSC_VER) && _MSC_VER < 1900 #define gd_vsnprintf(m_buffer, m_count, m_format, m_args_copy) vsnprintf_s(m_buffer, m_count, _TRUNCATE, m_format, m_args_copy) #define gd_vscprintf(m_format, m_args_copy) _vscprintf(m_format, m_args_copy) #else #define gd_vsnprintf(m_buffer, m_count, m_format, m_args_copy) vsnprintf(m_buffer, m_count, m_format, m_args_copy) -#define gd_vscprintf(m_format, m_args_copy) vsnprintf(NULL, 0, p_format, m_args_copy) +#define gd_vscprintf(m_format, m_args_copy) vsnprintf(nullptr, 0, p_format, m_args_copy) #endif String str_format(const char *p_format, va_list p_list) { diff --git a/modules/ogg/SCsub b/modules/ogg/SCsub index 44c7963cd3..e768fb4ae8 100644 --- a/modules/ogg/SCsub +++ b/modules/ogg/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") # Only kept to build the thirdparty library used by the theora and webm # modules. @@ -9,7 +9,7 @@ Import('env_modules') env_ogg = env_modules.Clone() # Thirdparty source files -if env['builtin_libogg']: +if env["builtin_libogg"]: thirdparty_dir = "#thirdparty/libogg/" thirdparty_sources = [ "bitwise.c", diff --git a/modules/ogg/config.py b/modules/ogg/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/ogg/config.py +++ b/modules/ogg/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/ogg/register_types.h b/modules/ogg/register_types.h index 09095c9b62..849d27bb06 100644 --- a/modules/ogg/register_types.h +++ b/modules/ogg/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef OGG_REGISTER_TYPES_H +#define OGG_REGISTER_TYPES_H + void register_ogg_types(); void unregister_ogg_types(); + +#endif // OGG_REGISTER_TYPES_H diff --git a/modules/opensimplex/SCsub b/modules/opensimplex/SCsub index 311d33b047..52d8b145ef 100644 --- a/modules/opensimplex/SCsub +++ b/modules/opensimplex/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_opensimplex = env_modules.Clone() diff --git a/modules/opensimplex/config.py b/modules/opensimplex/config.py index c1010ad433..90b85dbd70 100644 --- a/modules/opensimplex/config.py +++ b/modules/opensimplex/config.py @@ -1,14 +1,17 @@ def can_build(env, platform): - return True + return True + def configure(env): - pass + pass + def get_doc_classes(): return [ "NoiseTexture", - "OpenSimplexNoise" + "OpenSimplexNoise", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp index 8e5b04f995..1181e69cd3 100644 --- a/modules/opensimplex/noise_texture.cpp +++ b/modules/opensimplex/noise_texture.cpp @@ -34,7 +34,7 @@ NoiseTexture::NoiseTexture() { update_queued = false; - noise_thread = NULL; + noise_thread = nullptr; regen_queued = false; first_time = true; @@ -50,7 +50,7 @@ NoiseTexture::NoiseTexture() { NoiseTexture::~NoiseTexture() { if (texture.is_valid()) { - VS::get_singleton()->free(texture); + RS::get_singleton()->free(texture); } if (noise_thread) { Thread::wait_to_finish(noise_thread); @@ -59,7 +59,6 @@ NoiseTexture::~NoiseTexture() { } void NoiseTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture::set_width); ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture::set_height); @@ -88,7 +87,6 @@ void NoiseTexture::_bind_methods() { } void NoiseTexture::_validate_property(PropertyInfo &property) const { - if (property.name == "bump_strength") { if (!as_normalmap) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; @@ -100,21 +98,20 @@ void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) { data = p_image; if (data.is_valid()) { if (texture.is_valid()) { - RID new_texture = VS::get_singleton()->texture_2d_create(p_image); - VS::get_singleton()->texture_replace(texture, new_texture); + RID new_texture = RS::get_singleton()->texture_2d_create(p_image); + RS::get_singleton()->texture_replace(texture, new_texture); } else { - texture = VS::get_singleton()->texture_2d_create(p_image); + texture = RS::get_singleton()->texture_2d_create(p_image); } } emit_changed(); } void NoiseTexture::_thread_done(const Ref<Image> &p_image) { - _set_texture_data(p_image); Thread::wait_to_finish(noise_thread); memdelete(noise_thread); - noise_thread = NULL; + noise_thread = nullptr; if (regen_queued) { noise_thread = Thread::create(_thread_function, this); regen_queued = false; @@ -127,24 +124,28 @@ void NoiseTexture::_thread_function(void *p_ud) { } void NoiseTexture::_queue_update() { - - if (update_queued) + if (update_queued) { return; + } update_queued = true; call_deferred("_update_texture"); } Ref<Image> NoiseTexture::_generate_texture() { + // Prevent memdelete due to unref() on other thread. + Ref<OpenSimplexNoise> ref_noise = noise; - if (noise.is_null()) return Ref<Image>(); + if (ref_noise.is_null()) { + return Ref<Image>(); + } Ref<Image> image; if (seamless) { - image = noise->get_seamless_image(size.x); + image = ref_noise->get_seamless_image(size.x); } else { - image = noise->get_image(size.x, size.y); + image = ref_noise->get_image(size.x, size.y); } if (as_normalmap) { @@ -164,7 +165,6 @@ void NoiseTexture::_update_texture() { use_thread = false; #endif if (use_thread) { - if (!noise_thread) { noise_thread = Thread::create(_thread_function, this); regen_queued = false; @@ -180,8 +180,9 @@ void NoiseTexture::_update_texture() { } void NoiseTexture::set_noise(Ref<OpenSimplexNoise> p_noise) { - if (p_noise == noise) + if (p_noise == noise) { return; + } if (noise.is_valid()) { noise->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); } @@ -197,19 +198,25 @@ Ref<OpenSimplexNoise> NoiseTexture::get_noise() { } void NoiseTexture::set_width(int p_width) { - if (p_width == size.x) return; + if (p_width == size.x) { + return; + } size.x = p_width; _queue_update(); } void NoiseTexture::set_height(int p_height) { - if (p_height == size.y) return; + if (p_height == size.y) { + return; + } size.y = p_height; _queue_update(); } void NoiseTexture::set_seamless(bool p_seamless) { - if (p_seamless == seamless) return; + if (p_seamless == seamless) { + return; + } seamless = p_seamless; _queue_update(); } @@ -219,7 +226,9 @@ bool NoiseTexture::get_seamless() { } void NoiseTexture::set_as_normalmap(bool p_as_normalmap) { - if (p_as_normalmap == as_normalmap) return; + if (p_as_normalmap == as_normalmap) { + return; + } as_normalmap = p_as_normalmap; _queue_update(); _change_notify(); @@ -230,37 +239,35 @@ bool NoiseTexture::is_normalmap() { } void NoiseTexture::set_bump_strength(float p_bump_strength) { - - if (p_bump_strength == bump_strength) return; + if (p_bump_strength == bump_strength) { + return; + } bump_strength = p_bump_strength; - if (as_normalmap) + if (as_normalmap) { _queue_update(); + } } float NoiseTexture::get_bump_strength() { - return bump_strength; } int NoiseTexture::get_width() const { - return size.x; } int NoiseTexture::get_height() const { - return size.y; } RID NoiseTexture::get_rid() const { if (!texture.is_valid()) { - texture = VS::get_singleton()->texture_2d_placeholder_create(); + texture = RS::get_singleton()->texture_2d_placeholder_create(); } return texture; } Ref<Image> NoiseTexture::get_data() const { - return data; } diff --git a/modules/opensimplex/open_simplex_noise.cpp b/modules/opensimplex/open_simplex_noise.cpp index 238faa4130..00b3d47db9 100644 --- a/modules/opensimplex/open_simplex_noise.cpp +++ b/modules/opensimplex/open_simplex_noise.cpp @@ -33,7 +33,6 @@ #include "core/core_string_names.h" OpenSimplexNoise::OpenSimplexNoise() { - seed = 0; persistence = 0.5; octaves = 3; @@ -53,9 +52,9 @@ void OpenSimplexNoise::_init_seeds() { } void OpenSimplexNoise::set_seed(int p_seed) { - - if (seed == p_seed) + if (seed == p_seed) { return; + } seed = p_seed; @@ -65,12 +64,13 @@ void OpenSimplexNoise::set_seed(int p_seed) { } int OpenSimplexNoise::get_seed() { - return seed; } void OpenSimplexNoise::set_octaves(int p_octaves) { - if (p_octaves == octaves) return; + if (p_octaves == octaves) { + return; + } ERR_FAIL_COND_MSG(p_octaves > MAX_OCTAVES, vformat("The number of OpenSimplexNoise octaves is limited to %d; ignoring the new value.", MAX_OCTAVES)); @@ -79,25 +79,30 @@ void OpenSimplexNoise::set_octaves(int p_octaves) { } void OpenSimplexNoise::set_period(float p_period) { - if (p_period == period) return; + if (p_period == period) { + return; + } period = p_period; emit_changed(); } void OpenSimplexNoise::set_persistence(float p_persistence) { - if (p_persistence == persistence) return; + if (p_persistence == persistence) { + return; + } persistence = p_persistence; emit_changed(); } void OpenSimplexNoise::set_lacunarity(float p_lacunarity) { - if (p_lacunarity == lacunarity) return; + if (p_lacunarity == lacunarity) { + return; + } lacunarity = p_lacunarity; emit_changed(); } Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) { - Vector<uint8_t> data; data.resize(p_width * p_height * 4); @@ -120,7 +125,6 @@ Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) { } Ref<Image> OpenSimplexNoise::get_seamless_image(int p_size) { - Vector<uint8_t> data; data.resize(p_size * p_size * 4); @@ -128,7 +132,6 @@ Ref<Image> OpenSimplexNoise::get_seamless_image(int p_size) { for (int i = 0; i < p_size; i++) { for (int j = 0; j < p_size; j++) { - float ii = (float)i / (float)p_size; float jj = (float)j / (float)p_size; @@ -157,7 +160,6 @@ Ref<Image> OpenSimplexNoise::get_seamless_image(int p_size) { } void OpenSimplexNoise::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_seed"), &OpenSimplexNoise::get_seed); ClassDB::bind_method(D_METHOD("set_seed", "seed"), &OpenSimplexNoise::set_seed); @@ -192,12 +194,10 @@ void OpenSimplexNoise::_bind_methods() { } float OpenSimplexNoise::get_noise_1d(float x) { - return get_noise_2d(x, 1.0); } float OpenSimplexNoise::get_noise_2d(float x, float y) { - x /= period; y /= period; @@ -218,7 +218,6 @@ float OpenSimplexNoise::get_noise_2d(float x, float y) { } float OpenSimplexNoise::get_noise_3d(float x, float y, float z) { - x /= period; y /= period; z /= period; @@ -241,7 +240,6 @@ float OpenSimplexNoise::get_noise_3d(float x, float y, float z) { } float OpenSimplexNoise::get_noise_4d(float x, float y, float z, float w) { - x /= period; y /= period; z /= period; diff --git a/modules/opensimplex/register_types.cpp b/modules/opensimplex/register_types.cpp index 6fae1fe415..fef90cdce3 100644 --- a/modules/opensimplex/register_types.cpp +++ b/modules/opensimplex/register_types.cpp @@ -33,7 +33,6 @@ #include "open_simplex_noise.h" void register_opensimplex_types() { - ClassDB::register_class<OpenSimplexNoise>(); ClassDB::register_class<NoiseTexture>(); } diff --git a/modules/opensimplex/register_types.h b/modules/opensimplex/register_types.h index 56e128f09e..51c6815eae 100644 --- a/modules/opensimplex/register_types.h +++ b/modules/opensimplex/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef OPENSIMPLEX_REGISTER_TYPES_H +#define OPENSIMPLEX_REGISTER_TYPES_H + void register_opensimplex_types(); void unregister_opensimplex_types(); + +#endif // OPENSIMPLEX_REGISTER_TYPES_H diff --git a/modules/opus/SCsub b/modules/opus/SCsub index fec2911d6d..e51590d808 100644 --- a/modules/opus/SCsub +++ b/modules/opus/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") # Only kept to build the thirdparty library used by the webm module. # AudioStreamOpus was dropped in 3.0 due to incompatibility with the new audio @@ -10,11 +10,10 @@ Import('env_modules') env_opus = env_modules.Clone() # Thirdparty source files -if env['builtin_opus']: +if env["builtin_opus"]: thirdparty_dir = "#thirdparty/opus/" thirdparty_sources = [ - # Sync with opus_sources.mk "opus.c", "opus_decoder.c", @@ -23,17 +22,14 @@ if env['builtin_opus']: "opus_multistream_encoder.c", "opus_multistream_decoder.c", "repacketizer.c", - "analysis.c", "mlp.c", "mlp_data.c", - # Sync with libopusfile Makefile.am "info.c", "internal.c", "opusfile.c", "stream.c", - # Sync with celt_sources.mk "celt/bands.c", "celt/celt.c", @@ -53,12 +49,11 @@ if env['builtin_opus']: "celt/quant_bands.c", "celt/rate.c", "celt/vq.c", - #"celt/arm/arm_celt_map.c", - #"celt/arm/armcpu.c", - #"celt/arm/celt_ne10_fft.c", - #"celt/arm/celt_ne10_mdct.c", - #"celt/arm/celt_neon_intr.c", - + # "celt/arm/arm_celt_map.c", + # "celt/arm/armcpu.c", + # "celt/arm/celt_ne10_fft.c", + # "celt/arm/celt_ne10_mdct.c", + # "celt/arm/celt_neon_intr.c", # Sync with silk_sources.mk "silk/CNG.c", "silk/code_signs.c", @@ -207,7 +202,7 @@ if env['builtin_opus']: thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources + opus_sources_silk] # also requires libogg - if env['builtin_libogg']: + if env["builtin_libogg"]: env_opus.Prepend(CPPPATH=["#thirdparty/libogg"]) env_opus.Append(CPPDEFINES=["HAVE_CONFIG_H"]) @@ -223,14 +218,14 @@ if env['builtin_opus']: env_opus.Prepend(CPPPATH=[thirdparty_dir + "/" + dir for dir in thirdparty_include_paths]) if env["platform"] == "android": - if ("android_arch" in env and env["android_arch"] == "armv7"): + if "android_arch" in env and env["android_arch"] == "armv7": env_opus.Append(CPPDEFINES=["OPUS_ARM_OPT"]) - elif ("android_arch" in env and env["android_arch"] == "arm64v8"): + elif "android_arch" in env and env["android_arch"] == "arm64v8": env_opus.Append(CPPDEFINES=["OPUS_ARM64_OPT"]) elif env["platform"] == "iphone": - if ("arch" in env and env["arch"] == "arm"): + if "arch" in env and env["arch"] == "arm": env_opus.Append(CPPDEFINES=["OPUS_ARM_OPT"]) - elif ("arch" in env and env["arch"] == "arm64"): + elif "arch" in env and env["arch"] == "arm64": env_opus.Append(CPPDEFINES=["OPUS_ARM64_OPT"]) env_thirdparty = env_opus.Clone() diff --git a/modules/opus/config.py b/modules/opus/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/opus/config.py +++ b/modules/opus/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/opus/register_types.h b/modules/opus/register_types.h index 445be4e166..ad6e083c82 100644 --- a/modules/opus/register_types.h +++ b/modules/opus/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef OPUS_REGISTER_TYPES_H +#define OPUS_REGISTER_TYPES_H + void register_opus_types(); void unregister_opus_types(); + +#endif // OPUS_REGISTER_TYPES_H diff --git a/modules/pvr/SCsub b/modules/pvr/SCsub index 18da38fbbd..e0baf851f1 100644 --- a/modules/pvr/SCsub +++ b/modules/pvr/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_pvr = env_modules.Clone() diff --git a/modules/pvr/config.py b/modules/pvr/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/pvr/config.py +++ b/modules/pvr/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/pvr/register_types.cpp b/modules/pvr/register_types.cpp index 5f900a0256..1eb697bba3 100644 --- a/modules/pvr/register_types.cpp +++ b/modules/pvr/register_types.cpp @@ -35,13 +35,11 @@ static Ref<ResourceFormatPVR> resource_loader_pvr; void register_pvr_types() { - resource_loader_pvr.instance(); ResourceLoader::add_resource_format_loader(resource_loader_pvr); } void unregister_pvr_types() { - ResourceLoader::remove_resource_format_loader(resource_loader_pvr); resource_loader_pvr.unref(); } diff --git a/modules/pvr/register_types.h b/modules/pvr/register_types.h index 06c54f50b1..8318996a46 100644 --- a/modules/pvr/register_types.h +++ b/modules/pvr/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef PVR_REGISTER_TYPES_H +#define PVR_REGISTER_TYPES_H + void register_pvr_types(); void unregister_pvr_types(); + +#endif // PVR_REGISTER_TYPES_H diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp index 179c6f692b..36c0913f62 100644 --- a/modules/pvr/texture_loader_pvr.cpp +++ b/modules/pvr/texture_loader_pvr.cpp @@ -51,22 +51,24 @@ enum PVRFLags { }; -RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - - if (r_error) +RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_CANT_OPEN; + } Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - if (!f) + if (!f) { return RES(); + } FileAccessRef faref(f); ERR_FAIL_COND_V(err, RES()); - if (r_error) + if (r_error) { *r_error = ERR_FILE_CORRUPT; + } uint32_t hsize = f->get_32(); @@ -109,11 +111,14 @@ RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Image::Format format = Image::FORMAT_MAX; switch (flags & 0xFF) { - case 0x18: - case 0xC: format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC2A : Image::FORMAT_PVRTC2; break; + case 0xC: + format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC2A : Image::FORMAT_PVRTC2; + break; case 0x19: - case 0xD: format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4; break; + case 0xD: + format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4; + break; case 0x16: format = Image::FORMAT_L8; break; @@ -158,29 +163,29 @@ RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Ref<ImageTexture> texture = memnew(ImageTexture); texture->create_from_image(image); - if (r_error) + if (r_error) { *r_error = OK; + } return texture; } void ResourceFormatPVR::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("pvr"); } -bool ResourceFormatPVR::handles_type(const String &p_type) const { +bool ResourceFormatPVR::handles_type(const String &p_type) const { return ClassDB::is_parent_class(p_type, "Texture2D"); } -String ResourceFormatPVR::get_resource_type(const String &p_path) const { - if (p_path.get_extension().to_lower() == "pvr") +String ResourceFormatPVR::get_resource_type(const String &p_path) const { + if (p_path.get_extension().to_lower() == "pvr") { return "Texture2D"; + } return ""; } static void _compress_pvrtc4(Image *p_img) { - Ref<Image> img = p_img->duplicate(); bool make_mipmaps = false; @@ -189,8 +194,9 @@ static void _compress_pvrtc4(Image *p_img) { img->resize_to_po2(true); } img->convert(Image::FORMAT_RGBA8); - if (!img->has_mipmaps() && make_mipmaps) + if (!img->has_mipmaps() && make_mipmaps) { img->generate_mipmaps(); + } bool use_alpha = img->detect_alpha(); @@ -204,7 +210,6 @@ static void _compress_pvrtc4(Image *p_img) { const uint8_t *r = img->get_data().ptr(); for (int i = 0; i <= new_img->get_mipmap_count(); i++) { - int ofs, size, w, h; img->get_mipmap_offset_size_and_dimensions(i, ofs, size, w, h); Javelin::RgbaBitmap bm(w, h); @@ -222,7 +227,6 @@ static void _compress_pvrtc4(Image *p_img) { } ResourceFormatPVR::ResourceFormatPVR() { - Image::_image_decompress_pvrtc = _pvrtc_decompress; Image::_image_compress_pvrtc4_func = _compress_pvrtc4; Image::_image_compress_pvrtc2_func = _compress_pvrtc4; @@ -255,31 +259,28 @@ struct PVRTCBlock { }; _FORCE_INLINE_ bool is_po2(uint32_t p_input) { - - if (p_input == 0) - return 0; + if (p_input == 0) { + return false; + } uint32_t minus1 = p_input - 1; - return ((p_input | minus1) == (p_input ^ minus1)) ? 1 : 0; + return ((p_input | minus1) == (p_input ^ minus1)) ? true : false; } static void unpack_5554(const PVRTCBlock *p_block, int p_ab_colors[2][4]) { - uint32_t raw_bits[2]; raw_bits[0] = p_block->data[1] & (0xFFFE); raw_bits[1] = p_block->data[1] >> 16; for (int i = 0; i < 2; i++) { - if (raw_bits[i] & (1 << 15)) { - p_ab_colors[i][0] = (raw_bits[i] >> 10) & 0x1F; p_ab_colors[i][1] = (raw_bits[i] >> 5) & 0x1F; p_ab_colors[i][2] = raw_bits[i] & 0x1F; - if (i == 0) + if (i == 0) { p_ab_colors[0][2] |= p_ab_colors[0][2] >> 4; + } p_ab_colors[i][3] = 0xF; } else { - p_ab_colors[i][0] = (raw_bits[i] >> (8 - 1)) & 0x1E; p_ab_colors[i][1] = (raw_bits[i] >> (4 - 1)) & 0x1E; @@ -288,10 +289,11 @@ static void unpack_5554(const PVRTCBlock *p_block, int p_ab_colors[2][4]) { p_ab_colors[i][2] = (raw_bits[i] & 0xF) << 1; - if (i == 0) + if (i == 0) { p_ab_colors[0][2] |= p_ab_colors[0][2] >> 3; - else + } else { p_ab_colors[0][2] |= p_ab_colors[0][2] >> 4; + } p_ab_colors[i][3] = (raw_bits[i] >> 11) & 0xE; } @@ -299,15 +301,12 @@ static void unpack_5554(const PVRTCBlock *p_block, int p_ab_colors[2][4]) { } static void unpack_modulations(const PVRTCBlock *p_block, const int p_2bit, int p_modulation[8][16], int p_modulation_modes[8][16], int p_x, int p_y) { - int block_mod_mode = p_block->data[1] & 1; uint32_t modulation_bits = p_block->data[0]; if (p_2bit && block_mod_mode) { - for (int y = 0; y < BLK_Y_SIZE; y++) { for (int x = 0; x < BLK_X_2BPP; x++) { - p_modulation_modes[y + p_y][x + p_x] = block_mod_mode; if (((x ^ y) & 1) == 0) { @@ -318,15 +317,15 @@ static void unpack_modulations(const PVRTCBlock *p_block, const int p_2bit, int } } else if (p_2bit) { - for (int y = 0; y < BLK_Y_SIZE; y++) { for (int x = 0; x < BLK_X_2BPP; x++) { p_modulation_modes[y + p_y][x + p_x] = block_mod_mode; - if (modulation_bits & 1) + if (modulation_bits & 1) { p_modulation[y + p_y][x + p_x] = 0x3; - else + } else { p_modulation[y + p_y][x + p_x] = 0x0; + } modulation_bits >>= 1; } @@ -361,10 +360,11 @@ static void interpolate_colors(const int p_colorp[4], const int p_colorq[4], con v = (y & 0x3) | ((~y & 0x2) << 1); - if (p_2bit) + if (p_2bit) { u = (x & 0x7) | ((~x & 0x4) << 1); - else + } else { u = (x & 0x3) | ((~x & 0x2) << 1); + } v = v - BLK_Y_SIZE / 2; @@ -420,19 +420,20 @@ static void get_modulation_value(int x, int y, const int p_2bit, const int p_mod y = (y & 0x3) | ((~y & 0x2) << 1); - if (p_2bit) + if (p_2bit) { x = (x & 0x7) | ((~x & 0x4) << 1); - else + } else { x = (x & 0x3) | ((~x & 0x2) << 1); + } *p_dopt = 0; if (p_modulation_modes[y][x] == 0) { mod_val = rep_vals0[p_modulation[y][x]]; } else if (p_2bit) { - if (((x ^ y) & 1) == 0) + if (((x ^ y) & 1) == 0) { mod_val = rep_vals0[p_modulation[y][x]]; - else if (p_modulation_modes[y][x] == 1) { + } else if (p_modulation_modes[y][x] == 1) { mod_val = (rep_vals0[p_modulation[y - 1][x]] + rep_vals0[p_modulation[y + 1][x]] + rep_vals0[p_modulation[y][x - 1]] + @@ -459,7 +460,6 @@ static void get_modulation_value(int x, int y, const int p_2bit, const int p_mod static int disable_twiddling = 0; static uint32_t twiddle_uv(uint32_t p_height, uint32_t p_width, uint32_t p_y, uint32_t p_x) { - uint32_t twiddled; uint32_t min_dimension; @@ -484,8 +484,9 @@ static uint32_t twiddle_uv(uint32_t p_height, uint32_t p_width, uint32_t p_y, ui max_value = p_y; } - if (disable_twiddling) + if (disable_twiddling) { return (p_y * p_width + p_x); + } scr_bit_pos = 1; dst_bit_pos = 1; @@ -534,7 +535,7 @@ static void decompress_pvrtc(PVRTCBlock *p_comp_img, const int p_2bit, const int // local neighbourhood of blocks PVRTCBlock *p_blocks[2][2]; - PVRTCBlock *prev[2][2] = { { NULL, NULL }, { NULL, NULL } }; + PVRTCBlock *prev[2][2] = { { nullptr, nullptr }, { nullptr, nullptr } }; struct { @@ -545,17 +546,17 @@ static void decompress_pvrtc(PVRTCBlock *p_comp_img, const int p_2bit, const int int r_result[4]; - if (p_2bit) + if (p_2bit) { x_block_size = BLK_X_2BPP; - else + } else { x_block_size = BLK_X_4BPP; + } block_width = MAX(2, p_width / x_block_size); block_height = MAX(2, p_height / BLK_Y_SIZE); for (y = 0; y < p_height; y++) { for (x = 0; x < p_width; x++) { - block_x = (x - x_block_size / 2); blk_y = (y - BLK_Y_SIZE / 2); @@ -620,8 +621,9 @@ static void decompress_pvrtc(PVRTCBlock *p_comp_img, const int p_2bit, const int r_result[i] >>= 3; } - if (DoPT) + if (DoPT) { r_result[3] = 0; + } u_pos = (x + y * p_width) << 2; p_dst[u_pos + 0] = (uint8_t)r_result[0]; @@ -633,7 +635,6 @@ static void decompress_pvrtc(PVRTCBlock *p_comp_img, const int p_2bit, const int } static void _pvrtc_decompress(Image *p_img) { - ERR_FAIL_COND(p_img->get_format() != Image::FORMAT_PVRTC2 && p_img->get_format() != Image::FORMAT_PVRTC2A && p_img->get_format() != Image::FORMAT_PVRTC4 && p_img->get_format() != Image::FORMAT_PVRTC4A); bool _2bit = (p_img->get_format() == Image::FORMAT_PVRTC2 || p_img->get_format() == Image::FORMAT_PVRTC2A); @@ -649,6 +650,7 @@ static void _pvrtc_decompress(Image *p_img) { bool make_mipmaps = p_img->has_mipmaps(); p_img->create(p_img->get_width(), p_img->get_height(), false, Image::FORMAT_RGBA8, newdata); - if (make_mipmaps) + if (make_mipmaps) { p_img->generate_mipmaps(); + } } diff --git a/modules/pvr/texture_loader_pvr.h b/modules/pvr/texture_loader_pvr.h index c990c3612b..07ef129689 100644 --- a/modules/pvr/texture_loader_pvr.h +++ b/modules/pvr/texture_loader_pvr.h @@ -36,7 +36,7 @@ class ResourceFormatPVR : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/regex/SCsub b/modules/regex/SCsub index 6238cd3d9f..753650adcb 100644 --- a/modules/regex/SCsub +++ b/modules/regex/SCsub @@ -1,16 +1,16 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_regex = env_modules.Clone() -if env['builtin_pcre2']: - thirdparty_dir = '#thirdparty/pcre2/src/' - thirdparty_flags = ['PCRE2_STATIC', 'HAVE_CONFIG_H'] +if env["builtin_pcre2"]: + thirdparty_dir = "#thirdparty/pcre2/src/" + thirdparty_flags = ["PCRE2_STATIC", "HAVE_CONFIG_H"] - if env['builtin_pcre2_with_jit']: - thirdparty_flags.append('SUPPORT_JIT') + if env["builtin_pcre2_with_jit"]: + thirdparty_flags.append("SUPPORT_JIT") thirdparty_sources = [ "pcre2_auto_possess.c", @@ -24,7 +24,7 @@ if env['builtin_pcre2']: "pcre2_extuni.c", "pcre2_find_bracket.c", "pcre2_jit_compile.c", - #"pcre2_jit_match.c", "pcre2_jit_misc.c", # these files are included in pcre2_jit_compile.c. + # "pcre2_jit_match.c", "pcre2_jit_misc.c", # these files are included in pcre2_jit_compile.c. "pcre2_maketables.c", "pcre2_match.c", "pcre2_match_data.c", diff --git a/modules/regex/config.py b/modules/regex/config.py index 42cfe3b43c..df9f44cb95 100644 --- a/modules/regex/config.py +++ b/modules/regex/config.py @@ -1,14 +1,17 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "RegEx", "RegExMatch", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp index 53d1a1dd65..50ca01067b 100644 --- a/modules/regex/regex.cpp +++ b/modules/regex/regex.cpp @@ -36,51 +36,46 @@ extern "C" { } static void *_regex_malloc(PCRE2_SIZE size, void *user) { - return memalloc(size); } static void _regex_free(void *ptr, void *user) { - memfree(ptr); } int RegExMatch::_find(const Variant &p_name) const { - if (p_name.is_num()) { - int i = (int)p_name; - if (i >= data.size()) + if (i >= data.size()) { return -1; + } return i; } else if (p_name.get_type() == Variant::STRING) { - const Map<String, int>::Element *found = names.find((String)p_name); - if (found) + if (found) { return found->value(); + } } return -1; } String RegExMatch::get_subject() const { - return subject; } int RegExMatch::get_group_count() const { - - if (data.size() == 0) + if (data.size() == 0) { return 0; + } return data.size() - 1; } Dictionary RegExMatch::get_names() const { - Dictionary result; - for (const Map<String, int>::Element *i = names.front(); i != NULL; i = i->next()) { + for (const Map<String, int>::Element *i = names.front(); i != nullptr; i = i->next()) { result[i->key()] = i->value(); } @@ -88,13 +83,11 @@ Dictionary RegExMatch::get_names() const { } Array RegExMatch::get_strings() const { - Array result; int size = data.size(); for (int i = 0; i < size; i++) { - int start = data[i].start; if (start == -1) { @@ -111,16 +104,17 @@ Array RegExMatch::get_strings() const { } String RegExMatch::get_string(const Variant &p_name) const { - int id = _find(p_name); - if (id < 0) + if (id < 0) { return String(); + } int start = data[id].start; - if (start == -1) + if (start == -1) { return String(); + } int length = data[id].end - start; @@ -128,27 +122,26 @@ String RegExMatch::get_string(const Variant &p_name) const { } int RegExMatch::get_start(const Variant &p_name) const { - int id = _find(p_name); - if (id < 0) + if (id < 0) { return -1; + } return data[id].start; } int RegExMatch::get_end(const Variant &p_name) const { - int id = _find(p_name); - if (id < 0) + if (id < 0) { return -1; + } return data[id].end; } void RegExMatch::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_subject"), &RegExMatch::get_subject); ClassDB::bind_method(D_METHOD("get_group_count"), &RegExMatch::get_group_count); ClassDB::bind_method(D_METHOD("get_names"), &RegExMatch::get_names); @@ -163,37 +156,30 @@ void RegExMatch::_bind_methods() { } void RegEx::_pattern_info(uint32_t what, void *where) const { - if (sizeof(CharType) == 2) { - pcre2_pattern_info_16((pcre2_code_16 *)code, what, where); } else { - pcre2_pattern_info_32((pcre2_code_32 *)code, what, where); } } void RegEx::clear() { - if (sizeof(CharType) == 2) { - if (code) { pcre2_code_free_16((pcre2_code_16 *)code); - code = NULL; + code = nullptr; } } else { - if (code) { pcre2_code_free_32((pcre2_code_32 *)code); - code = NULL; + code = nullptr; } } } Error RegEx::compile(const String &p_pattern) { - pattern = p_pattern; clear(); @@ -202,7 +188,6 @@ Error RegEx::compile(const String &p_pattern) { uint32_t flags = PCRE2_DUPNAMES; if (sizeof(CharType) == 2) { - pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx; pcre2_compile_context_16 *cctx = pcre2_compile_context_create_16(gctx); PCRE2_SPTR16 p = (PCRE2_SPTR16)pattern.c_str(); @@ -220,7 +205,6 @@ Error RegEx::compile(const String &p_pattern) { } } else { - pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; pcre2_compile_context_32 *cctx = pcre2_compile_context_create_32(gctx); PCRE2_SPTR32 p = (PCRE2_SPTR32)pattern.c_str(); @@ -241,17 +225,16 @@ Error RegEx::compile(const String &p_pattern) { } Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) const { - - ERR_FAIL_COND_V(!is_valid(), NULL); + ERR_FAIL_COND_V(!is_valid(), nullptr); Ref<RegExMatch> result = memnew(RegExMatch); int length = p_subject.length(); - if (p_end >= 0 && p_end < length) + if (p_end >= 0 && p_end < length) { length = p_end; + } if (sizeof(CharType) == 2) { - pcre2_code_16 *c = (pcre2_code_16 *)code; pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx; pcre2_match_context_16 *mctx = pcre2_match_context_create_16(gctx); @@ -263,7 +246,7 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) if (res < 0) { pcre2_match_data_free_16(match); - return NULL; + return nullptr; } uint32_t size = pcre2_get_ovector_count_16(match); @@ -272,7 +255,6 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) result->data.resize(size); for (uint32_t i = 0; i < size; i++) { - result->data.write[i].start = ovector[i * 2]; result->data.write[i].end = ovector[i * 2 + 1]; } @@ -281,7 +263,6 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) pcre2_match_context_free_16(mctx); } else { - pcre2_code_32 *c = (pcre2_code_32 *)code; pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx); @@ -295,7 +276,7 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) pcre2_match_data_free_32(match); pcre2_match_context_free_32(mctx); - return NULL; + return nullptr; } uint32_t size = pcre2_get_ovector_count_32(match); @@ -304,7 +285,6 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) result->data.resize(size); for (uint32_t i = 0; i < size; i++) { - result->data.write[i].start = ovector[i * 2]; result->data.write[i].end = ovector[i * 2 + 1]; } @@ -324,13 +304,14 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) _pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &entry_size); for (uint32_t i = 0; i < count; i++) { - CharType id = table[i * entry_size]; - if (result->data[id].start == -1) + if (result->data[id].start == -1) { continue; + } String name = &table[i * entry_size + 1]; - if (result->names.has(name)) + if (result->names.has(name)) { continue; + } result->names.insert(name, id); } @@ -339,13 +320,13 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) } Array RegEx::search_all(const String &p_subject, int p_offset, int p_end) const { - int last_end = -1; Array result; Ref<RegExMatch> match = search(p_subject, p_offset, p_end); while (match.is_valid()) { - if (last_end == match->get_end(0)) + if (last_end == match->get_end(0)) { break; + } result.push_back(match); last_end = match->get_end(0); match = search(p_subject, match->get_end(0), p_end); @@ -354,7 +335,6 @@ Array RegEx::search_all(const String &p_subject, int p_offset, int p_end) const } String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_all, int p_offset, int p_end) const { - ERR_FAIL_COND_V(!is_valid(), String()); // safety_zone is the number of chars we allocate in addition to the number of chars expected in order to @@ -368,15 +348,16 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a output.resize(olength + safety_zone); uint32_t flags = PCRE2_SUBSTITUTE_OVERFLOW_LENGTH; - if (p_all) + if (p_all) { flags |= PCRE2_SUBSTITUTE_GLOBAL; + } PCRE2_SIZE length = p_subject.length(); - if (p_end >= 0 && (uint32_t)p_end < length) + if (p_end >= 0 && (uint32_t)p_end < length) { length = p_end; + } if (sizeof(CharType) == 2) { - pcre2_code_16 *c = (pcre2_code_16 *)code; pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx; pcre2_match_context_16 *mctx = pcre2_match_context_create_16(gctx); @@ -397,11 +378,11 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a pcre2_match_data_free_16(match); pcre2_match_context_free_16(mctx); - if (res < 0) + if (res < 0) { return String(); + } } else { - pcre2_code_32 *c = (pcre2_code_32 *)code; pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx); @@ -422,25 +403,23 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a pcre2_match_data_free_32(match); pcre2_match_context_free_32(mctx); - if (res < 0) + if (res < 0) { return String(); + } } return String(output.ptr(), olength); } bool RegEx::is_valid() const { - - return (code != NULL); + return (code != nullptr); } String RegEx::get_pattern() const { - return pattern; } int RegEx::get_group_count() const { - ERR_FAIL_COND_V(!is_valid(), 0); uint32_t count; @@ -451,7 +430,6 @@ int RegEx::get_group_count() const { } Array RegEx::get_names() const { - Array result; ERR_FAIL_COND_V(!is_valid(), result); @@ -465,7 +443,6 @@ Array RegEx::get_names() const { _pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &entry_size); for (uint32_t i = 0; i < count; i++) { - String name = &table[i * entry_size + 1]; if (result.find(name) < 0) { result.append(name); @@ -476,50 +453,42 @@ Array RegEx::get_names() const { } RegEx::RegEx() { - if (sizeof(CharType) == 2) { - - general_ctx = pcre2_general_context_create_16(&_regex_malloc, &_regex_free, NULL); + general_ctx = pcre2_general_context_create_16(&_regex_malloc, &_regex_free, nullptr); } else { - - general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, NULL); + general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr); } - code = NULL; + code = nullptr; } RegEx::RegEx(const String &p_pattern) { - if (sizeof(CharType) == 2) { - - general_ctx = pcre2_general_context_create_16(&_regex_malloc, &_regex_free, NULL); + general_ctx = pcre2_general_context_create_16(&_regex_malloc, &_regex_free, nullptr); } else { - - general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, NULL); + general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr); } - code = NULL; + code = nullptr; compile(p_pattern); } RegEx::~RegEx() { - if (sizeof(CharType) == 2) { - - if (code) + if (code) { pcre2_code_free_16((pcre2_code_16 *)code); + } pcre2_general_context_free_16((pcre2_general_context_16 *)general_ctx); } else { - - if (code) + if (code) { pcre2_code_free_32((pcre2_code_32 *)code); + } pcre2_general_context_free_32((pcre2_general_context_32 *)general_ctx); } } void RegEx::_bind_methods() { - ClassDB::bind_method(D_METHOD("clear"), &RegEx::clear); ClassDB::bind_method(D_METHOD("compile", "pattern"), &RegEx::compile); ClassDB::bind_method(D_METHOD("search", "subject", "offset", "end"), &RegEx::search, DEFVAL(0), DEFVAL(-1)); diff --git a/modules/regex/regex.h b/modules/regex/regex.h index a342c17c78..52b49c783e 100644 --- a/modules/regex/regex.h +++ b/modules/regex/regex.h @@ -39,7 +39,6 @@ #include "core/vector.h" class RegExMatch : public Reference { - GDCLASS(RegExMatch, Reference); struct Range { @@ -70,7 +69,6 @@ public: }; class RegEx : public Reference { - GDCLASS(RegEx, Reference); void *general_ctx; diff --git a/modules/regex/register_types.cpp b/modules/regex/register_types.cpp index 77b19fa8f0..5d4aeba2d7 100644 --- a/modules/regex/register_types.cpp +++ b/modules/regex/register_types.cpp @@ -33,7 +33,6 @@ #include "regex.h" void register_regex_types() { - ClassDB::register_class<RegExMatch>(); ClassDB::register_class<RegEx>(); } diff --git a/modules/regex/register_types.h b/modules/regex/register_types.h index 99a6bbeb2c..cf377cdf5f 100644 --- a/modules/regex/register_types.h +++ b/modules/regex/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef REGEX_REGISTER_TYPES_H +#define REGEX_REGISTER_TYPES_H + void register_regex_types(); void unregister_regex_types(); + +#endif // REGEX_REGISTER_TYPES_H diff --git a/modules/squish/SCsub b/modules/squish/SCsub index 15320bcd0c..b31032403f 100644 --- a/modules/squish/SCsub +++ b/modules/squish/SCsub @@ -1,12 +1,12 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_squish = env_modules.Clone() # Thirdparty source files -if env['builtin_squish']: +if env["builtin_squish"]: thirdparty_dir = "#thirdparty/squish/" thirdparty_sources = [ "alpha.cpp", diff --git a/modules/squish/config.py b/modules/squish/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/squish/config.py +++ b/modules/squish/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp index bb77f68590..c510779317 100644 --- a/modules/squish/image_compress_squish.cpp +++ b/modules/squish/image_compress_squish.cpp @@ -78,21 +78,21 @@ void image_decompress_squish(Image *p_image) { } void image_compress_squish(Image *p_image, float p_lossy_quality, Image::UsedChannels p_channels) { - - if (p_image->get_format() >= Image::FORMAT_DXT1) + if (p_image->get_format() >= Image::FORMAT_DXT1) { return; //do not compress, already compressed + } int w = p_image->get_width(); int h = p_image->get_height(); if (p_image->get_format() <= Image::FORMAT_RGBA8) { - int squish_comp = squish::kColourRangeFit; - if (p_lossy_quality > 0.85) + if (p_lossy_quality > 0.85) { squish_comp = squish::kColourIterativeClusterFit; - else if (p_lossy_quality > 0.75) + } else if (p_lossy_quality > 0.75) { squish_comp = squish::kColourClusterFit; + } Image::Format target_format = Image::FORMAT_RGBA8; @@ -100,32 +100,26 @@ void image_compress_squish(Image *p_image, float p_lossy_quality, Image::UsedCha switch (p_channels) { case Image::USED_CHANNELS_L: { - target_format = Image::FORMAT_DXT1; squish_comp |= squish::kDxt1; } break; case Image::USED_CHANNELS_LA: { - target_format = Image::FORMAT_DXT5; squish_comp |= squish::kDxt5; } break; case Image::USED_CHANNELS_R: { - target_format = Image::FORMAT_RGTC_R; squish_comp |= squish::kBc4; } break; case Image::USED_CHANNELS_RG: { - target_format = Image::FORMAT_RGTC_RG; squish_comp |= squish::kBc5; } break; case Image::USED_CHANNELS_RGB: { - target_format = Image::FORMAT_DXT1; squish_comp |= squish::kDxt1; } break; case Image::USED_CHANNELS_RGBA: { - //TODO, should convert both, then measure which one does a better job target_format = Image::FORMAT_DXT5; squish_comp |= squish::kDxt5; @@ -149,7 +143,6 @@ void image_compress_squish(Image *p_image, float p_lossy_quality, Image::UsedCha int dst_ofs = 0; for (int i = 0; i <= mm_count; i++) { - int bw = w % 4 != 0 ? w + (4 - w % 4) : w; int bh = h % 4 != 0 ? h + (4 - h % 4) : h; diff --git a/modules/squish/register_types.cpp b/modules/squish/register_types.cpp index 2a0cf82b56..ad28aff058 100644 --- a/modules/squish/register_types.cpp +++ b/modules/squish/register_types.cpp @@ -32,7 +32,6 @@ #include "image_compress_squish.h" void register_squish_types() { - Image::set_compress_bc_func(image_compress_squish); Image::_image_decompress_bc = image_decompress_squish; } diff --git a/modules/squish/register_types.h b/modules/squish/register_types.h index 0845e2b500..ab56c54d4a 100644 --- a/modules/squish/register_types.h +++ b/modules/squish/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef SQUISH_REGISTER_TYPES_H +#define SQUISH_REGISTER_TYPES_H + void register_squish_types(); void unregister_squish_types(); + +#endif // SQUISH_REGISTER_TYPES_H diff --git a/modules/stb_vorbis/SCsub b/modules/stb_vorbis/SCsub index d14939a3b1..266c87c802 100644 --- a/modules/stb_vorbis/SCsub +++ b/modules/stb_vorbis/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_stb_vorbis = env_modules.Clone() diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp index 42f341cef7..3aceaf11c5 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp @@ -33,7 +33,6 @@ #include "core/os/file_access.h" void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) { - ERR_FAIL_COND(!active); int todo = p_frames; @@ -76,12 +75,10 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra } float AudioStreamPlaybackOGGVorbis::get_stream_sampling_rate() { - return vorbis_stream->sample_rate; } void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) { - active = true; seek(p_from_pos); loops = 0; @@ -89,27 +86,25 @@ void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) { } void AudioStreamPlaybackOGGVorbis::stop() { - active = false; } -bool AudioStreamPlaybackOGGVorbis::is_playing() const { +bool AudioStreamPlaybackOGGVorbis::is_playing() const { return active; } int AudioStreamPlaybackOGGVorbis::get_loop_count() const { - return loops; } float AudioStreamPlaybackOGGVorbis::get_playback_position() const { - return float(frames_mixed) / vorbis_stream->sample_rate; } -void AudioStreamPlaybackOGGVorbis::seek(float p_time) { - if (!active) +void AudioStreamPlaybackOGGVorbis::seek(float p_time) { + if (!active) { return; + } if (p_time >= vorbis_stream->get_length()) { p_time = 0; @@ -122,19 +117,18 @@ void AudioStreamPlaybackOGGVorbis::seek(float p_time) { AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() { if (ogg_alloc.alloc_buffer) { stb_vorbis_close(ogg_stream); - AudioServer::get_singleton()->audio_data_free(ogg_alloc.alloc_buffer); + memfree(ogg_alloc.alloc_buffer); } } Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() { - Ref<AudioStreamPlaybackOGGVorbis> ovs; - ERR_FAIL_COND_V(data == NULL, ovs); + ERR_FAIL_COND_V(data == nullptr, ovs); ovs.instance(); ovs->vorbis_stream = Ref<AudioStreamOGGVorbis>(this); - ovs->ogg_alloc.alloc_buffer = (char *)AudioServer::get_singleton()->audio_data_alloc(decode_mem_size); + ovs->ogg_alloc.alloc_buffer = (char *)memalloc(decode_mem_size); ovs->ogg_alloc.alloc_buffer_length_in_bytes = decode_mem_size; ovs->frames_mixed = 0; ovs->active = false; @@ -142,9 +136,8 @@ Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() { int error; ovs->ogg_stream = stb_vorbis_open_memory((const unsigned char *)data, data_len, &error, &ovs->ogg_alloc); if (!ovs->ogg_stream) { - - AudioServer::get_singleton()->audio_data_free(ovs->ogg_alloc.alloc_buffer); - ovs->ogg_alloc.alloc_buffer = NULL; + memfree(ovs->ogg_alloc.alloc_buffer); + ovs->ogg_alloc.alloc_buffer = nullptr; ERR_FAIL_COND_V(!ovs->ogg_stream, Ref<AudioStreamPlaybackOGGVorbis>()); } @@ -152,31 +145,28 @@ Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() { } String AudioStreamOGGVorbis::get_stream_name() const { - return ""; //return stream_name; } void AudioStreamOGGVorbis::clear_data() { if (data) { - AudioServer::get_singleton()->audio_data_free(data); - data = NULL; + memfree(data); + data = nullptr; data_len = 0; } } void AudioStreamOGGVorbis::set_data(const Vector<uint8_t> &p_data) { - int src_data_len = p_data.size(); #define MAX_TEST_MEM (1 << 20) uint32_t alloc_try = 1024; Vector<char> alloc_mem; char *w; - stb_vorbis *ogg_stream = NULL; + stb_vorbis *ogg_stream = nullptr; stb_vorbis_alloc ogg_alloc; while (alloc_try < MAX_TEST_MEM) { - alloc_mem.resize(alloc_try); w = alloc_mem.ptrw(); @@ -189,12 +179,10 @@ void AudioStreamOGGVorbis::set_data(const Vector<uint8_t> &p_data) { ogg_stream = stb_vorbis_open_memory((const unsigned char *)src_datar, src_data_len, &error, &ogg_alloc); if (!ogg_stream && error == VORBIS_outofmem) { - alloc_try *= 2; } else { - ERR_FAIL_COND(alloc_try == MAX_TEST_MEM); - ERR_FAIL_COND(ogg_stream == NULL); + ERR_FAIL_COND(ogg_stream == nullptr); stb_vorbis_info info = stb_vorbis_get_info(ogg_stream); @@ -210,7 +198,8 @@ void AudioStreamOGGVorbis::set_data(const Vector<uint8_t> &p_data) { // free any existing data clear_data(); - data = AudioServer::get_singleton()->audio_data_alloc(src_data_len, src_datar); + data = memalloc(src_data_len); + copymem(data, src_datar, src_data_len); data_len = src_data_len; break; @@ -219,7 +208,6 @@ void AudioStreamOGGVorbis::set_data(const Vector<uint8_t> &p_data) { } Vector<uint8_t> AudioStreamOGGVorbis::get_data() const { - Vector<uint8_t> vdata; if (data_len && data) { @@ -238,7 +226,6 @@ void AudioStreamOGGVorbis::set_loop(bool p_enable) { } bool AudioStreamOGGVorbis::has_loop() const { - return loop; } @@ -251,12 +238,10 @@ float AudioStreamOGGVorbis::get_loop_offset() const { } float AudioStreamOGGVorbis::get_length() const { - return length; } void AudioStreamOGGVorbis::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamOGGVorbis::set_data); ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamOGGVorbis::get_data); @@ -272,8 +257,7 @@ void AudioStreamOGGVorbis::_bind_methods() { } AudioStreamOGGVorbis::AudioStreamOGGVorbis() { - - data = NULL; + data = nullptr; data_len = 0; length = 0; sample_rate = 1; diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.h b/modules/stb_vorbis/audio_stream_ogg_vorbis.h index f296e8c19f..3002134651 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.h +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.h @@ -39,7 +39,6 @@ class AudioStreamOGGVorbis; class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled { - GDCLASS(AudioStreamPlaybackOGGVorbis, AudioStreamPlaybackResampled); stb_vorbis *ogg_stream; @@ -71,7 +70,6 @@ public: }; class AudioStreamOGGVorbis : public AudioStream { - GDCLASS(AudioStreamOGGVorbis, AudioStream); OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged. RES_BASE_EXTENSION("oggstr"); diff --git a/modules/stb_vorbis/config.py b/modules/stb_vorbis/config.py index 200b8dfd50..1eb0a8cf33 100644 --- a/modules/stb_vorbis/config.py +++ b/modules/stb_vorbis/config.py @@ -1,13 +1,16 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "AudioStreamOGGVorbis", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/stb_vorbis/register_types.cpp b/modules/stb_vorbis/register_types.cpp index ac2612bd6a..6669d30278 100644 --- a/modules/stb_vorbis/register_types.cpp +++ b/modules/stb_vorbis/register_types.cpp @@ -38,7 +38,6 @@ #endif void register_stb_vorbis_types() { - #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { Ref<ResourceImporterOGGVorbis> ogg_import; diff --git a/modules/stb_vorbis/register_types.h b/modules/stb_vorbis/register_types.h index f6147abd01..f5a1dd31bc 100644 --- a/modules/stb_vorbis/register_types.h +++ b/modules/stb_vorbis/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef STB_VORBIS_REGISTER_TYPES_H +#define STB_VORBIS_REGISTER_TYPES_H + void register_stb_vorbis_types(); void unregister_stb_vorbis_types(); + +#endif // STB_VORBIS_REGISTER_TYPES_H diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp index 13d96541e3..d68d050d34 100644 --- a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp @@ -35,16 +35,14 @@ #include "scene/resources/texture.h" String ResourceImporterOGGVorbis::get_importer_name() const { - return "ogg_vorbis"; } String ResourceImporterOGGVorbis::get_visible_name() const { - return "OGGVorbis"; } -void ResourceImporterOGGVorbis::get_recognized_extensions(List<String> *p_extensions) const { +void ResourceImporterOGGVorbis::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("ogg"); } @@ -53,31 +51,27 @@ String ResourceImporterOGGVorbis::get_save_extension() const { } String ResourceImporterOGGVorbis::get_resource_type() const { - return "AudioStreamOGGVorbis"; } bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { - return true; } int ResourceImporterOGGVorbis::get_preset_count() const { return 0; } -String ResourceImporterOGGVorbis::get_preset_name(int p_idx) const { +String ResourceImporterOGGVorbis::get_preset_name(int p_idx) const { return String(); } void ResourceImporterOGGVorbis::get_import_options(List<ImportOption> *r_options, int p_preset) const { - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); } Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { - bool loop = p_options["loop"]; float loop_offset = p_options["loop_offset"]; diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.h b/modules/stb_vorbis/resource_importer_ogg_vorbis.h index 43541bcf3c..8d6f71a456 100644 --- a/modules/stb_vorbis/resource_importer_ogg_vorbis.h +++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.h @@ -50,7 +50,7 @@ public: virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL, Variant *r_metadata = NULL); + virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr); ResourceImporterOGGVorbis(); }; diff --git a/modules/svg/SCsub b/modules/svg/SCsub index 7961d1f33e..0bfba34fe5 100644 --- a/modules/svg/SCsub +++ b/modules/svg/SCsub @@ -1,14 +1,14 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_svg = env_modules.Clone() # Thirdparty source files thirdparty_dir = "#thirdparty/nanosvg/" thirdparty_sources = [ - "nanosvg.cc" + "nanosvg.cc", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] diff --git a/modules/svg/config.py b/modules/svg/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/svg/config.py +++ b/modules/svg/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index e9d30d015a..8ca4452ac9 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -40,6 +40,7 @@ void SVGRasterizer::rasterize(NSVGimage *p_image, float p_tx, float p_ty, float SVGRasterizer::SVGRasterizer() { rasterizer = nsvgCreateRasterizer(); } + SVGRasterizer::~SVGRasterizer() { nsvgDeleteRasterizer(rasterizer); } @@ -47,7 +48,6 @@ SVGRasterizer::~SVGRasterizer() { SVGRasterizer ImageLoaderSVG::rasterizer; inline void change_nsvg_paint_color(NSVGpaint *p_paint, const uint32_t p_old, const uint32_t p_new) { - if (p_paint->type == NSVG_PAINT_COLOR) { if (p_paint->color << 8 == p_old << 8) { p_paint->color = (p_paint->color & 0xFF000000) | (p_new & 0x00FFFFFF); @@ -64,9 +64,7 @@ inline void change_nsvg_paint_color(NSVGpaint *p_paint, const uint32_t p_old, co } void ImageLoaderSVG::_convert_colors(NSVGimage *p_svg_image) { - - for (NSVGshape *shape = p_svg_image->shapes; shape != NULL; shape = shape->next) { - + for (NSVGshape *shape = p_svg_image->shapes; shape != nullptr; shape = shape->next) { for (int i = 0; i < replace_colors.old_colors.size(); i++) { change_nsvg_paint_color(&(shape->stroke), replace_colors.old_colors[i], replace_colors.new_colors[i]); change_nsvg_paint_color(&(shape->fill), replace_colors.old_colors[i], replace_colors.new_colors[i]); @@ -75,7 +73,6 @@ void ImageLoaderSVG::_convert_colors(NSVGimage *p_svg_image) { } void ImageLoaderSVG::set_convert_colors(Dictionary *p_replace_color) { - if (p_replace_color) { Dictionary replace_color = *p_replace_color; for (int i = 0; i < replace_color.keys().size(); i++) { @@ -98,7 +95,7 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const Vector<uint8_t> *p NSVGimage *svg_image; const uint8_t *src_r = p_data->ptr(); svg_image = nsvgParse((char *)src_r, "px", 96); - if (svg_image == NULL) { + if (svg_image == nullptr) { ERR_PRINT("SVG Corrupted"); return ERR_FILE_CORRUPT; } @@ -133,7 +130,6 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const Vector<uint8_t> *p } Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *p_svg_str, float p_scale, bool upsample, bool convert_colors) { - size_t str_len = strlen(p_svg_str); Vector<uint8_t> src_data; src_data.resize(str_len + 1); @@ -144,7 +140,6 @@ Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *p } Error ImageLoaderSVG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - uint32_t size = f->get_len(); Vector<uint8_t> src_image; src_image.resize(size + 1); @@ -156,7 +151,6 @@ Error ImageLoaderSVG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force } void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("svg"); p_extensions->push_back("svgz"); } diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h index def2885199..ecaba5052b 100644 --- a/modules/svg/image_loader_svg.h +++ b/modules/svg/image_loader_svg.h @@ -43,7 +43,6 @@ struct NSVGrasterizer; struct NSVGimage; class SVGRasterizer { - NSVGrasterizer *rasterizer; public: @@ -63,7 +62,7 @@ class ImageLoaderSVG : public ImageFormatLoader { static Error _create_image(Ref<Image> p_image, const Vector<uint8_t> *p_data, float p_scale, bool upsample, bool convert_colors = false); public: - static void set_convert_colors(Dictionary *p_replace_color = NULL); + static void set_convert_colors(Dictionary *p_replace_color = nullptr); static Error create_image_from_string(Ref<Image> p_image, const char *p_svg_str, float p_scale, bool upsample, bool convert_colors = false); virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale); diff --git a/modules/svg/register_types.cpp b/modules/svg/register_types.cpp index b0782dae88..9fbefd2cfe 100644 --- a/modules/svg/register_types.cpp +++ b/modules/svg/register_types.cpp @@ -32,15 +32,13 @@ #include "image_loader_svg.h" -static ImageLoaderSVG *image_loader_svg = NULL; +static ImageLoaderSVG *image_loader_svg = nullptr; void register_svg_types() { - image_loader_svg = memnew(ImageLoaderSVG); ImageLoader::add_image_format_loader(image_loader_svg); } void unregister_svg_types() { - memdelete(image_loader_svg); } diff --git a/modules/svg/register_types.h b/modules/svg/register_types.h index aa50540552..a3d914e0cb 100644 --- a/modules/svg/register_types.h +++ b/modules/svg/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef SVG_REGISTER_TYPES_H +#define SVG_REGISTER_TYPES_H + void register_svg_types(); void unregister_svg_types(); + +#endif // SVG_REGISTER_TYPES_H diff --git a/modules/tga/SCsub b/modules/tga/SCsub index 7e405f405c..067caa6ea0 100644 --- a/modules/tga/SCsub +++ b/modules/tga/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_tga = env_modules.Clone() diff --git a/modules/tga/config.py b/modules/tga/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/tga/config.py +++ b/modules/tga/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index 0e904fdd76..ce889a4928 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -38,8 +38,9 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t Vector<uint8_t> pixels; error = pixels.resize(p_pixel_size); - if (error != OK) + if (error != OK) { return error; + } uint8_t *pixels_w = pixels.ptrw(); @@ -77,7 +78,6 @@ Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t } Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome) { - #define TGA_PUT_PIXEL(r, g, b, a) \ int image_data_ofs = ((y * width) + x); \ image_data_w[image_data_ofs * 4 + 0] = r; \ @@ -199,13 +199,12 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff } } - p_image->create(width, height, 0, Image::FORMAT_RGBA8, image_data); + p_image->create(width, height, false, Image::FORMAT_RGBA8, image_data); return OK; } Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - Vector<uint8_t> src_image; int src_image_len = f->get_len(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); @@ -234,8 +233,9 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force bool has_color_map = (tga_header.image_type == TGA_TYPE_RLE_INDEXED || tga_header.image_type == TGA_TYPE_INDEXED); bool is_monochrome = (tga_header.image_type == TGA_TYPE_RLE_MONOCHROME || tga_header.image_type == TGA_TYPE_MONOCHROME); - if (tga_header.image_type == TGA_TYPE_NO_DATA) + if (tga_header.image_type == TGA_TYPE_NO_DATA) { err = FAILED; + } if (has_color_map) { if (tga_header.color_map_length > 256 || (tga_header.color_map_depth != 24) || tga_header.color_map_type != 1) { @@ -247,8 +247,9 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force } } - if (tga_header.image_width <= 0 || tga_header.image_height <= 0) + if (tga_header.image_width <= 0 || tga_header.image_height <= 0) { err = FAILED; + } if (!(tga_header.pixel_depth == 8 || tga_header.pixel_depth == 24 || tga_header.pixel_depth == 32)) { err = FAILED; @@ -283,10 +284,9 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force uint8_t *uncompressed_buffer_w = uncompressed_buffer.ptrw(); const uint8_t *uncompressed_buffer_r; - const uint8_t *buffer = NULL; + const uint8_t *buffer = nullptr; if (is_encoded) { - err = decode_tga_rle(src_image_r, pixel_size, uncompressed_buffer_w, buffer_size); if (err == OK) { @@ -308,7 +308,6 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force } void ImageLoaderTGA::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("tga"); } diff --git a/modules/tga/register_types.cpp b/modules/tga/register_types.cpp index 359f4d785e..320f748083 100644 --- a/modules/tga/register_types.cpp +++ b/modules/tga/register_types.cpp @@ -32,15 +32,13 @@ #include "image_loader_tga.h" -static ImageLoaderTGA *image_loader_tga = NULL; +static ImageLoaderTGA *image_loader_tga = nullptr; void register_tga_types() { - image_loader_tga = memnew(ImageLoaderTGA); ImageLoader::add_image_format_loader(image_loader_tga); } void unregister_tga_types() { - memdelete(image_loader_tga); } diff --git a/modules/tga/register_types.h b/modules/tga/register_types.h index beef05a590..94a77d295e 100644 --- a/modules/tga/register_types.h +++ b/modules/tga/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef TGA_REGISTER_TYPES_H +#define TGA_REGISTER_TYPES_H + void register_tga_types(); void unregister_tga_types(); + +#endif // TGA_REGISTER_TYPES_H diff --git a/modules/theora/SCsub b/modules/theora/SCsub index ff65d2f8ec..a01e65b4b0 100644 --- a/modules/theora/SCsub +++ b/modules/theora/SCsub @@ -1,71 +1,71 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_theora = env_modules.Clone() # Thirdparty source files -if env['builtin_libtheora']: +if env["builtin_libtheora"]: thirdparty_dir = "#thirdparty/libtheora/" thirdparty_sources = [ - #"analyze.c", - #"apiwrapper.c", + # "analyze.c", + # "apiwrapper.c", "bitpack.c", "cpu.c", - #"decapiwrapper.c", + # "decapiwrapper.c", "decinfo.c", "decode.c", "dequant.c", - #"encapiwrapper.c", - #"encfrag.c", - #"encinfo.c", - #"encode.c", - #"encoder_disabled.c", - #"enquant.c", - #"fdct.c", + # "encapiwrapper.c", + # "encfrag.c", + # "encinfo.c", + # "encode.c", + # "encoder_disabled.c", + # "enquant.c", + # "fdct.c", "fragment.c", "huffdec.c", - #"huffenc.c", + # "huffenc.c", "idct.c", "info.c", "internal.c", - #"mathops.c", - #"mcenc.c", + # "mathops.c", + # "mcenc.c", "quant.c", - #"rate.c", + # "rate.c", "state.c", - #"tokenize.c", + # "tokenize.c", ] thirdparty_sources_x86 = [ - #"x86/mmxencfrag.c", - #"x86/mmxfdct.c", + # "x86/mmxencfrag.c", + # "x86/mmxfdct.c", "x86/mmxfrag.c", "x86/mmxidct.c", "x86/mmxstate.c", - #"x86/sse2fdct.c", - #"x86/x86enc.c", + # "x86/sse2fdct.c", + # "x86/x86enc.c", "x86/x86state.c", ] thirdparty_sources_x86_vc = [ - #"x86_vc/mmxencfrag.c", - #"x86_vc/mmxfdct.c", + # "x86_vc/mmxencfrag.c", + # "x86_vc/mmxfdct.c", "x86_vc/mmxfrag.c", "x86_vc/mmxidct.c", "x86_vc/mmxstate.c", - #"x86_vc/x86enc.c", + # "x86_vc/x86enc.c", "x86_vc/x86state.c", ] - if (env["x86_libtheora_opt_gcc"]): + if env["x86_libtheora_opt_gcc"]: thirdparty_sources += thirdparty_sources_x86 - if (env["x86_libtheora_opt_vc"]): + if env["x86_libtheora_opt_vc"]: thirdparty_sources += thirdparty_sources_x86_vc - if (env["x86_libtheora_opt_gcc"] or env["x86_libtheora_opt_vc"]): + if env["x86_libtheora_opt_gcc"] or env["x86_libtheora_opt_vc"]: env_theora.Append(CPPDEFINES=["OC_X86_ASM"]) thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] @@ -73,9 +73,9 @@ if env['builtin_libtheora']: env_theora.Prepend(CPPPATH=[thirdparty_dir]) # also requires libogg and libvorbis - if env['builtin_libogg']: + if env["builtin_libogg"]: env_theora.Prepend(CPPPATH=["#thirdparty/libogg"]) - if env['builtin_libvorbis']: + if env["builtin_libvorbis"]: env_theora.Prepend(CPPPATH=["#thirdparty/libvorbis"]) env_thirdparty = env_theora.Clone() diff --git a/modules/theora/config.py b/modules/theora/config.py index c7713d7607..413acce2df 100644 --- a/modules/theora/config.py +++ b/modules/theora/config.py @@ -1,13 +1,16 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "VideoStreamTheora", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/theora/register_types.cpp b/modules/theora/register_types.cpp index f58e27c855..0676cab5c5 100644 --- a/modules/theora/register_types.cpp +++ b/modules/theora/register_types.cpp @@ -35,7 +35,6 @@ static Ref<ResourceFormatLoaderTheora> resource_loader_theora; void register_theora_types() { - resource_loader_theora.instance(); ResourceLoader::add_resource_format_loader(resource_loader_theora, true); @@ -43,7 +42,6 @@ void register_theora_types() { } void unregister_theora_types() { - ResourceLoader::remove_resource_format_loader(resource_loader_theora); resource_loader_theora.unref(); } diff --git a/modules/theora/register_types.h b/modules/theora/register_types.h index 66eb49aed1..4f0670b2c7 100644 --- a/modules/theora/register_types.h +++ b/modules/theora/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef THEORA_REGISTER_TYPES_H +#define THEORA_REGISTER_TYPES_H + void register_theora_types(); void unregister_theora_types(); + +#endif // THEORA_REGISTER_TYPES_H diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index ee44c6bf05..498391e44a 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -36,7 +36,6 @@ #include "thirdparty/misc/yuv2rgb.h" int VideoStreamPlaybackTheora::buffer_data() { - char *buffer = ogg_sync_buffer(&oy, 4096); #ifdef THEORA_USE_THREAD_STREAMING @@ -69,18 +68,20 @@ int VideoStreamPlaybackTheora::buffer_data() { int VideoStreamPlaybackTheora::queue_page(ogg_page *page) { if (theora_p) { ogg_stream_pagein(&to, page); - if (to.e_o_s) + if (to.e_o_s) { theora_eos = true; + } } if (vorbis_p) { ogg_stream_pagein(&vo, page); - if (vo.e_o_s) + if (vo.e_o_s) { vorbis_eos = true; + } } return 0; } -void VideoStreamPlaybackTheora::video_write(void) { +void VideoStreamPlaybackTheora::video_write() { th_ycbcr_buffer yuv; th_decode_ycbcr_out(td, yuv); @@ -93,15 +94,12 @@ void VideoStreamPlaybackTheora::video_write(void) { //uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y/2); if (px_fmt == TH_PF_444) { - yuv444_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2); } else if (px_fmt == TH_PF_422) { - yuv422_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2); } else if (px_fmt == TH_PF_420) { - yuv420_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2); }; @@ -116,9 +114,9 @@ void VideoStreamPlaybackTheora::video_write(void) { } void VideoStreamPlaybackTheora::clear() { - - if (!file) + if (!file) { return; + } if (vorbis_p) { ogg_stream_clear(&vo); @@ -144,7 +142,7 @@ void VideoStreamPlaybackTheora::clear() { thread_sem->post(); //just in case Thread::wait_to_finish(thread); memdelete(thread); - thread = NULL; + thread = nullptr; ring_buffer.clear(); #endif @@ -159,15 +157,14 @@ void VideoStreamPlaybackTheora::clear() { if (file) { memdelete(file); } - file = NULL; + file = nullptr; playing = false; }; void VideoStreamPlaybackTheora::set_file(const String &p_file) { - ERR_FAIL_COND(playing); ogg_packet op; - th_setup_info *ts = NULL; + th_setup_info *ts = nullptr; file_name = p_file; if (file) { @@ -209,7 +206,9 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { while (!stateflag) { int ret = buffer_data(); - if (ret == 0) break; + if (ret == 0) { + break; + } while (ogg_sync_pageout(&oy, &og) > 0) { ogg_stream_state test; @@ -231,7 +230,6 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { copymem(&to, &test, sizeof(test)); theora_p = 1; } else if (!vorbis_p && vorbis_synthesis_headerin(&vi, &vc, &op) >= 0) { - /* it is vorbis */ if (audio_track_skip) { vorbis_info_clear(&vi); @@ -286,7 +284,9 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { return; } vorbis_p++; - if (vorbis_p == 3) break; + if (vorbis_p == 3) { + break; + } } /* The header pages/packets will arrive before anything else we @@ -372,14 +372,13 @@ float VideoStreamPlaybackTheora::get_time() const { }; Ref<Texture2D> VideoStreamPlaybackTheora::get_texture() const { - return texture; } void VideoStreamPlaybackTheora::update(float p_delta) { - - if (!file) + if (!file) { return; + } if (!playing || paused) { //printf("not playing\n"); @@ -413,13 +412,11 @@ void VideoStreamPlaybackTheora::update(float p_delta) { /* if there's pending, decoded audio, grab it */ ret = vorbis_synthesis_pcmout(&vd, &pcm); if (ret > 0) { - const int AUXBUF_LEN = 4096; int to_read = ret; float aux_buffer[AUXBUF_LEN]; while (to_read) { - int m = MIN(AUXBUF_LEN / vi.channels, to_read); int count = 0; @@ -447,7 +444,6 @@ void VideoStreamPlaybackTheora::update(float p_delta) { audio_frames_wrote += ret - to_read; } else { - /* no pending audio; is there a pending packet to decode? */ if (ogg_stream_packetout(&vo, &op) > 0) { if (vorbis_synthesis(&vb, &op) == 0) { /* test for success! */ @@ -460,14 +456,14 @@ void VideoStreamPlaybackTheora::update(float p_delta) { audio_done = videobuf_time < (audio_frames_wrote / float(vi.rate)); - if (buffer_full) + if (buffer_full) { break; + } } while (theora_p && !frame_done) { /* theora is one in, one out... */ if (ogg_stream_packetout(&to, &op) > 0) { - if (false && pp_inc) { pp_level += pp_inc; th_decode_ctl(td, TH_DECCTL_SET_PPLEVEL, &pp_level, @@ -534,7 +530,6 @@ void VideoStreamPlaybackTheora::update(float p_delta) { /* are we at or past time for this video frame? */ if (videobuf_ready && videobuf_time <= get_time()) { - //video_write(); //videobuf_ready=0; } else { @@ -554,10 +549,9 @@ void VideoStreamPlaybackTheora::update(float p_delta) { }; void VideoStreamPlaybackTheora::play() { - - if (!playing) + if (!playing) { time = 0; - else { + } else { stop(); } @@ -567,9 +561,7 @@ void VideoStreamPlaybackTheora::play() { }; void VideoStreamPlaybackTheora::stop() { - if (playing) { - clear(); set_file(file_name); //reset } @@ -578,86 +570,68 @@ void VideoStreamPlaybackTheora::stop() { }; bool VideoStreamPlaybackTheora::is_playing() const { - return playing; }; void VideoStreamPlaybackTheora::set_paused(bool p_paused) { - paused = p_paused; }; bool VideoStreamPlaybackTheora::is_paused() const { - return paused; }; -void VideoStreamPlaybackTheora::set_loop(bool p_enable){ - -}; +void VideoStreamPlaybackTheora::set_loop(bool p_enable) { +} bool VideoStreamPlaybackTheora::has_loop() const { - return false; }; float VideoStreamPlaybackTheora::get_length() const { - return 0; }; String VideoStreamPlaybackTheora::get_stream_name() const { - return ""; }; int VideoStreamPlaybackTheora::get_loop_count() const { - return 0; }; float VideoStreamPlaybackTheora::get_playback_position() const { - return get_time(); }; -void VideoStreamPlaybackTheora::seek(float p_time){ - - // no -}; +void VideoStreamPlaybackTheora::seek(float p_time) { +} void VideoStreamPlaybackTheora::set_mix_callback(AudioMixCallback p_callback, void *p_userdata) { - mix_callback = p_callback; mix_udata = p_userdata; } int VideoStreamPlaybackTheora::get_channels() const { - return vi.channels; } void VideoStreamPlaybackTheora::set_audio_track(int p_idx) { - audio_track = p_idx; } int VideoStreamPlaybackTheora::get_mix_rate() const { - return vi.rate; } #ifdef THEORA_USE_THREAD_STREAMING void VideoStreamPlaybackTheora::_streaming_thread(void *ud) { - VideoStreamPlaybackTheora *vs = (VideoStreamPlaybackTheora *)ud; while (!vs->thread_exit) { - //just fill back the buffer if (!vs->thread_eof) { - int to_read = vs->ring_buffer.space_left(); if (to_read) { int read = vs->file->get_buffer(vs->read_buffer.ptr(), to_read); @@ -673,8 +647,7 @@ void VideoStreamPlaybackTheora::_streaming_thread(void *ud) { #endif VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { - - file = NULL; + file = nullptr; theora_p = 0; vorbis_p = 0; videobuf_ready = 0; @@ -685,8 +658,8 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { buffering = false; texture = Ref<ImageTexture>(memnew(ImageTexture)); - mix_callback = NULL; - mix_udata = NULL; + mix_callback = nullptr; + mix_udata = nullptr; audio_track = 0; delay_compensation = 0; audio_frames_wrote = 0; @@ -696,7 +669,7 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { ring_buffer.resize(rb_power); read_buffer.resize(RB_SIZE_KB * 1024); thread_sem = Semaphore::create(); - thread = NULL; + thread = nullptr; thread_exit = false; thread_eof = false; @@ -704,19 +677,18 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { }; VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() { - #ifdef THEORA_USE_THREAD_STREAMING memdelete(thread_sem); #endif clear(); - if (file) + if (file) { memdelete(file); + } }; void VideoStreamTheora::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamTheora::set_file); ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamTheora::get_file); @@ -725,8 +697,7 @@ void VideoStreamTheora::_bind_methods() { //////////// -RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - +RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { if (r_error) { @@ -750,19 +721,17 @@ RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_origi } void ResourceFormatLoaderTheora::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("ogv"); } bool ResourceFormatLoaderTheora::handles_type(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "VideoStream"); } String ResourceFormatLoaderTheora::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "ogv") + if (el == "ogv") { return "VideoStreamTheora"; + } return ""; } diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index da3558ce34..f90c2465b4 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -45,7 +45,6 @@ //#define THEORA_USE_THREAD_STREAMING class VideoStreamPlaybackTheora : public VideoStreamPlayback { - GDCLASS(VideoStreamPlaybackTheora, VideoStreamPlayback); enum { @@ -63,7 +62,7 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback { int buffer_data(); int queue_page(ogg_page *page); - void video_write(void); + void video_write(); float get_time() const; bool theora_eos; @@ -161,7 +160,6 @@ public: }; class VideoStreamTheora : public VideoStream { - GDCLASS(VideoStreamTheora, VideoStream); String file; @@ -187,7 +185,7 @@ public: class ResourceFormatLoaderTheora : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/tinyexr/SCsub b/modules/tinyexr/SCsub index 97f9797b58..84b3b4015b 100644 --- a/modules/tinyexr/SCsub +++ b/modules/tinyexr/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_tinyexr = env_modules.Clone() @@ -15,6 +15,9 @@ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] env_tinyexr.Prepend(CPPPATH=[thirdparty_dir]) +# Enable threaded loading with C++11. +env_tinyexr.Append(CPPDEFINES=["TINYEXR_USE_THREAD"]) + env_thirdparty = env_tinyexr.Clone() env_thirdparty.disable_warnings() env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources) diff --git a/modules/tinyexr/config.py b/modules/tinyexr/config.py index 098f1eafa9..53b8f2f2e3 100644 --- a/modules/tinyexr/config.py +++ b/modules/tinyexr/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return env['tools'] + return env["tools"] + def configure(env): pass diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index 41938f5b42..9e7266b95a 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/modules/tinyexr/image_loader_tinyexr.cpp @@ -36,7 +36,6 @@ #include "thirdparty/tinyexr/tinyexr.h" Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - Vector<uint8_t> src_image; int src_image_len = f->get_len(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); @@ -56,13 +55,12 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f EXRVersion exr_version; EXRImage exr_image; EXRHeader exr_header; - const char *err = NULL; + const char *err = nullptr; InitEXRHeader(&exr_header); int ret = ParseEXRVersionFromMemory(&exr_version, w, src_image_len); if (ret != TINYEXR_SUCCESS) { - return ERR_FILE_CORRUPT; } @@ -141,12 +139,10 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f int output_channels = 0; if (idxA != -1) { - imgdata.resize(exr_image.width * exr_image.height * 8); //RGBA16 format = Image::FORMAT_RGBAH; output_channels = 4; } else { - imgdata.resize(exr_image.width * exr_image.height * 6); //RGB16 format = Image::FORMAT_RGBH; output_channels = 3; @@ -185,7 +181,6 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f // Assume `out_rgba` have enough memory allocated. for (int tile_index = 0; tile_index < num_tiles; tile_index++) { - const EXRTile &tile = exr_tiles[tile_index]; int tw = tile.width; @@ -194,7 +189,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f const float *r_channel_start = reinterpret_cast<const float *>(tile.images[idxR]); const float *g_channel_start = reinterpret_cast<const float *>(tile.images[idxG]); const float *b_channel_start = reinterpret_cast<const float *>(tile.images[idxB]); - const float *a_channel_start = NULL; + const float *a_channel_start = nullptr; if (idxA != -1) { a_channel_start = reinterpret_cast<const float *>(tile.images[idxA]); @@ -206,7 +201,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f const float *r_channel = r_channel_start + y * tile_width; const float *g_channel = g_channel_start + y * tile_width; const float *b_channel = b_channel_start + y * tile_width; - const float *a_channel = NULL; + const float *a_channel = nullptr; if (a_channel_start) { a_channel = a_channel_start + y * tile_width; @@ -215,11 +210,11 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f uint16_t *row_w = first_row_w + (y * exr_image.width * output_channels); for (int x = 0; x < tw; x++) { - Color color(*r_channel++, *g_channel++, *b_channel++); - if (p_force_linear) + if (p_force_linear) { color = color.to_linear(); + } *row_w++ = Math::make_half_float(color.r); *row_w++ = Math::make_half_float(color.g); @@ -242,7 +237,6 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f } void ImageLoaderTinyEXR::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("exr"); } diff --git a/modules/tinyexr/image_loader_tinyexr.h b/modules/tinyexr/image_loader_tinyexr.h index af95989254..ff040b0915 100644 --- a/modules/tinyexr/image_loader_tinyexr.h +++ b/modules/tinyexr/image_loader_tinyexr.h @@ -34,7 +34,6 @@ #include "core/io/image_loader.h" class ImageLoaderTinyEXR : public ImageFormatLoader { - public: virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; diff --git a/modules/tinyexr/image_saver_tinyexr.cpp b/modules/tinyexr/image_saver_tinyexr.cpp index 05080289bd..420619bd5f 100644 --- a/modules/tinyexr/image_saver_tinyexr.cpp +++ b/modules/tinyexr/image_saver_tinyexr.cpp @@ -140,7 +140,6 @@ static int get_channel_count(Image::Format p_format) { } Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) { - Image::Format format = p_img->get_format(); if (!is_supported_format(format)) { @@ -192,7 +191,6 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) const uint8_t *src_r = src_data.ptr(); for (int channel_index = 0; channel_index < channel_count; ++channel_index) { - // De-interleave channels PackedByteArray &dst = channels[channel_index]; @@ -201,7 +199,6 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) uint8_t *dst_w = dst.ptrw(); if (src_pixel_type == SRC_FLOAT && target_pixel_type == TINYEXR_PIXELTYPE_FLOAT) { - // Note: we don't save mipmaps CRASH_COND(src_data.size() < pixel_count * channel_count * target_pixel_type_size); @@ -213,7 +210,6 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) } } else if (src_pixel_type == SRC_HALF && target_pixel_type == TINYEXR_PIXELTYPE_HALF) { - CRASH_COND(src_data.size() < pixel_count * channel_count * target_pixel_type_size); const uint16_t *src_rp = (uint16_t *)src_r; @@ -224,7 +220,6 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) } } else if (src_pixel_type == SRC_BYTE && target_pixel_type == TINYEXR_PIXELTYPE_HALF) { - CRASH_COND(src_data.size() < pixel_count * channel_count); const uint8_t *src_rp = (uint8_t *)src_r; @@ -267,13 +262,21 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) header.channels = channel_infos; header.pixel_types = pixel_types; header.requested_pixel_types = requested_pixel_types; + header.compression_type = TINYEXR_COMPRESSIONTYPE_PIZ; + + unsigned char *mem = nullptr; + const char *err = nullptr; + + size_t bytes = SaveEXRImageToMemory(&image, &header, &mem, &err); - CharString utf8_filename = p_path.utf8(); - const char *err; - int ret = SaveEXRImageToFile(&image, &header, utf8_filename.ptr(), &err); - if (ret != TINYEXR_SUCCESS) { + if (bytes == 0) { print_error(String("Saving EXR failed. Error: {0}").format(varray(err))); return ERR_FILE_CANT_WRITE; + } else { + FileAccessRef ref = FileAccess::open(p_path, FileAccess::WRITE); + ERR_FAIL_COND_V(!ref, ERR_FILE_CANT_WRITE); + ref->store_buffer(mem, bytes); + free(mem); } return OK; diff --git a/modules/tinyexr/register_types.cpp b/modules/tinyexr/register_types.cpp index d8529fd893..9d0fb8729e 100644 --- a/modules/tinyexr/register_types.cpp +++ b/modules/tinyexr/register_types.cpp @@ -33,10 +33,9 @@ #include "image_loader_tinyexr.h" #include "image_saver_tinyexr.h" -static ImageLoaderTinyEXR *image_loader_tinyexr = NULL; +static ImageLoaderTinyEXR *image_loader_tinyexr = nullptr; void register_tinyexr_types() { - image_loader_tinyexr = memnew(ImageLoaderTinyEXR); ImageLoader::add_image_format_loader(image_loader_tinyexr); @@ -44,8 +43,7 @@ void register_tinyexr_types() { } void unregister_tinyexr_types() { - memdelete(image_loader_tinyexr); - Image::save_exr_func = NULL; + Image::save_exr_func = nullptr; } diff --git a/modules/tinyexr/register_types.h b/modules/tinyexr/register_types.h index 2028cd4a33..9739488312 100644 --- a/modules/tinyexr/register_types.h +++ b/modules/tinyexr/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef TINYEXR_REGISTER_TYPES_H +#define TINYEXR_REGISTER_TYPES_H + void register_tinyexr_types(); void unregister_tinyexr_types(); + +#endif // TINYEXR_REGISTER_TYPES_H diff --git a/modules/upnp/SCsub b/modules/upnp/SCsub index 3f56a69594..2e129e15ca 100644 --- a/modules/upnp/SCsub +++ b/modules/upnp/SCsub @@ -1,13 +1,13 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_upnp = env_modules.Clone() # Thirdparty source files -if env['builtin_miniupnpc']: +if env["builtin_miniupnpc"]: thirdparty_dir = "#thirdparty/miniupnpc/" thirdparty_sources = [ "miniupnpc.c", diff --git a/modules/upnp/config.py b/modules/upnp/config.py index 8724ff1a51..3e15b940a1 100644 --- a/modules/upnp/config.py +++ b/modules/upnp/config.py @@ -1,14 +1,17 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "UPNP", - "UPNPDevice" + "UPNPDevice", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/upnp/register_types.cpp b/modules/upnp/register_types.cpp index 270aa2d7e8..34900206de 100644 --- a/modules/upnp/register_types.cpp +++ b/modules/upnp/register_types.cpp @@ -36,7 +36,6 @@ #include "upnp_device.h" void register_upnp_types() { - ClassDB::register_class<UPNP>(); ClassDB::register_class<UPNPDevice>(); } diff --git a/modules/upnp/register_types.h b/modules/upnp/register_types.h index 4d752e4a94..0c71db9ffa 100644 --- a/modules/upnp/register_types.h +++ b/modules/upnp/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef UPNP_REGISTER_TYPES_H +#define UPNP_REGISTER_TYPES_H + void register_upnp_types(); void unregister_upnp_types(); + +#endif // UPNP_REGISTER_TYPES_H diff --git a/modules/upnp/upnp.cpp b/modules/upnp/upnp.cpp index 5ef7575b0c..988bf3017d 100644 --- a/modules/upnp/upnp.cpp +++ b/modules/upnp/upnp.cpp @@ -44,9 +44,8 @@ bool UPNP::is_common_device(const String &dev) const { } int UPNP::discover(int timeout, int ttl, const String &device_filter) { - ERR_FAIL_COND_V(timeout < 0, UPNP_RESULT_INVALID_PARAM); - ERR_FAIL_COND_V(ttl < 0, UPNP_RESULT_INVALID_PARAM); - ERR_FAIL_COND_V(ttl > 255, UPNP_RESULT_INVALID_PARAM); + ERR_FAIL_COND_V_MSG(timeout < 0, UPNP_RESULT_INVALID_PARAM, "The response's wait time can't be negative."); + ERR_FAIL_COND_V_MSG(ttl < 0 || ttl > 255, UPNP_RESULT_INVALID_PARAM, "The time-to-live must be set between 0 and 255 (inclusive)."); devices.clear(); @@ -54,9 +53,9 @@ int UPNP::discover(int timeout, int ttl, const String &device_filter) { struct UPNPDev *devlist; if (is_common_device(device_filter)) { - devlist = upnpDiscover(timeout, discover_multicast_if.utf8().get_data(), NULL, discover_local_port, discover_ipv6, ttl, &error); + devlist = upnpDiscover(timeout, discover_multicast_if.utf8().get_data(), nullptr, discover_local_port, discover_ipv6, ttl, &error); } else { - devlist = upnpDiscoverAll(timeout, discover_multicast_if.utf8().get_data(), NULL, discover_local_port, discover_ipv6, ttl, &error); + devlist = upnpDiscoverAll(timeout, discover_multicast_if.utf8().get_data(), nullptr, discover_local_port, discover_ipv6, ttl, &error); } if (error != UPNPDISCOVER_SUCCESS) { @@ -133,7 +132,7 @@ void UPNP::parse_igd(Ref<UPNPDevice> dev, UPNPDev *devlist) { parserootdesc(xml, size, &data); free(xml); - xml = 0; + xml = nullptr; GetUPNPUrls(urls, &data, dev->get_description_url().utf8().get_data(), 0); @@ -235,20 +234,20 @@ int UPNP::get_device_count() const { } Ref<UPNPDevice> UPNP::get_device(int index) const { - ERR_FAIL_INDEX_V(index, devices.size(), NULL); + ERR_FAIL_INDEX_V(index, devices.size(), nullptr); return devices.get(index); } void UPNP::add_device(Ref<UPNPDevice> device) { - ERR_FAIL_COND(device == NULL); + ERR_FAIL_COND(device == nullptr); devices.push_back(device); } void UPNP::set_device(int index, Ref<UPNPDevice> device) { ERR_FAIL_INDEX(index, devices.size()); - ERR_FAIL_COND(device == NULL); + ERR_FAIL_COND(device == nullptr); devices.set(index, device); } @@ -264,17 +263,17 @@ void UPNP::clear_devices() { } Ref<UPNPDevice> UPNP::get_gateway() const { - ERR_FAIL_COND_V(devices.size() < 1, NULL); + ERR_FAIL_COND_V_MSG(devices.size() < 1, nullptr, "Couldn't find any UPNPDevices."); for (int i = 0; i < devices.size(); i++) { Ref<UPNPDevice> dev = get_device(i); - if (dev != NULL && dev->is_valid_gateway()) { + if (dev != nullptr && dev->is_valid_gateway()) { return dev; } } - return NULL; + return nullptr; } void UPNP::set_discover_multicast_if(const String &m_if) { @@ -304,7 +303,7 @@ bool UPNP::is_discover_ipv6() const { String UPNP::query_external_address() const { Ref<UPNPDevice> dev = get_gateway(); - if (dev == NULL) { + if (dev == nullptr) { return ""; } @@ -314,7 +313,7 @@ String UPNP::query_external_address() const { int UPNP::add_port_mapping(int port, int port_internal, String desc, String proto, int duration) const { Ref<UPNPDevice> dev = get_gateway(); - if (dev == NULL) { + if (dev == nullptr) { return UPNP_RESULT_NO_GATEWAY; } @@ -326,7 +325,7 @@ int UPNP::add_port_mapping(int port, int port_internal, String desc, String prot int UPNP::delete_port_mapping(int port, String proto) const { Ref<UPNPDevice> dev = get_gateway(); - if (dev == NULL) { + if (dev == nullptr) { return UPNP_RESULT_NO_GATEWAY; } diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h index 46f44e04e5..1c4b5549f4 100644 --- a/modules/upnp/upnp.h +++ b/modules/upnp/upnp.h @@ -38,7 +38,6 @@ #include <miniupnpc/miniupnpc.h> class UPNP : public Reference { - GDCLASS(UPNP, Reference); private: diff --git a/modules/upnp/upnp_device.cpp b/modules/upnp/upnp_device.cpp index 6edfbc2d7d..40eb6106a0 100644 --- a/modules/upnp/upnp_device.cpp +++ b/modules/upnp/upnp_device.cpp @@ -35,7 +35,7 @@ #include <miniupnpc/upnpcommands.h> String UPNPDevice::query_external_address() const { - ERR_FAIL_COND_V(!is_valid_gateway(), ""); + ERR_FAIL_COND_V_MSG(!is_valid_gateway(), "", "The Internet Gateway Device must be valid."); char addr[16]; int i = UPNP_GetExternalIPAddress( @@ -43,17 +43,17 @@ String UPNPDevice::query_external_address() const { igd_service_type.utf8().get_data(), (char *)&addr); - ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, ""); + ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, "", "Couldn't get external IP address."); return String(addr); } int UPNPDevice::add_port_mapping(int port, int port_internal, String desc, String proto, int duration) const { - ERR_FAIL_COND_V(!is_valid_gateway(), UPNP::UPNP_RESULT_INVALID_GATEWAY); - ERR_FAIL_COND_V(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT); - ERR_FAIL_COND_V(port_internal < 0 || port_internal > 65535, UPNP::UPNP_RESULT_INVALID_PORT); // Needs to allow 0 because 0 signifies "use external port as internal port" - ERR_FAIL_COND_V(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL); - ERR_FAIL_COND_V(duration < 0, UPNP::UPNP_RESULT_INVALID_DURATION); + ERR_FAIL_COND_V_MSG(!is_valid_gateway(), UPNP::UPNP_RESULT_INVALID_GATEWAY, "The Internet Gateway Device must be valid."); + ERR_FAIL_COND_V_MSG(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 1 and 65535 (inclusive)."); + ERR_FAIL_COND_V_MSG(port_internal < 0 || port_internal > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 0 and 65535 (inclusive)."); // Needs to allow 0 because 0 signifies "use external port as internal port" + ERR_FAIL_COND_V_MSG(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL, "The protocol must be either TCP or UDP."); + ERR_FAIL_COND_V_MSG(duration < 0, UPNP::UPNP_RESULT_INVALID_DURATION, "The port mapping's lease duration can't be negative."); if (port_internal < 1) { port_internal = port; @@ -65,29 +65,29 @@ int UPNPDevice::add_port_mapping(int port, int port_internal, String desc, Strin itos(port).utf8().get_data(), itos(port_internal).utf8().get_data(), igd_our_addr.utf8().get_data(), - desc.empty() ? 0 : desc.utf8().get_data(), + desc.empty() ? nullptr : desc.utf8().get_data(), proto.utf8().get_data(), - NULL, // Remote host, always NULL as IGDs don't support it - duration > 0 ? itos(duration).utf8().get_data() : 0); + nullptr, // Remote host, always nullptr as IGDs don't support it + duration > 0 ? itos(duration).utf8().get_data() : nullptr); - ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i)); + ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i), "Couldn't add port mapping."); return UPNP::UPNP_RESULT_SUCCESS; } int UPNPDevice::delete_port_mapping(int port, String proto) const { - ERR_FAIL_COND_V(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT); - ERR_FAIL_COND_V(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL); + ERR_FAIL_COND_V_MSG(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 1 and 65535 (inclusive)."); + ERR_FAIL_COND_V_MSG(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL, "The protocol must be either TCP or UDP."); int i = UPNP_DeletePortMapping( igd_control_url.utf8().get_data(), igd_service_type.utf8().get_data(), itos(port).utf8().get_data(), proto.utf8().get_data(), - NULL // Remote host, always NULL as IGDs don't support it + nullptr // Remote host, always nullptr as IGDs don't support it ); - ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i)); + ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i), "Couldn't delete port mapping."); return UPNP::UPNP_RESULT_SUCCESS; } diff --git a/modules/upnp/upnp_device.h b/modules/upnp/upnp_device.h index f25d3427fc..4b519fce32 100644 --- a/modules/upnp/upnp_device.h +++ b/modules/upnp/upnp_device.h @@ -34,7 +34,6 @@ #include "core/reference.h" class UPNPDevice : public Reference { - GDCLASS(UPNPDevice, Reference); public: diff --git a/modules/vhacd/SCsub b/modules/vhacd/SCsub index 685976dc33..ecd432b275 100644 --- a/modules/vhacd/SCsub +++ b/modules/vhacd/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_vhacd = env_modules.Clone() @@ -19,7 +19,7 @@ thirdparty_sources = [ "src/btAlignedAllocator.cpp", "src/vhacdRaycastMesh.cpp", "src/VHACD.cpp", - "src/btConvexHullComputer.cpp" + "src/btConvexHullComputer.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] diff --git a/modules/vhacd/config.py b/modules/vhacd/config.py index 9ced70d2fb..d22f9454ed 100644 --- a/modules/vhacd/config.py +++ b/modules/vhacd/config.py @@ -1,6 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass - diff --git a/modules/vhacd/register_types.cpp b/modules/vhacd/register_types.cpp index 7deb20f6e7..40c5e47440 100644 --- a/modules/vhacd/register_types.cpp +++ b/modules/vhacd/register_types.cpp @@ -33,7 +33,6 @@ #include "thirdparty/vhacd/public/VHACD.h" static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces) { - Vector<float> vertices; vertices.resize(p_faces.size() * 9); Vector<uint32_t> indices; @@ -84,5 +83,5 @@ void register_vhacd_types() { } void unregister_vhacd_types() { - Mesh::convex_composition_function = NULL; + Mesh::convex_composition_function = nullptr; } diff --git a/modules/vhacd/register_types.h b/modules/vhacd/register_types.h index de56620813..d02a990901 100644 --- a/modules/vhacd/register_types.h +++ b/modules/vhacd/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef VHACD_REGISTER_TYPES_H +#define VHACD_REGISTER_TYPES_H + void register_vhacd_types(); void unregister_vhacd_types(); + +#endif // VHACD_REGISTER_TYPES_H diff --git a/modules/visual_script/SCsub b/modules/visual_script/SCsub index 3c3d2caa57..16faea08d7 100644 --- a/modules/visual_script/SCsub +++ b/modules/visual_script/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_vs = env_modules.Clone() diff --git a/modules/visual_script/config.py b/modules/visual_script/config.py index 087a13a200..bd459ca344 100644 --- a/modules/visual_script/config.py +++ b/modules/visual_script/config.py @@ -1,9 +1,11 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "@VisualScript", @@ -56,5 +58,6 @@ def get_doc_classes(): "VisualScriptYield", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 63bd88ad81..8afed1229f 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -41,13 +41,12 @@ #include "visual_script_nodes.h" #include "visual_script_yield_nodes.h" -VisualScriptLanguage *visual_script_language = NULL; +VisualScriptLanguage *visual_script_language = nullptr; #ifdef TOOLS_ENABLED -static _VisualScriptEditor *vs_editor_singleton = NULL; +static _VisualScriptEditor *vs_editor_singleton = nullptr; #endif void register_visual_script_types() { - visual_script_language = memnew(VisualScriptLanguage); //script_language_gd->init(); ScriptServer::register_language(visual_script_language); @@ -125,7 +124,6 @@ void register_visual_script_types() { } void unregister_visual_script_types() { - unregister_visual_script_nodes(); ScriptServer::unregister_language(visual_script_language); @@ -136,6 +134,7 @@ void unregister_visual_script_types() { memdelete(vs_editor_singleton); } #endif - if (visual_script_language) + if (visual_script_language) { memdelete(visual_script_language); + } } diff --git a/modules/visual_script/register_types.h b/modules/visual_script/register_types.h index 546c2fbff3..c18c2930b1 100644 --- a/modules/visual_script/register_types.h +++ b/modules/visual_script/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef VISUAL_SCRIPT_REGISTER_TYPES_H +#define VISUAL_SCRIPT_REGISTER_TYPES_H + void register_visual_script_types(); void unregister_visual_script_types(); + +#endif // VISUAL_SCRIPT_REGISTER_TYPES_H diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index d00cc6986f..f387c0f288 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -44,7 +44,6 @@ void VisualScriptNode::set_breakpoint(bool p_breakpoint) { } bool VisualScriptNode::is_breakpoint() const { - return breakpoint; } @@ -53,7 +52,6 @@ void VisualScriptNode::ports_changed_notify() { } void VisualScriptNode::set_default_input_value(int p_port, const Variant &p_value) { - ERR_FAIL_INDEX(p_port, default_input_values.size()); default_input_values[p_port] = p_value; @@ -66,13 +64,11 @@ void VisualScriptNode::set_default_input_value(int p_port, const Variant &p_valu } Variant VisualScriptNode::get_default_input_value(int p_port) const { - ERR_FAIL_INDEX_V(p_port, default_input_values.size(), Variant()); return default_input_values[p_port]; } void VisualScriptNode::_set_default_input_values(Array p_values) { - default_input_values = p_values; } @@ -81,7 +77,6 @@ void VisualScriptNode::validate_input_default_values() { //actually validate on save for (int i = 0; i < get_input_value_port_count(); i++) { - Variant::Type expected = get_input_value_port_info(i).type; if (expected == Variant::NIL || expected == default_input_values[i].get_type()) { @@ -94,14 +89,13 @@ void VisualScriptNode::validate_input_default_values() { default_input_values[i] = Variant::construct(expected, &existingp, 1, ce, false); if (ce.error != Callable::CallError::CALL_OK) { //could not convert? force.. - default_input_values[i] = Variant::construct(expected, NULL, 0, ce, false); + default_input_values[i] = Variant::construct(expected, nullptr, 0, ce, false); } } } } Array VisualScriptNode::_get_default_input_values() const { - //validate on save, since on load there is little info about this Array values = default_input_values; values.resize(get_input_value_port_count()); @@ -114,7 +108,6 @@ String VisualScriptNode::get_text() const { } void VisualScriptNode::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_visual_script"), &VisualScriptNode::get_visual_script); ClassDB::bind_method(D_METHOD("set_default_input_value", "port_idx", "value"), &VisualScriptNode::set_default_input_value); ClassDB::bind_method(D_METHOD("get_default_input_value", "port_idx"), &VisualScriptNode::get_default_input_value); @@ -127,7 +120,6 @@ void VisualScriptNode::_bind_methods() { } VisualScriptNode::TypeGuess VisualScriptNode::guess_output_type(TypeGuess *p_inputs, int p_output) const { - PropertyInfo pinfo = get_output_value_port_info(p_output); TypeGuess tg; @@ -141,9 +133,9 @@ VisualScriptNode::TypeGuess VisualScriptNode::guess_output_type(TypeGuess *p_inp } Ref<VisualScript> VisualScriptNode::get_visual_script() const { - - if (scripts_used.size()) + if (scripts_used.size()) { return Ref<VisualScript>(scripts_used.front()->get()); + } return Ref<VisualScript>(); } @@ -157,13 +149,11 @@ VisualScriptNode::VisualScriptNode() { ///////////////////// VisualScriptNodeInstance::VisualScriptNodeInstance() { - - sequence_outputs = NULL; - input_ports = NULL; + sequence_outputs = nullptr; + input_ports = nullptr; } VisualScriptNodeInstance::~VisualScriptNodeInstance() { - if (sequence_outputs) { memdelete_arr(sequence_outputs); } @@ -178,7 +168,6 @@ VisualScriptNodeInstance::~VisualScriptNodeInstance() { } void VisualScript::add_function(const StringName &p_name) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!String(p_name).is_valid_identifier()); ERR_FAIL_COND(functions.has(p_name)); @@ -188,16 +177,14 @@ void VisualScript::add_function(const StringName &p_name) { } bool VisualScript::has_function(const StringName &p_name) const { - return functions.has(p_name); } -void VisualScript::remove_function(const StringName &p_name) { +void VisualScript::remove_function(const StringName &p_name) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!functions.has(p_name)); for (Map<int, Function::NodeData>::Element *E = functions[p_name].nodes.front(); E; E = E->next()) { - E->get().node->disconnect("ports_changed", callable_mp(this, &VisualScript::_node_ports_changed)); E->get().node->scripts_used.erase(this); } @@ -206,11 +193,11 @@ void VisualScript::remove_function(const StringName &p_name) { } void VisualScript::rename_function(const StringName &p_name, const StringName &p_new_name) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!functions.has(p_name)); - if (p_new_name == p_name) + if (p_new_name == p_name) { return; + } ERR_FAIL_COND(!String(p_new_name).is_valid_identifier()); @@ -223,19 +210,16 @@ void VisualScript::rename_function(const StringName &p_name, const StringName &p } void VisualScript::set_function_scroll(const StringName &p_name, const Vector2 &p_scroll) { - ERR_FAIL_COND(!functions.has(p_name)); functions[p_name].scroll = p_scroll; } Vector2 VisualScript::get_function_scroll(const StringName &p_name) const { - ERR_FAIL_COND_V(!functions.has(p_name), Vector2()); return functions[p_name].scroll; } void VisualScript::get_function_list(List<StringName> *r_functions) const { - for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { r_functions->push_back(E->key()); } @@ -244,18 +228,15 @@ void VisualScript::get_function_list(List<StringName> *r_functions) const { } int VisualScript::get_function_node_id(const StringName &p_name) const { - ERR_FAIL_COND_V(!functions.has(p_name), -1); return functions[p_name].function_id; } void VisualScript::_node_ports_changed(int p_id) { - StringName function; for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - if (E->get().nodes.has(p_id)) { function = E->key(); break; @@ -276,11 +257,9 @@ void VisualScript::_node_ports_changed(int p_id) { for (Set<SequenceConnection>::Element *E = func.sequence_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id && E->get().from_output >= vsn->get_output_sequence_port_count()) { - to_remove.push_back(E->get()); } if (E->get().to_node == p_id && !vsn->has_input_sequence_port()) { - to_remove.push_back(E->get()); } } @@ -292,7 +271,6 @@ void VisualScript::_node_ports_changed(int p_id) { } { - List<DataConnection> to_remove; for (Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) { @@ -317,12 +295,10 @@ void VisualScript::_node_ports_changed(int p_id) { } void VisualScript::add_node(const StringName &p_func, int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!functions.has(p_func)); for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - ERR_FAIL_COND(E->get().nodes.has(p_id)); //id can exist only one in script, even for different functions } @@ -348,7 +324,6 @@ void VisualScript::add_node(const StringName &p_func, int p_id, const Ref<Visual } void VisualScript::remove_node(const StringName &p_func, int p_id) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -370,7 +345,6 @@ void VisualScript::remove_node(const StringName &p_func, int p_id) { } { - List<DataConnection> to_remove; for (Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) { @@ -396,7 +370,6 @@ void VisualScript::remove_node(const StringName &p_func, int p_id) { } bool VisualScript::has_node(const StringName &p_func, int p_id) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); const Function &func = functions[p_func]; @@ -404,7 +377,6 @@ bool VisualScript::has_node(const StringName &p_func, int p_id) const { } Ref<VisualScriptNode> VisualScript::get_node(const StringName &p_func, int p_id) const { - ERR_FAIL_COND_V(!functions.has(p_func), Ref<VisualScriptNode>()); const Function &func = functions[p_func]; @@ -414,7 +386,6 @@ Ref<VisualScriptNode> VisualScript::get_node(const StringName &p_func, int p_id) } void VisualScript::set_node_position(const StringName &p_func, int p_id, const Point2 &p_pos) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -424,7 +395,6 @@ void VisualScript::set_node_position(const StringName &p_func, int p_id, const P } Point2 VisualScript::get_node_position(const StringName &p_func, int p_id) const { - ERR_FAIL_COND_V(!functions.has(p_func), Point2()); const Function &func = functions[p_func]; @@ -433,7 +403,6 @@ Point2 VisualScript::get_node_position(const StringName &p_func, int p_id) const } void VisualScript::get_node_list(const StringName &p_func, List<int> *r_nodes) const { - ERR_FAIL_COND(!functions.has(p_func)); const Function &func = functions[p_func]; @@ -443,7 +412,6 @@ void VisualScript::get_node_list(const StringName &p_func, List<int> *r_nodes) c } void VisualScript::sequence_connect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -458,7 +426,6 @@ void VisualScript::sequence_connect(const StringName &p_func, int p_from_node, i } void VisualScript::sequence_disconnect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) { - ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -472,7 +439,6 @@ void VisualScript::sequence_disconnect(const StringName &p_func, int p_from_node } bool VisualScript::has_sequence_connection(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); const Function &func = functions[p_func]; @@ -485,7 +451,6 @@ bool VisualScript::has_sequence_connection(const StringName &p_func, int p_from_ } void VisualScript::get_sequence_connection_list(const StringName &p_func, List<SequenceConnection> *r_connection) const { - ERR_FAIL_COND(!functions.has(p_func)); const Function &func = functions[p_func]; @@ -495,7 +460,6 @@ void VisualScript::get_sequence_connection_list(const StringName &p_func, List<S } void VisualScript::data_connect(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -512,7 +476,6 @@ void VisualScript::data_connect(const StringName &p_func, int p_from_node, int p } void VisualScript::data_disconnect(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { - ERR_FAIL_COND(!functions.has(p_func)); Function &func = functions[p_func]; @@ -528,7 +491,6 @@ void VisualScript::data_disconnect(const StringName &p_func, int p_from_node, in } bool VisualScript::has_data_connection(const StringName &p_func, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); const Function &func = functions[p_func]; @@ -542,20 +504,19 @@ bool VisualScript::has_data_connection(const StringName &p_func, int p_from_node } bool VisualScript::is_input_value_port_connected(const StringName &p_func, int p_node, int p_port) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); const Function &func = functions[p_func]; for (const Set<DataConnection>::Element *E = func.data_connections.front(); E; E = E->next()) { - if (E->get().to_node == p_node && E->get().to_port == p_port) + if (E->get().to_node == p_node && E->get().to_port == p_port) { return true; + } } return false; } bool VisualScript::get_input_value_port_connection_source(const StringName &p_func, int p_node, int p_port, int *r_node, int *r_port) const { - ERR_FAIL_COND_V(!functions.has(p_func), false); const Function &func = functions[p_func]; @@ -571,7 +532,6 @@ bool VisualScript::get_input_value_port_connection_source(const StringName &p_fu } void VisualScript::get_data_connection_list(const StringName &p_func, List<DataConnection> *r_connection) const { - ERR_FAIL_COND(!functions.has(p_func)); const Function &func = functions[p_func]; @@ -585,7 +545,6 @@ void VisualScript::set_tool_enabled(bool p_enabled) { } void VisualScript::add_variable(const StringName &p_name, const Variant &p_default_value, bool p_export) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!String(p_name).is_valid_identifier()); ERR_FAIL_COND(variables.has(p_name)); @@ -605,12 +564,10 @@ void VisualScript::add_variable(const StringName &p_name, const Variant &p_defau } bool VisualScript::has_variable(const StringName &p_name) const { - return variables.has(p_name); } void VisualScript::remove_variable(const StringName &p_name) { - ERR_FAIL_COND(!variables.has(p_name)); variables.erase(p_name); @@ -620,7 +577,6 @@ void VisualScript::remove_variable(const StringName &p_name) { } void VisualScript::set_variable_default_value(const StringName &p_name, const Variant &p_value) { - ERR_FAIL_COND(!variables.has(p_name)); variables[p_name].default_value = p_value; @@ -629,13 +585,13 @@ void VisualScript::set_variable_default_value(const StringName &p_name, const Va _update_placeholders(); #endif } -Variant VisualScript::get_variable_default_value(const StringName &p_name) const { +Variant VisualScript::get_variable_default_value(const StringName &p_name) const { ERR_FAIL_COND_V(!variables.has(p_name), Variant()); return variables[p_name].default_value; } -void VisualScript::set_variable_info(const StringName &p_name, const PropertyInfo &p_info) { +void VisualScript::set_variable_info(const StringName &p_name, const PropertyInfo &p_info) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!variables.has(p_name)); variables[p_name].info = p_info; @@ -645,14 +601,13 @@ void VisualScript::set_variable_info(const StringName &p_name, const PropertyInf _update_placeholders(); #endif } -PropertyInfo VisualScript::get_variable_info(const StringName &p_name) const { +PropertyInfo VisualScript::get_variable_info(const StringName &p_name) const { ERR_FAIL_COND_V(!variables.has(p_name), PropertyInfo()); return variables[p_name].info; } void VisualScript::set_variable_export(const StringName &p_name, bool p_export) { - ERR_FAIL_COND(!variables.has(p_name)); variables[p_name]._export = p_export; @@ -662,30 +617,32 @@ void VisualScript::set_variable_export(const StringName &p_name, bool p_export) } bool VisualScript::get_variable_export(const StringName &p_name) const { - ERR_FAIL_COND_V(!variables.has(p_name), false); return variables[p_name]._export; } void VisualScript::_set_variable_info(const StringName &p_name, const Dictionary &p_info) { - PropertyInfo pinfo; - if (p_info.has("type")) + if (p_info.has("type")) { pinfo.type = Variant::Type(int(p_info["type"])); - if (p_info.has("name")) + } + if (p_info.has("name")) { pinfo.name = p_info["name"]; - if (p_info.has("hint")) + } + if (p_info.has("hint")) { pinfo.hint = PropertyHint(int(p_info["hint"])); - if (p_info.has("hint_string")) + } + if (p_info.has("hint_string")) { pinfo.hint_string = p_info["hint_string"]; - if (p_info.has("usage")) + } + if (p_info.has("usage")) { pinfo.usage = p_info["usage"]; + } set_variable_info(p_name, pinfo); } Dictionary VisualScript::_get_variable_info(const StringName &p_name) const { - PropertyInfo pinfo = get_variable_info(p_name); Dictionary d; d["type"] = pinfo.type; @@ -698,7 +655,6 @@ Dictionary VisualScript::_get_variable_info(const StringName &p_name) const { } void VisualScript::get_variable_list(List<StringName> *r_variables) const { - for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) { r_variables->push_back(E->key()); } @@ -707,17 +663,16 @@ void VisualScript::get_variable_list(List<StringName> *r_variables) const { } void VisualScript::set_instance_base_type(const StringName &p_type) { - ERR_FAIL_COND(instances.size()); base_type = p_type; } void VisualScript::rename_variable(const StringName &p_name, const StringName &p_new_name) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!variables.has(p_name)); - if (p_new_name == p_name) + if (p_new_name == p_name) { return; + } ERR_FAIL_COND(!String(p_new_name).is_valid_identifier()); @@ -727,10 +682,31 @@ void VisualScript::rename_variable(const StringName &p_name, const StringName &p variables[p_new_name] = variables[p_name]; variables.erase(p_name); + + List<StringName> funcs; + get_function_list(&funcs); + for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { // loop through all the functions + List<int> ids; + get_node_list(F->get(), &ids); + for (List<int>::Element *E = ids.front(); E; E = E->next()) { + Ref<VisualScriptVariableGet> nodeget = get_node(F->get(), E->get()); + if (nodeget.is_valid()) { + if (nodeget->get_variable() == p_name) { + nodeget->set_variable(p_new_name); + } + } else { + Ref<VisualScriptVariableSet> nodeset = get_node(F->get(), E->get()); + if (nodeset.is_valid()) { + if (nodeset->get_variable() == p_name) { + nodeset->set_variable(p_new_name); + } + } + } + } + } } void VisualScript::add_custom_signal(const StringName &p_name) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!String(p_name).is_valid_identifier()); ERR_FAIL_COND(custom_signals.has(p_name)); @@ -739,48 +715,49 @@ void VisualScript::add_custom_signal(const StringName &p_name) { } bool VisualScript::has_custom_signal(const StringName &p_name) const { - return custom_signals.has(p_name); } -void VisualScript::custom_signal_add_argument(const StringName &p_func, Variant::Type p_type, const String &p_name, int p_index) { +void VisualScript::custom_signal_add_argument(const StringName &p_func, Variant::Type p_type, const String &p_name, int p_index) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!custom_signals.has(p_func)); Argument arg; arg.type = p_type; arg.name = p_name; - if (p_index < 0) + if (p_index < 0) { custom_signals[p_func].push_back(arg); - else + } else { custom_signals[p_func].insert(0, arg); + } } -void VisualScript::custom_signal_set_argument_type(const StringName &p_func, int p_argidx, Variant::Type p_type) { +void VisualScript::custom_signal_set_argument_type(const StringName &p_func, int p_argidx, Variant::Type p_type) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!custom_signals.has(p_func)); ERR_FAIL_INDEX(p_argidx, custom_signals[p_func].size()); custom_signals[p_func].write[p_argidx].type = p_type; } -Variant::Type VisualScript::custom_signal_get_argument_type(const StringName &p_func, int p_argidx) const { +Variant::Type VisualScript::custom_signal_get_argument_type(const StringName &p_func, int p_argidx) const { ERR_FAIL_COND_V(!custom_signals.has(p_func), Variant::NIL); ERR_FAIL_INDEX_V(p_argidx, custom_signals[p_func].size(), Variant::NIL); return custom_signals[p_func][p_argidx].type; } + void VisualScript::custom_signal_set_argument_name(const StringName &p_func, int p_argidx, const String &p_name) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!custom_signals.has(p_func)); ERR_FAIL_INDEX(p_argidx, custom_signals[p_func].size()); custom_signals[p_func].write[p_argidx].name = p_name; } -String VisualScript::custom_signal_get_argument_name(const StringName &p_func, int p_argidx) const { +String VisualScript::custom_signal_get_argument_name(const StringName &p_func, int p_argidx) const { ERR_FAIL_COND_V(!custom_signals.has(p_func), String()); ERR_FAIL_INDEX_V(p_argidx, custom_signals[p_func].size(), String()); return custom_signals[p_func][p_argidx].name; } -void VisualScript::custom_signal_remove_argument(const StringName &p_func, int p_argidx) { +void VisualScript::custom_signal_remove_argument(const StringName &p_func, int p_argidx) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!custom_signals.has(p_func)); ERR_FAIL_INDEX(p_argidx, custom_signals[p_func].size()); @@ -788,12 +765,11 @@ void VisualScript::custom_signal_remove_argument(const StringName &p_func, int p } int VisualScript::custom_signal_get_argument_count(const StringName &p_func) const { - ERR_FAIL_COND_V(!custom_signals.has(p_func), 0); return custom_signals[p_func].size(); } -void VisualScript::custom_signal_swap_argument(const StringName &p_func, int p_argidx, int p_with_argidx) { +void VisualScript::custom_signal_swap_argument(const StringName &p_func, int p_argidx, int p_with_argidx) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!custom_signals.has(p_func)); ERR_FAIL_INDEX(p_argidx, custom_signals[p_func].size()); @@ -801,19 +777,19 @@ void VisualScript::custom_signal_swap_argument(const StringName &p_func, int p_a SWAP(custom_signals[p_func].write[p_argidx], custom_signals[p_func].write[p_with_argidx]); } -void VisualScript::remove_custom_signal(const StringName &p_name) { +void VisualScript::remove_custom_signal(const StringName &p_name) { ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!custom_signals.has(p_name)); custom_signals.erase(p_name); } void VisualScript::rename_custom_signal(const StringName &p_name, const StringName &p_new_name) { - ERR_FAIL_COND(instances.size()); ERR_FAIL_COND(!custom_signals.has(p_name)); - if (p_new_name == p_name) + if (p_new_name == p_name) { return; + } ERR_FAIL_COND(!String(p_new_name).is_valid_identifier()); @@ -826,7 +802,6 @@ void VisualScript::rename_custom_signal(const StringName &p_name, const StringNa } void VisualScript::get_custom_signal_list(List<StringName> *r_custom_signals) const { - for (const Map<StringName, Vector<Argument>>::Element *E = custom_signals.front(); E; E = E->next()) { r_custom_signals->push_back(E->key()); } @@ -835,11 +810,11 @@ void VisualScript::get_custom_signal_list(List<StringName> *r_custom_signals) co } int VisualScript::get_available_id() const { - int max_id = 0; for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - if (E->get().nodes.empty()) + if (E->get().nodes.empty()) { continue; + } int last_id = E->get().nodes.back()->key(); max_id = MAX(max_id, last_id + 1); @@ -851,12 +826,10 @@ int VisualScript::get_available_id() const { ///////////////////////////////// bool VisualScript::can_instance() const { - return true; //ScriptServer::is_scripting_enabled(); } StringName VisualScript::get_instance_base_type() const { - return base_type; } @@ -866,21 +839,20 @@ Ref<Script> VisualScript::get_base_script() const { #ifdef TOOLS_ENABLED void VisualScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { - placeholders.erase(p_placeholder); } void VisualScript::_update_placeholders() { - - if (placeholders.size() == 0) + if (placeholders.size() == 0) { return; //no bother if no placeholders + } List<PropertyInfo> pinfo; Map<StringName, Variant> values; for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) { - - if (!E->get()._export) + if (!E->get()._export) { continue; + } PropertyInfo p = E->get().info; p.name = String(E->key()); @@ -889,7 +861,6 @@ void VisualScript::_update_placeholders() { } for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { - E->get()->update(pinfo, values); } } @@ -897,11 +868,9 @@ void VisualScript::_update_placeholders() { #endif ScriptInstance *VisualScript::instance_create(Object *p_this) { - #ifdef TOOLS_ENABLED if (!ScriptServer::is_scripting_enabled() && !is_tool_script) { - PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(VisualScriptLanguage::singleton, Ref<Script>((Script *)this), p_this)); placeholders.insert(sins); @@ -909,9 +878,9 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) { Map<StringName, Variant> values; for (Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) { - - if (!E->get()._export) + if (!E->get()._export) { continue; + } PropertyInfo p = E->get().info; p.name = String(E->key()); @@ -938,17 +907,14 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) { } bool VisualScript::instance_has(const Object *p_this) const { - return instances.has((Object *)p_this); } bool VisualScript::has_source_code() const { - return false; } String VisualScript::get_source_code() const { - return String(); } @@ -956,12 +922,10 @@ void VisualScript::set_source_code(const String &p_code) { } Error VisualScript::reload(bool p_keep_state) { - return OK; } bool VisualScript::is_tool() const { - return is_tool_script; } @@ -970,19 +934,15 @@ bool VisualScript::is_valid() const { } ScriptLanguage *VisualScript::get_language() const { - return VisualScriptLanguage::singleton; } bool VisualScript::has_script_signal(const StringName &p_signal) const { - return custom_signals.has(p_signal); } void VisualScript::get_script_signal_list(List<MethodInfo> *r_signals) const { - for (const Map<StringName, Vector<Argument>>::Element *E = custom_signals.front(); E; E = E->next()) { - MethodInfo mi; mi.name = E->key(); for (int i = 0; i < E->get().size(); i++) { @@ -997,21 +957,19 @@ void VisualScript::get_script_signal_list(List<MethodInfo> *r_signals) const { } bool VisualScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { - - if (!variables.has(p_property)) + if (!variables.has(p_property)) { return false; + } r_value = variables[p_property].default_value; return true; } -void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const { +void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const { for (Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - MethodInfo mi; mi.name = E->key(); if (E->get().function_id >= 0) { - Ref<VisualScriptFunction> func = E->get().nodes[E->get().function_id].node; if (func.is_valid()) { for (int i = 0; i < func->get_argument_count(); i++) { @@ -1028,22 +986,20 @@ void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const { } bool VisualScript::has_method(const StringName &p_method) const { - return functions.has(p_method); } -MethodInfo VisualScript::get_method_info(const StringName &p_method) const { +MethodInfo VisualScript::get_method_info(const StringName &p_method) const { const Map<StringName, Function>::Element *E = functions.find(p_method); - if (!E) + if (!E) { return MethodInfo(); + } MethodInfo mi; mi.name = E->key(); if (E->get().function_id >= 0) { - Ref<VisualScriptFunction> func = E->get().nodes[E->get().function_id].node; if (func.is_valid()) { - for (int i = 0; i < func->get_argument_count(); i++) { PropertyInfo arg; arg.name = func->get_argument_name(i); @@ -1061,7 +1017,6 @@ MethodInfo VisualScript::get_method_info(const StringName &p_method) const { } void VisualScript::get_script_property_list(List<PropertyInfo> *p_list) const { - List<StringName> vars; get_variable_list(&vars); @@ -1078,8 +1033,9 @@ int VisualScript::get_member_line(const StringName &p_member) const { #ifdef TOOLS_ENABLED if (has_function(p_member)) { for (Map<int, Function::NodeData>::Element *E = functions[p_member].nodes.front(); E; E = E->next()) { - if (Object::cast_to<VisualScriptFunction>(E->get().node.ptr())) + if (Object::cast_to<VisualScriptFunction>(E->get().node.ptr())) { return E->key(); + } } } #endif @@ -1088,9 +1044,7 @@ int VisualScript::get_member_line(const StringName &p_member) const { #ifdef TOOLS_ENABLED bool VisualScript::are_subnodes_edited() const { - for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - for (const Map<int, Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) { if (F->get().node->is_edited()) { return true; @@ -1157,15 +1111,14 @@ MultiplayerAPI::RPCMode VisualScript::get_rset_mode(const StringName &p_variable } void VisualScript::_set_data(const Dictionary &p_data) { - Dictionary d = p_data; - if (d.has("base_type")) + if (d.has("base_type")) { base_type = d["base_type"]; + } variables.clear(); Array vars = d["variables"]; for (int i = 0; i < vars.size(); i++) { - Dictionary v = vars[i]; StringName name = v["name"]; add_variable(name); @@ -1177,7 +1130,6 @@ void VisualScript::_set_data(const Dictionary &p_data) { custom_signals.clear(); Array sigs = d["signals"]; for (int i = 0; i < sigs.size(); i++) { - Dictionary cs = sigs[i]; add_custom_signal(cs["name"]); @@ -1194,7 +1146,6 @@ void VisualScript::_set_data(const Dictionary &p_data) { Vector2 last_size = Vector2(0.0, 0.0); for (int i = 0; i < funcs.size(); i++) { - Dictionary func = funcs[i]; StringName name = func["name"]; @@ -1244,22 +1195,21 @@ void VisualScript::_set_data(const Dictionary &p_data) { Array sequence_connections = func["sequence_connections"]; for (int j = 0; j < sequence_connections.size(); j += 3) { - sequence_connect(name, sequence_connections[j + 0], sequence_connections[j + 1], sequence_connections[j + 2]); } Array data_connections = func["data_connections"]; for (int j = 0; j < data_connections.size(); j += 4) { - data_connect(name, data_connections[j + 0], data_connections[j + 1], data_connections[j + 2], data_connections[j + 3]); } } - if (d.has("is_tool_script")) + if (d.has("is_tool_script")) { is_tool_script = d["is_tool_script"]; - else + } else { is_tool_script = false; + } // Takes all the rpc methods rpc_functions.clear(); @@ -1287,12 +1237,10 @@ void VisualScript::_set_data(const Dictionary &p_data) { } Dictionary VisualScript::_get_data() const { - Dictionary d; d["base_type"] = base_type; Array vars; for (const Map<StringName, Variable>::Element *E = variables.front(); E; E = E->next()) { - Dictionary var = _get_variable_info(E->key()); var["name"] = E->key(); //make sure it's the right one var["default_value"] = E->get().default_value; @@ -1303,7 +1251,6 @@ Dictionary VisualScript::_get_data() const { Array sigs; for (const Map<StringName, Vector<Argument>>::Element *E = custom_signals.front(); E; E = E->next()) { - Dictionary cs; cs["name"] = E->key(); Array args; @@ -1321,7 +1268,6 @@ Dictionary VisualScript::_get_data() const { Array funcs; for (const Map<StringName, Function>::Element *E = functions.front(); E; E = E->next()) { - Dictionary func; func["name"] = E->key(); func["function_id"] = E->get().function_id; @@ -1330,7 +1276,6 @@ Dictionary VisualScript::_get_data() const { Array nodes; for (const Map<int, Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) { - nodes.push_back(F->key()); nodes.push_back(F->get().pos); nodes.push_back(F->get().node); @@ -1341,7 +1286,6 @@ Dictionary VisualScript::_get_data() const { Array sequence_connections; for (const Set<SequenceConnection>::Element *F = E->get().sequence_connections.front(); F; F = F->next()) { - sequence_connections.push_back(F->get().from_node); sequence_connections.push_back(F->get().from_output); sequence_connections.push_back(F->get().to_node); @@ -1352,7 +1296,6 @@ Dictionary VisualScript::_get_data() const { Array data_connections; for (const Set<DataConnection>::Element *F = E->get().data_connections.front(); F; F = F->next()) { - data_connections.push_back(F->get().from_node); data_connections.push_back(F->get().from_port); data_connections.push_back(F->get().to_node); @@ -1372,7 +1315,6 @@ Dictionary VisualScript::_get_data() const { } void VisualScript::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_function", "name"), &VisualScript::add_function); ClassDB::bind_method(D_METHOD("has_function", "name"), &VisualScript::has_function); ClassDB::bind_method(D_METHOD("remove_function", "name"), &VisualScript::remove_function); @@ -1435,11 +1377,14 @@ void VisualScript::_bind_methods() { } VisualScript::VisualScript() { - base_type = "Object"; is_tool_script = false; } +bool VisualScript::inherits_script(const Ref<Script> &p_script) const { + return this == p_script.ptr(); //there is no inheritance in visual scripts, so this is enough +} + StringName VisualScript::get_default_func() const { return StringName("f_312843592"); } @@ -1458,7 +1403,6 @@ Set<int> VisualScript::get_output_sequence_ports_connected(const String &edited_ } VisualScript::~VisualScript() { - while (!functions.empty()) { remove_function(functions.front()->key()); } @@ -1467,10 +1411,10 @@ VisualScript::~VisualScript() { //////////////////////////////////////////// bool VisualScriptInstance::set(const StringName &p_name, const Variant &p_value) { - Map<StringName, Variant>::Element *E = variables.find(p_name); - if (!E) + if (!E) { return false; + } E->get() = p_value; @@ -1478,45 +1422,45 @@ bool VisualScriptInstance::set(const StringName &p_name, const Variant &p_value) } bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const { - const Map<StringName, Variant>::Element *E = variables.find(p_name); - if (!E) + if (!E) { return false; + } r_ret = E->get(); return true; } -void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { +void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { for (const Map<StringName, VisualScript::Variable>::Element *E = script->variables.front(); E; E = E->next()) { - - if (!E->get()._export) + if (!E->get()._export) { continue; + } PropertyInfo p = E->get().info; p.name = String(E->key()); p.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; p_properties->push_back(p); } } -Variant::Type VisualScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { +Variant::Type VisualScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { const Map<StringName, VisualScript::Variable>::Element *E = script->variables.find(p_name); if (!E) { - if (r_is_valid) + if (r_is_valid) { *r_is_valid = false; + } ERR_FAIL_V(Variant::NIL); } - if (r_is_valid) + if (r_is_valid) { *r_is_valid = true; + } return E->get().info.type; } void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const { - for (const Map<StringName, VisualScript::Function>::Element *E = script->functions.front(); E; E = E->next()) { - if (E->key() == script->get_default_func()) { continue; } @@ -1524,10 +1468,8 @@ void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const { MethodInfo mi; mi.name = E->key(); if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) { - Ref<VisualScriptFunction> vsf = E->get().nodes[E->get().function_id].node; if (vsf.is_valid()) { - for (int i = 0; i < vsf->get_argument_count(); i++) { PropertyInfo arg; arg.name = vsf->get_argument_name(i); @@ -1545,10 +1487,11 @@ void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const { p_list->push_back(mi); } } -bool VisualScriptInstance::has_method(const StringName &p_method) const { - if (p_method == script->get_default_func()) +bool VisualScriptInstance::has_method(const StringName &p_method) const { + if (p_method == script->get_default_func()) { return false; + } return script->functions.has(p_method); } @@ -1557,29 +1500,27 @@ bool VisualScriptInstance::has_method(const StringName &p_method) const { #define VSDEBUG(m_text) void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int p_pass, int *pass_stack, const Variant **input_args, Variant **output_args, Variant *variant_stack, Callable::CallError &r_error, String &error_str, VisualScriptNodeInstance **r_error_node) { - ERR_FAIL_COND(node->pass_idx == -1); - if (pass_stack[node->pass_idx] == p_pass) + if (pass_stack[node->pass_idx] == p_pass) { return; + } pass_stack[node->pass_idx] = p_pass; if (!node->dependencies.empty()) { - int dc = node->dependencies.size(); VisualScriptNodeInstance **deps = node->dependencies.ptrw(); for (int i = 0; i < dc; i++) { - _dependency_step(deps[i], p_pass, pass_stack, input_args, output_args, variant_stack, r_error, error_str, r_error_node); - if (r_error.error != Callable::CallError::CALL_OK) + if (r_error.error != Callable::CallError::CALL_OK) { return; + } } } for (int i = 0; i < node->input_port_count; i++) { - int index = node->input_ports[i] & VisualScriptNodeInstance::INPUT_MASK; if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) { @@ -1594,7 +1535,7 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int output_args[i] = &variant_stack[node->output_ports[i]]; } - Variant *working_mem = node->working_mem_idx >= 0 ? &variant_stack[node->working_mem_idx] : (Variant *)NULL; + Variant *working_mem = node->working_mem_idx >= 0 ? &variant_stack[node->working_mem_idx] : (Variant *)nullptr; node->step(input_args, output_args, VisualScriptNodeInstance::START_MODE_BEGIN_SEQUENCE, working_mem, r_error, error_str); //ignore return @@ -1604,7 +1545,6 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int } Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p_stack, int p_stack_size, VisualScriptNodeInstance *p_node, int p_flow_stack_pos, int p_pass, bool p_resuming_yield, Callable::CallError &r_error) { - Map<StringName, Function>::Element *F = functions.find(p_method); ERR_FAIL_COND_V(!F, Variant()); Function *f = &F->get(); @@ -1615,8 +1555,8 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p const Variant **input_args = (const Variant **)(sequence_bits + f->node_count); Variant **output_args = (Variant **)(input_args + max_input_args); int flow_max = f->flow_stack_size; - int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)NULL; - int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)NULL; + int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)nullptr; + int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)nullptr; String error_str; @@ -1624,7 +1564,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p bool error = false; int current_node_id = f->node; Variant return_value; - Variant *working_mem = NULL; + Variant *working_mem = nullptr; int flow_stack_pos = p_flow_stack_pos; @@ -1635,7 +1575,6 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p #endif while (true) { - p_pass++; //increment pass current_node_id = node->get_id(); @@ -1643,7 +1582,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p VSDEBUG("AT STACK POS: " + itos(flow_stack_pos)); //setup working mem - working_mem = node->working_mem_idx >= 0 ? &variant_stack[node->working_mem_idx] : (Variant *)NULL; + working_mem = node->working_mem_idx >= 0 ? &variant_stack[node->working_mem_idx] : (Variant *)nullptr; VSDEBUG("WORKING MEM: " + itos(node->working_mem_idx)); @@ -1654,16 +1593,13 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p input_args[i] = &variant_stack[i]; } } else { - //run dependencies first if (!node->dependencies.empty()) { - int dc = node->dependencies.size(); VisualScriptNodeInstance **deps = node->dependencies.ptrw(); for (int i = 0; i < dc; i++) { - _dependency_step(deps[i], p_pass, pass_stack, input_args, output_args, variant_stack, r_error, error_str, &node); if (r_error.error != Callable::CallError::CALL_OK) { error = true; @@ -1674,12 +1610,10 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } if (!error) { - //setup input pointers normally VSDEBUG("INPUT PORTS: " + itos(node->input_port_count)); for (int i = 0; i < node->input_port_count; i++) { - int index = node->input_ports[i] & VisualScriptNodeInstance::INPUT_MASK; if (node->input_ports[i] & VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT) { @@ -1695,8 +1629,9 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } } - if (error) + if (error) { break; + } //setup output pointers @@ -1742,7 +1677,6 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } else { Ref<VisualScriptFunctionState> state = *working_mem; if (!state.is_valid()) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; error_str = RTR("Node yielded, but did not return a function state in the first working memory."); error = true; @@ -1781,15 +1715,17 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p bool do_break = false; if (EngineDebugger::get_script_debugger()->get_lines_left() > 0) { - - if (EngineDebugger::get_script_debugger()->get_depth() <= 0) + if (EngineDebugger::get_script_debugger()->get_depth() <= 0) { EngineDebugger::get_script_debugger()->set_lines_left(EngineDebugger::get_script_debugger()->get_lines_left() - 1); - if (EngineDebugger::get_script_debugger()->get_lines_left() <= 0) + } + if (EngineDebugger::get_script_debugger()->get_lines_left() <= 0) { do_break = true; + } } - if (EngineDebugger::get_script_debugger()->is_breakpoint(current_node_id, source)) + if (EngineDebugger::get_script_debugger()->is_breakpoint(current_node_id, source)) { do_break = true; + } if (do_break) { VisualScriptLanguage::singleton->debug_break("Breakpoint", true); @@ -1804,7 +1740,6 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p if (ret & VisualScriptNodeInstance::STEP_EXIT_FUNCTION_BIT) { if (node->get_working_memory_size() == 0) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; error_str = RTR("Return value must be assigned to first element of node working memory! Fix your node please."); error = true; @@ -1817,7 +1752,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p break; //exit function requested, bye } - VisualScriptNodeInstance *next = NULL; //next node + VisualScriptNodeInstance *next = nullptr; //next node if ((ret == output || ret & VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) && node->sequence_output_count) { //if no exit bit was set, and has sequence outputs, guess next node @@ -1837,13 +1772,11 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } if (flow_stack) { - //update flow stack pos (may have changed) flow_stack[flow_stack_pos] = current_node_id; //add stack push bit if requested if (ret & VisualScriptNodeInstance::STEP_FLAG_PUSH_STACK_BIT) { - flow_stack[flow_stack_pos] |= VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT; sequence_bits[node->sequence_index] = true; //remember sequence bit VSDEBUG("NEXT SEQ - FLAG BIT"); @@ -1864,7 +1797,6 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p break; //simply exit without value or error } } else if (next) { - if (sequence_bits[next->sequence_index]) { // what happened here is that we are entering a node that is in the middle of doing a sequence (pushed stack) from the front // because each node has a working memory, we can't really do a sub-sequence @@ -1874,7 +1806,6 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p bool found = false; for (int i = flow_stack_pos; i >= 0; i--) { - if ((flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK) == next->get_id()) { flow_stack_pos = i; //roll back and remove bit flow_stack[i] = next->get_id(); @@ -1916,10 +1847,8 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p bool found = false; for (int i = flow_stack_pos; i >= 0; i--) { - VSDEBUG("FS " + itos(i) + " - " + itos(flow_stack[i])); if (flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_PUSHED_BIT) { - node = instances[flow_stack[i] & VisualScriptNodeInstance::FLOW_STACK_MASK]; flow_stack_pos = i; found = true; @@ -1935,13 +1864,11 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p VSDEBUG("NO NEXT NODE, GO BACK TO: " + itos(flow_stack_pos)); } } else { - node = next; //stackless mode, simply assign next node } } if (error) { - //error // function, file, line, error, explanation String err_file = script->get_path(); @@ -1949,7 +1876,6 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p int err_line = current_node_id; //not a line but it works as one if (node && (r_error.error != Callable::CallError::CALL_ERROR_INVALID_METHOD || error_str == String())) { - if (error_str != String()) { error_str += " "; } @@ -1972,13 +1898,11 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p // debugger break did not happen if (!VisualScriptLanguage::singleton->debug_break(error_str, false)) { - _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, error_str.utf8().get_data(), ERR_HANDLER_SCRIPT); } //} } else { - //return_value= } @@ -1997,7 +1921,6 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p } Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_OK; //ok by default Map<StringName, Function>::Element *F = functions.find(p_method); @@ -2033,8 +1956,8 @@ Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p const Variant **input_args = (const Variant **)(sequence_bits + f->node_count); Variant **output_args = (Variant **)(input_args + max_input_args); int flow_max = f->flow_stack_size; - int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)NULL; - int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)NULL; + int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)nullptr; + int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)nullptr; for (int i = 0; i < f->node_count; i++) { sequence_bits[i] = false; //all starts as false @@ -2085,7 +2008,6 @@ Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p } void VisualScriptInstance::notification(int p_notification) { - //do nothing as this is called using virtual Variant what = p_notification; @@ -2097,25 +2019,27 @@ void VisualScriptInstance::notification(int p_notification) { String VisualScriptInstance::to_string(bool *r_valid) { if (has_method(CoreStringNames::get_singleton()->_to_string)) { Callable::CallError ce; - Variant ret = call(CoreStringNames::get_singleton()->_to_string, NULL, 0, ce); + Variant ret = call(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce); if (ce.error == Callable::CallError::CALL_OK) { if (ret.get_type() != Variant::STRING) { - if (r_valid) + if (r_valid) { *r_valid = false; + } ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String."); } - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret.operator String(); } } - if (r_valid) + if (r_valid) { *r_valid = false; + } return String(); } Ref<Script> VisualScriptInstance::get_script() const { - return script; } @@ -2160,7 +2084,6 @@ MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_ } void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) { - script = p_script; owner = p_owner; source = p_script->get_path(); @@ -2171,16 +2094,21 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o if (Object::cast_to<Node>(p_owner)) { //turn on these if they exist and base is a node Node *node = Object::cast_to<Node>(p_owner); - if (p_script->functions.has("_process")) + if (p_script->functions.has("_process")) { node->set_process(true); - if (p_script->functions.has("_physics_process")) + } + if (p_script->functions.has("_physics_process")) { node->set_physics_process(true); - if (p_script->functions.has("_input")) + } + if (p_script->functions.has("_input")) { node->set_process_input(true); - if (p_script->functions.has("_unhandled_input")) + } + if (p_script->functions.has("_unhandled_input")) { node->set_process_unhandled_input(true); - if (p_script->functions.has("_unhandled_key_input")) + } + if (p_script->functions.has("_unhandled_key_input")) { node->set_process_unhandled_key_input(true); + } } for (const Map<StringName, VisualScript::Variable>::Element *E = script->variables.front(); E; E = E->next()) { @@ -2188,7 +2116,6 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o } for (const Map<StringName, VisualScript::Function>::Element *E = script->functions.front(); E; E = E->next()) { - if (E->key() == script->get_default_func()) { continue; } @@ -2227,7 +2154,6 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o //first create the nodes for (const Map<int, VisualScript::Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) { - Ref<VisualScriptNode> node = F->get().node; VisualScriptNodeInstance *instance = node->instance(this); //create instance @@ -2237,18 +2163,17 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o instance->id = F->key(); instance->input_port_count = node->get_input_value_port_count(); - instance->input_ports = NULL; + instance->input_ports = nullptr; instance->output_port_count = node->get_output_value_port_count(); - instance->output_ports = NULL; + instance->output_ports = nullptr; instance->sequence_output_count = node->get_output_sequence_port_count(); instance->sequence_index = function.node_count++; - instance->sequence_outputs = NULL; + instance->sequence_outputs = nullptr; instance->pass_idx = -1; if (instance->input_port_count) { instance->input_ports = memnew_arr(int, instance->input_port_count); for (int i = 0; i < instance->input_port_count; i++) { - instance->input_ports[i] = -1; //if not assigned, will become default value } } @@ -2263,7 +2188,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o if (instance->sequence_output_count) { instance->sequence_outputs = memnew_arr(VisualScriptNodeInstance *, instance->sequence_output_count); for (int i = 0; i < instance->sequence_output_count; i++) { - instance->sequence_outputs[i] = NULL; //if it remains null, flow ends here + instance->sequence_outputs[i] = nullptr; //if it remains null, flow ends here } } @@ -2273,10 +2198,11 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o StringName var_name; - if (Object::cast_to<VisualScriptLocalVar>(*node)) + if (Object::cast_to<VisualScriptLocalVar>(*node)) { var_name = String(Object::cast_to<VisualScriptLocalVar>(*node)->get_var_name()).strip_edges(); - else + } else { var_name = String(Object::cast_to<VisualScriptLocalVarSet>(*node)->get_var_name()).strip_edges(); + } if (!local_var_indices.has(var_name)) { local_var_indices[var_name] = function.max_stack; @@ -2303,7 +2229,6 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o //second pass, do data connections for (const Set<VisualScript::DataConnection>::Element *F = E->get().data_connections.front(); F; F = F->next()) { - VisualScript::DataConnection dc = F->get(); ERR_CONTINUE(!instances.has(dc.from_node)); VisualScriptNodeInstance *from = instances[dc.from_node]; @@ -2313,7 +2238,6 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o ERR_CONTINUE(dc.to_port >= to->input_port_count); if (from->output_ports[dc.from_port] == -1) { - int stack_pos = function.max_stack++; from->output_ports[dc.from_port] = stack_pos; } @@ -2333,7 +2257,6 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o //third pass, do sequence connections for (const Set<VisualScript::SequenceConnection>::Element *F = E->get().sequence_connections.front(); F; F = F->next()) { - VisualScript::SequenceConnection sc = F->get(); ERR_CONTINUE(!instances.has(sc.from_node)); VisualScriptNodeInstance *from = instances[sc.from_node]; @@ -2349,7 +2272,6 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o // 2) connect unassigned output ports to trash for (const Map<int, VisualScript::Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) { - ERR_CONTINUE(!instances.has(F->key())); Ref<VisualScriptNode> node = F->get().node; @@ -2358,7 +2280,6 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o // connect to default values for (int i = 0; i < instance->input_port_count; i++) { if (instance->input_ports[i] == -1) { - //unassigned, connect to default val instance->input_ports[i] = default_values.size() | VisualScriptNodeInstance::INPUT_DEFAULT_VALUE_BIT; default_values.push_back(node->get_default_input_value(i)); @@ -2378,7 +2299,6 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o } ScriptLanguage *VisualScriptInstance::get_language() { - return VisualScriptLanguage::singleton; } @@ -2386,7 +2306,6 @@ VisualScriptInstance::VisualScriptInstance() { } VisualScriptInstance::~VisualScriptInstance() { - { MutexLock lock(VisualScriptLanguage::singleton->lock); @@ -2403,7 +2322,6 @@ VisualScriptInstance::~VisualScriptInstance() { ///////////////////// Variant VisualScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - ERR_FAIL_COND_V(function == StringName(), Variant()); #ifdef DEBUG_ENABLED @@ -2424,7 +2342,6 @@ Variant VisualScriptFunctionState::_signal_callback(const Variant **p_args, int } else if (p_argcount == 1) { //noooneee, reserved for me, me and only me. } else { - for (int i = 0; i < p_argcount - 1; i++) { args.push_back(*p_args[i]); } @@ -2451,7 +2368,6 @@ Variant VisualScriptFunctionState::_signal_callback(const Variant **p_args, int } void VisualScriptFunctionState::connect_to_signal(Object *p_obj, const String &p_signal, Array p_binds) { - Vector<Variant> binds; for (int i = 0; i < p_binds.size(); i++) { binds.push_back(p_binds[i]); @@ -2461,12 +2377,10 @@ void VisualScriptFunctionState::connect_to_signal(Object *p_obj, const String &p } bool VisualScriptFunctionState::is_valid() const { - return function != StringName(); } Variant VisualScriptFunctionState::resume(Array p_args) { - ERR_FAIL_COND_V(function == StringName(), Variant()); #ifdef DEBUG_ENABLED @@ -2488,7 +2402,6 @@ Variant VisualScriptFunctionState::resume(Array p_args) { } void VisualScriptFunctionState::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect_to_signal", "obj", "signals", "args"), &VisualScriptFunctionState::connect_to_signal); ClassDB::bind_method(D_METHOD("resume", "args"), &VisualScriptFunctionState::resume, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("is_valid"), &VisualScriptFunctionState::is_valid); @@ -2499,7 +2412,6 @@ VisualScriptFunctionState::VisualScriptFunctionState() { } VisualScriptFunctionState::~VisualScriptFunctionState() { - if (function != StringName()) { Variant *s = ((Variant *)stack.ptr()); for (int i = 0; i < variant_stack_size; i++) { @@ -2511,37 +2423,39 @@ VisualScriptFunctionState::~VisualScriptFunctionState() { /////////////////////////////////////////////// String VisualScriptLanguage::get_name() const { - return "VisualScript"; } /* LANGUAGE FUNCTIONS */ void VisualScriptLanguage::init() { } -String VisualScriptLanguage::get_type() const { +String VisualScriptLanguage::get_type() const { return "VisualScript"; } -String VisualScriptLanguage::get_extension() const { +String VisualScriptLanguage::get_extension() const { return "vs"; } -Error VisualScriptLanguage::execute_file(const String &p_path) { +Error VisualScriptLanguage::execute_file(const String &p_path) { return OK; } + void VisualScriptLanguage::finish() { } /* EDITOR FUNCTIONS */ void VisualScriptLanguage::get_reserved_words(List<String> *p_words) const { } + void VisualScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { } + void VisualScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { } -Ref<Script> VisualScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { +Ref<Script> VisualScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { Ref<VisualScript> script; script.instance(); script->set_instance_base_type(p_base_class_name); @@ -2549,7 +2463,6 @@ Ref<Script> VisualScriptLanguage::get_template(const String &p_class_name, const } bool VisualScriptLanguage::is_using_templates() { - return true; } @@ -2559,32 +2472,32 @@ void VisualScriptLanguage::make_template(const String &p_class_name, const Strin } bool VisualScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const { - return false; } -Script *VisualScriptLanguage::create_script() const { +Script *VisualScriptLanguage::create_script() const { return memnew(VisualScript); } -bool VisualScriptLanguage::has_named_classes() const { +bool VisualScriptLanguage::has_named_classes() const { return false; } -bool VisualScriptLanguage::supports_builtin_mode() const { +bool VisualScriptLanguage::supports_builtin_mode() const { return true; } -int VisualScriptLanguage::find_function(const String &p_function, const String &p_code) const { +int VisualScriptLanguage::find_function(const String &p_function, const String &p_code) const { return -1; } -String VisualScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const { +String VisualScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const { return String(); } void VisualScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_to_line) const { } + void VisualScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) { } @@ -2594,7 +2507,6 @@ bool VisualScriptLanguage::debug_break_parse(const String &p_file, int p_node, c //break because of parse error if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { - _debug_parse_err_node = p_node; _debug_parse_err_file = p_file; _debug_error = p_error; @@ -2606,9 +2518,7 @@ bool VisualScriptLanguage::debug_break_parse(const String &p_file, int p_node, c } bool VisualScriptLanguage::debug_break(const String &p_error, bool p_allow_continue) { - if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { - _debug_parse_err_node = -1; _debug_parse_err_file = ""; _debug_error = p_error; @@ -2620,21 +2530,21 @@ bool VisualScriptLanguage::debug_break(const String &p_error, bool p_allow_conti } String VisualScriptLanguage::debug_get_error() const { - return _debug_error; } int VisualScriptLanguage::debug_get_stack_level_count() const { - - if (_debug_parse_err_node >= 0) + if (_debug_parse_err_node >= 0) { return 1; + } return _debug_call_stack_pos; } -int VisualScriptLanguage::debug_get_stack_level_line(int p_level) const { - if (_debug_parse_err_node >= 0) +int VisualScriptLanguage::debug_get_stack_level_line(int p_level) const { + if (_debug_parse_err_node >= 0) { return _debug_parse_err_node; + } ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, -1); @@ -2642,28 +2552,31 @@ int VisualScriptLanguage::debug_get_stack_level_line(int p_level) const { return *(_call_stack[l].current_id); } -String VisualScriptLanguage::debug_get_stack_level_function(int p_level) const { - if (_debug_parse_err_node >= 0) +String VisualScriptLanguage::debug_get_stack_level_function(int p_level) const { + if (_debug_parse_err_node >= 0) { return ""; + } ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, ""); int l = _debug_call_stack_pos - p_level - 1; return *_call_stack[l].function; } -String VisualScriptLanguage::debug_get_stack_level_source(int p_level) const { - if (_debug_parse_err_node >= 0) +String VisualScriptLanguage::debug_get_stack_level_source(int p_level) const { + if (_debug_parse_err_node >= 0) { return _debug_parse_err_file; + } ERR_FAIL_INDEX_V(p_level, _debug_call_stack_pos, ""); int l = _debug_call_stack_pos - p_level - 1; return _call_stack[l].instance->get_script_ptr()->get_path(); } -void VisualScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { - if (_debug_parse_err_node >= 0) +void VisualScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { + if (_debug_parse_err_node >= 0) { return; + } ERR_FAIL_INDEX(p_level, _debug_call_stack_pos); @@ -2700,7 +2613,6 @@ void VisualScriptLanguage::debug_get_stack_level_locals(int p_level, List<String } for (int i = 0; i < node->output_port_count; i++) { - String name = node->get_base_node()->get_output_value_port_info(i).name; if (name == String()) { name = "out_" + itos(i); @@ -2735,17 +2647,19 @@ void VisualScriptLanguage::debug_get_stack_level_locals(int p_level, List<String } */ } -void VisualScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { - if (_debug_parse_err_node >= 0) +void VisualScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { + if (_debug_parse_err_node >= 0) { return; + } ERR_FAIL_INDEX(p_level, _debug_call_stack_pos); int l = _debug_call_stack_pos - p_level - 1; Ref<VisualScript> vs = _call_stack[l].instance->get_script(); - if (vs.is_null()) + if (vs.is_null()) { return; + } List<StringName> vars; vs->get_variable_list(&vars); @@ -2759,48 +2673,48 @@ void VisualScriptLanguage::debug_get_stack_level_members(int p_level, List<Strin } void VisualScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { - //no globals are really reachable in gdscript } -String VisualScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { +String VisualScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { return ""; } void VisualScriptLanguage::reload_all_scripts() { } + void VisualScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { } + /* LOADER FUNCTIONS */ void VisualScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("vs"); } + void VisualScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const { } + void VisualScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_constants) const { } void VisualScriptLanguage::profiling_start() { } + void VisualScriptLanguage::profiling_stop() { } int VisualScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) { - return 0; } int VisualScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) { - return 0; } -VisualScriptLanguage *VisualScriptLanguage::singleton = NULL; +VisualScriptLanguage *VisualScriptLanguage::singleton = nullptr; void VisualScriptLanguage::add_register_func(const String &p_name, VisualScriptNodeRegisterFunc p_func) { - ERR_FAIL_COND(register_funcs.has(p_name)); register_funcs[p_name] = p_func; } @@ -2811,21 +2725,18 @@ void VisualScriptLanguage::remove_register_func(const String &p_name) { } Ref<VisualScriptNode> VisualScriptLanguage::create_node_from_name(const String &p_name) { - ERR_FAIL_COND_V(!register_funcs.has(p_name), Ref<VisualScriptNode>()); return register_funcs[p_name](p_name); } void VisualScriptLanguage::get_registered_node_names(List<String> *r_names) { - for (Map<String, VisualScriptNodeRegisterFunc>::Element *E = register_funcs.front(); E; E = E->next()) { r_names->push_back(E->key()); } } VisualScriptLanguage::VisualScriptLanguage() { - notification = "_notification"; _step = "_step"; _subcall = "_subcall"; @@ -2844,14 +2755,13 @@ VisualScriptLanguage::VisualScriptLanguage() { } else { _debug_max_call_stack = 0; - _call_stack = NULL; + _call_stack = nullptr; } } VisualScriptLanguage::~VisualScriptLanguage() { - if (_call_stack) { memdelete_arr(_call_stack); } - singleton = NULL; + singleton = nullptr; } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 20273316b4..d54b1faf42 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -89,7 +89,6 @@ public: virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance) = 0; struct TypeGuess { - Variant::Type type; StringName gdclass; Ref<Script> script; @@ -166,16 +165,13 @@ public: }; class VisualScript : public Script { - GDCLASS(VisualScript, Script); RES_BASE_EXTENSION("vs"); public: struct SequenceConnection { - union { - struct { uint64_t from_node : 24; uint64_t from_output : 16; @@ -185,15 +181,12 @@ public: }; bool operator<(const SequenceConnection &p_connection) const { - return id < p_connection.id; } }; struct DataConnection { - union { - struct { uint64_t from_node : 24; uint64_t from_port : 8; @@ -204,7 +197,6 @@ public: }; bool operator<(const DataConnection &p_connection) const { - return id < p_connection.id; } }; @@ -272,6 +264,8 @@ protected: static void _bind_methods(); public: + bool inherits_script(const Ref<Script> &p_script) const; + // TODO: Remove it in future when breaking changes are acceptable StringName get_default_func() const; void add_function(const StringName &p_name); @@ -420,7 +414,7 @@ public: virtual bool set(const StringName &p_name, const Variant &p_value); virtual bool get(const StringName &p_name, Variant &r_ret) const; virtual void get_property_list(List<PropertyInfo> *p_properties) const; - virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const; + virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const; virtual void get_method_list(List<MethodInfo> *p_list) const; virtual bool has_method(const StringName &p_method) const; @@ -429,20 +423,20 @@ public: String to_string(bool *r_valid); bool set_variable(const StringName &p_variable, const Variant &p_value) { - Map<StringName, Variant>::Element *E = variables.find(p_variable); - if (!E) + if (!E) { return false; + } E->get() = p_value; return true; } bool get_variable(const StringName &p_variable, Variant *r_variable) const { - const Map<StringName, Variant>::Element *E = variables.find(p_variable); - if (!E) + if (!E) { return false; + } *r_variable = E->get(); return true; @@ -474,7 +468,6 @@ public: }; class VisualScriptFunctionState : public Reference { - GDCLASS(VisualScriptFunctionState, Reference); friend class VisualScriptInstance; @@ -505,11 +498,9 @@ public: typedef Ref<VisualScriptNode> (*VisualScriptNodeRegisterFunc)(const String &p_type); class VisualScriptLanguage : public ScriptLanguage { - Map<String, VisualScriptNodeRegisterFunc> register_funcs; struct CallLevel { - Variant *stack; Variant **work_mem; const StringName *function; @@ -538,12 +529,13 @@ public: bool debug_break_parse(const String &p_file, int p_node, const String &p_error); _FORCE_INLINE_ void enter_function(VisualScriptInstance *p_instance, const StringName *p_function, Variant *p_stack, Variant **p_work_mem, int *current_id) { - - if (Thread::get_main_id() != Thread::get_caller_id()) + if (Thread::get_main_id() != Thread::get_caller_id()) { return; //no support for other threads than main for now + } - if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) + if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) { EngineDebugger::get_script_debugger()->set_depth(EngineDebugger::get_script_debugger()->get_depth() + 1); + } if (_debug_call_stack_pos >= _debug_max_call_stack) { //stack overflow @@ -561,15 +553,15 @@ public: } _FORCE_INLINE_ void exit_function() { - - if (Thread::get_main_id() != Thread::get_caller_id()) + if (Thread::get_main_id() != Thread::get_caller_id()) { return; //no support for other threads than main for now + } - if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) + if (EngineDebugger::get_script_debugger()->get_lines_left() > 0 && EngineDebugger::get_script_debugger()->get_depth() >= 0) { EngineDebugger::get_script_debugger()->set_depth(EngineDebugger::get_script_debugger()->get_depth() - 1); + } if (_debug_call_stack_pos == 0) { - _debug_error = "Stack Underflow (Engine Bug)"; EngineDebugger::get_script_debugger()->debug(this); return; @@ -596,7 +588,7 @@ public: virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; virtual bool is_using_templates(); virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script); - virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL, List<ScriptLanguage::Warning> *r_warnings = NULL, Set<int> *r_safe_lines = NULL) const; + virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const; virtual Script *create_script() const; virtual bool has_named_classes() const; virtual bool supports_builtin_mode() const; @@ -643,7 +635,6 @@ public: //aid for registering template <class T> static Ref<VisualScriptNode> create_node_generic(const String &p_name) { - Ref<T> node; node.instance(); return node; diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 07f152efd4..a0dcd76d10 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -110,30 +110,26 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX }; VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::find_function(const String &p_string) { - for (int i = 0; i < FUNC_MAX; i++) { - if (p_string == func_name[i]) + if (p_string == func_name[i]) { return BuiltinFunc(i); + } } return FUNC_MAX; } String VisualScriptBuiltinFunc::get_func_name(BuiltinFunc p_func) { - ERR_FAIL_INDEX_V(p_func, FUNC_MAX, String()); return func_name[p_func]; } int VisualScriptBuiltinFunc::get_output_sequence_port_count() const { - return has_input_sequence_port() ? 1 : 0; } bool VisualScriptBuiltinFunc::has_input_sequence_port() const { - switch (func) { - case MATH_RANDOMIZE: case TEXT_PRINT: case TEXT_PRINTERR: @@ -145,9 +141,7 @@ bool VisualScriptBuiltinFunc::has_input_sequence_port() const { } int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { - switch (p_func) { - case MATH_RANDOMIZE: case MATH_RAND: case MATH_RANDF: @@ -228,11 +222,10 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { } int VisualScriptBuiltinFunc::get_input_value_port_count() const { - return get_func_argument_count(func); } -int VisualScriptBuiltinFunc::get_output_value_port_count() const { +int VisualScriptBuiltinFunc::get_output_value_port_count() const { switch (func) { case MATH_RANDOMIZE: case TEXT_PRINT: @@ -250,14 +243,11 @@ int VisualScriptBuiltinFunc::get_output_value_port_count() const { } String VisualScriptBuiltinFunc::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const { - switch (func) { - case MATH_SIN: case MATH_COS: case MATH_TAN: @@ -280,96 +270,106 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::FLOAT, "s"); } break; case MATH_ATAN2: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "y"); - else + } else { return PropertyInfo(Variant::FLOAT, "x"); + } } break; case MATH_FMOD: case MATH_FPOSMOD: case LOGIC_MAX: case LOGIC_MIN: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "a"); - else + } else { return PropertyInfo(Variant::FLOAT, "b"); + } } break; case MATH_POSMOD: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::INT, "a"); - else + } else { return PropertyInfo(Variant::INT, "b"); + } } break; case MATH_POW: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "base"); - else + } else { return PropertyInfo(Variant::FLOAT, "exp"); + } } break; case MATH_EASE: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "s"); - else + } else { return PropertyInfo(Variant::FLOAT, "curve"); + } } break; case MATH_STEP_DECIMALS: { return PropertyInfo(Variant::FLOAT, "step"); } break; case MATH_STEPIFY: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "s"); - else + } else { return PropertyInfo(Variant::FLOAT, "steps"); + } } break; case MATH_LERP: case MATH_LERP_ANGLE: case MATH_INVERSE_LERP: case MATH_SMOOTHSTEP: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "from"); - else if (p_idx == 1) + } else if (p_idx == 1) { return PropertyInfo(Variant::FLOAT, "to"); - else + } else { return PropertyInfo(Variant::FLOAT, "weight"); + } } break; case MATH_RANGE_LERP: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "value"); - else if (p_idx == 1) + } else if (p_idx == 1) { return PropertyInfo(Variant::FLOAT, "istart"); - else if (p_idx == 2) + } else if (p_idx == 2) { return PropertyInfo(Variant::FLOAT, "istop"); - else if (p_idx == 3) + } else if (p_idx == 3) { return PropertyInfo(Variant::FLOAT, "ostart"); - else + } else { return PropertyInfo(Variant::FLOAT, "ostop"); + } } break; case MATH_MOVE_TOWARD: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "from"); - else if (p_idx == 1) + } else if (p_idx == 1) { return PropertyInfo(Variant::FLOAT, "to"); - else + } else { return PropertyInfo(Variant::FLOAT, "delta"); + } } break; case MATH_DECTIME: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "value"); - else if (p_idx == 1) + } else if (p_idx == 1) { return PropertyInfo(Variant::FLOAT, "amount"); - else + } else { return PropertyInfo(Variant::FLOAT, "step"); + } } break; case MATH_RANDOMIZE: case MATH_RAND: case MATH_RANDF: { - } break; case MATH_RANDOM: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "from"); - else + } else { return PropertyInfo(Variant::FLOAT, "to"); + } } break; case MATH_SEED: case MATH_RANDSEED: { @@ -388,33 +388,37 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::FLOAT, "db"); } break; case MATH_POLAR2CARTESIAN: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "r"); - else + } else { return PropertyInfo(Variant::FLOAT, "th"); + } } break; case MATH_CARTESIAN2POLAR: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "x"); - else + } else { return PropertyInfo(Variant::FLOAT, "y"); + } } break; case MATH_WRAP: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::INT, "value"); - else if (p_idx == 1) + } else if (p_idx == 1) { return PropertyInfo(Variant::INT, "min"); - else + } else { return PropertyInfo(Variant::INT, "max"); + } } break; case MATH_WRAPF: case LOGIC_CLAMP: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "value"); - else if (p_idx == 1) + } else if (p_idx == 1) { return PropertyInfo(Variant::FLOAT, "min"); - else + } else { return PropertyInfo(Variant::FLOAT, "max"); + } } break; case LOGIC_NEAREST_PO2: { return PropertyInfo(Variant::INT, "value"); @@ -423,16 +427,18 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::OBJECT, "source"); } break; case FUNC_FUNCREF: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::OBJECT, "instance"); - else + } else { return PropertyInfo(Variant::STRING, "funcname"); + } } break; case TYPE_CONVERT: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::NIL, "what"); - else + } else { return PropertyInfo(Variant::STRING, "type"); + } } break; case TYPE_OF: { return PropertyInfo(Variant::NIL, "what"); @@ -453,29 +459,30 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::NIL, "value"); } break; case STR_TO_VAR: { - return PropertyInfo(Variant::STRING, "string"); } break; case VAR_TO_STR: case VAR_TO_BYTES: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::NIL, "var"); - else + } else { return PropertyInfo(Variant::BOOL, "full_objects"); + } } break; case BYTES_TO_VAR: { - - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytes"); - else + } else { return PropertyInfo(Variant::BOOL, "allow_objects"); + } } break; case COLORN: { - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::STRING, "name"); - else + } else { return PropertyInfo(Variant::FLOAT, "alpha"); + } } break; case FUNC_MAX: { } @@ -485,10 +492,8 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const } PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) const { - Variant::Type t = Variant::NIL; switch (func) { - case MATH_SIN: case MATH_COS: case MATH_TAN: @@ -506,10 +511,12 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons case MATH_CEIL: { t = Variant::FLOAT; } break; - case MATH_POSMOD: - case MATH_ROUND: { + case MATH_POSMOD: { t = Variant::INT; } break; + case MATH_ROUND: { + t = Variant::FLOAT; + } break; case MATH_ABS: { t = Variant::NIL; } break; @@ -543,10 +550,8 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons } break; case MATH_RANDOMIZE: { - } break; case MATH_RAND: { - t = Variant::INT; } break; case MATH_RANDF: @@ -554,14 +559,13 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons t = Variant::FLOAT; } break; case MATH_SEED: { - } break; case MATH_RANDSEED: { - - if (p_idx == 0) + if (p_idx == 0) { return PropertyInfo(Variant::INT, "rnd"); - else + } else { return PropertyInfo(Variant::INT, "seed"); + } } break; case MATH_DEG2RAD: case MATH_RAD2DEG: @@ -580,24 +584,20 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons case LOGIC_MAX: case LOGIC_MIN: case LOGIC_CLAMP: { - } break; case LOGIC_NEAREST_PO2: { t = Variant::NIL; } break; case OBJ_WEAKREF: { - t = Variant::OBJECT; } break; case FUNC_FUNCREF: { - t = Variant::OBJECT; } break; case TYPE_CONVERT: { - } break; case TEXT_ORD: case TYPE_OF: { @@ -605,41 +605,37 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons } break; case TYPE_EXISTS: { - t = Variant::BOOL; } break; case TEXT_CHAR: case TEXT_STR: { - t = Variant::STRING; } break; case TEXT_PRINT: { - } break; case TEXT_PRINTERR: { - } break; case TEXT_PRINTRAW: { - } break; case VAR_TO_STR: { t = Variant::STRING; } break; case STR_TO_VAR: { - } break; case VAR_TO_BYTES: { - if (p_idx == 0) + if (p_idx == 0) { t = Variant::PACKED_BYTE_ARRAY; - else + } else { t = Variant::BOOL; + } } break; case BYTES_TO_VAR: { - if (p_idx == 1) + if (p_idx == 1) { t = Variant::BOOL; + } } break; case COLORN: { t = Variant::COLOR; @@ -656,15 +652,14 @@ String VisualScriptBuiltinFunc::get_caption() const { return "BuiltinFunc"; } + */ String VisualScriptBuiltinFunc::get_caption() const { - return func_name[func]; } void VisualScriptBuiltinFunc::set_func(BuiltinFunc p_which) { - ERR_FAIL_INDEX(p_which, FUNC_MAX); func = p_which; _change_notify(); @@ -684,197 +679,159 @@ VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::get_func() { } void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str) { - switch (p_func) { case VisualScriptBuiltinFunc::MATH_SIN: { - VALIDATE_ARG_NUM(0); *r_return = Math::sin((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_COS: { - VALIDATE_ARG_NUM(0); *r_return = Math::cos((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_TAN: { - VALIDATE_ARG_NUM(0); *r_return = Math::tan((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_SINH: { - VALIDATE_ARG_NUM(0); *r_return = Math::sinh((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_COSH: { - VALIDATE_ARG_NUM(0); *r_return = Math::cosh((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_TANH: { - VALIDATE_ARG_NUM(0); *r_return = Math::tanh((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ASIN: { - VALIDATE_ARG_NUM(0); *r_return = Math::asin((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ACOS: { - VALIDATE_ARG_NUM(0); *r_return = Math::acos((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ATAN: { - VALIDATE_ARG_NUM(0); *r_return = Math::atan((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ATAN2: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::atan2((double)*p_inputs[0], (double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_SQRT: { - VALIDATE_ARG_NUM(0); *r_return = Math::sqrt((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_FMOD: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::fmod((double)*p_inputs[0], (double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_FPOSMOD: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::fposmod((double)*p_inputs[0], (double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_POSMOD: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::posmod((int)*p_inputs[0], (int)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_FLOOR: { - VALIDATE_ARG_NUM(0); *r_return = Math::floor((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_CEIL: { - VALIDATE_ARG_NUM(0); *r_return = Math::ceil((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ROUND: { - VALIDATE_ARG_NUM(0); *r_return = Math::round((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ABS: { - if (p_inputs[0]->get_type() == Variant::INT) { - int64_t i = *p_inputs[0]; *r_return = ABS(i); } else if (p_inputs[0]->get_type() == Variant::FLOAT) { - real_t r = *p_inputs[0]; *r_return = Math::abs(r); } else { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::FLOAT; } } break; case VisualScriptBuiltinFunc::MATH_SIGN: { - if (p_inputs[0]->get_type() == Variant::INT) { - int64_t i = *p_inputs[0]; *r_return = i < 0 ? -1 : (i > 0 ? +1 : 0); } else if (p_inputs[0]->get_type() == Variant::FLOAT) { - real_t r = *p_inputs[0]; *r_return = r < 0.0 ? -1.0 : (r > 0.0 ? +1.0 : 0.0); } else { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::FLOAT; } } break; case VisualScriptBuiltinFunc::MATH_POW: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::pow((double)*p_inputs[0], (double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_LOG: { - VALIDATE_ARG_NUM(0); *r_return = Math::log((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_EXP: { - VALIDATE_ARG_NUM(0); *r_return = Math::exp((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ISNAN: { - VALIDATE_ARG_NUM(0); *r_return = Math::is_nan((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_ISINF: { - VALIDATE_ARG_NUM(0); *r_return = Math::is_inf((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_EASE: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::ease((double)*p_inputs[0], (double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_STEP_DECIMALS: { - VALIDATE_ARG_NUM(0); *r_return = Math::step_decimals((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_STEPIFY: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::stepify((double)*p_inputs[0], (double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_LERP: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_LERP_ANGLE: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::lerp_angle((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_INVERSE_LERP: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_RANGE_LERP: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); @@ -889,14 +846,12 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_MOVE_TOWARD: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::MATH_DECTIME: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); @@ -913,20 +868,17 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in *r_return = Math::randf(); } break; case VisualScriptBuiltinFunc::MATH_RANDOM: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::random((double)*p_inputs[0], (double)*p_inputs[1]); } break; case VisualScriptBuiltinFunc::MATH_SEED: { - VALIDATE_ARG_NUM(0); uint64_t seed = *p_inputs[0]; Math::seed(seed); } break; case VisualScriptBuiltinFunc::MATH_RANDSEED: { - VALIDATE_ARG_NUM(0); uint64_t seed = *p_inputs[0]; int ret = Math::rand_from_seed(&seed); @@ -937,22 +889,18 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::MATH_DEG2RAD: { - VALIDATE_ARG_NUM(0); *r_return = Math::deg2rad((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_RAD2DEG: { - VALIDATE_ARG_NUM(0); *r_return = Math::rad2deg((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_LINEAR2DB: { - VALIDATE_ARG_NUM(0); *r_return = Math::linear2db((double)*p_inputs[0]); } break; case VisualScriptBuiltinFunc::MATH_DB2LINEAR: { - VALIDATE_ARG_NUM(0); *r_return = Math::db2linear((double)*p_inputs[0]); } break; @@ -983,9 +931,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in *r_return = Math::wrapf((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case VisualScriptBuiltinFunc::LOGIC_MAX: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; *r_return = MAX(a, b); @@ -1001,9 +947,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::LOGIC_MIN: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; *r_return = MIN(a, b); @@ -1018,9 +962,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } } break; case VisualScriptBuiltinFunc::LOGIC_CLAMP: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT && p_inputs[2]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; int64_t c = *p_inputs[2]; @@ -1038,15 +980,12 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } } break; case VisualScriptBuiltinFunc::LOGIC_NEAREST_PO2: { - VALIDATE_ARG_NUM(0); int64_t num = *p_inputs[0]; *r_return = next_power_of_2(num); } break; case VisualScriptBuiltinFunc::OBJ_WEAKREF: { - if (p_inputs[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -1055,10 +994,8 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } if (p_inputs[0]->is_ref()) { - REF r = *p_inputs[0]; if (!r.is_valid()) { - return; } @@ -1068,7 +1005,6 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } else { Object *obj = *p_inputs[0]; if (!obj) { - return; } Ref<WeakRef> wref = memnew(WeakRef); @@ -1078,9 +1014,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::FUNC_FUNCREF: { - if (p_inputs[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -1088,7 +1022,6 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in return; } if (p_inputs[1]->get_type() != Variant::STRING && p_inputs[1]->get_type() != Variant::NODE_PATH) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; r_error.expected = Variant::STRING; @@ -1105,11 +1038,9 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::TYPE_CONVERT: { - VALIDATE_ARG_NUM(1); int type = *p_inputs[1]; if (type < 0 || type >= Variant::VARIANT_MAX) { - r_error_str = RTR("Invalid type argument to convert(), use TYPE_* constants."); r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -1117,29 +1048,24 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in return; } else { - *r_return = Variant::construct(Variant::Type(type), p_inputs, 1, r_error); } } break; case VisualScriptBuiltinFunc::TYPE_OF: { - *r_return = p_inputs[0]->get_type(); } break; case VisualScriptBuiltinFunc::TYPE_EXISTS: { - *r_return = ClassDB::class_exists(*p_inputs[0]); } break; case VisualScriptBuiltinFunc::TEXT_CHAR: { - CharType result[2] = { *p_inputs[0], 0 }; *r_return = String(result); } break; case VisualScriptBuiltinFunc::TEXT_ORD: { - if (p_inputs[0]->get_type() != Variant::STRING) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -1163,39 +1089,33 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::TEXT_STR: { - String str = *p_inputs[0]; *r_return = str; } break; case VisualScriptBuiltinFunc::TEXT_PRINT: { - String str = *p_inputs[0]; print_line(str); } break; case VisualScriptBuiltinFunc::TEXT_PRINTERR: { - String str = *p_inputs[0]; print_error(str); } break; case VisualScriptBuiltinFunc::TEXT_PRINTRAW: { - String str = *p_inputs[0]; OS::get_singleton()->print("%s", str.utf8().get_data()); } break; case VisualScriptBuiltinFunc::VAR_TO_STR: { - String vars; VariantWriter::write_to_string(*p_inputs[0], vars); *r_return = vars; } break; case VisualScriptBuiltinFunc::STR_TO_VAR: { - if (p_inputs[0]->get_type() != Variant::STRING) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -1221,7 +1141,6 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::VAR_TO_BYTES: { - if (p_inputs[1]->get_type() != Variant::BOOL) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; @@ -1231,7 +1150,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in PackedByteArray barr; int len; bool full_objects = *p_inputs[1]; - Error err = encode_variant(*p_inputs[0], NULL, len, full_objects); + Error err = encode_variant(*p_inputs[0], nullptr, len, full_objects); if (err) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -1248,7 +1167,6 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in *r_return = barr; } break; case VisualScriptBuiltinFunc::BYTES_TO_VAR: { - if (p_inputs[0]->get_type() != Variant::PACKED_BYTE_ARRAY) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -1267,7 +1185,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in Variant ret; { const uint8_t *r = varr.ptr(); - Error err = decode_variant(ret, r, varr.size(), NULL, allow_objects); + Error err = decode_variant(ret, r, varr.size(), nullptr, allow_objects); if (err != OK) { r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format."); r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; @@ -1281,7 +1199,6 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::COLORN: { - VALIDATE_ARG_NUM(1); Color color = Color::named(*p_inputs[0]); @@ -1307,14 +1224,12 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - VisualScriptBuiltinFunc::exec_func(func, p_inputs, p_outputs[0], r_error, r_error_str); return 0; } }; VisualScriptNodeInstance *VisualScriptBuiltinFunc::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceBuiltinFunc *instance = memnew(VisualScriptNodeInstanceBuiltinFunc); instance->node = this; instance->instance = p_instance; @@ -1323,16 +1238,15 @@ VisualScriptNodeInstance *VisualScriptBuiltinFunc::instance(VisualScriptInstance } void VisualScriptBuiltinFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_func", "which"), &VisualScriptBuiltinFunc::set_func); ClassDB::bind_method(D_METHOD("get_func"), &VisualScriptBuiltinFunc::get_func); String cc; for (int i = 0; i < FUNC_MAX; i++) { - - if (i > 0) + if (i > 0) { cc += ","; + } cc += func_name[i]; } ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, cc), "set_func", "get_func"); @@ -1409,24 +1323,20 @@ void VisualScriptBuiltinFunc::_bind_methods() { } VisualScriptBuiltinFunc::VisualScriptBuiltinFunc(VisualScriptBuiltinFunc::BuiltinFunc func) { - this->func = func; } VisualScriptBuiltinFunc::VisualScriptBuiltinFunc() { - func = MATH_SIN; } template <VisualScriptBuiltinFunc::BuiltinFunc func> static Ref<VisualScriptNode> create_builtin_func_node(const String &p_name) { - Ref<VisualScriptBuiltinFunc> node = memnew(VisualScriptBuiltinFunc(func)); return node; } void register_visual_script_builtin_func_node() { - VisualScriptLanguage::singleton->add_register_func("functions/built_in/sin", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SIN>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/cos", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_COS>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/tan", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_TAN>); diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index d950f858d4..1b186353f1 100644 --- a/modules/visual_script/visual_script_builtin_funcs.h +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -34,7 +34,6 @@ #include "visual_script.h" class VisualScriptBuiltinFunc : public VisualScriptNode { - GDCLASS(VisualScriptBuiltinFunc, VisualScriptNode); public: diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index ca255ebf82..fea7d151df 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -30,15 +30,15 @@ #include "visual_script_editor.h" +#include "core/input/input.h" #include "core/object.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/script_language.h" #include "core/variant.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "visual_script_expression.h" #include "visual_script_flow_control.h" #include "visual_script_func_nodes.h" @@ -46,7 +46,6 @@ #ifdef TOOLS_ENABLED class VisualScriptEditorSignalEdit : public Object { - GDCLASS(VisualScriptEditorSignalEdit, Object); StringName sig; @@ -62,22 +61,21 @@ protected: } void _sig_changed() { - _change_notify(); emit_signal("changed"); } bool _set(const StringName &p_name, const Variant &p_value) { - - if (sig == StringName()) + if (sig == StringName()) { return false; + } if (p_name == "argument_count") { - int new_argc = p_value; int argc = script->custom_signal_get_argument_count(sig); - if (argc == new_argc) + if (argc == new_argc) { return true; + } undo_redo->create_action(TTR("Change Signal Arguments")); @@ -87,9 +85,7 @@ protected: undo_redo->add_undo_method(script.ptr(), "custom_signal_add_argument", sig, script->custom_signal_get_argument_name(sig, i), script->custom_signal_get_argument_type(sig, i), -1); } } else if (new_argc > argc) { - for (int i = argc; i < new_argc; i++) { - undo_redo->add_do_method(script.ptr(), "custom_signal_add_argument", sig, Variant::NIL, "arg" + itos(i + 1), -1); undo_redo->add_undo_method(script.ptr(), "custom_signal_remove_argument", sig, argc); } @@ -107,7 +103,6 @@ protected: ERR_FAIL_INDEX_V(idx, script->custom_signal_get_argument_count(sig), false); String what = String(p_name).get_slice("/", 2); if (what == "type") { - int old_type = script->custom_signal_get_argument_type(sig, idx); int new_type = p_value; undo_redo->create_action(TTR("Change Argument Type")); @@ -119,7 +114,6 @@ protected: } if (what == "name") { - String old_name = script->custom_signal_get_argument_name(sig, idx); String new_name = p_value; undo_redo->create_action(TTR("Change Argument name")); @@ -134,9 +128,9 @@ protected: } bool _get(const StringName &p_name, Variant &r_ret) const { - - if (sig == StringName()) + if (sig == StringName()) { return false; + } if (p_name == "argument_count") { r_ret = script->custom_signal_get_argument_count(sig); @@ -159,9 +153,9 @@ protected: return false; } void _get_property_list(List<PropertyInfo> *p_list) const { - - if (sig == StringName()) + if (sig == StringName()) { return; + } p_list->push_back(PropertyInfo(Variant::INT, "argument_count", PROPERTY_HINT_RANGE, "0,256")); String argt = "Variant"; @@ -177,16 +171,14 @@ protected: public: void edit(const StringName &p_sig) { - sig = p_sig; _change_notify(); } - VisualScriptEditorSignalEdit() { undo_redo = NULL; } + VisualScriptEditorSignalEdit() { undo_redo = nullptr; } }; class VisualScriptEditorVariableEdit : public Object { - GDCLASS(VisualScriptEditorVariableEdit, Object); StringName var; @@ -203,20 +195,18 @@ protected: } void _var_changed() { - _change_notify(); emit_signal("changed"); } void _var_value_changed() { - _change_notify("value"); //so the whole tree is not redrawn, makes editing smoother in general emit_signal("changed"); } bool _set(const StringName &p_name, const Variant &p_value) { - - if (var == StringName()) + if (var == StringName()) { return false; + } if (String(p_name) == "value") { undo_redo->create_action(TTR("Set Variable Default Value")); @@ -232,7 +222,6 @@ protected: Dictionary d = script->call("get_variable_info", var); if (String(p_name) == "type") { - Dictionary dc = d.duplicate(); dc["type"] = p_value; undo_redo->create_action(TTR("Set Variable Type")); @@ -245,7 +234,6 @@ protected: } if (String(p_name) == "hint") { - Dictionary dc = d.duplicate(); dc["hint"] = p_value; undo_redo->create_action(TTR("Set Variable Type")); @@ -258,7 +246,6 @@ protected: } if (String(p_name) == "hint_string") { - Dictionary dc = d.duplicate(); dc["hint_string"] = p_value; undo_redo->create_action(TTR("Set Variable Type")); @@ -280,9 +267,9 @@ protected: } bool _get(const StringName &p_name, Variant &r_ret) const { - - if (var == StringName()) + if (var == StringName()) { return false; + } if (String(p_name) == "value") { r_ret = script->get_variable_default_value(var); @@ -312,9 +299,9 @@ protected: return false; } void _get_property_list(List<PropertyInfo> *p_list) const { - - if (var == StringName()) + if (var == StringName()) { return; + } String argt = "Variant"; for (int i = 1; i < Variant::VARIANT_MAX; i++) { @@ -330,100 +317,233 @@ protected: public: void edit(const StringName &p_var) { - var = p_var; _change_notify(); } - VisualScriptEditorVariableEdit() { undo_redo = NULL; } + VisualScriptEditorVariableEdit() { undo_redo = nullptr; } }; static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) { Color color; - if (dark_theme) + if (dark_theme) { switch (p_type) { - case Variant::NIL: color = Color(0.41, 0.93, 0.74); break; - - case Variant::BOOL: color = Color(0.55, 0.65, 0.94); break; - case Variant::INT: color = Color(0.49, 0.78, 0.94); break; - case Variant::FLOAT: color = Color(0.38, 0.85, 0.96); break; - case Variant::STRING: color = Color(0.42, 0.65, 0.93); break; - - case Variant::VECTOR2: color = Color(0.74, 0.57, 0.95); break; - case Variant::RECT2: color = Color(0.95, 0.57, 0.65); break; - case Variant::VECTOR3: color = Color(0.84, 0.49, 0.93); break; - case Variant::TRANSFORM2D: color = Color(0.77, 0.93, 0.41); break; - case Variant::PLANE: color = Color(0.97, 0.44, 0.44); break; - case Variant::QUAT: color = Color(0.93, 0.41, 0.64); break; - case Variant::AABB: color = Color(0.93, 0.47, 0.57); break; - case Variant::BASIS: color = Color(0.89, 0.93, 0.41); break; - case Variant::TRANSFORM: color = Color(0.96, 0.66, 0.43); break; - - case Variant::COLOR: color = Color(0.62, 1.0, 0.44); break; - case Variant::NODE_PATH: color = Color(0.41, 0.58, 0.93); break; - case Variant::_RID: color = Color(0.41, 0.93, 0.6); break; - case Variant::OBJECT: color = Color(0.47, 0.95, 0.91); break; - case Variant::DICTIONARY: color = Color(0.47, 0.93, 0.69); break; - - case Variant::ARRAY: color = Color(0.88, 0.88, 0.88); break; - case Variant::PACKED_BYTE_ARRAY: color = Color(0.67, 0.96, 0.78); break; - case Variant::PACKED_INT32_ARRAY: color = Color(0.69, 0.86, 0.96); break; - case Variant::PACKED_FLOAT32_ARRAY: color = Color(0.59, 0.91, 0.97); break; - case Variant::PACKED_INT64_ARRAY: color = Color(0.69, 0.86, 0.96); break; - case Variant::PACKED_FLOAT64_ARRAY: color = Color(0.59, 0.91, 0.97); break; - case Variant::PACKED_STRING_ARRAY: color = Color(0.62, 0.77, 0.95); break; - case Variant::PACKED_VECTOR2_ARRAY: color = Color(0.82, 0.7, 0.96); break; - case Variant::PACKED_VECTOR3_ARRAY: color = Color(0.87, 0.61, 0.95); break; - case Variant::PACKED_COLOR_ARRAY: color = Color(0.91, 1.0, 0.59); break; + case Variant::NIL: + color = Color(0.41, 0.93, 0.74); + break; + + case Variant::BOOL: + color = Color(0.55, 0.65, 0.94); + break; + case Variant::INT: + color = Color(0.49, 0.78, 0.94); + break; + case Variant::FLOAT: + color = Color(0.38, 0.85, 0.96); + break; + case Variant::STRING: + color = Color(0.42, 0.65, 0.93); + break; + + case Variant::VECTOR2: + color = Color(0.74, 0.57, 0.95); + break; + case Variant::VECTOR2I: + color = Color(0.74, 0.57, 0.95); + break; + case Variant::RECT2: + color = Color(0.95, 0.57, 0.65); + break; + case Variant::RECT2I: + color = Color(0.95, 0.57, 0.65); + break; + case Variant::VECTOR3: + color = Color(0.84, 0.49, 0.93); + break; + case Variant::VECTOR3I: + color = Color(0.84, 0.49, 0.93); + break; + case Variant::TRANSFORM2D: + color = Color(0.77, 0.93, 0.41); + break; + case Variant::PLANE: + color = Color(0.97, 0.44, 0.44); + break; + case Variant::QUAT: + color = Color(0.93, 0.41, 0.64); + break; + case Variant::AABB: + color = Color(0.93, 0.47, 0.57); + break; + case Variant::BASIS: + color = Color(0.89, 0.93, 0.41); + break; + case Variant::TRANSFORM: + color = Color(0.96, 0.66, 0.43); + break; + + case Variant::COLOR: + color = Color(0.62, 1.0, 0.44); + break; + case Variant::NODE_PATH: + color = Color(0.41, 0.58, 0.93); + break; + case Variant::_RID: + color = Color(0.41, 0.93, 0.6); + break; + case Variant::OBJECT: + color = Color(0.47, 0.95, 0.91); + break; + case Variant::DICTIONARY: + color = Color(0.47, 0.93, 0.69); + break; + + case Variant::ARRAY: + color = Color(0.88, 0.88, 0.88); + break; + case Variant::PACKED_BYTE_ARRAY: + color = Color(0.67, 0.96, 0.78); + break; + case Variant::PACKED_INT32_ARRAY: + color = Color(0.69, 0.86, 0.96); + break; + case Variant::PACKED_FLOAT32_ARRAY: + color = Color(0.59, 0.91, 0.97); + break; + case Variant::PACKED_INT64_ARRAY: + color = Color(0.69, 0.86, 0.96); + break; + case Variant::PACKED_FLOAT64_ARRAY: + color = Color(0.59, 0.91, 0.97); + break; + case Variant::PACKED_STRING_ARRAY: + color = Color(0.62, 0.77, 0.95); + break; + case Variant::PACKED_VECTOR2_ARRAY: + color = Color(0.82, 0.7, 0.96); + break; + case Variant::PACKED_VECTOR3_ARRAY: + color = Color(0.87, 0.61, 0.95); + break; + case Variant::PACKED_COLOR_ARRAY: + color = Color(0.91, 1.0, 0.59); + break; default: color.set_hsv(p_type / float(Variant::VARIANT_MAX), 0.7, 0.7); } - else + } else { switch (p_type) { - case Variant::NIL: color = Color(0.15, 0.89, 0.63); break; - - case Variant::BOOL: color = Color(0.43, 0.56, 0.92); break; - case Variant::INT: color = Color(0.31, 0.7, 0.91); break; - case Variant::FLOAT: color = Color(0.15, 0.8, 0.94); break; - case Variant::STRING: color = Color(0.27, 0.56, 0.91); break; - - case Variant::VECTOR2: color = Color(0.68, 0.46, 0.93); break; - case Variant::RECT2: color = Color(0.93, 0.46, 0.56); break; - case Variant::VECTOR3: color = Color(0.86, 0.42, 0.93); break; - case Variant::TRANSFORM2D: color = Color(0.59, 0.81, 0.1); break; - case Variant::PLANE: color = Color(0.97, 0.44, 0.44); break; - case Variant::QUAT: color = Color(0.93, 0.41, 0.64); break; - case Variant::AABB: color = Color(0.93, 0.47, 0.57); break; - case Variant::BASIS: color = Color(0.7, 0.73, 0.1); break; - case Variant::TRANSFORM: color = Color(0.96, 0.56, 0.28); break; - - case Variant::COLOR: color = Color(0.24, 0.75, 0.0); break; - case Variant::NODE_PATH: color = Color(0.41, 0.58, 0.93); break; - case Variant::_RID: color = Color(0.17, 0.9, 0.45); break; - case Variant::OBJECT: color = Color(0.07, 0.84, 0.76); break; - case Variant::DICTIONARY: color = Color(0.34, 0.91, 0.62); break; - - case Variant::ARRAY: color = Color(0.45, 0.45, 0.45); break; - case Variant::PACKED_BYTE_ARRAY: color = Color(0.38, 0.92, 0.6); break; - case Variant::PACKED_INT32_ARRAY: color = Color(0.38, 0.73, 0.92); break; - case Variant::PACKED_FLOAT32_ARRAY: color = Color(0.25, 0.83, 0.95); break; - case Variant::PACKED_INT64_ARRAY: color = Color(0.38, 0.73, 0.92); break; - case Variant::PACKED_FLOAT64_ARRAY: color = Color(0.25, 0.83, 0.95); break; - case Variant::PACKED_STRING_ARRAY: color = Color(0.38, 0.62, 0.92); break; - case Variant::PACKED_VECTOR2_ARRAY: color = Color(0.62, 0.36, 0.92); break; - case Variant::PACKED_VECTOR3_ARRAY: color = Color(0.79, 0.35, 0.92); break; - case Variant::PACKED_COLOR_ARRAY: color = Color(0.57, 0.73, 0.0); break; + case Variant::NIL: + color = Color(0.15, 0.89, 0.63); + break; + + case Variant::BOOL: + color = Color(0.43, 0.56, 0.92); + break; + case Variant::INT: + color = Color(0.31, 0.7, 0.91); + break; + case Variant::FLOAT: + color = Color(0.15, 0.8, 0.94); + break; + case Variant::STRING: + color = Color(0.27, 0.56, 0.91); + break; + + case Variant::VECTOR2: + color = Color(0.68, 0.46, 0.93); + break; + case Variant::VECTOR2I: + color = Color(0.68, 0.46, 0.93); + break; + case Variant::RECT2: + color = Color(0.93, 0.46, 0.56); + break; + case Variant::RECT2I: + color = Color(0.93, 0.46, 0.56); + break; + case Variant::VECTOR3: + color = Color(0.86, 0.42, 0.93); + break; + case Variant::VECTOR3I: + color = Color(0.86, 0.42, 0.93); + break; + case Variant::TRANSFORM2D: + color = Color(0.59, 0.81, 0.1); + break; + case Variant::PLANE: + color = Color(0.97, 0.44, 0.44); + break; + case Variant::QUAT: + color = Color(0.93, 0.41, 0.64); + break; + case Variant::AABB: + color = Color(0.93, 0.47, 0.57); + break; + case Variant::BASIS: + color = Color(0.7, 0.73, 0.1); + break; + case Variant::TRANSFORM: + color = Color(0.96, 0.56, 0.28); + break; + + case Variant::COLOR: + color = Color(0.24, 0.75, 0.0); + break; + case Variant::NODE_PATH: + color = Color(0.41, 0.58, 0.93); + break; + case Variant::_RID: + color = Color(0.17, 0.9, 0.45); + break; + case Variant::OBJECT: + color = Color(0.07, 0.84, 0.76); + break; + case Variant::DICTIONARY: + color = Color(0.34, 0.91, 0.62); + break; + + case Variant::ARRAY: + color = Color(0.45, 0.45, 0.45); + break; + case Variant::PACKED_BYTE_ARRAY: + color = Color(0.38, 0.92, 0.6); + break; + case Variant::PACKED_INT32_ARRAY: + color = Color(0.38, 0.73, 0.92); + break; + case Variant::PACKED_FLOAT32_ARRAY: + color = Color(0.25, 0.83, 0.95); + break; + case Variant::PACKED_INT64_ARRAY: + color = Color(0.38, 0.73, 0.92); + break; + case Variant::PACKED_FLOAT64_ARRAY: + color = Color(0.25, 0.83, 0.95); + break; + case Variant::PACKED_STRING_ARRAY: + color = Color(0.38, 0.62, 0.92); + break; + case Variant::PACKED_VECTOR2_ARRAY: + color = Color(0.62, 0.36, 0.92); + break; + case Variant::PACKED_VECTOR3_ARRAY: + color = Color(0.79, 0.35, 0.92); + break; + case Variant::PACKED_COLOR_ARRAY: + color = Color(0.57, 0.73, 0.0); + break; default: color.set_hsv(p_type / float(Variant::VARIANT_MAX), 0.3, 0.3); } + } return color; } void VisualScriptEditor::_update_graph_connections() { - graph->clear_connections(); List<StringName> funcs; @@ -435,12 +555,10 @@ void VisualScriptEditor::_update_graph_connections() { } for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { - List<VisualScript::SequenceConnection> sequence_conns; script->get_sequence_connection_list(F->get(), &sequence_conns); for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { - graph->connect_node(itos(E->get().from_node), E->get().from_output, itos(E->get().to_node), 0); } @@ -448,7 +566,6 @@ void VisualScriptEditor::_update_graph_connections() { script->get_data_connection_list(F->get(), &data_conns); for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) { - VisualScript::DataConnection dc = E->get(); Ref<VisualScriptNode> from_node = script->get_node(F->get(), E->get().from_node); @@ -466,9 +583,9 @@ void VisualScriptEditor::_update_graph_connections() { } void VisualScriptEditor::_update_graph(int p_only_id) { - - if (updating_graph) + if (updating_graph) { return; + } updating_graph = true; @@ -476,13 +593,12 @@ void VisualScriptEditor::_update_graph(int p_only_id) { if (p_only_id >= 0) { if (graph->has_node(itos(p_only_id))) { Node *gid = graph->get_node(itos(p_only_id)); - if (gid) + if (gid) { memdelete(gid); + } } } else { - for (int i = 0; i < graph->get_child_count(); i++) { - if (Object::cast_to<GraphNode>(graph->get_child(i))) { memdelete(graph->get_child(i)); i--; @@ -504,36 +620,41 @@ void VisualScriptEditor::_update_graph(int p_only_id) { select_func_text->hide(); Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { - Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("bool", "EditorIcons"), - Control::get_icon("int", "EditorIcons"), - Control::get_icon("float", "EditorIcons"), - Control::get_icon("String", "EditorIcons"), - Control::get_icon("Vector2", "EditorIcons"), - Control::get_icon("Rect2", "EditorIcons"), - Control::get_icon("Vector3", "EditorIcons"), - Control::get_icon("Transform2D", "EditorIcons"), - Control::get_icon("Plane", "EditorIcons"), - Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("AABB", "EditorIcons"), - Control::get_icon("Basis", "EditorIcons"), - Control::get_icon("Transform", "EditorIcons"), - Control::get_icon("Color", "EditorIcons"), - Control::get_icon("NodePath", "EditorIcons"), - Control::get_icon("RID", "EditorIcons"), - Control::get_icon("MiniObject", "EditorIcons"), - Control::get_icon("Dictionary", "EditorIcons"), - Control::get_icon("Array", "EditorIcons"), - Control::get_icon("PackedByteArray", "EditorIcons"), - Control::get_icon("PackedInt32Array", "EditorIcons"), - Control::get_icon("PackedFloat32Array", "EditorIcons"), - Control::get_icon("PackedStringArray", "EditorIcons"), - Control::get_icon("PackedVector2Array", "EditorIcons"), - Control::get_icon("PackedVector3Array", "EditorIcons"), - Control::get_icon("PackedColorArray", "EditorIcons") + Control::get_theme_icon("Variant", "EditorIcons"), + Control::get_theme_icon("bool", "EditorIcons"), + Control::get_theme_icon("int", "EditorIcons"), + Control::get_theme_icon("float", "EditorIcons"), + Control::get_theme_icon("String", "EditorIcons"), + Control::get_theme_icon("Vector2", "EditorIcons"), + Control::get_theme_icon("Vector2i", "EditorIcons"), + Control::get_theme_icon("Rect2", "EditorIcons"), + Control::get_theme_icon("Rect2i", "EditorIcons"), + Control::get_theme_icon("Vector3", "EditorIcons"), + Control::get_theme_icon("Vector3i", "EditorIcons"), + Control::get_theme_icon("Transform2D", "EditorIcons"), + Control::get_theme_icon("Plane", "EditorIcons"), + Control::get_theme_icon("Quat", "EditorIcons"), + Control::get_theme_icon("AABB", "EditorIcons"), + Control::get_theme_icon("Basis", "EditorIcons"), + Control::get_theme_icon("Transform", "EditorIcons"), + Control::get_theme_icon("Color", "EditorIcons"), + Control::get_theme_icon("NodePath", "EditorIcons"), + Control::get_theme_icon("RID", "EditorIcons"), + Control::get_theme_icon("MiniObject", "EditorIcons"), + Control::get_theme_icon("Callable", "EditorIcons"), + Control::get_theme_icon("Signal", "EditorIcons"), + Control::get_theme_icon("Dictionary", "EditorIcons"), + Control::get_theme_icon("Array", "EditorIcons"), + Control::get_theme_icon("PackedByteArray", "EditorIcons"), + Control::get_theme_icon("PackedInt32Array", "EditorIcons"), + Control::get_theme_icon("PackedFloat32Array", "EditorIcons"), + Control::get_theme_icon("PackedStringArray", "EditorIcons"), + Control::get_theme_icon("PackedVector2Array", "EditorIcons"), + Control::get_theme_icon("PackedVector3Array", "EditorIcons"), + Control::get_theme_icon("PackedColorArray", "EditorIcons") }; - Ref<Texture2D> seq_port = Control::get_icon("VisualShaderPort", "EditorIcons"); + Ref<Texture2D> seq_port = Control::get_theme_icon("VisualShaderPort", "EditorIcons"); for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { // loop through all the functions @@ -542,9 +663,9 @@ void VisualScriptEditor::_update_graph(int p_only_id) { StringName editor_icons = "EditorIcons"; for (List<int>::Element *E = ids.front(); E; E = E->next()) { - - if (p_only_id >= 0 && p_only_id != E->get()) + if (p_only_id >= 0 && p_only_id != E->get()) { continue; + } Ref<VisualScriptNode> node = script->get_node(F->get(), E->get()); Vector2 pos = script->get_node_position(F->get(), E->get()); @@ -582,8 +703,9 @@ void VisualScriptEditor::_update_graph(int p_only_id) { btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port), varray(E->get()), CONNECT_DEFERRED); } if (nd_list->is_output_port_editable()) { - if (nd_list->is_input_port_editable()) + if (nd_list->is_input_port_editable()) { hbnc->add_spacer(); + } has_gnode_text = true; Button *btn = memnew(Button); btn->set_text(TTR("Add Output Port")); @@ -596,7 +718,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { LineEdit *line_edit = memnew(LineEdit); line_edit->set_text(node->get_text()); line_edit->set_expand_to_text_length(true); - line_edit->add_font_override("font", get_font("source", "EditorFonts")); + line_edit->add_theme_font_override("font", get_theme_font("source", "EditorFonts")); gnode->add_child(line_edit); line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E->get())); } else { @@ -619,8 +741,9 @@ void VisualScriptEditor::_update_graph(int p_only_id) { if (node_styles.has(node->get_category())) { Ref<StyleBoxFlat> sbf = node_styles[node->get_category()]; - if (gnode->is_comment()) + if (gnode->is_comment()) { sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox("comment", "GraphNode"); + } Color c = sbf->get_border_color(); Color ic = c; @@ -637,14 +760,14 @@ void VisualScriptEditor::_update_graph(int p_only_id) { mono_color.a = 0.85; c = mono_color; } - gnode->add_color_override("title_color", c); + gnode->add_theme_color_override("title_color", c); c.a = 0.7; - gnode->add_color_override("close_color", c); - gnode->add_color_override("resizer_color", ic); - gnode->add_style_override("frame", sbf); + gnode->add_theme_color_override("close_color", c); + gnode->add_theme_color_override("resizer_color", ic); + gnode->add_theme_style_override("frame", sbf); } - const Color mono_color = get_color("mono_color", "Editor"); + const Color mono_color = get_theme_color("mono_color", "Editor"); int slot_idx = 0; @@ -668,12 +791,10 @@ void VisualScriptEditor::_update_graph(int p_only_id) { int mixed_seq_ports = 0; if (!single_seq_output) { - if (node->has_mixed_input_and_sequence_ports()) { mixed_seq_ports = node->get_output_sequence_port_count(); } else { for (int i = 0; i < node->get_output_sequence_port_count(); i++) { - Label *text2 = memnew(Label); text2->set_text(node->get_output_sequence_port_text(i)); text2->set_align(Label::ALIGN_RIGHT); @@ -685,7 +806,6 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } for (int i = 0; i < MAX(node->get_output_value_port_count(), MAX(mixed_seq_ports, node->get_input_value_port_count())); i++) { - bool left_ok = false; Variant::Type left_type = Variant::NIL; String left_name; @@ -713,7 +833,6 @@ void VisualScriptEditor::_update_graph(int p_only_id) { vbc->add_child(hbc); vbc->add_child(hbc2); if (left_ok) { - Ref<Texture2D> t; if (left_type >= 0 && left_type < Variant::VARIANT_MAX) { t = type_icons[left_type]; @@ -750,7 +869,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } Button *rmbtn = memnew(Button); - rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); hbc->add_child(rmbtn); rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E->get(), i), CONNECT_DEFERRED); } else { @@ -758,7 +877,6 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } if (left_type != Variant::NIL && !script->is_input_value_port_connected(F->get(), E->get(), i)) { - PropertyInfo pi = node->get_input_value_port_info(i); Button *button = memnew(Button); Variant value = node->get_default_input_value(i); @@ -774,7 +892,6 @@ void VisualScriptEditor::_update_graph(int p_only_id) { button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); button->connect("draw", callable_mp(this, &VisualScriptEditor::_draw_color_over_button), varray(button, value)); } else if (left_type == Variant::OBJECT && Ref<Resource>(value).is_valid()) { - Ref<Resource> res = value; Array arr; arr.push_back(button->get_instance_id()); @@ -782,10 +899,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) { EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_button_resource_previewed", arr); } else if (pi.type == Variant::INT && pi.hint == PROPERTY_HINT_ENUM) { - button->set_text(pi.hint_string.get_slice(",", value)); } else { - button->set_text(value); } button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited), varray(button, E->get(), i)); @@ -801,7 +916,6 @@ void VisualScriptEditor::_update_graph(int p_only_id) { hbc2->add_spacer(); if (i < mixed_seq_ports) { - Label *text2 = memnew(Label); text2->set_text(node->get_output_sequence_port_text(i)); text2->set_align(Label::ALIGN_RIGHT); @@ -809,10 +923,9 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } if (right_ok) { - if (is_vslist) { Button *rmbtn = memnew(Button); - rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); hbc->add_child(rmbtn); rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E->get(), i), CONNECT_DEFERRED); @@ -856,7 +969,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->add_child(vbc); - bool dark_theme = get_constant("dark_theme", "Editor"); + bool dark_theme = get_theme_constant("dark_theme", "Editor"); if (i < mixed_seq_ports) { gnode->set_slot(slot_idx, left_ok, left_type, _color_from_type(left_type, dark_theme), true, TYPE_SEQUENCE, mono_color, Ref<Texture2D>(), seq_port); } else { @@ -880,12 +993,12 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } void VisualScriptEditor::_change_port_type(int p_select, int p_id, int p_port, bool is_input) { - StringName func = _get_function_of_node(p_id); Ref<VisualScriptLists> vsn = script->get_node(func, p_id); - if (!vsn.is_valid()) + if (!vsn.is_valid()) { return; + } undo_redo->create_action("Change Port Type"); if (is_input) { @@ -899,24 +1012,27 @@ void VisualScriptEditor::_change_port_type(int p_select, int p_id, int p_port, b } void VisualScriptEditor::_update_node_size(int p_id) { - Node *node = graph->get_node(itos(p_id)); - if (Object::cast_to<Control>(node)) + if (Object::cast_to<Control>(node)) { Object::cast_to<Control>(node)->set_size(Vector2(1, 1)); //shrink if text is smaller + } } + void VisualScriptEditor::_port_name_focus_out(const Node *p_name_box, int p_id, int p_port, bool is_input) { StringName func = _get_function_of_node(p_id); Ref<VisualScriptLists> vsn = script->get_node(func, p_id); - if (!vsn.is_valid()) + if (!vsn.is_valid()) { return; + } String text; - if (Object::cast_to<LineEdit>(p_name_box)) + if (Object::cast_to<LineEdit>(p_name_box)) { text = Object::cast_to<LineEdit>(p_name_box)->get_text(); - else + } else { return; + } undo_redo->create_action("Change Port Name"); if (is_input) { @@ -940,14 +1056,13 @@ void VisualScriptEditor::_update_members() { TreeItem *functions = members->create_item(root); functions->set_selectable(0, false); functions->set_text(0, TTR("Functions:")); - functions->add_button(0, Control::get_icon("Override", "EditorIcons"), 1, false, TTR("Override an existing built-in function.")); - functions->add_button(0, Control::get_icon("Add", "EditorIcons"), 0, false, TTR("Create a new function.")); - functions->set_custom_color(0, Control::get_color("mono_color", "Editor")); + functions->add_button(0, Control::get_theme_icon("Override", "EditorIcons"), 1, false, TTR("Override an existing built-in function.")); + functions->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), 0, false, TTR("Create a new function.")); + functions->set_custom_color(0, Control::get_theme_color("mono_color", "Editor")); List<StringName> func_names; script->get_function_list(&func_names); for (List<StringName>::Element *E = func_names.front(); E; E = E->next()) { - if (E->get() == default_func) { continue; } @@ -956,45 +1071,51 @@ void VisualScriptEditor::_update_members() { ti->set_text(0, E->get()); ti->set_selectable(0, true); ti->set_metadata(0, E->get()); - ti->add_button(0, Control::get_icon("Edit", "EditorIcons"), 0); - if (selected == E->get()) + ti->add_button(0, Control::get_theme_icon("Edit", "EditorIcons"), 0); + if (selected == E->get()) { ti->select(0); + } } TreeItem *variables = members->create_item(root); variables->set_selectable(0, false); variables->set_text(0, TTR("Variables:")); - variables->add_button(0, Control::get_icon("Add", "EditorIcons"), -1, false, TTR("Create a new variable.")); - variables->set_custom_color(0, Control::get_color("mono_color", "Editor")); + variables->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), -1, false, TTR("Create a new variable.")); + variables->set_custom_color(0, Control::get_theme_color("mono_color", "Editor")); Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { - Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("bool", "EditorIcons"), - Control::get_icon("int", "EditorIcons"), - Control::get_icon("float", "EditorIcons"), - Control::get_icon("String", "EditorIcons"), - Control::get_icon("Vector2", "EditorIcons"), - Control::get_icon("Rect2", "EditorIcons"), - Control::get_icon("Vector3", "EditorIcons"), - Control::get_icon("Transform2D", "EditorIcons"), - Control::get_icon("Plane", "EditorIcons"), - Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("AABB", "EditorIcons"), - Control::get_icon("Basis", "EditorIcons"), - Control::get_icon("Transform", "EditorIcons"), - Control::get_icon("Color", "EditorIcons"), - Control::get_icon("NodePath", "EditorIcons"), - Control::get_icon("RID", "EditorIcons"), - Control::get_icon("MiniObject", "EditorIcons"), - Control::get_icon("Dictionary", "EditorIcons"), - Control::get_icon("Array", "EditorIcons"), - Control::get_icon("PackedByteArray", "EditorIcons"), - Control::get_icon("PackedInt32Array", "EditorIcons"), - Control::get_icon("PackedFloat32Array", "EditorIcons"), - Control::get_icon("PackedStringArray", "EditorIcons"), - Control::get_icon("PackedVector2Array", "EditorIcons"), - Control::get_icon("PackedVector3Array", "EditorIcons"), - Control::get_icon("PackedColorArray", "EditorIcons") + Control::get_theme_icon("Variant", "EditorIcons"), + Control::get_theme_icon("bool", "EditorIcons"), + Control::get_theme_icon("int", "EditorIcons"), + Control::get_theme_icon("float", "EditorIcons"), + Control::get_theme_icon("String", "EditorIcons"), + Control::get_theme_icon("Vector2", "EditorIcons"), + Control::get_theme_icon("Vector2i", "EditorIcons"), + Control::get_theme_icon("Rect2", "EditorIcons"), + Control::get_theme_icon("Rect2i", "EditorIcons"), + Control::get_theme_icon("Vector3", "EditorIcons"), + Control::get_theme_icon("Vector3i", "EditorIcons"), + Control::get_theme_icon("Transform2D", "EditorIcons"), + Control::get_theme_icon("Plane", "EditorIcons"), + Control::get_theme_icon("Quat", "EditorIcons"), + Control::get_theme_icon("AABB", "EditorIcons"), + Control::get_theme_icon("Basis", "EditorIcons"), + Control::get_theme_icon("Transform", "EditorIcons"), + Control::get_theme_icon("Color", "EditorIcons"), + Control::get_theme_icon("NodePath", "EditorIcons"), + Control::get_theme_icon("RID", "EditorIcons"), + Control::get_theme_icon("MiniObject", "EditorIcons"), + Control::get_theme_icon("Callable", "EditorIcons"), + Control::get_theme_icon("Signal", "EditorIcons"), + Control::get_theme_icon("Dictionary", "EditorIcons"), + Control::get_theme_icon("Array", "EditorIcons"), + Control::get_theme_icon("PackedByteArray", "EditorIcons"), + Control::get_theme_icon("PackedInt32Array", "EditorIcons"), + Control::get_theme_icon("PackedFloat32Array", "EditorIcons"), + Control::get_theme_icon("PackedStringArray", "EditorIcons"), + Control::get_theme_icon("PackedVector2Array", "EditorIcons"), + Control::get_theme_icon("PackedVector3Array", "EditorIcons"), + Control::get_theme_icon("PackedColorArray", "EditorIcons") }; List<StringName> var_names; @@ -1010,15 +1131,16 @@ void VisualScriptEditor::_update_members() { ti->set_selectable(0, true); ti->set_editable(0, true); ti->set_metadata(0, E->get()); - if (selected == E->get()) + if (selected == E->get()) { ti->select(0); + } } TreeItem *_signals = members->create_item(root); _signals->set_selectable(0, false); _signals->set_text(0, TTR("Signals:")); - _signals->add_button(0, Control::get_icon("Add", "EditorIcons"), -1, false, TTR("Create a new signal.")); - _signals->set_custom_color(0, Control::get_color("mono_color", "Editor")); + _signals->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), -1, false, TTR("Create a new signal.")); + _signals->set_custom_color(0, Control::get_theme_color("mono_color", "Editor")); List<StringName> signal_names; script->get_custom_signal_list(&signal_names); @@ -1028,26 +1150,27 @@ void VisualScriptEditor::_update_members() { ti->set_selectable(0, true); ti->set_editable(0, true); ti->set_metadata(0, E->get()); - if (selected == E->get()) + if (selected == E->get()) { ti->select(0); + } } String base_type = script->get_instance_base_type(); String icon_type = base_type; - if (!Control::has_icon(base_type, "EditorIcons")) { + if (!Control::has_theme_icon(base_type, "EditorIcons")) { icon_type = "Object"; } base_type_select->set_text(base_type); - base_type_select->set_icon(Control::get_icon(icon_type, "EditorIcons")); + base_type_select->set_icon(Control::get_theme_icon(icon_type, "EditorIcons")); updating_members = false; } void VisualScriptEditor::_member_selected() { - - if (updating_members) + if (updating_members) { return; + } TreeItem *ti = members->get_selected(); ERR_FAIL_COND(!ti); @@ -1055,7 +1178,6 @@ void VisualScriptEditor::_member_selected() { selected = ti->get_metadata(0); if (ti->get_parent() == members->get_root()->get_children()) { - #ifdef OSX_ENABLED bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_META); #else @@ -1069,9 +1191,9 @@ void VisualScriptEditor::_member_selected() { } void VisualScriptEditor::_member_edited() { - - if (updating_members) + if (updating_members) { return; + } TreeItem *ti = members->get_edited(); ERR_FAIL_COND(!ti); @@ -1079,11 +1201,11 @@ void VisualScriptEditor::_member_edited() { String name = ti->get_metadata(0); String new_name = ti->get_text(0); - if (name == new_name) + if (name == new_name) { return; + } if (!new_name.is_valid_identifier()) { - EditorNode::get_singleton()->show_warning(TTR("Name is not a valid identifier:") + " " + new_name); updating_members = true; ti->set_text(0, name); @@ -1092,7 +1214,6 @@ void VisualScriptEditor::_member_edited() { } if (script->has_function(new_name) || script->has_variable(new_name) || script->has_custom_signal(new_name)) { - EditorNode::get_singleton()->show_warning(TTR("Name already in use by another func/var/signal:") + " " + new_name); updating_members = true; ti->set_text(0, name); @@ -1103,7 +1224,6 @@ void VisualScriptEditor::_member_edited() { TreeItem *root = members->get_root(); if (ti->get_parent() == root->get_children()) { - selected = new_name; int node_id = script->get_function_node_id(name); @@ -1127,8 +1247,9 @@ void VisualScriptEditor::_member_edited() { script->get_node_list(E->get(), &lst); for (List<int>::Element *F = lst.front(); F; F = F->next()) { Ref<VisualScriptFunctionCall> fncall = script->get_node(E->get(), F->get()); - if (!fncall.is_valid()) + if (!fncall.is_valid()) { continue; + } if (fncall->get_function() == name) { undo_redo->add_do_method(fncall.ptr(), "set_function", new_name); undo_redo->add_undo_method(fncall.ptr(), "set_function", name); @@ -1148,13 +1269,14 @@ void VisualScriptEditor::_member_edited() { } if (ti->get_parent() == root->get_children()->get_next()) { - selected = new_name; undo_redo->create_action(TTR("Rename Variable")); undo_redo->add_do_method(script.ptr(), "rename_variable", name, new_name); undo_redo->add_undo_method(script.ptr(), "rename_variable", new_name, name); undo_redo->add_do_method(this, "_update_members"); undo_redo->add_undo_method(this, "_update_members"); + undo_redo->add_do_method(this, "_update_graph"); + undo_redo->add_undo_method(this, "_update_graph"); undo_redo->add_do_method(this, "emit_signal", "edited_script_changed"); undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed"); undo_redo->commit_action(); @@ -1163,7 +1285,6 @@ void VisualScriptEditor::_member_edited() { } if (ti->get_parent() == root->get_children()->get_next()->get_next()) { - selected = new_name; undo_redo->create_action(TTR("Rename Signal")); undo_redo->add_do_method(script.ptr(), "rename_custom_signal", name, new_name); @@ -1200,8 +1321,9 @@ void VisualScriptEditor::_create_function() { for (int i = 0; i < func_input_vbox->get_child_count(); i++) { OptionButton *opbtn = Object::cast_to<OptionButton>(func_input_vbox->get_child(i)->get_child(3)); LineEdit *lne = Object::cast_to<LineEdit>(func_input_vbox->get_child(i)->get_child(1)); - if (!opbtn || !lne) + if (!opbtn || !lne) { continue; + } Variant::Type arg_type = Variant::Type(opbtn->get_selected()); String arg_name = lne->get_text(); func_node->add_argument(arg_type, arg_name); @@ -1246,13 +1368,14 @@ void VisualScriptEditor::_add_func_input() { OptionButton *type_box = memnew(OptionButton); type_box->set_custom_minimum_size(Size2(120 * EDSCALE, 0)); - for (int i = Variant::NIL; i < Variant::VARIANT_MAX; i++) + for (int i = Variant::NIL; i < Variant::VARIANT_MAX; i++) { type_box->add_item(Variant::get_type_name(Variant::Type(i))); + } type_box->select(1); hbox->add_child(type_box); Button *delete_button = memnew(Button); - delete_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + delete_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); delete_button->set_tooltip(vformat(TTR("Delete input port"))); hbox->add_child(delete_button); @@ -1262,7 +1385,7 @@ void VisualScriptEditor::_add_func_input() { } func_input_vbox->add_child(hbox); - hbox->set_meta("id", hbox->get_position_in_parent()); + hbox->set_meta("id", hbox->get_index()); delete_button->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_func_input), varray(hbox)); @@ -1279,13 +1402,13 @@ void VisualScriptEditor::_deselect_input_names() { int cn = func_input_vbox->get_child_count(); for (int i = 0; i < cn; i++) { LineEdit *lne = Object::cast_to<LineEdit>(func_input_vbox->get_child(i)->get_child(1)); - if (lne) + if (lne) { lne->deselect(); + } } } void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_button) { - TreeItem *ti = Object::cast_to<TreeItem>(p_item); TreeItem *root = members->get_root(); @@ -1300,7 +1423,6 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt return; } else if (p_button == 0) { - String name = _validate_name("new_function"); selected = name; Vector2 ofs = _get_available_pos(); @@ -1368,12 +1490,12 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt } void VisualScriptEditor::_add_input_port(int p_id) { - StringName func = _get_function_of_node(p_id); Ref<VisualScriptLists> vsn = script->get_node(func, p_id); - if (!vsn.is_valid()) + if (!vsn.is_valid()) { return; + } updating_graph = true; @@ -1390,12 +1512,12 @@ void VisualScriptEditor::_add_input_port(int p_id) { } void VisualScriptEditor::_add_output_port(int p_id) { - StringName func = _get_function_of_node(p_id); Ref<VisualScriptLists> vsn = script->get_node(func, p_id); - if (!vsn.is_valid()) + if (!vsn.is_valid()) { return; + } updating_graph = true; @@ -1412,12 +1534,12 @@ void VisualScriptEditor::_add_output_port(int p_id) { } void VisualScriptEditor::_remove_input_port(int p_id, int p_port) { - StringName func = _get_function_of_node(p_id); Ref<VisualScriptLists> vsn = script->get_node(func, p_id); - if (!vsn.is_valid()) + if (!vsn.is_valid()) { return; + } updating_graph = true; @@ -1426,14 +1548,16 @@ void VisualScriptEditor::_remove_input_port(int p_id, int p_port) { int conn_from = -1, conn_port = -1; script->get_input_value_port_connection_source(func, p_id, p_port, &conn_from, &conn_port); - if (conn_from != -1) + if (conn_from != -1) { undo_redo->add_do_method(script.ptr(), "data_disconnect", func, conn_from, conn_port, p_id, p_port); + } undo_redo->add_do_method(vsn.ptr(), "remove_input_data_port", p_port); undo_redo->add_do_method(this, "_update_graph", p_id); - if (conn_from != -1) + if (conn_from != -1) { undo_redo->add_undo_method(script.ptr(), "data_connect", func, conn_from, conn_port, p_id, p_port); + } undo_redo->add_undo_method(vsn.ptr(), "add_input_data_port", vsn->get_input_value_port_info(p_port).type, vsn->get_input_value_port_info(p_port).name, p_port); undo_redo->add_undo_method(this, "_update_graph", p_id); @@ -1444,12 +1568,12 @@ void VisualScriptEditor::_remove_input_port(int p_id, int p_port) { } void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { - StringName func = _get_function_of_node(p_id); Ref<VisualScriptLists> vsn = script->get_node(func, p_id); - if (!vsn.is_valid()) + if (!vsn.is_valid()) { return; + } updating_graph = true; @@ -1462,8 +1586,9 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { for (const List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { if (E->get().from_node == p_id && E->get().from_port == p_port) { // push into the connections map - if (!conn_map.has(E->get().to_node)) + if (!conn_map.has(E->get().to_node)) { conn_map.set(E->get().to_node, Set<int>()); + } conn_map[E->get().to_node].insert(E->get().to_port); } } @@ -1488,12 +1613,12 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) { } void VisualScriptEditor::_expression_text_changed(const String &p_text, int p_id) { - StringName func = _get_function_of_node(p_id); Ref<VisualScriptExpression> vse = script->get_node(func, p_id); - if (!vse.is_valid()) + if (!vse.is_valid()) { return; + } updating_graph = true; @@ -1505,15 +1630,17 @@ void VisualScriptEditor::_expression_text_changed(const String &p_text, int p_id undo_redo->commit_action(); Node *node = graph->get_node(itos(p_id)); - if (Object::cast_to<Control>(node)) + if (Object::cast_to<Control>(node)) { Object::cast_to<Control>(node)->set_size(Vector2(1, 1)); //shrink if text is smaller + } updating_graph = false; } Vector2 VisualScriptEditor::_get_available_pos(bool centered, Vector2 ofs) const { - if (centered) + if (centered) { ofs = graph->get_scroll_ofs() + graph->get_size() * 0.5; + } if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -1539,8 +1666,9 @@ Vector2 VisualScriptEditor::_get_available_pos(bool centered, Vector2 ofs) const } } } - if (exists) + if (exists) { continue; + } break; } @@ -1548,12 +1676,10 @@ Vector2 VisualScriptEditor::_get_available_pos(bool centered, Vector2 ofs) const } String VisualScriptEditor::_validate_name(const String &p_name) const { - String valid = p_name; int counter = 1; while (true) { - bool exists = script->has_function(valid) || script->has_variable(valid) || script->has_custom_signal(valid); if (exists) { @@ -1569,7 +1695,6 @@ String VisualScriptEditor::_validate_name(const String &p_name) const { } void VisualScriptEditor::_on_nodes_delete() { - // delete all the selected nodes List<int> to_erase; @@ -1583,13 +1708,13 @@ void VisualScriptEditor::_on_nodes_delete() { } } - if (to_erase.empty()) + if (to_erase.empty()) { return; + } undo_redo->create_action(TTR("Remove VisualScript Nodes")); for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { - int cr_node = F->get(); StringName func = _get_function_of_node(cr_node); @@ -1601,7 +1726,6 @@ void VisualScriptEditor::_on_nodes_delete() { script->get_sequence_connection_list(func, &sequence_conns); for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { - if (E->get().from_node == cr_node || E->get().to_node == cr_node) { undo_redo->add_undo_method(script.ptr(), "sequence_connect", func, E->get().from_node, E->get().from_output, E->get().to_node); } @@ -1611,7 +1735,6 @@ void VisualScriptEditor::_on_nodes_delete() { script->get_data_connection_list(func, &data_conns); for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) { - if (E->get().from_node == F->get() || E->get().to_node == F->get()) { undo_redo->add_undo_method(script.ptr(), "data_connect", func, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } @@ -1624,7 +1747,6 @@ void VisualScriptEditor::_on_nodes_delete() { } void VisualScriptEditor::_on_nodes_duplicate() { - Set<int> to_duplicate; List<StringName> funcs; @@ -1639,8 +1761,9 @@ void VisualScriptEditor::_on_nodes_duplicate() { } } - if (to_duplicate.empty()) + if (to_duplicate.empty()) { return; + } undo_redo->create_action(TTR("Duplicate VisualScript Nodes")); int idc = script->get_available_id() + 1; @@ -1649,7 +1772,6 @@ void VisualScriptEditor::_on_nodes_duplicate() { HashMap<int, int> remap; for (Set<int>::Element *F = to_duplicate.front(); F; F = F->next()) { - // duplicate from the specific function but place it into the default func as it would lack the connections StringName func = _get_function_of_node(F->get()); Ref<VisualScriptNode> node = script->get_node(func, F->get()); @@ -1701,10 +1823,11 @@ void VisualScriptEditor::_on_nodes_duplicate() { } void VisualScriptEditor::_generic_search(String p_base_type, Vector2 pos, bool node_centered) { - if (node_centered) + if (node_centered) { port_action_pos = graph->get_size() / 2.0f; - else + } else { port_action_pos = graph->get_viewport()->get_mouse_position() - graph->get_global_position(); + } new_connect_node_select->select_from_visual_script(p_base_type, false, false); // neither connecting nor reset text @@ -1713,8 +1836,9 @@ void VisualScriptEditor::_generic_search(String p_base_type, Vector2 pos, bool n pos.x = pos.x > bounds.x ? bounds.x : pos.x; pos.y = pos.y > bounds.y ? bounds.y : pos.y; - if (pos != Vector2()) + if (pos != Vector2()) { new_connect_node_select->set_position(pos); + } } void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) { @@ -1738,7 +1862,6 @@ void VisualScriptEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { } void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { - Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (members->has_focus()) { @@ -1768,21 +1891,19 @@ void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> btn = p_event; if (btn.is_valid() && btn->is_doubleclick()) { TreeItem *ti = members->get_selected(); - if (ti && ti->get_parent() == members->get_root()->get_children()) // to check if it's a function + if (ti && ti->get_parent() == members->get_root()->get_children()) { // to check if it's a function _center_on_node(ti->get_metadata(0), script->get_function_node_id(ti->get_metadata(0))); + } } } void VisualScriptEditor::_rename_function(const String &name, const String &new_name) { - if (!new_name.is_valid_identifier()) { - EditorNode::get_singleton()->show_warning(TTR("Name is not a valid identifier:") + " " + new_name); return; } if (script->has_function(new_name) || script->has_variable(new_name) || script->has_custom_signal(new_name)) { - EditorNode::get_singleton()->show_warning(TTR("Name already in use by another func/var/signal:") + " " + new_name); return; } @@ -1808,8 +1929,9 @@ void VisualScriptEditor::_rename_function(const String &name, const String &new_ script->get_node_list(E->get(), &lst); for (List<int>::Element *F = lst.front(); F; F = F->next()) { Ref<VisualScriptFunctionCall> fncall = script->get_node(E->get(), F->get()); - if (!fncall.is_valid()) + if (!fncall.is_valid()) { continue; + } if (fncall->get_function() == name) { undo_redo->add_do_method(fncall.ptr(), "set_function", new_name); undo_redo->add_undo_method(fncall.ptr(), "set_function", name); @@ -1827,9 +1949,9 @@ void VisualScriptEditor::_rename_function(const String &name, const String &new_ } void VisualScriptEditor::_fn_name_box_input(const Ref<InputEvent> &p_event) { - - if (!function_name_edit->is_visible()) + if (!function_name_edit->is_visible()) { return; + } Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ENTER) { @@ -1840,31 +1962,28 @@ void VisualScriptEditor::_fn_name_box_input(const Ref<InputEvent> &p_event) { } Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { - if (p_from == members) { - TreeItem *it = members->get_item_at_position(p_point); - if (!it) + if (!it) { return Variant(); + } String type = it->get_metadata(0); - if (type == String()) + if (type == String()) { return Variant(); + } Dictionary dd; TreeItem *root = members->get_root(); if (it->get_parent() == root->get_children()) { - dd["type"] = "visual_script_function_drag"; dd["function"] = type; } else if (it->get_parent() == root->get_children()->get_next()) { - dd["type"] = "visual_script_variable_drag"; dd["variable"] = type; } else if (it->get_parent() == root->get_children()->get_next()->get_next()) { - dd["type"] = "visual_script_signal_drag"; dd["signal"] = type; @@ -1881,9 +2000,7 @@ Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f } bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { - if (p_from == graph) { - Dictionary d = p_data; if (d.has("type") && (String(d["type"]) == "visual_script_node_drag" || @@ -1894,9 +2011,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & String(d["type"]) == "resource" || String(d["type"]) == "files" || String(d["type"]) == "nodes")) { - if (String(d["type"]) == "obj_property") { - #ifdef OSX_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Getter. Hold Shift to drop a generic signature."), find_keycode_name(KEY_META))); #else @@ -1905,7 +2020,6 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & } if (String(d["type"]) == "nodes") { - #ifdef OSX_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a simple reference to the node."), find_keycode_name(KEY_META))); #else @@ -1914,7 +2028,6 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & } if (String(d["type"]) == "visual_script_variable_drag") { - #ifdef OSX_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Variable Setter."), find_keycode_name(KEY_META))); #else @@ -1930,26 +2043,27 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & } static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const Ref<Script> &script) { - - if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene) - return NULL; + if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene) { + return nullptr; + } Ref<Script> scr = p_current_node->get_script(); - if (scr.is_valid() && scr == script) + if (scr.is_valid() && scr == script) { return p_current_node; + } for (int i = 0; i < p_current_node->get_child_count(); i++) { Node *n = _find_script_node(p_edited_scene, p_current_node->get_child(i), script); - if (n) + if (n) { return n; + } } - return NULL; + return nullptr; } void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { - if (p_from != graph) { return; } @@ -1984,7 +2098,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "visual_script_variable_drag") { - #ifdef OSX_ENABLED bool use_set = Input::get_singleton()->is_key_pressed(KEY_META); #else @@ -2005,7 +2118,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da vnodes->set_variable(d["variable"]); vnode = vnodes; } else { - Ref<VisualScriptVariableGet> vnodeg; vnodeg.instance(); vnodeg->set_variable(d["variable"]); @@ -2029,7 +2141,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "visual_script_function_drag") { - Vector2 ofs = graph->get_scroll_ofs() + p_point; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -2062,7 +2173,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "visual_script_signal_drag") { - Vector2 ofs = graph->get_scroll_ofs() + p_point; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -2092,7 +2202,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "resource") { - Vector2 ofs = graph->get_scroll_ofs() + p_point; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -2122,7 +2231,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "files") { - Vector2 ofs = graph->get_scroll_ofs() + p_point; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -2140,10 +2248,10 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da undo_redo->create_action(TTR("Add Preload Node")); for (int i = 0; i < files.size(); i++) { - Ref<Resource> res = ResourceLoader::load(files[i]); - if (!res.is_valid()) + if (!res.is_valid()) { continue; + } Ref<VisualScriptPreload> prnode; prnode.instance(); @@ -2162,7 +2270,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } for (List<int>::Element *E = new_ids.front(); E; E = E->next()) { - Node *node = graph->get_node(itos(E->get())); if (node) { graph->set_selected(node); @@ -2172,7 +2279,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "nodes") { - Node *sn = _find_script_node(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root(), script); if (!sn) { @@ -2204,7 +2310,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } for (int i = 0; i < nodes.size(); i++) { - NodePath np = nodes[i]; Node *node = get_node(np); if (!node) { @@ -2242,7 +2347,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "obj_property") { - Node *sn = _find_script_node(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root(), script); if (!sn && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { @@ -2252,8 +2356,9 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da Object *obj = d["object"]; - if (!obj) + if (!obj) { return; + } Node *node = Object::cast_to<Node>(obj); Vector2 ofs = graph->get_scroll_ofs() + p_point; @@ -2271,18 +2376,17 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da #endif if (!node || Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { - - if (use_get) + if (use_get) { undo_redo->create_action(TTR("Add Getter Property")); - else + } else { undo_redo->create_action(TTR("Add Setter Property")); + } int base_id = script->get_available_id(); Ref<VisualScriptNode> vnode; if (!use_get) { - Ref<VisualScriptPropertySet> pset; pset.instance(); pset->set_call_mode(VisualScriptPropertySet::CALL_MODE_INSTANCE); @@ -2293,7 +2397,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da }*/ vnode = pset; } else { - Ref<VisualScriptPropertyGet> pget; pget.instance(); pget->set_call_mode(VisualScriptPropertyGet::CALL_MODE_INSTANCE); @@ -2315,18 +2418,17 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da undo_redo->commit_action(); } else { - - if (use_get) + if (use_get) { undo_redo->create_action(TTR("Add Getter Property")); - else + } else { undo_redo->create_action(TTR("Add Setter Property")); + } int base_id = script->get_available_id(); Ref<VisualScriptNode> vnode; if (!use_get) { - Ref<VisualScriptPropertySet> pset; pset.instance(); if (sn == node) { @@ -2338,7 +2440,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da vnode = pset; } else { - Ref<VisualScriptPropertyGet> pget; pget.instance(); if (sn == node) { @@ -2364,33 +2465,33 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } void VisualScriptEditor::_selected_method(const String &p_method, const String &p_type, const bool p_connecting) { - Ref<VisualScriptFunctionCall> vsfc = script->get_node(default_func, selecting_method_id); - if (!vsfc.is_valid()) + if (!vsfc.is_valid()) { return; + } vsfc->set_function(p_method); } void VisualScriptEditor::_draw_color_over_button(Object *obj, Color p_color) { - Button *button = Object::cast_to<Button>(obj); - if (!button) + if (!button) { return; + } - Ref<StyleBox> normal = get_stylebox("normal", "Button"); + Ref<StyleBox> normal = get_theme_stylebox("normal", "Button"); button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) { - Array ud = p_ud; ERR_FAIL_COND(ud.size() != 2); ObjectID id = ud[0]; Object *obj = ObjectDB::get_instance(id); - if (!obj) + if (!obj) { return; + } Button *b = Object::cast_to<Button>(obj); ERR_FAIL_COND(!b); @@ -2398,7 +2499,6 @@ void VisualScriptEditor::_button_resource_previewed(const String &p_path, const if (p_preview.is_null()) { b->set_text(ud[1]); } else { - b->set_icon(p_preview); } } @@ -2413,7 +2513,6 @@ RES VisualScriptEditor::get_edited_resource() const { } void VisualScriptEditor::set_edited_resource(const RES &p_res) { - script = p_res; signal_editor->script = script; signal_editor->undo_redo = undo_redo; @@ -2435,7 +2534,6 @@ void VisualScriptEditor::set_edited_resource(const RES &p_res) { } Vector<String> VisualScriptEditor::get_functions() { - return Vector<String>(); } @@ -2443,7 +2541,6 @@ void VisualScriptEditor::reload_text() { } String VisualScriptEditor::get_name() { - String name; if (script->get_path().find("local://") == -1 && script->get_path().find("::") == -1) { @@ -2451,26 +2548,24 @@ String VisualScriptEditor::get_name() { if (is_unsaved()) { name += "(*)"; } - } else if (script->get_name() != "") + } else if (script->get_name() != "") { name = script->get_name(); - else + } else { name = script->get_class() + "(" + itos(script->get_instance_id()) + ")"; + } return name; } -Ref<Texture2D> VisualScriptEditor::get_icon() { - - return Control::get_icon("VisualScript", "EditorIcons"); +Ref<Texture2D> VisualScriptEditor::get_theme_icon() { + return Control::get_theme_icon("VisualScript", "EditorIcons"); } bool VisualScriptEditor::is_unsaved() { - return script->is_edited() || script->are_subnodes_edited(); } Variant VisualScriptEditor::get_edit_state() { - Dictionary d; d["function"] = default_func; d["scroll"] = graph->get_scroll_ofs(); @@ -2481,7 +2576,6 @@ Variant VisualScriptEditor::get_edit_state() { } void VisualScriptEditor::set_edit_state(const Variant &p_state) { - Dictionary d = p_state; if (d.has("function")) { selected = default_func; @@ -2505,15 +2599,15 @@ void VisualScriptEditor::set_edit_state(const Variant &p_state) { } void VisualScriptEditor::_center_on_node(const StringName &p_func, int p_id) { - Node *n = graph->get_node(itos(p_id)); GraphNode *gn = Object::cast_to<GraphNode>(n); // clear selection for (int i = 0; i < graph->get_child_count(); i++) { GraphNode *gnd = Object::cast_to<GraphNode>(graph->get_child(i)); - if (gnd) + if (gnd) { gnd->set_selected(false); + } } if (gn) { @@ -2526,18 +2620,16 @@ void VisualScriptEditor::_center_on_node(const StringName &p_func, int p_id) { } void VisualScriptEditor::goto_line(int p_line, bool p_with_error) { - p_line += 1; //add one because script lines begin from 0. - if (p_with_error) + if (p_with_error) { error_line = p_line; + } List<StringName> functions; script->get_function_list(&functions); for (List<StringName>::Element *E = functions.front(); E; E = E->next()) { - if (script->has_node(E->get(), p_line)) { - _update_graph(); _update_members(); @@ -2568,7 +2660,6 @@ void VisualScriptEditor::convert_indent_to_tabs() { } void VisualScriptEditor::ensure_focus() { - graph->grab_focus(); } @@ -2580,15 +2671,12 @@ void VisualScriptEditor::reload(bool p_soft) { } void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) { - List<StringName> functions; script->get_function_list(&functions); for (List<StringName>::Element *E = functions.front(); E; E = E->next()) { - List<int> nodes; script->get_node_list(E->get(), &nodes); for (List<int>::Element *F = nodes.front(); F; F = F->next()) { - Ref<VisualScriptNode> vsn = script->get_node(E->get(), F->get()); if (vsn->is_breakpoint()) { p_breakpoints->push_back(F->get() - 1); //subtract 1 because breakpoints in text start from zero @@ -2598,7 +2686,6 @@ void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) { } void VisualScriptEditor::add_callback(const String &p_function, PackedStringArray p_args) { - if (script->has_function(p_function)) { _update_members(); _update_graph(); @@ -2609,7 +2696,6 @@ void VisualScriptEditor::add_callback(const String &p_function, PackedStringArra Ref<VisualScriptFunction> func; func.instance(); for (int i = 0; i < p_args.size(); i++) { - String name = p_args[i]; Variant::Type type = Variant::NIL; @@ -2617,7 +2703,6 @@ void VisualScriptEditor::add_callback(const String &p_function, PackedStringArra String tt = name.get_slice(":", 1); name = name.get_slice(":", 0); for (int j = 0; j < Variant::VARIANT_MAX; j++) { - String tname = Variant::get_type_name(Variant::Type(j)); if (tname == tt) { type = Variant::Type(j); @@ -2644,7 +2729,6 @@ bool VisualScriptEditor::show_members_overview() { } void VisualScriptEditor::update_settings() { - _update_graph(); } @@ -2659,12 +2743,10 @@ void VisualScriptEditor::set_tooltip_request_func(String p_method, Object *p_obj } Control *VisualScriptEditor::get_edit_menu() { - return edit_menu; } void VisualScriptEditor::_change_base_type() { - select_base_type->popup_create(true, true); } @@ -2678,7 +2760,6 @@ void VisualScriptEditor::clear_edit_menu() { } void VisualScriptEditor::_change_base_type_callback() { - String bt = select_base_type->get_selected_type(); ERR_FAIL_COND(bt == String()); @@ -2691,16 +2772,15 @@ void VisualScriptEditor::_change_base_type_callback() { } void VisualScriptEditor::_node_selected(Node *p_node) { - Ref<VisualScriptNode> vnode = p_node->get_meta("__vnode"); - if (vnode.is_null()) + if (vnode.is_null()) { return; + } EditorNode::get_singleton()->push_item(vnode.ptr()); //edit node in inspector } static bool _get_out_slot(const Ref<VisualScriptNode> &p_node, int p_slot, int &r_real_slot, bool &r_sequence) { - if (p_slot < p_node->get_output_sequence_port_count()) { r_sequence = true; r_real_slot = p_slot; @@ -2715,7 +2795,6 @@ static bool _get_out_slot(const Ref<VisualScriptNode> &p_node, int p_slot, int & } static bool _get_in_slot(const Ref<VisualScriptNode> &p_node, int p_slot, int &r_real_slot, bool &r_sequence) { - if (p_slot == 0 && p_node->has_input_sequence_port()) { r_sequence = true; r_real_slot = 0; @@ -2729,30 +2808,28 @@ static bool _get_in_slot(const Ref<VisualScriptNode> &p_node, int p_slot, int &r } void VisualScriptEditor::_begin_node_move() { - undo_redo->create_action(TTR("Move Node(s)")); } void VisualScriptEditor::_end_node_move() { - undo_redo->commit_action(); } void VisualScriptEditor::_move_node(const StringName &p_func, int p_id, const Vector2 &p_to) { - - if (!script->has_function(p_func)) + if (!script->has_function(p_func)) { return; + } Node *node = graph->get_node(itos(p_id)); - if (Object::cast_to<GraphNode>(node)) + if (Object::cast_to<GraphNode>(node)) { Object::cast_to<GraphNode>(node)->set_offset(p_to); + } script->set_node_position(p_func, p_id, p_to / EDSCALE); } StringName VisualScriptEditor::_get_function_of_node(int p_id) const { - List<StringName> funcs; script->get_function_list(&funcs); for (List<StringName>::Element *E = funcs.front(); E; E = E->next()) { @@ -2765,7 +2842,6 @@ StringName VisualScriptEditor::_get_function_of_node(int p_id) const { } void VisualScriptEditor::_node_moved(Vector2 p_from, Vector2 p_to, int p_id) { - StringName func = _get_function_of_node(p_id); undo_redo->add_do_method(this, "_move_node", func, p_id, p_to); @@ -2773,7 +2849,6 @@ void VisualScriptEditor::_node_moved(Vector2 p_from, Vector2 p_to, int p_id) { } void VisualScriptEditor::_remove_node(int p_id) { - undo_redo->create_action(TTR("Remove VisualScript Node")); StringName func = _get_function_of_node(p_id); @@ -2785,7 +2860,6 @@ void VisualScriptEditor::_remove_node(int p_id) { script->get_sequence_connection_list(func, &sequence_conns); for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) { - if (E->get().from_node == p_id || E->get().to_node == p_id) { undo_redo->add_undo_method(script.ptr(), "sequence_connect", func, E->get().from_node, E->get().from_output, E->get().to_node); } @@ -2795,7 +2869,6 @@ void VisualScriptEditor::_remove_node(int p_id) { script->get_data_connection_list(func, &data_conns); for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) { - if (E->get().from_node == p_id || E->get().to_node == p_id) { undo_redo->add_undo_method(script.ptr(), "data_connect", func, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } @@ -2808,7 +2881,6 @@ void VisualScriptEditor::_remove_node(int p_id) { } void VisualScriptEditor::_node_ports_changed(const String &p_func, int p_id) { - _update_graph(p_id); } @@ -2820,15 +2892,15 @@ bool VisualScriptEditor::node_has_sequence_connections(const StringName &p_func, int from = E->get().from_node; int to = E->get().to_node; - if (to == p_id || from == p_id) + if (to == p_id || from == p_id) { return true; + } } return false; } void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot) { - StringName from_func = _get_function_of_node(p_from.to_int()); Ref<VisualScriptNode> from_node = script->get_node(from_func, p_from.to_int()); @@ -2837,8 +2909,9 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, bool from_seq; int from_port; - if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) + if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) { return; //can't connect this, it's invalid + } StringName to_func = _get_function_of_node(p_to.to_int()); @@ -2848,8 +2921,9 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, bool to_seq; int to_port; - if (!_get_in_slot(to_node, p_to_slot, to_port, to_seq)) + if (!_get_in_slot(to_node, p_to_slot, to_port, to_seq)) { return; //can't connect this, it's invalid + } ERR_FAIL_COND(from_seq != to_seq); @@ -2950,19 +3024,21 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, Vector2 constructor_pos; if ((to_node_pos.x - from_node_pos.x) < 0) { // to is behind from node - if (to_node_pos.x > (from_node_pos.x - to_node_size.x - 240)) + if (to_node_pos.x > (from_node_pos.x - to_node_size.x - 240)) { new_to_node_pos.x = from_node_pos.x - to_node_size.x - 240; // approx size of constructor node + padding - else + } else { new_to_node_pos.x = to_node_pos.x; + } new_to_node_pos.y = to_node_pos.y; constructor_pos.x = from_node_pos.x - 210; constructor_pos.y = to_node_pos.y; } else { // to is ahead of from node - if (to_node_pos.x < (from_node_size.x + from_node_pos.x + 240)) + if (to_node_pos.x < (from_node_size.x + from_node_pos.x + 240)) { new_to_node_pos.x = from_node_size.x + from_node_pos.x + 240; // approx size of constructor node + padding - else + } else { new_to_node_pos.x = to_node_pos.x; + } new_to_node_pos.y = to_node_pos.y; constructor_pos.x = from_node_size.x + from_node_pos.x + 10; constructor_pos.y = to_node_pos.y; @@ -3026,7 +3102,6 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, } void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot) { - StringName func = _get_function_of_node(p_from.to_int()); ERR_FAIL_COND(func != _get_function_of_node(p_to.to_int())); @@ -3036,8 +3111,9 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl bool from_seq; int from_port; - if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) + if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) { return; //can't connect this, it's invalid + } Ref<VisualScriptNode> to_node = script->get_node(func, p_to.to_int()); ERR_FAIL_COND(!to_node.is_valid()); @@ -3045,8 +3121,9 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl bool to_seq; int to_port; - if (!_get_in_slot(to_node, p_to_slot, to_port, to_seq)) + if (!_get_in_slot(to_node, p_to_slot, to_port, to_seq)) { return; //can't connect this, it's invalid + } ERR_FAIL_COND(from_seq != to_seq); @@ -3056,7 +3133,6 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl undo_redo->add_do_method(script.ptr(), "sequence_disconnect", func, p_from.to_int(), from_port, p_to.to_int()); undo_redo->add_undo_method(script.ptr(), "sequence_connect", func, p_from.to_int(), from_port, p_to.to_int()); } else { - can_swap = true; data_disconnect_node = p_to.to_int(); data_disconnect_port = to_port; @@ -3076,7 +3152,6 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl } void VisualScriptEditor::_move_nodes_with_rescan(const StringName &p_func_from, const StringName &p_func_to, int p_id) { - Set<int> nodes_to_move; HashMap<int, Map<int, int>> seqconns_to_move; // from => List(outp, to) HashMap<int, Map<int, Pair<int, int>>> dataconns_to_move; // to => List(inp_p => from, outp) @@ -3093,8 +3168,9 @@ void VisualScriptEditor::_move_nodes_with_rescan(const StringName &p_func_from, int from = E->get().from_node; int to = E->get().to_node; int out_p = E->get().from_output; - if (!seqcons.has(from)) + if (!seqcons.has(from)) { seqcons.set(from, Map<int, int>()); + } seqcons[from].insert(out_p, to); sequence_connections.insert(to); sequence_connections.insert(from); @@ -3117,12 +3193,14 @@ void VisualScriptEditor::_move_nodes_with_rescan(const StringName &p_func_from, } continue; } - if (!seen.has(conn)) + if (!seen.has(conn)) { seen.set(conn, Set<int>()); + } seen[conn].insert(E->key()); stack.push_back(conn); - if (!seqconns_to_move.has(conn)) + if (!seqconns_to_move.has(conn)) { seqconns_to_move.set(conn, Map<int, int>()); + } seqconns_to_move[conn].insert(E->key(), E->get()); conn = E->get(); nodes_to_move.insert(conn); @@ -3147,8 +3225,9 @@ void VisualScriptEditor::_move_nodes_with_rescan(const StringName &p_func_from, int out_p = E->get().from_port; int in_p = E->get().to_port; - if (!connections.has(to)) + if (!connections.has(to)) { connections.set(to, Map<int, Pair<int, int>>()); + } connections[to].insert(in_p, Pair<int, int>(from, out_p)); } @@ -3185,12 +3264,14 @@ void VisualScriptEditor::_move_nodes_with_rescan(const StringName &p_func_from, } } - if (!seen.has(id)) + if (!seen.has(id)) { seen.set(id, Set<int>()); + } seen[id].insert(E->key()); stack.push_back(id); - if (!dataconns_to_move.has(id)) + if (!dataconns_to_move.has(id)) { dataconns_to_move.set(id, Map<int, Pair<int, int>>()); + } dataconns_to_move[id].insert(E->key(), Pair<int, int>(E->get().first, E->get().second)); id = E->get().first; nodes_to_be_added.insert(id); @@ -3286,22 +3367,22 @@ void VisualScriptEditor::_move_nodes_with_rescan(const StringName &p_func_from, } void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_pos) { - Node *node = graph->get_node(p_from); GraphNode *gn = Object::cast_to<GraphNode>(node); - if (!gn) + if (!gn) { return; + } StringName func = _get_function_of_node(p_from.to_int()); Ref<VisualScriptNode> vsn = script->get_node(func, p_from.to_int()); - if (!vsn.is_valid()) + if (!vsn.is_valid()) { return; + } port_action_pos = p_release_pos; if (p_from_slot < vsn->get_output_sequence_port_count()) { - port_action_node = p_from.to_int(); port_action_output = p_from_slot; _port_action_menu(CREATE_ACTION, func); @@ -3313,12 +3394,12 @@ void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_fro } VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes) { - VisualScriptNode::TypeGuess tg; tg.type = Variant::NIL; - if (visited_nodes.has(p_port_action_node)) + if (visited_nodes.has(p_port_action_node)) { return tg; //no loop + } visited_nodes.insert(p_port_action_node); @@ -3327,7 +3408,6 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac Ref<VisualScriptNode> node = script->get_node(func, p_port_action_node); if (!node.is_valid()) { - return tg; } @@ -3344,16 +3424,13 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac int from_port; if (script->get_input_value_port_connection_source(func, p_port_action_node, i, &from_node, &from_port)) { - g = _guess_output_type(from_node, from_port, visited_nodes); } else { Variant defval = node->get_default_input_value(i); if (defval.get_type() == Variant::OBJECT) { - Object *obj = defval; if (obj) { - g.type = Variant::OBJECT; g.gdclass = obj->get_class(); g.script = obj->get_script(); @@ -3369,7 +3446,6 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac } void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) { - Vector2 ofs = graph->get_scroll_ofs() + port_action_pos; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -3380,7 +3456,6 @@ void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) Set<int> vn; switch (p_option) { - case CREATE_CALL_SET_GET: { Ref<VisualScriptFunctionCall> n; n.instance(); @@ -3444,10 +3519,9 @@ void VisualScriptEditor::_port_action_menu(int p_option, const StringName &func) } void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode, int new_id) { - undo_redo->create_action(TTR("Connect Node Data")); VisualScriptReturn *vnode_return = Object::cast_to<VisualScriptReturn>(vnode.ptr()); - if (vnode_return != NULL && vnode_old->get_output_value_port_count() > 0) { + if (vnode_return != nullptr && vnode_old->get_output_value_port_count() > 0) { vnode_return->set_enable_return_value(true); } if (vnode_old->get_output_value_port_count() <= 0) { @@ -3470,7 +3544,6 @@ void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<Visua } void VisualScriptEditor::_selected_connect_node(const String &p_text, const String &p_category, const bool p_connecting) { - Vector2 ofs = graph->get_scroll_ofs() + port_action_pos; if (graph->is_using_snap()) { int snap = graph->get_snap(); @@ -3492,8 +3565,9 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri if (p_category == "visualscript") { Ref<VisualScriptNode> vnode_new = VisualScriptLanguage::singleton->create_node_from_name(p_text); Ref<VisualScriptNode> vnode_old; - if (port_node_exists) + if (port_node_exists) { vnode_old = script->get_node(func, port_action_node); + } int new_id = script->get_available_id(); if (Object::cast_to<VisualScriptOperator>(vnode_new.ptr()) && vnode_old.is_valid()) { @@ -3532,18 +3606,15 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri Ref<VisualScriptPropertySet> script_prop_set; if (p_category == String("method")) { - Ref<VisualScriptFunctionCall> n; n.instance(); vnode = n; } else if (p_category == String("set")) { - Ref<VisualScriptPropertySet> n; n.instance(); vnode = n; script_prop_set = n; } else if (p_category == String("get")) { - Ref<VisualScriptPropertyGet> n; n.instance(); n->set_property(p_text); @@ -3552,33 +3623,27 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri if (p_category == String("action")) { if (p_text == "VisualScriptCondition") { - Ref<VisualScriptCondition> n; n.instance(); vnode = n; } if (p_text == "VisualScriptSwitch") { - Ref<VisualScriptSwitch> n; n.instance(); vnode = n; } else if (p_text == "VisualScriptSequence") { - Ref<VisualScriptSequence> n; n.instance(); vnode = n; } else if (p_text == "VisualScriptIterator") { - Ref<VisualScriptIterator> n; n.instance(); vnode = n; } else if (p_text == "VisualScriptWhile") { - Ref<VisualScriptWhile> n; n.instance(); vnode = n; } else if (p_text == "VisualScriptReturn") { - Ref<VisualScriptReturn> n; n.instance(); vnode = n; @@ -3593,15 +3658,15 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri undo_redo->add_undo_method(this, "_update_graph", new_id); undo_redo->commit_action(); - if (script_prop_set.is_valid()) + if (script_prop_set.is_valid()) { script_prop_set->set_property(p_text); + } port_action_new_node = new_id; Ref<VisualScriptNode> vsn = script->get_node(func, port_action_new_node); if (Object::cast_to<VisualScriptFunctionCall>(vsn.ptr())) { - Ref<VisualScriptFunctionCall> vsfc = vsn; vsfc->set_function(p_text); @@ -3706,18 +3771,18 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri } } _update_graph(port_action_new_node); - if (port_node_exists) + if (port_node_exists) { _update_graph_connections(); + } } void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id) { - VisualScriptOperator *vnode_operator = Object::cast_to<VisualScriptOperator>(vnode_new.ptr()); - if (vnode_operator != NULL && !vnode_operator->has_input_sequence_port()) { + if (vnode_operator != nullptr && !vnode_operator->has_input_sequence_port()) { return; } VisualScriptConstructor *vnode_constructor = Object::cast_to<VisualScriptConstructor>(vnode_new.ptr()); - if (vnode_constructor != NULL) { + if (vnode_constructor != nullptr) { return; } if (vnode_old->get_output_sequence_port_count() <= 0) { @@ -3759,7 +3824,6 @@ void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<Visual } void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, const String &p_category, const bool p_connecting) { - String name = p_text; if (script->has_function(name)) { EditorNode::get_singleton()->show_warning(vformat(TTR("Script already has function '%s'"), name)); @@ -3822,10 +3886,10 @@ void VisualScriptEditor::_cancel_connect_node() { } int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const Vector2 &p_point, const StringName &p_func) { - StringName func = default_func; - if (p_func != StringName()) + if (p_func != StringName()) { func = p_func; + } Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(p_text); int new_id = script->get_available_id(); @@ -3839,10 +3903,10 @@ int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const V } void VisualScriptEditor::_default_value_changed() { - Ref<VisualScriptNode> vsn = script->get_node(_get_function_of_node(editing_id), editing_id); - if (vsn.is_null()) + if (vsn.is_null()) { return; + } undo_redo->create_action(TTR("Change Input Value")); undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, default_value_edit->get_variant()); @@ -3854,15 +3918,14 @@ void VisualScriptEditor::_default_value_changed() { } void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_input_port) { - Ref<VisualScriptNode> vsn = script->get_node(_get_function_of_node(p_id), p_id); - if (vsn.is_null()) + if (vsn.is_null()) { return; + } PropertyInfo pinfo = vsn->get_input_value_port_info(p_input_port); Variant existing = vsn->get_default_input_value(p_input_port); if (pinfo.type != Variant::NIL && existing.get_type() != pinfo.type) { - Callable::CallError ce; const Variant *existingp = &existing; existing = Variant::construct(pinfo.type, &existingp, 1, ce, false); @@ -3872,7 +3935,6 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i default_value_edit->set_size(Size2(1, 1)); if (pinfo.type == Variant::NODE_PATH) { - Node *edited_scene = get_tree()->get_edited_scene_root(); if (edited_scene) { // Fixing an old crash bug ( Visual Script Crashes on editing NodePath with an empty scene open) Node *script_node = _find_script_node(edited_scene, edited_scene, script); @@ -3889,11 +3951,12 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i } } - if (default_value_edit->edit(NULL, pinfo.name, pinfo.type, existing, pinfo.hint, pinfo.hint_string)) { - if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT) + if (default_value_edit->edit(nullptr, pinfo.name, pinfo.type, existing, pinfo.hint, pinfo.hint_string)) { + if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT) { default_value_edit->popup_centered_ratio(); - else + } else { default_value_edit->popup(); + } } editing_id = p_id; @@ -3901,23 +3964,22 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i } void VisualScriptEditor::_show_hint(const String &p_hint) { - hint_text->set_text(p_hint); hint_text->show(); hint_text_timer->start(); } void VisualScriptEditor::_hide_timer() { - hint_text->hide(); } void VisualScriptEditor::_notification(int p_what) { - switch (p_what) { case NOTIFICATION_READY: { variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_members)); + variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph), varray(-1), CONNECT_DEFERRED); signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_members)); + signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph), varray(-1), CONNECT_DEFERRED); [[fallthrough]]; } case NOTIFICATION_THEME_CHANGED: { @@ -3925,9 +3987,9 @@ void VisualScriptEditor::_notification(int p_what) { return; } - edit_variable_edit->add_style_override("bg", get_stylebox("bg", "Tree")); - edit_signal_edit->add_style_override("bg", get_stylebox("bg", "Tree")); - func_input_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + edit_variable_edit->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); + edit_signal_edit->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); + func_input_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme(); @@ -3974,9 +4036,9 @@ void VisualScriptEditor::_notification(int p_what) { } void VisualScriptEditor::_graph_ofs_changed(const Vector2 &p_ofs) { - - if (updating_graph || !script.is_valid()) + if (updating_graph || !script.is_valid()) { return; + } updating_graph = true; @@ -3989,20 +4051,22 @@ void VisualScriptEditor::_graph_ofs_changed(const Vector2 &p_ofs) { } void VisualScriptEditor::_comment_node_resized(const Vector2 &p_new_size, int p_node) { - - if (updating_graph) + if (updating_graph) { return; + } StringName func = _get_function_of_node(p_node); Ref<VisualScriptComment> vsc = script->get_node(func, p_node); - if (vsc.is_null()) + if (vsc.is_null()) { return; + } Node *node = graph->get_node(itos(p_node)); GraphNode *gn = Object::cast_to<GraphNode>(node); - if (!gn) + if (!gn) { return; + } updating_graph = true; @@ -4020,13 +4084,11 @@ void VisualScriptEditor::_comment_node_resized(const Vector2 &p_new_size, int p_ } void VisualScriptEditor::_menu_option(int p_what) { - switch (p_what) { case EDIT_DELETE_NODES: { _on_nodes_delete(); } break; case EDIT_TOGGLE_BREAKPOINT: { - List<String> reselect; for (int i = 0; i < graph->get_child_count(); i++) { GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); @@ -4056,8 +4118,9 @@ void VisualScriptEditor::_menu_option(int p_what) { } break; case EDIT_COPY_NODES: case EDIT_CUT_NODES: { - if (!script->has_function(default_func)) + if (!script->has_function(default_func)) { break; + } clipboard->nodes.clear(); clipboard->data_connections.clear(); @@ -4068,7 +4131,6 @@ void VisualScriptEditor::_menu_option(int p_what) { GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); if (gn) { if (gn->is_selected()) { - int id = String(gn->get_name()).to_int(); StringName func = _get_function_of_node(id); Ref<VisualScriptNode> node = script->get_node(func, id); @@ -4085,8 +4147,9 @@ void VisualScriptEditor::_menu_option(int p_what) { } } - if (clipboard->nodes.empty()) + if (clipboard->nodes.empty()) { break; + } for (Set<String>::Element *F = funcs.front(); F; F = F->next()) { List<VisualScript::SequenceConnection> sequence_connections; @@ -4094,9 +4157,7 @@ void VisualScriptEditor::_menu_option(int p_what) { script->get_sequence_connection_list(F->get(), &sequence_connections); for (List<VisualScript::SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) { - if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) { - clipboard->sequence_connections.insert(E->get()); } } @@ -4106,9 +4167,7 @@ void VisualScriptEditor::_menu_option(int p_what) { script->get_data_connection_list(F->get(), &data_connections); for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { - if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) { - clipboard->data_connections.insert(E->get()); } } @@ -4119,8 +4178,9 @@ void VisualScriptEditor::_menu_option(int p_what) { } break; case EDIT_PASTE_NODES: { - if (!script->has_function(default_func)) + if (!script->has_function(default_func)) { break; + } if (clipboard->nodes.empty()) { EditorNode::get_singleton()->show_warning(TTR("Clipboard is empty!")); @@ -4150,7 +4210,6 @@ void VisualScriptEditor::_menu_option(int p_what) { } for (Map<int, Ref<VisualScriptNode>>::Element *E = clipboard->nodes.front(); E; E = E->next()) { - Ref<VisualScriptNode> node = E->get()->duplicate(); int new_id = idc++; @@ -4169,13 +4228,11 @@ void VisualScriptEditor::_menu_option(int p_what) { } for (Set<VisualScript::SequenceConnection>::Element *E = clipboard->sequence_connections.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "sequence_connect", default_func, remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", default_func, remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]); } for (Set<VisualScript::DataConnection>::Element *E = clipboard->data_connections.front(); E; E = E->next()) { - undo_redo->add_do_method(script.ptr(), "data_connect", default_func, remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); undo_redo->add_undo_method(script.ptr(), "data_disconnect", default_func, remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port); } @@ -4194,7 +4251,6 @@ void VisualScriptEditor::_menu_option(int p_what) { } } break; case EDIT_CREATE_FUNCTION: { - StringName function = ""; Map<int, Ref<VisualScriptNode>> nodes; Set<int> selections; @@ -4236,9 +4292,9 @@ void VisualScriptEditor::_menu_option(int p_what) { Set<int> end_nodes; if (nodes.size() == 1) { Ref<VisualScriptNode> nd = script->get_node(function, nodes.front()->key()); - if (nd.is_valid() && nd->has_input_sequence_port()) + if (nd.is_valid() && nd->has_input_sequence_port()) { start_node = nodes.front()->key(); - else { + } else { EditorNode::get_singleton()->show_warning(TTR("Select at least one node with sequence port.")); return; } @@ -4267,9 +4323,9 @@ void VisualScriptEditor::_menu_option(int p_what) { } } Ref<VisualScriptNode> nd = script->get_node(function, top_nd); - if (nd.is_valid() && nd->has_input_sequence_port()) + if (nd.is_valid() && nd->has_input_sequence_port()) { start_node = top_nd; - else { + } else { EditorNode::get_singleton()->show_warning(TTR("Select at least one node with sequence port.")); return; } @@ -4466,7 +4522,6 @@ void VisualScriptEditor::_get_ends(int p_node, const List<VisualScript::Sequence } void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { - TreeItem *ti = members->get_selected(); ERR_FAIL_COND(!ti); @@ -4479,12 +4534,11 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { TreeItem *root = members->get_root(); - Ref<Texture2D> del_icon = Control::get_icon("Remove", "EditorIcons"); + Ref<Texture2D> del_icon = Control::get_theme_icon("Remove", "EditorIcons"); - Ref<Texture2D> edit_icon = Control::get_icon("Edit", "EditorIcons"); + Ref<Texture2D> edit_icon = Control::get_theme_icon("Edit", "EditorIcons"); if (ti->get_parent() == root->get_children()) { - member_type = MEMBER_FUNCTION; member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); @@ -4495,7 +4549,6 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { } if (ti->get_parent() == root->get_children()->get_next()) { - member_type = MEMBER_VARIABLE; member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); @@ -4506,7 +4559,6 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { } if (ti->get_parent() == root->get_children()->get_next()->get_next()) { - member_type = MEMBER_SIGNAL; member_name = ti->get_text(0); member_popup->add_icon_shortcut(edit_icon, ED_GET_SHORTCUT("visual_script_editor/edit_member"), MEMBER_EDIT); @@ -4518,10 +4570,8 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { } void VisualScriptEditor::_member_option(int p_option) { - switch (member_type) { case MEMBER_FUNCTION: { - if (p_option == MEMBER_REMOVE) { //delete the function String name = member_name; @@ -4564,7 +4614,6 @@ void VisualScriptEditor::_member_option(int p_option) { } } break; case MEMBER_VARIABLE: { - String name = member_name; if (p_option == MEMBER_REMOVE) { @@ -4578,7 +4627,7 @@ void VisualScriptEditor::_member_option(int p_option) { } else if (p_option == MEMBER_EDIT) { variable_editor->edit(name); edit_variable_dialog->set_title(TTR("Editing Variable:") + " " + name); - edit_variable_dialog->popup_centered_minsize(Size2(400, 200) * EDSCALE); + edit_variable_dialog->popup_centered(Size2(400, 200) * EDSCALE); } } break; case MEMBER_SIGNAL: { @@ -4599,7 +4648,7 @@ void VisualScriptEditor::_member_option(int p_option) { } else if (p_option == MEMBER_EDIT) { signal_editor->edit(name); edit_signal_dialog->set_title(TTR("Editing Signal:") + " " + name); - edit_signal_dialog->popup_centered_minsize(Size2(400, 300) * EDSCALE); + edit_signal_dialog->popup_centered(Size2(400, 300) * EDSCALE); } } break; } @@ -4612,7 +4661,6 @@ void VisualScriptEditor::set_syntax_highlighter(SyntaxHighlighter *p_highlighter } void VisualScriptEditor::_bind_methods() { - ClassDB::bind_method("_move_node", &VisualScriptEditor::_move_node); ClassDB::bind_method("_update_graph", &VisualScriptEditor::_update_graph, DEFVAL(-1)); @@ -4629,12 +4677,12 @@ void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_input", &VisualScriptEditor::_input); ClassDB::bind_method("_update_graph_connections", &VisualScriptEditor::_update_graph_connections); + ClassDB::bind_method("_update_members", &VisualScriptEditor::_update_members); ClassDB::bind_method("_generic_search", &VisualScriptEditor::_generic_search); } VisualScriptEditor::VisualScriptEditor() { - if (!clipboard) { clipboard = memnew(Clipboard); } @@ -4687,10 +4735,9 @@ VisualScriptEditor::VisualScriptEditor() { add_child(member_popup); member_popup->connect("id_pressed", callable_mp(this, &VisualScriptEditor::_member_option)); - function_name_edit = memnew(PopupDialog); + function_name_edit = memnew(AcceptDialog); function_name_box = memnew(LineEdit); function_name_edit->add_child(function_name_box); - function_name_edit->set_h_size_flags(SIZE_EXPAND); function_name_box->connect("gui_input", callable_mp(this, &VisualScriptEditor::_fn_name_box_input)); function_name_box->set_expand_to_text_length(true); add_child(function_name_edit); @@ -4770,7 +4817,6 @@ VisualScriptEditor::VisualScriptEditor() { func_input_scroll->add_child(func_input_vbox); function_create_dialog = memnew(ConfirmationDialog); - function_create_dialog->set_v_size_flags(SIZE_EXPAND_FILL); function_create_dialog->set_title(TTR("Create Function")); function_create_dialog->add_child(function_vb); function_create_dialog->get_ok()->set_text(TTR("Create")); @@ -4859,7 +4905,6 @@ VisualScriptEditor::VisualScriptEditor() { new_connect_node_select = memnew(VisualScriptPropertySelector); add_child(new_connect_node_select); - new_connect_node_select->set_resizable(true); new_connect_node_select->connect("selected", callable_mp(this, &VisualScriptEditor::_selected_connect_node)); new_connect_node_select->get_cancel()->connect("pressed", callable_mp(this, &VisualScriptEditor::_cancel_connect_node)); @@ -4869,30 +4914,28 @@ VisualScriptEditor::VisualScriptEditor() { } VisualScriptEditor::~VisualScriptEditor() { - undo_redo->clear_history(); // Avoid crashes. memdelete(signal_editor); memdelete(variable_editor); } static ScriptEditorBase *create_editor(const RES &p_resource) { - if (Object::cast_to<VisualScript>(*p_resource)) { return memnew(VisualScriptEditor); } - return NULL; + return nullptr; } -VisualScriptEditor::Clipboard *VisualScriptEditor::clipboard = NULL; +VisualScriptEditor::Clipboard *VisualScriptEditor::clipboard = nullptr; void VisualScriptEditor::free_clipboard() { - if (clipboard) + if (clipboard) { memdelete(clipboard); + } } static void register_editor_callback() { - ScriptEditor::register_create_script_editor_function(create_editor); ED_SHORTCUT("visual_script_editor/delete_selected", TTR("Delete Selected"), KEY_DELETE); @@ -4907,20 +4950,18 @@ static void register_editor_callback() { } void VisualScriptEditor::register_editor() { - // Too early to register stuff here, request a callback. EditorNode::add_plugin_init_callback(register_editor_callback); } Ref<VisualScriptNode> _VisualScriptEditor::create_node_custom(const String &p_name) { - Ref<VisualScriptCustomNode> node; node.instance(); node->set_script(singleton->custom_nodes[p_name]); return node; } -_VisualScriptEditor *_VisualScriptEditor::singleton = NULL; +_VisualScriptEditor *_VisualScriptEditor::singleton = nullptr; Map<String, REF> _VisualScriptEditor::custom_nodes; _VisualScriptEditor::_VisualScriptEditor() { diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 6ff00cf0a6..37063b2da1 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -114,7 +114,7 @@ class VisualScriptEditor : public ScriptEditorBase { UndoRedo *undo_redo; Tree *members; - PopupDialog *function_name_edit; + AcceptDialog *function_name_edit; LineEdit *function_name_box; Label *hint_text; @@ -152,7 +152,6 @@ class VisualScriptEditor : public ScriptEditorBase { String _validate_name(const String &p_name) const; struct Clipboard { - Map<int, Ref<VisualScriptNode>> nodes; Map<int, Vector2> nodes_positions; @@ -298,7 +297,7 @@ public: virtual Vector<String> get_functions(); virtual void reload_text(); virtual String get_name(); - virtual Ref<Texture2D> get_icon(); + virtual Ref<Texture2D> get_theme_icon(); virtual bool is_unsaved(); virtual Variant get_edit_state(); virtual void set_edit_state(const Variant &p_state); diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index c52315a477..bd41117497 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -31,7 +31,6 @@ #include "visual_script_expression.h" bool VisualScriptExpression::_set(const StringName &p_name, const Variant &p_value) { - if (String(p_name) == "expression") { expression = p_value; expression_dirty = true; @@ -52,7 +51,6 @@ bool VisualScriptExpression::_set(const StringName &p_name, const Variant &p_val } if (String(p_name) == "input_count") { - int from = inputs.size(); inputs.resize(int(p_value)); for (int i = from; i < inputs.size(); i++) { @@ -70,17 +68,14 @@ bool VisualScriptExpression::_set(const StringName &p_name, const Variant &p_val } if (String(p_name).begins_with("input_")) { - int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int(); ERR_FAIL_INDEX_V(idx, inputs.size(), false); String what = String(p_name).get_slice("/", 1); if (what == "type") { - inputs.write[idx].type = Variant::Type(int(p_value)); } else if (what == "name") { - inputs.write[idx].name = p_value; } else { return false; @@ -95,7 +90,6 @@ bool VisualScriptExpression::_set(const StringName &p_name, const Variant &p_val } bool VisualScriptExpression::_get(const StringName &p_name, Variant &r_ret) const { - if (String(p_name) == "expression") { r_ret = expression; return true; @@ -117,17 +111,14 @@ bool VisualScriptExpression::_get(const StringName &p_name, Variant &r_ret) cons } if (String(p_name).begins_with("input_")) { - int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int(); ERR_FAIL_INDEX_V(idx, inputs.size(), false); String what = String(p_name).get_slice("/", 1); if (what == "type") { - r_ret = inputs[idx].type; } else if (what == "name") { - r_ret = inputs[idx].name; } else { return false; @@ -138,8 +129,8 @@ bool VisualScriptExpression::_get(const StringName &p_name, Variant &r_ret) cons return false; } -void VisualScriptExpression::_get_property_list(List<PropertyInfo> *p_list) const { +void VisualScriptExpression::_get_property_list(List<PropertyInfo> *p_list) const { String argt = "Any"; for (int i = 1; i < Variant::VARIANT_MAX; i++) { argt += "," + Variant::get_type_name(Variant::Type(i)); @@ -151,55 +142,48 @@ void VisualScriptExpression::_get_property_list(List<PropertyInfo> *p_list) cons p_list->push_back(PropertyInfo(Variant::BOOL, "sequenced")); for (int i = 0; i < inputs.size(); i++) { - p_list->push_back(PropertyInfo(Variant::INT, "input_" + itos(i) + "/type", PROPERTY_HINT_ENUM, argt)); p_list->push_back(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name")); } } int VisualScriptExpression::get_output_sequence_port_count() const { - return sequenced ? 1 : 0; } -bool VisualScriptExpression::has_input_sequence_port() const { +bool VisualScriptExpression::has_input_sequence_port() const { return sequenced; } String VisualScriptExpression::get_output_sequence_port_text(int p_port) const { - return String(); } int VisualScriptExpression::get_input_value_port_count() const { - return inputs.size(); } -int VisualScriptExpression::get_output_value_port_count() const { +int VisualScriptExpression::get_output_value_port_count() const { return 1; } PropertyInfo VisualScriptExpression::get_input_value_port_info(int p_idx) const { - return PropertyInfo(inputs[p_idx].type, inputs[p_idx].name); } -PropertyInfo VisualScriptExpression::get_output_value_port_info(int p_idx) const { +PropertyInfo VisualScriptExpression::get_output_value_port_info(int p_idx) const { return PropertyInfo(output_type, "result"); } String VisualScriptExpression::get_caption() const { - return "Expression"; } -String VisualScriptExpression::get_text() const { +String VisualScriptExpression::get_text() const { return expression; } Error VisualScriptExpression::_get_token(Token &r_token) { - while (true) { #define GET_CHAR() (str_ofs >= expression.length() ? 0 : expression[str_ofs++]) @@ -210,58 +194,47 @@ Error VisualScriptExpression::_get_token(Token &r_token) { } switch (cchar) { - case 0: { r_token.type = TK_EOF; return OK; } break; case '{': { - r_token.type = TK_CURLY_BRACKET_OPEN; return OK; }; case '}': { - r_token.type = TK_CURLY_BRACKET_CLOSE; return OK; }; case '[': { - r_token.type = TK_BRACKET_OPEN; return OK; }; case ']': { - r_token.type = TK_BRACKET_CLOSE; return OK; }; case '(': { - r_token.type = TK_PARENTHESIS_OPEN; return OK; }; case ')': { - r_token.type = TK_PARENTHESIS_CLOSE; return OK; }; case ',': { - r_token.type = TK_COMMA; return OK; }; case ':': { - r_token.type = TK_COLON; return OK; }; case '.': { - r_token.type = TK_PERIOD; return OK; }; case '=': { - cchar = GET_CHAR(); if (cchar == '=') { r_token.type = TK_OP_EQUAL; @@ -273,7 +246,6 @@ Error VisualScriptExpression::_get_token(Token &r_token) { return OK; }; case '!': { - if (expression[str_ofs] == '=') { r_token.type = TK_OP_NOT_EQUAL; str_ofs++; @@ -283,7 +255,6 @@ Error VisualScriptExpression::_get_token(Token &r_token) { return OK; }; case '>': { - if (expression[str_ofs] == '=') { r_token.type = TK_OP_GREATER_EQUAL; str_ofs++; @@ -296,7 +267,6 @@ Error VisualScriptExpression::_get_token(Token &r_token) { return OK; }; case '<': { - if (expression[str_ofs] == '=') { r_token.type = TK_OP_LESS_EQUAL; str_ofs++; @@ -329,7 +299,6 @@ Error VisualScriptExpression::_get_token(Token &r_token) { return OK; }; case '&': { - if (expression[str_ofs] == '&') { r_token.type = TK_OP_AND; str_ofs++; @@ -339,7 +308,6 @@ Error VisualScriptExpression::_get_token(Token &r_token) { return OK; }; case '|': { - if (expression[str_ofs] == '|') { r_token.type = TK_OP_OR; str_ofs++; @@ -349,22 +317,18 @@ Error VisualScriptExpression::_get_token(Token &r_token) { return OK; }; case '^': { - r_token.type = TK_OP_BIT_XOR; return OK; }; case '~': { - r_token.type = TK_OP_BIT_INVERT; return OK; }; case '"': { - String str; while (true) { - CharType ch = GET_CHAR(); if (ch == 0) { @@ -385,12 +349,21 @@ Error VisualScriptExpression::_get_token(Token &r_token) { CharType res = 0; switch (next) { - - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; - case 'r': res = 13; break; + case 'b': + res = 8; + break; + case 't': + res = 9; + break; + case 'n': + res = 10; + break; + case 'f': + res = 12; + break; + case 'r': + res = 13; + break; case 'u': { // hex number for (int j = 0; j < 4; j++) { @@ -402,7 +375,6 @@ Error VisualScriptExpression::_get_token(Token &r_token) { return ERR_PARSE_ERROR; } if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { - _set_error("Malformed hex constant in string"); r_token.type = TK_ERROR; return ERR_PARSE_ERROR; @@ -444,7 +416,6 @@ Error VisualScriptExpression::_get_token(Token &r_token) { } break; default: { - if (cchar <= 32) { break; } @@ -466,10 +437,8 @@ Error VisualScriptExpression::_get_token(Token &r_token) { bool is_float = false; while (true) { - switch (reading) { case READING_INT: { - if (c >= '0' && c <= '9') { //pass } else if (c == '.') { @@ -483,9 +452,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { } break; case READING_DEC: { - if (c >= '0' && c <= '9') { - } else if (c == 'e') { reading = READING_EXP; @@ -495,13 +462,13 @@ Error VisualScriptExpression::_get_token(Token &r_token) { } break; case READING_EXP: { - if (c >= '0' && c <= '9') { exp_beg = true; } else if ((c == '-' || c == '+') && !exp_sign && !exp_beg) { - if (c == '-') + if (c == '-') { is_float = true; + } exp_sign = true; } else { @@ -510,8 +477,9 @@ Error VisualScriptExpression::_get_token(Token &r_token) { } break; } - if (reading == READING_DONE) + if (reading == READING_DONE) { break; + } num += String::chr(c); c = GET_CHAR(); } @@ -520,19 +488,18 @@ Error VisualScriptExpression::_get_token(Token &r_token) { r_token.type = TK_CONSTANT; - if (is_float) + if (is_float) { r_token.value = num.to_double(); - else + } else { r_token.value = num.to_int(); + } return OK; } else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') { - String id; bool first = true; while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && cchar >= '0' && cchar <= '9')) { - id += String::chr(cchar); cchar = GET_CHAR(); first = false; @@ -572,7 +539,6 @@ Error VisualScriptExpression::_get_token(Token &r_token) { } else if (id == "self") { r_token.type = TK_SELF; } else { - for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (id == Variant::get_type_name(Variant::Type(i))) { r_token.type = TK_BASIC_TYPE; @@ -647,17 +613,17 @@ const char *VisualScriptExpression::token_name[TK_MAX] = { }; VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { - Vector<Expression> expression; while (true) { //keep appending stuff to expression - ENode *expr = NULL; + ENode *expr = nullptr; Token tk; _get_token(tk); - if (error_set) - return NULL; + if (error_set) { + return nullptr; + } switch (tk.type) { case TK_CURLY_BRACKET_OPEN: { @@ -665,7 +631,6 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { DictionaryNode *dn = alloc_node<DictionaryNode>(); while (true) { - int cofs = str_ofs; _get_token(tk); if (tk.type == TK_CURLY_BRACKET_CLOSE) { @@ -674,19 +639,21 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { str_ofs = cofs; //revert //parse an expression ENode *expr2 = _parse_expression(); - if (!expr2) - return NULL; + if (!expr2) { + return nullptr; + } dn->dict.push_back(expr2); _get_token(tk); if (tk.type != TK_COLON) { _set_error("Expected ':'"); - return NULL; + return nullptr; } expr2 = _parse_expression(); - if (!expr2) - return NULL; + if (!expr2) { + return nullptr; + } dn->dict.push_back(expr2); @@ -709,7 +676,6 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { ArrayNode *an = alloc_node<ArrayNode>(); while (true) { - int cofs = str_ofs; _get_token(tk); if (tk.type == TK_BRACKET_CLOSE) { @@ -718,8 +684,9 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { str_ofs = cofs; //revert //parse an expression ENode *expr2 = _parse_expression(); - if (!expr2) - return NULL; + if (!expr2) { + return nullptr; + } an->array.push_back(expr2); cofs = str_ofs; @@ -738,19 +705,19 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { case TK_PARENTHESIS_OPEN: { //a suexpression ENode *e = _parse_expression(); - if (error_set) - return NULL; + if (error_set) { + return nullptr; + } _get_token(tk); if (tk.type != TK_PARENTHESIS_CLOSE) { _set_error("Expected ')'"); - return NULL; + return nullptr; } expr = e; } break; case TK_IDENTIFIER: { - String what = tk.value; int index = -1; for (int i = 0; i < inputs.size(); i++) { @@ -766,11 +733,10 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { expr = input; } else { _set_error("Invalid input identifier '" + what + "'. For script variables, use self (locals are for inputs)." + what); - return NULL; + return nullptr; } } break; case TK_SELF: { - SelfNode *self = alloc_node<SelfNode>(); expr = self; } break; @@ -786,14 +752,13 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { _get_token(tk); if (tk.type != TK_PARENTHESIS_OPEN) { _set_error("Expected '('"); - return NULL; + return nullptr; } ConstructorNode *constructor = alloc_node<ConstructorNode>(); constructor->data_type = bt; while (true) { - int cofs = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { @@ -802,8 +767,9 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { str_ofs = cofs; //revert //parse an expression ENode *expr2 = _parse_expression(); - if (!expr2) - return NULL; + if (!expr2) { + return nullptr; + } constructor->arguments.push_back(expr2); @@ -827,14 +793,13 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { _get_token(tk); if (tk.type != TK_PARENTHESIS_OPEN) { _set_error("Expected '('"); - return NULL; + return nullptr; } BuiltinFuncNode *bifunc = alloc_node<BuiltinFuncNode>(); bifunc->func = VisualScriptBuiltinFunc::BuiltinFunc(int(tk.value)); while (true) { - int cofs = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { @@ -843,8 +808,9 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { str_ofs = cofs; //revert //parse an expression ENode *expr2 = _parse_expression(); - if (!expr2) - return NULL; + if (!expr2) { + return nullptr; + } bifunc->arguments.push_back(expr2); @@ -868,7 +834,6 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } break; case TK_OP_SUB: { - Expression e; e.is_op = true; e.op = Variant::OP_NEGATE; @@ -876,7 +841,6 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { continue; } break; case TK_OP_NOT: { - Expression e; e.is_op = true; e.op = Variant::OP_NOT; @@ -886,7 +850,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { default: { _set_error("Expected expression."); - return NULL; + return nullptr; } break; } @@ -895,8 +859,9 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { while (true) { int cofs2 = str_ofs; _get_token(tk); - if (error_set) - return NULL; + if (error_set) { + return nullptr; + } bool done = false; @@ -908,15 +873,16 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { index->base = expr; ENode *what = _parse_expression(); - if (!what) - return NULL; + if (!what) { + return nullptr; + } index->index = what; _get_token(tk); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']' at end of index."); - return NULL; + return nullptr; } expr = index; @@ -926,7 +892,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { _get_token(tk); if (tk.type != TK_IDENTIFIER) { _set_error("Expected identifier after '.'"); - return NULL; + return nullptr; } StringName identifier = tk.value; @@ -940,7 +906,6 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { func_call->base = expr; while (true) { - int cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { @@ -949,8 +914,9 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { str_ofs = cofs3; //revert //parse an expression ENode *expr2 = _parse_expression(); - if (!expr2) - return NULL; + if (!expr2) { + return nullptr; + } func_call->arguments.push_back(expr2); @@ -983,8 +949,9 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } break; } - if (done) + if (done) { break; + } } //push expression @@ -999,33 +966,76 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { int cofs = str_ofs; _get_token(tk); - if (error_set) - return NULL; + if (error_set) { + return nullptr; + } Variant::Operator op = Variant::OP_MAX; switch (tk.type) { - case TK_OP_IN: op = Variant::OP_IN; break; - case TK_OP_EQUAL: op = Variant::OP_EQUAL; break; - case TK_OP_NOT_EQUAL: op = Variant::OP_NOT_EQUAL; break; - case TK_OP_LESS: op = Variant::OP_LESS; break; - case TK_OP_LESS_EQUAL: op = Variant::OP_LESS_EQUAL; break; - case TK_OP_GREATER: op = Variant::OP_GREATER; break; - case TK_OP_GREATER_EQUAL: op = Variant::OP_GREATER_EQUAL; break; - case TK_OP_AND: op = Variant::OP_AND; break; - case TK_OP_OR: op = Variant::OP_OR; break; - case TK_OP_NOT: op = Variant::OP_NOT; break; - case TK_OP_ADD: op = Variant::OP_ADD; break; - case TK_OP_SUB: op = Variant::OP_SUBTRACT; break; - case TK_OP_MUL: op = Variant::OP_MULTIPLY; break; - case TK_OP_DIV: op = Variant::OP_DIVIDE; break; - case TK_OP_MOD: op = Variant::OP_MODULE; break; - case TK_OP_SHIFT_LEFT: op = Variant::OP_SHIFT_LEFT; break; - case TK_OP_SHIFT_RIGHT: op = Variant::OP_SHIFT_RIGHT; break; - case TK_OP_BIT_AND: op = Variant::OP_BIT_AND; break; - case TK_OP_BIT_OR: op = Variant::OP_BIT_OR; break; - case TK_OP_BIT_XOR: op = Variant::OP_BIT_XOR; break; - case TK_OP_BIT_INVERT: op = Variant::OP_BIT_NEGATE; break; + case TK_OP_IN: + op = Variant::OP_IN; + break; + case TK_OP_EQUAL: + op = Variant::OP_EQUAL; + break; + case TK_OP_NOT_EQUAL: + op = Variant::OP_NOT_EQUAL; + break; + case TK_OP_LESS: + op = Variant::OP_LESS; + break; + case TK_OP_LESS_EQUAL: + op = Variant::OP_LESS_EQUAL; + break; + case TK_OP_GREATER: + op = Variant::OP_GREATER; + break; + case TK_OP_GREATER_EQUAL: + op = Variant::OP_GREATER_EQUAL; + break; + case TK_OP_AND: + op = Variant::OP_AND; + break; + case TK_OP_OR: + op = Variant::OP_OR; + break; + case TK_OP_NOT: + op = Variant::OP_NOT; + break; + case TK_OP_ADD: + op = Variant::OP_ADD; + break; + case TK_OP_SUB: + op = Variant::OP_SUBTRACT; + break; + case TK_OP_MUL: + op = Variant::OP_MULTIPLY; + break; + case TK_OP_DIV: + op = Variant::OP_DIVIDE; + break; + case TK_OP_MOD: + op = Variant::OP_MODULE; + break; + case TK_OP_SHIFT_LEFT: + op = Variant::OP_SHIFT_LEFT; + break; + case TK_OP_SHIFT_RIGHT: + op = Variant::OP_SHIFT_RIGHT; + break; + case TK_OP_BIT_AND: + op = Variant::OP_BIT_AND; + break; + case TK_OP_BIT_OR: + op = Variant::OP_BIT_OR; + break; + case TK_OP_BIT_XOR: + op = Variant::OP_BIT_XOR; + break; + case TK_OP_BIT_INVERT: + op = Variant::OP_BIT_NEGATE; + break; default: { }; } @@ -1047,15 +1057,12 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ while (expression.size() > 1) { - int next_op = -1; int min_priority = 0xFFFFF; bool is_unary = false; for (int i = 0; i < expression.size(); i++) { - if (!expression[i].is_op) { - continue; } @@ -1064,7 +1071,6 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { bool unary = false; switch (expression[i].op) { - case Variant::OP_BIT_NEGATE: priority = 0; unary = true; @@ -1074,40 +1080,78 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { unary = true; break; - case Variant::OP_MULTIPLY: priority = 2; break; - case Variant::OP_DIVIDE: priority = 2; break; - case Variant::OP_MODULE: priority = 2; break; + case Variant::OP_MULTIPLY: + priority = 2; + break; + case Variant::OP_DIVIDE: + priority = 2; + break; + case Variant::OP_MODULE: + priority = 2; + break; - case Variant::OP_ADD: priority = 3; break; - case Variant::OP_SUBTRACT: priority = 3; break; + case Variant::OP_ADD: + priority = 3; + break; + case Variant::OP_SUBTRACT: + priority = 3; + break; - case Variant::OP_SHIFT_LEFT: priority = 4; break; - case Variant::OP_SHIFT_RIGHT: priority = 4; break; + case Variant::OP_SHIFT_LEFT: + priority = 4; + break; + case Variant::OP_SHIFT_RIGHT: + priority = 4; + break; - case Variant::OP_BIT_AND: priority = 5; break; - case Variant::OP_BIT_XOR: priority = 6; break; - case Variant::OP_BIT_OR: priority = 7; break; + case Variant::OP_BIT_AND: + priority = 5; + break; + case Variant::OP_BIT_XOR: + priority = 6; + break; + case Variant::OP_BIT_OR: + priority = 7; + break; - case Variant::OP_LESS: priority = 8; break; - case Variant::OP_LESS_EQUAL: priority = 8; break; - case Variant::OP_GREATER: priority = 8; break; - case Variant::OP_GREATER_EQUAL: priority = 8; break; + case Variant::OP_LESS: + priority = 8; + break; + case Variant::OP_LESS_EQUAL: + priority = 8; + break; + case Variant::OP_GREATER: + priority = 8; + break; + case Variant::OP_GREATER_EQUAL: + priority = 8; + break; - case Variant::OP_EQUAL: priority = 8; break; - case Variant::OP_NOT_EQUAL: priority = 8; break; + case Variant::OP_EQUAL: + priority = 8; + break; + case Variant::OP_NOT_EQUAL: + priority = 8; + break; - case Variant::OP_IN: priority = 10; break; + case Variant::OP_IN: + priority = 10; + break; case Variant::OP_NOT: priority = 11; unary = true; break; - case Variant::OP_AND: priority = 12; break; - case Variant::OP_OR: priority = 13; break; + case Variant::OP_AND: + priority = 12; + break; + case Variant::OP_OR: + priority = 13; + break; default: { _set_error("Parser bug, invalid operator in expression: " + itos(expression[i].op)); - return NULL; + return nullptr; } } @@ -1122,51 +1166,45 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } if (next_op == -1) { - _set_error("Yet another parser bug...."); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } // OK! create operator.. if (is_unary) { - int expr_pos = next_op; while (expression[expr_pos].is_op) { - expr_pos++; if (expr_pos == expression.size()) { //can happen.. _set_error("Unexpected end of expression..."); - return NULL; + return nullptr; } } //consecutively do unary operators for (int i = expr_pos - 1; i >= next_op; i--) { - OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; op->nodes[0] = expression[i + 1].node; - op->nodes[1] = NULL; + op->nodes[1] = nullptr; expression.write[i].is_op = false; expression.write[i].node = op; expression.remove(i + 1); } } else { - if (next_op < 1 || next_op >= (expression.size() - 1)) { _set_error("Parser bug..."); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[next_op].op; if (expression[next_op - 1].is_op) { - _set_error("Parser bug..."); - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } if (expression[next_op + 1].is_op) { @@ -1176,7 +1214,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { // due to how precedence works, unaries will always disappear first _set_error("Unexpected two consecutive operators."); - return NULL; + return nullptr; } op->nodes[0] = expression[next_op - 1].node; //expression goes as left @@ -1193,14 +1231,14 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { } bool VisualScriptExpression::_compile_expression() { - - if (!expression_dirty) + if (!expression_dirty) { return error_set; + } if (nodes) { memdelete(nodes); - nodes = NULL; - root = NULL; + nodes = nullptr; + root = nullptr; } error_str = String(); @@ -1210,11 +1248,11 @@ bool VisualScriptExpression::_compile_expression() { root = _parse_expression(); if (error_set) { - root = NULL; + root = nullptr; if (nodes) { memdelete(nodes); } - nodes = NULL; + nodes = nullptr; return true; } @@ -1230,38 +1268,35 @@ public: //virtual int get_working_memory_size() const { return 0; } //execute by parsing the tree directly virtual bool _execute(const Variant **p_inputs, VisualScriptExpression::ENode *p_node, Variant &r_ret, String &r_error_str, Callable::CallError &ce) { - switch (p_node->type) { case VisualScriptExpression::ENode::TYPE_INPUT: { - const VisualScriptExpression::InputNode *in = static_cast<const VisualScriptExpression::InputNode *>(p_node); r_ret = *p_inputs[in->index]; } break; case VisualScriptExpression::ENode::TYPE_CONSTANT: { - const VisualScriptExpression::ConstantNode *c = static_cast<const VisualScriptExpression::ConstantNode *>(p_node); r_ret = c->value; } break; case VisualScriptExpression::ENode::TYPE_SELF: { - r_ret = instance->get_owner_ptr(); } break; case VisualScriptExpression::ENode::TYPE_OPERATOR: { - const VisualScriptExpression::OperatorNode *op = static_cast<const VisualScriptExpression::OperatorNode *>(p_node); Variant a; bool ret = _execute(p_inputs, op->nodes[0], a, r_error_str, ce); - if (ret) + if (ret) { return true; + } Variant b; if (op->nodes[1]) { ret = _execute(p_inputs, op->nodes[1], b, r_error_str, ce); - if (ret) + if (ret) { return true; + } } bool valid = true; @@ -1273,19 +1308,20 @@ public: } break; case VisualScriptExpression::ENode::TYPE_INDEX: { - const VisualScriptExpression::IndexNode *index = static_cast<const VisualScriptExpression::IndexNode *>(p_node); Variant base; bool ret = _execute(p_inputs, index->base, base, r_error_str, ce); - if (ret) + if (ret) { return true; + } Variant idx; ret = _execute(p_inputs, index->index, idx, r_error_str, ce); - if (ret) + if (ret) { return true; + } bool valid; r_ret = base.get(idx, &valid); @@ -1296,13 +1332,13 @@ public: } break; case VisualScriptExpression::ENode::TYPE_NAMED_INDEX: { - const VisualScriptExpression::NamedIndexNode *index = static_cast<const VisualScriptExpression::NamedIndexNode *>(p_node); Variant base; bool ret = _execute(p_inputs, index->base, base, r_error_str, ce); - if (ret) + if (ret) { return true; + } bool valid; r_ret = base.get_named(index->name, &valid); @@ -1318,11 +1354,11 @@ public: Array arr; arr.resize(array->array.size()); for (int i = 0; i < array->array.size(); i++) { - Variant value; bool ret = _execute(p_inputs, array->array[i], value, r_error_str, ce); - if (ret) + if (ret) { return true; + } arr[i] = value; } @@ -1334,16 +1370,17 @@ public: Dictionary d; for (int i = 0; i < dictionary->dict.size(); i += 2) { - Variant key; bool ret = _execute(p_inputs, dictionary->dict[i + 0], key, r_error_str, ce); - if (ret) + if (ret) { return true; + } Variant value; ret = _execute(p_inputs, dictionary->dict[i + 1], value, r_error_str, ce); - if (ret) + if (ret) { return true; + } d[key] = value; } @@ -1351,7 +1388,6 @@ public: r_ret = d; } break; case VisualScriptExpression::ENode::TYPE_CONSTRUCTOR: { - const VisualScriptExpression::ConstructorNode *constructor = static_cast<const VisualScriptExpression::ConstructorNode *>(p_node); Vector<Variant> arr; @@ -1360,11 +1396,11 @@ public: argp.resize(constructor->arguments.size()); for (int i = 0; i < constructor->arguments.size(); i++) { - Variant value; bool ret = _execute(p_inputs, constructor->arguments[i], value, r_error_str, ce); - if (ret) + if (ret) { return true; + } arr.write[i] = value; argp.write[i] = &arr[i]; } @@ -1378,7 +1414,6 @@ public: } break; case VisualScriptExpression::ENode::TYPE_BUILTIN_FUNC: { - const VisualScriptExpression::BuiltinFuncNode *bifunc = static_cast<const VisualScriptExpression::BuiltinFuncNode *>(p_node); Vector<Variant> arr; @@ -1387,11 +1422,11 @@ public: argp.resize(bifunc->arguments.size()); for (int i = 0; i < bifunc->arguments.size(); i++) { - Variant value; bool ret = _execute(p_inputs, bifunc->arguments[i], value, r_error_str, ce); - if (ret) + if (ret) { return true; + } arr.write[i] = value; argp.write[i] = &arr[i]; } @@ -1405,13 +1440,13 @@ public: } break; case VisualScriptExpression::ENode::TYPE_CALL: { - const VisualScriptExpression::CallNode *call = static_cast<const VisualScriptExpression::CallNode *>(p_node); Variant base; bool ret = _execute(p_inputs, call->base, base, r_error_str, ce); - if (ret) + if (ret) { return true; + } Vector<Variant> arr; Vector<const Variant *> argp; @@ -1419,11 +1454,11 @@ public: argp.resize(call->arguments.size()); for (int i = 0; i < call->arguments.size(); i++) { - Variant value; bool ret2 = _execute(p_inputs, call->arguments[i], value, r_error_str, ce); - if (ret2) + if (ret2) { return true; + } arr.write[i] = value; argp.write[i] = &arr[i]; } @@ -1441,7 +1476,6 @@ public: } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (!expression->root || expression->error_set) { r_error_str = expression->error_str; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -1455,7 +1489,6 @@ public: #ifdef DEBUG_ENABLED if (!error && expression->output_type != Variant::NIL && !Variant::can_convert_strict(p_outputs[0]->get_type(), expression->output_type)) { - r_error_str += "Can't convert expression result from " + Variant::get_type_name(p_outputs[0]->get_type()) + " to " + Variant::get_type_name(expression->output_type) + "."; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; } @@ -1466,7 +1499,6 @@ public: }; VisualScriptNodeInstance *VisualScriptExpression::instance(VisualScriptInstance *p_instance) { - _compile_expression(); VisualScriptNodeInstanceExpression *instance = memnew(VisualScriptNodeInstanceExpression); instance->instance = p_instance; @@ -1478,19 +1510,17 @@ VisualScriptExpression::VisualScriptExpression() { output_type = Variant::NIL; expression_dirty = true; error_set = true; - root = NULL; - nodes = NULL; + root = nullptr; + nodes = nullptr; sequenced = false; } VisualScriptExpression::~VisualScriptExpression() { - if (nodes) { memdelete(nodes); } } void register_visual_script_expression_node() { - VisualScriptLanguage::singleton->add_register_func("operators/expression", create_node_generic<VisualScriptExpression>); } diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h index d131713ef0..dee0213d54 100644 --- a/modules/visual_script/visual_script_expression.h +++ b/modules/visual_script/visual_script_expression.h @@ -35,12 +35,10 @@ #include "visual_script_builtin_funcs.h" class VisualScriptExpression : public VisualScriptNode { - GDCLASS(VisualScriptExpression, VisualScriptNode); friend class VisualScriptNodeInstanceExpression; struct Input { - Variant::Type type; String name; @@ -101,14 +99,14 @@ class VisualScriptExpression : public VisualScriptNode { static const char *token_name[TK_MAX]; struct Token { - TokenType type; Variant value; }; void _set_error(const String &p_err) { - if (error_set) + if (error_set) { return; + } error_str = p_err; error_set = true; } @@ -119,7 +117,6 @@ class VisualScriptExpression : public VisualScriptNode { bool error_set; struct ENode { - enum Type { TYPE_INPUT, TYPE_CONSTANT, @@ -138,7 +135,7 @@ class VisualScriptExpression : public VisualScriptNode { Type type; - ENode() { next = NULL; } + ENode() { next = nullptr; } virtual ~ENode() { if (next) { memdelete(next); @@ -147,7 +144,6 @@ class VisualScriptExpression : public VisualScriptNode { }; struct Expression { - bool is_op; union { Variant::Operator op; @@ -158,7 +154,6 @@ class VisualScriptExpression : public VisualScriptNode { ENode *_parse_expression(); struct InputNode : public ENode { - int index; InputNode() { type = TYPE_INPUT; @@ -166,7 +161,6 @@ class VisualScriptExpression : public VisualScriptNode { }; struct ConstantNode : public ENode { - Variant value; ConstantNode() { type = TYPE_CONSTANT; @@ -174,7 +168,6 @@ class VisualScriptExpression : public VisualScriptNode { }; struct OperatorNode : public ENode { - Variant::Operator op; ENode *nodes[2]; @@ -185,7 +178,6 @@ class VisualScriptExpression : public VisualScriptNode { }; struct SelfNode : public ENode { - SelfNode() { type = TYPE_SELF; } diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 475893e86d..3ed20fab35 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -39,78 +39,70 @@ ////////////////////////////////////////// int VisualScriptReturn::get_output_sequence_port_count() const { - return 0; } bool VisualScriptReturn::has_input_sequence_port() const { - return true; } int VisualScriptReturn::get_input_value_port_count() const { - return with_value ? 1 : 0; } -int VisualScriptReturn::get_output_value_port_count() const { +int VisualScriptReturn::get_output_value_port_count() const { return 0; } String VisualScriptReturn::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptReturn::get_input_value_port_info(int p_idx) const { - PropertyInfo pinfo; pinfo.name = "result"; pinfo.type = type; return pinfo; } + PropertyInfo VisualScriptReturn::get_output_value_port_info(int p_idx) const { return PropertyInfo(); } String VisualScriptReturn::get_caption() const { - return "Return"; } String VisualScriptReturn::get_text() const { - return get_name(); } void VisualScriptReturn::set_return_type(Variant::Type p_type) { - - if (type == p_type) + if (type == p_type) { return; + } type = p_type; ports_changed_notify(); } Variant::Type VisualScriptReturn::get_return_type() const { - return type; } void VisualScriptReturn::set_enable_return_value(bool p_enable) { - if (with_value == p_enable) + if (with_value == p_enable) { return; + } with_value = p_enable; ports_changed_notify(); } bool VisualScriptReturn::is_return_value_enabled() const { - return with_value; } void VisualScriptReturn::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_return_type", "type"), &VisualScriptReturn::set_return_type); ClassDB::bind_method(D_METHOD("get_return_type"), &VisualScriptReturn::get_return_type); ClassDB::bind_method(D_METHOD("set_enable_return_value", "enable"), &VisualScriptReturn::set_enable_return_value); @@ -136,7 +128,6 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (with_value) { *p_working_mem = *p_inputs[0]; return STEP_EXIT_FUNCTION_BIT; @@ -148,7 +139,6 @@ public: }; VisualScriptNodeInstance *VisualScriptReturn::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceReturn *instance = memnew(VisualScriptNodeInstanceReturn); instance->node = this; instance->instance = p_instance; @@ -157,14 +147,12 @@ VisualScriptNodeInstance *VisualScriptReturn::instance(VisualScriptInstance *p_i } VisualScriptReturn::VisualScriptReturn() { - with_value = false; type = Variant::NIL; } template <bool with_value> static Ref<VisualScriptNode> create_return_node(const String &p_name) { - Ref<VisualScriptReturn> node; node.instance(); node->set_enable_return_value(with_value); @@ -176,52 +164,47 @@ static Ref<VisualScriptNode> create_return_node(const String &p_name) { ////////////////////////////////////////// int VisualScriptCondition::get_output_sequence_port_count() const { - return 3; } bool VisualScriptCondition::has_input_sequence_port() const { - return true; } int VisualScriptCondition::get_input_value_port_count() const { - return 1; } -int VisualScriptCondition::get_output_value_port_count() const { +int VisualScriptCondition::get_output_value_port_count() const { return 0; } String VisualScriptCondition::get_output_sequence_port_text(int p_port) const { - - if (p_port == 0) + if (p_port == 0) { return "true"; - else if (p_port == 1) + } else if (p_port == 1) { return "false"; - else + } else { return "done"; + } } PropertyInfo VisualScriptCondition::get_input_value_port_info(int p_idx) const { - PropertyInfo pinfo; pinfo.name = "cond"; pinfo.type = Variant::BOOL; return pinfo; } + PropertyInfo VisualScriptCondition::get_output_value_port_info(int p_idx) const { return PropertyInfo(); } String VisualScriptCondition::get_caption() const { - return "Condition"; } String VisualScriptCondition::get_text() const { - return "if (cond) is: "; } @@ -238,18 +221,17 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - - if (p_start_mode == START_MODE_CONTINUE_SEQUENCE) + if (p_start_mode == START_MODE_CONTINUE_SEQUENCE) { return 2; - else if (p_inputs[0]->operator bool()) + } else if (p_inputs[0]->operator bool()) { return 0 | STEP_FLAG_PUSH_STACK_BIT; - else + } else { return 1 | STEP_FLAG_PUSH_STACK_BIT; + } } }; VisualScriptNodeInstance *VisualScriptCondition::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceCondition *instance = memnew(VisualScriptNodeInstanceCondition); instance->node = this; instance->instance = p_instance; @@ -264,50 +246,45 @@ VisualScriptCondition::VisualScriptCondition() { ////////////////////////////////////////// int VisualScriptWhile::get_output_sequence_port_count() const { - return 2; } bool VisualScriptWhile::has_input_sequence_port() const { - return true; } int VisualScriptWhile::get_input_value_port_count() const { - return 1; } -int VisualScriptWhile::get_output_value_port_count() const { +int VisualScriptWhile::get_output_value_port_count() const { return 0; } String VisualScriptWhile::get_output_sequence_port_text(int p_port) const { - - if (p_port == 0) + if (p_port == 0) { return "repeat"; - else + } else { return "exit"; + } } PropertyInfo VisualScriptWhile::get_input_value_port_info(int p_idx) const { - PropertyInfo pinfo; pinfo.name = "cond"; pinfo.type = Variant::BOOL; return pinfo; } + PropertyInfo VisualScriptWhile::get_output_value_port_info(int p_idx) const { return PropertyInfo(); } String VisualScriptWhile::get_caption() const { - return "While"; } String VisualScriptWhile::get_text() const { - return "while (cond): "; } @@ -324,23 +301,23 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - bool keep_going = p_inputs[0]->operator bool(); - if (keep_going) + if (keep_going) { return 0 | STEP_FLAG_PUSH_STACK_BIT; - else + } else { return 1; + } } }; VisualScriptNodeInstance *VisualScriptWhile::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceWhile *instance = memnew(VisualScriptNodeInstanceWhile); instance->node = this; instance->instance = p_instance; return instance; } + VisualScriptWhile::VisualScriptWhile() { } @@ -349,52 +326,48 @@ VisualScriptWhile::VisualScriptWhile() { ////////////////////////////////////////// int VisualScriptIterator::get_output_sequence_port_count() const { - return 2; } bool VisualScriptIterator::has_input_sequence_port() const { - return true; } int VisualScriptIterator::get_input_value_port_count() const { - return 1; } -int VisualScriptIterator::get_output_value_port_count() const { +int VisualScriptIterator::get_output_value_port_count() const { return 1; } String VisualScriptIterator::get_output_sequence_port_text(int p_port) const { - - if (p_port == 0) + if (p_port == 0) { return "each"; - else + } else { return "exit"; + } } PropertyInfo VisualScriptIterator::get_input_value_port_info(int p_idx) const { - PropertyInfo pinfo; pinfo.name = "input"; pinfo.type = Variant::NIL; return pinfo; } + PropertyInfo VisualScriptIterator::get_output_value_port_info(int p_idx) const { PropertyInfo pinfo; pinfo.name = "elem"; pinfo.type = Variant::NIL; return pinfo; } -String VisualScriptIterator::get_caption() const { +String VisualScriptIterator::get_caption() const { return "Iterator"; } String VisualScriptIterator::get_text() const { - return "for (elem) in (input): "; } @@ -411,7 +384,6 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (p_start_mode == START_MODE_BEGIN_SEQUENCE) { p_working_mem[0] = *p_inputs[0]; bool valid; @@ -423,8 +395,9 @@ public: return 0; } - if (!can_iter) + if (!can_iter) { return 1; //nothing to iterate + } *p_outputs[0] = p_working_mem[0].iter_get(p_working_mem[1], valid); @@ -445,8 +418,9 @@ public: return 0; } - if (!can_iter) + if (!can_iter) { return 1; //nothing to iterate + } *p_outputs[0] = p_working_mem[0].iter_get(p_working_mem[1], valid); @@ -462,7 +436,6 @@ public: }; VisualScriptNodeInstance *VisualScriptIterator::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceIterator *instance = memnew(VisualScriptNodeInstanceIterator); instance->node = this; instance->instance = p_instance; @@ -477,62 +450,56 @@ VisualScriptIterator::VisualScriptIterator() { ////////////////////////////////////////// int VisualScriptSequence::get_output_sequence_port_count() const { - return steps; } bool VisualScriptSequence::has_input_sequence_port() const { - return true; } int VisualScriptSequence::get_input_value_port_count() const { - return 0; } -int VisualScriptSequence::get_output_value_port_count() const { +int VisualScriptSequence::get_output_value_port_count() const { return 1; } String VisualScriptSequence::get_output_sequence_port_text(int p_port) const { - return itos(p_port + 1); } PropertyInfo VisualScriptSequence::get_input_value_port_info(int p_idx) const { return PropertyInfo(); } + PropertyInfo VisualScriptSequence::get_output_value_port_info(int p_idx) const { return PropertyInfo(Variant::INT, "current"); } -String VisualScriptSequence::get_caption() const { +String VisualScriptSequence::get_caption() const { return "Sequence"; } String VisualScriptSequence::get_text() const { - return "in order: "; } void VisualScriptSequence::set_steps(int p_steps) { - ERR_FAIL_COND(p_steps < 1); - if (steps == p_steps) + if (steps == p_steps) { return; + } steps = p_steps; ports_changed_notify(); } int VisualScriptSequence::get_steps() const { - return steps; } void VisualScriptSequence::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_steps", "steps"), &VisualScriptSequence::set_steps); ClassDB::bind_method(D_METHOD("get_steps"), &VisualScriptSequence::get_steps); @@ -550,9 +517,7 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (p_start_mode == START_MODE_BEGIN_SEQUENCE) { - p_working_mem[0] = 0; } @@ -560,9 +525,9 @@ public: *p_outputs[0] = step; - if (step + 1 == steps) + if (step + 1 == steps) { return step; - else { + } else { p_working_mem[0] = step + 1; return step | STEP_FLAG_PUSH_STACK_BIT; } @@ -570,15 +535,14 @@ public: }; VisualScriptNodeInstance *VisualScriptSequence::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceSequence *instance = memnew(VisualScriptNodeInstanceSequence); instance->node = this; instance->instance = p_instance; instance->steps = steps; return instance; } -VisualScriptSequence::VisualScriptSequence() { +VisualScriptSequence::VisualScriptSequence() { steps = 1; } @@ -587,52 +551,46 @@ VisualScriptSequence::VisualScriptSequence() { ////////////////////////////////////////// int VisualScriptSwitch::get_output_sequence_port_count() const { - return case_values.size() + 1; } bool VisualScriptSwitch::has_input_sequence_port() const { - return true; } int VisualScriptSwitch::get_input_value_port_count() const { - return case_values.size() + 1; } -int VisualScriptSwitch::get_output_value_port_count() const { +int VisualScriptSwitch::get_output_value_port_count() const { return 0; } String VisualScriptSwitch::get_output_sequence_port_text(int p_port) const { - - if (p_port == case_values.size()) + if (p_port == case_values.size()) { return "done"; + } return String(); } PropertyInfo VisualScriptSwitch::get_input_value_port_info(int p_idx) const { - if (p_idx < case_values.size()) { return PropertyInfo(case_values[p_idx].type, " ="); - } else + } else { return PropertyInfo(Variant::NIL, "input"); + } } PropertyInfo VisualScriptSwitch::get_output_value_port_info(int p_idx) const { - return PropertyInfo(); } String VisualScriptSwitch::get_caption() const { - return "Switch"; } String VisualScriptSwitch::get_text() const { - return "'input' is:"; } @@ -646,13 +604,11 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (p_start_mode == START_MODE_CONTINUE_SEQUENCE) { return case_count; //exit } for (int i = 0; i < case_count; i++) { - if (*p_inputs[i] == *p_inputs[case_count]) { return i | STEP_FLAG_PUSH_STACK_BIT; } @@ -663,7 +619,6 @@ public: }; VisualScriptNodeInstance *VisualScriptSwitch::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceSwitch *instance = memnew(VisualScriptNodeInstanceSwitch); instance->instance = p_instance; instance->case_count = case_values.size(); @@ -671,7 +626,6 @@ VisualScriptNodeInstance *VisualScriptSwitch::instance(VisualScriptInstance *p_i } bool VisualScriptSwitch::_set(const StringName &p_name, const Variant &p_value) { - if (String(p_name) == "case_count") { case_values.resize(p_value); _change_notify(); @@ -680,7 +634,6 @@ bool VisualScriptSwitch::_set(const StringName &p_name, const Variant &p_value) } if (String(p_name).begins_with("case/")) { - int idx = String(p_name).get_slice("/", 1).to_int(); ERR_FAIL_INDEX_V(idx, case_values.size(), false); @@ -695,14 +648,12 @@ bool VisualScriptSwitch::_set(const StringName &p_name, const Variant &p_value) } bool VisualScriptSwitch::_get(const StringName &p_name, Variant &r_ret) const { - if (String(p_name) == "case_count") { r_ret = case_values.size(); return true; } if (String(p_name).begins_with("case/")) { - int idx = String(p_name).get_slice("/", 1).to_int(); ERR_FAIL_INDEX_V(idx, case_values.size(), false); @@ -712,8 +663,8 @@ bool VisualScriptSwitch::_get(const StringName &p_name, Variant &r_ret) const { return false; } -void VisualScriptSwitch::_get_property_list(List<PropertyInfo> *p_list) const { +void VisualScriptSwitch::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, "case_count", PROPERTY_HINT_RANGE, "0,128")); String argt = "Any"; @@ -737,56 +688,49 @@ VisualScriptSwitch::VisualScriptSwitch() { ////////////////////////////////////////// int VisualScriptTypeCast::get_output_sequence_port_count() const { - return 2; } bool VisualScriptTypeCast::has_input_sequence_port() const { - return true; } int VisualScriptTypeCast::get_input_value_port_count() const { - return 1; } -int VisualScriptTypeCast::get_output_value_port_count() const { +int VisualScriptTypeCast::get_output_value_port_count() const { return 1; } String VisualScriptTypeCast::get_output_sequence_port_text(int p_port) const { - return p_port == 0 ? "yes" : "no"; } PropertyInfo VisualScriptTypeCast::get_input_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "instance"); } PropertyInfo VisualScriptTypeCast::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "", PROPERTY_HINT_TYPE_STRING, get_base_type()); } String VisualScriptTypeCast::get_caption() const { - return "Type Cast"; } String VisualScriptTypeCast::get_text() const { - - if (script != String()) + if (script != String()) { return "Is " + script.get_file() + "?"; - else + } else { return "Is " + base_type + "?"; + } } void VisualScriptTypeCast::set_base_type(const StringName &p_type) { - - if (base_type == p_type) + if (base_type == p_type) { return; + } base_type = p_type; _change_notify(); @@ -794,26 +738,24 @@ void VisualScriptTypeCast::set_base_type(const StringName &p_type) { } StringName VisualScriptTypeCast::get_base_type() const { - return base_type; } void VisualScriptTypeCast::set_base_script(const String &p_path) { - - if (script == p_path) + if (script == p_path) { return; + } script = p_path; _change_notify(); ports_changed_notify(); } -String VisualScriptTypeCast::get_base_script() const { +String VisualScriptTypeCast::get_base_script() const { return script; } VisualScriptTypeCast::TypeGuess VisualScriptTypeCast::guess_output_type(TypeGuess *p_inputs, int p_output) const { - TypeGuess tg; tg.type = Variant::OBJECT; if (script != String()) { @@ -837,7 +779,6 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - Object *obj = *p_inputs[0]; *p_outputs[0] = Variant(); @@ -849,7 +790,6 @@ public: } if (script != String()) { - Ref<Script> obj_script = obj->get_script(); if (!obj_script.is_valid()) { return 1; //well, definitely not the script because object we got has no script. @@ -867,7 +807,6 @@ public: } while (obj_script.is_valid()) { - if (cast_script == obj_script) { *p_outputs[0] = *p_inputs[0]; //copy return 0; // it is the script, yey @@ -882,13 +821,13 @@ public: if (ClassDB::is_parent_class(obj->get_class_name(), base_type)) { *p_outputs[0] = *p_inputs[0]; //copy return 0; - } else + } else { return 1; + } } }; VisualScriptNodeInstance *VisualScriptTypeCast::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceTypeCast *instance = memnew(VisualScriptNodeInstanceTypeCast); instance->instance = p_instance; instance->base_type = base_type; @@ -897,7 +836,6 @@ VisualScriptNodeInstance *VisualScriptTypeCast::instance(VisualScriptInstance *p } void VisualScriptTypeCast::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_base_type", "type"), &VisualScriptTypeCast::set_base_type); ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptTypeCast::get_base_type); @@ -911,8 +849,9 @@ void VisualScriptTypeCast::_bind_methods() { String script_ext_hint; for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) { - if (script_ext_hint != String()) + if (script_ext_hint != String()) { script_ext_hint += ","; + } script_ext_hint += "*." + E->get(); } @@ -921,12 +860,10 @@ void VisualScriptTypeCast::_bind_methods() { } VisualScriptTypeCast::VisualScriptTypeCast() { - base_type = "Object"; } void register_visual_script_flow_control_nodes() { - VisualScriptLanguage::singleton->add_register_func("flow_control/return", create_return_node<false>); VisualScriptLanguage::singleton->add_register_func("flow_control/return_with_value", create_return_node<true>); VisualScriptLanguage::singleton->add_register_func("flow_control/condition", create_node_generic<VisualScriptCondition>); @@ -934,6 +871,6 @@ void register_visual_script_flow_control_nodes() { VisualScriptLanguage::singleton->add_register_func("flow_control/iterator", create_node_generic<VisualScriptIterator>); VisualScriptLanguage::singleton->add_register_func("flow_control/sequence", create_node_generic<VisualScriptSequence>); VisualScriptLanguage::singleton->add_register_func("flow_control/switch", create_node_generic<VisualScriptSwitch>); - //VisualScriptLanguage::singleton->add_register_func("flow_control/input_filter", create_node_generic<VisualScriptInputFilter>); + //VisualScriptLanguage::singleton->add_register_func("flow_control/input", create_node_generic<VisualScriptInputFilter>); VisualScriptLanguage::singleton->add_register_func("flow_control/type_cast", create_node_generic<VisualScriptTypeCast>); } diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h index 8597d051db..45b56b3073 100644 --- a/modules/visual_script/visual_script_flow_control.h +++ b/modules/visual_script/visual_script_flow_control.h @@ -34,7 +34,6 @@ #include "visual_script.h" class VisualScriptReturn : public VisualScriptNode { - GDCLASS(VisualScriptReturn, VisualScriptNode); Variant::Type type; @@ -71,7 +70,6 @@ public: }; class VisualScriptCondition : public VisualScriptNode { - GDCLASS(VisualScriptCondition, VisualScriptNode); protected: @@ -99,7 +97,6 @@ public: }; class VisualScriptWhile : public VisualScriptNode { - GDCLASS(VisualScriptWhile, VisualScriptNode); protected: @@ -127,7 +124,6 @@ public: }; class VisualScriptIterator : public VisualScriptNode { - GDCLASS(VisualScriptIterator, VisualScriptNode); protected: @@ -155,7 +151,6 @@ public: }; class VisualScriptSequence : public VisualScriptNode { - GDCLASS(VisualScriptSequence, VisualScriptNode); int steps; @@ -188,7 +183,6 @@ public: }; class VisualScriptSwitch : public VisualScriptNode { - GDCLASS(VisualScriptSwitch, VisualScriptNode); struct Case { @@ -230,7 +224,6 @@ public: }; class VisualScriptTypeCast : public VisualScriptNode { - GDCLASS(VisualScriptTypeCast, VisualScriptNode); StringName base_type; diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 011432ef39..f13377f3c8 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -42,95 +42,98 @@ ////////////////////////////////////////// int VisualScriptFunctionCall::get_output_sequence_port_count() const { - - if ((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function))) + if ((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function))) { return 0; - else + } else { return 1; + } } bool VisualScriptFunctionCall::has_input_sequence_port() const { - return !((method_cache.flags & METHOD_FLAG_CONST && call_mode != CALL_MODE_INSTANCE) || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function))); } #ifdef TOOLS_ENABLED static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const Ref<Script> &script) { - - if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene) - return NULL; + if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene) { + return nullptr; + } Ref<Script> scr = p_current_node->get_script(); - if (scr.is_valid() && scr == script) + if (scr.is_valid() && scr == script) { return p_current_node; + } for (int i = 0; i < p_current_node->get_child_count(); i++) { Node *n = _find_script_node(p_edited_scene, p_current_node->get_child(i), script); - if (n) + if (n) { return n; + } } - return NULL; + return nullptr; } #endif Node *VisualScriptFunctionCall::_get_base_node() const { - #ifdef TOOLS_ENABLED Ref<Script> script = get_visual_script(); - if (!script.is_valid()) - return NULL; + if (!script.is_valid()) { + return nullptr; + } MainLoop *main_loop = OS::get_singleton()->get_main_loop(); SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop); - if (!scene_tree) - return NULL; + if (!scene_tree) { + return nullptr; + } Node *edited_scene = scene_tree->get_edited_scene_root(); - if (!edited_scene) - return NULL; + if (!edited_scene) { + return nullptr; + } Node *script_node = _find_script_node(edited_scene, edited_scene, script); - if (!script_node) - return NULL; + if (!script_node) { + return nullptr; + } - if (!script_node->has_node(base_path)) - return NULL; + if (!script_node->has_node(base_path)) { + return nullptr; + } Node *path_to = script_node->get_node(base_path); return path_to; #else - return NULL; + return nullptr; #endif } StringName VisualScriptFunctionCall::_get_base_type() const { - - if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) + if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) { return get_visual_script()->get_instance_base_type(); - else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { + } else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { Node *path = _get_base_node(); - if (path) + if (path) { return path->get_class(); + } } return base_type; } int VisualScriptFunctionCall::get_input_value_port_count() const { - if (call_mode == CALL_MODE_BASIC_TYPE) { Vector<Variant::Type> types = Variant::get_method_argument_types(basic_type, function); return types.size() + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) + 1; } else { - MethodBind *mb = ClassDB::get_method(_get_base_type(), function); if (mb) { int defaulted_args = mb->get_argument_count() < use_default_args ? mb->get_argument_count() : use_default_args; @@ -141,10 +144,9 @@ int VisualScriptFunctionCall::get_input_value_port_count() const { return method_cache.arguments.size() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - defaulted_args; } } -int VisualScriptFunctionCall::get_output_value_port_count() const { +int VisualScriptFunctionCall::get_output_value_port_count() const { if (call_mode == CALL_MODE_BASIC_TYPE) { - bool returns = false; Variant::get_method_return_type(basic_type, function, &returns); return returns ? 1 : 0; @@ -154,8 +156,9 @@ int VisualScriptFunctionCall::get_output_value_port_count() const { MethodBind *mb = ClassDB::get_method(_get_base_type(), function); if (mb) { ret = mb->has_return() ? 1 : 0; - } else + } else { ret = 1; //it is assumed that script always returns something + } if (call_mode == CALL_MODE_INSTANCE) { ret++; @@ -166,12 +169,10 @@ int VisualScriptFunctionCall::get_output_value_port_count() const { } String VisualScriptFunctionCall::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) const { - if (call_mode == CALL_MODE_INSTANCE || call_mode == CALL_MODE_BASIC_TYPE) { if (p_idx == 0) { PropertyInfo pi; @@ -184,7 +185,6 @@ PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) cons } if (rpc_call_mode >= RPC_RELIABLE_TO_ID) { - if (p_idx == 0) { return PropertyInfo(Variant::INT, "peer_id"); } else { @@ -195,13 +195,11 @@ PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) cons #ifdef DEBUG_METHODS_ENABLED if (call_mode == CALL_MODE_BASIC_TYPE) { - Vector<StringName> names = Variant::get_method_argument_names(basic_type, function); Vector<Variant::Type> types = Variant::get_method_argument_types(basic_type, function); return PropertyInfo(types[p_idx], names[p_idx]); } else { - MethodBind *mb = ClassDB::get_method(_get_base_type(), function); if (mb) { return mb->get_argument_info(p_idx); @@ -219,14 +217,11 @@ PropertyInfo VisualScriptFunctionCall::get_input_value_port_info(int p_idx) cons } PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) const { - #ifdef DEBUG_METHODS_ENABLED if (call_mode == CALL_MODE_BASIC_TYPE) { - return PropertyInfo(Variant::get_method_return_type(basic_type, function), ""); } else { - if (call_mode == CALL_MODE_INSTANCE) { if (p_idx == 0) { return PropertyInfo(Variant::OBJECT, "pass", PROPERTY_HINT_TYPE_STRING, get_base_type()); @@ -260,20 +255,21 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con } String VisualScriptFunctionCall::get_caption() const { - if (call_mode == CALL_MODE_SELF) + if (call_mode == CALL_MODE_SELF) { return " " + String(function) + "()"; - if (call_mode == CALL_MODE_SINGLETON) + } + if (call_mode == CALL_MODE_SINGLETON) { return String(singleton) + ":" + String(function) + "()"; - else if (call_mode == CALL_MODE_BASIC_TYPE) + } else if (call_mode == CALL_MODE_BASIC_TYPE) { return Variant::get_type_name(basic_type) + "." + String(function) + "()"; - else if (call_mode == CALL_MODE_NODE_PATH) + } else if (call_mode == CALL_MODE_NODE_PATH) { return " [" + String(base_path.simplified()) + "]." + String(function) + "()"; - else + } else { return " " + base_type + "." + String(function) + "()"; + } } String VisualScriptFunctionCall::get_text() const { - if (rpc_call_mode) { return "RPC"; } @@ -281,9 +277,9 @@ String VisualScriptFunctionCall::get_text() const { } void VisualScriptFunctionCall::set_basic_type(Variant::Type p_type) { - - if (basic_type == p_type) + if (basic_type == p_type) { return; + } basic_type = p_type; _change_notify(); @@ -291,14 +287,13 @@ void VisualScriptFunctionCall::set_basic_type(Variant::Type p_type) { } Variant::Type VisualScriptFunctionCall::get_basic_type() const { - return basic_type; } void VisualScriptFunctionCall::set_base_type(const StringName &p_type) { - - if (base_type == p_type) + if (base_type == p_type) { return; + } base_type = p_type; _change_notify(); @@ -306,14 +301,13 @@ void VisualScriptFunctionCall::set_base_type(const StringName &p_type) { } StringName VisualScriptFunctionCall::get_base_type() const { - return base_type; } void VisualScriptFunctionCall::set_base_script(const String &p_path) { - - if (base_script == p_path) + if (base_script == p_path) { return; + } base_script = p_path; _change_notify(); @@ -321,14 +315,13 @@ void VisualScriptFunctionCall::set_base_script(const String &p_path) { } String VisualScriptFunctionCall::get_base_script() const { - return base_script; } void VisualScriptFunctionCall::set_singleton(const StringName &p_type) { - - if (singleton == p_type) + if (singleton == p_type) { return; + } singleton = p_type; Object *obj = Engine::get_singleton()->get_singleton_object(singleton); @@ -341,7 +334,6 @@ void VisualScriptFunctionCall::set_singleton(const StringName &p_type) { } StringName VisualScriptFunctionCall::get_singleton() const { - return singleton; } @@ -350,7 +342,6 @@ void VisualScriptFunctionCall::_update_method_cache() { Ref<Script> script; if (call_mode == CALL_MODE_NODE_PATH) { - Node *node = _get_base_node(); if (node) { type = node->get_class(); @@ -358,7 +349,6 @@ void VisualScriptFunctionCall::_update_method_cache() { script = node->get_script(); } } else if (call_mode == CALL_MODE_SELF) { - if (get_visual_script().is_valid()) { type = get_visual_script()->get_instance_base_type(); base_type = type; //cache, too @@ -366,7 +356,6 @@ void VisualScriptFunctionCall::_update_method_cache() { } } else if (call_mode == CALL_MODE_SINGLETON) { - Object *obj = Engine::get_singleton()->get_singleton_object(singleton); if (obj) { type = obj->get_class(); @@ -374,17 +363,13 @@ void VisualScriptFunctionCall::_update_method_cache() { } } else if (call_mode == CALL_MODE_INSTANCE) { - type = base_type; if (base_script != String()) { - if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { - ScriptServer::edit_request_func(base_script); //make sure it's loaded } if (ResourceCache::has(base_script)) { - script = Ref<Resource>(ResourceCache::get(base_script)); } else { return; @@ -421,16 +406,15 @@ void VisualScriptFunctionCall::_update_method_cache() { } } } else if (script.is_valid() && script->has_method(function)) { - method_cache = script->get_method_info(function); use_default_args = method_cache.default_arguments.size(); } } void VisualScriptFunctionCall::set_function(const StringName &p_type) { - - if (function == p_type) + if (function == p_type) { return; + } function = p_type; @@ -445,15 +429,15 @@ void VisualScriptFunctionCall::set_function(const StringName &p_type) { _change_notify(); ports_changed_notify(); } -StringName VisualScriptFunctionCall::get_function() const { +StringName VisualScriptFunctionCall::get_function() const { return function; } void VisualScriptFunctionCall::set_base_path(const NodePath &p_type) { - - if (base_path == p_type) + if (base_path == p_type) { return; + } base_path = p_type; _change_notify(); @@ -461,59 +445,54 @@ void VisualScriptFunctionCall::set_base_path(const NodePath &p_type) { } NodePath VisualScriptFunctionCall::get_base_path() const { - return base_path; } void VisualScriptFunctionCall::set_call_mode(CallMode p_mode) { - - if (call_mode == p_mode) + if (call_mode == p_mode) { return; + } call_mode = p_mode; _change_notify(); ports_changed_notify(); } -VisualScriptFunctionCall::CallMode VisualScriptFunctionCall::get_call_mode() const { +VisualScriptFunctionCall::CallMode VisualScriptFunctionCall::get_call_mode() const { return call_mode; } void VisualScriptFunctionCall::set_use_default_args(int p_amount) { - - if (use_default_args == p_amount) + if (use_default_args == p_amount) { return; + } use_default_args = p_amount; ports_changed_notify(); } void VisualScriptFunctionCall::set_rpc_call_mode(VisualScriptFunctionCall::RPCCallMode p_mode) { - - if (rpc_call_mode == p_mode) + if (rpc_call_mode == p_mode) { return; + } rpc_call_mode = p_mode; ports_changed_notify(); _change_notify(); } VisualScriptFunctionCall::RPCCallMode VisualScriptFunctionCall::get_rpc_call_mode() const { - return rpc_call_mode; } int VisualScriptFunctionCall::get_use_default_args() const { - return use_default_args; } void VisualScriptFunctionCall::set_validate(bool p_amount) { - validate = p_amount; } bool VisualScriptFunctionCall::get_validate() const { - return validate; } @@ -523,12 +502,10 @@ void VisualScriptFunctionCall::_set_argument_cache(const Dictionary &p_cache) { } Dictionary VisualScriptFunctionCall::_get_argument_cache() const { - return method_cache; } void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const { - if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; @@ -556,8 +533,9 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const property.hint = PROPERTY_HINT_ENUM; String sl; for (List<Engine::Singleton>::Element *E = names.front(); E; E = E->next()) { - if (sl != String()) + if (sl != String()) { sl += ","; + } sl += E->get().name; } property.hint_string = sl; @@ -568,7 +546,6 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const if (call_mode != CALL_MODE_NODE_PATH) { property.usage = 0; } else { - Node *bnode = _get_base_node(); if (bnode) { property.hint_string = bnode->get_path(); //convert to loong string @@ -577,9 +554,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } if (property.name == "function") { - if (call_mode == CALL_MODE_BASIC_TYPE) { - property.hint = PROPERTY_HINT_METHOD_OF_VARIANT_TYPE; property.hint_string = Variant::get_type_name(basic_type); @@ -587,13 +562,11 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const property.hint = PROPERTY_HINT_METHOD_OF_SCRIPT; property.hint_string = itos(get_visual_script()->get_instance_id()); } else if (call_mode == CALL_MODE_SINGLETON) { - Object *obj = Engine::get_singleton()->get_singleton_object(singleton); if (obj) { property.hint = PROPERTY_HINT_METHOD_OF_INSTANCE; property.hint_string = itos(obj->get_instance_id()); } else { - property.hint = PROPERTY_HINT_METHOD_OF_BASE_TYPE; property.hint_string = base_type; //should be cached } @@ -603,15 +576,12 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const if (base_script != String()) { if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { - ScriptServer::edit_request_func(base_script); //make sure it's loaded } if (ResourceCache::has(base_script)) { - Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script)); if (script.is_valid()) { - property.hint = PROPERTY_HINT_METHOD_OF_SCRIPT; property.hint_string = itos(script->get_instance_id()); } @@ -631,18 +601,15 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } if (property.name == "use_default_args") { - property.hint = PROPERTY_HINT_RANGE; int mc = 0; if (call_mode == CALL_MODE_BASIC_TYPE) { - mc = Variant::get_method_default_arguments(basic_type, function).size(); } else { MethodBind *mb = ClassDB::get_method(_get_base_type(), function); if (mb) { - mc = mb->get_default_argument_count(); } } @@ -650,7 +617,6 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const if (mc == 0) { property.usage = 0; //do not show } else { - property.hint_string = "0," + itos(mc) + ",1"; } } @@ -663,7 +629,6 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } void VisualScriptFunctionCall::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &VisualScriptFunctionCall::set_base_type); ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptFunctionCall::get_base_type); @@ -699,8 +664,9 @@ void VisualScriptFunctionCall::_bind_methods() { String bt; for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (i > 0) + if (i > 0) { bt += ","; + } bt += Variant::get_type_name(Variant::Type(i)); } @@ -712,8 +678,9 @@ void VisualScriptFunctionCall::_bind_methods() { String script_ext_hint; for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) { - if (script_ext_hint != String()) + if (script_ext_hint != String()) { script_ext_hint += ","; + } script_ext_hint += "*." + E->get(); } @@ -761,13 +728,14 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } _FORCE_INLINE_ bool call_rpc(Object *p_base, const Variant **p_args, int p_argcount) { - - if (!p_base) + if (!p_base) { return false; + } Node *node = Object::cast_to<Node>(p_base); - if (!node) + if (!node) { return false; + } int to_id = 0; bool reliable = true; @@ -789,11 +757,8 @@ public: } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - switch (call_mode) { - case VisualScriptFunctionCall::CALL_MODE_SELF: { - Object *object = instance->get_owner_ptr(); if (rpc_mode) { @@ -805,7 +770,6 @@ public: } } break; case VisualScriptFunctionCall::CALL_MODE_NODE_PATH: { - Node *node = Object::cast_to<Node>(instance->get_owner_ptr()); if (!node) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -831,7 +795,6 @@ public: } break; case VisualScriptFunctionCall::CALL_MODE_INSTANCE: case VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE: { - Variant v = *p_inputs[0]; if (rpc_mode) { @@ -863,7 +826,6 @@ public: } break; case VisualScriptFunctionCall::CALL_MODE_SINGLETON: { - Object *object = Engine::get_singleton()->get_singleton_object(singleton); if (!object) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -882,7 +844,6 @@ public: } if (!validate) { - //ignore call errors if validation is disabled r_error.error = Callable::CallError::CALL_OK; r_error_str = String(); @@ -893,7 +854,6 @@ public: }; VisualScriptNodeInstance *VisualScriptFunctionCall::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceFunctionCall *instance = memnew(VisualScriptNodeInstanceFunctionCall); instance->node = this; instance->instance = p_instance; @@ -909,7 +869,6 @@ VisualScriptNodeInstance *VisualScriptFunctionCall::instance(VisualScriptInstanc } VisualScriptFunctionCall::TypeGuess VisualScriptFunctionCall::guess_output_type(TypeGuess *p_inputs, int p_output) const { - if (p_output == 0 && call_mode == CALL_MODE_INSTANCE) { return p_inputs[0]; } @@ -918,7 +877,6 @@ VisualScriptFunctionCall::TypeGuess VisualScriptFunctionCall::guess_output_type( } VisualScriptFunctionCall::VisualScriptFunctionCall() { - validate = true; call_mode = CALL_MODE_SELF; basic_type = Variant::NIL; @@ -929,7 +887,6 @@ VisualScriptFunctionCall::VisualScriptFunctionCall() { template <VisualScriptFunctionCall::CallMode cmode> static Ref<VisualScriptNode> create_function_call_node(const String &p_name) { - Ref<VisualScriptFunctionCall> node; node.instance(); node->set_call_mode(cmode); @@ -941,87 +898,85 @@ static Ref<VisualScriptNode> create_function_call_node(const String &p_name) { ////////////////////////////////////////// int VisualScriptPropertySet::get_output_sequence_port_count() const { - return call_mode != CALL_MODE_BASIC_TYPE ? 1 : 0; } bool VisualScriptPropertySet::has_input_sequence_port() const { - return call_mode != CALL_MODE_BASIC_TYPE; } Node *VisualScriptPropertySet::_get_base_node() const { - #ifdef TOOLS_ENABLED Ref<Script> script = get_visual_script(); - if (!script.is_valid()) - return NULL; + if (!script.is_valid()) { + return nullptr; + } MainLoop *main_loop = OS::get_singleton()->get_main_loop(); SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop); - if (!scene_tree) - return NULL; + if (!scene_tree) { + return nullptr; + } Node *edited_scene = scene_tree->get_edited_scene_root(); - if (!edited_scene) - return NULL; + if (!edited_scene) { + return nullptr; + } Node *script_node = _find_script_node(edited_scene, edited_scene, script); - if (!script_node) - return NULL; + if (!script_node) { + return nullptr; + } - if (!script_node->has_node(base_path)) - return NULL; + if (!script_node->has_node(base_path)) { + return nullptr; + } Node *path_to = script_node->get_node(base_path); return path_to; #else - return NULL; + return nullptr; #endif } StringName VisualScriptPropertySet::_get_base_type() const { - - if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) + if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) { return get_visual_script()->get_instance_base_type(); - else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { + } else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { Node *path = _get_base_node(); - if (path) + if (path) { return path->get_class(); + } } return base_type; } int VisualScriptPropertySet::get_input_value_port_count() const { - int pc = (call_mode == CALL_MODE_BASIC_TYPE || call_mode == CALL_MODE_INSTANCE) ? 2 : 1; return pc; } -int VisualScriptPropertySet::get_output_value_port_count() const { +int VisualScriptPropertySet::get_output_value_port_count() const { return (call_mode == CALL_MODE_BASIC_TYPE || call_mode == CALL_MODE_INSTANCE) ? 1 : 0; } String VisualScriptPropertySet::get_output_sequence_port_text(int p_port) const { - return String(); } void VisualScriptPropertySet::_adjust_input_index(PropertyInfo &pinfo) const { - if (index != StringName()) { - Variant v; Callable::CallError ce; - v = Variant::construct(pinfo.type, NULL, 0, ce); + v = Variant::construct(pinfo.type, nullptr, 0, ce); Variant i = v.get(index); pinfo.type = i.get_type(); } @@ -1065,7 +1020,6 @@ PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) cons } String VisualScriptPropertySet::get_caption() const { - static const char *opname[ASSIGN_OP_MAX] = { "Set", "Add", "Subtract", "Multiply", "Divide", "Mod", "ShiftLeft", "ShiftRight", "BitAnd", "BitOr", "BitXor" }; @@ -1079,7 +1033,6 @@ String VisualScriptPropertySet::get_caption() const { } String VisualScriptPropertySet::get_text() const { - if (call_mode == CALL_MODE_BASIC_TYPE) { return String("On ") + Variant::get_type_name(basic_type); } @@ -1096,22 +1049,21 @@ String VisualScriptPropertySet::get_text() const { void VisualScriptPropertySet::_update_base_type() { //cache it because this information may not be available on load if (call_mode == CALL_MODE_NODE_PATH) { - Node *node = _get_base_node(); if (node) { base_type = node->get_class(); } } else if (call_mode == CALL_MODE_SELF) { - if (get_visual_script().is_valid()) { base_type = get_visual_script()->get_instance_base_type(); } } } -void VisualScriptPropertySet::set_basic_type(Variant::Type p_type) { - if (basic_type == p_type) +void VisualScriptPropertySet::set_basic_type(Variant::Type p_type) { + if (basic_type == p_type) { return; + } basic_type = p_type; _change_notify(); @@ -1120,14 +1072,13 @@ void VisualScriptPropertySet::set_basic_type(Variant::Type p_type) { } Variant::Type VisualScriptPropertySet::get_basic_type() const { - return basic_type; } void VisualScriptPropertySet::set_base_type(const StringName &p_type) { - - if (base_type == p_type) + if (base_type == p_type) { return; + } base_type = p_type; _change_notify(); @@ -1135,14 +1086,13 @@ void VisualScriptPropertySet::set_base_type(const StringName &p_type) { } StringName VisualScriptPropertySet::get_base_type() const { - return base_type; } void VisualScriptPropertySet::set_base_script(const String &p_path) { - - if (base_script == p_path) + if (base_script == p_path) { return; + } base_script = p_path; _change_notify(); @@ -1150,45 +1100,40 @@ void VisualScriptPropertySet::set_base_script(const String &p_path) { } String VisualScriptPropertySet::get_base_script() const { - return base_script; } void VisualScriptPropertySet::_update_cache() { - - if (!Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop())) + if (!Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop())) { return; + } - if (!Engine::get_singleton()->is_editor_hint()) //only update cache if editor exists, it's pointless otherwise + if (!Engine::get_singleton()->is_editor_hint()) { //only update cache if editor exists, it's pointless otherwise return; + } if (call_mode == CALL_MODE_BASIC_TYPE) { - //not super efficient.. Variant v; Callable::CallError ce; - v = Variant::construct(basic_type, NULL, 0, ce); + v = Variant::construct(basic_type, nullptr, 0, ce); List<PropertyInfo> pinfo; v.get_property_list(&pinfo); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - if (E->get().name == property) { - type_cache = E->get(); } } } else { - StringName type; Ref<Script> script; - Node *node = NULL; + Node *node = nullptr; if (call_mode == CALL_MODE_NODE_PATH) { - node = _get_base_node(); if (node) { type = node->get_class(); @@ -1196,24 +1141,19 @@ void VisualScriptPropertySet::_update_cache() { script = node->get_script(); } } else if (call_mode == CALL_MODE_SELF) { - if (get_visual_script().is_valid()) { type = get_visual_script()->get_instance_base_type(); base_type = type; //cache, too script = get_visual_script(); } } else if (call_mode == CALL_MODE_INSTANCE) { - type = base_type; if (base_script != String()) { - if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { - ScriptServer::edit_request_func(base_script); //make sure it's loaded } if (ResourceCache::has(base_script)) { - script = Ref<Resource>(ResourceCache::get(base_script)); } else { return; @@ -1224,19 +1164,16 @@ void VisualScriptPropertySet::_update_cache() { List<PropertyInfo> pinfo; if (node) { - node->get_property_list(&pinfo); } else { ClassDB::get_property_list(type, &pinfo); } if (script.is_valid()) { - script->get_script_property_list(&pinfo); } for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - if (E->get().name == property) { type_cache = E->get(); return; @@ -1246,9 +1183,9 @@ void VisualScriptPropertySet::_update_cache() { } void VisualScriptPropertySet::set_property(const StringName &p_type) { - - if (property == p_type) + if (property == p_type) { return; + } property = p_type; index = StringName(); @@ -1256,15 +1193,15 @@ void VisualScriptPropertySet::set_property(const StringName &p_type) { _change_notify(); ports_changed_notify(); } -StringName VisualScriptPropertySet::get_property() const { +StringName VisualScriptPropertySet::get_property() const { return property; } void VisualScriptPropertySet::set_base_path(const NodePath &p_type) { - - if (base_path == p_type) + if (base_path == p_type) { return; + } base_path = p_type; _update_base_type(); @@ -1273,22 +1210,21 @@ void VisualScriptPropertySet::set_base_path(const NodePath &p_type) { } NodePath VisualScriptPropertySet::get_base_path() const { - return base_path; } void VisualScriptPropertySet::set_call_mode(CallMode p_mode) { - - if (call_mode == p_mode) + if (call_mode == p_mode) { return; + } call_mode = p_mode; _update_base_type(); _change_notify(); ports_changed_notify(); } -VisualScriptPropertySet::CallMode VisualScriptPropertySet::get_call_mode() const { +VisualScriptPropertySet::CallMode VisualScriptPropertySet::get_call_mode() const { return call_mode; } @@ -1297,14 +1233,13 @@ void VisualScriptPropertySet::_set_type_cache(const Dictionary &p_type) { } Dictionary VisualScriptPropertySet::_get_type_cache() const { - return type_cache; } void VisualScriptPropertySet::set_index(const StringName &p_type) { - - if (index == p_type) + if (index == p_type) { return; + } index = p_type; _update_cache(); _change_notify(); @@ -1312,15 +1247,14 @@ void VisualScriptPropertySet::set_index(const StringName &p_type) { } StringName VisualScriptPropertySet::get_index() const { - return index; } void VisualScriptPropertySet::set_assign_op(AssignOp p_op) { - ERR_FAIL_INDEX(p_op, ASSIGN_OP_MAX); - if (assign_op == p_op) + if (assign_op == p_op) { return; + } assign_op = p_op; _update_cache(); @@ -1333,7 +1267,6 @@ VisualScriptPropertySet::AssignOp VisualScriptPropertySet::get_assign_op() const } void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { - if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; @@ -1356,7 +1289,6 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { if (call_mode != CALL_MODE_NODE_PATH) { property.usage = 0; } else { - Node *bnode = _get_base_node(); if (bnode) { property.hint_string = bnode->get_path(); //convert to loong string @@ -1365,9 +1297,7 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { } if (property.name == "property") { - if (call_mode == CALL_MODE_BASIC_TYPE) { - property.hint = PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE; property.hint_string = Variant::get_type_name(basic_type); @@ -1380,15 +1310,12 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { if (base_script != String()) { if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { - ScriptServer::edit_request_func(base_script); //make sure it's loaded } if (ResourceCache::has(base_script)) { - Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script)); if (script.is_valid()) { - property.hint = PROPERTY_HINT_PROPERTY_OF_SCRIPT; property.hint_string = itos(script->get_instance_id()); } @@ -1408,9 +1335,8 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { } if (property.name == "index") { - Callable::CallError ce; - Variant v = Variant::construct(type_cache.type, NULL, 0, ce); + Variant v = Variant::construct(type_cache.type, nullptr, 0, ce); List<PropertyInfo> plist; v.get_property_list(&plist); String options = ""; @@ -1421,13 +1347,13 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { property.hint = PROPERTY_HINT_ENUM; property.hint_string = options; property.type = Variant::STRING; - if (options == "") + if (options == "") { property.usage = 0; //hide if type has no usable index + } } } void VisualScriptPropertySet::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &VisualScriptPropertySet::set_base_type); ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptPropertySet::get_base_type); @@ -1457,8 +1383,9 @@ void VisualScriptPropertySet::_bind_methods() { String bt; for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (i > 0) + if (i > 0) { bt += ","; + } bt += Variant::get_type_name(Variant::Type(i)); } @@ -1470,8 +1397,9 @@ void VisualScriptPropertySet::_bind_methods() { String script_ext_hint; for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) { - if (script_ext_hint != String()) + if (script_ext_hint != String()) { script_ext_hint += ","; + } script_ext_hint += "*." + E->get(); } @@ -1520,11 +1448,9 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } _FORCE_INLINE_ void _process_get(Variant &source, const Variant &p_argument, bool &valid) { - if (index != StringName() && assign_op == VisualScriptPropertySet::ASSIGN_OP_NONE) { source.set_named(index, p_argument, &valid); } else { - Variant value; if (index != StringName()) { value = source.get_named(index, &valid); @@ -1579,11 +1505,8 @@ public: } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - switch (call_mode) { - case VisualScriptPropertySet::CALL_MODE_SELF: { - Object *object = instance->get_owner_ptr(); bool valid; @@ -1602,7 +1525,6 @@ public: } } break; case VisualScriptPropertySet::CALL_MODE_NODE_PATH: { - Node *node = Object::cast_to<Node>(instance->get_owner_ptr()); if (!node) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -1620,7 +1542,6 @@ public: bool valid; if (needs_get) { - Variant value = another->get(property, &valid); _process_get(value, *p_inputs[0], valid); another->set(property, value, &valid); @@ -1636,7 +1557,6 @@ public: } break; case VisualScriptPropertySet::CALL_MODE_INSTANCE: case VisualScriptPropertySet::CALL_MODE_BASIC_TYPE: { - Variant v = *p_inputs[0]; bool valid; @@ -1664,7 +1584,6 @@ public: }; VisualScriptNodeInstance *VisualScriptPropertySet::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstancePropertySet *instance = memnew(VisualScriptNodeInstancePropertySet); instance->node = this; instance->instance = p_instance; @@ -1678,15 +1597,14 @@ VisualScriptNodeInstance *VisualScriptPropertySet::instance(VisualScriptInstance } VisualScriptPropertySet::TypeGuess VisualScriptPropertySet::guess_output_type(TypeGuess *p_inputs, int p_output) const { - if (p_output == 0 && call_mode == CALL_MODE_INSTANCE) { return p_inputs[0]; } return VisualScriptNode::guess_output_type(p_inputs, p_output); } -VisualScriptPropertySet::VisualScriptPropertySet() { +VisualScriptPropertySet::VisualScriptPropertySet() { assign_op = ASSIGN_OP_NONE; call_mode = CALL_MODE_SELF; base_type = "Object"; @@ -1695,7 +1613,6 @@ VisualScriptPropertySet::VisualScriptPropertySet() { template <VisualScriptPropertySet::CallMode cmode> static Ref<VisualScriptNode> create_property_set_node(const String &p_name) { - Ref<VisualScriptPropertySet> node; node.instance(); node->set_call_mode(cmode); @@ -1707,94 +1624,93 @@ static Ref<VisualScriptNode> create_property_set_node(const String &p_name) { ////////////////////////////////////////// int VisualScriptPropertyGet::get_output_sequence_port_count() const { - return 0; // (call_mode==CALL_MODE_SELF || call_mode==CALL_MODE_NODE_PATH)?0:1; } bool VisualScriptPropertyGet::has_input_sequence_port() const { - return false; //(call_mode==CALL_MODE_SELF || call_mode==CALL_MODE_NODE_PATH)?false:true; } + void VisualScriptPropertyGet::_update_base_type() { //cache it because this information may not be available on load if (call_mode == CALL_MODE_NODE_PATH) { - Node *node = _get_base_node(); if (node) { base_type = node->get_class(); } } else if (call_mode == CALL_MODE_SELF) { - if (get_visual_script().is_valid()) { base_type = get_visual_script()->get_instance_base_type(); } } } -Node *VisualScriptPropertyGet::_get_base_node() const { +Node *VisualScriptPropertyGet::_get_base_node() const { #ifdef TOOLS_ENABLED Ref<Script> script = get_visual_script(); - if (!script.is_valid()) - return NULL; + if (!script.is_valid()) { + return nullptr; + } MainLoop *main_loop = OS::get_singleton()->get_main_loop(); SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop); - if (!scene_tree) - return NULL; + if (!scene_tree) { + return nullptr; + } Node *edited_scene = scene_tree->get_edited_scene_root(); - if (!edited_scene) - return NULL; + if (!edited_scene) { + return nullptr; + } Node *script_node = _find_script_node(edited_scene, edited_scene, script); - if (!script_node) - return NULL; + if (!script_node) { + return nullptr; + } - if (!script_node->has_node(base_path)) - return NULL; + if (!script_node->has_node(base_path)) { + return nullptr; + } Node *path_to = script_node->get_node(base_path); return path_to; #else - return NULL; + return nullptr; #endif } StringName VisualScriptPropertyGet::_get_base_type() const { - - if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) + if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) { return get_visual_script()->get_instance_base_type(); - else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { + } else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { Node *path = _get_base_node(); - if (path) + if (path) { return path->get_class(); + } } return base_type; } int VisualScriptPropertyGet::get_input_value_port_count() const { - return (call_mode == CALL_MODE_BASIC_TYPE || call_mode == CALL_MODE_INSTANCE) ? 1 : 0; } -int VisualScriptPropertyGet::get_output_value_port_count() const { +int VisualScriptPropertyGet::get_output_value_port_count() const { return 1; } String VisualScriptPropertyGet::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptPropertyGet::get_input_value_port_info(int p_idx) const { - if (call_mode == CALL_MODE_INSTANCE || call_mode == CALL_MODE_BASIC_TYPE) { if (p_idx == 0) { PropertyInfo pi; @@ -1819,12 +1735,10 @@ PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) cons } String VisualScriptPropertyGet::get_caption() const { - return String("Get ") + property; } String VisualScriptPropertyGet::get_text() const { - if (call_mode == CALL_MODE_BASIC_TYPE) { return String("On ") + Variant::get_type_name(basic_type); } @@ -1839,9 +1753,9 @@ String VisualScriptPropertyGet::get_text() const { } void VisualScriptPropertyGet::set_base_type(const StringName &p_type) { - - if (base_type == p_type) + if (base_type == p_type) { return; + } base_type = p_type; _change_notify(); @@ -1849,14 +1763,13 @@ void VisualScriptPropertyGet::set_base_type(const StringName &p_type) { } StringName VisualScriptPropertyGet::get_base_type() const { - return base_type; } void VisualScriptPropertyGet::set_base_script(const String &p_path) { - - if (base_script == p_path) + if (base_script == p_path) { return; + } base_script = p_path; _change_notify(); @@ -1864,40 +1777,33 @@ void VisualScriptPropertyGet::set_base_script(const String &p_path) { } String VisualScriptPropertyGet::get_base_script() const { - return base_script; } void VisualScriptPropertyGet::_update_cache() { - if (call_mode == CALL_MODE_BASIC_TYPE) { - //not super efficient.. Variant v; Callable::CallError ce; - v = Variant::construct(basic_type, NULL, 0, ce); + v = Variant::construct(basic_type, nullptr, 0, ce); List<PropertyInfo> pinfo; v.get_property_list(&pinfo); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - if (E->get().name == property) { - type_cache = E->get().type; return; } } } else { - StringName type; Ref<Script> script; - Node *node = NULL; + Node *node = nullptr; if (call_mode == CALL_MODE_NODE_PATH) { - node = _get_base_node(); if (node) { type = node->get_class(); @@ -1905,24 +1811,19 @@ void VisualScriptPropertyGet::_update_cache() { script = node->get_script(); } } else if (call_mode == CALL_MODE_SELF) { - if (get_visual_script().is_valid()) { type = get_visual_script()->get_instance_base_type(); base_type = type; //cache, too script = get_visual_script(); } } else if (call_mode == CALL_MODE_INSTANCE) { - type = base_type; if (base_script != String()) { - if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { - ScriptServer::edit_request_func(base_script); //make sure it's loaded } if (ResourceCache::has(base_script)) { - script = Ref<Resource>(ResourceCache::get(base_script)); } else { return; @@ -1942,7 +1843,6 @@ void VisualScriptPropertyGet::_update_cache() { } if (node) { - Variant prop = node->get(property, &valid); if (valid) { type_cache = prop.get_type(); @@ -1951,7 +1851,6 @@ void VisualScriptPropertyGet::_update_cache() { } if (script.is_valid()) { - type_ret = script->get_static_property_type(property, &valid); if (valid) { @@ -1963,9 +1862,9 @@ void VisualScriptPropertyGet::_update_cache() { } void VisualScriptPropertyGet::set_property(const StringName &p_type) { - - if (property == p_type) + if (property == p_type) { return; + } property = p_type; @@ -1973,15 +1872,15 @@ void VisualScriptPropertyGet::set_property(const StringName &p_type) { _change_notify(); ports_changed_notify(); } -StringName VisualScriptPropertyGet::get_property() const { +StringName VisualScriptPropertyGet::get_property() const { return property; } void VisualScriptPropertyGet::set_base_path(const NodePath &p_type) { - - if (base_path == p_type) + if (base_path == p_type) { return; + } base_path = p_type; _change_notify(); @@ -1990,29 +1889,28 @@ void VisualScriptPropertyGet::set_base_path(const NodePath &p_type) { } NodePath VisualScriptPropertyGet::get_base_path() const { - return base_path; } void VisualScriptPropertyGet::set_call_mode(CallMode p_mode) { - - if (call_mode == p_mode) + if (call_mode == p_mode) { return; + } call_mode = p_mode; _change_notify(); _update_base_type(); ports_changed_notify(); } -VisualScriptPropertyGet::CallMode VisualScriptPropertyGet::get_call_mode() const { +VisualScriptPropertyGet::CallMode VisualScriptPropertyGet::get_call_mode() const { return call_mode; } void VisualScriptPropertyGet::set_basic_type(Variant::Type p_type) { - - if (basic_type == p_type) + if (basic_type == p_type) { return; + } basic_type = p_type; _change_notify(); @@ -2020,7 +1918,6 @@ void VisualScriptPropertyGet::set_basic_type(Variant::Type p_type) { } Variant::Type VisualScriptPropertyGet::get_basic_type() const { - return basic_type; } @@ -2029,14 +1926,13 @@ void VisualScriptPropertyGet::_set_type_cache(Variant::Type p_type) { } Variant::Type VisualScriptPropertyGet::_get_type_cache() const { - return type_cache; } void VisualScriptPropertyGet::set_index(const StringName &p_type) { - - if (index == p_type) + if (index == p_type) { return; + } index = p_type; _update_cache(); _change_notify(); @@ -2044,12 +1940,10 @@ void VisualScriptPropertyGet::set_index(const StringName &p_type) { } StringName VisualScriptPropertyGet::get_index() const { - return index; } void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { - if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; @@ -2072,7 +1966,6 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { if (call_mode != CALL_MODE_NODE_PATH) { property.usage = 0; } else { - Node *bnode = _get_base_node(); if (bnode) { property.hint_string = bnode->get_path(); //convert to loong string @@ -2081,9 +1974,7 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { } if (property.name == "property") { - if (call_mode == CALL_MODE_BASIC_TYPE) { - property.hint = PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE; property.hint_string = Variant::get_type_name(basic_type); @@ -2096,15 +1987,12 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { if (base_script != String()) { if (!ResourceCache::has(base_script) && ScriptServer::edit_request_func) { - ScriptServer::edit_request_func(base_script); //make sure it's loaded } if (ResourceCache::has(base_script)) { - Ref<Script> script = Ref<Resource>(ResourceCache::get(base_script)); if (script.is_valid()) { - property.hint = PROPERTY_HINT_PROPERTY_OF_SCRIPT; property.hint_string = itos(script->get_instance_id()); } @@ -2123,9 +2011,8 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { } if (property.name == "index") { - Callable::CallError ce; - Variant v = Variant::construct(type_cache, NULL, 0, ce); + Variant v = Variant::construct(type_cache, nullptr, 0, ce); List<PropertyInfo> plist; v.get_property_list(&plist); String options = ""; @@ -2136,13 +2023,13 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { property.hint = PROPERTY_HINT_ENUM; property.hint_string = options; property.type = Variant::STRING; - if (options == "") + if (options == "") { property.usage = 0; //hide if type has no usable index + } } } void VisualScriptPropertyGet::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &VisualScriptPropertyGet::set_base_type); ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptPropertyGet::get_base_type); @@ -2169,8 +2056,9 @@ void VisualScriptPropertyGet::_bind_methods() { String bt; for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (i > 0) + if (i > 0) { bt += ","; + } bt += Variant::get_type_name(Variant::Type(i)); } @@ -2182,8 +2070,9 @@ void VisualScriptPropertyGet::_bind_methods() { String script_ext_hint; for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) { - if (script_ext_hint != String()) + if (script_ext_hint != String()) { script_ext_hint += ","; + } script_ext_hint += "." + E->get(); } @@ -2212,11 +2101,8 @@ public: VisualScriptInstance *instance; virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - switch (call_mode) { - case VisualScriptPropertyGet::CALL_MODE_SELF: { - Object *object = instance->get_owner_ptr(); bool valid; @@ -2234,7 +2120,6 @@ public: } } break; case VisualScriptPropertyGet::CALL_MODE_NODE_PATH: { - Node *node = Object::cast_to<Node>(instance->get_owner_ptr()); if (!node) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -2265,7 +2150,6 @@ public: } break; default: { - bool valid; Variant v = *p_inputs[0]; @@ -2286,7 +2170,6 @@ public: }; VisualScriptNodeInstance *VisualScriptPropertyGet::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstancePropertyGet *instance = memnew(VisualScriptNodeInstancePropertyGet); instance->node = this; instance->instance = p_instance; @@ -2299,7 +2182,6 @@ VisualScriptNodeInstance *VisualScriptPropertyGet::instance(VisualScriptInstance } VisualScriptPropertyGet::VisualScriptPropertyGet() { - call_mode = CALL_MODE_SELF; base_type = "Object"; basic_type = Variant::NIL; @@ -2308,7 +2190,6 @@ VisualScriptPropertyGet::VisualScriptPropertyGet() { template <VisualScriptPropertyGet::CallMode cmode> static Ref<VisualScriptNode> create_property_get_node(const String &p_name) { - Ref<VisualScriptPropertyGet> node; node.instance(); node->set_call_mode(cmode); @@ -2320,44 +2201,40 @@ static Ref<VisualScriptNode> create_property_get_node(const String &p_name) { ////////////////////////////////////////// int VisualScriptEmitSignal::get_output_sequence_port_count() const { - return 1; } bool VisualScriptEmitSignal::has_input_sequence_port() const { - return true; } int VisualScriptEmitSignal::get_input_value_port_count() const { - Ref<VisualScript> vs = get_visual_script(); if (vs.is_valid()) { - - if (!vs->has_custom_signal(name)) + if (!vs->has_custom_signal(name)) { return 0; + } return vs->custom_signal_get_argument_count(name); } return 0; } + int VisualScriptEmitSignal::get_output_value_port_count() const { return 0; } String VisualScriptEmitSignal::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptEmitSignal::get_input_value_port_info(int p_idx) const { - Ref<VisualScript> vs = get_visual_script(); if (vs.is_valid()) { - - if (!vs->has_custom_signal(name)) + if (!vs->has_custom_signal(name)) { return PropertyInfo(); + } return PropertyInfo(vs->custom_signal_get_argument_type(name, p_idx), vs->custom_signal_get_argument_name(name, p_idx)); } @@ -2366,32 +2243,29 @@ PropertyInfo VisualScriptEmitSignal::get_input_value_port_info(int p_idx) const } PropertyInfo VisualScriptEmitSignal::get_output_value_port_info(int p_idx) const { - return PropertyInfo(); } String VisualScriptEmitSignal::get_caption() const { - return "Emit " + String(name); } void VisualScriptEmitSignal::set_signal(const StringName &p_type) { - - if (name == p_type) + if (name == p_type) { return; + } name = p_type; _change_notify(); ports_changed_notify(); } -StringName VisualScriptEmitSignal::get_signal() const { +StringName VisualScriptEmitSignal::get_signal() const { return name; } void VisualScriptEmitSignal::_validate_property(PropertyInfo &property) const { - if (property.name == "signal") { property.hint = PROPERTY_HINT_ENUM; @@ -2399,15 +2273,14 @@ void VisualScriptEmitSignal::_validate_property(PropertyInfo &property) const { Ref<VisualScript> vs = get_visual_script(); if (vs.is_valid()) { - vs->get_custom_signal_list(&sigs); } String ml; for (List<StringName>::Element *E = sigs.front(); E; E = E->next()) { - - if (ml != String()) + if (ml != String()) { ml += ","; + } ml += E->get(); } @@ -2416,7 +2289,6 @@ void VisualScriptEmitSignal::_validate_property(PropertyInfo &property) const { } void VisualScriptEmitSignal::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_signal", "name"), &VisualScriptEmitSignal::set_signal); ClassDB::bind_method(D_METHOD("get_signal"), &VisualScriptEmitSignal::get_signal); @@ -2435,7 +2307,6 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - Object *obj = instance->get_owner_ptr(); obj->emit_signal(name, p_inputs, argcount); @@ -2445,7 +2316,6 @@ public: }; VisualScriptNodeInstance *VisualScriptEmitSignal::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceEmitSignal *instance = memnew(VisualScriptNodeInstanceEmitSignal); instance->node = this; instance->instance = p_instance; @@ -2458,7 +2328,6 @@ VisualScriptEmitSignal::VisualScriptEmitSignal() { } static Ref<VisualScriptNode> create_basic_type_call_node(const String &p_name) { - Vector<String> path = p_name.split("/"); ERR_FAIL_COND_V(path.size() < 4, Ref<VisualScriptNode>()); String base_type = path[2]; @@ -2470,7 +2339,6 @@ static Ref<VisualScriptNode> create_basic_type_call_node(const String &p_name) { Variant::Type type = Variant::VARIANT_MAX; for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (Variant::get_type_name(Variant::Type(i)) == base_type) { type = Variant::Type(i); break; @@ -2487,7 +2355,6 @@ static Ref<VisualScriptNode> create_basic_type_call_node(const String &p_name) { } void register_visual_script_func_nodes() { - VisualScriptLanguage::singleton->add_register_func("functions/call", create_node_generic<VisualScriptFunctionCall>); VisualScriptLanguage::singleton->add_register_func("functions/set", create_node_generic<VisualScriptPropertySet>); VisualScriptLanguage::singleton->add_register_func("functions/get", create_node_generic<VisualScriptPropertyGet>); @@ -2497,11 +2364,10 @@ void register_visual_script_func_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/emit_signal", create_node_generic<VisualScriptEmitSignal>); for (int i = 0; i < Variant::VARIANT_MAX; i++) { - Variant::Type t = Variant::Type(i); String type_name = Variant::get_type_name(t); Callable::CallError ce; - Variant vt = Variant::construct(t, NULL, 0, ce); + Variant vt = Variant::construct(t, nullptr, 0, ce); List<MethodInfo> ml; vt.get_method_list(&ml); diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 2dba0ae3c1..6921f0e820 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -34,7 +34,6 @@ #include "visual_script.h" class VisualScriptFunctionCall : public VisualScriptNode { - GDCLASS(VisualScriptFunctionCall, VisualScriptNode); public: @@ -137,7 +136,6 @@ VARIANT_ENUM_CAST(VisualScriptFunctionCall::CallMode); VARIANT_ENUM_CAST(VisualScriptFunctionCall::RPCCallMode); class VisualScriptPropertySet : public VisualScriptNode { - GDCLASS(VisualScriptPropertySet, VisualScriptNode); public: @@ -243,7 +241,6 @@ VARIANT_ENUM_CAST(VisualScriptPropertySet::CallMode); VARIANT_ENUM_CAST(VisualScriptPropertySet::AssignOp); class VisualScriptPropertyGet : public VisualScriptNode { - GDCLASS(VisualScriptPropertyGet, VisualScriptNode); public: @@ -325,7 +322,6 @@ public: VARIANT_ENUM_CAST(VisualScriptPropertyGet::CallMode); class VisualScriptEmitSignal : public VisualScriptNode { - GDCLASS(VisualScriptEmitSignal, VisualScriptNode); private: diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 41c1ea4ca2..87aa64211e 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "core/global_constants.h" -#include "core/os/input.h" +#include "core/input/input.h" #include "core/os/os.h" #include "core/project_settings.h" #include "scene/main/node.h" @@ -43,13 +43,12 @@ ////////////////////////////////////////// bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value) { - if (p_name == "argument_count") { - int new_argc = p_value; int argc = arguments.size(); - if (argc == new_argc) + if (argc == new_argc) { return true; + } arguments.resize(new_argc); @@ -66,7 +65,6 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value ERR_FAIL_INDEX_V(idx, arguments.size(), false); String what = String(p_name).get_slice("/", 1); if (what == "type") { - Variant::Type new_type = Variant::Type(int(p_value)); arguments.write[idx].type = new_type; ports_changed_notify(); @@ -75,7 +73,6 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value } if (what == "name") { - arguments.write[idx].name = p_value; ports_changed_notify(); return true; @@ -107,7 +104,6 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value } bool VisualScriptFunction::_get(const StringName &p_name, Variant &r_ret) const { - if (p_name == "argument_count") { r_ret = arguments.size(); return true; @@ -148,8 +144,8 @@ bool VisualScriptFunction::_get(const StringName &p_name, Variant &r_ret) const return false; } -void VisualScriptFunction::_get_property_list(List<PropertyInfo> *p_list) const { +void VisualScriptFunction::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, "argument_count", PROPERTY_HINT_RANGE, "0,256")); String argt = "Any"; for (int i = 1; i < Variant::VARIANT_MAX; i++) { @@ -171,35 +167,30 @@ void VisualScriptFunction::_get_property_list(List<PropertyInfo> *p_list) const } int VisualScriptFunction::get_output_sequence_port_count() const { - return 1; } bool VisualScriptFunction::has_input_sequence_port() const { - return false; } int VisualScriptFunction::get_input_value_port_count() const { - return 0; } -int VisualScriptFunction::get_output_value_port_count() const { +int VisualScriptFunction::get_output_value_port_count() const { return arguments.size(); } String VisualScriptFunction::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptFunction::get_input_value_port_info(int p_idx) const { - ERR_FAIL_V(PropertyInfo()); } -PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const { +PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, arguments.size(), PropertyInfo()); PropertyInfo out; out.type = arguments[p_idx].type; @@ -210,55 +201,53 @@ PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const { } String VisualScriptFunction::get_caption() const { - return "Function"; } String VisualScriptFunction::get_text() const { - return get_name(); //use name as function name I guess } void VisualScriptFunction::add_argument(Variant::Type p_type, const String &p_name, int p_index, const PropertyHint p_hint, const String &p_hint_string) { - Argument arg; arg.name = p_name; arg.type = p_type; arg.hint = p_hint; arg.hint_string = p_hint_string; - if (p_index >= 0) + if (p_index >= 0) { arguments.insert(p_index, arg); - else + } else { arguments.push_back(arg); + } ports_changed_notify(); } -void VisualScriptFunction::set_argument_type(int p_argidx, Variant::Type p_type) { +void VisualScriptFunction::set_argument_type(int p_argidx, Variant::Type p_type) { ERR_FAIL_INDEX(p_argidx, arguments.size()); arguments.write[p_argidx].type = p_type; ports_changed_notify(); } -Variant::Type VisualScriptFunction::get_argument_type(int p_argidx) const { +Variant::Type VisualScriptFunction::get_argument_type(int p_argidx) const { ERR_FAIL_INDEX_V(p_argidx, arguments.size(), Variant::NIL); return arguments[p_argidx].type; } -void VisualScriptFunction::set_argument_name(int p_argidx, const String &p_name) { +void VisualScriptFunction::set_argument_name(int p_argidx, const String &p_name) { ERR_FAIL_INDEX(p_argidx, arguments.size()); arguments.write[p_argidx].name = p_name; ports_changed_notify(); } -String VisualScriptFunction::get_argument_name(int p_argidx) const { +String VisualScriptFunction::get_argument_name(int p_argidx) const { ERR_FAIL_INDEX_V(p_argidx, arguments.size(), String()); return arguments[p_argidx].name; } -void VisualScriptFunction::remove_argument(int p_argidx) { +void VisualScriptFunction::remove_argument(int p_argidx) { ERR_FAIL_INDEX(p_argidx, arguments.size()); arguments.remove(p_argidx); @@ -266,7 +255,6 @@ void VisualScriptFunction::remove_argument(int p_argidx) { } int VisualScriptFunction::get_argument_count() const { - return arguments.size(); } @@ -286,7 +274,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - int ac = node->get_argument_count(); for (int i = 0; i < ac; i++) { @@ -310,7 +297,6 @@ public: }; VisualScriptNodeInstance *VisualScriptFunction::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceFunction *instance = memnew(VisualScriptNodeInstanceFunction); instance->node = this; instance->instance = p_instance; @@ -318,7 +304,6 @@ VisualScriptNodeInstance *VisualScriptFunction::instance(VisualScriptInstance *p } VisualScriptFunction::VisualScriptFunction() { - stack_size = 256; stack_less = false; sequenced = true; @@ -335,23 +320,19 @@ bool VisualScriptFunction::is_stack_less() const { } void VisualScriptFunction::set_sequenced(bool p_enable) { - sequenced = p_enable; } bool VisualScriptFunction::is_sequenced() const { - return sequenced; } void VisualScriptFunction::set_stack_size(int p_size) { - ERR_FAIL_COND(p_size < 1 || p_size > 100000); stack_size = p_size; } int VisualScriptFunction::get_stack_size() const { - return stack_size; } @@ -360,10 +341,12 @@ int VisualScriptFunction::get_stack_size() const { ////////////////////////////////////////// int VisualScriptLists::get_output_sequence_port_count() const { - if (sequenced) + if (sequenced) { return 1; + } return 0; } + bool VisualScriptLists::has_input_sequence_port() const { return sequenced; } @@ -375,6 +358,7 @@ String VisualScriptLists::get_output_sequence_port_text(int p_port) const { int VisualScriptLists::get_input_value_port_count() const { return inputports.size(); } + int VisualScriptLists::get_output_value_port_count() const { return outputports.size(); } @@ -387,6 +371,7 @@ PropertyInfo VisualScriptLists::get_input_value_port_info(int p_idx) const { pi.type = inputports[p_idx].type; return pi; } + PropertyInfo VisualScriptLists::get_output_value_port_info(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, outputports.size(), PropertyInfo()); @@ -399,9 +384,11 @@ PropertyInfo VisualScriptLists::get_output_value_port_info(int p_idx) const { bool VisualScriptLists::is_input_port_editable() const { return ((flags & INPUT_EDITABLE) == INPUT_EDITABLE); } + bool VisualScriptLists::is_input_port_name_editable() const { return ((flags & INPUT_NAME_EDITABLE) == INPUT_NAME_EDITABLE); } + bool VisualScriptLists::is_input_port_type_editable() const { return ((flags & INPUT_TYPE_EDITABLE) == INPUT_TYPE_EDITABLE); } @@ -409,22 +396,23 @@ bool VisualScriptLists::is_input_port_type_editable() const { bool VisualScriptLists::is_output_port_editable() const { return ((flags & OUTPUT_EDITABLE) == OUTPUT_EDITABLE); } + bool VisualScriptLists::is_output_port_name_editable() const { return ((flags & INPUT_NAME_EDITABLE) == INPUT_NAME_EDITABLE); } + bool VisualScriptLists::is_output_port_type_editable() const { return ((flags & INPUT_TYPE_EDITABLE) == INPUT_TYPE_EDITABLE); } // for the inspector bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) { - if (p_name == "input_count" && is_input_port_editable()) { - int new_argc = p_value; int argc = inputports.size(); - if (argc == new_argc) + if (argc == new_argc) { return true; + } inputports.resize(new_argc); @@ -441,7 +429,6 @@ bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_INDEX_V(idx, inputports.size(), false); String what = String(p_name).get_slice("/", 1); if (what == "type") { - Variant::Type new_type = Variant::Type(int(p_value)); inputports.write[idx].type = new_type; ports_changed_notify(); @@ -450,7 +437,6 @@ bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) { } if (what == "name") { - inputports.write[idx].name = p_value; ports_changed_notify(); return true; @@ -458,11 +444,11 @@ bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) { } if (p_name == "output_count" && is_output_port_editable()) { - int new_argc = p_value; int argc = outputports.size(); - if (argc == new_argc) + if (argc == new_argc) { return true; + } outputports.resize(new_argc); @@ -479,7 +465,6 @@ bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_INDEX_V(idx, outputports.size(), false); String what = String(p_name).get_slice("/", 1); if (what == "type") { - Variant::Type new_type = Variant::Type(int(p_value)); outputports.write[idx].type = new_type; ports_changed_notify(); @@ -488,7 +473,6 @@ bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) { } if (what == "name") { - outputports.write[idx].name = p_value; ports_changed_notify(); return true; @@ -503,8 +487,8 @@ bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) { return false; } -bool VisualScriptLists::_get(const StringName &p_name, Variant &r_ret) const { +bool VisualScriptLists::_get(const StringName &p_name, Variant &r_ret) const { if (p_name == "input_count" && is_input_port_editable()) { r_ret = inputports.size(); return true; @@ -548,8 +532,8 @@ bool VisualScriptLists::_get(const StringName &p_name, Variant &r_ret) const { return false; } -void VisualScriptLists::_get_property_list(List<PropertyInfo> *p_list) const { +void VisualScriptLists::_get_property_list(List<PropertyInfo> *p_list) const { if (is_input_port_editable()) { p_list->push_back(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,256")); String argt = "Any"; @@ -580,25 +564,27 @@ void VisualScriptLists::_get_property_list(List<PropertyInfo> *p_list) const { // input data port interaction void VisualScriptLists::add_input_data_port(Variant::Type p_type, const String &p_name, int p_index) { - - if (!is_input_port_editable()) + if (!is_input_port_editable()) { return; + } Port inp; inp.name = p_name; inp.type = p_type; - if (p_index >= 0) + if (p_index >= 0) { inputports.insert(p_index, inp); - else + } else { inputports.push_back(inp); + } ports_changed_notify(); _change_notify(); } -void VisualScriptLists::set_input_data_port_type(int p_idx, Variant::Type p_type) { - if (!is_input_port_type_editable()) +void VisualScriptLists::set_input_data_port_type(int p_idx, Variant::Type p_type) { + if (!is_input_port_type_editable()) { return; + } ERR_FAIL_INDEX(p_idx, inputports.size()); @@ -606,10 +592,11 @@ void VisualScriptLists::set_input_data_port_type(int p_idx, Variant::Type p_type ports_changed_notify(); _change_notify(); } -void VisualScriptLists::set_input_data_port_name(int p_idx, const String &p_name) { - if (!is_input_port_name_editable()) +void VisualScriptLists::set_input_data_port_name(int p_idx, const String &p_name) { + if (!is_input_port_name_editable()) { return; + } ERR_FAIL_INDEX(p_idx, inputports.size()); @@ -617,10 +604,11 @@ void VisualScriptLists::set_input_data_port_name(int p_idx, const String &p_name ports_changed_notify(); _change_notify(); } -void VisualScriptLists::remove_input_data_port(int p_argidx) { - if (!is_input_port_editable()) +void VisualScriptLists::remove_input_data_port(int p_argidx) { + if (!is_input_port_editable()) { return; + } ERR_FAIL_INDEX(p_argidx, inputports.size()); @@ -632,25 +620,27 @@ void VisualScriptLists::remove_input_data_port(int p_argidx) { // output data port interaction void VisualScriptLists::add_output_data_port(Variant::Type p_type, const String &p_name, int p_index) { - - if (!is_output_port_editable()) + if (!is_output_port_editable()) { return; + } Port out; out.name = p_name; out.type = p_type; - if (p_index >= 0) + if (p_index >= 0) { outputports.insert(p_index, out); - else + } else { outputports.push_back(out); + } ports_changed_notify(); _change_notify(); } -void VisualScriptLists::set_output_data_port_type(int p_idx, Variant::Type p_type) { - if (!is_output_port_type_editable()) +void VisualScriptLists::set_output_data_port_type(int p_idx, Variant::Type p_type) { + if (!is_output_port_type_editable()) { return; + } ERR_FAIL_INDEX(p_idx, outputports.size()); @@ -658,10 +648,11 @@ void VisualScriptLists::set_output_data_port_type(int p_idx, Variant::Type p_typ ports_changed_notify(); _change_notify(); } -void VisualScriptLists::set_output_data_port_name(int p_idx, const String &p_name) { - if (!is_output_port_name_editable()) +void VisualScriptLists::set_output_data_port_name(int p_idx, const String &p_name) { + if (!is_output_port_name_editable()) { return; + } ERR_FAIL_INDEX(p_idx, outputports.size()); @@ -669,10 +660,11 @@ void VisualScriptLists::set_output_data_port_name(int p_idx, const String &p_nam ports_changed_notify(); _change_notify(); } -void VisualScriptLists::remove_output_data_port(int p_argidx) { - if (!is_output_port_editable()) +void VisualScriptLists::remove_output_data_port(int p_argidx) { + if (!is_output_port_editable()) { return; + } ERR_FAIL_INDEX(p_argidx, outputports.size()); @@ -684,11 +676,13 @@ void VisualScriptLists::remove_output_data_port(int p_argidx) { // sequences void VisualScriptLists::set_sequenced(bool p_enable) { - if (sequenced == p_enable) + if (sequenced == p_enable) { return; + } sequenced = p_enable; ports_changed_notify(); } + bool VisualScriptLists::is_sequenced() const { return sequenced; } @@ -716,10 +710,12 @@ void VisualScriptLists::_bind_methods() { ////////////////////////////////////////// int VisualScriptComposeArray::get_output_sequence_port_count() const { - if (sequenced) + if (sequenced) { return 1; + } return 0; } + bool VisualScriptComposeArray::has_input_sequence_port() const { return sequenced; } @@ -731,6 +727,7 @@ String VisualScriptComposeArray::get_output_sequence_port_text(int p_port) const int VisualScriptComposeArray::get_input_value_port_count() const { return inputports.size(); } + int VisualScriptComposeArray::get_output_value_port_count() const { return 1; } @@ -743,6 +740,7 @@ PropertyInfo VisualScriptComposeArray::get_input_value_port_info(int p_idx) cons pi.type = inputports[p_idx].type; return pi; } + PropertyInfo VisualScriptComposeArray::get_output_value_port_info(int p_idx) const { PropertyInfo pi; pi.name = "out"; @@ -753,6 +751,7 @@ PropertyInfo VisualScriptComposeArray::get_output_value_port_info(int p_idx) con String VisualScriptComposeArray::get_caption() const { return "Compose Array"; } + String VisualScriptComposeArray::get_text() const { return ""; } @@ -763,11 +762,11 @@ public: virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (input_count > 0) { Array arr; - for (int i = 0; i < input_count; i++) + for (int i = 0; i < input_count; i++) { arr.push_back((*p_inputs[i])); + } Variant va = Variant(arr); *p_outputs[0] = va; @@ -778,7 +777,6 @@ public: }; VisualScriptNodeInstance *VisualScriptComposeArray::instance(VisualScriptInstance *p_instance) { - VisualScriptComposeArrayNode *instance = memnew(VisualScriptComposeArrayNode); instance->input_count = inputports.size(); return instance; @@ -795,31 +793,26 @@ VisualScriptComposeArray::VisualScriptComposeArray() { ////////////////////////////////////////// int VisualScriptOperator::get_output_sequence_port_count() const { - return 0; } bool VisualScriptOperator::has_input_sequence_port() const { - return false; } int VisualScriptOperator::get_input_value_port_count() const { - return (op == Variant::OP_BIT_NEGATE || op == Variant::OP_NOT || op == Variant::OP_NEGATE || op == Variant::OP_POSITIVE) ? 1 : 2; } -int VisualScriptOperator::get_output_value_port_count() const { +int VisualScriptOperator::get_output_value_port_count() const { return 1; } String VisualScriptOperator::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptOperator::get_input_value_port_info(int p_idx) const { - static const Variant::Type port_types[Variant::OP_MAX][2] = { { Variant::NIL, Variant::NIL }, //OP_EQUAL, { Variant::NIL, Variant::NIL }, //OP_NOT_EQUAL, @@ -857,10 +850,12 @@ PropertyInfo VisualScriptOperator::get_input_value_port_info(int p_idx) const { PropertyInfo pinfo; pinfo.name = p_idx == 0 ? "A" : "B"; pinfo.type = port_types[op][p_idx]; - if (pinfo.type == Variant::NIL) + if (pinfo.type == Variant::NIL) { pinfo.type = typed; + } return pinfo; } + PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { static const Variant::Type port_types[Variant::OP_MAX] = { //comparison @@ -898,8 +893,9 @@ PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { PropertyInfo pinfo; pinfo.name = ""; pinfo.type = port_types[op]; - if (pinfo.type == Variant::NIL) + if (pinfo.type == Variant::NIL) { pinfo.type = typed; + } return pinfo; } @@ -937,7 +933,6 @@ static const char *op_names[] = { }; String VisualScriptOperator::get_caption() const { - static const wchar_t *op_names[] = { //comparison L"A = B", //OP_EQUAL, @@ -974,34 +969,31 @@ String VisualScriptOperator::get_caption() const { } void VisualScriptOperator::set_operator(Variant::Operator p_op) { - - if (op == p_op) + if (op == p_op) { return; + } op = p_op; ports_changed_notify(); } Variant::Operator VisualScriptOperator::get_operator() const { - return op; } void VisualScriptOperator::set_typed(Variant::Type p_op) { - - if (typed == p_op) + if (typed == p_op) { return; + } typed = p_op; ports_changed_notify(); } Variant::Type VisualScriptOperator::get_typed() const { - return typed; } void VisualScriptOperator::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualScriptOperator::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualScriptOperator::get_operator); @@ -1010,8 +1002,9 @@ void VisualScriptOperator::_bind_methods() { String types; for (int i = 0; i < Variant::OP_MAX; i++) { - if (i > 0) + if (i > 0) { types += ","; + } types += op_names[i]; } @@ -1032,25 +1025,23 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - bool valid; if (unary) { - Variant::evaluate(op, *p_inputs[0], Variant(), *p_outputs[0], valid); } else { Variant::evaluate(op, *p_inputs[0], *p_inputs[1], *p_outputs[0], valid); } if (!valid) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; if (p_outputs[0]->get_type() == Variant::STRING) { r_error_str = *p_outputs[0]; } else { - if (unary) + if (unary) { r_error_str = String(op_names[op]) + RTR(": Invalid argument of type: ") + Variant::get_type_name(p_inputs[0]->get_type()); - else + } else { r_error_str = String(op_names[op]) + RTR(": Invalid arguments: ") + "A: " + Variant::get_type_name(p_inputs[0]->get_type()) + " B: " + Variant::get_type_name(p_inputs[1]->get_type()); + } } } @@ -1059,7 +1050,6 @@ public: }; VisualScriptNodeInstance *VisualScriptOperator::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceOperator *instance = memnew(VisualScriptNodeInstanceOperator); instance->unary = get_input_value_port_count() == 1; instance->op = op; @@ -1067,14 +1057,12 @@ VisualScriptNodeInstance *VisualScriptOperator::instance(VisualScriptInstance *p } VisualScriptOperator::VisualScriptOperator() { - op = Variant::OP_ADD; typed = Variant::NIL; } template <Variant::Operator OP> static Ref<VisualScriptNode> create_op_node(const String &p_name) { - Ref<VisualScriptOperator> node; node.instance(); node->set_operator(OP); @@ -1086,31 +1074,26 @@ static Ref<VisualScriptNode> create_op_node(const String &p_name) { ////////////////////////////////////////// int VisualScriptSelect::get_output_sequence_port_count() const { - return 0; } bool VisualScriptSelect::has_input_sequence_port() const { - return false; } int VisualScriptSelect::get_input_value_port_count() const { - return 3; } -int VisualScriptSelect::get_output_value_port_count() const { +int VisualScriptSelect::get_output_value_port_count() const { return 1; } String VisualScriptSelect::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptSelect::get_input_value_port_info(int p_idx) const { - if (p_idx == 0) { return PropertyInfo(Variant::BOOL, "cond"); } else if (p_idx == 1) { @@ -1119,37 +1102,33 @@ PropertyInfo VisualScriptSelect::get_input_value_port_info(int p_idx) const { return PropertyInfo(typed, "b"); } } -PropertyInfo VisualScriptSelect::get_output_value_port_info(int p_idx) const { +PropertyInfo VisualScriptSelect::get_output_value_port_info(int p_idx) const { return PropertyInfo(typed, "out"); } String VisualScriptSelect::get_caption() const { - return "Select"; } String VisualScriptSelect::get_text() const { - return "a if cond, else b"; } void VisualScriptSelect::set_typed(Variant::Type p_op) { - - if (typed == p_op) + if (typed == p_op) { return; + } typed = p_op; ports_changed_notify(); } Variant::Type VisualScriptSelect::get_typed() const { - return typed; } void VisualScriptSelect::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_typed", "type"), &VisualScriptSelect::set_typed); ClassDB::bind_method(D_METHOD("get_typed"), &VisualScriptSelect::get_typed); @@ -1166,25 +1145,23 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - bool cond = *p_inputs[0]; - if (cond) + if (cond) { *p_outputs[0] = *p_inputs[1]; - else + } else { *p_outputs[0] = *p_inputs[2]; + } return 0; } }; VisualScriptNodeInstance *VisualScriptSelect::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceSelect *instance = memnew(VisualScriptNodeInstanceSelect); return instance; } VisualScriptSelect::VisualScriptSelect() { - typed = Variant::NIL; } @@ -1193,36 +1170,30 @@ VisualScriptSelect::VisualScriptSelect() { ////////////////////////////////////////// int VisualScriptVariableGet::get_output_sequence_port_count() const { - return 0; } bool VisualScriptVariableGet::has_input_sequence_port() const { - return false; } int VisualScriptVariableGet::get_input_value_port_count() const { - return 0; } -int VisualScriptVariableGet::get_output_value_port_count() const { +int VisualScriptVariableGet::get_output_value_port_count() const { return 1; } String VisualScriptVariableGet::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptVariableGet::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) const { - PropertyInfo pinfo; pinfo.name = "value"; if (get_visual_script().is_valid() && get_visual_script()->has_variable(variable)) { @@ -1235,24 +1206,22 @@ PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) cons } String VisualScriptVariableGet::get_caption() const { - return "Get " + variable; } -void VisualScriptVariableGet::set_variable(StringName p_variable) { - if (variable == p_variable) +void VisualScriptVariableGet::set_variable(StringName p_variable) { + if (variable == p_variable) { return; + } variable = p_variable; ports_changed_notify(); } StringName VisualScriptVariableGet::get_variable() const { - return variable; } void VisualScriptVariableGet::_validate_property(PropertyInfo &property) const { - if (property.name == "var_name" && get_visual_script().is_valid()) { Ref<VisualScript> vs = get_visual_script(); List<StringName> vars; @@ -1260,8 +1229,9 @@ void VisualScriptVariableGet::_validate_property(PropertyInfo &property) const { String vhint; for (List<StringName>::Element *E = vars.front(); E; E = E->next()) { - if (vhint != String()) + if (vhint != String()) { vhint += ","; + } vhint += E->get().operator String(); } @@ -1272,7 +1242,6 @@ void VisualScriptVariableGet::_validate_property(PropertyInfo &property) const { } void VisualScriptVariableGet::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_variable", "name"), &VisualScriptVariableGet::set_variable); ClassDB::bind_method(D_METHOD("get_variable"), &VisualScriptVariableGet::get_variable); @@ -1286,7 +1255,6 @@ public: StringName variable; virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (!instance->get_variable(variable, p_outputs[0])) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = RTR("VariableGet not found in script: ") + "'" + String(variable) + "'"; @@ -1297,13 +1265,13 @@ public: }; VisualScriptNodeInstance *VisualScriptVariableGet::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceVariableGet *instance = memnew(VisualScriptNodeInstanceVariableGet); instance->node = this; instance->instance = p_instance; instance->variable = variable; return instance; } + VisualScriptVariableGet::VisualScriptVariableGet() { } @@ -1312,31 +1280,26 @@ VisualScriptVariableGet::VisualScriptVariableGet() { ////////////////////////////////////////// int VisualScriptVariableSet::get_output_sequence_port_count() const { - return 1; } bool VisualScriptVariableSet::has_input_sequence_port() const { - return true; } int VisualScriptVariableSet::get_input_value_port_count() const { - return 1; } -int VisualScriptVariableSet::get_output_value_port_count() const { +int VisualScriptVariableSet::get_output_value_port_count() const { return 0; } String VisualScriptVariableSet::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptVariableSet::get_input_value_port_info(int p_idx) const { - PropertyInfo pinfo; pinfo.name = "set"; if (get_visual_script().is_valid() && get_visual_script()->has_variable(variable)) { @@ -1349,30 +1312,26 @@ PropertyInfo VisualScriptVariableSet::get_input_value_port_info(int p_idx) const } PropertyInfo VisualScriptVariableSet::get_output_value_port_info(int p_idx) const { - return PropertyInfo(); } String VisualScriptVariableSet::get_caption() const { - return "Set " + variable; } void VisualScriptVariableSet::set_variable(StringName p_variable) { - - if (variable == p_variable) + if (variable == p_variable) { return; + } variable = p_variable; ports_changed_notify(); } StringName VisualScriptVariableSet::get_variable() const { - return variable; } void VisualScriptVariableSet::_validate_property(PropertyInfo &property) const { - if (property.name == "var_name" && get_visual_script().is_valid()) { Ref<VisualScript> vs = get_visual_script(); List<StringName> vars; @@ -1380,8 +1339,9 @@ void VisualScriptVariableSet::_validate_property(PropertyInfo &property) const { String vhint; for (List<StringName>::Element *E = vars.front(); E; E = E->next()) { - if (vhint != String()) + if (vhint != String()) { vhint += ","; + } vhint += E->get().operator String(); } @@ -1392,7 +1352,6 @@ void VisualScriptVariableSet::_validate_property(PropertyInfo &property) const { } void VisualScriptVariableSet::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_variable", "name"), &VisualScriptVariableSet::set_variable); ClassDB::bind_method(D_METHOD("get_variable"), &VisualScriptVariableSet::get_variable); @@ -1408,9 +1367,7 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (!instance->set_variable(variable, *p_inputs[0])) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = RTR("VariableSet not found in script: ") + "'" + String(variable) + "'"; } @@ -1420,13 +1377,13 @@ public: }; VisualScriptNodeInstance *VisualScriptVariableSet::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceVariableSet *instance = memnew(VisualScriptNodeInstanceVariableSet); instance->node = this; instance->instance = p_instance; instance->variable = variable; return instance; } + VisualScriptVariableSet::VisualScriptVariableSet() { } @@ -1435,36 +1392,30 @@ VisualScriptVariableSet::VisualScriptVariableSet() { ////////////////////////////////////////// int VisualScriptConstant::get_output_sequence_port_count() const { - return 0; } bool VisualScriptConstant::has_input_sequence_port() const { - return false; } int VisualScriptConstant::get_input_value_port_count() const { - return 0; } -int VisualScriptConstant::get_output_value_port_count() const { +int VisualScriptConstant::get_output_value_port_count() const { return 1; } String VisualScriptConstant::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptConstant::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptConstant::get_output_value_port_info(int p_idx) const { - PropertyInfo pinfo; pinfo.name = String(value); pinfo.type = type; @@ -1472,51 +1423,48 @@ PropertyInfo VisualScriptConstant::get_output_value_port_info(int p_idx) const { } String VisualScriptConstant::get_caption() const { - return "Constant"; } void VisualScriptConstant::set_constant_type(Variant::Type p_type) { - - if (type == p_type) + if (type == p_type) { return; + } type = p_type; Callable::CallError ce; - value = Variant::construct(type, NULL, 0, ce); + value = Variant::construct(type, nullptr, 0, ce); ports_changed_notify(); _change_notify(); } Variant::Type VisualScriptConstant::get_constant_type() const { - return type; } void VisualScriptConstant::set_constant_value(Variant p_value) { - - if (value == p_value) + if (value == p_value) { return; + } value = p_value; ports_changed_notify(); } -Variant VisualScriptConstant::get_constant_value() const { +Variant VisualScriptConstant::get_constant_value() const { return value; } void VisualScriptConstant::_validate_property(PropertyInfo &property) const { - if (property.name == "value") { property.type = type; - if (type == Variant::NIL) + if (type == Variant::NIL) { property.usage = 0; //do not save if nil + } } } void VisualScriptConstant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_constant_type", "type"), &VisualScriptConstant::set_constant_type); ClassDB::bind_method(D_METHOD("get_constant_type"), &VisualScriptConstant::get_constant_type); @@ -1538,21 +1486,18 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = constant; return 0; } }; VisualScriptNodeInstance *VisualScriptConstant::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceConstant *instance = memnew(VisualScriptNodeInstanceConstant); instance->constant = value; return instance; } VisualScriptConstant::VisualScriptConstant() { - type = Variant::NIL; } @@ -1561,36 +1506,30 @@ VisualScriptConstant::VisualScriptConstant() { ////////////////////////////////////////// int VisualScriptPreload::get_output_sequence_port_count() const { - return 0; } bool VisualScriptPreload::has_input_sequence_port() const { - return false; } int VisualScriptPreload::get_input_value_port_count() const { - return 0; } -int VisualScriptPreload::get_output_value_port_count() const { +int VisualScriptPreload::get_output_value_port_count() const { return 1; } String VisualScriptPreload::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptPreload::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptPreload::get_output_value_port_info(int p_idx) const { - PropertyInfo pinfo; pinfo.type = Variant::OBJECT; if (preload.is_valid()) { @@ -1611,26 +1550,23 @@ PropertyInfo VisualScriptPreload::get_output_value_port_info(int p_idx) const { } String VisualScriptPreload::get_caption() const { - return "Preload"; } void VisualScriptPreload::set_preload(const Ref<Resource> &p_preload) { - - if (preload == p_preload) + if (preload == p_preload) { return; + } preload = p_preload; ports_changed_notify(); } Ref<Resource> VisualScriptPreload::get_preload() const { - return preload; } void VisualScriptPreload::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_preload", "resource"), &VisualScriptPreload::set_preload); ClassDB::bind_method(D_METHOD("get_preload"), &VisualScriptPreload::get_preload); @@ -1643,14 +1579,12 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = preload; return 0; } }; VisualScriptNodeInstance *VisualScriptPreload::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstancePreload *instance = memnew(VisualScriptNodeInstancePreload); instance->preload = preload; return instance; @@ -1664,31 +1598,26 @@ VisualScriptPreload::VisualScriptPreload() { ////////////////////////////////////////// int VisualScriptIndexGet::get_output_sequence_port_count() const { - return 0; } bool VisualScriptIndexGet::has_input_sequence_port() const { - return false; } int VisualScriptIndexGet::get_input_value_port_count() const { - return 2; } -int VisualScriptIndexGet::get_output_value_port_count() const { +int VisualScriptIndexGet::get_output_value_port_count() const { return 1; } String VisualScriptIndexGet::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptIndexGet::get_input_value_port_info(int p_idx) const { - if (p_idx == 0) { return PropertyInfo(Variant::NIL, "base"); } else { @@ -1697,12 +1626,10 @@ PropertyInfo VisualScriptIndexGet::get_input_value_port_info(int p_idx) const { } PropertyInfo VisualScriptIndexGet::get_output_value_port_info(int p_idx) const { - return PropertyInfo(); } String VisualScriptIndexGet::get_caption() const { - return "Get Index"; } @@ -1711,7 +1638,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - bool valid; *p_outputs[0] = p_inputs[0]->get(*p_inputs[1], &valid); @@ -1724,10 +1650,10 @@ public: }; VisualScriptNodeInstance *VisualScriptIndexGet::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceIndexGet *instance = memnew(VisualScriptNodeInstanceIndexGet); return instance; } + VisualScriptIndexGet::VisualScriptIndexGet() { } @@ -1736,31 +1662,26 @@ VisualScriptIndexGet::VisualScriptIndexGet() { ////////////////////////////////////////// int VisualScriptIndexSet::get_output_sequence_port_count() const { - return 1; } bool VisualScriptIndexSet::has_input_sequence_port() const { - return true; } int VisualScriptIndexSet::get_input_value_port_count() const { - return 3; } -int VisualScriptIndexSet::get_output_value_port_count() const { +int VisualScriptIndexSet::get_output_value_port_count() const { return 0; } String VisualScriptIndexSet::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptIndexSet::get_input_value_port_info(int p_idx) const { - if (p_idx == 0) { return PropertyInfo(Variant::NIL, "base"); } else if (p_idx == 1) { @@ -1772,12 +1693,10 @@ PropertyInfo VisualScriptIndexSet::get_input_value_port_info(int p_idx) const { } PropertyInfo VisualScriptIndexSet::get_output_value_port_info(int p_idx) const { - return PropertyInfo(); } String VisualScriptIndexSet::get_caption() const { - return "Set Index"; } @@ -1786,7 +1705,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - bool valid; *p_outputs[0] = *p_inputs[0]; p_outputs[0]->set(*p_inputs[1], *p_inputs[2], &valid); @@ -1800,10 +1718,10 @@ public: }; VisualScriptNodeInstance *VisualScriptIndexSet::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceIndexSet *instance = memnew(VisualScriptNodeInstanceIndexSet); return instance; } + VisualScriptIndexSet::VisualScriptIndexSet() { } @@ -1812,31 +1730,26 @@ VisualScriptIndexSet::VisualScriptIndexSet() { ////////////////////////////////////////// int VisualScriptGlobalConstant::get_output_sequence_port_count() const { - return 0; } bool VisualScriptGlobalConstant::has_input_sequence_port() const { - return false; } int VisualScriptGlobalConstant::get_input_value_port_count() const { - return 0; } -int VisualScriptGlobalConstant::get_output_value_port_count() const { +int VisualScriptGlobalConstant::get_output_value_port_count() const { return 1; } String VisualScriptGlobalConstant::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptGlobalConstant::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } @@ -1846,12 +1759,10 @@ PropertyInfo VisualScriptGlobalConstant::get_output_value_port_info(int p_idx) c } String VisualScriptGlobalConstant::get_caption() const { - return "Global Constant"; } void VisualScriptGlobalConstant::set_global_constant(int p_which) { - index = p_which; _change_notify(); ports_changed_notify(); @@ -1867,37 +1778,33 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = GlobalConstants::get_global_constant_value(index); return 0; } }; VisualScriptNodeInstance *VisualScriptGlobalConstant::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceGlobalConstant *instance = memnew(VisualScriptNodeInstanceGlobalConstant); instance->index = index; return instance; } void VisualScriptGlobalConstant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_global_constant", "index"), &VisualScriptGlobalConstant::set_global_constant); ClassDB::bind_method(D_METHOD("get_global_constant"), &VisualScriptGlobalConstant::get_global_constant); String cc; for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) { - - if (i > 0) + if (i > 0) { cc += ","; + } cc += GlobalConstants::get_global_constant_name(i); } ADD_PROPERTY(PropertyInfo(Variant::INT, "constant", PROPERTY_HINT_ENUM, cc), "set_global_constant", "get_global_constant"); } VisualScriptGlobalConstant::VisualScriptGlobalConstant() { - index = 0; } @@ -1906,31 +1813,26 @@ VisualScriptGlobalConstant::VisualScriptGlobalConstant() { ////////////////////////////////////////// int VisualScriptClassConstant::get_output_sequence_port_count() const { - return 0; } bool VisualScriptClassConstant::has_input_sequence_port() const { - return false; } int VisualScriptClassConstant::get_input_value_port_count() const { - return 0; } -int VisualScriptClassConstant::get_output_value_port_count() const { +int VisualScriptClassConstant::get_output_value_port_count() const { return 1; } String VisualScriptClassConstant::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptClassConstant::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } @@ -1943,12 +1845,10 @@ PropertyInfo VisualScriptClassConstant::get_output_value_port_info(int p_idx) co } String VisualScriptClassConstant::get_caption() const { - return "Class Constant"; } void VisualScriptClassConstant::set_class_constant(const StringName &p_which) { - name = p_which; _change_notify(); ports_changed_notify(); @@ -1959,7 +1859,6 @@ StringName VisualScriptClassConstant::get_class_constant() { } void VisualScriptClassConstant::set_base_type(const StringName &p_which) { - base_type = p_which; List<String> constants; ClassDB::get_integer_constant_list(base_type, &constants, true); @@ -1992,7 +1891,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (!valid) { r_error_str = "Invalid constant name, pick a valid class constant."; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -2004,16 +1902,13 @@ public: }; VisualScriptNodeInstance *VisualScriptClassConstant::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceClassConstant *instance = memnew(VisualScriptNodeInstanceClassConstant); instance->value = ClassDB::get_integer_constant(base_type, name, &instance->valid); return instance; } void VisualScriptClassConstant::_validate_property(PropertyInfo &property) const { - if (property.name == "constant") { - List<String> constants; ClassDB::get_integer_constant_list(base_type, &constants, true); @@ -2028,7 +1923,6 @@ void VisualScriptClassConstant::_validate_property(PropertyInfo &property) const } void VisualScriptClassConstant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_class_constant", "name"), &VisualScriptClassConstant::set_class_constant); ClassDB::bind_method(D_METHOD("get_class_constant"), &VisualScriptClassConstant::get_class_constant); @@ -2040,7 +1934,6 @@ void VisualScriptClassConstant::_bind_methods() { } VisualScriptClassConstant::VisualScriptClassConstant() { - base_type = "Object"; } @@ -2049,41 +1942,34 @@ VisualScriptClassConstant::VisualScriptClassConstant() { ////////////////////////////////////////// int VisualScriptBasicTypeConstant::get_output_sequence_port_count() const { - return 0; } bool VisualScriptBasicTypeConstant::has_input_sequence_port() const { - return false; } int VisualScriptBasicTypeConstant::get_input_value_port_count() const { - return 0; } -int VisualScriptBasicTypeConstant::get_output_value_port_count() const { +int VisualScriptBasicTypeConstant::get_output_value_port_count() const { return 1; } String VisualScriptBasicTypeConstant::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptBasicTypeConstant::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptBasicTypeConstant::get_output_value_port_info(int p_idx) const { - return PropertyInfo(type, "value"); } String VisualScriptBasicTypeConstant::get_caption() const { - return "Basic Constant"; } @@ -2096,7 +1982,6 @@ String VisualScriptBasicTypeConstant::get_text() const { } void VisualScriptBasicTypeConstant::set_basic_type_constant(const StringName &p_which) { - name = p_which; _change_notify(); ports_changed_notify(); @@ -2107,7 +1992,6 @@ StringName VisualScriptBasicTypeConstant::get_basic_type_constant() const { } void VisualScriptBasicTypeConstant::set_basic_type(Variant::Type p_which) { - type = p_which; List<StringName> constants; @@ -2141,7 +2025,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (!valid) { r_error_str = "Invalid constant name, pick a valid basic type constant."; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -2153,16 +2036,13 @@ public: }; VisualScriptNodeInstance *VisualScriptBasicTypeConstant::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceBasicTypeConstant *instance = memnew(VisualScriptNodeInstanceBasicTypeConstant); instance->value = Variant::get_constant_value(type, name, &instance->valid); return instance; } void VisualScriptBasicTypeConstant::_validate_property(PropertyInfo &property) const { - if (property.name == "constant") { - List<StringName> constants; Variant::get_constants_for_type(type, &constants); @@ -2181,7 +2061,6 @@ void VisualScriptBasicTypeConstant::_validate_property(PropertyInfo &property) c } void VisualScriptBasicTypeConstant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_basic_type", "name"), &VisualScriptBasicTypeConstant::set_basic_type); ClassDB::bind_method(D_METHOD("get_basic_type"), &VisualScriptBasicTypeConstant::get_basic_type); @@ -2198,7 +2077,6 @@ void VisualScriptBasicTypeConstant::_bind_methods() { } VisualScriptBasicTypeConstant::VisualScriptBasicTypeConstant() { - type = Variant::NIL; } @@ -2229,46 +2107,38 @@ double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX] = { }; int VisualScriptMathConstant::get_output_sequence_port_count() const { - return 0; } bool VisualScriptMathConstant::has_input_sequence_port() const { - return false; } int VisualScriptMathConstant::get_input_value_port_count() const { - return 0; } -int VisualScriptMathConstant::get_output_value_port_count() const { +int VisualScriptMathConstant::get_output_value_port_count() const { return 1; } String VisualScriptMathConstant::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptMathConstant::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::FLOAT, const_name[constant]); } String VisualScriptMathConstant::get_caption() const { - return "Math Constant"; } void VisualScriptMathConstant::set_math_constant(MathConstant p_which) { - constant = p_which; _change_notify(); ports_changed_notify(); @@ -2284,30 +2154,27 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = value; return 0; } }; VisualScriptNodeInstance *VisualScriptMathConstant::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceMathConstant *instance = memnew(VisualScriptNodeInstanceMathConstant); instance->value = const_value[constant]; return instance; } void VisualScriptMathConstant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_math_constant", "which"), &VisualScriptMathConstant::set_math_constant); ClassDB::bind_method(D_METHOD("get_math_constant"), &VisualScriptMathConstant::get_math_constant); String cc; for (int i = 0; i < MATH_CONSTANT_MAX; i++) { - - if (i > 0) + if (i > 0) { cc += ","; + } cc += const_name[i]; } ADD_PROPERTY(PropertyInfo(Variant::INT, "constant", PROPERTY_HINT_ENUM, cc), "set_math_constant", "get_math_constant"); @@ -2324,7 +2191,6 @@ void VisualScriptMathConstant::_bind_methods() { } VisualScriptMathConstant::VisualScriptMathConstant() { - constant = MATH_CONSTANT_ONE; } @@ -2333,46 +2199,38 @@ VisualScriptMathConstant::VisualScriptMathConstant() { ////////////////////////////////////////// int VisualScriptEngineSingleton::get_output_sequence_port_count() const { - return 0; } bool VisualScriptEngineSingleton::has_input_sequence_port() const { - return false; } int VisualScriptEngineSingleton::get_input_value_port_count() const { - return 0; } -int VisualScriptEngineSingleton::get_output_value_port_count() const { +int VisualScriptEngineSingleton::get_output_value_port_count() const { return 1; } String VisualScriptEngineSingleton::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptEngineSingleton::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptEngineSingleton::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, singleton); } String VisualScriptEngineSingleton::get_caption() const { - return "Get Engine Singleton"; } void VisualScriptEngineSingleton::set_singleton(const String &p_string) { - singleton = p_string; _change_notify(); @@ -2390,21 +2248,18 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = singleton; return 0; } }; VisualScriptNodeInstance *VisualScriptEngineSingleton::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceEngineSingleton *instance = memnew(VisualScriptNodeInstanceEngineSingleton); instance->singleton = Engine::get_singleton()->get_singleton_object(singleton); return instance; } VisualScriptEngineSingleton::TypeGuess VisualScriptEngineSingleton::guess_output_type(TypeGuess *p_inputs, int p_output) const { - Object *obj = Engine::get_singleton()->get_singleton_object(singleton); TypeGuess tg; tg.type = Variant::OBJECT; @@ -2417,7 +2272,6 @@ VisualScriptEngineSingleton::TypeGuess VisualScriptEngineSingleton::guess_output } void VisualScriptEngineSingleton::_validate_property(PropertyInfo &property) const { - String cc; List<Engine::Singleton> singletons; @@ -2425,11 +2279,13 @@ void VisualScriptEngineSingleton::_validate_property(PropertyInfo &property) con Engine::get_singleton()->get_singletons(&singletons); for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) { - if (E->get().name == "VS" || E->get().name == "PS" || E->get().name == "PS2D" || E->get().name == "AS" || E->get().name == "TS" || E->get().name == "SS" || E->get().name == "SS2D") + if (E->get().name == "VS" || E->get().name == "PS" || E->get().name == "PS2D" || E->get().name == "AS" || E->get().name == "TS" || E->get().name == "SS" || E->get().name == "SS2D") { continue; //skip these, too simple named + } - if (cc != String()) + if (cc != String()) { cc += ","; + } cc += E->get().name; } @@ -2438,7 +2294,6 @@ void VisualScriptEngineSingleton::_validate_property(PropertyInfo &property) con } void VisualScriptEngineSingleton::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_singleton", "name"), &VisualScriptEngineSingleton::set_singleton); ClassDB::bind_method(D_METHOD("get_singleton"), &VisualScriptEngineSingleton::get_singleton); @@ -2446,7 +2301,6 @@ void VisualScriptEngineSingleton::_bind_methods() { } VisualScriptEngineSingleton::VisualScriptEngineSingleton() { - singleton = String(); } @@ -2455,46 +2309,38 @@ VisualScriptEngineSingleton::VisualScriptEngineSingleton() { ////////////////////////////////////////// int VisualScriptSceneNode::get_output_sequence_port_count() const { - return 0; } bool VisualScriptSceneNode::has_input_sequence_port() const { - return false; } int VisualScriptSceneNode::get_input_value_port_count() const { - return 0; } -int VisualScriptSceneNode::get_output_value_port_count() const { +int VisualScriptSceneNode::get_output_value_port_count() const { return 1; } String VisualScriptSceneNode::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptSceneNode::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptSceneNode::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, path.simplified()); } String VisualScriptSceneNode::get_caption() const { - return "Get Scene Node"; } void VisualScriptSceneNode::set_node_path(const NodePath &p_path) { - path = p_path; _change_notify(); ports_changed_notify(); @@ -2513,7 +2359,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - Node *node = Object::cast_to<Node>(instance->get_owner_ptr()); if (!node) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -2535,7 +2380,6 @@ public: }; VisualScriptNodeInstance *VisualScriptSceneNode::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceSceneNode *instance = memnew(VisualScriptNodeInstanceSceneNode); instance->node = this; instance->instance = p_instance; @@ -2546,52 +2390,57 @@ VisualScriptNodeInstance *VisualScriptSceneNode::instance(VisualScriptInstance * #ifdef TOOLS_ENABLED static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const Ref<Script> &script) { - - if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene) - return NULL; + if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene) { + return nullptr; + } Ref<Script> scr = p_current_node->get_script(); - if (scr.is_valid() && scr == script) + if (scr.is_valid() && scr == script) { return p_current_node; + } for (int i = 0; i < p_current_node->get_child_count(); i++) { Node *n = _find_script_node(p_edited_scene, p_current_node->get_child(i), script); - if (n) + if (n) { return n; + } } - return NULL; + return nullptr; } #endif VisualScriptSceneNode::TypeGuess VisualScriptSceneNode::guess_output_type(TypeGuess *p_inputs, int p_output) const { - VisualScriptSceneNode::TypeGuess tg; tg.type = Variant::OBJECT; tg.gdclass = "Node"; #ifdef TOOLS_ENABLED Ref<Script> script = get_visual_script(); - if (!script.is_valid()) + if (!script.is_valid()) { return tg; + } MainLoop *main_loop = OS::get_singleton()->get_main_loop(); SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop); - if (!scene_tree) + if (!scene_tree) { return tg; + } Node *edited_scene = scene_tree->get_edited_scene_root(); - if (!edited_scene) + if (!edited_scene) { return tg; + } Node *script_node = _find_script_node(edited_scene, edited_scene, script); - if (!script_node) + if (!script_node) { return tg; + } Node *another = script_node->get_node(path); @@ -2604,29 +2453,31 @@ VisualScriptSceneNode::TypeGuess VisualScriptSceneNode::guess_output_type(TypeGu } void VisualScriptSceneNode::_validate_property(PropertyInfo &property) const { - #ifdef TOOLS_ENABLED if (property.name == "node_path") { - Ref<Script> script = get_visual_script(); - if (!script.is_valid()) + if (!script.is_valid()) { return; + } MainLoop *main_loop = OS::get_singleton()->get_main_loop(); SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop); - if (!scene_tree) + if (!scene_tree) { return; + } Node *edited_scene = scene_tree->get_edited_scene_root(); - if (!edited_scene) + if (!edited_scene) { return; + } Node *script_node = _find_script_node(edited_scene, edited_scene, script); - if (!script_node) + if (!script_node) { return; + } property.hint_string = script_node->get_path(); } @@ -2634,7 +2485,6 @@ void VisualScriptSceneNode::_validate_property(PropertyInfo &property) const { } void VisualScriptSceneNode::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_node_path", "path"), &VisualScriptSceneNode::set_node_path); ClassDB::bind_method(D_METHOD("get_node_path"), &VisualScriptSceneNode::get_node_path); @@ -2642,7 +2492,6 @@ void VisualScriptSceneNode::_bind_methods() { } VisualScriptSceneNode::VisualScriptSceneNode() { - path = String("."); } @@ -2651,41 +2500,34 @@ VisualScriptSceneNode::VisualScriptSceneNode() { ////////////////////////////////////////// int VisualScriptSceneTree::get_output_sequence_port_count() const { - return 0; } bool VisualScriptSceneTree::has_input_sequence_port() const { - return false; } int VisualScriptSceneTree::get_input_value_port_count() const { - return 0; } -int VisualScriptSceneTree::get_output_value_port_count() const { +int VisualScriptSceneTree::get_output_value_port_count() const { return 1; } String VisualScriptSceneTree::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptSceneTree::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptSceneTree::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "Scene Tree", PROPERTY_HINT_TYPE_STRING, "SceneTree"); } String VisualScriptSceneTree::get_caption() const { - return "Get Scene Tree"; } @@ -2697,7 +2539,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - Node *node = Object::cast_to<Node>(instance->get_owner_ptr()); if (!node) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -2719,7 +2560,6 @@ public: }; VisualScriptNodeInstance *VisualScriptSceneTree::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceSceneTree *instance = memnew(VisualScriptNodeInstanceSceneTree); instance->node = this; instance->instance = p_instance; @@ -2727,7 +2567,6 @@ VisualScriptNodeInstance *VisualScriptSceneTree::instance(VisualScriptInstance * } VisualScriptSceneTree::TypeGuess VisualScriptSceneTree::guess_output_type(TypeGuess *p_inputs, int p_output) const { - TypeGuess tg; tg.type = Variant::OBJECT; tg.gdclass = "SceneTree"; @@ -2748,46 +2587,38 @@ VisualScriptSceneTree::VisualScriptSceneTree() { ////////////////////////////////////////// int VisualScriptResourcePath::get_output_sequence_port_count() const { - return 0; } bool VisualScriptResourcePath::has_input_sequence_port() const { - return false; } int VisualScriptResourcePath::get_input_value_port_count() const { - return 0; } -int VisualScriptResourcePath::get_output_value_port_count() const { +int VisualScriptResourcePath::get_output_value_port_count() const { return 1; } String VisualScriptResourcePath::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptResourcePath::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptResourcePath::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::STRING, path); } String VisualScriptResourcePath::get_caption() const { - return "Resource Path"; } void VisualScriptResourcePath::set_resource_path(const String &p_path) { - path = p_path; _change_notify(); ports_changed_notify(); @@ -2804,21 +2635,18 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = path; return 0; } }; VisualScriptNodeInstance *VisualScriptResourcePath::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceResourcePath *instance = memnew(VisualScriptNodeInstanceResourcePath); instance->path = path; return instance; } void VisualScriptResourcePath::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_resource_path", "path"), &VisualScriptResourcePath::set_resource_path); ClassDB::bind_method(D_METHOD("get_resource_path"), &VisualScriptResourcePath::get_resource_path); @@ -2826,7 +2654,6 @@ void VisualScriptResourcePath::_bind_methods() { } VisualScriptResourcePath::VisualScriptResourcePath() { - path = ""; } @@ -2835,47 +2662,41 @@ VisualScriptResourcePath::VisualScriptResourcePath() { ////////////////////////////////////////// int VisualScriptSelf::get_output_sequence_port_count() const { - return 0; } bool VisualScriptSelf::has_input_sequence_port() const { - return false; } int VisualScriptSelf::get_input_value_port_count() const { - return 0; } -int VisualScriptSelf::get_output_value_port_count() const { +int VisualScriptSelf::get_output_value_port_count() const { return 1; } String VisualScriptSelf::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptSelf::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptSelf::get_output_value_port_info(int p_idx) const { - String type_name; - if (get_visual_script().is_valid()) + if (get_visual_script().is_valid()) { type_name = get_visual_script()->get_instance_base_type(); - else + } else { type_name = "instance"; + } return PropertyInfo(Variant::OBJECT, type_name); } String VisualScriptSelf::get_caption() const { - return "Get Self"; } @@ -2886,28 +2707,26 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = instance->get_owner_ptr(); return 0; } }; VisualScriptNodeInstance *VisualScriptSelf::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceSelf *instance = memnew(VisualScriptNodeInstanceSelf); instance->instance = p_instance; return instance; } VisualScriptSelf::TypeGuess VisualScriptSelf::guess_output_type(TypeGuess *p_inputs, int p_output) const { - VisualScriptSceneNode::TypeGuess tg; tg.type = Variant::OBJECT; tg.gdclass = "Object"; Ref<Script> script = get_visual_script(); - if (!script.is_valid()) + if (!script.is_valid()) { return tg; + } tg.gdclass = script->get_instance_base_type(); tg.script = script; @@ -2926,7 +2745,6 @@ VisualScriptSelf::VisualScriptSelf() { ////////////////////////////////////////// int VisualScriptCustomNode::get_output_sequence_port_count() const { - if (get_script_instance() && get_script_instance()->has_method("_get_output_sequence_port_count")) { return get_script_instance()->call("_get_output_sequence_port_count"); } @@ -2934,7 +2752,6 @@ int VisualScriptCustomNode::get_output_sequence_port_count() const { } bool VisualScriptCustomNode::has_input_sequence_port() const { - if (get_script_instance() && get_script_instance()->has_method("_has_input_sequence_port")) { return get_script_instance()->call("_has_input_sequence_port"); } @@ -2942,14 +2759,13 @@ bool VisualScriptCustomNode::has_input_sequence_port() const { } int VisualScriptCustomNode::get_input_value_port_count() const { - if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_count")) { return get_script_instance()->call("_get_input_value_port_count"); } return 0; } -int VisualScriptCustomNode::get_output_value_port_count() const { +int VisualScriptCustomNode::get_output_value_port_count() const { if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_count")) { return get_script_instance()->call("_get_output_value_port_count"); } @@ -2957,7 +2773,6 @@ int VisualScriptCustomNode::get_output_value_port_count() const { } String VisualScriptCustomNode::get_output_sequence_port_text(int p_port) const { - if (get_script_instance() && get_script_instance()->has_method("_get_output_sequence_port_text")) { return get_script_instance()->call("_get_output_sequence_port_text", p_port); } @@ -2966,7 +2781,6 @@ String VisualScriptCustomNode::get_output_sequence_port_text(int p_port) const { } PropertyInfo VisualScriptCustomNode::get_input_value_port_info(int p_idx) const { - PropertyInfo info; if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_type")) { info.type = Variant::Type(int(get_script_instance()->call("_get_input_value_port_type", p_idx))); @@ -2978,7 +2792,6 @@ PropertyInfo VisualScriptCustomNode::get_input_value_port_info(int p_idx) const } PropertyInfo VisualScriptCustomNode::get_output_value_port_info(int p_idx) const { - PropertyInfo info; if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_type")) { info.type = Variant::Type(int(get_script_instance()->call("_get_output_value_port_type", p_idx))); @@ -2990,7 +2803,6 @@ PropertyInfo VisualScriptCustomNode::get_output_value_port_info(int p_idx) const } String VisualScriptCustomNode::get_caption() const { - if (get_script_instance() && get_script_instance()->has_method("_get_caption")) { return get_script_instance()->call("_get_caption"); } @@ -2998,7 +2810,6 @@ String VisualScriptCustomNode::get_caption() const { } String VisualScriptCustomNode::get_text() const { - if (get_script_instance() && get_script_instance()->has_method("_get_text")) { return get_script_instance()->call("_get_text"); } @@ -3006,7 +2817,6 @@ String VisualScriptCustomNode::get_text() const { } String VisualScriptCustomNode::get_category() const { - if (get_script_instance() && get_script_instance()->has_method("_get_category")) { return get_script_instance()->call("_get_category"); } @@ -3023,7 +2833,6 @@ public: virtual int get_working_memory_size() const { return work_mem_size; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (node->get_script_instance()) { #ifdef DEBUG_ENABLED if (!node->get_script_instance()->has_method(VisualScriptLanguage::singleton->_step)) { @@ -3085,7 +2894,6 @@ public: }; VisualScriptNodeInstance *VisualScriptCustomNode::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceCustomNode *instance = memnew(VisualScriptNodeInstanceCustomNode); instance->instance = p_instance; instance->node = this; @@ -3106,7 +2914,6 @@ void VisualScriptCustomNode::_script_changed() { } void VisualScriptCustomNode::_bind_methods() { - BIND_VMETHOD(MethodInfo(Variant::INT, "_get_output_sequence_port_count")); BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_input_sequence_port")); @@ -3150,42 +2957,35 @@ VisualScriptCustomNode::VisualScriptCustomNode() { ////////////////////////////////////////// int VisualScriptSubCall::get_output_sequence_port_count() const { - return 1; } bool VisualScriptSubCall::has_input_sequence_port() const { - return true; } int VisualScriptSubCall::get_input_value_port_count() const { - Ref<Script> script = get_script(); if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) { - MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall); return mi.arguments.size(); } return 0; } -int VisualScriptSubCall::get_output_value_port_count() const { +int VisualScriptSubCall::get_output_value_port_count() const { return 1; } String VisualScriptSubCall::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptSubCall::get_input_value_port_info(int p_idx) const { - Ref<Script> script = get_script(); if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) { - MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall); return mi.arguments[p_idx]; } @@ -3194,7 +2994,6 @@ PropertyInfo VisualScriptSubCall::get_input_value_port_info(int p_idx) const { } PropertyInfo VisualScriptSubCall::get_output_value_port_info(int p_idx) const { - Ref<Script> script = get_script(); if (script.is_valid() && script->has_method(VisualScriptLanguage::singleton->_subcall)) { MethodInfo mi = script->get_method_info(VisualScriptLanguage::singleton->_subcall); @@ -3204,25 +3003,24 @@ PropertyInfo VisualScriptSubCall::get_output_value_port_info(int p_idx) const { } String VisualScriptSubCall::get_caption() const { - return "SubCall"; } String VisualScriptSubCall::get_text() const { - Ref<Script> script = get_script(); if (script.is_valid()) { - if (script->get_name() != String()) + if (script->get_name() != String()) { return script->get_name(); - if (script->get_path().is_resource_file()) + } + if (script->get_path().is_resource_file()) { return script->get_path().get_file(); + } return script->get_class(); } return ""; } String VisualScriptSubCall::get_category() const { - return "custom"; } @@ -3236,7 +3034,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (!valid) { r_error_str = "Node requires a script with a _subcall(<args>) method to work."; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -3248,7 +3045,6 @@ public: }; VisualScriptNodeInstance *VisualScriptSubCall::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceSubCall *instance = memnew(VisualScriptNodeInstanceSubCall); instance->instance = p_instance; Ref<Script> script = get_script(); @@ -3262,7 +3058,6 @@ VisualScriptNodeInstance *VisualScriptSubCall::instance(VisualScriptInstance *p_ } void VisualScriptSubCall::_bind_methods() { - MethodInfo scmi(Variant::NIL, "_subcall", PropertyInfo(Variant::NIL, "arguments")); scmi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; BIND_VMETHOD(scmi); @@ -3276,87 +3071,78 @@ VisualScriptSubCall::VisualScriptSubCall() { ////////////////////////////////////////// int VisualScriptComment::get_output_sequence_port_count() const { - return 0; } bool VisualScriptComment::has_input_sequence_port() const { - return false; } int VisualScriptComment::get_input_value_port_count() const { return 0; } -int VisualScriptComment::get_output_value_port_count() const { +int VisualScriptComment::get_output_value_port_count() const { return 0; } String VisualScriptComment::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptComment::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptComment::get_output_value_port_info(int p_idx) const { - return PropertyInfo(); } String VisualScriptComment::get_caption() const { - return title; } String VisualScriptComment::get_text() const { - return description; } void VisualScriptComment::set_title(const String &p_title) { - - if (title == p_title) + if (title == p_title) { return; + } title = p_title; ports_changed_notify(); } String VisualScriptComment::get_title() const { - return title; } void VisualScriptComment::set_description(const String &p_description) { - - if (description == p_description) + if (description == p_description) { return; + } description = p_description; ports_changed_notify(); } -String VisualScriptComment::get_description() const { +String VisualScriptComment::get_description() const { return description; } void VisualScriptComment::set_size(const Size2 &p_size) { - - if (size == p_size) + if (size == p_size) { return; + } size = p_size; ports_changed_notify(); } -Size2 VisualScriptComment::get_size() const { +Size2 VisualScriptComment::get_size() const { return size; } String VisualScriptComment::get_category() const { - return "data"; } @@ -3367,20 +3153,17 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - return 0; } }; VisualScriptNodeInstance *VisualScriptComment::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceComment *instance = memnew(VisualScriptNodeInstanceComment); instance->instance = p_instance; return instance; } void VisualScriptComment::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_title", "title"), &VisualScriptComment::set_title); ClassDB::bind_method(D_METHOD("get_title"), &VisualScriptComment::get_title); @@ -3396,7 +3179,6 @@ void VisualScriptComment::_bind_methods() { } VisualScriptComment::VisualScriptComment() { - title = "Comment"; size = Size2(150, 150); } @@ -3406,70 +3188,60 @@ VisualScriptComment::VisualScriptComment() { ////////////////////////////////////////// int VisualScriptConstructor::get_output_sequence_port_count() const { - return 0; } bool VisualScriptConstructor::has_input_sequence_port() const { - return false; } int VisualScriptConstructor::get_input_value_port_count() const { return constructor.arguments.size(); } -int VisualScriptConstructor::get_output_value_port_count() const { +int VisualScriptConstructor::get_output_value_port_count() const { return 1; } String VisualScriptConstructor::get_output_sequence_port_text(int p_port) const { - return ""; } PropertyInfo VisualScriptConstructor::get_input_value_port_info(int p_idx) const { - return constructor.arguments[p_idx]; } PropertyInfo VisualScriptConstructor::get_output_value_port_info(int p_idx) const { - return PropertyInfo(type, "value"); } String VisualScriptConstructor::get_caption() const { - return "Construct " + Variant::get_type_name(type); } String VisualScriptConstructor::get_category() const { - return "functions"; } void VisualScriptConstructor::set_constructor_type(Variant::Type p_type) { - - if (type == p_type) + if (type == p_type) { return; + } type = p_type; ports_changed_notify(); } Variant::Type VisualScriptConstructor::get_constructor_type() const { - return type; } void VisualScriptConstructor::set_constructor(const Dictionary &p_info) { - constructor = MethodInfo::from_dict(p_info); ports_changed_notify(); } Dictionary VisualScriptConstructor::get_constructor() const { - return constructor; } @@ -3482,7 +3254,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - Callable::CallError ce; *p_outputs[0] = Variant::construct(type, p_inputs, argcount, ce); if (ce.error != Callable::CallError::CALL_OK) { @@ -3494,7 +3265,6 @@ public: }; VisualScriptNodeInstance *VisualScriptConstructor::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceConstructor *instance = memnew(VisualScriptNodeInstanceConstructor); instance->instance = p_instance; instance->type = type; @@ -3503,7 +3273,6 @@ VisualScriptNodeInstance *VisualScriptConstructor::instance(VisualScriptInstance } void VisualScriptConstructor::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_constructor_type", "type"), &VisualScriptConstructor::set_constructor_type); ClassDB::bind_method(D_METHOD("get_constructor_type"), &VisualScriptConstructor::get_constructor_type); @@ -3515,14 +3284,12 @@ void VisualScriptConstructor::_bind_methods() { } VisualScriptConstructor::VisualScriptConstructor() { - type = Variant::NIL; } static Map<String, Pair<Variant::Type, MethodInfo>> constructor_map; static Ref<VisualScriptNode> create_constructor_node(const String &p_name) { - ERR_FAIL_COND_V(!constructor_map.has(p_name), Ref<VisualScriptNode>()); Ref<VisualScriptConstructor> vsc; @@ -3538,69 +3305,60 @@ static Ref<VisualScriptNode> create_constructor_node(const String &p_name) { ////////////////////////////////////////// int VisualScriptLocalVar::get_output_sequence_port_count() const { - return 0; } bool VisualScriptLocalVar::has_input_sequence_port() const { - return false; } int VisualScriptLocalVar::get_input_value_port_count() const { return 0; } -int VisualScriptLocalVar::get_output_value_port_count() const { +int VisualScriptLocalVar::get_output_value_port_count() const { return 1; } String VisualScriptLocalVar::get_output_sequence_port_text(int p_port) const { - return ""; } PropertyInfo VisualScriptLocalVar::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } -PropertyInfo VisualScriptLocalVar::get_output_value_port_info(int p_idx) const { +PropertyInfo VisualScriptLocalVar::get_output_value_port_info(int p_idx) const { return PropertyInfo(type, name); } String VisualScriptLocalVar::get_caption() const { - return "Get Local Var"; } String VisualScriptLocalVar::get_category() const { - return "data"; } void VisualScriptLocalVar::set_var_name(const StringName &p_name) { - - if (name == p_name) + if (name == p_name) { return; + } name = p_name; ports_changed_notify(); } StringName VisualScriptLocalVar::get_var_name() const { - return name; } void VisualScriptLocalVar::set_var_type(Variant::Type p_type) { - type = p_type; ports_changed_notify(); } Variant::Type VisualScriptLocalVar::get_var_type() const { - return type; } @@ -3611,14 +3369,12 @@ public: virtual int get_working_memory_size() const { return 1; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_outputs[0] = *p_working_mem; return 0; } }; VisualScriptNodeInstance *VisualScriptLocalVar::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceLocalVar *instance = memnew(VisualScriptNodeInstanceLocalVar); instance->instance = p_instance; instance->name = name; @@ -3627,7 +3383,6 @@ VisualScriptNodeInstance *VisualScriptLocalVar::instance(VisualScriptInstance *p } void VisualScriptLocalVar::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_var_name", "name"), &VisualScriptLocalVar::set_var_name); ClassDB::bind_method(D_METHOD("get_var_name"), &VisualScriptLocalVar::get_var_name); @@ -3644,7 +3399,6 @@ void VisualScriptLocalVar::_bind_methods() { } VisualScriptLocalVar::VisualScriptLocalVar() { - name = "new_local"; type = Variant::NIL; } @@ -3654,74 +3408,64 @@ VisualScriptLocalVar::VisualScriptLocalVar() { ////////////////////////////////////////// int VisualScriptLocalVarSet::get_output_sequence_port_count() const { - return 1; } bool VisualScriptLocalVarSet::has_input_sequence_port() const { - return true; } int VisualScriptLocalVarSet::get_input_value_port_count() const { return 1; } -int VisualScriptLocalVarSet::get_output_value_port_count() const { +int VisualScriptLocalVarSet::get_output_value_port_count() const { return 1; } String VisualScriptLocalVarSet::get_output_sequence_port_text(int p_port) const { - return ""; } PropertyInfo VisualScriptLocalVarSet::get_input_value_port_info(int p_idx) const { - return PropertyInfo(type, "set"); } -PropertyInfo VisualScriptLocalVarSet::get_output_value_port_info(int p_idx) const { +PropertyInfo VisualScriptLocalVarSet::get_output_value_port_info(int p_idx) const { return PropertyInfo(type, "get"); } String VisualScriptLocalVarSet::get_caption() const { - return "Set Local Var"; } String VisualScriptLocalVarSet::get_text() const { - return name; } String VisualScriptLocalVarSet::get_category() const { - return "data"; } void VisualScriptLocalVarSet::set_var_name(const StringName &p_name) { - - if (name == p_name) + if (name == p_name) { return; + } name = p_name; ports_changed_notify(); } StringName VisualScriptLocalVarSet::get_var_name() const { - return name; } void VisualScriptLocalVarSet::set_var_type(Variant::Type p_type) { - type = p_type; ports_changed_notify(); } Variant::Type VisualScriptLocalVarSet::get_var_type() const { - return type; } @@ -3732,7 +3476,6 @@ public: virtual int get_working_memory_size() const { return 1; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - *p_working_mem = *p_inputs[0]; *p_outputs[0] = *p_working_mem; return 0; @@ -3740,7 +3483,6 @@ public: }; VisualScriptNodeInstance *VisualScriptLocalVarSet::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceLocalVarSet *instance = memnew(VisualScriptNodeInstanceLocalVarSet); instance->instance = p_instance; instance->name = name; @@ -3749,7 +3491,6 @@ VisualScriptNodeInstance *VisualScriptLocalVarSet::instance(VisualScriptInstance } void VisualScriptLocalVarSet::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_var_name", "name"), &VisualScriptLocalVarSet::set_var_name); ClassDB::bind_method(D_METHOD("get_var_name"), &VisualScriptLocalVarSet::get_var_name); @@ -3766,7 +3507,6 @@ void VisualScriptLocalVarSet::_bind_methods() { } VisualScriptLocalVarSet::VisualScriptLocalVarSet() { - name = "new_local"; type = Variant::NIL; } @@ -3776,34 +3516,30 @@ VisualScriptLocalVarSet::VisualScriptLocalVarSet() { ////////////////////////////////////////// int VisualScriptInputAction::get_output_sequence_port_count() const { - return 0; } bool VisualScriptInputAction::has_input_sequence_port() const { - return false; } int VisualScriptInputAction::get_input_value_port_count() const { return 0; } -int VisualScriptInputAction::get_output_value_port_count() const { +int VisualScriptInputAction::get_output_value_port_count() const { return 1; } String VisualScriptInputAction::get_output_sequence_port_text(int p_port) const { - return ""; } PropertyInfo VisualScriptInputAction::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } -PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) const { +PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) const { String mstr; switch (mode) { case MODE_PRESSED: { @@ -3824,39 +3560,36 @@ PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) cons } String VisualScriptInputAction::get_caption() const { - return "Action " + name; } String VisualScriptInputAction::get_category() const { - return "data"; } void VisualScriptInputAction::set_action_name(const StringName &p_name) { - - if (name == p_name) + if (name == p_name) { return; + } name = p_name; ports_changed_notify(); } StringName VisualScriptInputAction::get_action_name() const { - return name; } void VisualScriptInputAction::set_action_mode(Mode p_mode) { - - if (mode == p_mode) + if (mode == p_mode) { return; + } mode = p_mode; ports_changed_notify(); } -VisualScriptInputAction::Mode VisualScriptInputAction::get_action_mode() const { +VisualScriptInputAction::Mode VisualScriptInputAction::get_action_mode() const { return mode; } @@ -3867,7 +3600,6 @@ public: VisualScriptInputAction::Mode mode; virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - switch (mode) { case VisualScriptInputAction::MODE_PRESSED: { *p_outputs[0] = Input::get_singleton()->is_action_pressed(action); @@ -3888,7 +3620,6 @@ public: }; VisualScriptNodeInstance *VisualScriptInputAction::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceInputAction *instance = memnew(VisualScriptNodeInstanceInputAction); instance->instance = p_instance; instance->action = name; @@ -3898,9 +3629,7 @@ VisualScriptNodeInstance *VisualScriptInputAction::instance(VisualScriptInstance } void VisualScriptInputAction::_validate_property(PropertyInfo &property) const { - if (property.name == "action") { - property.hint = PROPERTY_HINT_ENUM; String actions; @@ -3911,8 +3640,9 @@ void VisualScriptInputAction::_validate_property(PropertyInfo &property) const { for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { const PropertyInfo &pi = E->get(); - if (!pi.name.begins_with("input/")) + if (!pi.name.begins_with("input/")) { continue; + } String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); @@ -3922,8 +3652,9 @@ void VisualScriptInputAction::_validate_property(PropertyInfo &property) const { al.sort(); for (int i = 0; i < al.size(); i++) { - if (actions != String()) + if (actions != String()) { actions += ","; + } actions += al[i]; } @@ -3932,7 +3663,6 @@ void VisualScriptInputAction::_validate_property(PropertyInfo &property) const { } void VisualScriptInputAction::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_action_name", "name"), &VisualScriptInputAction::set_action_name); ClassDB::bind_method(D_METHOD("get_action_name"), &VisualScriptInputAction::get_action_name); @@ -3949,7 +3679,6 @@ void VisualScriptInputAction::_bind_methods() { } VisualScriptInputAction::VisualScriptInputAction() { - name = ""; mode = MODE_PRESSED; } @@ -3959,60 +3688,51 @@ VisualScriptInputAction::VisualScriptInputAction() { ////////////////////////////////////////// int VisualScriptDeconstruct::get_output_sequence_port_count() const { - return 0; } bool VisualScriptDeconstruct::has_input_sequence_port() const { - return false; } int VisualScriptDeconstruct::get_input_value_port_count() const { return 1; } -int VisualScriptDeconstruct::get_output_value_port_count() const { +int VisualScriptDeconstruct::get_output_value_port_count() const { return elements.size(); } String VisualScriptDeconstruct::get_output_sequence_port_text(int p_port) const { - return ""; } PropertyInfo VisualScriptDeconstruct::get_input_value_port_info(int p_idx) const { - return PropertyInfo(type, "value"); } PropertyInfo VisualScriptDeconstruct::get_output_value_port_info(int p_idx) const { - return PropertyInfo(elements[p_idx].type, elements[p_idx].name); } String VisualScriptDeconstruct::get_caption() const { - return "Deconstruct " + Variant::get_type_name(type); } String VisualScriptDeconstruct::get_category() const { - return "functions"; } void VisualScriptDeconstruct::_update_elements() { - elements.clear(); Variant v; Callable::CallError ce; - v = Variant::construct(type, NULL, 0, ce); + v = Variant::construct(type, nullptr, 0, ce); List<PropertyInfo> pinfo; v.get_property_list(&pinfo); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - Element e; e.name = E->get().name; e.type = E->get().type; @@ -4021,9 +3741,9 @@ void VisualScriptDeconstruct::_update_elements() { } void VisualScriptDeconstruct::set_deconstruct_type(Variant::Type p_type) { - - if (type == p_type) + if (type == p_type) { return; + } type = p_type; _update_elements(); @@ -4032,12 +3752,10 @@ void VisualScriptDeconstruct::set_deconstruct_type(Variant::Type p_type) { } Variant::Type VisualScriptDeconstruct::get_deconstruct_type() const { - return type; } void VisualScriptDeconstruct::_set_elem_cache(const Array &p_elements) { - ERR_FAIL_COND(p_elements.size() % 2 == 1); elements.resize(p_elements.size() / 2); for (int i = 0; i < elements.size(); i++) { @@ -4047,7 +3765,6 @@ void VisualScriptDeconstruct::_set_elem_cache(const Array &p_elements) { } Array VisualScriptDeconstruct::_get_elem_cache() const { - Array ret; for (int i = 0; i < elements.size(); i++) { ret.push_back(elements[i].name); @@ -4064,7 +3781,6 @@ public: //virtual int get_working_memory_size() const { return 0; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - Variant in = *p_inputs[0]; for (int i = 0; i < outputs.size(); i++) { @@ -4082,7 +3798,6 @@ public: }; VisualScriptNodeInstance *VisualScriptDeconstruct::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceDeconstruct *instance = memnew(VisualScriptNodeInstanceDeconstruct); instance->instance = p_instance; instance->outputs.resize(elements.size()); @@ -4097,7 +3812,6 @@ void VisualScriptDeconstruct::_validate_property(PropertyInfo &property) const { } void VisualScriptDeconstruct::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_deconstruct_type", "type"), &VisualScriptDeconstruct::set_deconstruct_type); ClassDB::bind_method(D_METHOD("get_deconstruct_type"), &VisualScriptDeconstruct::get_deconstruct_type); @@ -4114,7 +3828,6 @@ void VisualScriptDeconstruct::_bind_methods() { } VisualScriptDeconstruct::VisualScriptDeconstruct() { - type = Variant::NIL; } @@ -4127,7 +3840,6 @@ static Ref<VisualScriptNode> create_node_deconst_typed(const String &p_name) { } void register_visual_script_nodes() { - VisualScriptLanguage::singleton->add_register_func("data/set_variable", create_node_generic<VisualScriptVariableSet>); VisualScriptLanguage::singleton->add_register_func("data/get_variable", create_node_generic<VisualScriptVariableGet>); VisualScriptLanguage::singleton->add_register_func("data/engine_singleton", create_node_generic<VisualScriptEngineSingleton>); @@ -4184,9 +3896,12 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("operators/logic/select", create_node_generic<VisualScriptSelect>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2), create_node_deconst_typed<Variant::Type::VECTOR2>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2I), create_node_deconst_typed<Variant::Type::VECTOR2I>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3), create_node_deconst_typed<Variant::Type::VECTOR3>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3I), create_node_deconst_typed<Variant::Type::VECTOR3I>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::COLOR), create_node_deconst_typed<Variant::Type::COLOR>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2), create_node_deconst_typed<Variant::Type::RECT2>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2I), create_node_deconst_typed<Variant::Type::RECT2I>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM2D), create_node_deconst_typed<Variant::Type::TRANSFORM2D>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PLANE), create_node_deconst_typed<Variant::Type::PLANE>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::QUAT), create_node_deconst_typed<Variant::Type::QUAT>); @@ -4196,12 +3911,10 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/compose_array", create_node_generic<VisualScriptComposeArray>); for (int i = 1; i < Variant::VARIANT_MAX; i++) { - List<MethodInfo> constructors; Variant::get_constructor_list(Variant::Type(i), &constructors); for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) { - if (E->get().arguments.size() > 0) { String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + "("; for (int j = 0; j < E->get().arguments.size(); j++) { @@ -4226,6 +3939,5 @@ void register_visual_script_nodes() { } void unregister_visual_script_nodes() { - constructor_map.clear(); } diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index 0df5071491..fa284b216c 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -34,7 +34,6 @@ #include "visual_script.h" class VisualScriptFunction : public VisualScriptNode { - GDCLASS(VisualScriptFunction, VisualScriptNode); struct Argument { @@ -104,7 +103,6 @@ public: }; class VisualScriptLists : public VisualScriptNode { - GDCLASS(VisualScriptLists, VisualScriptNode) struct Port { @@ -176,7 +174,6 @@ public: }; class VisualScriptComposeArray : public VisualScriptLists { - GDCLASS(VisualScriptComposeArray, VisualScriptLists) public: @@ -201,7 +198,6 @@ public: }; class VisualScriptOperator : public VisualScriptNode { - GDCLASS(VisualScriptOperator, VisualScriptNode); Variant::Type typed; @@ -237,7 +233,6 @@ public: }; class VisualScriptSelect : public VisualScriptNode { - GDCLASS(VisualScriptSelect, VisualScriptNode); Variant::Type typed; @@ -270,7 +265,6 @@ public: }; class VisualScriptVariableGet : public VisualScriptNode { - GDCLASS(VisualScriptVariableGet, VisualScriptNode); StringName variable; @@ -303,7 +297,6 @@ public: }; class VisualScriptVariableSet : public VisualScriptNode { - GDCLASS(VisualScriptVariableSet, VisualScriptNode); StringName variable; @@ -336,7 +329,6 @@ public: }; class VisualScriptConstant : public VisualScriptNode { - GDCLASS(VisualScriptConstant, VisualScriptNode); Variant::Type type; @@ -373,7 +365,6 @@ public: }; class VisualScriptPreload : public VisualScriptNode { - GDCLASS(VisualScriptPreload, VisualScriptNode); Ref<Resource> preload; @@ -405,7 +396,6 @@ public: }; class VisualScriptIndexGet : public VisualScriptNode { - GDCLASS(VisualScriptIndexGet, VisualScriptNode); public: @@ -429,7 +419,6 @@ public: }; class VisualScriptIndexSet : public VisualScriptNode { - GDCLASS(VisualScriptIndexSet, VisualScriptNode); public: @@ -453,7 +442,6 @@ public: }; class VisualScriptGlobalConstant : public VisualScriptNode { - GDCLASS(VisualScriptGlobalConstant, VisualScriptNode); int index; @@ -484,7 +472,6 @@ public: }; class VisualScriptClassConstant : public VisualScriptNode { - GDCLASS(VisualScriptClassConstant, VisualScriptNode); StringName base_type; @@ -521,7 +508,6 @@ public: }; class VisualScriptBasicTypeConstant : public VisualScriptNode { - GDCLASS(VisualScriptBasicTypeConstant, VisualScriptNode); Variant::Type type; @@ -559,7 +545,6 @@ public: }; class VisualScriptMathConstant : public VisualScriptNode { - GDCLASS(VisualScriptMathConstant, VisualScriptNode); public: @@ -609,7 +594,6 @@ public: VARIANT_ENUM_CAST(VisualScriptMathConstant::MathConstant) class VisualScriptEngineSingleton : public VisualScriptNode { - GDCLASS(VisualScriptEngineSingleton, VisualScriptNode); String singleton; @@ -645,7 +629,6 @@ public: }; class VisualScriptSceneNode : public VisualScriptNode { - GDCLASS(VisualScriptSceneNode, VisualScriptNode); NodePath path; @@ -680,7 +663,6 @@ public: }; class VisualScriptSceneTree : public VisualScriptNode { - GDCLASS(VisualScriptSceneTree, VisualScriptNode); protected: @@ -710,7 +692,6 @@ public: }; class VisualScriptResourcePath : public VisualScriptNode { - GDCLASS(VisualScriptResourcePath, VisualScriptNode); String path; @@ -742,7 +723,6 @@ public: }; class VisualScriptSelf : public VisualScriptNode { - GDCLASS(VisualScriptSelf, VisualScriptNode); protected: @@ -771,7 +751,6 @@ public: }; class VisualScriptCustomNode : public VisualScriptNode { - GDCLASS(VisualScriptCustomNode, VisualScriptNode); protected: @@ -819,7 +798,6 @@ public: VARIANT_ENUM_CAST(VisualScriptCustomNode::StartMode); class VisualScriptSubCall : public VisualScriptNode { - GDCLASS(VisualScriptSubCall, VisualScriptNode); protected: @@ -847,7 +825,6 @@ public: }; class VisualScriptComment : public VisualScriptNode { - GDCLASS(VisualScriptComment, VisualScriptNode); String title; @@ -888,7 +865,6 @@ public: }; class VisualScriptConstructor : public VisualScriptNode { - GDCLASS(VisualScriptConstructor, VisualScriptNode); Variant::Type type; @@ -924,7 +900,6 @@ public: }; class VisualScriptLocalVar : public VisualScriptNode { - GDCLASS(VisualScriptLocalVar, VisualScriptNode); StringName name; @@ -960,7 +935,6 @@ public: }; class VisualScriptLocalVarSet : public VisualScriptNode { - GDCLASS(VisualScriptLocalVarSet, VisualScriptNode); StringName name; @@ -997,7 +971,6 @@ public: }; class VisualScriptInputAction : public VisualScriptNode { - GDCLASS(VisualScriptInputAction, VisualScriptNode); public: @@ -1045,7 +1018,6 @@ public: VARIANT_ENUM_CAST(VisualScriptInputAction::Mode) class VisualScriptDeconstruct : public VisualScriptNode { - GDCLASS(VisualScriptDeconstruct, VisualScriptNode); struct Element { diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index d799f19143..f14c9ce49d 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -39,30 +39,28 @@ #include "modules/visual_script/visual_script_func_nodes.h" #include "modules/visual_script/visual_script_nodes.h" #include "scene/main/node.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" void VisualScriptPropertySelector::_text_changed(const String &p_newtext) { _update_search(); } void VisualScriptPropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) { - Ref<InputEventKey> k = p_ie; if (k.is_valid()) { - switch (k->get_keycode()) { case KEY_UP: case KEY_DOWN: case KEY_PAGEUP: case KEY_PAGEDOWN: { - search_options->call("_gui_input", k); search_box->accept_event(); TreeItem *root = search_options->get_root(); - if (!root->get_children()) + if (!root->get_children()) { break; + } TreeItem *current = search_options->get_selected(); @@ -97,37 +95,37 @@ void VisualScriptPropertySelector::_update_search() { for (List<StringName>::Element *E = base_list.front(); E; E = E->next()) { List<MethodInfo> methods; List<PropertyInfo> props; - TreeItem *category = NULL; + TreeItem *category = nullptr; Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { - Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("bool", "EditorIcons"), - Control::get_icon("int", "EditorIcons"), - Control::get_icon("float", "EditorIcons"), - Control::get_icon("String", "EditorIcons"), - Control::get_icon("Vector2", "EditorIcons"), - Control::get_icon("Rect2", "EditorIcons"), - Control::get_icon("Vector3", "EditorIcons"), - Control::get_icon("Transform2D", "EditorIcons"), - Control::get_icon("Plane", "EditorIcons"), - Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("AABB", "EditorIcons"), - Control::get_icon("Basis", "EditorIcons"), - Control::get_icon("Transform", "EditorIcons"), - Control::get_icon("Color", "EditorIcons"), - Control::get_icon("Path", "EditorIcons"), - Control::get_icon("RID", "EditorIcons"), - Control::get_icon("Object", "EditorIcons"), - Control::get_icon("Dictionary", "EditorIcons"), - Control::get_icon("Array", "EditorIcons"), - Control::get_icon("PackedByteArray", "EditorIcons"), - Control::get_icon("PackedInt32Array", "EditorIcons"), - Control::get_icon("PackedFloat32Array", "EditorIcons"), - Control::get_icon("PackedInt64Array", "EditorIcons"), - Control::get_icon("PackedFloat64Array", "EditorIcons"), - Control::get_icon("PackedStringArray", "EditorIcons"), - Control::get_icon("PackedVector2Array", "EditorIcons"), - Control::get_icon("PackedVector3Array", "EditorIcons"), - Control::get_icon("PackedColorArray", "EditorIcons") + vbc->get_theme_icon("Variant", "EditorIcons"), + vbc->get_theme_icon("bool", "EditorIcons"), + vbc->get_theme_icon("int", "EditorIcons"), + vbc->get_theme_icon("float", "EditorIcons"), + vbc->get_theme_icon("String", "EditorIcons"), + vbc->get_theme_icon("Vector2", "EditorIcons"), + vbc->get_theme_icon("Rect2", "EditorIcons"), + vbc->get_theme_icon("Vector3", "EditorIcons"), + vbc->get_theme_icon("Transform2D", "EditorIcons"), + vbc->get_theme_icon("Plane", "EditorIcons"), + vbc->get_theme_icon("Quat", "EditorIcons"), + vbc->get_theme_icon("AABB", "EditorIcons"), + vbc->get_theme_icon("Basis", "EditorIcons"), + vbc->get_theme_icon("Transform", "EditorIcons"), + vbc->get_theme_icon("Color", "EditorIcons"), + vbc->get_theme_icon("Path", "EditorIcons"), + vbc->get_theme_icon("RID", "EditorIcons"), + vbc->get_theme_icon("Object", "EditorIcons"), + vbc->get_theme_icon("Dictionary", "EditorIcons"), + vbc->get_theme_icon("Array", "EditorIcons"), + vbc->get_theme_icon("PackedByteArray", "EditorIcons"), + vbc->get_theme_icon("PackedInt32Array", "EditorIcons"), + vbc->get_theme_icon("PackedFloat32Array", "EditorIcons"), + vbc->get_theme_icon("PackedInt64Array", "EditorIcons"), + vbc->get_theme_icon("PackedFloat64Array", "EditorIcons"), + vbc->get_theme_icon("PackedStringArray", "EditorIcons"), + vbc->get_theme_icon("PackedVector2Array", "EditorIcons"), + vbc->get_theme_icon("PackedVector3Array", "EditorIcons"), + vbc->get_theme_icon("PackedColorArray", "EditorIcons") }; { String b = String(E->get()); @@ -153,11 +151,13 @@ void VisualScriptPropertySelector::_update_search() { } } for (List<PropertyInfo>::Element *F = props.front(); F; F = F->next()) { - if (!(F->get().usage & PROPERTY_USAGE_EDITOR) && !(F->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) + if (!(F->get().usage & PROPERTY_USAGE_EDITOR) && !(F->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) { continue; + } - if (type_filter.size() && type_filter.find(F->get().type) == -1) + if (type_filter.size() && type_filter.find(F->get().type) == -1) { continue; + } // capitalize() also converts underscore to space, we'll match again both possible styles String get_text_raw = String(vformat(TTR("Get %s"), F->get().name)); @@ -172,7 +172,7 @@ void VisualScriptPropertySelector::_update_search() { item->set_metadata(0, F->get().name); item->set_icon(0, type_icons[F->get().type]); item->set_metadata(1, "get"); - item->set_collapsed(1); + item->set_collapsed(true); item->set_selectable(0, true); item->set_selectable(1, false); item->set_selectable(2, false); @@ -196,10 +196,9 @@ void VisualScriptPropertySelector::_update_search() { if (type != Variant::NIL) { Variant v; Callable::CallError ce; - v = Variant::construct(type, NULL, 0, ce); + v = Variant::construct(type, nullptr, 0, ce); v.get_method_list(&methods); } else { - Object *obj = ObjectDB::get_instance(script); if (Object::cast_to<Script>(obj)) { Object::cast_to<Script>(obj)->get_script_method_list(&methods); @@ -209,23 +208,24 @@ void VisualScriptPropertySelector::_update_search() { } } for (List<MethodInfo>::Element *M = methods.front(); M; M = M->next()) { - String name = M->get().name.get_slice(":", 0); - if (name.begins_with("_") && !(M->get().flags & METHOD_FLAG_VIRTUAL)) + if (name.begins_with("_") && !(M->get().flags & METHOD_FLAG_VIRTUAL)) { continue; + } - if (virtuals_only && !(M->get().flags & METHOD_FLAG_VIRTUAL)) + if (virtuals_only && !(M->get().flags & METHOD_FLAG_VIRTUAL)) { continue; + } - if (!virtuals_only && (M->get().flags & METHOD_FLAG_VIRTUAL)) + if (!virtuals_only && (M->get().flags & METHOD_FLAG_VIRTUAL)) { continue; + } MethodInfo mi = M->get(); String desc_arguments; if (mi.arguments.size() > 0) { desc_arguments = "("; for (int i = 0; i < mi.arguments.size(); i++) { - if (i > 0) { desc_arguments += ", "; } @@ -252,19 +252,19 @@ void VisualScriptPropertySelector::_update_search() { TreeItem *item = search_options->create_item(category ? category : root); item->set_text(0, desc); - item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); + item->set_icon(0, vbc->get_theme_icon("MemberMethod", "EditorIcons")); item->set_metadata(0, name); item->set_selectable(0, true); item->set_metadata(1, "method"); - item->set_collapsed(1); + item->set_collapsed(true); item->set_selectable(1, false); item->set_selectable(2, false); item->set_metadata(2, connecting); } - if (category && category->get_children() == NULL) { + if (category && category->get_children() == nullptr) { memdelete(category); //old category was unused } } @@ -304,23 +304,23 @@ void VisualScriptPropertySelector::_update_search() { } TreeItem *selected_item = search_options->search_item_text(search_box->get_text()); - if (!found && selected_item != NULL) { + if (!found && selected_item != nullptr) { selected_item->select(0); found = true; } - get_ok()->set_disabled(root->get_children() == NULL); + get_ok()->set_disabled(root->get_children() == nullptr); } void VisualScriptPropertySelector::create_visualscript_item(const String &name, TreeItem *const root, const String &search_input, const String &text) { if (search_input == String() || text.findn(search_input) != -1) { TreeItem *item = search_options->create_item(root); item->set_text(0, text); - item->set_icon(0, get_icon("VisualScript", "EditorIcons")); + item->set_icon(0, vbc->get_theme_icon("VisualScript", "EditorIcons")); item->set_metadata(0, name); item->set_metadata(1, "action"); item->set_selectable(0, true); - item->set_collapsed(1); + item->set_collapsed(true); item->set_selectable(1, false); item->set_selectable(2, false); item->set_metadata(2, connecting); @@ -359,8 +359,9 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt bool in_modifier = p_modifiers.empty(); for (Set<String>::Element *F = p_modifiers.front(); F && in_modifier; F = F->next()) { - if (E->get().findn(F->get()) != -1) + if (E->get().findn(F->get()) != -1) { in_modifier = true; + } } if (!in_modifier) { continue; @@ -399,7 +400,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt } item->set_text(0, type_name + String("").join(desc)); - item->set_icon(0, get_icon("VisualScript", "EditorIcons")); + item->set_icon(0, vbc->get_theme_icon("VisualScript", "EditorIcons")); item->set_selectable(0, true); item->set_metadata(0, E->get()); item->set_selectable(0, true); @@ -411,21 +412,21 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt } void VisualScriptPropertySelector::_confirmed() { - TreeItem *ti = search_options->get_selected(); - if (!ti) + if (!ti) { return; + } emit_signal("selected", ti->get_metadata(0), ti->get_metadata(1), ti->get_metadata(2)); - hide(); + set_visible(false); } void VisualScriptPropertySelector::_item_selected() { - help_bit->set_text(""); TreeItem *item = search_options->get_selected(); - if (!item) + if (!item) { return; + } String name = item->get_metadata(0); String class_type; @@ -442,7 +443,6 @@ void VisualScriptPropertySelector::_item_selected() { String at_class = class_type; while (at_class != String()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(at_class); if (E) { for (int i = 0; i < E->get().properties.size(); i++) { @@ -457,7 +457,6 @@ void VisualScriptPropertySelector::_item_selected() { at_class = class_type; while (at_class != String()) { - Map<String, DocData::ClassDoc>::Element *C = dd->class_list.find(at_class); if (C) { for (int i = 0; i < C->get().methods.size(); i++) { @@ -481,7 +480,7 @@ void VisualScriptPropertySelector::_item_selected() { List<String> *names = memnew(List<String>); VisualScriptLanguage::singleton->get_registered_node_names(names); - if (names->find(name) != NULL) { + if (names->find(name) != nullptr) { Ref<VisualScriptOperator> operator_node = VisualScriptLanguage::singleton->create_node_from_name(name); if (operator_node.is_valid()) { Map<String, DocData::ClassDoc>::Element *F = dd->class_list.find(operator_node->get_class_name()); @@ -512,38 +511,37 @@ void VisualScriptPropertySelector::_item_selected() { memdelete(names); - if (text == String()) + if (text == String()) { return; + } help_bit->set_text(text); } void VisualScriptPropertySelector::_hide_requested() { - _closed(); // From WindowDialog. + _cancel_pressed(); // From AcceptDialog. } void VisualScriptPropertySelector::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - connect("confirmed", callable_mp(this, &VisualScriptPropertySelector::_confirmed)); } } void VisualScriptPropertySelector::select_method_from_base_type(const String &p_base, const String &p_current, const bool p_virtuals_only, const bool p_connecting, bool clear_text) { - base_type = p_base; selected = p_current; type = Variant::NIL; properties = false; - instance = NULL; + instance = nullptr; virtuals_only = p_virtuals_only; show_window(.5f); - if (clear_text) + if (clear_text) { search_box->set_text(""); - else + } else { search_box->select_all(); + } search_box->grab_focus(); connecting = p_connecting; @@ -555,20 +553,20 @@ void VisualScriptPropertySelector::set_type_filter(const Vector<Variant::Type> & } void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_current, bool p_virtuals_only, bool p_seq_connect, const bool p_connecting, bool clear_text) { - base_type = p_base; selected = p_current; type = Variant::NIL; properties = true; visual_script_generic = false; - instance = NULL; + instance = nullptr; virtuals_only = p_virtuals_only; show_window(.5f); - if (clear_text) + if (clear_text) { search_box->set_text(""); - else + } else { search_box->select_all(); + } search_box->grab_focus(); seq_connect = p_seq_connect; connecting = p_connecting; @@ -585,14 +583,15 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip script = p_script->get_instance_id(); properties = true; visual_script_generic = false; - instance = NULL; + instance = nullptr; virtuals_only = false; show_window(.5f); - if (clear_text) + if (clear_text) { search_box->set_text(""); - else + } else { search_box->select_all(); + } search_box->grab_focus(); seq_connect = false; connecting = p_connecting; @@ -607,14 +606,15 @@ void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, type = p_type; properties = true; visual_script_generic = false; - instance = NULL; + instance = nullptr; virtuals_only = false; show_window(.5f); - if (clear_text) + if (clear_text) { search_box->set_text(""); - else + } else { search_box->select_all(); + } search_box->grab_focus(); seq_connect = false; connecting = p_connecting; @@ -628,14 +628,15 @@ void VisualScriptPropertySelector::select_from_action(const String &p_type, cons type = Variant::NIL; properties = false; visual_script_generic = false; - instance = NULL; + instance = nullptr; virtuals_only = false; show_window(.5f); - if (clear_text) + if (clear_text) { search_box->set_text(""); - else + } else { search_box->select_all(); + } search_box->grab_focus(); seq_connect = true; connecting = p_connecting; @@ -653,10 +654,11 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons virtuals_only = false; show_window(.5f); - if (clear_text) + if (clear_text) { search_box->set_text(""); - else + } else { search_box->select_all(); + } search_box->grab_focus(); seq_connect = false; connecting = p_connecting; @@ -670,13 +672,14 @@ void VisualScriptPropertySelector::select_from_visual_script(const String &p_bas type = Variant::NIL; properties = true; visual_script_generic = true; - instance = NULL; + instance = nullptr; virtuals_only = false; show_window(.5f); - if (clear_text) + if (clear_text) { search_box->set_text(""); - else + } else { search_box->select_all(); + } search_box->grab_focus(); connecting = p_connecting; @@ -684,22 +687,15 @@ void VisualScriptPropertySelector::select_from_visual_script(const String &p_bas } void VisualScriptPropertySelector::show_window(float p_screen_ratio) { - Rect2 rect; - Point2 window_size = get_viewport_rect().size; - rect.size = (window_size * p_screen_ratio).floor(); - rect.size.x = rect.size.x / 2.2f; - rect.position = ((window_size - rect.size) / 2.0f).floor(); - popup(rect); + popup_centered_ratio(p_screen_ratio); } void VisualScriptPropertySelector::_bind_methods() { - ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "category"), PropertyInfo(Variant::BOOL, "connecting"))); } VisualScriptPropertySelector::VisualScriptPropertySelector() { - - VBoxContainer *vbc = memnew(VBoxContainer); + vbc = memnew(VBoxContainer); add_child(vbc); //set_child_rect(vbc); search_box = memnew(LineEdit); diff --git a/modules/visual_script/visual_script_property_selector.h b/modules/visual_script/visual_script_property_selector.h index f438ca1f5b..cc49b2863d 100644 --- a/modules/visual_script/visual_script_property_selector.h +++ b/modules/visual_script/visual_script_property_selector.h @@ -64,6 +64,7 @@ class VisualScriptPropertySelector : public ConfirmationDialog { Object *instance; bool virtuals_only; bool seq_connect; + VBoxContainer *vbc; Vector<Variant::Type> type_filter; diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index 858074742e..dd07cc45a7 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -40,51 +40,51 @@ ////////////////////////////////////////// int VisualScriptYield::get_output_sequence_port_count() const { - return 1; } bool VisualScriptYield::has_input_sequence_port() const { - return true; } int VisualScriptYield::get_input_value_port_count() const { - return 0; } -int VisualScriptYield::get_output_value_port_count() const { +int VisualScriptYield::get_output_value_port_count() const { return 0; } String VisualScriptYield::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptYield::get_input_value_port_info(int p_idx) const { - return PropertyInfo(); } PropertyInfo VisualScriptYield::get_output_value_port_info(int p_idx) const { - return PropertyInfo(); } String VisualScriptYield::get_caption() const { - return yield_mode == YIELD_RETURN ? "Yield" : "Wait"; } String VisualScriptYield::get_text() const { - switch (yield_mode) { - case YIELD_RETURN: return ""; break; - case YIELD_FRAME: return "Next Frame"; break; - case YIELD_PHYSICS_FRAME: return "Next Physics Frame"; break; - case YIELD_WAIT: return rtos(wait_time) + " sec(s)"; break; + case YIELD_RETURN: + return ""; + break; + case YIELD_FRAME: + return "Next Frame"; + break; + case YIELD_PHYSICS_FRAME: + return "Next Physics Frame"; + break; + case YIELD_WAIT: + return rtos(wait_time) + " sec(s)"; + break; } return String(); @@ -100,7 +100,6 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return false; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (p_start_mode == START_MODE_RESUME_YIELD) { return 0; //resuming yield } else { @@ -118,13 +117,18 @@ public: int ret = STEP_YIELD_BIT; switch (mode) { - case VisualScriptYield::YIELD_RETURN: ret = STEP_EXIT_FUNCTION_BIT; break; //return the yield - case VisualScriptYield::YIELD_FRAME: state->connect_to_signal(tree, "idle_frame", Array()); break; - case VisualScriptYield::YIELD_PHYSICS_FRAME: state->connect_to_signal(tree, "physics_frame", Array()); break; - case VisualScriptYield::YIELD_WAIT: state->connect_to_signal(tree->create_timer(wait_time).ptr(), "timeout", Array()); break; + case VisualScriptYield::YIELD_FRAME: + state->connect_to_signal(tree, "idle_frame", Array()); + break; + case VisualScriptYield::YIELD_PHYSICS_FRAME: + state->connect_to_signal(tree, "physics_frame", Array()); + break; + case VisualScriptYield::YIELD_WAIT: + state->connect_to_signal(tree->create_timer(wait_time).ptr(), "timeout", Array()); + break; } *p_working_mem = state; @@ -135,7 +139,6 @@ public: }; VisualScriptNodeInstance *VisualScriptYield::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceYield *instance = memnew(VisualScriptNodeInstanceYield); //instance->instance=p_instance; instance->mode = yield_mode; @@ -144,34 +147,31 @@ VisualScriptNodeInstance *VisualScriptYield::instance(VisualScriptInstance *p_in } void VisualScriptYield::set_yield_mode(YieldMode p_mode) { - - if (yield_mode == p_mode) + if (yield_mode == p_mode) { return; + } yield_mode = p_mode; ports_changed_notify(); _change_notify(); } VisualScriptYield::YieldMode VisualScriptYield::get_yield_mode() { - return yield_mode; } void VisualScriptYield::set_wait_time(float p_time) { - - if (wait_time == p_time) + if (wait_time == p_time) { return; + } wait_time = p_time; ports_changed_notify(); } float VisualScriptYield::get_wait_time() { - return wait_time; } void VisualScriptYield::_validate_property(PropertyInfo &property) const { - if (property.name == "wait_time") { if (yield_mode != YIELD_WAIT) { property.usage = 0; @@ -180,7 +180,6 @@ void VisualScriptYield::_validate_property(PropertyInfo &property) const { } void VisualScriptYield::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_yield_mode", "mode"), &VisualScriptYield::set_yield_mode); ClassDB::bind_method(D_METHOD("get_yield_mode"), &VisualScriptYield::get_yield_mode); @@ -196,14 +195,12 @@ void VisualScriptYield::_bind_methods() { } VisualScriptYield::VisualScriptYield() { - yield_mode = YIELD_FRAME; wait_time = 1; } template <VisualScriptYield::YieldMode MODE> static Ref<VisualScriptNode> create_yield_node(const String &p_name) { - Ref<VisualScriptYield> node; node.instance(); node->set_yield_mode(MODE); @@ -215,126 +212,129 @@ static Ref<VisualScriptNode> create_yield_node(const String &p_name) { ////////////////////////////////////////////////// int VisualScriptYieldSignal::get_output_sequence_port_count() const { - return 1; } bool VisualScriptYieldSignal::has_input_sequence_port() const { - return true; } #ifdef TOOLS_ENABLED static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const Ref<Script> &script) { - - if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene) - return NULL; + if (p_edited_scene != p_current_node && p_current_node->get_owner() != p_edited_scene) { + return nullptr; + } Ref<Script> scr = p_current_node->get_script(); - if (scr.is_valid() && scr == script) + if (scr.is_valid() && scr == script) { return p_current_node; + } for (int i = 0; i < p_current_node->get_child_count(); i++) { Node *n = _find_script_node(p_edited_scene, p_current_node->get_child(i), script); - if (n) + if (n) { return n; + } } - return NULL; + return nullptr; } #endif Node *VisualScriptYieldSignal::_get_base_node() const { - #ifdef TOOLS_ENABLED Ref<Script> script = get_visual_script(); - if (!script.is_valid()) - return NULL; + if (!script.is_valid()) { + return nullptr; + } MainLoop *main_loop = OS::get_singleton()->get_main_loop(); SceneTree *scene_tree = Object::cast_to<SceneTree>(main_loop); - if (!scene_tree) - return NULL; + if (!scene_tree) { + return nullptr; + } Node *edited_scene = scene_tree->get_edited_scene_root(); - if (!edited_scene) - return NULL; + if (!edited_scene) { + return nullptr; + } Node *script_node = _find_script_node(edited_scene, edited_scene, script); - if (!script_node) - return NULL; + if (!script_node) { + return nullptr; + } - if (!script_node->has_node(base_path)) - return NULL; + if (!script_node->has_node(base_path)) { + return nullptr; + } Node *path_to = script_node->get_node(base_path); return path_to; #else - return NULL; + return nullptr; #endif } StringName VisualScriptYieldSignal::_get_base_type() const { - - if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) + if (call_mode == CALL_MODE_SELF && get_visual_script().is_valid()) { return get_visual_script()->get_instance_base_type(); - else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { + } else if (call_mode == CALL_MODE_NODE_PATH && get_visual_script().is_valid()) { Node *path = _get_base_node(); - if (path) + if (path) { return path->get_class(); + } } return base_type; } int VisualScriptYieldSignal::get_input_value_port_count() const { - - if (call_mode == CALL_MODE_INSTANCE) + if (call_mode == CALL_MODE_INSTANCE) { return 1; - else + } else { return 0; + } } -int VisualScriptYieldSignal::get_output_value_port_count() const { +int VisualScriptYieldSignal::get_output_value_port_count() const { MethodInfo sr; - if (!ClassDB::get_signal(_get_base_type(), signal, &sr)) + if (!ClassDB::get_signal(_get_base_type(), signal, &sr)) { return 0; + } return sr.arguments.size(); } String VisualScriptYieldSignal::get_output_sequence_port_text(int p_port) const { - return String(); } PropertyInfo VisualScriptYieldSignal::get_input_value_port_info(int p_idx) const { - - if (call_mode == CALL_MODE_INSTANCE) + if (call_mode == CALL_MODE_INSTANCE) { return PropertyInfo(Variant::OBJECT, "instance"); - else + } else { return PropertyInfo(); + } } PropertyInfo VisualScriptYieldSignal::get_output_value_port_info(int p_idx) const { - MethodInfo sr; - if (!ClassDB::get_signal(_get_base_type(), signal, &sr)) + if (!ClassDB::get_signal(_get_base_type(), signal, &sr)) { return PropertyInfo(); //no signal + } ERR_FAIL_INDEX_V(p_idx, sr.arguments.size(), PropertyInfo()); return sr.arguments[p_idx]; } String VisualScriptYieldSignal::get_caption() const { - static const char *cname[3] = { "WaitSignal", "WaitNodeSignal", @@ -345,17 +345,17 @@ String VisualScriptYieldSignal::get_caption() const { } String VisualScriptYieldSignal::get_text() const { - - if (call_mode == CALL_MODE_SELF) + if (call_mode == CALL_MODE_SELF) { return " " + String(signal) + "()"; - else + } else { return " " + _get_base_type() + "." + String(signal) + "()"; + } } void VisualScriptYieldSignal::set_base_type(const StringName &p_type) { - - if (base_type == p_type) + if (base_type == p_type) { return; + } base_type = p_type; @@ -364,29 +364,28 @@ void VisualScriptYieldSignal::set_base_type(const StringName &p_type) { } StringName VisualScriptYieldSignal::get_base_type() const { - return base_type; } void VisualScriptYieldSignal::set_signal(const StringName &p_type) { - - if (signal == p_type) + if (signal == p_type) { return; + } signal = p_type; _change_notify(); ports_changed_notify(); } -StringName VisualScriptYieldSignal::get_signal() const { +StringName VisualScriptYieldSignal::get_signal() const { return signal; } void VisualScriptYieldSignal::set_base_path(const NodePath &p_type) { - - if (base_path == p_type) + if (base_path == p_type) { return; + } base_path = p_type; @@ -395,14 +394,13 @@ void VisualScriptYieldSignal::set_base_path(const NodePath &p_type) { } NodePath VisualScriptYieldSignal::get_base_path() const { - return base_path; } void VisualScriptYieldSignal::set_call_mode(CallMode p_mode) { - - if (call_mode == p_mode) + if (call_mode == p_mode) { return; + } call_mode = p_mode; @@ -411,12 +409,10 @@ void VisualScriptYieldSignal::set_call_mode(CallMode p_mode) { } VisualScriptYieldSignal::CallMode VisualScriptYieldSignal::get_call_mode() const { - return call_mode; } void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { - if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = PROPERTY_USAGE_NOEDITOR; @@ -427,7 +423,6 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { if (call_mode != CALL_MODE_NODE_PATH) { property.usage = 0; } else { - Node *bnode = _get_base_node(); if (bnode) { property.hint_string = bnode->get_path(); //convert to loong string @@ -444,8 +439,9 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { List<String> mstring; for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { - if (E->get().name.begins_with("_")) + if (E->get().name.begins_with("_")) { continue; + } mstring.push_back(E->get().name.get_slice(":", 0)); } @@ -453,9 +449,9 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { String ml; for (List<String>::Element *E = mstring.front(); E; E = E->next()) { - - if (ml != String()) + if (ml != String()) { ml += ","; + } ml += E->get(); } @@ -464,7 +460,6 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { } void VisualScriptYieldSignal::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_base_type", "base_type"), &VisualScriptYieldSignal::set_base_type); ClassDB::bind_method(D_METHOD("get_base_type"), &VisualScriptYieldSignal::get_base_type); @@ -479,8 +474,9 @@ void VisualScriptYieldSignal::_bind_methods() { String bt; for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (i > 0) + if (i > 0) { bt += ","; + } bt += Variant::get_type_name(Variant::Type(i)); } @@ -510,23 +506,19 @@ public: //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) { - if (p_start_mode == START_MODE_RESUME_YIELD) { return 0; //resuming yield } else { //yield - Object *object = NULL; + Object *object = nullptr; switch (call_mode) { - case VisualScriptYieldSignal::CALL_MODE_SELF: { - object = instance->get_owner_ptr(); } break; case VisualScriptYieldSignal::CALL_MODE_NODE_PATH: { - Node *node = Object::cast_to<Node>(instance->get_owner_ptr()); if (!node) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -545,7 +537,6 @@ public: } break; case VisualScriptYieldSignal::CALL_MODE_INSTANCE: { - object = *p_inputs[0]; if (!object) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; @@ -569,7 +560,6 @@ public: }; VisualScriptNodeInstance *VisualScriptYieldSignal::instance(VisualScriptInstance *p_instance) { - VisualScriptNodeInstanceYieldSignal *instance = memnew(VisualScriptNodeInstanceYieldSignal); instance->node = this; instance->instance = p_instance; @@ -579,15 +569,14 @@ VisualScriptNodeInstance *VisualScriptYieldSignal::instance(VisualScriptInstance instance->output_args = get_output_value_port_count(); return instance; } -VisualScriptYieldSignal::VisualScriptYieldSignal() { +VisualScriptYieldSignal::VisualScriptYieldSignal() { call_mode = CALL_MODE_SELF; base_type = "Object"; } template <VisualScriptYieldSignal::CallMode cmode> static Ref<VisualScriptNode> create_yield_signal_node(const String &p_name) { - Ref<VisualScriptYieldSignal> node; node.instance(); node->set_call_mode(cmode); @@ -595,7 +584,6 @@ static Ref<VisualScriptNode> create_yield_signal_node(const String &p_name) { } void register_visual_script_yield_nodes() { - VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_frame", create_yield_node<VisualScriptYield::YIELD_FRAME>); VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_physics_frame", create_yield_node<VisualScriptYield::YIELD_PHYSICS_FRAME>); VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_time", create_yield_node<VisualScriptYield::YIELD_WAIT>); diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h index 4b976bd6c6..4877e8b7e6 100644 --- a/modules/visual_script/visual_script_yield_nodes.h +++ b/modules/visual_script/visual_script_yield_nodes.h @@ -34,7 +34,6 @@ #include "visual_script.h" class VisualScriptYield : public VisualScriptNode { - GDCLASS(VisualScriptYield, VisualScriptNode); public: @@ -84,7 +83,6 @@ public: VARIANT_ENUM_CAST(VisualScriptYield::YieldMode) class VisualScriptYieldSignal : public VisualScriptNode { - GDCLASS(VisualScriptYieldSignal, VisualScriptNode); public: diff --git a/modules/vorbis/SCsub b/modules/vorbis/SCsub index bde4359595..05d46757d3 100644 --- a/modules/vorbis/SCsub +++ b/modules/vorbis/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") # Only kept to build the thirdparty library used by the theora and webm # modules. We now use stb_vorbis for AudioStreamOGGVorbis. @@ -11,11 +11,11 @@ env_vorbis = env_modules.Clone() stub = True # Thirdparty source files -if env['builtin_libvorbis']: +if env["builtin_libvorbis"]: thirdparty_dir = "#thirdparty/libvorbis/" thirdparty_sources = [ - #"analysis.c", - #"barkmel.c", + # "analysis.c", + # "barkmel.c", "bitrate.c", "block.c", "codebook.c", @@ -29,14 +29,14 @@ if env['builtin_libvorbis']: "mapping0.c", "mdct.c", "psy.c", - #"psytune.c", + # "psytune.c", "registry.c", "res0.c", "sharedbook.c", "smallft.c", "synthesis.c", - #"tone.c", - #"vorbisenc.c", + # "tone.c", + # "vorbisenc.c", "vorbisfile.c", "window.c", ] @@ -46,7 +46,7 @@ if env['builtin_libvorbis']: env_vorbis.Prepend(CPPPATH=[thirdparty_dir]) # also requires libogg - if env['builtin_libogg']: + if env["builtin_libogg"]: env_vorbis.Prepend(CPPPATH=["#thirdparty/libogg"]) env_thirdparty = env_vorbis.Clone() diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/vorbis/config.py +++ b/modules/vorbis/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/vorbis/register_types.h b/modules/vorbis/register_types.h index 83d4904a87..7fa0dfdeef 100644 --- a/modules/vorbis/register_types.h +++ b/modules/vorbis/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef VORBIS_REGISTER_TYPES_H +#define VORBIS_REGISTER_TYPES_H + void register_vorbis_types(); void unregister_vorbis_types(); + +#endif // VORBIS_REGISTER_TYPES_H diff --git a/modules/webm/SCsub b/modules/webm/SCsub index 32e6727656..247b4ead37 100644 --- a/modules/webm/SCsub +++ b/modules/webm/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_webm = env_modules.Clone() @@ -18,14 +18,14 @@ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] env_webm.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "libwebm/"]) # also requires libogg, libvorbis and libopus -if env['builtin_libogg']: +if env["builtin_libogg"]: env_webm.Prepend(CPPPATH=["#thirdparty/libogg"]) -if env['builtin_libvorbis']: +if env["builtin_libvorbis"]: env_webm.Prepend(CPPPATH=["#thirdparty/libvorbis"]) -if env['builtin_opus']: +if env["builtin_opus"]: env_webm.Prepend(CPPPATH=["#thirdparty/opus"]) -if env['builtin_libvpx']: +if env["builtin_libvpx"]: env_webm.Prepend(CPPPATH=["#thirdparty/libvpx"]) SConscript("libvpx/SCsub") diff --git a/modules/webm/config.py b/modules/webm/config.py index ba4dcce2f5..93b49d177a 100644 --- a/modules/webm/config.py +++ b/modules/webm/config.py @@ -1,13 +1,16 @@ def can_build(env, platform): - return platform not in ['iphone'] + return platform not in ["iphone"] + def configure(env): pass + def get_doc_classes(): return [ "VideoStreamWebm", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub index 14fa6c1268..dd6866ad0e 100644 --- a/modules/webm/libvpx/SCsub +++ b/modules/webm/libvpx/SCsub @@ -1,7 +1,7 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") # Thirdparty sources @@ -9,9 +9,7 @@ libvpx_dir = "#thirdparty/libvpx/" libvpx_sources = [ "vp8/vp8_dx_iface.c", - "vp8/common/generic/systemdependent.c", - "vp8/common/alloccommon.c", "vp8/common/blockd.c", "vp8/common/copy_c.c", @@ -37,16 +35,12 @@ libvpx_sources = [ "vp8/common/swapyv12buffer.c", "vp8/common/treecoder.c", "vp8/common/vp8_loopfilter.c", - "vp8/decoder/dboolhuff.c", "vp8/decoder/decodeframe.c", "vp8/decoder/decodemv.c", "vp8/decoder/detokenize.c", "vp8/decoder/onyxd_if.c", - - "vp9/vp9_dx_iface.c", - "vp9/common/vp9_alloccommon.c", "vp9/common/vp9_blockd.c", "vp9/common/vp9_common_data.c", @@ -69,21 +63,16 @@ libvpx_sources = [ "vp9/common/vp9_seg_common.c", "vp9/common/vp9_thread_common.c", "vp9/common/vp9_tile_common.c", - "vp9/decoder/vp9_decodeframe.c", "vp9/decoder/vp9_decodemv.c", "vp9/decoder/vp9_decoder.c", "vp9/decoder/vp9_detokenize.c", "vp9/decoder/vp9_dsubexp.c", "vp9/decoder/vp9_dthread.c", - - "vpx/src/vpx_codec.c", "vpx/src/vpx_decoder.c", "vpx/src/vpx_image.c", "vpx/src/vpx_psnr.c", - - "vpx_dsp/bitreader.c", "vpx_dsp/bitreader_buffer.c", "vpx_dsp/intrapred.c", @@ -92,18 +81,11 @@ libvpx_sources = [ "vpx_dsp/prob.c", "vpx_dsp/vpx_convolve.c", "vpx_dsp/vpx_dsp_rtcd.c", - - "vpx_mem/vpx_mem.c", - - "vpx_scale/vpx_scale_rtcd.c", - "vpx_scale/generic/yv12config.c", "vpx_scale/generic/yv12extend.c", - - - "vpx_util/vpx_thread.c" + "vpx_util/vpx_thread.c", ] libvpx_sources_mt = [ @@ -114,29 +96,23 @@ libvpx_sources_intrin_x86 = [ "vp8/common/x86/filter_x86.c", "vp8/common/x86/loopfilter_x86.c", "vp8/common/x86/vp8_asm_stubs.c", - - - "vpx_dsp/x86/vpx_asm_stubs.c" + "vpx_dsp/x86/vpx_asm_stubs.c", ] libvpx_sources_intrin_x86_mmx = [ "vp8/common/x86/idct_blk_mmx.c", ] libvpx_sources_intrin_x86_sse2 = [ "vp8/common/x86/idct_blk_sse2.c", - - "vp9/common/x86/vp9_idct_intrin_sse2.c", - - "vpx_dsp/x86/inv_txfm_sse2.c", "vpx_dsp/x86/loopfilter_sse2.c", ] libvpx_sources_intrin_x86_ssse3 = [ - "vpx_dsp/x86/vpx_subpixel_8t_intrin_ssse3.c" + "vpx_dsp/x86/vpx_subpixel_8t_intrin_ssse3.c", ] libvpx_sources_intrin_x86_avx2 = [ "vpx_dsp/x86/loopfilter_avx2.c", - "vpx_dsp/x86/vpx_subpixel_8t_intrin_avx2.c" + "vpx_dsp/x86/vpx_subpixel_8t_intrin_avx2.c", ] libvpx_sources_x86asm = [ "vp8/common/x86/copy_sse2.asm", @@ -153,8 +129,6 @@ libvpx_sources_x86asm = [ "vp8/common/x86/subpixel_sse2.asm", "vp8/common/x86/subpixel_ssse3.asm", "vp8/common/x86/vp8_loopfilter_mmx.asm", - - "vpx_dsp/x86/intrapred_sse2.asm", "vpx_dsp/x86/intrapred_ssse3.asm", "vpx_dsp/x86/inv_wht_sse2.asm", @@ -163,21 +137,15 @@ libvpx_sources_x86asm = [ "vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm", "vpx_dsp/x86/vpx_subpixel_bilinear_sse2.asm", "vpx_dsp/x86/vpx_subpixel_bilinear_ssse3.asm", - - - "vpx_ports/emms.asm" + "vpx_ports/emms.asm", ] libvpx_sources_x86_64asm = [ "vp8/common/x86/loopfilter_block_sse2_x86_64.asm", - - - "vpx_dsp/x86/inv_txfm_ssse3_x86_64.asm" + "vpx_dsp/x86/inv_txfm_ssse3_x86_64.asm", ] libvpx_sources_arm = [ "vpx_ports/arm_cpudetect.c", - - "vp8/common/arm/loopfilter_arm.c", ] libvpx_sources_arm_neon = [ @@ -196,12 +164,8 @@ libvpx_sources_arm_neon = [ "vp8/common/arm/neon/shortidct4x4llm_neon.c", "vp8/common/arm/neon/sixtappredict_neon.c", "vp8/common/arm/neon/vp8_loopfilter_neon.c", - - "vp9/common/arm/neon/vp9_iht4x4_add_neon.c", "vp9/common/arm/neon/vp9_iht8x8_add_neon.c", - - "vpx_dsp/arm/idct16x16_1_add_neon.c", "vpx_dsp/arm/idct16x16_add_neon.c", "vpx_dsp/arm/idct16x16_neon.c", @@ -220,22 +184,22 @@ libvpx_sources_arm_neon = [ "vpx_dsp/arm/vpx_convolve8_neon.c", "vpx_dsp/arm/vpx_convolve_avg_neon.c", "vpx_dsp/arm/vpx_convolve_copy_neon.c", - "vpx_dsp/arm/vpx_convolve_neon.c" + "vpx_dsp/arm/vpx_convolve_neon.c", ] libvpx_sources_arm_neon_gas = [ "vpx_dsp/arm/gas/intrapred_neon_asm.s", "vpx_dsp/arm/gas/loopfilter_mb_neon.s", - "vpx_dsp/arm/gas/save_reg_neon.s" + "vpx_dsp/arm/gas/save_reg_neon.s", ] libvpx_sources_arm_neon_armasm_ms = [ "vpx_dsp/arm/armasm_ms/intrapred_neon_asm.asm", "vpx_dsp/arm/armasm_ms/loopfilter_mb_neon.asm", - "vpx_dsp/arm/armasm_ms/save_reg_neon.asm" + "vpx_dsp/arm/armasm_ms/save_reg_neon.asm", ] libvpx_sources_arm_neon_gas_apple = [ "vpx_dsp/arm/gas_apple/intrapred_neon_asm.s", "vpx_dsp/arm/gas_apple/loopfilter_mb_neon.s", - "vpx_dsp/arm/gas_apple/save_reg_neon.s" + "vpx_dsp/arm/gas_apple/save_reg_neon.s", ] libvpx_sources = [libvpx_dir + file for file in libvpx_sources] @@ -258,25 +222,43 @@ env_libvpx = env_modules.Clone() env_libvpx.disable_warnings() env_libvpx.Prepend(CPPPATH=[libvpx_dir]) -webm_multithread = env["platform"] != 'javascript' +webm_multithread = env["platform"] != "javascript" cpu_bits = env["bits"] webm_cpu_x86 = False webm_cpu_arm = False -if env["platform"] == 'uwp': - if 'arm' in env["PROGSUFFIX"]: +if env["platform"] == "uwp": + if "arm" in env["PROGSUFFIX"]: webm_cpu_arm = True else: webm_cpu_x86 = True else: import platform - is_x11_or_server_arm = ((env["platform"] == 'x11' or env["platform"] == 'server') and (platform.machine().startswith('arm') or platform.machine().startswith('aarch'))) - is_ios_x86 = (env["platform"] == 'iphone' and ("arch" in env and env["arch"].startswith('x86'))) - is_android_x86 = (env["platform"] == 'android' and env["android_arch"].startswith('x86')) + + is_x11_or_server_arm = (env["platform"] == "linuxbsd" or env["platform"] == "server") and ( + platform.machine().startswith("arm") or platform.machine().startswith("aarch") + ) + is_ios_x86 = env["platform"] == "iphone" and ("arch" in env and env["arch"].startswith("x86")) + is_android_x86 = env["platform"] == "android" and env["android_arch"].startswith("x86") if is_android_x86: - cpu_bits = '32' if env["android_arch"] == 'x86' else '64' - webm_cpu_x86 = not is_x11_or_server_arm and (cpu_bits == '32' or cpu_bits == '64') and (env["platform"] == 'windows' or env["platform"] == 'x11' or env["platform"] == 'osx' or env["platform"] == 'haiku' or is_android_x86 or is_ios_x86) - webm_cpu_arm = is_x11_or_server_arm or (not is_ios_x86 and env["platform"] == 'iphone') or (not is_android_x86 and env["platform"] == 'android') + cpu_bits = "32" if env["android_arch"] == "x86" else "64" + webm_cpu_x86 = ( + not is_x11_or_server_arm + and (cpu_bits == "32" or cpu_bits == "64") + and ( + env["platform"] == "windows" + or env["platform"] == "linuxbsd" + or env["platform"] == "osx" + or env["platform"] == "haiku" + or is_android_x86 + or is_ios_x86 + ) + ) + webm_cpu_arm = ( + is_x11_or_server_arm + or (not is_ios_x86 and env["platform"] == "iphone") + or (not is_android_x86 and env["platform"] == "android") + ) if webm_cpu_x86: import subprocess @@ -306,38 +288,43 @@ if webm_cpu_x86: webm_simd_optimizations = False if webm_cpu_x86: - if env["platform"] == 'windows' or env["platform"] == 'uwp': - env_libvpx["ASFORMAT"] = 'win' - elif env["platform"] == 'osx' or env["platform"] == "iphone": - env_libvpx["ASFORMAT"] = 'macho' + if env["platform"] == "windows" or env["platform"] == "uwp": + env_libvpx["ASFORMAT"] = "win" + elif env["platform"] == "osx" or env["platform"] == "iphone": + env_libvpx["ASFORMAT"] = "macho" else: - env_libvpx["ASFORMAT"] = 'elf' + env_libvpx["ASFORMAT"] = "elf" env_libvpx["ASFORMAT"] += cpu_bits - env_libvpx["AS"] = 'yasm' - env_libvpx["ASFLAGS"] = '-I' + libvpx_dir[1:] + ' -f $ASFORMAT -D $ASCPU' - env_libvpx["ASCOM"] = '$AS $ASFLAGS -o $TARGET $SOURCES' + env_libvpx["AS"] = "yasm" + env_libvpx["ASFLAGS"] = "-I" + libvpx_dir[1:] + " -f $ASFORMAT -D $ASCPU" + env_libvpx["ASCOM"] = "$AS $ASFLAGS -o $TARGET $SOURCES" - if cpu_bits == '32': - env_libvpx["ASCPU"] = 'X86_32' - elif cpu_bits == '64': - env_libvpx["ASCPU"] = 'X86_64' + if cpu_bits == "32": + env_libvpx["ASCPU"] = "X86_32" + elif cpu_bits == "64": + env_libvpx["ASCPU"] = "X86_64" - env_libvpx.Append(CPPDEFINES=['WEBM_X86ASM']) + env_libvpx.Append(CPPDEFINES=["WEBM_X86ASM"]) webm_simd_optimizations = True if webm_cpu_arm: - if env["platform"] == 'iphone': - env_libvpx["ASFLAGS"] = '-arch armv7' - elif env["platform"] == 'android' and env["android_arch"] == 'armv7' or env["platform"] == 'x11' or env["platform"] == 'server': - env_libvpx["ASFLAGS"] = '-mfpu=neon' - elif env["platform"] == 'uwp': - env_libvpx["AS"] = 'armasm' - env_libvpx["ASFLAGS"] = '' - env_libvpx["ASCOM"] = '$AS $ASFLAGS -o $TARGET $SOURCES' - - env_libvpx.Append(CPPDEFINES=['WEBM_ARMASM']) + if env["platform"] == "iphone": + env_libvpx["ASFLAGS"] = "-arch armv7" + elif ( + env["platform"] == "android" + and env["android_arch"] == "armv7" + or env["platform"] == "linuxbsd" + or env["platform"] == "server" + ): + env_libvpx["ASFLAGS"] = "-mfpu=neon" + elif env["platform"] == "uwp": + env_libvpx["AS"] = "armasm" + env_libvpx["ASFLAGS"] = "" + env_libvpx["ASCOM"] = "$AS $ASFLAGS -o $TARGET $SOURCES" + + env_libvpx.Append(CPPDEFINES=["WEBM_ARMASM"]) webm_simd_optimizations = True @@ -350,45 +337,49 @@ if webm_multithread: env_libvpx.add_source_files(env.modules_sources, libvpx_sources_mt) if webm_cpu_x86: - is_clang_or_gcc = ('gcc' in os.path.basename(env["CC"])) or ('clang' in os.path.basename(env["CC"])) or ("osxcross" in env) + is_clang_or_gcc = ( + ("gcc" in os.path.basename(env["CC"])) or ("clang" in os.path.basename(env["CC"])) or ("osxcross" in env) + ) env_libvpx_mmx = env_libvpx.Clone() - if cpu_bits == '32' and is_clang_or_gcc: - env_libvpx_mmx.Append(CCFLAGS=['-mmmx']) + if cpu_bits == "32" and is_clang_or_gcc: + env_libvpx_mmx.Append(CCFLAGS=["-mmmx"]) env_libvpx_mmx.add_source_files(env.modules_sources, libvpx_sources_intrin_x86_mmx) env_libvpx_sse2 = env_libvpx.Clone() - if cpu_bits == '32' and is_clang_or_gcc: - env_libvpx_sse2.Append(CCFLAGS=['-msse2']) + if cpu_bits == "32" and is_clang_or_gcc: + env_libvpx_sse2.Append(CCFLAGS=["-msse2"]) env_libvpx_sse2.add_source_files(env.modules_sources, libvpx_sources_intrin_x86_sse2) env_libvpx_ssse3 = env_libvpx.Clone() if is_clang_or_gcc: - env_libvpx_ssse3.Append(CCFLAGS=['-mssse3']) + env_libvpx_ssse3.Append(CCFLAGS=["-mssse3"]) env_libvpx_ssse3.add_source_files(env.modules_sources, libvpx_sources_intrin_x86_ssse3) env_libvpx_avx2 = env_libvpx.Clone() if is_clang_or_gcc: - env_libvpx_avx2.Append(CCFLAGS=['-mavx2']) + env_libvpx_avx2.Append(CCFLAGS=["-mavx2"]) env_libvpx_avx2.add_source_files(env.modules_sources, libvpx_sources_intrin_x86_avx2) env_libvpx.add_source_files(env.modules_sources, libvpx_sources_intrin_x86) env_libvpx.add_source_files(env.modules_sources, libvpx_sources_x86asm) - if cpu_bits == '64': + if cpu_bits == "64": env_libvpx.add_source_files(env.modules_sources, libvpx_sources_x86_64asm) elif webm_cpu_arm: env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm) - if env["platform"] == 'android': + if env["platform"] == "android": env_libvpx.Prepend(CPPPATH=[libvpx_dir + "third_party/android"]) env_libvpx.add_source_files(env.modules_sources, [libvpx_dir + "third_party/android/cpu-features.c"]) env_libvpx_neon = env_libvpx.Clone() env_libvpx_neon.add_source_files(env.modules_sources, libvpx_sources_arm_neon) - if env["platform"] == 'uwp': + if env["platform"] == "uwp": env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm_neon_armasm_ms) - elif env["platform"] == 'iphone': + elif env["platform"] == "iphone": env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm_neon_gas_apple) - elif (is_x11_or_server_arm and cpu_bits == '32') or (env["platform"] == 'android' and not env["android_arch"] == 'arm64v8'): + elif (is_x11_or_server_arm and cpu_bits == "32") or ( + env["platform"] == "android" and not env["android_arch"] == "arm64v8" + ): env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm_neon_gas) diff --git a/modules/webm/register_types.cpp b/modules/webm/register_types.cpp index 5449dd458c..6248787879 100644 --- a/modules/webm/register_types.cpp +++ b/modules/webm/register_types.cpp @@ -35,7 +35,6 @@ static Ref<ResourceFormatLoaderWebm> resource_loader_webm; void register_webm_types() { - resource_loader_webm.instance(); ResourceLoader::add_resource_format_loader(resource_loader_webm, true); @@ -43,7 +42,6 @@ void register_webm_types() { } void unregister_webm_types() { - ResourceLoader::remove_resource_format_loader(resource_loader_webm); resource_loader_webm.unref(); } diff --git a/modules/webm/register_types.h b/modules/webm/register_types.h index 962a0dab4e..6a02e3a87a 100644 --- a/modules/webm/register_types.h +++ b/modules/webm/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef WEBM_REGISTER_TYPES_H +#define WEBM_REGISTER_TYPES_H + void register_webm_types(); void unregister_webm_types(); + +#endif // WEBM_REGISTER_TYPES_H diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp index 265383831e..832e14d91a 100644 --- a/modules/webm/video_stream_webm.cpp +++ b/modules/webm/video_stream_webm.cpp @@ -48,41 +48,39 @@ #include <mkvparser/mkvparser.h> class MkvReader : public mkvparser::IMkvReader { - public: MkvReader(const String &p_file) { - file = FileAccess::open(p_file, FileAccess::READ); ERR_FAIL_COND_MSG(!file, "Failed loading resource: '" + p_file + "'."); } ~MkvReader() { - - if (file) + if (file) { memdelete(file); + } } virtual int Read(long long pos, long len, unsigned char *buf) { - if (file) { - - if (file->get_position() != (size_t)pos) + if (file->get_position() != (size_t)pos) { file->seek(pos); - if (file->get_buffer(buf, len) == len) + } + if (file->get_buffer(buf, len) == len) { return 0; + } } return -1; } virtual int Length(long long *total, long long *available) { - if (file) { - const size_t len = file->get_len(); - if (total) + if (total) { *total = len; - if (available) + } + if (available) { *available = len; + } return 0; } return -1; @@ -95,49 +93,25 @@ private: /**/ VideoStreamPlaybackWebm::VideoStreamPlaybackWebm() : - audio_track(0), - webm(NULL), - video(NULL), - audio(NULL), - video_frames(NULL), - audio_frame(NULL), - video_frames_pos(0), - video_frames_capacity(0), - num_decoded_samples(0), - samples_offset(-1), - mix_callback(NULL), - mix_udata(NULL), - playing(false), - paused(false), - delay_compensation(0.0), - time(0.0), - video_frame_delay(0.0), - video_pos(0.0), - texture(memnew(ImageTexture)), - pcm(NULL) {} -VideoStreamPlaybackWebm::~VideoStreamPlaybackWebm() { + texture(memnew(ImageTexture)) {} +VideoStreamPlaybackWebm::~VideoStreamPlaybackWebm() { delete_pointers(); } bool VideoStreamPlaybackWebm::open_file(const String &p_file) { - file_name = p_file; webm = memnew(WebMDemuxer(new MkvReader(file_name), 0, audio_track)); if (webm->isOpen()) { - video = memnew(VPXDecoder(*webm, OS::get_singleton()->get_processor_count())); if (video->isOpen()) { - audio = memnew(OpusVorbisDecoder(*webm)); if (audio->isOpen()) { - audio_frame = memnew(WebMFrame); pcm = (float *)memalloc(sizeof(float) * audio->getBufferSamples() * webm->getChannels()); } else { - memdelete(audio); - audio = NULL; + audio = nullptr; } frame_data.resize((webm->getWidth() * webm->getHeight()) << 2); @@ -149,26 +123,24 @@ bool VideoStreamPlaybackWebm::open_file(const String &p_file) { return true; } memdelete(video); - video = NULL; + video = nullptr; } memdelete(webm); - webm = NULL; + webm = nullptr; return false; } void VideoStreamPlaybackWebm::stop() { - if (playing) { - delete_pointers(); - pcm = NULL; + pcm = nullptr; - audio_frame = NULL; - video_frames = NULL; + audio_frame = nullptr; + video_frames = nullptr; - video = NULL; - audio = NULL; + video = nullptr; + audio = nullptr; open_file(file_name); //Should not fail here... @@ -180,8 +152,8 @@ void VideoStreamPlaybackWebm::stop() { time = 0.0; playing = false; } -void VideoStreamPlaybackWebm::play() { +void VideoStreamPlaybackWebm::play() { stop(); delay_compensation = ProjectSettings::get_singleton()->get("audio/video_delay_compensation_ms"); @@ -191,58 +163,52 @@ void VideoStreamPlaybackWebm::play() { } bool VideoStreamPlaybackWebm::is_playing() const { - return playing; } void VideoStreamPlaybackWebm::set_paused(bool p_paused) { - paused = p_paused; } -bool VideoStreamPlaybackWebm::is_paused() const { +bool VideoStreamPlaybackWebm::is_paused() const { return paused; } void VideoStreamPlaybackWebm::set_loop(bool p_enable) { - //Empty } -bool VideoStreamPlaybackWebm::has_loop() const { +bool VideoStreamPlaybackWebm::has_loop() const { return false; } float VideoStreamPlaybackWebm::get_length() const { - - if (webm) + if (webm) { return webm->getLength(); + } return 0.0f; } float VideoStreamPlaybackWebm::get_playback_position() const { - return video_pos; } -void VideoStreamPlaybackWebm::seek(float p_time) { +void VideoStreamPlaybackWebm::seek(float p_time) { //Not implemented } void VideoStreamPlaybackWebm::set_audio_track(int p_idx) { - audio_track = p_idx; } Ref<Texture2D> VideoStreamPlaybackWebm::get_texture() const { - return texture; } void VideoStreamPlaybackWebm::update(float p_delta) { - - if ((!playing || paused) || !video) + if ((!playing || paused) || !video) { return; + } time += p_delta; @@ -253,16 +219,13 @@ void VideoStreamPlaybackWebm::update(float p_delta) { bool audio_buffer_full = false; if (samples_offset > -1) { - //Mix remaining samples const int to_read = num_decoded_samples - samples_offset; const int mixed = mix_callback(mix_udata, pcm + samples_offset * webm->getChannels(), to_read); if (mixed != to_read) { - samples_offset += mixed; audio_buffer_full = true; } else { - samples_offset = -1; } } @@ -270,10 +233,8 @@ void VideoStreamPlaybackWebm::update(float p_delta) { const bool hasAudio = (audio && mix_callback); while ((hasAudio && !audio_buffer_full && !has_enough_video_frames()) || (!hasAudio && video_frames_pos == 0)) { - if (hasAudio && !audio_buffer_full && audio_frame->isValid() && audio->getPCMF(*audio_frame, pcm, num_decoded_samples) && num_decoded_samples > 0) { - const int mixed = mix_callback(mix_udata, pcm, num_decoded_samples); if (mixed != num_decoded_samples) { @@ -284,42 +245,37 @@ void VideoStreamPlaybackWebm::update(float p_delta) { WebMFrame *video_frame; if (video_frames_pos >= video_frames_capacity) { - WebMFrame **video_frames_new = (WebMFrame **)memrealloc(video_frames, ++video_frames_capacity * sizeof(void *)); ERR_FAIL_COND(!video_frames_new); //Out of memory (video_frames = video_frames_new)[video_frames_capacity - 1] = memnew(WebMFrame); } video_frame = video_frames[video_frames_pos]; - if (!webm->readFrame(video_frame, audio_frame)) //This will invalidate frames + if (!webm->readFrame(video_frame, audio_frame)) { //This will invalidate frames break; //Can't demux, EOS? + } - if (video_frame->isValid()) + if (video_frame->isValid()) { ++video_frames_pos; + } }; bool video_frame_done = false; while (video_frames_pos > 0 && !video_frame_done) { - WebMFrame *video_frame = video_frames[0]; // It seems VPXDecoder::decode has to be executed even though we might skip this frame if (video->decode(*video_frame)) { - VPXDecoder::IMAGE_ERROR err; VPXDecoder::Image image; if (should_process(*video_frame)) { - if ((err = video->getImage(image)) != VPXDecoder::NO_FRAME) { - if (err == VPXDecoder::NO_ERROR && image.w == webm->getWidth() && image.h == webm->getHeight()) { - uint8_t *w = frame_data.ptrw(); bool converted = false; if (image.chromaShiftW == 0 && image.chromaShiftH == 0 && image.cs == VPX_CS_SRGB) { - uint8_t *wp = w; unsigned char *rRow = image.planes[2]; unsigned char *gRow = image.planes[0]; @@ -337,22 +293,18 @@ void VideoStreamPlaybackWebm::update(float p_delta) { } converted = true; } else if (image.chromaShiftW == 1 && image.chromaShiftH == 1) { - yuv420_2_rgb8888(w, image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); //libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) { - yuv422_2_rgb8888(w, image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); //libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) { - yuv444_2_rgb8888(w, image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); //libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) { - //libyuv::I411ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2] image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); //converted = true; } @@ -372,25 +324,27 @@ void VideoStreamPlaybackWebm::update(float p_delta) { video_frames[video_frames_pos] = video_frame; } - if (video_frames_pos == 0 && webm->isEOS()) + if (video_frames_pos == 0 && webm->isEOS()) { stop(); + } } void VideoStreamPlaybackWebm::set_mix_callback(VideoStreamPlayback::AudioMixCallback p_callback, void *p_userdata) { - mix_callback = p_callback; mix_udata = p_userdata; } -int VideoStreamPlaybackWebm::get_channels() const { - if (audio) +int VideoStreamPlaybackWebm::get_channels() const { + if (audio) { return webm->getChannels(); + } return 0; } -int VideoStreamPlaybackWebm::get_mix_rate() const { - if (audio) +int VideoStreamPlaybackWebm::get_mix_rate() const { + if (audio) { return webm->getSampleRate(); + } return 0; } @@ -415,52 +369,54 @@ bool VideoStreamPlaybackWebm::should_process(WebMFrame &video_frame) { } void VideoStreamPlaybackWebm::delete_pointers() { - - if (pcm) + if (pcm) { memfree(pcm); + } - if (audio_frame) + if (audio_frame) { memdelete(audio_frame); + } if (video_frames) { - for (int i = 0; i < video_frames_capacity; ++i) + for (int i = 0; i < video_frames_capacity; ++i) { memdelete(video_frames[i]); + } memfree(video_frames); } - if (video) + if (video) { memdelete(video); - if (audio) + } + if (audio) { memdelete(audio); + } - if (webm) + if (webm) { memdelete(webm); + } } /**/ -VideoStreamWebm::VideoStreamWebm() : - audio_track(0) {} +VideoStreamWebm::VideoStreamWebm() {} Ref<VideoStreamPlayback> VideoStreamWebm::instance_playback() { - Ref<VideoStreamPlaybackWebm> pb = memnew(VideoStreamPlaybackWebm); pb->set_audio_track(audio_track); - if (pb->open_file(file)) + if (pb->open_file(file)) { return pb; - return NULL; + } + return nullptr; } void VideoStreamWebm::set_file(const String &p_file) { - file = p_file; } -String VideoStreamWebm::get_file() { +String VideoStreamWebm::get_file() { return file; } void VideoStreamWebm::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamWebm::set_file); ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamWebm::get_file); @@ -468,14 +424,12 @@ void VideoStreamWebm::_bind_methods() { } void VideoStreamWebm::set_audio_track(int p_track) { - audio_track = p_track; } //////////// -RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - +RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { if (r_error) { @@ -499,19 +453,17 @@ RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_origina } void ResourceFormatLoaderWebm::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("webm"); } bool ResourceFormatLoaderWebm::handles_type(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "VideoStream"); } String ResourceFormatLoaderWebm::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "webm") + if (el == "webm") { return "VideoStreamWebm"; + } return ""; } diff --git a/modules/webm/video_stream_webm.h b/modules/webm/video_stream_webm.h index 3feaa1278f..f6c148b29b 100644 --- a/modules/webm/video_stream_webm.h +++ b/modules/webm/video_stream_webm.h @@ -40,31 +40,30 @@ class VPXDecoder; class OpusVorbisDecoder; class VideoStreamPlaybackWebm : public VideoStreamPlayback { - GDCLASS(VideoStreamPlaybackWebm, VideoStreamPlayback); String file_name; - int audio_track; + int audio_track = 0; - WebMDemuxer *webm; - VPXDecoder *video; - OpusVorbisDecoder *audio; + WebMDemuxer *webm = nullptr; + VPXDecoder *video = nullptr; + OpusVorbisDecoder *audio = nullptr; - WebMFrame **video_frames, *audio_frame; - int video_frames_pos, video_frames_capacity; + WebMFrame **video_frames = nullptr, *audio_frame = nullptr; + int video_frames_pos = 0, video_frames_capacity = 0; - int num_decoded_samples, samples_offset; - AudioMixCallback mix_callback; - void *mix_udata; + int num_decoded_samples = 0, samples_offset = -1; + AudioMixCallback mix_callback = nullptr; + void *mix_udata = nullptr; - bool playing, paused; - double delay_compensation; - double time, video_frame_delay, video_pos; + bool playing = false, paused = false; + double delay_compensation = 0.0; + double time = 0.0, video_frame_delay = 0.0, video_pos = 0.0; Vector<uint8_t> frame_data; Ref<ImageTexture> texture; - float *pcm; + float *pcm = nullptr; public: VideoStreamPlaybackWebm(); @@ -107,11 +106,10 @@ private: /**/ class VideoStreamWebm : public VideoStream { - GDCLASS(VideoStreamWebm, VideoStream); String file; - int audio_track; + int audio_track = 0; protected: static void _bind_methods(); @@ -128,7 +126,7 @@ public: class ResourceFormatLoaderWebm : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/modules/webp/SCsub b/modules/webp/SCsub index 666628bb44..58f2bb35e6 100644 --- a/modules/webp/SCsub +++ b/modules/webp/SCsub @@ -1,12 +1,12 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_webp = env_modules.Clone() # Thirdparty source files -if env['builtin_libwebp']: +if env["builtin_libwebp"]: thirdparty_dir = "#thirdparty/libwebp/" thirdparty_sources = [ "dec/alpha_dec.c", diff --git a/modules/webp/config.py b/modules/webp/config.py index 1c8cd12a2d..d22f9454ed 100644 --- a/modules/webp/config.py +++ b/modules/webp/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): return True + def configure(env): pass diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp index 09a8985472..d5c80e7909 100644 --- a/modules/webp/image_loader_webp.cpp +++ b/modules/webp/image_loader_webp.cpp @@ -39,23 +39,22 @@ #include <webp/encode.h> static Vector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quality) { - ERR_FAIL_COND_V(p_image.is_null() || p_image->empty(), Vector<uint8_t>()); Ref<Image> img = p_image->duplicate(); - if (img->detect_alpha()) + if (img->detect_alpha()) { img->convert(Image::FORMAT_RGBA8); - else + } else { img->convert(Image::FORMAT_RGB8); + } Size2 s(img->get_width(), img->get_height()); Vector<uint8_t> data = img->get_data(); const uint8_t *r = data.ptr(); - uint8_t *dst_buff = NULL; + uint8_t *dst_buff = nullptr; size_t dst_size = 0; if (img->get_format() == Image::FORMAT_RGB8) { - dst_size = WebPEncodeRGB(r, s.width, s.height, 3 * s.width, CLAMP(p_quality * 100.0, 0, 100.0), &dst_buff); } else { dst_size = WebPEncodeRGBA(r, s.width, s.height, 4 * s.width, CLAMP(p_quality * 100.0, 0, 100.0), &dst_buff); @@ -76,7 +75,6 @@ static Vector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quali } static Ref<Image> _webp_lossy_unpack(const Vector<uint8_t> &p_buffer) { - int size = p_buffer.size() - 4; ERR_FAIL_COND_V(size <= 0, Ref<Image>()); const uint8_t *r = p_buffer.ptr(); @@ -101,9 +99,9 @@ static Ref<Image> _webp_lossy_unpack(const Vector<uint8_t> &p_buffer) { bool errdec = false; if (features.has_alpha) { - errdec = WebPDecodeRGBAInto(&r[4], size, dst_w, datasize, 4 * features.width) == NULL; + errdec = WebPDecodeRGBAInto(&r[4], size, dst_w, datasize, 4 * features.width) == nullptr; } else { - errdec = WebPDecodeRGBInto(&r[4], size, dst_w, datasize, 3 * features.width) == NULL; + errdec = WebPDecodeRGBInto(&r[4], size, dst_w, datasize, 3 * features.width) == nullptr; } ERR_FAIL_COND_V_MSG(errdec, Ref<Image>(), "Failed decoding WebP image."); @@ -113,7 +111,6 @@ static Ref<Image> _webp_lossy_unpack(const Vector<uint8_t> &p_buffer) { } Error webp_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p_buffer_len) { - ERR_FAIL_NULL_V(p_image, ERR_INVALID_PARAMETER); WebPBitstreamFeatures features; @@ -128,20 +125,19 @@ Error webp_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p bool errdec = false; if (features.has_alpha) { - errdec = WebPDecodeRGBAInto(p_buffer, p_buffer_len, dst_w, datasize, 4 * features.width) == NULL; + errdec = WebPDecodeRGBAInto(p_buffer, p_buffer_len, dst_w, datasize, 4 * features.width) == nullptr; } else { - errdec = WebPDecodeRGBInto(p_buffer, p_buffer_len, dst_w, datasize, 3 * features.width) == NULL; + errdec = WebPDecodeRGBInto(p_buffer, p_buffer_len, dst_w, datasize, 3 * features.width) == nullptr; } ERR_FAIL_COND_V_MSG(errdec, ERR_FILE_CORRUPT, "Failed decoding WebP image."); - p_image->create(features.width, features.height, 0, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image); + p_image->create(features.width, features.height, false, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image); return OK; } static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) { - Ref<Image> img; img.instance(); Error err = webp_load_image_from_buffer(img.ptr(), p_png, p_size); @@ -150,7 +146,6 @@ static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) { } Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) { - Vector<uint8_t> src_image; int src_image_len = f->get_len(); ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT); @@ -168,7 +163,6 @@ Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_forc } void ImageLoaderWEBP::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("webp"); } diff --git a/modules/webp/image_loader_webp.h b/modules/webp/image_loader_webp.h index 9206ca2525..49a7407600 100644 --- a/modules/webp/image_loader_webp.h +++ b/modules/webp/image_loader_webp.h @@ -34,7 +34,6 @@ #include "core/io/image_loader.h" class ImageLoaderWEBP : public ImageFormatLoader { - public: virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale); virtual void get_recognized_extensions(List<String> *p_extensions) const; diff --git a/modules/webp/register_types.cpp b/modules/webp/register_types.cpp index 12a0c05f44..0788b06309 100644 --- a/modules/webp/register_types.cpp +++ b/modules/webp/register_types.cpp @@ -32,15 +32,13 @@ #include "image_loader_webp.h" -static ImageLoaderWEBP *image_loader_webp = NULL; +static ImageLoaderWEBP *image_loader_webp = nullptr; void register_webp_types() { - image_loader_webp = memnew(ImageLoaderWEBP); ImageLoader::add_image_format_loader(image_loader_webp); } void unregister_webp_types() { - memdelete(image_loader_webp); } diff --git a/modules/webp/register_types.h b/modules/webp/register_types.h index 9591b91558..d574d7be1d 100644 --- a/modules/webp/register_types.h +++ b/modules/webp/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef WEBP_REGISTER_TYPES_H +#define WEBP_REGISTER_TYPES_H + void register_webp_types(); void unregister_webp_types(); + +#endif // WEBP_REGISTER_TYPES_H diff --git a/modules/webrtc/SCsub b/modules/webrtc/SCsub index 868553b879..20b4c8f8d2 100644 --- a/modules/webrtc/SCsub +++ b/modules/webrtc/SCsub @@ -1,15 +1,15 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") # Thirdparty source files env_webrtc = env_modules.Clone() use_gdnative = env_webrtc["module_gdnative_enabled"] -if use_gdnative: # GDNative is retained in Javascript for export compatibility - env_webrtc.Append(CPPDEFINES=['WEBRTC_GDNATIVE_ENABLED']) +if use_gdnative: # GDNative is retained in Javascript for export compatibility + env_webrtc.Append(CPPDEFINES=["WEBRTC_GDNATIVE_ENABLED"]) env_webrtc.Prepend(CPPPATH=["#modules/gdnative/include/"]) env_webrtc.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/webrtc/config.py b/modules/webrtc/config.py index 48b4c33c5d..0a075ccef1 100644 --- a/modules/webrtc/config.py +++ b/modules/webrtc/config.py @@ -1,15 +1,18 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "WebRTCPeerConnection", "WebRTCDataChannel", - "WebRTCMultiplayer" + "WebRTCMultiplayer", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/webrtc/register_types.h b/modules/webrtc/register_types.h index e6b50506e5..8f5b9e8452 100644 --- a/modules/webrtc/register_types.h +++ b/modules/webrtc/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef WEBRTC_REGISTER_TYPES_H +#define WEBRTC_REGISTER_TYPES_H + void register_webrtc_types(); void unregister_webrtc_types(); + +#endif // WEBRTC_REGISTER_TYPES_H diff --git a/modules/webrtc/webrtc_data_channel_gdnative.cpp b/modules/webrtc/webrtc_data_channel_gdnative.cpp index b0c4b473fc..67ad2c07ce 100644 --- a/modules/webrtc/webrtc_data_channel_gdnative.cpp +++ b/modules/webrtc/webrtc_data_channel_gdnative.cpp @@ -39,94 +39,94 @@ void WebRTCDataChannelGDNative::_bind_methods() { } WebRTCDataChannelGDNative::WebRTCDataChannelGDNative() { - interface = NULL; + interface = nullptr; } WebRTCDataChannelGDNative::~WebRTCDataChannelGDNative() { } Error WebRTCDataChannelGDNative::poll() { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->poll(interface->data); } void WebRTCDataChannelGDNative::close() { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->close(interface->data); } void WebRTCDataChannelGDNative::set_write_mode(WriteMode p_mode) { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->set_write_mode(interface->data, p_mode); } WebRTCDataChannel::WriteMode WebRTCDataChannelGDNative::get_write_mode() const { - ERR_FAIL_COND_V(interface == NULL, WRITE_MODE_BINARY); + ERR_FAIL_COND_V(interface == nullptr, WRITE_MODE_BINARY); return (WriteMode)interface->get_write_mode(interface->data); } bool WebRTCDataChannelGDNative::was_string_packet() const { - ERR_FAIL_COND_V(interface == NULL, false); + ERR_FAIL_COND_V(interface == nullptr, false); return interface->was_string_packet(interface->data); } WebRTCDataChannel::ChannelState WebRTCDataChannelGDNative::get_ready_state() const { - ERR_FAIL_COND_V(interface == NULL, STATE_CLOSED); + ERR_FAIL_COND_V(interface == nullptr, STATE_CLOSED); return (ChannelState)interface->get_ready_state(interface->data); } String WebRTCDataChannelGDNative::get_label() const { - ERR_FAIL_COND_V(interface == NULL, ""); + ERR_FAIL_COND_V(interface == nullptr, ""); return String(interface->get_label(interface->data)); } bool WebRTCDataChannelGDNative::is_ordered() const { - ERR_FAIL_COND_V(interface == NULL, false); + ERR_FAIL_COND_V(interface == nullptr, false); return interface->is_ordered(interface->data); } int WebRTCDataChannelGDNative::get_id() const { - ERR_FAIL_COND_V(interface == NULL, -1); + ERR_FAIL_COND_V(interface == nullptr, -1); return interface->get_id(interface->data); } int WebRTCDataChannelGDNative::get_max_packet_life_time() const { - ERR_FAIL_COND_V(interface == NULL, -1); + ERR_FAIL_COND_V(interface == nullptr, -1); return interface->get_max_packet_life_time(interface->data); } int WebRTCDataChannelGDNative::get_max_retransmits() const { - ERR_FAIL_COND_V(interface == NULL, -1); + ERR_FAIL_COND_V(interface == nullptr, -1); return interface->get_max_retransmits(interface->data); } String WebRTCDataChannelGDNative::get_protocol() const { - ERR_FAIL_COND_V(interface == NULL, ""); + ERR_FAIL_COND_V(interface == nullptr, ""); return String(interface->get_protocol(interface->data)); } bool WebRTCDataChannelGDNative::is_negotiated() const { - ERR_FAIL_COND_V(interface == NULL, false); + ERR_FAIL_COND_V(interface == nullptr, false); return interface->is_negotiated(interface->data); } Error WebRTCDataChannelGDNative::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->get_packet(interface->data, r_buffer, &r_buffer_size); } Error WebRTCDataChannelGDNative::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->put_packet(interface->data, p_buffer, p_buffer_size); } int WebRTCDataChannelGDNative::get_max_packet_size() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_max_packet_size(interface->data); } int WebRTCDataChannelGDNative::get_available_packet_count() const { - ERR_FAIL_COND_V(interface == NULL, 0); + ERR_FAIL_COND_V(interface == nullptr, 0); return interface->get_available_packet_count(interface->data); } diff --git a/modules/webrtc/webrtc_data_channel_js.cpp b/modules/webrtc/webrtc_data_channel_js.cpp index 37203a4ec9..2c648ba9f9 100644 --- a/modules/webrtc/webrtc_data_channel_js.cpp +++ b/modules/webrtc/webrtc_data_channel_js.cpp @@ -68,7 +68,6 @@ void WebRTCDataChannelJS::_on_error() { } void WebRTCDataChannelJS::_on_message(uint8_t *p_data, uint32_t p_size, bool p_is_string) { - ERR_FAIL_COND_MSG(in_buffer.space_left() < (int)(p_size + 5), "Buffer full! Dropping data."); uint8_t is_string = p_is_string ? 1 : 0; @@ -312,14 +311,14 @@ WebRTCDataChannelJS::WebRTCDataChannelJS(int js_id) { return; } var len = buffer.length*buffer.BYTES_PER_ELEMENT; - var out = Module._malloc(len); - Module.HEAPU8.set(buffer, out); + var out = _malloc(len); + HEAPU8.set(buffer, out); ccall("_emrtc_on_ch_message", "void", ["number", "number", "number", "number"], [c_ptr, out, len, is_string] ); - Module._free(out); + _free(out); } }, this, js_id); @@ -334,7 +333,7 @@ WebRTCDataChannelJS::WebRTCDataChannelJS(int js_id) { stringToUTF8(str, ptr, len+1); return ptr; }, js_id); - if(str != NULL) { + if(str != nullptr) { _label.parse_utf8(str); EM_ASM({ _free($0) }, str); } @@ -347,7 +346,7 @@ WebRTCDataChannelJS::WebRTCDataChannelJS(int js_id) { stringToUTF8(str, ptr, len+1); return ptr; }, js_id); - if(str != NULL) { + if(str != nullptr) { _protocol.parse_utf8(str); EM_ASM({ _free($0) }, str); } diff --git a/modules/webrtc/webrtc_multiplayer.cpp b/modules/webrtc/webrtc_multiplayer.cpp index c24ae3468f..e0c0cad68c 100644 --- a/modules/webrtc/webrtc_multiplayer.cpp +++ b/modules/webrtc/webrtc_multiplayer.cpp @@ -65,8 +65,9 @@ bool WebRTCMultiplayer::is_server() const { } void WebRTCMultiplayer::poll() { - if (peer_map.size() == 0) + if (peer_map.size() == 0) { return; + } List<int> remove; List<int> add; @@ -113,15 +114,17 @@ void WebRTCMultiplayer::poll() { // Remove disconnected peers for (List<int>::Element *E = remove.front(); E; E = E->next()) { remove_peer(E->get()); - if (next_packet_peer == E->get()) + if (next_packet_peer == E->get()) { next_packet_peer = 0; + } } // Signal newly connected peers for (List<int>::Element *E = add.front(); E; E = E->next()) { // Already connected to server: simply notify new peer. // NOTE: Mesh is always connected. - if (connection_status == CONNECTION_CONNECTED) + if (connection_status == CONNECTION_CONNECTED) { emit_signal("peer_connected", E->get()); + } // Server emulation mode suppresses peer_conencted until server connects. if (server_compat && E->get() == TARGET_PEER_SERVER) { @@ -131,20 +134,24 @@ void WebRTCMultiplayer::poll() { emit_signal("connection_succeeded"); // Notify of all previously connected peers for (Map<int, Ref<ConnectedPeer>>::Element *F = peer_map.front(); F; F = F->next()) { - if (F->key() != 1 && F->get()->connected) + if (F->key() != 1 && F->get()->connected) { emit_signal("peer_connected", F->key()); + } } break; // Because we already notified of all newly added peers. } } // Fetch next packet - if (next_packet_peer == 0) + if (next_packet_peer == 0) { _find_next_peer(); + } } void WebRTCMultiplayer::_find_next_peer() { Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.find(next_packet_peer); - if (E) E = E->next(); + if (E) { + E = E->next(); + } // After last. while (E) { for (List<Ref<WebRTCDataChannel>>::Element *F = E->get()->channels.front(); F; F = F->next()) { @@ -164,8 +171,9 @@ void WebRTCMultiplayer::_find_next_peer() { return; } } - if (E->key() == (int)next_packet_peer) + if (E->key() == (int)next_packet_peer) { break; + } E = E->next(); } // No packet found @@ -190,10 +198,11 @@ Error WebRTCMultiplayer::initialize(int p_self_id, bool p_server_compat) { server_compat = p_server_compat; // Mesh and server are always connected - if (!server_compat || p_self_id == 1) + if (!server_compat || p_self_id == 1) { connection_status = CONNECTION_CONNECTED; - else + } else { connection_status = CONNECTION_CONNECTING; + } return OK; } @@ -316,10 +325,9 @@ Error WebRTCMultiplayer::put_packet(const uint8_t *p_buffer, int p_buffer_size) break; } - Map<int, Ref<ConnectedPeer>>::Element *E = NULL; + Map<int, Ref<ConnectedPeer>>::Element *E = nullptr; if (target_peer > 0) { - E = peer_map.find(target_peer); ERR_FAIL_COND_V_MSG(!E, ERR_INVALID_PARAMETER, "Invalid target peer: " + itos(target_peer) + "."); @@ -331,10 +339,10 @@ Error WebRTCMultiplayer::put_packet(const uint8_t *p_buffer, int p_buffer_size) int exclude = -target_peer; for (Map<int, Ref<ConnectedPeer>>::Element *F = peer_map.front(); F; F = F->next()) { - // Exclude packet. If target_peer == 0 then don't exclude any packets - if (target_peer != 0 && F->key() == exclude) + if (target_peer != 0 && F->key() == exclude) { continue; + } ERR_CONTINUE(F->value()->channels.size() <= ch || !F->value()->channels[ch].is_valid()); F->value()->channels[ch]->put_packet(p_buffer, p_buffer_size); @@ -344,8 +352,9 @@ Error WebRTCMultiplayer::put_packet(const uint8_t *p_buffer, int p_buffer_size) } int WebRTCMultiplayer::get_available_packet_count() const { - if (next_packet_peer == 0) + if (next_packet_peer == 0) { return 0; // To be sure next call to get_packet works if size > 0 . + } int size = 0; for (Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.front(); E; E = E->next()) { for (List<Ref<WebRTCDataChannel>>::Element *F = E->get()->channels.front(); F; F = F->next()) { @@ -371,6 +380,7 @@ WebRTCMultiplayer::WebRTCMultiplayer() { unique_id = 0; next_packet_peer = 0; target_peer = 0; + client_count = 0; transfer_mode = TRANSFER_MODE_RELIABLE; refuse_connections = false; connection_status = CONNECTION_DISCONNECTED; diff --git a/modules/webrtc/webrtc_multiplayer.h b/modules/webrtc/webrtc_multiplayer.h index 0e1335b8a8..906b90a1b6 100644 --- a/modules/webrtc/webrtc_multiplayer.h +++ b/modules/webrtc/webrtc_multiplayer.h @@ -35,7 +35,6 @@ #include "webrtc_peer_connection.h" class WebRTCMultiplayer : public NetworkedMultiplayerPeer { - GDCLASS(WebRTCMultiplayer, NetworkedMultiplayerPeer); protected: @@ -50,7 +49,6 @@ private: }; class ConnectedPeer : public Reference { - public: Ref<WebRTCPeerConnection> connection; List<Ref<WebRTCDataChannel>> channels; @@ -58,8 +56,9 @@ private: ConnectedPeer() { connected = false; - for (int i = 0; i < CH_RESERVED_MAX; i++) + for (int i = 0; i < CH_RESERVED_MAX; i++) { channels.push_front(Ref<WebRTCDataChannel>()); + } } }; diff --git a/modules/webrtc/webrtc_peer_connection.cpp b/modules/webrtc/webrtc_peer_connection.cpp index 90c62e2495..670924bca2 100644 --- a/modules/webrtc/webrtc_peer_connection.cpp +++ b/modules/webrtc/webrtc_peer_connection.cpp @@ -30,17 +30,16 @@ #include "webrtc_peer_connection.h" -WebRTCPeerConnection *(*WebRTCPeerConnection::_create)() = NULL; +WebRTCPeerConnection *(*WebRTCPeerConnection::_create)() = nullptr; Ref<WebRTCPeerConnection> WebRTCPeerConnection::create_ref() { - return create(); } WebRTCPeerConnection *WebRTCPeerConnection::create() { - - if (!_create) - return NULL; + if (!_create) { + return nullptr; + } return _create(); } diff --git a/modules/webrtc/webrtc_peer_connection_gdnative.cpp b/modules/webrtc/webrtc_peer_connection_gdnative.cpp index 411ad50275..aaa45d3a54 100644 --- a/modules/webrtc/webrtc_peer_connection_gdnative.cpp +++ b/modules/webrtc/webrtc_peer_connection_gdnative.cpp @@ -36,12 +36,12 @@ #include "modules/gdnative/nativescript/nativescript.h" #include "webrtc_data_channel_gdnative.h" -const godot_net_webrtc_library *WebRTCPeerConnectionGDNative::default_library = NULL; +const godot_net_webrtc_library *WebRTCPeerConnectionGDNative::default_library = nullptr; Error WebRTCPeerConnectionGDNative::set_default_library(const godot_net_webrtc_library *p_lib) { if (default_library) { const godot_net_webrtc_library *old = default_library; - default_library = NULL; + default_library = nullptr; old->unregistered(); } default_library = p_lib; @@ -49,7 +49,6 @@ Error WebRTCPeerConnectionGDNative::set_default_library(const godot_net_webrtc_l } WebRTCPeerConnection *WebRTCPeerConnectionGDNative::_create() { - WebRTCPeerConnectionGDNative *obj = memnew(WebRTCPeerConnectionGDNative); ERR_FAIL_COND_V_MSG(!default_library, obj, "Default GDNative WebRTC implementation not defined."); @@ -64,54 +63,54 @@ void WebRTCPeerConnectionGDNative::_bind_methods() { } WebRTCPeerConnectionGDNative::WebRTCPeerConnectionGDNative() { - interface = NULL; + interface = nullptr; } WebRTCPeerConnectionGDNative::~WebRTCPeerConnectionGDNative() { } Error WebRTCPeerConnectionGDNative::initialize(Dictionary p_config) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->initialize(interface->data, (const godot_dictionary *)&p_config); } Ref<WebRTCDataChannel> WebRTCPeerConnectionGDNative::create_data_channel(String p_label, Dictionary p_options) { - ERR_FAIL_COND_V(interface == NULL, NULL); + ERR_FAIL_COND_V(interface == nullptr, nullptr); return (WebRTCDataChannel *)interface->create_data_channel(interface->data, p_label.utf8().get_data(), (const godot_dictionary *)&p_options); } Error WebRTCPeerConnectionGDNative::create_offer() { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->create_offer(interface->data); } Error WebRTCPeerConnectionGDNative::set_local_description(String p_type, String p_sdp) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->set_local_description(interface->data, p_type.utf8().get_data(), p_sdp.utf8().get_data()); } Error WebRTCPeerConnectionGDNative::set_remote_description(String p_type, String p_sdp) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->set_remote_description(interface->data, p_type.utf8().get_data(), p_sdp.utf8().get_data()); } Error WebRTCPeerConnectionGDNative::add_ice_candidate(String sdpMidName, int sdpMlineIndexName, String sdpName) { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->add_ice_candidate(interface->data, sdpMidName.utf8().get_data(), sdpMlineIndexName, sdpName.utf8().get_data()); } Error WebRTCPeerConnectionGDNative::poll() { - ERR_FAIL_COND_V(interface == NULL, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED); return (Error)interface->poll(interface->data); } void WebRTCPeerConnectionGDNative::close() { - ERR_FAIL_COND(interface == NULL); + ERR_FAIL_COND(interface == nullptr); interface->close(interface->data); } WebRTCPeerConnection::ConnectionState WebRTCPeerConnectionGDNative::get_connection_state() const { - ERR_FAIL_COND_V(interface == NULL, STATE_DISCONNECTED); + ERR_FAIL_COND_V(interface == nullptr, STATE_DISCONNECTED); return (ConnectionState)interface->get_connection_state(interface->data); } diff --git a/modules/webrtc/webrtc_peer_connection_js.cpp b/modules/webrtc/webrtc_peer_connection_js.cpp index a84dabab72..593c3a5162 100644 --- a/modules/webrtc/webrtc_peer_connection_js.cpp +++ b/modules/webrtc/webrtc_peer_connection_js.cpp @@ -279,7 +279,7 @@ Ref<WebRTCDataChannel> WebRTCPeerConnectionJS::create_data_channel(String p_chan } }, _js_id, p_channel.utf8().get_data(), config.utf8().get_data()); /* clang-format on */ - ERR_FAIL_COND_V(id == 0, NULL); + ERR_FAIL_COND_V(id == 0, nullptr); return memnew(WebRTCDataChannelJS(id)); } diff --git a/modules/webrtc/webrtc_peer_connection_js.h b/modules/webrtc/webrtc_peer_connection_js.h index 6540077e84..cdaf3068e3 100644 --- a/modules/webrtc/webrtc_peer_connection_js.h +++ b/modules/webrtc/webrtc_peer_connection_js.h @@ -36,7 +36,6 @@ #include "webrtc_peer_connection.h" class WebRTCPeerConnectionJS : public WebRTCPeerConnection { - private: int _js_id; ConnectionState _conn_state; diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub index 033169411f..af60055855 100644 --- a/modules/websocket/SCsub +++ b/modules/websocket/SCsub @@ -1,13 +1,13 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") # Thirdparty source files env_ws = env_modules.Clone() -if env['builtin_wslay'] and not env["platform"] == "javascript": # already builtin for javascript +if env["builtin_wslay"] and not env["platform"] == "javascript": # already builtin for javascript wslay_dir = "#thirdparty/wslay/" wslay_sources = [ "wslay_net.c", diff --git a/modules/websocket/config.py b/modules/websocket/config.py index f59ef432b4..9e27a1a0fe 100644 --- a/modules/websocket/config.py +++ b/modules/websocket/config.py @@ -1,16 +1,19 @@ def can_build(env, platform): return True + def configure(env): pass + def get_doc_classes(): return [ "WebSocketClient", "WebSocketMultiplayerPeer", "WebSocketPeer", - "WebSocketServer" + "WebSocketServer", ] + def get_doc_path(): return "doc_classes" diff --git a/modules/websocket/editor_debugger_server_websocket.cpp b/modules/websocket/editor_debugger_server_websocket.cpp new file mode 100644 index 0000000000..95ea7ceafa --- /dev/null +++ b/modules/websocket/editor_debugger_server_websocket.cpp @@ -0,0 +1,93 @@ +/*************************************************************************/ +/* editor_debugger_server_websocket.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "editor_debugger_server_websocket.h" + +#include "core/project_settings.h" +#include "editor/editor_settings.h" +#include "modules/websocket/remote_debugger_peer_websocket.h" + +void EditorDebuggerServerWebSocket::_peer_connected(int p_id, String _protocol) { + pending_peers.push_back(p_id); +} + +void EditorDebuggerServerWebSocket::_peer_disconnected(int p_id, bool p_was_clean) { + if (pending_peers.find(p_id)) { + pending_peers.erase(p_id); + } +} + +void EditorDebuggerServerWebSocket::poll() { + server->poll(); +} + +Error EditorDebuggerServerWebSocket::start() { + int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port"); + Vector<String> protocols; + protocols.push_back("binary"); // compatibility with EMSCRIPTEN TCP-to-WebSocket layer. + return server->listen(remote_port, protocols); +} + +void EditorDebuggerServerWebSocket::stop() { + server->stop(); + pending_peers.clear(); +} + +bool EditorDebuggerServerWebSocket::is_active() const { + return server->is_listening(); +} + +bool EditorDebuggerServerWebSocket::is_connection_available() const { + return pending_peers.size() > 0; +} + +Ref<RemoteDebuggerPeer> EditorDebuggerServerWebSocket::take_connection() { + ERR_FAIL_COND_V(!is_connection_available(), Ref<RemoteDebuggerPeer>()); + RemoteDebuggerPeer *peer = memnew(RemoteDebuggerPeerWebSocket(server->get_peer(pending_peers[0]))); + pending_peers.pop_front(); + return peer; +} + +EditorDebuggerServerWebSocket::EditorDebuggerServerWebSocket() { + server = Ref<WebSocketServer>(WebSocketServer::create()); + int max_pkts = (int)GLOBAL_GET("network/limits/debugger/max_queued_messages"); + server->set_buffers(8192, max_pkts, 8192, max_pkts); + server->connect("client_connected", callable_mp(this, &EditorDebuggerServerWebSocket::_peer_connected)); + server->connect("client_disconnected", callable_mp(this, &EditorDebuggerServerWebSocket::_peer_disconnected)); +} + +EditorDebuggerServerWebSocket::~EditorDebuggerServerWebSocket() { + stop(); +} + +EditorDebuggerServer *EditorDebuggerServerWebSocket::create(const String &p_protocol) { + ERR_FAIL_COND_V(p_protocol != "ws://", nullptr); + return memnew(EditorDebuggerServerWebSocket); +} diff --git a/modules/websocket/editor_debugger_server_websocket.h b/modules/websocket/editor_debugger_server_websocket.h new file mode 100644 index 0000000000..c66db1b72a --- /dev/null +++ b/modules/websocket/editor_debugger_server_websocket.h @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* editor_debugger_server_websocket.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H +#define SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H + +#include "modules/websocket/websocket_server.h" + +#include "editor/debugger/editor_debugger_server.h" + +class EditorDebuggerServerWebSocket : public EditorDebuggerServer { + GDCLASS(EditorDebuggerServerWebSocket, EditorDebuggerServer); + +private: + Ref<WebSocketServer> server; + List<int> pending_peers; + +public: + static EditorDebuggerServer *create(const String &p_protocol); + + void _peer_connected(int p_peer, String p_protocol); + void _peer_disconnected(int p_peer, bool p_was_clean); + + void poll(); + Error start(); + void stop(); + bool is_active() const; + bool is_connection_available() const; + Ref<RemoteDebuggerPeer> take_connection(); + + EditorDebuggerServerWebSocket(); + ~EditorDebuggerServerWebSocket(); +}; + +#endif // SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index bbe4d6dc5b..7c31449709 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -65,7 +65,6 @@ EMSCRIPTEN_KEEPALIVE void _esws_on_close(void *obj, int code, char *reason, int } Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) { - String proto_string; for (int i = 0; i < p_protocols.size(); i++) { if (i != 0) @@ -142,14 +141,14 @@ Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, } var len = buffer.length*buffer.BYTES_PER_ELEMENT; - var out = Module._malloc(len); - Module.HEAPU8.set(buffer, out); + var out = _malloc(len); + HEAPU8.set(buffer, out); ccall("_esws_on_message", "void", ["number", "number", "number", "number"], [c_ptr, out, len, is_string] ); - Module._free(out); + _free(out); }); socket.addEventListener("error", function (event) { @@ -190,12 +189,10 @@ void EMWSClient::poll() { } Ref<WebSocketPeer> EMWSClient::get_peer(int p_peer_id) const { - return _peer; } NetworkedMultiplayerPeer::ConnectionStatus EMWSClient::get_connection_status() const { - if (_peer->is_connected_to_host()) { if (_is_connecting) return CONNECTION_CONNECTING; @@ -206,17 +203,14 @@ NetworkedMultiplayerPeer::ConnectionStatus EMWSClient::get_connection_status() c }; void EMWSClient::disconnect_from_host(int p_code, String p_reason) { - _peer->close(p_code, p_reason); }; IP_Address EMWSClient::get_connected_host() const { - ERR_FAIL_V_MSG(IP_Address(), "Not supported in HTML5 export."); }; uint16_t EMWSClient::get_connected_port() const { - ERR_FAIL_V_MSG(0, "Not supported in HTML5 export."); }; @@ -231,8 +225,9 @@ Error EMWSClient::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffe } EMWSClient::EMWSClient() { - _in_buf_size = nearest_shift((int)GLOBAL_GET(WSC_IN_BUF) - 1) + 10; - _in_pkt_size = nearest_shift((int)GLOBAL_GET(WSC_IN_PKT) - 1); + _in_buf_size = DEF_BUF_SHIFT; + _in_pkt_size = DEF_PKT_SHIFT; + _is_connecting = false; _peer = Ref<EMWSPeer>(memnew(EMWSPeer)); /* clang-format off */ @@ -243,7 +238,6 @@ EMWSClient::EMWSClient() { }; EMWSClient::~EMWSClient() { - disconnect_from_host(); _peer = Ref<EMWSPeer>(); /* clang-format off */ diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h index 9f1c220ed4..ab8a0612bb 100644 --- a/modules/websocket/emws_client.h +++ b/modules/websocket/emws_client.h @@ -38,7 +38,6 @@ #include "websocket_client.h" class EMWSClient : public WebSocketClient { - GDCIIMPL(EMWSClient, WebSocketClient); private: diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp index 9472daa620..749f45451a 100644 --- a/modules/websocket/emws_peer.cpp +++ b/modules/websocket/emws_peer.cpp @@ -34,7 +34,6 @@ #include "core/io/ip.h" void EMWSPeer::set_sock(int p_sock, unsigned int p_in_buf_size, unsigned int p_in_pkt_size) { - peer_sock = p_sock; _in_buffer.resize(p_in_pkt_size, p_in_buf_size); _packet_buffer.resize((1 << p_in_buf_size)); @@ -49,13 +48,11 @@ EMWSPeer::WriteMode EMWSPeer::get_write_mode() const { } Error EMWSPeer::read_msg(uint8_t *p_data, uint32_t p_size, bool p_is_string) { - uint8_t is_string = p_is_string ? 1 : 0; return _in_buffer.write_packet(p_data, p_size, &is_string); } Error EMWSPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - int is_bin = write_mode == WebSocketPeer::WRITE_MODE_BINARY ? 1 : 0; /* clang-format off */ @@ -86,7 +83,6 @@ Error EMWSPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { }; Error EMWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - if (_in_buffer.packets_left() == 0) return ERR_UNAVAILABLE; @@ -101,22 +97,18 @@ Error EMWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { }; int EMWSPeer::get_available_packet_count() const { - return _in_buffer.packets_left(); }; bool EMWSPeer::was_string_packet() const { - return _is_string; }; bool EMWSPeer::is_connected_to_host() const { - return peer_sock != -1; }; void EMWSPeer::close(int p_code, String p_reason) { - if (peer_sock != -1) { /* clang-format off */ EM_ASM({ @@ -134,17 +126,14 @@ void EMWSPeer::close(int p_code, String p_reason) { }; IP_Address EMWSPeer::get_connected_host() const { - ERR_FAIL_V_MSG(IP_Address(), "Not supported in HTML5 export."); }; uint16_t EMWSPeer::get_connected_port() const { - ERR_FAIL_V_MSG(0, "Not supported in HTML5 export."); }; void EMWSPeer::set_no_delay(bool p_enabled) { - ERR_FAIL_MSG("'set_no_delay' is not supported in HTML5 export."); } @@ -155,7 +144,6 @@ EMWSPeer::EMWSPeer() { }; EMWSPeer::~EMWSPeer() { - close(); }; diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h index 6308ebe490..9c00f2d58b 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -41,7 +41,6 @@ #include "websocket_peer.h" class EMWSPeer : public WebSocketPeer { - GDCIIMPL(EMWSPeer, WebSocketPeer); private: diff --git a/modules/websocket/emws_server.cpp b/modules/websocket/emws_server.cpp index 8ceefa42b6..9d43283d3e 100644 --- a/modules/websocket/emws_server.cpp +++ b/modules/websocket/emws_server.cpp @@ -34,7 +34,6 @@ #include "core/os/os.h" Error EMWSServer::listen(int p_port, Vector<String> p_protocols, bool gd_mp_api) { - return FAILED; } @@ -50,7 +49,7 @@ bool EMWSServer::has_peer(int p_id) const { } Ref<WebSocketPeer> EMWSServer::get_peer(int p_id) const { - return NULL; + return nullptr; } Vector<String> EMWSServer::get_protocols() const { @@ -60,12 +59,10 @@ Vector<String> EMWSServer::get_protocols() const { } IP_Address EMWSServer::get_peer_address(int p_peer_id) const { - return IP_Address(); } int EMWSServer::get_peer_port(int p_peer_id) const { - return 0; } diff --git a/modules/websocket/emws_server.h b/modules/websocket/emws_server.h index f273fd078f..bb6f35a711 100644 --- a/modules/websocket/emws_server.h +++ b/modules/websocket/emws_server.h @@ -38,7 +38,6 @@ #include "websocket_server.h" class EMWSServer : public WebSocketServer { - GDCIIMPL(EMWSServer, WebSocketServer); public: diff --git a/modules/websocket/packet_buffer.h b/modules/websocket/packet_buffer.h index ea3658c827..9973efe297 100644 --- a/modules/websocket/packet_buffer.h +++ b/modules/websocket/packet_buffer.h @@ -36,7 +36,6 @@ template <class T> class PacketBuffer { - private: typedef struct { uint32_t size; @@ -63,7 +62,7 @@ public: ERR_FAIL_COND_V(p_info && _packets.space_left() < 1, ERR_OUT_OF_MEMORY); #endif - // If p_info is NULL, only the payload is written + // If p_info is nullptr, only the payload is written if (p_info) { _Packet p; p.size = p_size; @@ -71,7 +70,7 @@ public: _packets.write(p); } - // If p_payload is NULL, only the packet information is written. + // If p_payload is nullptr, only the packet information is written. if (p_payload) { _payload.write((const uint8_t *)p_payload, p_size); } diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp index e389d75ffd..bc50de414e 100644 --- a/modules/websocket/register_types.cpp +++ b/modules/websocket/register_types.cpp @@ -40,24 +40,19 @@ #include "wsl_client.h" #include "wsl_server.h" #endif +#ifdef TOOLS_ENABLED +#include "editor/debugger/editor_debugger_server.h" +#include "editor/editor_node.h" +#include "editor_debugger_server_websocket.h" +#endif -void register_websocket_types() { -#define _SET_HINT(NAME, _VAL_, _MAX_) \ - GLOBAL_DEF(NAME, _VAL_); \ - ProjectSettings::get_singleton()->set_custom_property_info(NAME, PropertyInfo(Variant::INT, NAME, PROPERTY_HINT_RANGE, "2," #_MAX_ ",1,or_greater")); - - // Client buffers project settings - _SET_HINT(WSC_IN_BUF, 64, 4096); - _SET_HINT(WSC_IN_PKT, 1024, 16384); - _SET_HINT(WSC_OUT_BUF, 64, 4096); - _SET_HINT(WSC_OUT_PKT, 1024, 16384); - - // Server buffers project settings - _SET_HINT(WSS_IN_BUF, 64, 4096); - _SET_HINT(WSS_IN_PKT, 1024, 16384); - _SET_HINT(WSS_OUT_BUF, 64, 4096); - _SET_HINT(WSS_OUT_PKT, 1024, 16384); +#ifdef TOOLS_ENABLED +static void _editor_init_callback() { + EditorDebuggerServer::register_protocol_handler("ws://", EditorDebuggerServerWebSocket::create); +} +#endif +void register_websocket_types() { #ifdef JAVASCRIPT_ENABLED EMWSPeer::make_default(); EMWSClient::make_default(); @@ -72,6 +67,10 @@ void register_websocket_types() { ClassDB::register_custom_instance_class<WebSocketServer>(); ClassDB::register_custom_instance_class<WebSocketClient>(); ClassDB::register_custom_instance_class<WebSocketPeer>(); + +#ifdef TOOLS_ENABLED + EditorNode::add_init_callback(&_editor_init_callback); +#endif } void unregister_websocket_types() {} diff --git a/modules/websocket/register_types.h b/modules/websocket/register_types.h index b254b9dae8..bb7be57ab3 100644 --- a/modules/websocket/register_types.h +++ b/modules/websocket/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef WEBSOCKET_REGISTER_TYPES_H +#define WEBSOCKET_REGISTER_TYPES_H + void register_websocket_types(); void unregister_websocket_types(); + +#endif // WEBSOCKET_REGISTER_TYPES_H diff --git a/modules/websocket/remote_debugger_peer_websocket.cpp b/modules/websocket/remote_debugger_peer_websocket.cpp new file mode 100644 index 0000000000..a67a959e31 --- /dev/null +++ b/modules/websocket/remote_debugger_peer_websocket.cpp @@ -0,0 +1,133 @@ +/*************************************************************************/ +/* remote_debugger_peer_websocket.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "remote_debugger_peer_websocket.h" + +#include "core/project_settings.h" + +Error RemoteDebuggerPeerWebSocket::connect_to_host(const String &p_uri) { + Vector<String> protocols; + protocols.push_back("binary"); // Compatibility for emscripten TCP-to-WebSocket. + + ws_client->connect_to_url(p_uri, protocols); + ws_client->poll(); + + if (ws_client->get_connection_status() == WebSocketClient::CONNECTION_DISCONNECTED) { + ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(ws_client->get_connection_status()) + "."); + return FAILED; + } + + ws_peer = ws_client->get_peer(1); + + return OK; +} + +bool RemoteDebuggerPeerWebSocket::is_peer_connected() { + return ws_peer.is_valid() && ws_peer->is_connected_to_host(); +} + +void RemoteDebuggerPeerWebSocket::poll() { + ws_client->poll(); + + while (ws_peer->is_connected_to_host() && ws_peer->get_available_packet_count() > 0 && in_queue.size() < max_queued_messages) { + Variant var; + Error err = ws_peer->get_var(var); + ERR_CONTINUE(err != OK); + ERR_CONTINUE(var.get_type() != Variant::ARRAY); + in_queue.push_back(var); + } + + while (ws_peer->is_connected_to_host() && out_queue.size() > 0) { + Array var = out_queue[0]; + Error err = ws_peer->put_var(var); + ERR_BREAK(err != OK); // Peer buffer full? + out_queue.pop_front(); + } +} + +int RemoteDebuggerPeerWebSocket::get_max_message_size() const { + return 8 << 20; // 8 Mib +} + +bool RemoteDebuggerPeerWebSocket::has_message() { + return in_queue.size() > 0; +} + +Array RemoteDebuggerPeerWebSocket::get_message() { + ERR_FAIL_COND_V(in_queue.size() < 1, Array()); + Array msg = in_queue[0]; + in_queue.pop_front(); + return msg; +} + +Error RemoteDebuggerPeerWebSocket::put_message(const Array &p_arr) { + if (out_queue.size() >= max_queued_messages) { + return ERR_OUT_OF_MEMORY; + } + out_queue.push_back(p_arr); + return OK; +} + +void RemoteDebuggerPeerWebSocket::close() { + if (ws_peer.is_valid()) { + ws_peer.unref(); + } + ws_client->disconnect_from_host(); +} + +bool RemoteDebuggerPeerWebSocket::can_block() const { +#ifdef JAVASCRIPT_ENABLED + return false; +#else + return true; +#endif +} + +RemoteDebuggerPeerWebSocket::RemoteDebuggerPeerWebSocket(Ref<WebSocketPeer> p_peer) { +#ifdef JAVASCRIPT_ENABLED + ws_client = Ref<WebSocketClient>(memnew(EMWSClient)); +#else + ws_client = Ref<WebSocketClient>(memnew(WSLClient)); +#endif + max_queued_messages = (int)GLOBAL_GET("network/limits/debugger/max_queued_messages"); + ws_client->set_buffers(8192, max_queued_messages, 8192, max_queued_messages); + ws_peer = p_peer; +} + +RemoteDebuggerPeer *RemoteDebuggerPeerWebSocket::create(const String &p_uri) { + ERR_FAIL_COND_V(!p_uri.begins_with("ws://") && !p_uri.begins_with("wss://"), nullptr); + RemoteDebuggerPeerWebSocket *peer = memnew(RemoteDebuggerPeerWebSocket); + Error err = peer->connect_to_host(p_uri); + if (err != OK) { + memdelete(peer); + return nullptr; + } + return peer; +} diff --git a/modules/websocket/remote_debugger_peer_websocket.h b/modules/websocket/remote_debugger_peer_websocket.h new file mode 100644 index 0000000000..bb03e5e892 --- /dev/null +++ b/modules/websocket/remote_debugger_peer_websocket.h @@ -0,0 +1,65 @@ +/*************************************************************************/ +/* remote_debugger_peer_websocket.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SCRIPT_DEBUGGER_WEBSOCKET_H +#define SCRIPT_DEBUGGER_WEBSOCKET_H + +#ifdef JAVASCRIPT_ENABLED +#include "modules/websocket/emws_client.h" +#else +#include "modules/websocket/wsl_client.h" +#endif +#include "core/debugger/remote_debugger_peer.h" + +class RemoteDebuggerPeerWebSocket : public RemoteDebuggerPeer { + Ref<WebSocketClient> ws_client; + Ref<WebSocketPeer> ws_peer; + List<Array> in_queue; + List<Array> out_queue; + + int max_queued_messages; + +public: + static RemoteDebuggerPeer *create(const String &p_uri); + + Error connect_to_host(const String &p_uri); + bool is_peer_connected(); + int get_max_message_size() const; + bool has_message(); + Error put_message(const Array &p_arr); + Array get_message(); + void close(); + void poll(); + bool can_block() const; + + RemoteDebuggerPeerWebSocket(Ref<WebSocketPeer> p_peer = Ref<WebSocketPeer>()); +}; + +#endif // SCRIPT_DEBUGGER_WEBSOCKET_H diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp index 7ee4b990b5..3900180739 100644 --- a/modules/websocket/websocket_client.cpp +++ b/modules/websocket/websocket_client.cpp @@ -33,7 +33,6 @@ GDCINULL(WebSocketClient); WebSocketClient::WebSocketClient() { - verify_ssl = true; } @@ -54,8 +53,9 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto port = 443; } else { ssl = false; - if (host.begins_with("ws://")) + if (host.begins_with("ws://")) { host = host.substr(5, host.length() - 5); + } } // Path @@ -76,33 +76,27 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto } void WebSocketClient::set_verify_ssl_enabled(bool p_verify_ssl) { - verify_ssl = p_verify_ssl; } bool WebSocketClient::is_verify_ssl_enabled() const { - return verify_ssl; } Ref<X509Certificate> WebSocketClient::get_trusted_ssl_certificate() const { - return ssl_cert; } void WebSocketClient::set_trusted_ssl_certificate(Ref<X509Certificate> p_cert) { - ERR_FAIL_COND(get_connection_status() != CONNECTION_DISCONNECTED); ssl_cert = p_cert; } bool WebSocketClient::is_server() const { - return false; } void WebSocketClient::_on_peer_packet() { - if (_is_multiplayer) { _process_multiplayer(get_peer(1), 1); } else { @@ -111,7 +105,6 @@ void WebSocketClient::_on_peer_packet() { } void WebSocketClient::_on_connect(String p_protocol) { - if (_is_multiplayer) { // need to wait for ID confirmation... } else { @@ -120,12 +113,10 @@ void WebSocketClient::_on_connect(String p_protocol) { } void WebSocketClient::_on_close_request(int p_code, String p_reason) { - emit_signal("server_close_request", p_code, p_reason); } void WebSocketClient::_on_disconnect(bool p_was_clean) { - if (_is_multiplayer) { emit_signal("connection_failed"); } else { @@ -134,7 +125,6 @@ void WebSocketClient::_on_disconnect(bool p_was_clean) { } void WebSocketClient::_on_error() { - if (_is_multiplayer) { emit_signal("connection_failed"); } else { diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h index 4dc1224066..ba8e21aed6 100644 --- a/modules/websocket/websocket_client.h +++ b/modules/websocket/websocket_client.h @@ -37,7 +37,6 @@ #include "websocket_peer.h" class WebSocketClient : public WebSocketMultiplayerPeer { - GDCLASS(WebSocketClient, WebSocketMultiplayerPeer); GDCICLASS(WebSocketClient); diff --git a/modules/websocket/websocket_macros.h b/modules/websocket/websocket_macros.h index 8aa01a70ed..cf4545b435 100644 --- a/modules/websocket/websocket_macros.h +++ b/modules/websocket/websocket_macros.h @@ -31,15 +31,9 @@ #ifndef WEBSOCKETMACTOS_H #define WEBSOCKETMACTOS_H -#define WSC_IN_BUF "network/limits/websocket_client/max_in_buffer_kb" -#define WSC_IN_PKT "network/limits/websocket_client/max_in_packets" -#define WSC_OUT_BUF "network/limits/websocket_client/max_out_buffer_kb" -#define WSC_OUT_PKT "network/limits/websocket_client/max_out_packets" - -#define WSS_IN_BUF "network/limits/websocket_server/max_in_buffer_kb" -#define WSS_IN_PKT "network/limits/websocket_server/max_in_packets" -#define WSS_OUT_BUF "network/limits/websocket_server/max_out_buffer_kb" -#define WSS_OUT_PKT "network/limits/websocket_server/max_out_packets" +// Defaults per peer buffers, 1024 packets with a shared 65536 bytes payload. +#define DEF_PKT_SHIFT 10 +#define DEF_BUF_SHIFT 16 /* clang-format off */ #define GDCICLASS(CNAME) \ @@ -56,13 +50,13 @@ public:\ static CNAME *create() {\ \ if (!_create)\ - return NULL;\ + return nullptr;\ return _create();\ }\ protected:\ #define GDCINULL(CNAME) \ -CNAME *(*CNAME::_create)() = NULL; +CNAME *(*CNAME::_create)() = nullptr; #define GDCIIMPL(IMPNAME, CNAME) \ public:\ diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp index 9eb1445b35..fa2fe891a5 100644 --- a/modules/websocket/websocket_multiplayer_peer.cpp +++ b/modules/websocket/websocket_multiplayer_peer.cpp @@ -33,7 +33,6 @@ #include "core/os/os.h" WebSocketMultiplayerPeer::WebSocketMultiplayerPeer() { - _is_multiplayer = false; _peer_id = 0; _target_peer = 0; @@ -42,20 +41,17 @@ WebSocketMultiplayerPeer::WebSocketMultiplayerPeer() { _current_packet.source = 0; _current_packet.destination = 0; _current_packet.size = 0; - _current_packet.data = NULL; + _current_packet.data = nullptr; } WebSocketMultiplayerPeer::~WebSocketMultiplayerPeer() { - _clear(); } int WebSocketMultiplayerPeer::_gen_unique_id() const { - uint32_t hash = 0; while (hash == 0 || hash == 1) { - hash = hash_djb2_one_32( (uint32_t)OS::get_singleton()->get_ticks_usec()); hash = hash_djb2_one_32( @@ -71,22 +67,22 @@ int WebSocketMultiplayerPeer::_gen_unique_id() const { return hash; } -void WebSocketMultiplayerPeer::_clear() { +void WebSocketMultiplayerPeer::_clear() { _peer_map.clear(); - if (_current_packet.data != NULL) + if (_current_packet.data != nullptr) { memfree(_current_packet.data); + } for (List<Packet>::Element *E = _incoming_packets.front(); E; E = E->next()) { memfree(E->get().data); - E->get().data = NULL; + E->get().data = nullptr; } _incoming_packets.clear(); } void WebSocketMultiplayerPeer::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_buffers", "input_buffer_size_kb", "input_max_packets", "output_buffer_size_kb", "output_max_packets"), &WebSocketMultiplayerPeer::set_buffers); ClassDB::bind_method(D_METHOD("get_peer", "peer_id"), &WebSocketMultiplayerPeer::get_peer); @@ -97,21 +93,19 @@ void WebSocketMultiplayerPeer::_bind_methods() { // PacketPeer // int WebSocketMultiplayerPeer::get_available_packet_count() const { - ERR_FAIL_COND_V_MSG(!_is_multiplayer, 0, "Please use get_peer(ID).get_available_packet_count to get available packet count from peers when not using the MultiplayerAPI."); return _incoming_packets.size(); } Error WebSocketMultiplayerPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - ERR_FAIL_COND_V_MSG(!_is_multiplayer, ERR_UNCONFIGURED, "Please use get_peer(ID).get_packet/var to communicate with peers when not using the MultiplayerAPI."); r_buffer_size = 0; - if (_current_packet.data != NULL) { + if (_current_packet.data != nullptr) { memfree(_current_packet.data); - _current_packet.data = NULL; + _current_packet.data = nullptr; } _current_packet = _incoming_packets.front()->get(); @@ -124,7 +118,6 @@ Error WebSocketMultiplayerPeer::get_packet(const uint8_t **r_buffer, int &r_buff } Error WebSocketMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - ERR_FAIL_COND_V_MSG(!_is_multiplayer, ERR_UNCONFIGURED, "Please use get_peer(ID).put_packet/var to communicate with peers when not using the MultiplayerAPI."); Vector<uint8_t> buffer = _make_pkt(SYS_NONE, get_unique_id(), _target_peer, p_buffer, p_buffer_size); @@ -140,23 +133,19 @@ Error WebSocketMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer // NetworkedMultiplayerPeer // void WebSocketMultiplayerPeer::set_transfer_mode(TransferMode p_mode) { - // Websocket uses TCP, reliable } NetworkedMultiplayerPeer::TransferMode WebSocketMultiplayerPeer::get_transfer_mode() const { - // Websocket uses TCP, reliable return TRANSFER_MODE_RELIABLE; } void WebSocketMultiplayerPeer::set_target_peer(int p_target_peer) { - _target_peer = p_target_peer; } int WebSocketMultiplayerPeer::get_packet_peer() const { - ERR_FAIL_COND_V_MSG(!_is_multiplayer, 1, "This function is not available when not using the MultiplayerAPI."); ERR_FAIL_COND_V(_incoming_packets.size() == 0, 1); @@ -164,22 +153,18 @@ int WebSocketMultiplayerPeer::get_packet_peer() const { } int WebSocketMultiplayerPeer::get_unique_id() const { - return _peer_id; } void WebSocketMultiplayerPeer::set_refuse_new_connections(bool p_enable) { - _refusing = p_enable; } bool WebSocketMultiplayerPeer::is_refusing_new_connections() const { - return _refusing; } void WebSocketMultiplayerPeer::_send_sys(Ref<WebSocketPeer> p_peer, uint8_t p_type, int32_t p_peer_id) { - ERR_FAIL_COND(!p_peer.is_valid()); ERR_FAIL_COND(!p_peer->is_connected_to_host()); @@ -188,7 +173,6 @@ void WebSocketMultiplayerPeer::_send_sys(Ref<WebSocketPeer> p_peer, uint8_t p_ty } Vector<uint8_t> WebSocketMultiplayerPeer::_make_pkt(uint8_t p_type, int32_t p_from, int32_t p_to, const uint8_t *p_data, uint32_t p_data_size) { - Vector<uint8_t> out; out.resize(PROTO_SIZE + p_data_size); @@ -202,7 +186,6 @@ Vector<uint8_t> WebSocketMultiplayerPeer::_make_pkt(uint8_t p_type, int32_t p_fr } void WebSocketMultiplayerPeer::_send_add(int32_t p_peer_id) { - // First of all, confirm the ID! _send_sys(get_peer(p_peer_id), SYS_ID, p_peer_id); @@ -211,8 +194,9 @@ void WebSocketMultiplayerPeer::_send_add(int32_t p_peer_id) { for (Map<int, Ref<WebSocketPeer>>::Element *E = _peer_map.front(); E; E = E->next()) { int32_t id = E->key(); - if (p_peer_id == id) + if (p_peer_id == id) { continue; // Skip the newwly added peer (already confirmed) + } // Send new peer to others _send_sys(get_peer(id), SYS_ADD, p_peer_id); @@ -224,8 +208,9 @@ void WebSocketMultiplayerPeer::_send_add(int32_t p_peer_id) { void WebSocketMultiplayerPeer::_send_del(int32_t p_peer_id) { for (Map<int, Ref<WebSocketPeer>>::Element *E = _peer_map.front(); E; E = E->next()) { int32_t id = E->key(); - if (p_peer_id != id) + if (p_peer_id != id) { _send_sys(get_peer(id), SYS_DEL, p_peer_id); + } } } @@ -242,27 +227,25 @@ void WebSocketMultiplayerPeer::_store_pkt(int32_t p_source, int32_t p_dest, cons Error WebSocketMultiplayerPeer::_server_relay(int32_t p_from, int32_t p_to, const uint8_t *p_buffer, uint32_t p_buffer_size) { if (p_to == 1) { - return OK; // Will not send to self } else if (p_to == 0) { - for (Map<int, Ref<WebSocketPeer>>::Element *E = _peer_map.front(); E; E = E->next()) { - if (E->key() != p_from) + if (E->key() != p_from) { E->get()->put_packet(p_buffer, p_buffer_size); + } } return OK; // Sent to all but sender } else if (p_to < 0) { - for (Map<int, Ref<WebSocketPeer>>::Element *E = _peer_map.front(); E; E = E->next()) { - if (E->key() != p_from && E->key() != -p_to) + if (E->key() != p_from && E->key() != -p_to) { E->get()->put_packet(p_buffer, p_buffer_size); + } } return OK; // Sent to all but sender and excluded } else { - ERR_FAIL_COND_V(p_to == p_from, FAILED); Ref<WebSocketPeer> peer_to = get_peer(p_to); @@ -273,7 +256,6 @@ Error WebSocketMultiplayerPeer::_server_relay(int32_t p_from, int32_t p_to, cons } void WebSocketMultiplayerPeer::_process_multiplayer(Ref<WebSocketPeer> p_peer, uint32_t p_peer_id) { - ERR_FAIL_COND(!p_peer.is_valid()); const uint8_t *in_buffer; @@ -304,21 +286,19 @@ void WebSocketMultiplayerPeer::_process_multiplayer(Ref<WebSocketPeer> p_peer, u _store_pkt(from, to, in_buffer, data_size); } else if (to == 0) { - // Broadcast, for us too _store_pkt(from, to, in_buffer, data_size); } else if (to < 0) { - // All but one, for us if not excluded - if (_peer_id != -(int32_t)p_peer_id) + if (_peer_id != -(int32_t)p_peer_id) { _store_pkt(from, to, in_buffer, data_size); + } } // Relay if needed (i.e. "to" includes a peer that is not the server) _server_relay(from, to, in_buffer, size); } else { - if (type == SYS_NONE) { // Payload message _store_pkt(from, to, in_buffer, data_size); @@ -331,12 +311,12 @@ void WebSocketMultiplayerPeer::_process_multiplayer(Ref<WebSocketPeer> p_peer, u copymem(&id, &in_buffer[PROTO_SIZE], 4); switch (type) { - case SYS_ADD: // Add peer _peer_map[id] = Ref<WebSocketPeer>(); emit_signal("peer_connected", id); - if (id == 1) // We just connected to the server + if (id == 1) { // We just connected to the server emit_signal("connection_succeeded"); + } break; case SYS_DEL: // Remove peer diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h index c6669c730c..3ee26e2c5b 100644 --- a/modules/websocket/websocket_multiplayer_peer.h +++ b/modules/websocket/websocket_multiplayer_peer.h @@ -37,7 +37,6 @@ #include "websocket_peer.h" class WebSocketMultiplayerPeer : public NetworkedMultiplayerPeer { - GDCLASS(WebSocketMultiplayerPeer, NetworkedMultiplayerPeer); private: diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index d4173600ec..5f7d1c768b 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -36,7 +36,6 @@ #include "websocket_macros.h" class WebSocketPeer : public PacketPeer { - GDCLASS(WebSocketPeer, PacketPeer); GDCICLASS(WebSocketPeer); diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp index a7ced65543..b20b925dec 100644 --- a/modules/websocket/websocket_server.cpp +++ b/modules/websocket/websocket_server.cpp @@ -41,7 +41,6 @@ WebSocketServer::~WebSocketServer() { } void WebSocketServer::_bind_methods() { - ClassDB::bind_method(D_METHOD("is_listening"), &WebSocketServer::is_listening); ClassDB::bind_method(D_METHOD("listen", "port", "protocols", "gd_mp_api"), &WebSocketServer::listen, DEFVAL(Vector<String>()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("stop"), &WebSocketServer::stop); @@ -110,19 +109,18 @@ void WebSocketServer::set_ca_chain(Ref<X509Certificate> p_ca_chain) { } NetworkedMultiplayerPeer::ConnectionStatus WebSocketServer::get_connection_status() const { - if (is_listening()) + if (is_listening()) { return CONNECTION_CONNECTED; + } return CONNECTION_DISCONNECTED; } bool WebSocketServer::is_server() const { - return true; } void WebSocketServer::_on_peer_packet(int32_t p_peer_id) { - if (_is_multiplayer) { _process_multiplayer(get_peer(p_peer_id), p_peer_id); } else { @@ -131,7 +129,6 @@ void WebSocketServer::_on_peer_packet(int32_t p_peer_id) { } void WebSocketServer::_on_connect(int32_t p_peer_id, String p_protocol) { - if (_is_multiplayer) { // Send add to clients _send_add(p_peer_id); @@ -142,7 +139,6 @@ void WebSocketServer::_on_connect(int32_t p_peer_id, String p_protocol) { } void WebSocketServer::_on_disconnect(int32_t p_peer_id, bool p_was_clean) { - if (_is_multiplayer) { // Send delete to clients _send_del(p_peer_id); @@ -153,6 +149,5 @@ void WebSocketServer::_on_disconnect(int32_t p_peer_id, bool p_was_clean) { } void WebSocketServer::_on_close_request(int32_t p_peer_id, int p_code, String p_reason) { - emit_signal("client_close_request", p_peer_id, p_code, p_reason); } diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h index 3ce4dbe711..5df0a37945 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -37,7 +37,6 @@ #include "websocket_peer.h" class WebSocketServer : public WebSocketMultiplayerPeer { - GDCLASS(WebSocketServer, WebSocketMultiplayerPeer); GDCICLASS(WebSocketServer); diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp index bada750ec2..7d16c2e99f 100644 --- a/modules/websocket/wsl_client.cpp +++ b/modules/websocket/wsl_client.cpp @@ -117,10 +117,11 @@ bool WSLClient::_verify_headers(String &r_protocol) { ERR_FAIL_COND_V_MSG(header.size() != 2, false, "Invalid header -> " + psa[i] + "."); String name = header[0].to_lower(); String value = header[1].strip_edges(); - if (headers.has(name)) + if (headers.has(name)) { headers[name] += "," + value; - else + } else { headers[name] = value; + } } #define _WSL_CHECK(NAME, VALUE) \ @@ -142,19 +143,20 @@ bool WSLClient::_verify_headers(String &r_protocol) { r_protocol = headers["sec-websocket-protocol"]; bool valid = false; for (int i = 0; i < _protocols.size(); i++) { - if (_protocols[i] != r_protocol) + if (_protocols[i] != r_protocol) { continue; + } valid = true; break; } - if (!valid) + if (!valid) { return false; + } } return true; } Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) { - ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE); _peer = Ref<WSLPeer>(memnew(WSLPeer)); @@ -200,8 +202,9 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, if (p_protocols.size() > 0) { request += "Sec-WebSocket-Protocol: "; for (int i = 0; i < p_protocols.size(); i++) { - if (i != 0) + if (i != 0) { request += ","; + } request += p_protocols[i]; } request += "\r\n"; @@ -229,8 +232,9 @@ void WSLClient::poll() { return; } - if (_connection.is_null()) + if (_connection.is_null()) { return; // Not connected. + } switch (_tcp->get_status()) { case StreamPeerTCP::STATUS_NONE: @@ -257,9 +261,9 @@ void WSLClient::poll() { ERR_FAIL_COND(ssl.is_null()); // Bug? ssl->poll(); } - if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) + if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) { return; // Need more polling. - else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) { + } else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) { disconnect_from_host(); _on_error(); return; // Error. @@ -278,27 +282,26 @@ void WSLClient::poll() { } Ref<WebSocketPeer> WSLClient::get_peer(int p_peer_id) const { - - ERR_FAIL_COND_V(p_peer_id != 1, NULL); + ERR_FAIL_COND_V(p_peer_id != 1, nullptr); return _peer; } NetworkedMultiplayerPeer::ConnectionStatus WSLClient::get_connection_status() const { - - if (_peer->is_connected_to_host()) + if (_peer->is_connected_to_host()) { return CONNECTION_CONNECTED; + } - if (_tcp->is_connected_to_host()) + if (_tcp->is_connected_to_host()) { return CONNECTION_CONNECTING; + } return CONNECTION_DISCONNECTED; } void WSLClient::disconnect_from_host(int p_code, String p_reason) { - _peer->close(p_code, p_reason); - _connection = Ref<StreamPeer>(NULL); + _connection = Ref<StreamPeer>(nullptr); _tcp = Ref<StreamPeerTCP>(memnew(StreamPeerTCP)); _key = ""; @@ -314,13 +317,11 @@ void WSLClient::disconnect_from_host(int p_code, String p_reason) { } IP_Address WSLClient::get_connected_host() const { - ERR_FAIL_COND_V(!_peer->is_connected_to_host(), IP_Address()); return _peer->get_connected_host(); } uint16_t WSLClient::get_connected_port() const { - ERR_FAIL_COND_V(!_peer->is_connected_to_host(), 0); return _peer->get_connected_port(); } @@ -336,10 +337,10 @@ Error WSLClient::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer } WSLClient::WSLClient() { - _in_buf_size = nearest_shift((int)GLOBAL_GET(WSC_IN_BUF) - 1) + 10; - _in_pkt_size = nearest_shift((int)GLOBAL_GET(WSC_IN_PKT) - 1); - _out_buf_size = nearest_shift((int)GLOBAL_GET(WSC_OUT_BUF) - 1) + 10; - _out_pkt_size = nearest_shift((int)GLOBAL_GET(WSC_OUT_PKT) - 1); + _in_buf_size = DEF_BUF_SHIFT; + _in_pkt_size = DEF_PKT_SHIFT; + _out_buf_size = DEF_BUF_SHIFT; + _out_pkt_size = DEF_PKT_SHIFT; _peer.instance(); _tcp.instance(); @@ -347,7 +348,6 @@ WSLClient::WSLClient() { } WSLClient::~WSLClient() { - _peer->close_now(); _peer->invalidate(); disconnect_from_host(); diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h index 2cecfd97ee..8355a5a737 100644 --- a/modules/websocket/wsl_client.h +++ b/modules/websocket/wsl_client.h @@ -41,7 +41,6 @@ #include "wslay/wslay.h" class WSLClient : public WebSocketClient { - GDCIIMPL(WSLClient, WebSocketClient); private: diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp index ff32e83dc1..bf1ba43f8a 100644 --- a/modules/websocket/wsl_peer.cpp +++ b/modules/websocket/wsl_peer.cpp @@ -60,8 +60,9 @@ String WSLPeer::compute_key_response(String p_key) { } void WSLPeer::_wsl_destroy(struct PeerData **p_data) { - if (!p_data || !(*p_data)) + if (!p_data || !(*p_data)) { return; + } struct PeerData *data = *p_data; if (data->polling) { data->destroy = true; @@ -69,7 +70,7 @@ void WSLPeer::_wsl_destroy(struct PeerData **p_data) { } wslay_event_context_free(data->ctx); memdelete(data); - *p_data = NULL; + *p_data = nullptr; } bool WSLPeer::_wsl_poll(struct PeerData *p_data) { @@ -147,8 +148,9 @@ void wsl_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event } WSLPeer *peer = (WSLPeer *)peer_data->peer; - if (peer->parse_message(arg) != OK) + if (peer->parse_message(arg) != OK) { return; + } if (peer_data->is_server) { WSLServer *helper = (WSLServer *)peer_data->obj; @@ -163,9 +165,9 @@ wslay_event_callbacks wsl_callbacks = { wsl_recv_callback, wsl_send_callback, wsl_genmask_callback, - NULL, /* on_frame_recv_start_callback */ - NULL, /* on_frame_recv_callback */ - NULL, /* on_frame_recv_end_callback */ + nullptr, /* on_frame_recv_start_callback */ + nullptr, /* on_frame_recv_callback */ + nullptr, /* on_frame_recv_end_callback */ wsl_msg_recv_callback }; @@ -199,8 +201,8 @@ Error WSLPeer::parse_message(const wslay_event_on_msg_recv_arg *arg) { } void WSLPeer::make_context(PeerData *p_data, unsigned int p_in_buf_size, unsigned int p_in_pkt_size, unsigned int p_out_buf_size, unsigned int p_out_pkt_size) { - ERR_FAIL_COND(_data != NULL); - ERR_FAIL_COND(p_data == NULL); + ERR_FAIL_COND(_data != nullptr); + ERR_FAIL_COND(p_data == nullptr); _in_buffer.resize(p_in_pkt_size, p_in_buf_size); _packet_buffer.resize((1 << MAX(p_in_buf_size, p_out_buf_size))); @@ -209,10 +211,11 @@ void WSLPeer::make_context(PeerData *p_data, unsigned int p_in_buf_size, unsigne _data->peer = this; _data->valid = true; - if (_data->is_server) + if (_data->is_server) { wslay_event_context_server_init(&(_data->ctx), &wsl_callbacks, _data); - else + } else { wslay_event_context_client_init(&(_data->ctx), &wsl_callbacks, _data); + } wslay_event_config_set_max_recv_msg_length(_data->ctx, (1ULL << p_in_buf_size)); } @@ -225,16 +228,16 @@ WSLPeer::WriteMode WSLPeer::get_write_mode() const { } void WSLPeer::poll() { - if (!_data) + if (!_data) { return; + } if (_wsl_poll(_data)) { - _data = NULL; + _data = nullptr; } } Error WSLPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - ERR_FAIL_COND_V(!is_connected_to_host(), FAILED); struct wslay_event_msg msg; // Should I use fragmented? @@ -251,13 +254,13 @@ Error WSLPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { } Error WSLPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - r_buffer_size = 0; ERR_FAIL_COND_V(!is_connected_to_host(), FAILED); - if (_in_buffer.packets_left() == 0) + if (_in_buffer.packets_left() == 0) { return ERR_UNAVAILABLE; + } int read = 0; uint8_t *rw = _packet_buffer.ptrw(); @@ -270,21 +273,19 @@ Error WSLPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { } int WSLPeer::get_available_packet_count() const { - - if (!is_connected_to_host()) + if (!is_connected_to_host()) { return 0; + } return _in_buffer.packets_left(); } bool WSLPeer::was_string_packet() const { - return _is_string; } bool WSLPeer::is_connected_to_host() const { - - return _data != NULL; + return _data != nullptr; } void WSLPeer::close_now() { @@ -305,43 +306,40 @@ void WSLPeer::close(int p_code, String p_reason) { } IP_Address WSLPeer::get_connected_host() const { - ERR_FAIL_COND_V(!is_connected_to_host() || _data->tcp.is_null(), IP_Address()); return _data->tcp->get_connected_host(); } uint16_t WSLPeer::get_connected_port() const { - ERR_FAIL_COND_V(!is_connected_to_host() || _data->tcp.is_null(), 0); return _data->tcp->get_connected_port(); } void WSLPeer::set_no_delay(bool p_enabled) { - ERR_FAIL_COND(!is_connected_to_host() || _data->tcp.is_null()); _data->tcp->set_no_delay(p_enabled); } void WSLPeer::invalidate() { - if (_data) + if (_data) { _data->valid = false; + } } WSLPeer::WSLPeer() { - _data = NULL; + _data = nullptr; _is_string = 0; close_code = -1; write_mode = WRITE_MODE_BINARY; } WSLPeer::~WSLPeer() { - close(); invalidate(); _wsl_destroy(&_data); - _data = NULL; + _data = nullptr; } #endif // JAVASCRIPT_ENABLED diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index 00549cd9bc..fe4abfb64c 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -44,7 +44,6 @@ #define WSL_MAX_HEADER_SIZE 4096 class WSLPeer : public WebSocketPeer { - GDCIIMPL(WSLPeer, WebSocketPeer); public: @@ -67,10 +66,10 @@ public: valid = false; is_server = false; id = 1; - ctx = NULL; - obj = NULL; + ctx = nullptr; + obj = nullptr; closing = false; - peer = NULL; + peer = nullptr; } }; diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp index b66cdf3ea2..da7bfc70c0 100644 --- a/modules/websocket/wsl_server.cpp +++ b/modules/websocket/wsl_server.cpp @@ -60,10 +60,11 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) { ERR_FAIL_COND_V_MSG(header.size() != 2, false, "Invalid header -> " + psa[i]); String name = header[0].to_lower(); String value = header[1].strip_edges(); - if (headers.has(name)) + if (headers.has(name)) { headers[name] += "," + value; - else + } else { headers[name] = value; + } } #define _WSL_CHECK(NAME, VALUE) \ ERR_FAIL_COND_V_MSG(!headers.has(NAME) || headers[NAME].to_lower() != VALUE, false, \ @@ -83,44 +84,52 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols) { String proto = protos[i].strip_edges(); // Check if we have the given protocol for (int j = 0; j < p_protocols.size(); j++) { - if (proto != p_protocols[j]) + if (proto != p_protocols[j]) { continue; + } protocol = proto; break; } // Found a protocol - if (protocol != "") + if (protocol != "") { break; + } } - if (protocol == "") // Invalid protocol(s) requested + if (protocol == "") { // Invalid protocol(s) requested return false; - } else if (p_protocols.size() > 0) // No protocol requested, but we need one + } + } else if (p_protocols.size() > 0) { // No protocol requested, but we need one return false; + } return true; } Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols) { - if (OS::get_singleton()->get_ticks_msec() - time > WSL_SERVER_TIMEOUT) + if (OS::get_singleton()->get_ticks_msec() - time > WSL_SERVER_TIMEOUT) { return ERR_TIMEOUT; + } if (use_ssl) { Ref<StreamPeerSSL> ssl = static_cast<Ref<StreamPeerSSL>>(connection); - if (ssl.is_null()) + if (ssl.is_null()) { return FAILED; + } ssl->poll(); - if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) + if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) { return ERR_BUSY; - else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) + } else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) { return FAILED; + } } if (!has_request) { int read = 0; while (true) { ERR_FAIL_COND_V_MSG(req_pos >= WSL_MAX_HEADER_SIZE, ERR_OUT_OF_MEMORY, "Response headers too big."); Error err = connection->get_partial_data(&req_buf[req_pos], 1, read); - if (err != OK) // Got an error + if (err != OK) { // Got an error return FAILED; - else if (read != 1) // Busy, wait next poll + } else if (read != 1) { // Busy, wait next poll return ERR_BUSY; + } char *r = (char *)req_buf; int l = req_pos; if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') { @@ -132,8 +141,9 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols) { s += "Upgrade: websocket\r\n"; s += "Connection: Upgrade\r\n"; s += "Sec-WebSocket-Accept: " + WSLPeer::compute_key_response(key) + "\r\n"; - if (protocol != "") + if (protocol != "") { s += "Sec-WebSocket-Protocol: " + protocol + "\r\n"; + } s += "\r\n"; response = s.utf8(); has_request = true; @@ -150,8 +160,9 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols) { } response_sent += sent; } - if (response_sent < response.size() - 1) + if (response_sent < response.size() - 1) { return ERR_BUSY; + } return OK; } @@ -169,7 +180,6 @@ Error WSLServer::listen(int p_port, const Vector<String> p_protocols, bool gd_mp } void WSLServer::poll() { - List<int> remove_ids; for (Map<int, Ref<WebSocketPeer>>::Element *E = _peer_map.front(); E; E = E->next()) { Ref<WSLPeer> peer = (WSLPeer *)E->get().ptr(); @@ -217,13 +227,15 @@ void WSLServer::poll() { } remove_peers.clear(); - if (!_server->is_listening()) + if (!_server->is_listening()) { return; + } while (_server->is_connection_available()) { Ref<StreamPeerTCP> conn = _server->take_connection(); - if (is_refusing_new_connections()) + if (is_refusing_new_connections()) { continue; // Conn will go out-of-scope and be closed. + } Ref<PendingPeer> peer = memnew(PendingPeer); if (private_key.is_valid() && ssl_cert.is_valid()) { @@ -265,7 +277,7 @@ bool WSLServer::has_peer(int p_id) const { } Ref<WebSocketPeer> WSLServer::get_peer(int p_id) const { - ERR_FAIL_COND_V(!has_peer(p_id), NULL); + ERR_FAIL_COND_V(!has_peer(p_id), nullptr); return _peer_map[p_id]; } @@ -298,10 +310,10 @@ Error WSLServer::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer } WSLServer::WSLServer() { - _in_buf_size = nearest_shift((int)GLOBAL_GET(WSS_IN_BUF) - 1) + 10; - _in_pkt_size = nearest_shift((int)GLOBAL_GET(WSS_IN_PKT) - 1); - _out_buf_size = nearest_shift((int)GLOBAL_GET(WSS_OUT_BUF) - 1) + 10; - _out_pkt_size = nearest_shift((int)GLOBAL_GET(WSS_OUT_PKT) - 1); + _in_buf_size = DEF_BUF_SHIFT; + _in_pkt_size = DEF_PKT_SHIFT; + _out_buf_size = DEF_BUF_SHIFT; + _out_pkt_size = DEF_PKT_SHIFT; _server.instance(); } diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h index 2e893d6727..f86de02797 100644 --- a/modules/websocket/wsl_server.h +++ b/modules/websocket/wsl_server.h @@ -43,12 +43,10 @@ #define WSL_SERVER_TIMEOUT 1000 class WSLServer : public WebSocketServer { - GDCIIMPL(WSLServer, WebSocketServer); private: class PendingPeer : public Reference { - private: bool _parse_request(const Vector<String> p_protocols); diff --git a/modules/xatlas_unwrap/SCsub b/modules/xatlas_unwrap/SCsub index b242fd4673..c659349d05 100644 --- a/modules/xatlas_unwrap/SCsub +++ b/modules/xatlas_unwrap/SCsub @@ -1,12 +1,12 @@ #!/usr/bin/env python -Import('env') -Import('env_modules') +Import("env") +Import("env_modules") env_xatlas_unwrap = env_modules.Clone() # Thirdparty source files -if env['builtin_xatlas']: +if env["builtin_xatlas"]: thirdparty_dir = "#thirdparty/xatlas/" thirdparty_sources = [ "xatlas.cpp", diff --git a/modules/xatlas_unwrap/config.py b/modules/xatlas_unwrap/config.py index bd092bdc16..2e73c51626 100644 --- a/modules/xatlas_unwrap/config.py +++ b/modules/xatlas_unwrap/config.py @@ -1,5 +1,6 @@ def can_build(env, platform): - return (env['tools'] and platform not in ["android", "ios"]) + return env["tools"] and platform not in ["android", "ios"] + def configure(env): pass diff --git a/modules/xatlas_unwrap/register_types.cpp b/modules/xatlas_unwrap/register_types.cpp index c69b566525..6242009f67 100644 --- a/modules/xatlas_unwrap/register_types.cpp +++ b/modules/xatlas_unwrap/register_types.cpp @@ -32,14 +32,90 @@ #include "core/error_macros.h" +#include "core/crypto/crypto_core.h" + #include "thirdparty/xatlas/xatlas.h" #include <stdio.h> #include <stdlib.h> -extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y); +extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache); + +bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uvs, int **r_vertices, int *r_vertex_count, int **r_indices, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache) { + CryptoCore::MD5Context ctx; + ctx.start(); + + ctx.update((unsigned char *)&p_texel_size, sizeof(float)); + ctx.update((unsigned char *)p_indices, sizeof(int) * p_index_count); + ctx.update((unsigned char *)p_vertices, sizeof(float) * p_vertex_count); + ctx.update((unsigned char *)p_normals, sizeof(float) * p_vertex_count); + + unsigned char hash[16]; + ctx.finish(hash); + + bool cached = false; + unsigned int cache_idx = 0; + + if (r_used_cache && r_cache_size) { + //Check if hash is in cache data + + int *cache_data = r_cache_data; + int n_entries = cache_data[0]; + unsigned int r_idx = 1; + for (int i = 0; i < n_entries; ++i) { + if (memcmp(&cache_data[r_idx], hash, 16) == 0) { + cached = true; + cache_idx = r_idx; + break; + } + + r_idx += 4; // hash + r_idx += 2; // size hint + + int vertex_count = cache_data[r_idx]; + r_idx += 1; // vertex count + r_idx += vertex_count; // vertex + r_idx += vertex_count * 2; // uvs + + int index_count = cache_data[r_idx]; + r_idx += 1; // index count + r_idx += index_count; // indices + } + } + + if (r_used_cache && cached) { + int *cache_data = r_cache_data; -bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) { + // Return cache data pointer to the caller + r_cache_data = &cache_data[cache_idx]; + + cache_idx += 4; + + // Load size + *r_size_hint_x = cache_data[cache_idx]; + *r_size_hint_y = cache_data[cache_idx + 1]; + cache_idx += 2; + + // Load vertices + *r_vertex_count = cache_data[cache_idx]; + cache_idx++; + *r_vertices = &cache_data[cache_idx]; + cache_idx += *r_vertex_count; + + // Load UVs + *r_uvs = (float *)&cache_data[cache_idx]; + cache_idx += *r_vertex_count * 2; + + // Load indices + *r_index_count = cache_data[cache_idx]; + cache_idx++; + *r_indices = &cache_data[cache_idx]; + + // Return cache data size to the caller + r_cache_size = sizeof(int) * (4 + 2 + 1 + *r_vertex_count + (*r_vertex_count * 2) + 1 + *r_index_count); // hash + size hint + vertex_count + vertices + uvs + index_count + indices + r_used_cache = true; + return true; + } //set up input mesh xatlas::MeshDecl input_mesh; @@ -52,7 +128,7 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver input_mesh.vertexPositionStride = sizeof(float) * 3; input_mesh.vertexNormalData = p_normals; input_mesh.vertexNormalStride = sizeof(uint32_t) * 3; - input_mesh.vertexUvData = NULL; + input_mesh.vertexUvData = nullptr; input_mesh.vertexUvStride = 0; xatlas::ChartOptions chart_options; @@ -60,6 +136,7 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver pack_options.maxChartSize = 4096; pack_options.blockAlign = true; + pack_options.padding = 1; pack_options.texelsPerUnit = 1.0 / p_texel_size; xatlas::Atlas *atlas = xatlas::Create(); @@ -68,7 +145,7 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver ERR_FAIL_COND_V_MSG(err != xatlas::AddMeshError::Enum::Success, false, xatlas::StringForEnum(err)); printf("Generate..\n"); - xatlas::Generate(atlas, chart_options, NULL, pack_options); + xatlas::Generate(atlas, chart_options, xatlas::ParameterizeOptions(), pack_options); *r_size_hint_x = atlas->width; *r_size_hint_y = atlas->height; @@ -82,16 +159,16 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver const xatlas::Mesh &output = atlas->meshes[0]; - *r_vertex = (int *)malloc(sizeof(int) * output.vertexCount); - *r_uv = (float *)malloc(sizeof(float) * output.vertexCount * 2); - *r_index = (int *)malloc(sizeof(int) * output.indexCount); + *r_vertices = (int *)malloc(sizeof(int) * output.vertexCount); + *r_uvs = (float *)malloc(sizeof(float) * output.vertexCount * 2); + *r_indices = (int *)malloc(sizeof(int) * output.indexCount); float max_x = 0; float max_y = 0; for (uint32_t i = 0; i < output.vertexCount; i++) { - (*r_vertex)[i] = output.vertexArray[i].xref; - (*r_uv)[i * 2 + 0] = output.vertexArray[i].uv[0] / w; - (*r_uv)[i * 2 + 1] = output.vertexArray[i].uv[1] / h; + (*r_vertices)[i] = output.vertexArray[i].xref; + (*r_uvs)[i * 2 + 0] = output.vertexArray[i].uv[0] / w; + (*r_uvs)[i * 2 + 1] = output.vertexArray[i].uv[1] / h; max_x = MAX(max_x, output.vertexArray[i].uv[0]); max_y = MAX(max_y, output.vertexArray[i].uv[1]); } @@ -100,18 +177,58 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver *r_vertex_count = output.vertexCount; for (uint32_t i = 0; i < output.indexCount; i++) { - (*r_index)[i] = output.indexArray[i]; + (*r_indices)[i] = output.indexArray[i]; } *r_index_count = output.indexCount; xatlas::Destroy(atlas); - printf("Done\n"); + + if (r_used_cache) { + unsigned int new_cache_size = 4 + 2 + 1 + *r_vertex_count + (*r_vertex_count * 2) + 1 + *r_index_count; // hash + size hint + vertex_count + vertices + uvs + index_count + indices + new_cache_size *= sizeof(int); + int *new_cache_data = (int *)memalloc(new_cache_size); + unsigned int new_cache_idx = 0; + + // hash + memcpy(&new_cache_data[new_cache_idx], hash, 16); + new_cache_idx += 4; + + // size hint + new_cache_data[new_cache_idx] = *r_size_hint_x; + new_cache_data[new_cache_idx + 1] = *r_size_hint_y; + new_cache_idx += 2; + + // vertex count + new_cache_data[new_cache_idx] = *r_vertex_count; + new_cache_idx++; + + // vertices + memcpy(&new_cache_data[new_cache_idx], *r_vertices, sizeof(int) * *r_vertex_count); + new_cache_idx += *r_vertex_count; + + // uvs + memcpy(&new_cache_data[new_cache_idx], *r_uvs, sizeof(float) * *r_vertex_count * 2); + new_cache_idx += *r_vertex_count * 2; + + // index count + new_cache_data[new_cache_idx] = *r_index_count; + new_cache_idx++; + + // indices + memcpy(&new_cache_data[new_cache_idx], *r_indices, sizeof(int) * *r_index_count); + new_cache_idx += *r_index_count; + + // Return cache data to the caller + r_cache_data = new_cache_data; + r_cache_size = new_cache_size; + r_used_cache = false; + } + return true; } void register_xatlas_unwrap_types() { - array_mesh_lightmap_unwrap_callback = xatlas_mesh_lightmap_unwrap_callback; } diff --git a/modules/xatlas_unwrap/register_types.h b/modules/xatlas_unwrap/register_types.h index 3f2181fa63..fe924bab96 100644 --- a/modules/xatlas_unwrap/register_types.h +++ b/modules/xatlas_unwrap/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef XATLAS_UNWRAP_REGISTER_TYPES_H +#define XATLAS_UNWRAP_REGISTER_TYPES_H + void register_xatlas_unwrap_types(); void unregister_xatlas_unwrap_types(); + +#endif // XATLAS_UNWRAP_REGISTER_TYPES_H |