#include "behavior.h" #include #include #include #include #include UF_BEHAVIOR_REGISTER_CPP(ext::SoundEmitterBehavior) #define this ((uf::Object*) &self) void ext::SoundEmitterBehavior::initialize( uf::Object& self ) { auto& metadata = this->getComponent(); auto& emitter = this->getComponent(); auto& sounds = emitter.get(); auto& scene = uf::scene::getCurrentScene(); auto& sMetadata = scene.getComponent(); auto& assetLoader = scene.getComponent(); if ( !metadata["audio"]["epsilon"].is() ) metadata["audio"]["epsilon"] = 0.001f; // auto& sounds = this->getComponent>(); this->addHook( "sound:Stop.%UID%", [&](ext::json::Value& json){ std::string filename = json["filename"].as(); for ( size_t i = 0; i < sounds.size(); ++i ) { if ( sounds[i]->getFilename() != filename ) continue; sounds[i]->destroy(); delete sounds[i]; sounds.erase(sounds.begin() + i); metadata["sounds"].erase(i); } }); this->addHook( "sound:Emit.%UID%", [&](ext::json::Value& json){ if ( ext::json::isNull(json["volume"]) ) json["volume"] = metadata["audio"]["volume"]; if ( ext::json::isNull(json["pitch"]) ) json["pitch"] = metadata["audio"]["pitch"]; if ( ext::json::isNull(json["gain"]) ) json["gain"] = metadata["audio"]["gain"]; if ( ext::json::isNull(json["rolloffFactor"]) ) json["rolloffFactor"] = metadata["audio"]["rolloffFactor"]; if ( ext::json::isNull(json["maxDistance"]) ) json["maxDistance"] = metadata["audio"]["maxDistance"]; if ( ext::json::isNull(json["epsilon"]) ) json["epsilon"] = metadata["audio"]["epsilon"]; metadata["sounds"].emplace_back(json); uf::Audio& audio = emitter.add( json["filename"].as(), json["unique"].as() ); { float volume = 1.0f; if ( json["volume"].is() ) { volume = json["volume"].as(); } else if ( json["volume"].is() ) { std::string key = json["volume"].as(); if ( sMetadata["volumes"][key].is() ) { volume = sMetadata["volumes"][key].as(); } } audio.setVolume(volume); } if ( json["pitch"].is() ) audio.setPitch(json["pitch"].as()); if ( json["gain"].is() ) audio.setGain(json["gain"].as()); if ( json["rolloffFactor"].is() ) audio.setRolloffFactor(json["rolloffFactor"].as()); if ( json["maxDistance"].is() ) audio.setMaxDistance(json["maxDistance"].as()); audio.play(); }); this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){ std::string filename = json["filename"].as(); std::string category = json["category"].as(); if ( category != "" && category != "audio" ) return; if ( category == "" && uf::io::extension(filename) != "ogg" ) return; const uf::Audio* audioPointer = NULL; if ( !assetLoader.has(filename) ) return; audioPointer = &assetLoader.get(filename); if ( !audioPointer ) return; uf::Serializer payload = metadata["audio"]; payload["filename"] = filename; this->callHook("sound:Emit.%UID%", payload); }); } void ext::SoundEmitterBehavior::tick( uf::Object& self ) { auto& transform = this->getComponent>(); auto flatten = uf::transform::flatten( transform ); auto& metadata = this->getComponent(); auto& emitter = this->getComponent(); auto& sounds = emitter.get(); for ( size_t i = 0; i < sounds.size(); ++i ) { auto& audio = *sounds[i]; auto& json = metadata["sounds"][i]; if ( json["spatial"].as() && audio.playing() ) { audio.setPosition( flatten.position ); audio.setOrientation( flatten.orientation ); } if ( json["loop"].as() ) { float current = audio.getTime(); float end = audio.getDuration(); float epsilon = json["epsilon"].is() ? json["epsilon"].as() : 0.005f; if ( current + epsilon >= end || !audio.playing() ) { audio.setTime(0); if ( !audio.playing() ) audio.play(); } } else if ( !audio.playing() ) { audio.destroy(); delete sounds[i]; sounds.erase(sounds.begin() + i); metadata["sounds"].erase(i); } } } void ext::SoundEmitterBehavior::render( uf::Object& self ){} void ext::SoundEmitterBehavior::destroy( uf::Object& self ){} #undef this