// // Copyright (c) 2014-2017 THUNDERBEAST GAMES LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #include #include #include #include "GlowProcess.h" #include "GlowServiceEvents.h" #include "GlowService.h" namespace AtomicGlow { GlowService::GlowService(Context* context) : Object(context), bakeCanceled_(false) { } GlowService::~GlowService() { } void GlowService::OnGlowProcessExited() { if (glowProcess_.NotNull()) { if (!glowProcess_->GetExitCalled() || bakeCanceled_) { using namespace AtomicGlowServiceBakeResult; VariantMap eventData; eventData[P_RESULT] = bakeCanceled_ ? "Bake canceled" : "GlowService::OnGlowProcessExited() - Glow process exited unexpectedly"; eventData[P_SUCCESS] = false; SendEvent(E_ATOMICGLOWSERVICEBAKERESULT, eventData); } } if (scene_) { scene_->LoadLightmaps(true); } projectPath_ = String::EMPTY; glowProcess_ = 0; scene_ = 0; } void GlowService::OnBakeError(const String& result) { ATOMIC_LOGERRORF("%s", result.CString()); glowProcess_->Exit(); using namespace AtomicGlowServiceBakeResult; VariantMap eventData; eventData[P_RESULT] = result; eventData[P_SUCCESS] = false; SendEvent(E_ATOMICGLOWSERVICEBAKERESULT, eventData); } void GlowService::OnBakeSuccess() { glowProcess_->Exit(); using namespace AtomicGlowServiceBakeResult; VariantMap eventData; eventData[P_RESULT] = "success"; eventData[P_SUCCESS] = true; SendEvent(E_ATOMICGLOWSERVICEBAKERESULT, eventData); } void GlowService::ProcessBakeData(VectorBuffer& bakeData) { if (!scene_) { ATOMIC_LOGERROR("GlowService::ProcessBakeData() - called with null scene"); return; } unsigned count = bakeData.ReadUInt(); PODVector children; scene_->GetChildrenWithComponent(children, true); for (unsigned i = 0; i < count; i++) { Node* node = 0; StaticModel* staticModel = 0; unsigned nodeID = bakeData.ReadUInt(); unsigned staticModelID = bakeData.ReadUInt(); unsigned lightMask = bakeData.ReadUInt(); unsigned lightmapIndex = bakeData.ReadUInt(); Vector4 tilingOffset = bakeData.ReadVector4(); for (unsigned j = 0; j < children.Size(); j++) { if (children[j]->GetID() == nodeID) { node = children[j]; staticModel = node->GetComponent(); if (!staticModel || staticModel->GetID() != staticModelID) { ATOMIC_LOGERROR("GlowService::ProcessBakeData() - mismatched node <-> static model ID"); return; } break; } } if (!node) { ATOMIC_LOGERROR("GlowService::ProcessBakeData() - unable to find node ID"); return; } staticModel->SetLightMask(lightMask); staticModel->SetLightmapIndex(lightmapIndex); staticModel->SetLightmapTilingOffset(tilingOffset); } } bool GlowService::Bake(const String& projectPath, Scene* scene, const GlowSettings& settings) { if (!scene) { ATOMIC_LOGERROR("GlowService::Bake() - Called with null scene"); return false; } String sceneName = scene->GetFileName(); if (!sceneName.Length()) { ATOMIC_LOGERROR("GlowService::Bake() - Called with unnamed scene"); return false; } if (!projectPath.Length()) { ATOMIC_LOGERROR("GlowService::Bake() - zero length projectPath"); return false; } if (glowProcess_.NotNull()) { ATOMIC_LOGERROR("GlowService::Bake() - Called with existing glow process"); return false; } bakeCanceled_ = false; result_.Clear(); glowProcess_ = new GlowProcess(context_); projectPath_ = projectPath; StringVector args; args.Push("--project"); args.Push(projectPath_); args += glowBaseArgs_; if (!glowProcess_->Start(glowBinaryPath_, args)) { ATOMIC_LOGERROR("GlowService::Bake() - Glow process failed to start"); return false; } scene_ = scene; projectPath_ = projectPath; using namespace IPCCmd; VariantMap cmdMap; cmdMap[P_COMMAND] = "bake"; cmdMap["scenename"] = sceneName; // settings VectorBuffer settingsBuffer; settings.Pack(settingsBuffer); cmdMap["settings"] = settingsBuffer; glowProcess_->QueueCommand(cmdMap); return true; } void GlowService::CancelBake() { if (glowProcess_.Null()) { ATOMIC_LOGERROR("GlowService::CancelBake() - Called without existing glow process"); return; } bakeCanceled_ = true; glowProcess_->Exit(); } bool GlowService::Start() { bool failed = false; if (failed) { ATOMIC_LOGERROR("GlowService::Start() - Unable to start AtomicGlow service"); return false; } glowBinaryPath_ = String::EMPTY; glowBaseArgs_.Clear(); #ifdef ATOMIC_DEBUG glowBinaryPath_ = "/Users/jenge/Dev/atomic/build-AtomicGameEngine-Desktop-Debug/Source/AtomicGlow/AtomicGlow"; #else glowBinaryPath_ = "/Users/jenge/Dev/atomic/build-AtomicGameEngine-Desktop-Release/Source/AtomicGlow/AtomicGlow"; #endif return true; } }