scene transitions via Scene object
This commit is contained in:
parent
40c0eb2693
commit
fc95fc2844
6 changed files with 322 additions and 35 deletions
|
|
@ -9,6 +9,7 @@
|
||||||
#include "PyWindow.h"
|
#include "PyWindow.h"
|
||||||
#include "PySceneObject.h"
|
#include "PySceneObject.h"
|
||||||
#include "PyFOV.h"
|
#include "PyFOV.h"
|
||||||
|
#include "PyTransition.h"
|
||||||
#include "PySound.h"
|
#include "PySound.h"
|
||||||
#include "PyMusic.h"
|
#include "PyMusic.h"
|
||||||
#include "PyKeyboard.h"
|
#include "PyKeyboard.h"
|
||||||
|
|
@ -51,6 +52,14 @@ static PyObject* mcrfpy_module_getattr(PyObject* self, PyObject* args)
|
||||||
return McRFPy_API::api_get_scenes();
|
return McRFPy_API::api_get_scenes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(name, "default_transition") == 0) {
|
||||||
|
return PyTransition::to_python(PyTransition::default_transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(name, "default_transition_duration") == 0) {
|
||||||
|
return PyFloat_FromDouble(PyTransition::default_duration);
|
||||||
|
}
|
||||||
|
|
||||||
// Attribute not found - raise AttributeError
|
// Attribute not found - raise AttributeError
|
||||||
PyErr_Format(PyExc_AttributeError, "module 'mcrfpy' has no attribute '%s'", name);
|
PyErr_Format(PyExc_AttributeError, "module 'mcrfpy' has no attribute '%s'", name);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -71,6 +80,33 @@ static int mcrfpy_module_setattro(PyObject* self, PyObject* name, PyObject* valu
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(name_str, "default_transition") == 0) {
|
||||||
|
TransitionType trans;
|
||||||
|
if (!PyTransition::from_arg(value, &trans, nullptr)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PyTransition::default_transition = trans;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(name_str, "default_transition_duration") == 0) {
|
||||||
|
double duration;
|
||||||
|
if (PyFloat_Check(value)) {
|
||||||
|
duration = PyFloat_AsDouble(value);
|
||||||
|
} else if (PyLong_Check(value)) {
|
||||||
|
duration = PyLong_AsDouble(value);
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "default_transition_duration must be a number");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (duration < 0.0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "default_transition_duration must be non-negative");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PyTransition::default_duration = static_cast<float>(duration);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// For other attributes, use default module setattr
|
// For other attributes, use default module setattr
|
||||||
return PyObject_GenericSetAttr(self, name, value);
|
return PyObject_GenericSetAttr(self, name, value);
|
||||||
}
|
}
|
||||||
|
|
@ -392,7 +428,16 @@ PyObject* PyInit_mcrfpy()
|
||||||
// Fallback to integer if enum failed
|
// Fallback to integer if enum failed
|
||||||
PyModule_AddIntConstant(m, "default_fov", FOV_BASIC);
|
PyModule_AddIntConstant(m, "default_fov", FOV_BASIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add Transition enum class (uses Python's IntEnum)
|
||||||
|
PyObject* transition_class = PyTransition::create_enum_class(m);
|
||||||
|
if (!transition_class) {
|
||||||
|
// If enum creation fails, continue without it (non-fatal)
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
// Note: default_transition and default_transition_duration are handled via
|
||||||
|
// mcrfpy_module_getattr/setattro using PyTransition::default_transition/default_duration
|
||||||
|
|
||||||
// Add automation submodule
|
// Add automation submodule
|
||||||
PyObject* automation_module = McRFPy_Automation::init_automation_module();
|
PyObject* automation_module = McRFPy_Automation::init_automation_module();
|
||||||
if (automation_module != NULL) {
|
if (automation_module != NULL) {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "GameEngine.h"
|
#include "GameEngine.h"
|
||||||
#include "McRFPy_API.h"
|
#include "McRFPy_API.h"
|
||||||
#include "McRFPy_Doc.h"
|
#include "McRFPy_Doc.h"
|
||||||
|
#include "PyTransition.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// Static map to store Python scene objects by name
|
// Static map to store Python scene objects by name
|
||||||
|
|
@ -75,13 +76,54 @@ PyObject* PySceneClass::__repr__(PySceneObject* self)
|
||||||
return PyUnicode_FromFormat("<Scene '%s'>", self->name.c_str());
|
return PyUnicode_FromFormat("<Scene '%s'>", self->name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* PySceneClass::activate(PySceneObject* self, PyObject* args)
|
PyObject* PySceneClass::activate(PySceneObject* self, PyObject* args, PyObject* kwds)
|
||||||
{
|
{
|
||||||
// Call the static method from McRFPy_API
|
static const char* keywords[] = {"transition", "duration", nullptr};
|
||||||
PyObject* py_args = Py_BuildValue("(s)", self->name.c_str());
|
PyObject* transition_arg = nullptr;
|
||||||
PyObject* result = McRFPy_API::_setScene(NULL, py_args);
|
PyObject* duration_arg = nullptr;
|
||||||
Py_DECREF(py_args);
|
|
||||||
return result;
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", const_cast<char**>(keywords),
|
||||||
|
&transition_arg, &duration_arg)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get transition type (use default if not provided)
|
||||||
|
TransitionType transition_type;
|
||||||
|
bool trans_was_none = false;
|
||||||
|
if (transition_arg) {
|
||||||
|
if (!PyTransition::from_arg(transition_arg, &transition_type, &trans_was_none)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
transition_type = PyTransition::default_transition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get duration (use default if not provided)
|
||||||
|
float duration;
|
||||||
|
if (duration_arg && duration_arg != Py_None) {
|
||||||
|
if (PyFloat_Check(duration_arg)) {
|
||||||
|
duration = static_cast<float>(PyFloat_AsDouble(duration_arg));
|
||||||
|
} else if (PyLong_Check(duration_arg)) {
|
||||||
|
duration = static_cast<float>(PyLong_AsLong(duration_arg));
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "duration must be a number");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
duration = PyTransition::default_duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build transition string for _setScene (or call game->changeScene directly)
|
||||||
|
GameEngine* game = McRFPy_API::game;
|
||||||
|
if (!game) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "No game engine");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call game->changeScene directly with proper transition
|
||||||
|
game->changeScene(self->name, transition_type, duration);
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// children property getter (replaces get_ui method)
|
// children property getter (replaces get_ui method)
|
||||||
|
|
@ -455,12 +497,15 @@ PyGetSetDef PySceneClass::getsetters[] = {
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
PyMethodDef PySceneClass::methods[] = {
|
PyMethodDef PySceneClass::methods[] = {
|
||||||
{"activate", (PyCFunction)activate, METH_NOARGS,
|
{"activate", (PyCFunction)activate, METH_VARARGS | METH_KEYWORDS,
|
||||||
MCRF_METHOD(SceneClass, activate,
|
MCRF_METHOD(SceneClass, activate,
|
||||||
MCRF_SIG("()", "None"),
|
MCRF_SIG("(transition: Transition = None, duration: float = None)", "None"),
|
||||||
MCRF_DESC("Make this the active scene."),
|
MCRF_DESC("Make this the active scene with optional transition effect."),
|
||||||
|
MCRF_ARGS_START
|
||||||
|
MCRF_ARG("transition", "Transition type (mcrfpy.Transition enum). Defaults to mcrfpy.default_transition")
|
||||||
|
MCRF_ARG("duration", "Transition duration in seconds. Defaults to mcrfpy.default_transition_duration")
|
||||||
MCRF_RETURNS("None")
|
MCRF_RETURNS("None")
|
||||||
MCRF_NOTE("Deactivates the current scene and activates this one. Scene transitions and lifecycle callbacks are triggered.")
|
MCRF_NOTE("Deactivates the current scene and activates this one. Lifecycle callbacks (on_exit, on_enter) are triggered.")
|
||||||
)},
|
)},
|
||||||
{"register_keyboard", (PyCFunction)register_keyboard, METH_VARARGS,
|
{"register_keyboard", (PyCFunction)register_keyboard, METH_VARARGS,
|
||||||
MCRF_METHOD(SceneClass, register_keyboard,
|
MCRF_METHOD(SceneClass, register_keyboard,
|
||||||
|
|
@ -575,9 +620,8 @@ int McRFPy_API::api_set_current_scene(PyObject* value)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string old_scene = game->scene;
|
// Use changeScene with default transition settings
|
||||||
game->scene = scene_name;
|
game->changeScene(scene_name, PyTransition::default_transition, PyTransition::default_duration);
|
||||||
McRFPy_API::triggerSceneChange(old_scene, scene_name);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public:
|
||||||
static PyObject* __repr__(PySceneObject* self);
|
static PyObject* __repr__(PySceneObject* self);
|
||||||
|
|
||||||
// Scene methods
|
// Scene methods
|
||||||
static PyObject* activate(PySceneObject* self, PyObject* args);
|
static PyObject* activate(PySceneObject* self, PyObject* args, PyObject* kwds);
|
||||||
static PyObject* register_keyboard(PySceneObject* self, PyObject* args);
|
static PyObject* register_keyboard(PySceneObject* self, PyObject* args);
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
|
|
|
||||||
158
src/PyTransition.cpp
Normal file
158
src/PyTransition.cpp
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
#include "PyTransition.h"
|
||||||
|
#include "McRFPy_API.h"
|
||||||
|
|
||||||
|
// Static storage
|
||||||
|
PyObject* PyTransition::transition_enum_class = nullptr;
|
||||||
|
TransitionType PyTransition::default_transition = TransitionType::None;
|
||||||
|
float PyTransition::default_duration = 1.0f;
|
||||||
|
|
||||||
|
PyObject* PyTransition::create_enum_class(PyObject* module) {
|
||||||
|
// Import IntEnum from enum module
|
||||||
|
PyObject* enum_module = PyImport_ImportModule("enum");
|
||||||
|
if (!enum_module) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* int_enum = PyObject_GetAttrString(enum_module, "IntEnum");
|
||||||
|
Py_DECREF(enum_module);
|
||||||
|
if (!int_enum) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create dict of enum members
|
||||||
|
PyObject* members = PyDict_New();
|
||||||
|
if (!members) {
|
||||||
|
Py_DECREF(int_enum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all Transition type members
|
||||||
|
// Values match the C++ TransitionType enum
|
||||||
|
struct {
|
||||||
|
const char* name;
|
||||||
|
int value;
|
||||||
|
} transition_members[] = {
|
||||||
|
{"NONE", static_cast<int>(TransitionType::None)},
|
||||||
|
{"FADE", static_cast<int>(TransitionType::Fade)},
|
||||||
|
{"SLIDE_LEFT", static_cast<int>(TransitionType::SlideLeft)},
|
||||||
|
{"SLIDE_RIGHT", static_cast<int>(TransitionType::SlideRight)},
|
||||||
|
{"SLIDE_UP", static_cast<int>(TransitionType::SlideUp)},
|
||||||
|
{"SLIDE_DOWN", static_cast<int>(TransitionType::SlideDown)},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& m : transition_members) {
|
||||||
|
PyObject* value = PyLong_FromLong(m.value);
|
||||||
|
if (!value) {
|
||||||
|
Py_DECREF(members);
|
||||||
|
Py_DECREF(int_enum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (PyDict_SetItemString(members, m.name, value) < 0) {
|
||||||
|
Py_DECREF(value);
|
||||||
|
Py_DECREF(members);
|
||||||
|
Py_DECREF(int_enum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_DECREF(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call IntEnum("Transition", members) to create the enum class
|
||||||
|
PyObject* name = PyUnicode_FromString("Transition");
|
||||||
|
if (!name) {
|
||||||
|
Py_DECREF(members);
|
||||||
|
Py_DECREF(int_enum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntEnum(name, members) using functional API
|
||||||
|
PyObject* args = PyTuple_Pack(2, name, members);
|
||||||
|
Py_DECREF(name);
|
||||||
|
Py_DECREF(members);
|
||||||
|
if (!args) {
|
||||||
|
Py_DECREF(int_enum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* transition_class = PyObject_Call(int_enum, args, NULL);
|
||||||
|
Py_DECREF(args);
|
||||||
|
Py_DECREF(int_enum);
|
||||||
|
|
||||||
|
if (!transition_class) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the reference for fast type checking
|
||||||
|
transition_enum_class = transition_class;
|
||||||
|
Py_INCREF(transition_enum_class);
|
||||||
|
|
||||||
|
// Add to module
|
||||||
|
if (PyModule_AddObject(module, "Transition", transition_class) < 0) {
|
||||||
|
Py_DECREF(transition_class);
|
||||||
|
transition_enum_class = nullptr;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transition_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PyTransition::from_arg(PyObject* arg, TransitionType* out_type, bool* was_none) {
|
||||||
|
if (was_none) *was_none = false;
|
||||||
|
|
||||||
|
// Accept None -> caller should use default
|
||||||
|
if (arg == Py_None || arg == NULL) {
|
||||||
|
if (was_none) *was_none = true;
|
||||||
|
*out_type = default_transition;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept Transition enum member (check if it's an instance of our enum)
|
||||||
|
if (transition_enum_class && PyObject_IsInstance(arg, transition_enum_class)) {
|
||||||
|
// IntEnum members have a 'value' attribute
|
||||||
|
PyObject* value = PyObject_GetAttrString(arg, "value");
|
||||||
|
if (!value) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
long val = PyLong_AsLong(value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
if (val == -1 && PyErr_Occurred()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*out_type = static_cast<TransitionType>(val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept int (for flexibility)
|
||||||
|
if (PyLong_Check(arg)) {
|
||||||
|
long val = PyLong_AsLong(arg);
|
||||||
|
if (val == -1 && PyErr_Occurred()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (val < 0 || val > static_cast<int>(TransitionType::SlideDown)) {
|
||||||
|
PyErr_Format(PyExc_ValueError,
|
||||||
|
"Invalid Transition value: %ld. Must be 0-5 or use mcrfpy.Transition enum.",
|
||||||
|
val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*out_type = static_cast<TransitionType>(val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"transition must be mcrfpy.Transition enum member, int, or None");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* PyTransition::to_python(TransitionType type) {
|
||||||
|
if (!transition_enum_class) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Transition enum not initialized");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the enum member by value
|
||||||
|
PyObject* value = PyLong_FromLong(static_cast<int>(type));
|
||||||
|
if (!value) return NULL;
|
||||||
|
|
||||||
|
PyObject* result = PyObject_CallFunctionObjArgs(transition_enum_class, value, NULL);
|
||||||
|
Py_DECREF(value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
29
src/PyTransition.h
Normal file
29
src/PyTransition.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Python.h"
|
||||||
|
#include "SceneTransition.h"
|
||||||
|
|
||||||
|
// Module-level Transition enum class (created at runtime using Python's IntEnum)
|
||||||
|
// Stored as a module attribute: mcrfpy.Transition
|
||||||
|
|
||||||
|
class PyTransition {
|
||||||
|
public:
|
||||||
|
// Create the Transition enum class and add to module
|
||||||
|
// Returns the enum class (new reference), or NULL on error
|
||||||
|
static PyObject* create_enum_class(PyObject* module);
|
||||||
|
|
||||||
|
// Helper to extract transition type from Python arg (accepts Transition enum, int, or None)
|
||||||
|
// Returns 1 on success, 0 on error (with exception set)
|
||||||
|
// If arg is None, sets *out_type to the default and sets *was_none to true
|
||||||
|
static int from_arg(PyObject* arg, TransitionType* out_type, bool* was_none = nullptr);
|
||||||
|
|
||||||
|
// Convert TransitionType to Python enum member
|
||||||
|
static PyObject* to_python(TransitionType type);
|
||||||
|
|
||||||
|
// Cached reference to the Transition enum class for fast type checking
|
||||||
|
static PyObject* transition_enum_class;
|
||||||
|
|
||||||
|
// Module-level defaults
|
||||||
|
static TransitionType default_transition;
|
||||||
|
static float default_duration;
|
||||||
|
};
|
||||||
|
|
@ -63,7 +63,7 @@ def create_test_scenes():
|
||||||
print("Created test scenes: red_scene, blue_scene, green_scene, menu_scene")
|
print("Created test scenes: red_scene, blue_scene, green_scene, menu_scene")
|
||||||
|
|
||||||
# Track current transition type
|
# Track current transition type
|
||||||
current_transition = "fade"
|
current_transition = mcrfpy.Transition.FADE
|
||||||
transition_duration = 1.0
|
transition_duration = 1.0
|
||||||
|
|
||||||
def handle_key(key, action):
|
def handle_key(key, action):
|
||||||
|
|
@ -76,24 +76,35 @@ def handle_key(key, action):
|
||||||
current_scene = (mcrfpy.current_scene.name if mcrfpy.current_scene else None)
|
current_scene = (mcrfpy.current_scene.name if mcrfpy.current_scene else None)
|
||||||
|
|
||||||
# Number keys set transition type
|
# Number keys set transition type
|
||||||
if key == "Num1":
|
keyselections = {
|
||||||
current_transition = "fade"
|
"Num1": mcrfpy.Transition.FADE,
|
||||||
print("Transition set to: fade")
|
"Num2": mcrfpy.Transition.SLIDE_LEFT,
|
||||||
elif key == "Num2":
|
"Num3": mcrfpy.Transition.SLIDE_RIGHT,
|
||||||
current_transition = "slide_left"
|
"Num4": mcrfpy.Transition.SLIDE_UP,
|
||||||
print("Transition set to: slide_left")
|
"Num5": mcrfpy.Transition.SLIDE_DOWN,
|
||||||
elif key == "Num3":
|
"Num6": mcrfpy.Transition.NONE
|
||||||
current_transition = "slide_right"
|
}
|
||||||
print("Transition set to: slide_right")
|
if key in keyselections:
|
||||||
elif key == "Num4":
|
current_transition = keyselections[key]
|
||||||
current_transition = "slide_up"
|
print(f"Transition set to: {current_transition}")
|
||||||
print("Transition set to: slide_up")
|
#if key == "Num1":
|
||||||
elif key == "Num5":
|
# current_transition = "fade"
|
||||||
current_transition = "slide_down"
|
# print("Transition set to: fade")
|
||||||
print("Transition set to: slide_down")
|
#elif key == "Num2":
|
||||||
elif key == "Num6":
|
# current_transition = "slide_left"
|
||||||
current_transition = None # Instant
|
# print("Transition set to: slide_left")
|
||||||
print("Transition set to: instant")
|
#elif key == "Num3":
|
||||||
|
# current_transition = "slide_right"
|
||||||
|
# print("Transition set to: slide_right")
|
||||||
|
#elif key == "Num4":
|
||||||
|
# current_transition = "slide_up"
|
||||||
|
# print("Transition set to: slide_up")
|
||||||
|
#elif key == "Num5":
|
||||||
|
# current_transition = "slide_down"
|
||||||
|
# print("Transition set to: slide_down")
|
||||||
|
#elif key == "Num6":
|
||||||
|
# current_transition = None # Instant
|
||||||
|
# print("Transition set to: instant")
|
||||||
|
|
||||||
# Letter keys change scene
|
# Letter keys change scene
|
||||||
keytransitions = {
|
keytransitions = {
|
||||||
|
|
@ -104,7 +115,7 @@ def handle_key(key, action):
|
||||||
}
|
}
|
||||||
if key in keytransitions:
|
if key in keytransitions:
|
||||||
if mcrfpy.current_scene != keytransitions[key]:
|
if mcrfpy.current_scene != keytransitions[key]:
|
||||||
keytransitions[key].activate()
|
keytransitions[key].activate(current_transition, transition_duration)
|
||||||
#elif key == "R":
|
#elif key == "R":
|
||||||
# if current_scene != "red_scene":
|
# if current_scene != "red_scene":
|
||||||
# print(f"Transitioning to red_scene with {current_transition}")
|
# print(f"Transitioning to red_scene with {current_transition}")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue