diff --git a/src/GameEngine.cpp b/src/GameEngine.cpp index 9ccf273..55a1ca1 100644 --- a/src/GameEngine.cpp +++ b/src/GameEngine.cpp @@ -202,16 +202,6 @@ Scene* GameEngine::getScene(const std::string& name) { auto it = scenes.find(name); return (it != scenes.end()) ? it->second : nullptr; } - -std::vector GameEngine::getSceneNames() const { - std::vector names; - names.reserve(scenes.size()); - for (const auto& [name, scene] : scenes) { - names.push_back(name); - } - return names; -} - void GameEngine::changeScene(std::string s) { changeScene(s, TransitionType::None, 0.0f); @@ -356,10 +346,9 @@ void GameEngine::run() profilerOverlay->render(*render_target); } - // Render ImGui overlays (console and scene explorer) + // Render ImGui console overlay if (imguiInitialized && !headless) { console.render(); - sceneExplorer.render(*this); ImGui::SFML::Render(*window); } @@ -561,12 +550,6 @@ void GameEngine::sUserInput() continue; // Don't pass grave key to game } - // Handle F4 for scene explorer toggle - if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::F4) { - sceneExplorer.toggle(); - continue; // Don't pass F4 to game - } - // If console wants keyboard, don't pass keyboard events to game if (console.wantsKeyboardInput()) { // Still process non-keyboard events (mouse, window close, etc.) diff --git a/src/GameEngine.h b/src/GameEngine.h index 512726d..f6cb27e 100644 --- a/src/GameEngine.h +++ b/src/GameEngine.h @@ -11,7 +11,6 @@ #include "SceneTransition.h" #include "Profiler.h" #include "ImGuiConsole.h" -#include "ImGuiSceneExplorer.h" #include #include #include @@ -192,7 +191,6 @@ private: // ImGui console overlay ImGuiConsole console; - ImGuiSceneExplorer sceneExplorer; bool imguiInitialized = false; // #219 - Thread synchronization for background Python threads @@ -216,7 +214,6 @@ public: ~GameEngine(); Scene* currentScene(); Scene* getScene(const std::string& name); // #118: Get scene by name - std::vector getSceneNames() const; // #136: Get all scene names for explorer void changeScene(std::string); void changeScene(std::string sceneName, TransitionType transitionType, float duration); void createScene(std::string); diff --git a/src/ImGuiConsole.cpp b/src/ImGuiConsole.cpp index d0363bf..0d02be1 100644 --- a/src/ImGuiConsole.cpp +++ b/src/ImGuiConsole.cpp @@ -381,9 +381,9 @@ void ImGuiConsole::render() { } ImGui::PopItemWidth(); - // Keep focus on input only after executing a command + // Keep focus on input ImGui::SetItemDefaultFocus(); - if (reclaimFocus) { + if (reclaimFocus || (visible && !ImGui::IsAnyItemActive())) { ImGui::SetKeyboardFocusHere(-1); } diff --git a/src/ImGuiSceneExplorer.cpp b/src/ImGuiSceneExplorer.cpp deleted file mode 100644 index f12d1d9..0000000 --- a/src/ImGuiSceneExplorer.cpp +++ /dev/null @@ -1,285 +0,0 @@ -#include "ImGuiSceneExplorer.h" -#include "imgui.h" -#include "GameEngine.h" -#include "Scene.h" -#include "UIDrawable.h" -#include "UIFrame.h" -#include "UICaption.h" -#include "UISprite.h" -#include "UIGrid.h" -#include "UIEntity.h" -#include "ImGuiConsole.h" -#include "PythonObjectCache.h" -#include -#include -#include - -bool ImGuiSceneExplorer::isEnabled() { - // Use the same enabled flag as the console - return ImGuiConsole::isEnabled(); -} - -void ImGuiSceneExplorer::toggle() { - if (isEnabled()) { - visible = !visible; - } -} - -void ImGuiSceneExplorer::render(GameEngine& engine) { - if (!visible || !isEnabled()) return; - - ImGuiIO& io = ImGui::GetIO(); - - // Position on the right side of the screen - ImGui::SetNextWindowSize(ImVec2(350, io.DisplaySize.y * 0.6f), ImGuiCond_FirstUseEver); - ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x - 360, 10), ImGuiCond_FirstUseEver); - - ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse; - - if (!ImGui::Begin("Scene Explorer", &visible, flags)) { - ImGui::End(); - return; - } - - // Scene tree header - ImGui::Text("Scenes (%zu):", engine.getSceneNames().size()); - ImGui::Separator(); - - // Scrollable tree region - ImGui::BeginChild("SceneTree", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar); - - // Get all scene names and render each - std::string currentSceneName = engine.scene; - std::vector sceneNames = engine.getSceneNames(); - - for (const auto& sceneName : sceneNames) { - bool isActive = (sceneName == currentSceneName); - renderSceneNode(engine, sceneName, isActive); - } - - ImGui::EndChild(); - - ImGui::End(); -} - -void ImGuiSceneExplorer::renderSceneNode(GameEngine& engine, const std::string& sceneName, bool isActive) { - ImGuiTreeNodeFlags sceneFlags = ImGuiTreeNodeFlags_OpenOnArrow - | ImGuiTreeNodeFlags_OpenOnDoubleClick - | ImGuiTreeNodeFlags_DefaultOpen; - - if (isActive) { - sceneFlags |= ImGuiTreeNodeFlags_Selected; - } - - // Build label with active indicator - std::string label = sceneName; - if (isActive) { - label += " [active]"; - } - - // Scene icon/indicator - bool sceneOpen = ImGui::TreeNodeEx(("##scene_" + sceneName).c_str(), sceneFlags, "%s %s", - isActive ? ">" : " ", label.c_str()); - - // Click to activate scene (if not already active) - if (ImGui::IsItemClicked() && !isActive) { - engine.changeScene(sceneName); - } - - if (sceneOpen) { - // Get scene's UI elements - auto ui_elements = engine.scene_ui(sceneName); - if (ui_elements && !ui_elements->empty()) { - for (auto& drawable : *ui_elements) { - if (drawable) { - renderDrawableNode(drawable, 0); - } - } - } else { - ImGui::TextDisabled(" (empty)"); - } - ImGui::TreePop(); - } -} - -void ImGuiSceneExplorer::renderDrawableNode(std::shared_ptr drawable, int depth) { - if (!drawable) return; - - ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow - | ImGuiTreeNodeFlags_OpenOnDoubleClick - | ImGuiTreeNodeFlags_SpanAvailWidth; - - // Check if this node has children - bool hasChildren = false; - UIFrame* frame = nullptr; - UIGrid* grid = nullptr; - - switch (drawable->derived_type()) { - case PyObjectsEnum::UIFRAME: - frame = static_cast(drawable.get()); - hasChildren = frame->children && !frame->children->empty(); - break; - case PyObjectsEnum::UIGRID: - grid = static_cast(drawable.get()); - hasChildren = (grid->entities && !grid->entities->empty()) || - (grid->children && !grid->children->empty()); - break; - default: - break; - } - - if (!hasChildren) { - flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; - } - - // Visibility indicator - const char* visIcon = drawable->visible ? "[v]" : "[h]"; - - // Build display string - std::string displayName = getDisplayName(drawable.get()); - std::string nodeLabel = std::string(visIcon) + " " + getTypeName(drawable.get()) + ": " + displayName; - - // Use pointer as unique ID - bool nodeOpen = ImGui::TreeNodeEx((void*)(intptr_t)drawable.get(), flags, "%s", nodeLabel.c_str()); - - // Double-click to toggle visibility - if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) { - drawable->visible = !drawable->visible; - } - - // Handle leaf nodes (NoTreePushOnOpen means TreePop not needed) - if (!hasChildren) { - return; - } - - if (nodeOpen) { - // Render children based on type - if (frame && frame->children) { - for (auto& child : *frame->children) { - if (child) { - renderDrawableNode(child, depth + 1); - } - } - } - - if (grid) { - // Render entities - if (grid->entities && !grid->entities->empty()) { - ImGuiTreeNodeFlags entityGroupFlags = ImGuiTreeNodeFlags_OpenOnArrow; - bool entitiesOpen = ImGui::TreeNodeEx("Entities", entityGroupFlags, "Entities (%zu)", - grid->entities->size()); - if (entitiesOpen) { - for (auto& entity : *grid->entities) { - if (entity) { - renderEntityNode(entity); - } - } - ImGui::TreePop(); - } - } - - // Render grid's drawable children (overlays) - if (grid->children && !grid->children->empty()) { - ImGuiTreeNodeFlags overlayGroupFlags = ImGuiTreeNodeFlags_OpenOnArrow; - bool overlaysOpen = ImGui::TreeNodeEx("Overlays", overlayGroupFlags, "Overlays (%zu)", - grid->children->size()); - if (overlaysOpen) { - for (auto& child : *grid->children) { - if (child) { - renderDrawableNode(child, depth + 1); - } - } - ImGui::TreePop(); - } - } - } - - ImGui::TreePop(); - } -} - -void ImGuiSceneExplorer::renderEntityNode(std::shared_ptr entity) { - if (!entity) return; - - ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf - | ImGuiTreeNodeFlags_NoTreePushOnOpen - | ImGuiTreeNodeFlags_SpanAvailWidth; - - std::string displayName = getEntityDisplayName(entity.get()); - std::string nodeLabel = "Entity: " + displayName; - - ImGui::TreeNodeEx((void*)(intptr_t)entity.get(), flags, "%s", nodeLabel.c_str()); -} - -std::string ImGuiSceneExplorer::getDisplayName(UIDrawable* drawable) { - if (!drawable) return "(null)"; - - // Try to get Python object repr from cache - if (drawable->serial_number != 0) { - PyObject* pyObj = PythonObjectCache::getInstance().lookup(drawable->serial_number); - if (pyObj) { - PyObject* repr = PyObject_Repr(pyObj); - if (repr) { - const char* repr_str = PyUnicode_AsUTF8(repr); - if (repr_str) { - std::string result(repr_str); - Py_DECREF(repr); - Py_DECREF(pyObj); - return result; - } - Py_DECREF(repr); - } - Py_DECREF(pyObj); - } - } - - // Use name if available - if (!drawable->name.empty()) { - return "\"" + drawable->name + "\""; - } - - // Fall back to address - std::ostringstream oss; - oss << "@" << std::hex << std::setw(8) << std::setfill('0') << (uintptr_t)drawable; - return oss.str(); -} - -std::string ImGuiSceneExplorer::getEntityDisplayName(UIEntity* entity) { - if (!entity) return "(null)"; - - // Try to get Python object repr from cache - if (entity->serial_number != 0) { - PyObject* pyObj = PythonObjectCache::getInstance().lookup(entity->serial_number); - if (pyObj) { - PyObject* repr = PyObject_Repr(pyObj); - if (repr) { - const char* repr_str = PyUnicode_AsUTF8(repr); - if (repr_str) { - std::string result(repr_str); - Py_DECREF(repr); - Py_DECREF(pyObj); - return result; - } - Py_DECREF(repr); - } - Py_DECREF(pyObj); - } - } - - // Fall back to position - std::ostringstream oss; - oss << "(" << entity->position.x << ", " << entity->position.y << ")"; - return oss.str(); -} - -const char* ImGuiSceneExplorer::getTypeName(UIDrawable* drawable) { - if (!drawable) return "null"; - - switch (drawable->derived_type()) { - case PyObjectsEnum::UIFRAME: return "Frame"; - case PyObjectsEnum::UICAPTION: return "Caption"; - case PyObjectsEnum::UISPRITE: return "Sprite"; - case PyObjectsEnum::UIGRID: return "Grid"; - default: return "Unknown"; - } -} diff --git a/src/ImGuiSceneExplorer.h b/src/ImGuiSceneExplorer.h deleted file mode 100644 index d41163a..0000000 --- a/src/ImGuiSceneExplorer.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include - -class GameEngine; -class UIDrawable; -class UIEntity; -class UIFrame; -class UIGrid; - -/** - * @brief ImGui-based scene tree explorer for debugging - * - * Displays hierarchical view of all scenes and their UI elements. - * Allows switching between scenes and collapsing/expanding the tree. - * Activated by F4 key. Mutually exclusive with the console (grave key). - */ -class ImGuiSceneExplorer { -public: - ImGuiSceneExplorer() = default; - - // Core functionality - void render(GameEngine& engine); - void toggle(); - bool isVisible() const { return visible; } - void setVisible(bool v) { visible = v; } - - // Configuration - uses same enabled flag as console - static bool isEnabled(); - -private: - bool visible = false; - - // Tree rendering helpers - void renderSceneNode(GameEngine& engine, const std::string& sceneName, bool isActive); - void renderDrawableNode(std::shared_ptr drawable, int depth = 0); - void renderEntityNode(std::shared_ptr entity); - - // Get display name for a drawable (name or type + address) - std::string getDisplayName(UIDrawable* drawable); - std::string getEntityDisplayName(UIEntity* entity); - - // Get type name string - const char* getTypeName(UIDrawable* drawable); -}; diff --git a/src/PyTimer.cpp b/src/PyTimer.cpp index f3c8d5b..b59df69 100644 --- a/src/PyTimer.cpp +++ b/src/PyTimer.cpp @@ -156,10 +156,14 @@ PyObject* PyTimer::stop(PyTimerObject* self, PyObject* Py_UNUSED(ignored)) { return nullptr; } - // Just mark as stopped - do NOT erase from map here! - // Removing from the map during iteration (e.g., from a timer callback) - // would invalidate iterators in testTimers(). The stopped flag tells - // testTimers() to safely remove this timer on its next pass. + // Remove from game engine map (but preserve the Timer data!) + if (Resources::game && !self->name.empty()) { + auto it = Resources::game->timers.find(self->name); + if (it != Resources::game->timers.end() && it->second == self->data) { + Resources::game->timers.erase(it); + } + } + self->data->stop(); // NOTE: We do NOT reset self->data here - the timer can be restarted Py_RETURN_NONE; diff --git a/src/UICollection.cpp b/src/UICollection.cpp index fe7fe52..6512dfd 100644 --- a/src/UICollection.cpp +++ b/src/UICollection.cpp @@ -126,18 +126,6 @@ static PyObject* convertDrawableToPython(std::shared_ptr drawable) { if (type) { Py_DECREF(type); } - - // Re-register in cache if the object has a serial number - // This handles the case where the original Python wrapper was GC'd - // but the C++ object persists (e.g., inline-created objects added to collections) - if (obj && drawable->serial_number != 0) { - PyObject* weakref = PyWeakref_NewRef(obj, NULL); - if (weakref) { - PythonObjectCache::getInstance().registerObject(drawable->serial_number, weakref); - Py_DECREF(weakref); - } - } - return obj; } diff --git a/src/UIEntityCollection.cpp b/src/UIEntityCollection.cpp index a51d1b7..cd11181 100644 --- a/src/UIEntityCollection.cpp +++ b/src/UIEntityCollection.cpp @@ -130,18 +130,6 @@ PyObject* UIEntityCollection::getitem(PyUIEntityCollectionObject* self, Py_ssize o->data = std::static_pointer_cast(target); o->weakreflist = NULL; - - // Re-register in cache if the entity has a serial number - // This handles the case where the original Python wrapper was GC'd - // but the C++ object persists (e.g., inline-created objects added to collections) - if (target->serial_number != 0) { - PyObject* weakref = PyWeakref_NewRef((PyObject*)o, NULL); - if (weakref) { - PythonObjectCache::getInstance().registerObject(target->serial_number, weakref); - Py_DECREF(weakref); - } - } - return (PyObject*)o; } diff --git a/src/scripts/cos_entities.py b/src/scripts/cos_entities.py index 2cbf080..f47cd70 100644 --- a/src/scripts/cos_entities.py +++ b/src/scripts/cos_entities.py @@ -82,7 +82,7 @@ class COSEntity(): #mcrfpy.Entity): # Fake mcrfpy.Entity integration; engine bu pass def try_move(self, dx, dy, test=False): - x_max, y_max = int(self.grid.grid_size.x), int(self.grid.grid_size.y) + x_max, y_max = self.grid.grid_size tx, ty = int(self.draw_pos.x + dx), int(self.draw_pos.y + dy) #for e in iterable_entities(self.grid): diff --git a/src/scripts/cos_tiles.py b/src/scripts/cos_tiles.py index 349fe31..079516f 100644 --- a/src/scripts/cos_tiles.py +++ b/src/scripts/cos_tiles.py @@ -22,7 +22,7 @@ class TileInfo: @staticmethod def from_grid(grid, xy:tuple): values = {} - x_max, y_max = int(grid.grid_size.x), int(grid.grid_size.y) + x_max, y_max = grid.grid_size for d in deltas: tx, ty = d[0] + xy[0], d[1] + xy[1] if tx < 0 or tx >= x_max or ty < 0 or ty >= y_max: @@ -71,7 +71,7 @@ def special_rule_verify(rule, grid, xy, unverified_tiles, pass_unverified=False) tx, ty = xy[0] + dxy[0], xy[1] + dxy[1] #print(f"Special rule: {cardinal} {allowed_tile} {type(allowed_tile)} -> ({tx}, {ty}) [{grid.at((tx, ty)).tilesprite}]{'*' if (tx, ty) in unverified_tiles else ''}") if (tx, ty) in unverified_tiles and cardinal in "nsew": return pass_unverified - x_max, y_max = int(grid.grid_size.x), int(grid.grid_size.y) + x_max, y_max = grid.grid_size if tx < 0 or tx >= x_max or ty < 0 or ty >= y_max: return False return grid.at((tx, ty)).tilesprite == allowed_tile @@ -107,7 +107,7 @@ def find_possible_tiles(grid, x, y, unverified_tiles=None, pass_unverified=False return list(set(list(possible))) def wfc_first_pass(grid): - w, h = int(grid.grid_size.x), int(grid.grid_size.y) + w, h = grid.grid_size possibilities = {} for x in range(0, w): for y in range(0, h): @@ -122,7 +122,7 @@ def wfc_first_pass(grid): return possibilities def wfc_pass(grid, possibilities=None): - w, h = int(grid.grid_size.x), int(grid.grid_size.y) + w, h = grid.grid_size if possibilities is None: #print("first pass results:") possibilities = wfc_first_pass(grid) diff --git a/src/scripts/game.py b/src/scripts/game.py index e3c1466..3d54841 100644 --- a/src/scripts/game.py +++ b/src/scripts/game.py @@ -22,47 +22,28 @@ class Resources: self.sfx_volume = 100 self.master_volume = 100 - # Load the music/sfx files using new Sound API + # load the music/sfx files here self.splats = [] for i in range(1, 10): - try: - sound = mcrfpy.Sound(f"assets/sfx/splat{i}.ogg") - self.splats.append(sound) - except RuntimeError: - pass # Sound file not found, skip + mcrfpy.createSoundBuffer(f"assets/sfx/splat{i}.ogg") - self.music = None # Will hold Music object when loaded def play_sfx(self, sfx_id): if self.sfx_enabled and self.sfx_volume and self.master_volume: - if sfx_id < len(self.splats): - sound = self.splats[sfx_id] - sound.volume = self.master_volume / 100 * self.sfx_volume - sound.play() + mcrfpy.setSoundVolume(self.master_volume/100 * self.sfx_volume) + mcrfpy.playSound(sfx_id) - def play_music(self, track_path): + def play_music(self, track_id): if self.music_enabled and self.music_volume and self.master_volume: - try: - self.music = mcrfpy.Music(track_path) - self.music.volume = self.master_volume / 100 * self.music_volume - self.music.play() - except RuntimeError: - pass # Music file not found - - def set_music_volume(self, volume): - self.music_volume = volume - if self.music: - self.music.volume = self.master_volume / 100 * self.music_volume - - def set_sfx_volume(self, volume): - self.sfx_volume = volume + mcrfpy.setMusicVolume(self.master_volume/100 * self.music_volume) + mcrfpy.playMusic(...) resources = Resources() class Crypt: def __init__(self): - self.scene = mcrfpy.Scene("play") - self.ui = self.scene.children + play = mcrfpy.Scene("play") + self.ui = mcrfpy.sceneUI("play") entity_frame = mcrfpy.Frame(pos=(815, 10), size=(194, 595), fill_color=frame_color) inventory_frame = mcrfpy.Frame(pos=(10, 610), size=(800, 143), fill_color=frame_color) @@ -263,8 +244,8 @@ class Crypt: def start(self): resources.play_sfx(1) - self.scene.activate() - self.scene.on_key = self.cos_keys + play.activate() + play.on_key = self.cos_keys def add_entity(self, e:ce.COSEntity): self.entities.append(e) @@ -421,7 +402,7 @@ class Crypt: self.grid = self.level.grid self.grid.zoom = 2.0 # Center the camera on the middle of the grid (pixel coordinates: cells * tile_size / 2) - gw, gh = int(self.grid.grid_size.x), int(self.grid.grid_size.y) + gw, gh = self.grid.grid_size self.grid.center = (gw * 16 / 2, gh * 16 / 2) # TODO, make an entity mover function #self.add_entity(self.player) @@ -482,12 +463,12 @@ class SweetButton: """Helper func for when graphics changes or glitches make the button stuck down""" self.main_button.x, self.main_button.y = (self.shadow_offset, self.shadow_offset) - def do_click(self, pos, button, action): - if action == "start": + def do_click(self, x, y, mousebtn, event): + if event == "start": self.main_button.x, self.main_button.y = (0, 0) - elif action == "end": + elif event == "end": self.main_button.x, self.main_button.y = (self.shadow_offset, self.shadow_offset) - result = self.click(self, (pos.x, pos.y, button, action)) + result = self.click(self, (x, y, mousebtn, event)) if result: # return True from event function to instantly un-pop self.main_button.x, self.main_button.y = (self.shadow_offset, self.shadow_offset) @@ -509,9 +490,9 @@ class SweetButton: class MainMenu: def __init__(self): - self.scene = mcrfpy.Scene("menu") - self.ui = self.scene.children - self.scene.activate() + menu = mcrfpy.Scene("menu") + self.ui = mcrfpy.sceneUI("menu") + menu.activate() self.crypt = None components = [] @@ -520,7 +501,7 @@ class MainMenu: self.grid = self.demo.grid self.grid.zoom = 1.75 # Center the camera on the middle of the grid (pixel coordinates: cells * tile_size / 2) - gw, gh = int(self.grid.grid_size.x), int(self.grid.grid_size.y) + gw, gh = self.grid.grid_size self.grid.center = (gw * 16 / 2, gh * 16 / 2) coords = self.demo.generate( [("boulder", "boulder", "rat", "cyclops", "boulder"), ("spawn"), ("rat", "big rat"), ("button", "boulder", "exit")] @@ -557,14 +538,14 @@ class MainMenu: #self.create_level(self.depth) for e in self.entities: self.grid.entities.append(e._entity) - def just_wiggle(timer, runtime): + def just_wiggle(*args): try: self.player.try_move(*random.choice(((1, 0),(-1, 0),(0, 1),(0, -1)))) for e in self.entities: e.act() except: pass - self.demo_timer = mcrfpy.Timer("demo_motion", just_wiggle, 100) + mcrfpy.setTimer("demo_motion", just_wiggle, 100) components.append( self.demo.grid ) @@ -624,22 +605,22 @@ class MainMenu: def toast_say(self, txt, delay=10): "kick off a toast event" - if self.toast_event is not None and hasattr(self, 'toast_timer'): - self.toast_timer.stop() + if self.toast_event is not None: + mcrfpy.delTimer("toast_timer") self.toast.text = txt self.toast_event = 350 self.toast.fill_color = (255, 255, 255, 255) self.toast.outline = 2 self.toast.outline_color = (0, 0, 0, 255) - self.toast_timer = mcrfpy.Timer("toast_timer", self.toast_callback, 100) + mcrfpy.setTimer("toast_timer", self.toast_callback, 100) - def toast_callback(self, timer, runtime): + def toast_callback(self, *args): "fade out the toast text" self.toast_event -= 5 if self.toast_event < 0: self.toast_event = None - self.toast_timer.stop() - self.toast.text = "" + mcrfpy.delTimer("toast_timer") + mcrfpy.text = "" return a = min(self.toast_event, 255) self.toast.fill_color = (255, 255, 255, a) @@ -651,8 +632,9 @@ class MainMenu: def play(self, sweet_btn, args): #if args[3] == "start": return # DRAMATIC on release action! if args[3] == "end": return - self.demo_timer.stop() # Clean up the demo timer + mcrfpy.delTimer("demo_motion") # Clean up the demo timer self.crypt = Crypt() + #mcrfpy.setScene("play") self.crypt.start() def scale(self, sweet_btn, args, window_scale=None): @@ -676,25 +658,26 @@ class MainMenu: resources.music_enabled = not resources.music_enabled print(f"music: {resources.music_enabled}") if resources.music_enabled: - resources.set_music_volume(resources.music_volume) + mcrfpy.setMusicVolume(self.music_volume) sweet_btn.text = "Music is ON" sweet_btn.sprite_number = 12 else: self.toast_say("Use your volume keys or\nlook in Settings for a volume meter.") - resources.set_music_volume(0) + mcrfpy.setMusicVolume(0) sweet_btn.text = "Music is OFF" sweet_btn.sprite_number = 17 def sfx_toggle(self, sweet_btn, args): if args[3] == "end": return resources.sfx_enabled = not resources.sfx_enabled + #print(f"sfx: {resources.sfx_enabled}") if resources.sfx_enabled: - resources.set_sfx_volume(resources.sfx_volume) + mcrfpy.setSoundVolume(self.sfx_volume) sweet_btn.text = "SFX are ON" sweet_btn.sprite_number = 0 else: self.toast_say("Use your volume keys or\nlook in Settings for a volume meter.") - resources.set_sfx_volume(0) + mcrfpy.setSoundVolume(0) sweet_btn.text = "SFX are OFF" sweet_btn.sprite_number = 17