godot-python icon indicating copy to clipboard operation
godot-python copied to clipboard

Can't pass a python dict or array to godot

Open garyo opened this issue 7 years ago • 4 comments

In pyobj_to_variant, in tools.py, it converts python objects to Godot Variants. Unfortunately there is no case in there for a python dict or even a python array. You get a TypeError if you try.

garyo avatar May 15 '18 18:05 garyo

Yep, that's by design. The thing is list/dict require being converted to Godot Dictionary and List which is obviously costly so I wasn't sure it was a good idea to allow using native python type here. Beside, given the Godot and Python types are not strictly 100% compatible I had concern it could cause subtle bugs.

Anyway, a lot of things have changed since this design choice so I wouldn't be surprised if it's no longer relevant, so if you think it's safe to do this I trust you on this ;-)

touilleMan avatar May 16 '18 09:05 touilleMan

Please add support for dict and array even if it is very slow. A performance warning could be shown. At the current stage I just use Python for prototyping and I would have to write many iterator like interfaces to pass larger data structures.

swenner avatar Sep 16 '18 12:09 swenner

Yes I agree, at least a direct conversion from Bytes to PoolByteArray would help.

fuderiki avatar Jun 07 '19 09:06 fuderiki

I wrote some code for converting between gd and py types, you're welcome to use it or submit it as a pull request.

I have added the code to a init.py in my scripts folder, to make it easy to access from my GD python scripts.

import it as: from . import gd2py, py2gd

then use like this:

py_obj = gd2py(gd_obj)

gd_obj = py2gd(py_obj)

Here is the code, I'll be pleased if someone uses it or suggests a performance improvement - I'm having to call it many times per frame...:

"""Utilities for use by Godot Python scripts"""
from godot import *


# CONVERTING GODOT TYPES TO PYTHON

def gdDict2py(gtype):
	d = {}
	for key, value in gtype.items():
		d[gd2py(key)] = gd2py(value)
	return d


def gdArray2py(gtype):
	l = []
	for i in gtype:
		l.append(gd2py(i))
	return l


if not 'gd2py_funcs' in locals():
	gd2py_funcs = {}
	gd2py_funcs[builtins.GDString] = str
	gd2py_funcs[builtins.Array] = gdArray2py
	gd2py_funcs[builtins.Dictionary] = gdDict2py


def gd2py(gtype):
	"""Looks up the object's type and uses appropriate converter.
	If you know the type in advance, it's more performant to use
	the specific type converters.
	"""
	return gd2py_funcs.get(type(gtype),_nothing)(gtype)


# CONVERTING PYTHON TYPES TO GODOT

def pyList2gd(ptype):
	l = builtins.Array()
	for i in ptype:
		l.append(py2gd(i))
	return l


def pyDict2gd(ptype):
	d = builtins.Dictionary()
	for key, value in ptype.items():
		d[py2gd(key)] = py2gd(value)
	return d


if not 'py2gd_funcs' in locals():
	py2gd_funcs = {}
	py2gd_funcs[str] = builtins.GDString
	py2gd_funcs[list] = pyList2gd
	py2gd_funcs[dict] = pyDict2gd


def py2gd(ptype):
	"""Looks up the object's type and uses appropriate converter.
	If you know the type in advance, it's more performant to use
	the specific type converters.
	"""
	return py2gd_funcs.get(type(ptype),_nothing)(ptype)


def _nothing(_type):
	return _type

whogben avatar Aug 23 '21 01:08 whogben