I'm encountering while working with the Godot Engine and specifically with a class called Cesium3DTileset that I've created using gdextension. I have extended this class in my GDScript, and I'm trying to modify its url property. However, I'm facing a peculiar behavior where the url is correctly set and non-empty in the GDScript context, but it appears as empty when accessed within the _process method of the Cesium3DTileset class.

Here's a summary of my setup and the issue:

Cesium3DTileset Class (C++):
I have a Cesium3DTileset class defined using gdextension in C++.
This class has a String property called url.
The class overrides the _process method to print the url property.
GDScript Extension:
In my GDScript, I extend the Cesium3DTileset class.
I set the url property using set_url("http://example.com/tileset").
I print the url property in the GDScript's _process method to confirm it's set correctly.
Observed Behavior:
When I run the game, the GDScript's _process method correctly prints the non-empty URL.
However, the _process method in the Cesium3DTileset class prints an empty string for the url property.
Here's a snippet of my code for better understanding:

// load_tileset called by _process method
void Cesium3DTileset::load_tileset( const godot::String p_url = "" )
{
    UtilityFunctions::print( "load_tileset->", url ); // print empty
    TilesetOptions options{};
void Cesium3DTileset::_bind_methods()
{
    ClassDB::bind_method( D_METHOD( "get_url" ), &Cesium3DTileset::get_url );
    ClassDB::bind_method( D_METHOD( "set_url", "p_url" ), &Cesium3DTileset::set_url );
    ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::STRING, "url" ), "set_url",
                           "get_url" );
  • xyz replied to this.
    xuwzen2024 changed the title to Issue with URL Property in GDExtension Class Extended in GDScript (Godot4.2) .

    xyz
    The codebase is extensive, I have removed some unrelated code.

    #include "Cesium3DTileset.h"
    #include "CameraManager.h"
    #include "GodotPrepareRendererResources.h"
    #include "GodotTilesetExternals.h"
    #include "HttpClientTest.h"
    #include "cesiumTestSuite.h"
    
    #include <godot_cpp/classes/engine.hpp>
    #include <godot_cpp/classes/file_access.hpp>
    #include <godot_cpp/core/class_db.hpp>
    #include <godot_cpp/templates/vector.hpp>
    #include <godot_cpp/variant/utility_functions.hpp>
    
    #include <Cesium3DTilesSelection/Tileset.h>
    #include <CesiumGeospatial/GlobeTransforms.h>
    #include <CesiumIonClient/Connection.h>
    #include <CesiumRasterOverlays/IonRasterOverlay.h>
    
    using namespace godot;
    using namespace CesiumForGodot;
    using namespace Cesium3DTilesSelection;
    
    void Cesium3DTileset::_bind_methods()
    {
        ClassDB::bind_method( D_METHOD( "get_url" ), &Cesium3DTileset::get_url );
        ClassDB::bind_method( D_METHOD( "set_url", "p_url" ), &Cesium3DTileset::set_url );
        ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::STRING, "url" ), "set_url",
                               "get_url" );
        ClassDB::bind_method( D_METHOD( "get_maximum_screen_space_error" ),
                              &Cesium3DTileset::get_maximum_screen_space_error );
        ClassDB::bind_method(
            D_METHOD( "set_maximum_screen_space_error", "p_maximum_screen_space_error" ),
            &Cesium3DTileset::set_maximum_screen_space_error );
        ClassDB::add_property( "Cesium3DTileset",
                               PropertyInfo( Variant::FLOAT, "maximum screenspace error" ),
                               "set_maximum_screen_space_error", "get_maximum_screen_space_error" );
    
        ClassDB::bind_method( D_METHOD( "get_preload_ancestors" ),
                              &Cesium3DTileset::get_preload_ancestors );
        ClassDB::bind_method( D_METHOD( "set_preload_ancestors", "p_preload_ancestors" ),
                              &Cesium3DTileset::set_preload_ancestors );
        ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::BOOL, "preload ancestors" ),
                               "set_preload_ancestors", "get_preload_ancestors" );
    
        ClassDB::bind_method( D_METHOD( "get_preload_siblings" ),
                              &Cesium3DTileset::get_preload_siblings );
        ClassDB::bind_method( D_METHOD( "set_preload_siblings", "p_preload_siblings" ),
                              &Cesium3DTileset::set_preload_siblings );
        ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::BOOL, "preload siblings" ),
                               "set_preload_siblings", "get_preload_siblings" );
    
        ClassDB::bind_method( D_METHOD( "get_forbid_holes" ), &Cesium3DTileset::get_forbid_holes );
        ClassDB::bind_method( D_METHOD( "set_forbid_holes", "p_forbid_holes" ),
                              &Cesium3DTileset::set_forbid_holes );
        ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::BOOL, "forbid holes" ),
                               "set_forbid_holes", "get_forbid_holes" );
    
        ClassDB::bind_method( D_METHOD( "get_maximum_simultaneous_tile_loads" ),
                              &Cesium3DTileset::get_maximum_simultaneous_tile_loads );
        ClassDB::bind_method(
            D_METHOD( "set_maximum_simultaneous_tile_loads", "p_maximum_simultaneous_tile_loads" ),
            &Cesium3DTileset::set_maximum_simultaneous_tile_loads );
        ClassDB::add_property(
            "Cesium3DTileset", PropertyInfo( Variant::INT, "maximum simultaneous tile loads" ),
            "set_maximum_simultaneous_tile_loads", "get_maximum_simultaneous_tile_loads" );
    
        ClassDB::bind_method( D_METHOD( "get_maximum_cached_mbytes" ),
                              &Cesium3DTileset::get_maximum_cached_mbytes );
        ClassDB::bind_method( D_METHOD( "set_maximum_cached_mbytes", "p_maximum_cached_mbytes" ),
                              &Cesium3DTileset::set_maximum_cached_mbytes );
        ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::INT, "maximum cached MB" ),
                               "set_maximum_cached_mbytes", "get_maximum_cached_mbytes" );
    
        ClassDB::bind_method( D_METHOD( "get_loading_descendant_limit" ),
                              &Cesium3DTileset::get_loading_descendant_limit );
        ClassDB::bind_method( D_METHOD( "set_loading_descendant_limit", "p_loading_descendant_limit" ),
                              &Cesium3DTileset::set_loading_descendant_limit );
        ClassDB::add_property( "Cesium3DTileset",
                               PropertyInfo( Variant::INT, "loading descendant limit" ),
                               "set_loading_descendant_limit", "get_loading_descendant_limit" );
    
        ClassDB::bind_method( D_METHOD( "get_enable_frustum_culling" ),
                              &Cesium3DTileset::get_enable_frustum_culling );
        ClassDB::bind_method( D_METHOD( "set_enable_frustum_culling", "p_enable_frustum_culling" ),
                              &Cesium3DTileset::set_enable_frustum_culling );
        ClassDB::add_property( "Cesium3DTileset",
                               PropertyInfo( Variant::BOOL, "enable frustum culling" ),
                               "set_enable_frustum_culling", "get_enable_frustum_culling" );
    
        ClassDB::bind_method( D_METHOD( "get_enable_fog_culling" ),
                              &Cesium3DTileset::get_enable_fog_culling );
        ClassDB::bind_method( D_METHOD( "set_enable_fog_culling", "p_enable_fog_culling" ),
                              &Cesium3DTileset::set_enable_fog_culling );
        ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::BOOL, "enable fog culling" ),
                               "set_enable_fog_culling", "get_enable_fog_culling" );
    
        ClassDB::bind_method( D_METHOD( "get_enforce_culled_screen_space_error" ),
                              &Cesium3DTileset::get_enforce_culled_screen_space_error );
        ClassDB::bind_method(
            D_METHOD( "set_enforce_culled_screen_space_error", "p_enforce_culled_screen_space_error" ),
            &Cesium3DTileset::set_enforce_culled_screen_space_error );
        ClassDB::add_property(
            "Cesium3DTileset", PropertyInfo( Variant::BOOL, "enforce culled screen space error" ),
            "set_enforce_culled_screen_space_error", "get_enforce_culled_screen_space_error" );
    
        ClassDB::bind_method( D_METHOD( "get_culled_screen_space_error" ),
                              &Cesium3DTileset::get_culled_screen_space_error );
        ClassDB::bind_method(
            D_METHOD( "set_culled_screen_space_error", "p_culled_screen_space_error" ),
            &Cesium3DTileset::set_culled_screen_space_error );
        ClassDB::add_property( "Cesium3DTileset",
                               PropertyInfo( Variant::FLOAT, "culled screen space error" ),
                               "set_culled_screen_space_error", "get_culled_screen_space_error" );
    
        ClassDB::bind_method( D_METHOD( "get_suspend_update" ), &Cesium3DTileset::get_suspend_update );
        ClassDB::bind_method( D_METHOD( "set_suspend_update", "p_suspend_update" ),
                              &Cesium3DTileset::set_suspend_update );
        ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::BOOL, "suspend update" ),
                               "set_suspend_update", "get_suspend_update" );
    
        ClassDB::bind_method( D_METHOD( "get_create_physics_meshes" ),
                              &Cesium3DTileset::get_create_physics_meshes );
        ClassDB::bind_method( D_METHOD( "set_create_physics_meshes", "p_create_physics_meshes" ),
                              &Cesium3DTileset::set_create_physics_meshes );
        ClassDB::add_property( "Cesium3DTileset",
                               PropertyInfo( Variant::BOOL, "create physics meshes" ),
                               "set_create_physics_meshes", "get_create_physics_meshes" );
    
        ClassDB::bind_method( D_METHOD( "get_generate_smooth_normals" ),
                              &Cesium3DTileset::get_generate_smooth_normals );
        ClassDB::bind_method( D_METHOD( "set_generate_smooth_normals", "p_generate_smooth_normals" ),
                              &Cesium3DTileset::set_generate_smooth_normals );
        ClassDB::add_property( "Cesium3DTileset",
                               PropertyInfo( Variant::BOOL, "generate smooth normals" ),
                               "set_generate_smooth_normals", "get_generate_smooth_normals" );
    
        ClassDB::bind_method( D_METHOD( "get_log_selection_stats" ),
                              &Cesium3DTileset::get_log_selection_stats );
        ClassDB::bind_method( D_METHOD( "set_log_selection_stats", "p_log_selection_stats" ),
                              &Cesium3DTileset::set_log_selection_stats );
        ClassDB::add_property( "Cesium3DTileset", PropertyInfo( Variant::BOOL, "log selection stats" ),
                               "set_log_selection_stats", "get_log_selection_stats" );
    
        ClassDB::bind_method( D_METHOD( "load_tileset" ), &Cesium3DTileset::load_tileset );
        ClassDB::bind_method( D_METHOD( "focus_tileset" ), &Cesium3DTileset::focus_tileset );
        ClassDB::bind_method( D_METHOD( "destroy_tileset" ), &Cesium3DTileset::destroy_tileset );
    }
    
    Cesium3DTileset::~Cesium3DTileset()
    {
        this->destroy_tileset();
    }
    
    void Cesium3DTileset::load_tileset( const godot::String p_url = "" )
    {
        UtilityFunctions::print( "load_tileset->", url );
        TilesetOptions options{};
        options.maximumScreenSpaceError = this->maximum_screen_space_error;
        options.preloadAncestors = this->preload_ancestors;
        options.preloadSiblings = this->preload_siblings;
        options.forbidHoles = this->forbid_holes;
        options.maximumSimultaneousTileLoads = this->maximum_simultaneous_tile_loads;
        options.maximumCachedBytes = this->maximum_cached_mbytes * 1024 * 1024;
        options.loadingDescendantLimit = this->loading_descendant_limit;
        options.enableFrustumCulling = this->enable_frustum_culling;
        options.enableFogCulling = this->enable_fog_culling;
        options.enforceCulledScreenSpaceError = this->enforce_culled_screen_space_error;
        options.culledScreenSpaceError = this->culled_screen_space_error;
        options.loadErrorCallback = []( const TilesetLoadFailureDetails &details ) {
            uint16_t statusCode = details.statusCode;
            std::string message = details.message;
            godot::StringName message_( message.c_str() );
            UtilityFunctions::printerr( "Error message: ", message_, " status code: ", statusCode );
        };
        options.mainThreadLoadingTimeLimit = 5.0;
        options.tileCacheUnloadTimeLimit = 5.0;
    
        TilesetContentOptions contentOptions{};
        contentOptions.generateMissingNormalsSmooth = this->generate_smooth_normals;
    
        CesiumGltf::SupportedGpuCompressedPixelFormats supportedFormats;
        supportedFormats.ETC2_RGBA = true;
        supportedFormats.ETC1_RGB = true;
        supportedFormats.BC1_RGB = true;
        supportedFormats.BC3_RGBA = true;
        supportedFormats.BC4_R = true;
        supportedFormats.BC5_RG = true;
        supportedFormats.BC7_RGBA = true;
        supportedFormats.ASTC_4x4_RGBA = true;
        supportedFormats.PVRTC1_4_RGB = true;
        supportedFormats.PVRTC1_4_RGBA = true;
        supportedFormats.ETC2_EAC_R11 = true;
        supportedFormats.ETC2_EAC_RG11 = true;
    
        contentOptions.ktx2TranscodeTargets =
            CesiumGltf::Ktx2TranscodeTargets( supportedFormats, false );
        contentOptions.applyTextureTransform = false;
        options.contentOptions = contentOptions;
    
        this->last_update_result = ViewUpdateResult();
        if ( !p_url.is_empty() )
        {
            url = p_url;
        }
        if ( url.is_empty() )
        {
            return;
        }
        if ( url.ends_with( ".json" ) )
        {
            std::string url_raw_str( url.utf8().get_data() );
            this->p_tileset =
                std::make_unique<Tileset>( createTilesetExternals( *this ), url_raw_str, options );
        }
    }
    
    void Cesium3DTileset::destroy_tileset()
    {
        if ( !this->p_tileset )
        {
            UtilityFunctions::print( "p_tileset is nullptr" );
            return;
        }
        UtilityFunctions::print( "Destory tileset" );
        this->p_tileset.reset();
    }
    
    
    void Cesium3DTileset::_process( double delta )
    {
        // testEditorCameraStates();
        if ( this->get_suspend_update() )
        {
            return;
        }
        if ( !this->p_tileset )
        {
            // UtilityFunctions::print( "_process check p_tileset nulptr" );
            this->load_tileset();
            if ( !this->p_tileset )
            {
                return;
            }
        }
    
        this->update_tileset_options_from_properties();
    
        std::vector<ViewState> viewStates = CameraManager::getAllCameras( *this );
        if ( viewStates.size() > 0 )
        {
            UtilityFunctions::print( "_process check viewStates size > 0" );
        }
    
        const ViewUpdateResult &updateResult =
            this->p_tileset->updateView( viewStates, static_cast<float>( delta ) );
    
        this->update_last_view_update_result_state( updateResult );
    
        for ( auto pTile : updateResult.tilesFadingOut )
        {
            if ( pTile->getState() != TileLoadState::Done )
            {
                continue;
            }
    
            const Cesium3DTilesSelection::TileContent &content = pTile->getContent();
            const Cesium3DTilesSelection::TileRenderContent *pRenderContent =
                content.getRenderContent();
            if ( pRenderContent )
            {
                CesiumGltfNode *pCesiumGltfNode =
                    static_cast<CesiumGltfNode *>( pRenderContent->getRenderResources() );
                if ( pCesiumGltfNode )
                {
                    pCesiumGltfNode->set_visible( false );
                }
            }
        }
    
        for ( auto pTile : updateResult.tilesToRenderThisFrame )
        {
            if ( pTile->getState() != TileLoadState::Done )
            {
                continue;
            }
            const Cesium3DTilesSelection::TileContent &content = pTile->getContent();
            const Cesium3DTilesSelection::TileRenderContent *pRenderContent =
                content.getRenderContent();
            if ( pRenderContent )
            {
                CesiumGltfNode *pCesiumGltfNode =
                    static_cast<CesiumGltfNode *>( pRenderContent->getRenderResources() );
                if ( pCesiumGltfNode )
                {
                    pCesiumGltfNode->set_visible( true );
                }
            }
        }
    
        this->update_load_status();
    }
    
    void Cesium3DTileset::set_url( const String p_url )
    {
        if ( url != p_url )
        {
            url = p_url;
            UtilityFunctions::print( "set_url->", url );
            this->destroy_tileset();
        }
    }
    String Cesium3DTileset::get_url() const
    {
        return url;
    }

    Furthermore, I have uploaded my project readme to Github(https://github.com/wxzen/godot-3dtiles). Feel free to check it out if you're interested. I intend to comlete the project through my own testing and then upload the first stable codebase.

    • xyz replied to this.

      xuwzen2024 Might be related to _process() thing from your other question.