1#include "EditorCommand.h"
4#include "EntityStore.h"
6#include "Serialization/EntityReader.h"
7#include "Serialization/EntityWriter.h"
8#include "Serialization/SceneReader.h"
9#include "Serialization/EntityCreator.h"
11#include "Bridge/SceneFunctions.h"
13#include "Components/Core/TransformComponent.h"
15#include "Foundation/Geometry/BoundingBox.hpp"
16#include "Foundation/Logging/Logger.h"
17#include "Foundation/Reflection/TypeDatabase.h"
24Cogs::Core::PostCommand::~PostCommand() =
default;
28Cogs::Core::CreateEntityCommand::CreateEntityCommand(EditorState* state,
const StringView& type,
const StringView& name,
bool openInRoot)
29 : EditorCommand(state, state->context), type(type.to_string()), name(name.to_string()),
30 openInRoot(openInRoot)
40 parentId = parent->
getId();
46 entityId = entity->getId();
48 previousSelection = state->selected;
53void Cogs::Core::CreateEntityCommand::undo()
55 if (entityId == NoEntity)
return;
57 if (parentId == NoEntity) {
58 context->store->destroyEntity(entityId);
63 if (entity && parent) {
64 context->store->removeChild(parent, entity);
68 state->setSelection(previousSelection);
77 previousSelection = state->selected;
80 object.CopyFrom(state->copied, state->copied.GetAllocator());
87 std::vector<ComponentModel::Entity*> entities(scene.entities.size());
89 ids.reserve(scene.entities.size());
93 (definition.parentIndex == SceneEntityDefinition::NoIndex ? parent : entities[definition.parentIndex]);
95 entities[definition.index] = createEntity(context, scene, definition, parentEntity);
97 ids.push_back(entities[definition.index]->getId());
100 RemoveEntitiesWithAncestors(context, ids, entityIds);
101 state->setSelection(entityIds);
104void Cogs::Core::PasteEntityCommand::undo()
106 for (
const EntityId entityId : entityIds) {
109 if (parent && entity) {
110 context->store->removeChild(parent, entity);
113 context->store->destroyEntity(entityId);
117 state->setSelection(previousSelection);
124 previousSelection = state->selected;
125 state->scrolled =
false;
127 if (selectedIds.size() && selectedIds[0] == NoEntity) {
131 if (mode == SelectMode::Exclusive) {
132 state->pickId = pickId;
133 state->setSelection(selectedIds);
135 else if (mode == SelectMode::Add) {
136 EntityIds newSelection = state->selected;
137 for (
const EntityId
id : selectedIds) {
138 const bool found = std::find(previousSelection.begin(), previousSelection.end(),
id) != previousSelection.end();
140 newSelection.push_back(
id);
143 state->pickId = pickId;
144 state->setSelection(newSelection);
146 else if (mode == SelectMode::Toggle) {
147 EntityIds newSelection = state->selected;
148 for (
const EntityId
id : selectedIds) {
149 const bool found = std::find(previousSelection.begin(), previousSelection.end(),
id) != previousSelection.end();
151 newSelection.push_back(
id);
152 if (selectedIds.size() == 1) {
153 state->pickId = pickId;
157 auto end = std::remove(newSelection.begin(), newSelection.end(),
id);
158 if (end != newSelection.end()) {
159 newSelection.erase(end, newSelection.end());
164 state->setSelection(newSelection);
168void Cogs::Core::SelectCommand::undo()
170 state->setSelection(previousSelection);
182void Cogs::Core::AddComponentCommand::undo()
190 context->store->removeComponent(entity, handle);
197 previousMode = state->mode;
198 state->mode = newMode;
201void Cogs::Core::ChangeEditingModeCommand::undo()
203 state->mode = previousMode;
210 for (
size_t i = 0; i < state->selected.size(); ++i) {
211 auto entity = context->store->getEntityPtr(entityIds[i]);
214 transformComponent->
position = state->startTranslations[i] + translation;
215 transformComponent->setChanged();
218 previousTranslations = state->startTranslations;
221void Cogs::Core::TranslateCommand::undo()
223 for (
size_t i = 0; i < state->selected.size(); ++i) {
224 auto entity = context->store->getEntityPtr(entityIds[i]);
227 transformComponent->
position = previousTranslations[i];
228 transformComponent->setChanged();
238 if (!translateCommand)
return false;
239 if (entityIds != translateCommand->entityIds)
return false;
241 translation = translateCommand->translation;
250 for (
size_t i = 0; i < state->selected.size(); ++i) {
251 auto entity = context->store->getEntityPtr(entityIds[i]);
254 transformComponent->
rotation = rotation * state->startRotations[i];
255 transformComponent->setChanged();
258 previousRotations = state->startRotations;
261void Cogs::Core::RotateCommand::undo()
263 for (
size_t i = 0; i < state->selected.size(); ++i) {
264 auto entity = context->store->getEntityPtr(entityIds[i]);
267 transformComponent->
rotation = previousRotations[i];
268 transformComponent->setChanged();
276 if (!rotateCommand)
return false;
277 if (entityIds != rotateCommand->entityIds)
return false;
279 rotation = rotateCommand->rotation;
287 for (
size_t i = 0; i < state->selected.size(); ++i) {
288 auto entity = context->store->getEntityPtr(entityIds[i]);
291 transformComponent->
scale = state->startScales[i] + scale;
292 transformComponent->setChanged();
295 previousScales = state->startScales;
298void Cogs::Core::ScaleCommand::undo()
300 for (
size_t i = 0; i < state->selected.size(); ++i) {
301 auto entity = context->store->getEntityPtr(entityIds[i]);
304 transformComponent->
scale = previousScales[i];
305 transformComponent->setChanged();
313 if (!scaleCommand)
return false;
314 if (entityIds != scaleCommand->entityIds)
return false;
316 scale = scaleCommand->scale;
326 Geometry::DBoundingBox bb;
327 ::calculateBoundingBoxWorld(context, entityId, bb.data());
328 LOG_DEBUG(logger,
"Original bounds: [%.2f %.2f %.2f] x [%.2f %.2f %.2f]",
329 bb.min.x, bb.min.y, bb.min.z,
330 bb.max.x, bb.max.y, bb.max.z);
333 if (!isEmpty(bb) && bb.min.x < bb.max.x) {
334 const glm::dvec3 extent = bb.max - bb.min;
335 scale = 2.0 / std::max(std::max(extent.x, extent.y), extent.z);
337 LOG_DEBUG(logger,
"Scale: %e", scale);
341 previousScale = trComp->scale;
342 trComp->scale = glm::vec3(
float(scale)) * trComp->scale;
344 previousPosition = trComp->position;
345 trComp->position = trComp->position - glm::vec3(scale * bb.min) - glm::vec3(1.f);
347 trComp->setChanged();
352void Cogs::Core::ScaleToUnitCubeCommand::undo()
356 trComp->scale = previousScale;
357 trComp->position = previousPosition;
358 trComp->setChanged();
372 for (
const EntityId s : entityIds) {
374 entityValue.SetObject();
376 writeEntity(context, context->store->getEntityPtr(s), entityValue, d,
nullptr, writeFlags);
378 d.PushBack(entityValue, d.GetAllocator());
381 copied = std::move(d);
385 parentIds.reserve(entityIds.size());
387 for (
const EntityId entityId : entityIds) {
388 EntityId parentId = NoEntity;
391 if (parent && entity) {
392 context->store->removeChild(parent, entity);
393 parentId = parent->
getId();
396 context->store->destroyEntity(entityId);
400 parentIds.emplace_back(parentId);
404 state->clearSelection();
405 state->mode = EditingMode::Select;
408void Cogs::Core::DestroyCommand::undo()
418 object.CopyFrom(copied, copied.GetAllocator());
420 AssetDefinition asset;
421 SceneDefinition& scene = asset.scene;
423 std::vector<ComponentModel::Entity*> entities(scene.entities.size());
425 ids.reserve(scene.entities.size());
428 for (SceneEntityDefinition& definition : scene.entities) {
430 if (!definition.isParentedByName()) {
431 if (definition.parentIndex == SceneEntityDefinition::NoIndex) {
433 assert(entityNo < parentIds.size());
434 parentEntity = (entityNo < parentIds.size() && parentIds[entityNo] != NoEntity) ?
435 context->store->getEntityPtr(parentIds[entityNo]) :
nullptr;
439 parentEntity = entities[definition.parentIndex];
443 entities[definition.index] = createEntity(context, scene, definition, parentEntity);
445 ids.push_back(entities[definition.index]->getId());
448 RemoveEntitiesWithAncestors(context, ids, ids);
449 state->setSelection(ids);
454 EntityPtr group = context->store->createEntity(
"Group",
"Group");
456 groupId = group->getId();
459 for (
const EntityId childId : entityIds) {
460 EntityPtr childEntity = context->store->getEntity(childId);
462 context->store->addChild(groupEntity, childEntity);
465 state->setSelection(groupId);
468void Cogs::Core::GroupCommand::undo()
470 for (
const EntityId
id : entityIds) {
471 context->store->removeChild(context->store->getEntityPtr(groupId), context->store->getEntityPtr(
id));
474 context->store->destroyEntity(groupId);
476 state->setSelection(entityIds);
480void Cogs::Core::RemoveEntitiesWithAncestors(Context* context,
const EntityIds& entityIds, EntityIds& output)
483 ids.reserve(entityIds.size());
484 for (
const EntityId
id : entityIds) {
486 while ((entity = context->store->getEntityParent(entity)) !=
nullptr) {
487 EntityId parentId = entity->getId();
488 if (std::find(entityIds.begin(), entityIds.end(), parentId) != entityIds.end()) {
498 output = std::move(ids);
Container for components, providing composition of dynamic entities.
T * getComponent() const
Get a pointer to the first component implementing the given type in the entity.
constexpr size_t getId() const noexcept
Get the unique identifier of this entity.
void addComponent(ComponentHandle component)
ComponentHandle getComponentHandle() const
Get a component handle to the first component implementing the given type.
class EntityStore * store
Entity store.
EntityPtr createChildEntity(const StringView &type, ComponentModel::Entity *parent, const StringView &name=StringView())
Create a new Entity, parenting it to the given parent.
EntityPtr createEntity(const StringView &name, const StringView &type, bool storeOwnership=true)
Create a new Entity.
void apply() override
Run the command.
Log implementation class.
static const Type & getType()
Get the Type of the given template argument.
Represents a discrete type definition, describing a native type class.
Provides a weakly referenced view over the contents of a string.
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
void COGSCORE_DLL_API readSceneDefinition(class Context *context, const Value &jsonScene, AssetLoadFlags flags, AssetDefinition &asset)
Parse JSON description of Entities in Cogs Scene. Store contents in asset param.
AssetWriteFlags
Flags that control serialization of assets.
@ Hierarchy
Save all children, not only children in EntityStore.
@ Geometry
Store entity vector fields (vector<vec3>, vector<vec2>, vector<int>, vector<float>).
void COGSCORE_DLL_API writeEntity(Context *context, ComponentModel::Entity *entity, rapidjson::Value &object, rapidjson::Document &d, SerializationContext *sc=nullptr, const AssetWriteFlags flags=AssetWriteFlags::None)
Serialize entity adding entity to the given parent 'object'.
Contains geometry calculations and generation.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Handle to a Component instance.
void apply() override
Run the command.
void apply() override
Run the command.
void apply() override
Run the command.
void apply() override
Run the command.
Base class for Cogs Editor commands.
ComponentModel::Entity * getSelected() const
Gets entity Pointer to the single selected entity. Nullptr if not one selected or not found.
void setSelection(const EntityIds &ids)
Set new selected entities.
void apply() override
Run the command.
void apply() override
Run the command.
void apply() override
Run the command.
bool mergeWith(const EditorCommand *command) override
bool mergeWith(const EditorCommand *command) override
void apply() override
Run the command.
void apply() override
Run the command.
bool mergeWith(const EditorCommand *command) override
void apply() override
Run the command.