Compare commits
3 Commits
master
...
standardiz
Author | SHA1 | Date |
---|---|---|
John McCardle | 5009fa0fb9 | |
John McCardle | a19781b56a | |
John McCardle | 159658521c |
|
@ -9,6 +9,11 @@ std::vector<sf::SoundBuffer> McRFPy_API::soundbuffers;
|
||||||
sf::Music McRFPy_API::music;
|
sf::Music McRFPy_API::music;
|
||||||
sf::Sound McRFPy_API::sfx;
|
sf::Sound McRFPy_API::sfx;
|
||||||
|
|
||||||
|
std::shared_ptr<PyFont> McRFPy_API::default_font;
|
||||||
|
std::shared_ptr<PyTexture> McRFPy_API::default_texture;
|
||||||
|
PyObject* McRFPy_API::mcrf_module;
|
||||||
|
|
||||||
|
|
||||||
static PyMethodDef mcrfpyMethods[] = {
|
static PyMethodDef mcrfpyMethods[] = {
|
||||||
{"registerPyAction", McRFPy_API::_registerPyAction, METH_VARARGS,
|
{"registerPyAction", McRFPy_API::_registerPyAction, METH_VARARGS,
|
||||||
"Register a callable Python object to correspond to an action string. (actionstr, callable)"},
|
"Register a callable Python object to correspond to an action string. (actionstr, callable)"},
|
||||||
|
@ -39,8 +44,15 @@ static PyMethodDef mcrfpyMethods[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyModuleDef mcrfpyModule = {
|
static PyModuleDef mcrfpyModule = {
|
||||||
PyModuleDef_HEAD_INIT, "mcrfpy", NULL, -1, mcrfpyMethods,
|
PyModuleDef_HEAD_INIT, /* m_base - Always initialize this member to PyModuleDef_HEAD_INIT. */
|
||||||
NULL, NULL, NULL, NULL
|
"mcrfpy", /* m_name */
|
||||||
|
NULL, /* m_doc - Docstring for the module; usually a docstring variable created with PyDoc_STRVAR is used. */
|
||||||
|
-1, /* m_size - Setting m_size to -1 means that the module does not support sub-interpreters, because it has global state. */
|
||||||
|
mcrfpyMethods, /* m_methods */
|
||||||
|
NULL, /* m_slots - An array of slot definitions ... When using single-phase initialization, m_slots must be NULL. */
|
||||||
|
NULL, /* traverseproc m_traverse - A traversal function to call during GC traversal of the module object */
|
||||||
|
NULL, /* inquiry m_clear - A clear function to call during GC clearing of the module object */
|
||||||
|
NULL /* freefunc m_free - A function to call during deallocation of the module object */
|
||||||
};
|
};
|
||||||
|
|
||||||
// Module initializer fn, passed to PyImport_AppendInittab
|
// Module initializer fn, passed to PyImport_AppendInittab
|
||||||
|
@ -72,11 +84,19 @@ PyObject* PyInit_mcrfpy()
|
||||||
auto t = pytypes[i];
|
auto t = pytypes[i];
|
||||||
while (t != nullptr)
|
while (t != nullptr)
|
||||||
{
|
{
|
||||||
PyType_Ready(t);
|
/*std::cout << */ PyType_Ready(t); /*<< std::endl; */
|
||||||
PyModule_AddType(m, t);
|
PyModule_AddType(m, t);
|
||||||
t = pytypes[i++];
|
t = pytypes[i++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add default_font and default_texture to module
|
||||||
|
McRFPy_API::default_font = std::make_shared<PyFont>("assets/JetbrainsMono.ttf");
|
||||||
|
McRFPy_API::default_texture = std::make_shared<PyTexture>("assets/kenney_tinydungeon.png", 16, 16);
|
||||||
|
//PyModule_AddObject(m, "default_font", McRFPy_API::default_font->pyObject());
|
||||||
|
//PyModule_AddObject(m, "default_texture", McRFPy_API::default_texture->pyObject());
|
||||||
|
PyModule_AddObject(m, "default_font", Py_None);
|
||||||
|
PyModule_AddObject(m, "default_texture", Py_None);
|
||||||
|
//McRFPy_API::mcrf_module = m;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,9 +148,13 @@ PyStatus init_python(const char *program_name)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
status = Py_InitializeFromConfig(&config);
|
status = Py_InitializeFromConfig(&config);
|
||||||
|
|
||||||
|
PyConfig_Clear(&config);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void McRFPy_API::setSpriteTexture(int ti)
|
void McRFPy_API::setSpriteTexture(int ti)
|
||||||
{
|
{
|
||||||
int tx = ti % texture_width, ty = ti / texture_width;
|
int tx = ti % texture_width, ty = ti / texture_width;
|
||||||
|
@ -139,6 +163,7 @@ void McRFPy_API::setSpriteTexture(int ti)
|
||||||
ty * texture_size,
|
ty * texture_size,
|
||||||
texture_size, texture_size));
|
texture_size, texture_size));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// functionality
|
// functionality
|
||||||
//void McRFPy_API::
|
//void McRFPy_API::
|
||||||
|
@ -155,6 +180,15 @@ void McRFPy_API::api_init() {
|
||||||
//texture_sprite_count = texture_width * texture_height;
|
//texture_sprite_count = texture_width * texture_height;
|
||||||
//texture.setSmooth(false);
|
//texture.setSmooth(false);
|
||||||
|
|
||||||
|
// Add default_font and default_texture to module
|
||||||
|
McRFPy_API::mcrf_module = PyImport_ImportModule("mcrfpy");
|
||||||
|
std::cout << PyUnicode_AsUTF8(PyObject_Repr(McRFPy_API::mcrf_module)) << std::endl;
|
||||||
|
|
||||||
|
//PyModule_AddObject(McRFPy_API::mcrf_module, "default_font", McRFPy_API::default_font->pyObject());
|
||||||
|
PyObject_SetAttrString(McRFPy_API::mcrf_module, "default_font", McRFPy_API::default_font->pyObject());
|
||||||
|
//PyModule_AddObject(McRFPy_API::mcrf_module, "default_texture", McRFPy_API::default_texture->pyObject());
|
||||||
|
PyObject_SetAttrString(McRFPy_API::mcrf_module, "default_texture", McRFPy_API::default_texture->pyObject());
|
||||||
|
|
||||||
//sprite.setTexture(texture);
|
//sprite.setTexture(texture);
|
||||||
//sprite.setScale(sf::Vector2f(4.0f, 4.0f));
|
//sprite.setScale(sf::Vector2f(4.0f, 4.0f));
|
||||||
//setSpriteTexture(0);
|
//setSpriteTexture(0);
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#include "PyFont.h"
|
||||||
|
#include "PyTexture.h"
|
||||||
|
|
||||||
class GameEngine; // forward declared (circular members)
|
class GameEngine; // forward declared (circular members)
|
||||||
|
|
||||||
class McRFPy_API
|
class McRFPy_API
|
||||||
|
@ -14,10 +17,14 @@ private:
|
||||||
|
|
||||||
McRFPy_API();
|
McRFPy_API();
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline static sf::Sprite sprite;
|
static PyObject* mcrf_module;
|
||||||
inline static sf::Texture texture;
|
static std::shared_ptr<PyFont> default_font;
|
||||||
static void setSpriteTexture(int);
|
static std::shared_ptr<PyTexture> default_texture;
|
||||||
|
//inline static sf::Sprite sprite;
|
||||||
|
//inline static sf::Texture texture;
|
||||||
|
//static void setSpriteTexture(int);
|
||||||
inline static GameEngine* game;
|
inline static GameEngine* game;
|
||||||
static void api_init();
|
static void api_init();
|
||||||
static void api_shutdown();
|
static void api_shutdown();
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "PyFont.h"
|
||||||
|
#include "McRFPy_API.h"
|
||||||
|
|
||||||
|
|
||||||
|
PyFont::PyFont(std::string filename)
|
||||||
|
: source(filename)
|
||||||
|
{
|
||||||
|
font = sf::Font();
|
||||||
|
font.loadFromFile(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* PyFont::pyObject()
|
||||||
|
{
|
||||||
|
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Font");
|
||||||
|
//PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyFontType, 0);
|
||||||
|
PyObject* obj = PyFont::pynew(type, Py_None, Py_None);
|
||||||
|
try {
|
||||||
|
((PyFontObject*)obj)->data = shared_from_this();
|
||||||
|
}
|
||||||
|
catch (std::bad_weak_ptr& e)
|
||||||
|
{
|
||||||
|
std::cout << "Bad weak ptr: shared_from_this() failed in PyFont::pyObject(); did you create a PyFont outside of std::make_shared? enjoy your segfault, soon!" << std::endl;
|
||||||
|
}
|
||||||
|
// TODO - shared_from_this will raise an exception if the object does not have a shared pointer. Constructor should be made private; write a factory function
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* PyFont::repr(PyObject* obj)
|
||||||
|
{
|
||||||
|
PyFontObject* self = (PyFontObject*)obj;
|
||||||
|
std::ostringstream ss;
|
||||||
|
if (!self->data)
|
||||||
|
{
|
||||||
|
ss << "<Font [invalid internal object]>";
|
||||||
|
std::string repr_str = ss.str();
|
||||||
|
return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace");
|
||||||
|
}
|
||||||
|
auto& pfont = *(self->data);
|
||||||
|
ss << "<Font (family=" << pfont.font.getInfo().family << ") source=`" << pfont.source << "`>";
|
||||||
|
std::string repr_str = ss.str();
|
||||||
|
return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace");
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_hash_t PyFont::hash(PyObject* obj)
|
||||||
|
{
|
||||||
|
auto self = (PyFontObject*)obj;
|
||||||
|
return reinterpret_cast<Py_hash_t>(self->data.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
int PyFont::init(PyFontObject* self, PyObject* args, PyObject* kwds)
|
||||||
|
{
|
||||||
|
static const char* keywords[] = { "filename", nullptr };
|
||||||
|
char* filename;
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", const_cast<char**>(keywords), &filename))
|
||||||
|
return -1;
|
||||||
|
self->data = std::make_shared<PyFont>(filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* PyFont::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds)
|
||||||
|
{
|
||||||
|
return (PyObject*)type->tp_alloc(type, 0);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Python.h"
|
||||||
|
|
||||||
|
class PyFont;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
std::shared_ptr<PyFont> data;
|
||||||
|
} PyFontObject;
|
||||||
|
|
||||||
|
class PyFont : public std::enable_shared_from_this<PyFont>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string source;
|
||||||
|
public:
|
||||||
|
PyFont(std::string filename);
|
||||||
|
sf::Font font;
|
||||||
|
PyObject* pyObject();
|
||||||
|
static PyObject* repr(PyObject*);
|
||||||
|
static Py_hash_t hash(PyObject*);
|
||||||
|
static int init(PyFontObject*, PyObject*, PyObject*);
|
||||||
|
static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace mcrfpydef {
|
||||||
|
static PyTypeObject PyFontType = {
|
||||||
|
.tp_name = "mcrfpy.Font",
|
||||||
|
.tp_basicsize = sizeof(PyFontObject),
|
||||||
|
.tp_itemsize = 0,
|
||||||
|
.tp_repr = PyFont::repr,
|
||||||
|
//.tp_hash = PyFont::hash,
|
||||||
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
|
.tp_doc = PyDoc_STR("SFML Font Object"),
|
||||||
|
//.tp_base = &PyBaseObject_Type,
|
||||||
|
.tp_init = (initproc)PyFont::init,
|
||||||
|
.tp_new = PyType_GenericNew, //PyFont::pynew,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
#include "PyTexture.h"
|
#include "PyTexture.h"
|
||||||
|
#include "McRFPy_API.h"
|
||||||
|
|
||||||
PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h)
|
PyTexture::PyTexture(std::string filename, int sprite_w, int sprite_h)
|
||||||
: source(filename), sprite_width(sprite_w), sprite_height(sprite_h)
|
: source(filename), sprite_width(sprite_w), sprite_height(sprite_h)
|
||||||
|
@ -28,9 +28,36 @@ sf::Sprite PyTexture::sprite(int index, sf::Vector2f pos, sf::Vector2f s)
|
||||||
|
|
||||||
PyObject* PyTexture::pyObject()
|
PyObject* PyTexture::pyObject()
|
||||||
{
|
{
|
||||||
PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyTextureType, 0);
|
// method 1: works but with type weirdness
|
||||||
|
//PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyTextureType, 0);
|
||||||
|
//Py_SET_TYPE(obj, &mcrfpydef::PyTextureType);
|
||||||
|
|
||||||
|
// method 2: does not work (segfault on use of the mcrfpy.Texture object)
|
||||||
|
//PyObject* obj = PyTexture::pynew(&mcrfpydef::PyTextureType, Py_None, Py_None);
|
||||||
|
|
||||||
|
// method 3: does not work (segfault on use of the mcrfpy.Texture object)
|
||||||
|
std::cout << "Find type" << std::endl;
|
||||||
|
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture");
|
||||||
|
//auto type = obj->ob_type;
|
||||||
|
//auto type = &mcrfpydef::PyTextureType;
|
||||||
|
//std::cout << "assigned value 0x" << std::hex << reinterpret_cast<long>(type) << std::endl;
|
||||||
|
//std::cout << "Found PyTextureType: " << PyUnicode_AsUTF8(PyObject_Repr((PyObject*)type)) << std::endl;
|
||||||
|
//std::cout << "PyTextureType metatype: " << PyUnicode_AsUTF8(PyObject_Repr((PyObject_Type((PyObject*)type)))) << std::endl;
|
||||||
|
//std::cout << "tp_alloc: 0x" << std::hex << reinterpret_cast <long>(type->tp_alloc) << std::endl <<
|
||||||
|
// "tp_new: 0x" << std::hex << reinterpret_cast<long>(type->tp_new) << std::endl;
|
||||||
|
//PyObject* obj = ((PyTypeObject*)type)->tp_new((PyTypeObject*)type, Py_None, Py_None);
|
||||||
|
PyObject* obj = PyTexture::pynew(type, Py_None, Py_None);
|
||||||
|
//Py_SET_TYPE(obj, type);
|
||||||
|
|
||||||
|
// method 4: call the type object?
|
||||||
|
|
||||||
|
std::cout << "Instantiated" << std::endl;
|
||||||
|
//Py_SET_TYPE(obj, &mcrfpydef::PyTextureType);
|
||||||
|
|
||||||
|
//PyObject_CallFunction(&mcrfpydef::PyTextureType,
|
||||||
try {
|
try {
|
||||||
((PyTextureObject*)obj)->data = shared_from_this();
|
((PyTextureObject*)obj)->data = shared_from_this();
|
||||||
|
std::cout << "Sideloaded texture: " << PyUnicode_AsUTF8(PyObject_Repr(obj)) << std::endl;
|
||||||
}
|
}
|
||||||
catch (std::bad_weak_ptr& e)
|
catch (std::bad_weak_ptr& e)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +67,22 @@ PyObject* PyTexture::pyObject()
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject* PyTexture::repr(PyObject* obj)
|
||||||
|
{
|
||||||
|
PyTextureObject* self = (PyTextureObject*)obj;
|
||||||
|
std::ostringstream ss;
|
||||||
|
if (!self->data)
|
||||||
|
{
|
||||||
|
ss << "<Texture [invalid internal object]>";
|
||||||
|
std::string repr_str = ss.str();
|
||||||
|
return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace");
|
||||||
|
}
|
||||||
|
auto& ptex = *(self->data);
|
||||||
|
ss << "<Texture " << ptex.sheet_height << " rows, " << ptex.sheet_width << " columns; " << ptex.sprite_width << "x" << ptex.sprite_height << "px sprites. source='" << ptex.source << "'>";
|
||||||
|
std::string repr_str = ss.str();
|
||||||
|
return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace");
|
||||||
|
}
|
||||||
|
|
||||||
Py_hash_t PyTexture::hash(PyObject* obj)
|
Py_hash_t PyTexture::hash(PyObject* obj)
|
||||||
{
|
{
|
||||||
auto self = (PyTextureObject*)obj;
|
auto self = (PyTextureObject*)obj;
|
||||||
|
|
|
@ -21,6 +21,7 @@ public:
|
||||||
sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0));
|
sf::Sprite sprite(int index, sf::Vector2f pos = sf::Vector2f(0, 0), sf::Vector2f s = sf::Vector2f(1.0, 1.0));
|
||||||
|
|
||||||
PyObject* pyObject();
|
PyObject* pyObject();
|
||||||
|
static PyObject* repr(PyObject*);
|
||||||
static Py_hash_t hash(PyObject*);
|
static Py_hash_t hash(PyObject*);
|
||||||
static int init(PyTextureObject*, PyObject*, PyObject*);
|
static int init(PyTextureObject*, PyObject*, PyObject*);
|
||||||
static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL);
|
static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL);
|
||||||
|
@ -31,10 +32,12 @@ namespace mcrfpydef {
|
||||||
.tp_name = "mcrfpy.Texture",
|
.tp_name = "mcrfpy.Texture",
|
||||||
.tp_basicsize = sizeof(PyTextureObject),
|
.tp_basicsize = sizeof(PyTextureObject),
|
||||||
.tp_itemsize = 0,
|
.tp_itemsize = 0,
|
||||||
|
.tp_repr = PyTexture::repr,
|
||||||
.tp_hash = PyTexture::hash,
|
.tp_hash = PyTexture::hash,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_doc = PyDoc_STR("SFML Texture Object"),
|
.tp_doc = PyDoc_STR("SFML Texture Object"),
|
||||||
|
//.tp_base = &PyBaseObject_Type,
|
||||||
.tp_init = (initproc)PyTexture::init,
|
.tp_init = (initproc)PyTexture::init,
|
||||||
.tp_new = PyTexture::pynew,
|
.tp_new = PyType_GenericNew, //PyTexture::pynew,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
7
src/UI.h
7
src/UI.h
|
@ -13,6 +13,7 @@
|
||||||
#include "PyColor.h"
|
#include "PyColor.h"
|
||||||
//#include "PyLinkedColor.h"
|
//#include "PyLinkedColor.h"
|
||||||
#include "PyVector.h"
|
#include "PyVector.h"
|
||||||
|
#include "PyFont.h"
|
||||||
|
|
||||||
enum PyObjectsEnum : int
|
enum PyObjectsEnum : int
|
||||||
{
|
{
|
||||||
|
@ -409,7 +410,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
|
||||||
* Begin PyFontType defs
|
* Begin PyFontType defs
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
std::shared_ptr<sf::Font> data;
|
std::shared_ptr<sf::Font> data;
|
||||||
|
@ -444,6 +445,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
|
||||||
return (PyObject*)self;
|
return (PyObject*)self;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
|
@ -792,13 +794,14 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
|
||||||
//
|
//
|
||||||
// Set Font
|
// Set Font
|
||||||
//
|
//
|
||||||
|
std::cout << PyUnicode_AsUTF8(PyObject_Repr(font)) << std::endl;
|
||||||
if (font != NULL && !PyObject_IsInstance(font, (PyObject*)&PyFontType)){
|
if (font != NULL && !PyObject_IsInstance(font, (PyObject*)&PyFontType)){
|
||||||
PyErr_SetString(PyExc_TypeError, "font must be a mcrfpy.Font instance");
|
PyErr_SetString(PyExc_TypeError, "font must be a mcrfpy.Font instance");
|
||||||
return -1;
|
return -1;
|
||||||
} else if (font != NULL)
|
} else if (font != NULL)
|
||||||
{
|
{
|
||||||
auto font_obj = (PyFontObject*)font;
|
auto font_obj = (PyFontObject*)font;
|
||||||
self->data->text.setFont(*font_obj->data);
|
self->data->text.setFont(font_obj->data->font);
|
||||||
self->font = font;
|
self->font = font;
|
||||||
Py_INCREF(font);
|
Py_INCREF(font);
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -2,6 +2,10 @@ import mcrfpy
|
||||||
font = mcrfpy.Font("assets/JetbrainsMono.ttf")
|
font = mcrfpy.Font("assets/JetbrainsMono.ttf")
|
||||||
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)
|
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)
|
||||||
|
|
||||||
|
print("[game.py] Default texture:")
|
||||||
|
print(mcrfpy.default_texture)
|
||||||
|
print(type(mcrfpy.default_texture))
|
||||||
|
|
||||||
# build test widgets
|
# build test widgets
|
||||||
|
|
||||||
mcrfpy.createScene("pytest")
|
mcrfpy.createScene("pytest")
|
||||||
|
|
Loading…
Reference in New Issue