touilleMan / godot-python

Python support for Godot 🐍🐍🐍
Other
1.86k stars 140 forks source link

godot.bindings has no attribute BulletPhysicsDirectSpaceState #83

Open prokopst opened 6 years ago

prokopst commented 6 years ago

I was trying to port my existing Godot C# experiment into Python and I got into weird trouble. The code follows this tutorial and explodes when trying to get self.get_world().direct_space_state on AttributeError: module 'godot.bindings' has no attribute 'BulletPhysicsDirectSpaceState'.

from godot import exposed
from godot.bindings import *
from typing import Any

@exposed
class TerrainV2(Spatial):
    _camera: Any

    def _ready(self):
        self._camera = self.get_node("/root/Spatial/Camera")
        print(self._camera)

    def _input(self, e):
        print("Event.")
        if isinstance(e, InputEventMouseButton):
            print("Got instance!")
            from_position = self._camera.project_ray_origin(e.position)
            to_position = from_position + self._camera.project_ray_normal(e.position) * 100000
            world = self.get_world()
            result = world.direct_space_state.intersect_ray(from_position, to_position)
            #             ^^^ booms here

Error:

From cffi callback <function pybind_instance_call_method at 0x000001E65D987BF8>:
Traceback (most recent call last):
  File "D:\dev\TanksAndMagic\pythonscript\windows-64-cpython\lib\godot\hazmat\ffi\instance.py", line 85, in pybind_instance_call_method
    pyret = meth(*pyargs)
  File "D:/dev/TanksAndMagic\tam\terrain_v2.py", line 21, in _input
    result = world.direct_space_state.intersect_ray(from_position, to_position)
  File "D:\dev\TanksAndMagic\pythonscript\windows-64-cpython\lib\godot\hazmat\base.py", line 250, in __getattr__
    return self.get(name)
  File "D:\dev\TanksAndMagic\pythonscript\windows-64-cpython\lib\godot\hazmat\lazy_bindings.py", line 243, in bind
    ret = gdobj_to_pyobj(rettype, ret)
  File "D:\dev\TanksAndMagic\pythonscript\windows-64-cpython\lib\godot\hazmat\tools.py", line 308, in gdobj_to_pyobj
    return variant_to_pyobj(p_gdobj)
  File "D:\dev\TanksAndMagic\pythonscript\windows-64-cpython\lib\godot\hazmat\tools.py", line 126, in variant_to_pyobj
    return getattr(godot_bindings_module, tmpobj.get_class())(p_raw)
  File "D:\dev\TanksAndMagic\pythonscript\windows-64-cpython\lib\godot\hazmat\lazy_bindings.py", line 388, in __getattr__
    return ModuleType.__getattribute__(self, name)
AttributeError: module 'godot.bindings' has no attribute 'BulletPhysicsDirectSpaceState'

Everything ^Bullet.+ in dir(godot.bindings):

BulletPhysicsDirectBodyState
BulletPhysicsServer

I can try zip my project if necessary.

touilleMan commented 6 years ago

It seems BulletPhysicsDirectSpaceState is not registered in ClassDB (running grep "register_class<BulletPhysicsDirectSpaceState" **/*.cpp on the godot codebase returns nothing). Given Python bindings is lazy and generated from Godot's ClassDB informations, this would explain your crash.

This leave open the question why C# binding is not affected (even if it's a static binding generated at compilation time, I would expect it to be generated from the ClassDB informations anyway...) You should open an issue on the main Godot project linking this issue.

prokopst commented 6 years ago

I've found that World::get_direct_space_state actually returns an instance of abstract class PhysicsDirectSpaceState. https://github.com/godotengine/godot/blob/master/scene/resources/world.h#L82

PhysicsDirectSpaceState is registered as a virtual class using register_virtual_class: https://github.com/godotengine/godot/blob/master/servers/register_server_types.cpp#L151

prokopst commented 6 years ago

FYI, such dirty workaround seems to work:

import godot.bindings as godot_bindings

godot_bindings.BulletPhysicsDirectSpaceState = godot_bindings.PhysicsDirectSpaceState

If I understand correctly C# takes the type from a method return type: https://github.com/godotengine/godot/blob/ef5672d3f94a7321ed779c922088bb72adbb1521/modules/mono/editor/bindings_generator.cpp#L1903

Not from the actual type of a value returned like Python bindings do.