godotengine / godot-cpp

C++ bindings for the Godot script API
MIT License
1.68k stars 509 forks source link

Extending the PhysicsBody3D class won't work due to missing constructor #1500

Closed samanthabeilman closed 2 months ago

samanthabeilman commented 2 months ago

Godot version

4.2

godot-cpp version

4.2

System information

Windows 11

Issue description

Hello!

I am a student and am trying to extend the PhysicsBody3D class as part of a learning exercise.

Early warning (so that nobody wastes too much time) that this may be a duplicate of: https://github.com/godotengine/godot/pull/67510 && https://github.com/godotengine/godot-cpp/issues/873.

I think that the problem may stem from the godot-cpp bindings not exposing the constructor for PhysicsBody3D. If this is intentional because it is an abstract class and is not allowed to be extended, then feel free to close this issue without responding (I truly don't want to waste your time).

When I use an empty constructor for PhysicsBody3D, the code will compile but the derived class is not available in the editor. (It says "Cannot get class 'PoolBall'. "). When I try to use the constructor with a PhysicsServer3D::BodyMode parameter, it will not compile, but I believe that that is the correct constructor to use (from reading the source code: https://github.com/godotengine/godot/blob/4.2/scene/3d/physics_body_3d.cpp#L55).

The following errors are produced when doing so:

src\pool_ball.cpp(12): error C2665: 'godot::PhysicsBody3D::PhysicsBody3D': no overloaded function could convert all the argument types
godot-cpp\gen\include\godot_cpp/classes/physics_body3d.hpp(72): note: could be 'godot::PhysicsBody3D::PhysicsBody3D(const godot::PhysicsBody3D &)'
src\pool_ball.cpp(12): note: 'godot::PhysicsBody3D::PhysicsBody3D(const godot::PhysicsBody3D &)': cannot convert argument 1 from 'godot::PhysicsServer3D::BodyMode' to 'const godot::PhysicsBody3D &'
src\pool_ball.cpp(12): note: Reason: cannot convert from 'godot::PhysicsServer3D::BodyMode' to 'const godot::PhysicsBody3D'
src\pool_ball.cpp(12): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
godot-cpp\gen\include\godot_cpp/classes/physics_body3d.hpp(53): note: or       'godot::PhysicsBody3D::PhysicsBody3D(godot::GodotObject *)'
src\pool_ball.cpp(12): note: 'godot::PhysicsBody3D::PhysicsBody3D(godot::GodotObject *)': cannot convert argument 1 from 'godot::PhysicsServer3D::BodyMode' to 'godot::GodotObject *'
src\pool_ball.cpp(12): note: Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or parenthesized function-style cast
godot-cpp\gen\include\godot_cpp/classes/physics_body3d.hpp(53): note: or       'godot::PhysicsBody3D::PhysicsBody3D(const char *)'
src\pool_ball.cpp(12): note: 'godot::PhysicsBody3D::PhysicsBody3D(const char *)': cannot convert argument 1 from 'godot::PhysicsServer3D::BodyMode' to 'const char *'
src\pool_ball.cpp(12): note: Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or parenthesized function-style cast
src\pool_ball.cpp(12): note: while trying to match the argument list '(godot::PhysicsServer3D::BodyMode)'
scons: *** [src\pool_ball.windows.template_debug.x86_64.obj] Error 2
scons: building terminated because of errors.

Apologies if the issue is due to my lack of understanding, and thank you for your time. :)


For your convenience, this is the godot-cpp\gen\include\godot_cpp\classes\physics_body3d.hpp:

/**************************************************************************/
/*  physics_body3d.hpp                                                    */
/**************************************************************************/
/*                         This file is part of:                          */
/*                             GODOT ENGINE                               */
/*                        https://godotengine.org                         */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
/*                                                                        */
/* 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.                 */
/**************************************************************************/

// THIS FILE IS GENERATED. EDITS WILL BE LOST.

#ifndef GODOT_CPP_PHYSICS_BODY3D_HPP
#define GODOT_CPP_PHYSICS_BODY3D_HPP

#include <godot_cpp/classes/collision_object3d.hpp>
#include <godot_cpp/classes/kinematic_collision3d.hpp>
#include <godot_cpp/classes/physics_server3d.hpp>
#include <godot_cpp/classes/ref.hpp>
#include <godot_cpp/variant/typed_array.hpp>

#include <godot_cpp/core/class_db.hpp>

#include <type_traits>

namespace godot {

class Node;
struct Transform3D;
struct Vector3;

class PhysicsBody3D : public CollisionObject3D {
    GDEXTENSION_CLASS(PhysicsBody3D, CollisionObject3D)

public:

    Ref<KinematicCollision3D> move_and_collide(const Vector3 &motion, bool test_only = false, double safe_margin = 0.001, bool recovery_as_collision = false, int32_t max_collisions = 1);
    bool test_move(const Transform3D &from, const Vector3 &motion, const Ref<KinematicCollision3D> &collision = nullptr, double safe_margin = 0.001, bool recovery_as_collision = false, int32_t max_collisions = 1);
    void set_axis_lock(PhysicsServer3D::BodyAxis axis, bool lock);
    bool get_axis_lock(PhysicsServer3D::BodyAxis axis) const;
    TypedArray<PhysicsBody3D> get_collision_exceptions();
    void add_collision_exception_with(Node *body);
    void remove_collision_exception_with(Node *body);
protected:
    template <typename T, typename B>
    static void register_virtuals() {
        CollisionObject3D::register_virtuals<T, B>();
    }

public:

};

} // namespace godot

#endif // ! GODOT_CPP_PHYSICS_BODY3D_HPP

(Edit: typo)

Steps to reproduce

  1. Create a derived class of PhysicsBody3D
  2. Create the constructor with either zero arguments, or one PhysicsServer::BodyMode parameter. (As seen in the minimal reproduction project)
  3. See the problem in the editor (new class not present) or in the compilation output respectively.

Minimal reproduction project

Header file

#ifndef POOL_BALL_H
#define POOL_BALL_H

#include <godot_cpp/classes/physics_body3d.hpp> 
#include <godot_cpp/classes/collision_object3d.hpp> 
#include <godot_cpp/classes/area3d.hpp> 
#include <godot_cpp/classes/node3d.hpp>

#include <godot_cpp/classes/physics_server3d.hpp>

#include <godot_cpp/core/class_db.hpp>

namespace godot {

class PoolBall : public PhysicsBody3D {
    GDCLASS(PoolBall, PhysicsBody3D);

    protected:
        static void _bind_methods();

    public:
        PoolBall();
};

}

#endif // POOL_BALL_H

C++ file

#include "pool_ball.h"

using namespace godot;

void PoolBall::_bind_methods() {}

// This one will throw errors during compilation
PoolBall::PoolBall() : PhysicsBody3D(PhysicsServer3D::BodyMode::BODY_MODE_KINEMATIC) {}
// OR the below will not give any errors during compilation, but the class is not available in the editor. 
// PoolBall::PoolBall() : PhysicsBody3D() {}
dsnopek commented 2 months ago

Abstract classes can't be extended from GDExtension. So, even if godot-cpp were modified to avoid the compiler error you're getting, unfortunately, it wouldn't work from the Godot side.

samanthabeilman commented 2 months ago

Understood! Thank you for the confirmation. I very much appreciate your time!