From ed390e56c3ce24fcd0d597a9bb8d36df730110c1 Mon Sep 17 00:00:00 2001 From: Anemunt <69436164+darkresident55@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:53:15 -0500 Subject: [PATCH] part 2 since i forgot to stage changes lol. --- src/AudioSystem.cpp | 32 +++++++++++++++++++++++++++++++- src/AudioSystem.h | 7 +++++++ src/Engine.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/Engine.h | 7 +++++++ src/EnginePanels.cpp | 38 +++++++++++++++++++++++++++++++------- src/ScriptRuntime.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/ScriptRuntime.h | 7 +++++++ 7 files changed, 155 insertions(+), 8 deletions(-) diff --git a/src/AudioSystem.cpp b/src/AudioSystem.cpp index 7f3fe34..c7ecaf6 100644 --- a/src/AudioSystem.cpp +++ b/src/AudioSystem.cpp @@ -80,6 +80,7 @@ bool AudioSystem::ensureSoundFor(const SceneObject& obj) { snd.clipPath = obj.audioSource.clipPath; snd.spatial = obj.audioSource.spatial; + snd.started = false; refreshSoundParams(obj, snd); activeSounds[obj.id] = std::move(snd); return true; @@ -93,8 +94,9 @@ void AudioSystem::refreshSoundParams(const SceneObject& obj, ActiveSound& snd) { ma_sound_set_max_distance(&snd.sound, obj.audioSource.maxDistance); ma_sound_set_position(&snd.sound, obj.position.x, obj.position.y, obj.position.z); - if (!ma_sound_is_playing(&snd.sound) && obj.audioSource.playOnStart && obj.audioSource.enabled) { + if (!ma_sound_is_playing(&snd.sound) && !snd.started && obj.audioSource.playOnStart && obj.audioSource.enabled) { ma_sound_start(&snd.sound); + snd.started = true; } } @@ -197,6 +199,34 @@ bool AudioSystem::seekPreview(const std::string& path, double seconds) { return res == MA_SUCCESS; } +bool AudioSystem::playObjectSound(const SceneObject& obj) { + if (!obj.hasAudioSource || obj.audioSource.clipPath.empty() || !obj.audioSource.enabled) return false; + if (!ensureSoundFor(obj)) return false; + ActiveSound& snd = activeSounds[obj.id]; + snd.started = true; + return ma_sound_start(&snd.sound) == MA_SUCCESS; +} + +bool AudioSystem::stopObjectSound(int objectId) { + auto it = activeSounds.find(objectId); + if (it == activeSounds.end()) return false; + return ma_sound_stop(&it->second.sound) == MA_SUCCESS; +} + +bool AudioSystem::setObjectLoop(const SceneObject& obj, bool loop) { + if (!ensureSoundFor(obj)) return false; + ActiveSound& snd = activeSounds[obj.id]; + ma_sound_set_looping(&snd.sound, loop ? MA_TRUE : MA_FALSE); + return true; +} + +bool AudioSystem::setObjectVolume(const SceneObject& obj, float volume) { + if (!ensureSoundFor(obj)) return false; + ActiveSound& snd = activeSounds[obj.id]; + ma_sound_set_volume(&snd.sound, volume); + return true; +} + AudioClipPreview AudioSystem::loadPreview(const std::string& path) { AudioClipPreview preview; preview.path = path; diff --git a/src/AudioSystem.h b/src/AudioSystem.h index 1e5aa2b..07bd2cc 100644 --- a/src/AudioSystem.h +++ b/src/AudioSystem.h @@ -33,11 +33,18 @@ public: bool getPreviewTime(const std::string& path, double& cursorSeconds, double& durationSeconds) const; bool seekPreview(const std::string& path, double seconds); + // Scene audio control (runtime) + bool playObjectSound(const SceneObject& obj); + bool stopObjectSound(int objectId); + bool setObjectLoop(const SceneObject& obj, bool loop); + bool setObjectVolume(const SceneObject& obj, float volume); + private: struct ActiveSound { ma_sound sound; std::string clipPath; bool spatial = true; + bool started = false; // prevents auto-restart after manual stop }; ma_engine engine{}; diff --git a/src/Engine.cpp b/src/Engine.cpp index 4ef8cff..1a84b64 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -1266,6 +1266,42 @@ bool Engine::teleportPhysicsActorFromScript(int id, const glm::vec3& position, c return physics.setActorPose(id, position, rotationDeg); } +bool Engine::playAudioFromScript(int id) { + SceneObject* obj = findObjectById(id); + if (!obj || !obj->hasAudioSource) return false; + return audio.playObjectSound(*obj); +} + +bool Engine::stopAudioFromScript(int id) { + return audio.stopObjectSound(id); +} + +bool Engine::setAudioLoopFromScript(int id, bool loop) { + SceneObject* obj = findObjectById(id); + if (!obj || !obj->hasAudioSource) return false; + obj->audioSource.loop = loop; + markProjectDirty(); + return audio.setObjectLoop(*obj, loop); +} + +bool Engine::setAudioVolumeFromScript(int id, float volume) { + SceneObject* obj = findObjectById(id); + if (!obj || !obj->hasAudioSource) return false; + obj->audioSource.volume = std::clamp(volume, 0.0f, 2.0f); + markProjectDirty(); + return audio.setObjectVolume(*obj, obj->audioSource.volume); +} + +bool Engine::setAudioClipFromScript(int id, const std::string& path) { + SceneObject* obj = findObjectById(id); + if (!obj || !obj->hasAudioSource) return false; + obj->audioSource.clipPath = path; + markProjectDirty(); + // Ensure clip is loaded; do not auto-play unless PlayAudio is called. + audio.setObjectLoop(*obj, obj->audioSource.loop); + return true; +} + void Engine::compileScriptFile(const fs::path& scriptPath) { if (!projectManager.currentProject.isLoaded) { addConsoleMessage("No project is loaded", ConsoleMessageType::Warning); diff --git a/src/Engine.h b/src/Engine.h index 6e1b43a..ef78478 100644 --- a/src/Engine.h +++ b/src/Engine.h @@ -92,6 +92,7 @@ private: bool isPlaying = false; bool isPaused = false; bool showViewOutput = true; + bool showSceneGizmos = true; bool showGameViewport = true; int previewCameraId = -1; bool gameViewCursorLocked = false; @@ -221,4 +222,10 @@ public: bool setRigidbodyVelocityFromScript(int id, const glm::vec3& velocity); bool getRigidbodyVelocityFromScript(int id, glm::vec3& outVelocity); bool teleportPhysicsActorFromScript(int id, const glm::vec3& position, const glm::vec3& rotationDeg); + // Audio control exposed to scripts + bool playAudioFromScript(int id); + bool stopAudioFromScript(int id); + bool setAudioLoopFromScript(int id, bool loop); + bool setAudioVolumeFromScript(int id, float volume); + bool setAudioClipFromScript(int id, const std::string& path); }; diff --git a/src/EnginePanels.cpp b/src/EnginePanels.cpp index b50fa69..a2851fc 100644 --- a/src/EnginePanels.cpp +++ b/src/EnginePanels.cpp @@ -3576,6 +3576,7 @@ void Engine::renderViewport() { } bool mouseOverViewportImage = false; + bool blockSelection = false; if (rendererInitialized) { glm::mat4 proj = glm::perspective( @@ -3687,6 +3688,11 @@ void Engine::renderViewport() { if (clickedIdx >= 0) { setCameraFacing(arrows[clickedIdx].dir); } + + // Prevent viewport picking when interacting with the axis widget. + if (widgetHover) { + blockSelection = true; + } } auto projectToScreen = [&](const glm::vec3& p) -> std::optional { @@ -4170,9 +4176,11 @@ void Engine::renderViewport() { } }; - for (const auto& obj : sceneObjects) { - if (obj.type == ObjectType::Camera) { - drawCameraDirection(obj); + if (showSceneGizmos) { + for (const auto& obj : sceneObjects) { + if (obj.type == ObjectType::Camera) { + drawCameraDirection(obj); + } } } @@ -4269,9 +4277,11 @@ void Engine::renderViewport() { } }; - for (const auto& obj : sceneObjects) { - if (obj.type == ObjectType::PointLight || obj.type == ObjectType::SpotLight || obj.type == ObjectType::AreaLight) { - drawLightOverlays(obj); + if (showSceneGizmos) { + for (const auto& obj : sceneObjects) { + if (obj.type == ObjectType::PointLight || obj.type == ObjectType::SpotLight || obj.type == ObjectType::AreaLight) { + drawLightOverlays(obj); + } } } @@ -4406,6 +4416,14 @@ void Engine::renderViewport() { } } + ImGui::SameLine(0.0f, toolbarSpacing * 1.25f); + if (GizmoToolbar::ModeButton("Gizmos", showSceneGizmos, ImVec2(70, 24), baseCol, accentCol, textCol)) { + showSceneGizmos = !showSceneGizmos; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Toggle light/camera scene symbols"); + } + ImGui::EndGroup(); ImGui::PopStyleVar(); @@ -4420,10 +4438,16 @@ void Engine::renderViewport() { splitter.Merge(toolbarDrawList); + // Prevent viewport picking when clicking on the toolbar overlay. + if (ImGui::IsMouseHoveringRect(bgMin, bgMax)) { + blockSelection = true; + } + // Left-click picking inside viewport if (mouseOverViewportImage && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && - !ImGuizmo::IsUsing() && !ImGuizmo::IsOver()) + !ImGuizmo::IsUsing() && !ImGuizmo::IsOver() && + !blockSelection) { glm::mat4 invViewProj = glm::inverse(proj * view); ImVec2 mousePos = ImGui::GetMousePos(); diff --git a/src/ScriptRuntime.cpp b/src/ScriptRuntime.cpp index a6621c7..eb6a883 100644 --- a/src/ScriptRuntime.cpp +++ b/src/ScriptRuntime.cpp @@ -108,6 +108,42 @@ bool ScriptContext::TeleportRigidbody(const glm::vec3& pos, const glm::vec3& rot return engine->teleportPhysicsActorFromScript(object->id, pos, object->rotation); } +bool ScriptContext::HasAudioSource() const { + return object && object->hasAudioSource && object->audioSource.enabled; +} + +bool ScriptContext::PlayAudio() { + if (!engine || !object || !object->hasAudioSource) return false; + return engine->playAudioFromScript(object->id); +} + +bool ScriptContext::StopAudio() { + if (!engine || !object || !object->hasAudioSource) return false; + return engine->stopAudioFromScript(object->id); +} + +bool ScriptContext::SetAudioLoop(bool loop) { + if (!engine || !object || !object->hasAudioSource) return false; + object->audioSource.loop = loop; + engine->markProjectDirty(); + return engine->setAudioLoopFromScript(object->id, loop); +} + +bool ScriptContext::SetAudioVolume(float volume) { + if (!engine || !object || !object->hasAudioSource) return false; + float clamped = std::clamp(volume, 0.0f, 2.0f); + object->audioSource.volume = clamped; + engine->markProjectDirty(); + return engine->setAudioVolumeFromScript(object->id, clamped); +} + +bool ScriptContext::SetAudioClip(const std::string& path) { + if (!engine || !object || !object->hasAudioSource) return false; + object->audioSource.clipPath = path; + engine->markProjectDirty(); + return engine->setAudioClipFromScript(object->id, path); +} + std::string ScriptContext::GetSetting(const std::string& key, const std::string& fallback) const { if (!script) return fallback; auto it = std::find_if(script->settings.begin(), script->settings.end(), diff --git a/src/ScriptRuntime.h b/src/ScriptRuntime.h index 4fe69ff..14bd875 100644 --- a/src/ScriptRuntime.h +++ b/src/ScriptRuntime.h @@ -40,6 +40,13 @@ struct ScriptContext { bool SetRigidbodyVelocity(const glm::vec3& velocity); bool GetRigidbodyVelocity(glm::vec3& outVelocity) const; bool TeleportRigidbody(const glm::vec3& pos, const glm::vec3& rotDeg); + // Audio helpers + bool HasAudioSource() const; + bool PlayAudio(); + bool StopAudio(); + bool SetAudioLoop(bool loop); + bool SetAudioVolume(float volume); + bool SetAudioClip(const std::string& path); // Settings helpers (auto-mark dirty) std::string GetSetting(const std::string& key, const std::string& fallback = "") const; void SetSetting(const std::string& key, const std::string& value);