Cogs.Core
ExportCommand.cpp
1#include "ExportCommand.h"
2#include "CommandParseHelpers.h"
3
4#include "Components/Core/ModelComponent.h"
5#include "Components/Core/MeshComponent.h"
6#include "Components/Core/SceneComponent.h"
7#include "Components/Core/StaticModelComponent.h"
8#include "Resources/Model.h"
9#include "Serialization/ModelWriter.h"
10
11#include "Foundation/Logging/Logger.h"
12#include "Foundation/Platform/IO.h"
13
14#include <iostream>
15#include <iomanip>
16#include <sstream>
17
18namespace
19{
20 Cogs::Logging::Log logger = Cogs::Logging::getLogger("ExportCommand");
21
22 void getEntity(Cogs::Core::Context* /*context*/, std::vector<Cogs::ComponentModel::Entity*>& entities, Cogs::ComponentModel::Entity* entity)
23 {
24 if (entity == nullptr) return;
25
26 if (auto result = std::find_if(entities.begin(), entities.end(), [e = entity](Cogs::ComponentModel::Entity*& x) { return x->getId() == e->getId(); });
27 result != entities.end()) {
28 return;
29 }
30
32 if (!sceneComp) return;
33
36 if (!meshComp && !staticModelComp) return;
37
38 LOG_DEBUG(logger, "export entity id: %zu", entity->getId());
39 entities.push_back(entity);
40 }
41}
42
43namespace Cogs::Core
44{
45}
46
47#ifndef EMSCRIPTEN
49{
50 std::string fileName = getOption(options, "fileName").to_string();
51
52 std::string stem = getOption(options, "stem").to_string();
53 if (fileName.empty() && !stem.empty()) {
54 fileName = stem + ".cogsbin";
55 }
56
57 if (!fileName.empty()) {
58 std::string outputName = replaceFileMacros(fileName, options);
59
60 std::string destination = getOption(options, "destination").to_string();
61
62 if (destination.size()) {
63 if (!IO::exists(destination)) {
64 fs::create_directories(destination);
65 }
66
67 outputName = IO::combine(destination, outputName);
68 }
69
70 fileName = outputName;
71 }
72
73 if (fileName.empty()) {
74 std::string name = "Model.cogsbin";
75
77 if (modelComp && modelComp->model) {
78 std::string modelPath = modelComp->model->getSource().to_string();
79 std::string modelFileName = IO::fileName(modelPath);
80
81 stem = IO::stem(modelFileName);
82
83 if (!stem.empty()) {
84 name = stem + ".cogsbin";
85 }
86 } else if (state->getSelected()->getName().size()) {
87 name = fixInvalidPathChars(state->getSelected()->getName()) + ".cogsbin";
88 }
89
90 fileName = name;
91 }
92
93 std::string path = fileName;
94
95 if (IO::isRelative(path)) {
96 path = IO::combine(state->directory, path);
97 }
98
99 bool ok = false;
100 if (exportScene) {
101 uint32_t numVertes;
102 uint32_t numIndexes;
103
104 std::vector<ComponentModel::Entity*> entities;
105 const std::unordered_map<EntityId, EntityPtr>& entityMap = context->store->getEntities();
106
107 for (const auto& e : entityMap) {
108 Cogs::ComponentModel::Entity* entity = context->store->getEntityPtr(static_cast<EntityId>(e.first));
109 getEntity(context, entities, entity);
110 }
111
112 ok = writeModels(context, numVertes, numIndexes, path, entities.data(), entities.size(), WriteModelFlags::COMPRESS_ZSTD | WriteModelFlags::COMPRESS_MAX);
113 }
114 else {
115 if (1 < state->selected.size()) {
116 uint32_t numVertes;
117 uint32_t numIndexes;
118
119 std::vector<ComponentModel::Entity*> entities;
120
121 for (auto id : state->selected) {
122 entities.push_back(context->store->getEntityPtr(id));
123 }
124 ok = writeModels(context, numVertes, numIndexes, path, entities.data(), entities.size(), WriteModelFlags::COMPRESS_ZSTD | WriteModelFlags::COMPRESS_MAX);
125 }
126 else {
127 ok = writeModel(context, path, state->getSelected(), WriteModelFlags::COMPRESS_ZSTD | WriteModelFlags::COMPRESS_MAX);
128 }
129 }
130
131 if (!ok) {
132 LOG_ERROR(logger, "Could not save model to: %s", path.c_str());
133 }
134 else {
135 LOG_DEBUG(logger, "Wrote %s", path.c_str());
136 }
137}
138#else
140#endif
141
142void Cogs::Core::ExportCommand::undo()
143{
144}
Container for components, providing composition of dynamic entities.
Definition: Entity.h:18
T * getComponent() const
Get a pointer to the first component implementing the given type in the entity.
Definition: Entity.h:35
constexpr size_t getId() const noexcept
Get the unique identifier of this entity.
Definition: Entity.h:113
const std::string & getName() const noexcept
Get the name of this entity.
Definition: Entity.h:120
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
class EntityStore * store
Entity store.
Definition: Context.h:231
ComponentModel::Entity * getEntityPtr(const EntityId entityId)
Get a raw pointer to the entity with the given id.
const std::unordered_map< EntityId, EntityPtr > & getEntities() const
Return map of entities with global ownership.
Definition: EntityStore.h:268
virtual void apply() override
Run the command.
Contains a handle to a Mesh resource to use when rendering using the MeshRenderComponent.
Definition: MeshComponent.h:15
Contains information on how the entity behaves in the scene.
Log implementation class.
Definition: LogManager.h:139
std::string to_string() const
String conversion method.
Definition: StringView.cpp:9
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.
std::string fixInvalidPathChars(const std::string &filename)
Remove characters that are not valid for filenames lik "<>:/\?" etc.
StringView getOption(const std::vector< ParsedValue > &options, const StringView &key, const StringView &defaultValue="")
Find and get value of option in vector as a string. Return default if not found.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
std::vector< ParsedValue > options
Options passed to the command when running in batch mode.
Definition: EditorCommand.h:61
ComponentModel::Entity * getSelected() const
Gets entity Pointer to the single selected entity. Nullptr if not one selected or not found.
Definition: EditorState.h:133
Contains a model reference to instance as children to the entity the ModelComponent belongs to.
ModelHandle model
Handle to a model resource that will be instanced onto the entity this ModelComponent belongs to.