2#include "Commands/CommandHelpers.h"
3#include "Commands/CommandParseHelpers.h"
4#include "Commands/ExportCommand.h"
5#include "EditorState.h"
6#include "Editor/Editor.h"
9#include "Renderer/IRenderer.h"
10#include "Renderer/InspectorGui/InspectorGuiRenderer.h"
12#include "Components/Core/LodComponent.h"
13#include "Components/Core/SceneComponent.h"
15#include "RRSaveAllLodCommand.h"
16#include "RRSaveAllLodCommand.h"
17#include "Rendering/Common.h"
19#include "Platform/Instrumentation.h"
21#include "Scene/GetBounds.h"
23#include "Foundation/Logging/Logger.h"
24#include "Foundation/Platform/IO.h"
26#define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING
27#include "rapidjson/document.h"
28#include "rapidjson/stringbuffer.h"
29#include "rapidjson/prettywriter.h"
30#undef _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING
35using namespace rapidjson;
40 const char * label1 =
"RR LOD Save All";
42 uint64_t getModelSizeEstimate(
const std::string & filename)
44 auto fh = Cogs::IO::openFile(filename, Cogs::FileHandle::OpenMode::Open, Cogs::FileHandle::AccessMode::Read);
45 uint64_t size = Cogs::IO::fileSize(fh);
50 void storeLodSidecarfile(std::string path,
51 const std::string & sourcePath,
52 const float threshold,
53 const std::vector<Cogs::Core::ParsedValue> & options,
54 Cogs::Geometry::BoundingBox bbox)
57 auto jsonpath = path +
".json";
58 const auto filename = Cogs::IO::fileName(jsonpath);
61 auto & alloc = doc.GetAllocator();
62 doc.AddMember(
"error", Value().SetFloat(threshold), alloc);
63 doc.AddMember(
"byteSize", Value().SetUint64(getModelSizeEstimate(path)), alloc);
64 doc.AddMember(
"path", Value().SetString(filename.c_str(), alloc), alloc);
65 doc.AddMember(
"offset", Value().SetUint(0), alloc);
66 doc.AddMember(
"source", Value().SetString(sourcePath.c_str(), alloc), alloc);
68 Value box(kArrayType);
69 box.PushBack(Value().SetFloat(bbox.min.x), alloc);
70 box.PushBack(Value().SetFloat(bbox.min.y), alloc);
71 box.PushBack(Value().SetFloat(bbox.min.z), alloc);
72 box.PushBack(Value().SetFloat(bbox.max.x), alloc);
73 box.PushBack(Value().SetFloat(bbox.max.y), alloc);
74 box.PushBack(Value().SetFloat(bbox.max.z), alloc);
75 doc.AddMember(
"bbox", box, alloc);
78 PrettyWriter<StringBuffer> writer(buffer);
81 LOG_DEBUG(logger,
"Writing JSon sidecar: '%s'.", jsonpath.c_str());
82 std::ofstream file(jsonpath.c_str());
83 file.write(buffer.GetString(), buffer.GetSize());
90 RRSaveAllLodCommand::RRSaveAllLodCommand(EditorState * state)
91 : ModalEditorCommand(state)
93 path.resize(128,
'\0');
96 void RRSaveAllLodCommand::apply()
99 bool hasExtension =
false;
100 std::string batchSource;
101 for (
auto & option : options) {
103 if (option.key ==
"path")
106 path.insert(path.begin(), std::begin(option.value), std::end(option.value));
108 else if (option.key ==
"source") {
109 batchSource = option.value;
111 else if (option.key ==
"stem") {
114 else if (option.key ==
"extension") {
120 auto fileName = IO::fileName(batchSource);
121 auto stem = IO::stem(fileName);
123 auto & stemValue = options.emplace_back();
124 stemValue.key =
"stem";
125 stemValue.value = stem;
128 auto fileName = IO::fileName(batchSource);
129 auto extension = IO::extension(batchSource);
131 auto & extensionValue = options.emplace_back();
132 extensionValue.key =
"extension";
133 extensionValue.value = extension;
141 void RRSaveAllLodCommand::beginModal()
146 void RRSaveAllLodCommand::showGui()
150 ImGui::OpenPopup(label1);
151 if (ImGui::BeginPopupModal(label1,
nullptr)) {
153 if (ImGui::InputText(
"Path", path.data(), path.size())) {
155 ImguiRenderer* guiRenderer = context->renderer->getGuiRenderer();
157 guiRenderer->addTextToGlyphBuilder(path.data());
164 if (ImGui::Button(
"Save", ImVec2(120, 0))) {
166 ImGui::CloseCurrentPopup();
174 bool RRSaveAllLodCommand::continueModal()
179 void RRSaveAllLodCommand::runTask()
181 while (!path.empty() && path.back() ==
' ')
182 path.resize(path.size() - 1);
184 auto entity = state->getSelected();
185 if (entity ==
nullptr) {
186 LOG_ERROR(logger,
"No Selected entity.");
190 auto lodComp = entity->getComponent<LodComponent>();
191 if (lodComp ==
nullptr) {
192 LOG_ERROR(logger,
"No LodComponent in entity to save.");
196 auto sourcePath = getOption(options,
"source",
"");
197 auto sceneComponent = entity->getComponent<SceneComponent>();
199 Cogs::Geometry::BoundingBox bb;
200 bb = state->context->bounds->getBounds(context, state->getSelected(),
true);
203 for (
auto threshold : lodComp->thresholds)
205 EntityPtr child = sceneComponent->children[index];
207 SelectCommand select(state, child->getId());
210 ExportCommand cmd(state, child->getId());
211 cmd.options = options;
212 auto & opt = cmd.options.emplace_back();
213 opt.key =
"fileName";
214 opt.value = std::string(path.empty() ?
"" : path.data()) +
"_" + std::to_string(threshold) +
".cogsbin";
215 opt.type = ParsedDataType::String;
218 auto outputPath = opt.value;
219 if (IO::isRelative(outputPath)) {
220 auto destination = getOption(options,
"destination").
to_string();
221 outputPath = IO::combine(destination, outputPath);
224 storeLodSidecarfile(outputPath, sourcePath.to_string(), threshold, options, bb);
230 SelectCommand select(state, entity->getId());
234 bool RRSaveAllLodCommand::issueTask()
Log implementation class.
std::string to_string() const
String conversion method.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
std::string replaceFileMacros(std::string outputName, const std::vector< ParsedValue > &options)
Replace common macroes for file name generation. I.e.: "A/$Filename" etc.
constexpr Log getLogger(const char(&name)[LEN]) noexcept