Refactor scene, environment, entity, and child entity saving for clear and faster execution

This commit is contained in:
Arnau Alier Torres 2025-04-21 12:36:29 +02:00
parent d1a99961b1
commit fddb88a9b2
37 changed files with 2071 additions and 1857 deletions

View File

@ -4,12 +4,16 @@
#define GLM_ENABLE_EXPERIMENTAL
#include <stdint.h>
#include <array>
#include <string>
#include <vector>
#include "Deer/Log.h"
#include "glm/glm.hpp"
#include "glm/gtc/quaternion.hpp"
#define ENTITY_MAX_CHILDREN 64
namespace Deer {
class ComponentScriptInstance;
@ -33,12 +37,44 @@ namespace Deer {
};
struct RelationshipComponent {
uint32_t parent_UID = 0;
std::vector<uint32_t> children;
uint16_t parent_id = 0;
uint16_t childCount = 0;
// Note: Since the root(id : 0) can't be a children, we will use 0 as
// null or empty
std::array<uint16_t, ENTITY_MAX_CHILDREN> childrens{};
inline uint16_t getChildrenId(size_t i) {
DEER_CORE_ASSERT(i >= 0 && i < childCount && childrens[i] != 0,
"Invalid child request {0}", i);
return childrens[i];
}
inline bool addChildrenId(uint16_t childId) {
if (childCount >= ENTITY_MAX_CHILDREN) return false;
childrens[childCount] = childId;
childCount++;
return true;
}
inline void removeChildren(uint16_t childId) {
uint16_t childPosition = 0;
for (int i = 0; i < childCount; i++) {
if (childrens[i] == childId) {
childPosition = i;
break;
}
}
// Move all childs one position
for (int i = childPosition + 1; i < childCount; i++) {
childrens[i - 1] = childrens[i];
}
childrens[childCount - 1] = 0;
childCount--;
}
RelationshipComponent() = default;
RelationshipComponent(const RelationshipComponent&) = default;
RelationshipComponent(uint32_t parent) : parent_UID(parent) {}
RelationshipComponent(uint16_t _parent) : parent_id(_parent) {}
};
struct TransformComponent {

View File

@ -1,11 +1,13 @@
#pragma once
#include <algorithm>
#include <array>
#include <string>
#include <unordered_map>
#include <vector>
#include "Deer/Components.h"
#include "Deer/Log.h"
#include "Deer/Memory.h"
#include "entt/entt.hpp"
#ifdef DEER_RENDER
@ -13,54 +15,88 @@
#include "DeerRender/SceneCamera.h"
#endif
#define ENVIRONMENT_MAX_ENTITIES 2048
namespace Deer {
class Entity;
using EntityMap = std::unordered_map<uint32_t, Entity>;
class Environment {
///////// NOTES ///////////
// - The entity id means the position in a array defined in Environment
// - The entity id is relative to a Environment so it can be a complete
// diferent entity in other environments
// - The entity number 0 is allways the root
// - There is a limit defined by ENVIRONMENT_MAX_ENTITIES of how many
// entities can be in an Environment
///////// NOTES ///////////
public:
Environment();
~Environment();
// This class can not be copyed
Environment(const Environment&) = delete;
Environment& operator=(Environment&) = delete;
// Clears all entities
void clear();
#ifdef DEER_RENDER
void render(SceneCamera& camera);
#endif
// Obtains the entity
Entity& getEntity(uint16_t id) const;
bool entityExists(uint16_t id) const;
uint16_t getEntityCount() const { return m_entityCount; }
Entity& getEntity(uint32_t id);
Entity& createEntity(const std::string& name = std::string());
// Creates a entity child at root
Entity& createEntity(const std::string& name = "");
Entity& createEntityWithId(uint16_t id, const std::string& name = "");
void destroyEntity(uint16_t id);
// Special behaviour
Entity createEmptyEntity();
// FEO
uint32_t tryGetMainCamera();
uint16_t tryGetMainCamera();
void setMainCamera(Entity& entity);
Entity& getRoot();
public:
// Obtains the entity that is on the root of the environment
inline Entity& getRoot() { return getEntity(0); }
#ifdef DEER_RENDER
void render(SceneCamera& camera);
#endif
entt::registry m_registry;
EntityMap m_entities;
uint32_t m_rootEntity = 0;
uint32_t m_mainCamera = 0;
private:
uint32_t m_idCreationOffset = 0;
inline uint32_t pullEntityID() {
uint16_t m_mainCamera = 0;
// To avoid inecessary loop we set this variable that means that smaller
// id's than this numbers are not null, empty or used
uint16_t m_idCreationOffset = 0;
// Since we don't initialize Entity in the big array for performance we
// want to keep track the ones we initialized defined by this value, it
// the id is greater it means that any information that it has can't be
// seen as valid
uint16_t m_maxIdValue = 0;
// Number of entities that exists inside
uint16_t m_entityCount = 0;
// This is where we save the entities, in a const list defined by
// ENVIRONMENT_MAX_ENTITIES, we have to make sure this system is as fast
// as possible
Scope<std::array<Entity, ENVIRONMENT_MAX_ENTITIES>> entities;
inline uint16_t pullEntityID() {
m_idCreationOffset++;
if (m_idCreationOffset > m_maxIdValue)
m_maxIdValue = m_idCreationOffset;
return m_idCreationOffset;
}
friend class Entity;
};
// Warning: This calss does not initialize for performance
class Entity {
public:
// This class can not be copied
Entity(const Entity&) = delete;
Entity() {}
static Entity nullEntity;
template <typename T, typename... Args>
T& addComponent(Args&&... args) const {
DEER_CORE_ASSERT(
@ -97,45 +133,33 @@ namespace Deer {
Entity& duplicate();
void destroy();
Entity& getParent();
inline uint32_t getParentUID() { return m_parentUID; }
uint16_t getId() const { return m_entityID; }
Entity& getParent() const;
inline uint16_t getParentId() const { return m_parentID; }
// TODO, enable transfer entitys from difrent enviroments
void setParent(Entity& parent);
bool isDescendant(Entity& parent);
uint32_t getParentUID() const { return m_parentUID; }
uint32_t getUID() const { return m_entityUID; }
bool isDescendantOf(Entity& parent) const;
Environment* getEnvironment() const { return m_environment; }
std::vector<uint32_t>& getChildren();
bool isRoot() { return m_isRoot; }
bool isRoot() const { return m_entityID == 0; }
glm::mat4 getWorldMatrix();
glm::mat4 getRelativeMatrix();
void updateInternalVars();
inline bool isValid() const {
return m_entityUID != 0 && m_environment != nullptr &&
m_environment->m_registry.valid(m_entityHandle);
}
inline bool operator==(const Entity& b) const {
return m_environment == b.m_environment &&
m_entityUID == b.m_entityUID;
}
inline bool isValid() const { return m_exists; }
private:
Entity(entt::entity handle, Environment* scene);
bool removeChild(Entity& child);
entt::entity m_entityHandle = entt::null;
Environment* m_environment = nullptr;
uint32_t m_entityUID = 0;
uint32_t m_parentUID = 0;
bool m_isRoot = false;
entt::entity m_entityHandle = entt::null;
uint16_t m_entityID = 0;
uint16_t m_parentID = 0;
bool m_exists = false;
Entity(entt::entity handle, Environment* scene, uint16_t entityID);
friend class Environment;
friend class std::unordered_map<uint32_t, Entity>;
};
} // namespace Deer

View File

@ -46,6 +46,7 @@ namespace Deer {
#define DEER_CORE_ASSERT(condition, ...) \
if (!(condition)) { \
Deer::Log::getCoreLogger()->error(__VA_ARGS__); \
__builtin_trap(); \
}
#define DEER_SCRIPT_ASSERT(condition, ...) \
if (!(condition)) { \

View File

@ -18,6 +18,9 @@ namespace Deer {
class Scene {
public:
Scene();
~Scene();
Scene(const Scene&) = delete;
Scene operator=(Scene&) = delete;
void createVoxelWorld(const VoxelWorldProps&);
void deleteVoxelWorld();
@ -28,13 +31,16 @@ namespace Deer {
void endExecution();
public:
inline Ref<Environment>& getMainEnviroment() { return m_enviroment; }
inline Ref<VoxelWorld>& getVoxelWorld() { return m_voxelWorld; }
inline Environment& getMainEnviroment() { return *m_enviroment; }
inline VoxelWorld& getVoxelWorld() { return *m_voxelWorld; }
inline bool isVoxelWorldInitialized() {
return m_voxelWorld != nullptr;
}
inline bool getExecutingState() { return m_isExecuting; }
private:
Ref<Environment> m_enviroment;
Ref<VoxelWorld> m_voxelWorld;
Scope<Environment> m_enviroment;
Scope<VoxelWorld> m_voxelWorld;
bool m_isExecuting = false;
#ifdef DEER_RENDER
@ -49,13 +55,10 @@ namespace Deer {
};
namespace SceneDataStore {
Scene loadScene(const Path& name);
void loadScene(Scene& scene, const Path& name);
void exportScene(const Scene& scene, const Path& name);
void deleteSceneJson(const Path& name);
void exportSceneJson(Scene& scene, const Path& name);
void exportScenesBin();
void exportRuntimeScene(Scene& scene);
Scene importRuntimeScene();
void exportRuntimeScene(const Scene& scene);
void importRuntimeScene(Scene& scene);
} // namespace SceneDataStore
} // namespace Deer

View File

@ -148,6 +148,7 @@ namespace Deer {
// Warning: Do not change the voxel data content since that could make
// undefined behaviour
VoxelWorld(const VoxelWorldProps &props);
~VoxelWorld();
// This class can not be copyed
// TODO: Make a function to duplicate a voxel World
VoxelWorld(const VoxelWorld &) = delete;

View File

@ -1,108 +1,90 @@
#include "Deer/Enviroment.h"
#include "Deer/Components.h"
#include "Deer/Enviroment.h"
namespace Deer {
Entity Entity::nullEntity = Entity();
Entity::Entity(entt::entity handle, Environment* scene)
: m_entityHandle(handle), m_environment(scene) {
}
bool Entity::removeChild(Entity& child) {
DEER_CORE_ASSERT(child.m_environment == m_environment, "Can not remove childrens from diferent enviroments");
std::vector<uint32_t>& children = getChildren();
auto it = std::find(children.begin(), children.end(), child.m_entityUID);
if (it != children.end())
{
children.erase(it);
return true;
}
return false;
}
Entity::Entity(entt::entity handle, Environment* scene, uint16_t entityID)
: m_entityHandle(handle),
m_environment(scene),
m_entityID(entityID),
m_exists(true) {}
void Entity::setParent(Entity& parent) {
DEER_CORE_ASSERT(parent.m_environment == m_environment , "Can not set parent from diferent enviroments");
DEER_CORE_ASSERT(!isRoot(), "Can not set parent to root");
DEER_CORE_ASSERT(isValid(), "Entity is not valid");
DEER_CORE_ASSERT(parent.m_environment == m_environment,
"Can not set parent from diferent enviroments");
DEER_CORE_ASSERT(parent.isValid(), "Parent is not valid");
if (parent.getId() == getId()) return;
if (m_parentUID == parent.m_entityUID)
Entity& current_parent = getParent();
if (parent.isDescendantOf(*this)) {
return;
if (m_parentUID != 0){
Entity& current_parent = getParent();
if (parent.isDescendant(*this)) {
return;
}
current_parent.removeChild(*this);
}
m_parentUID = parent.m_entityUID;
getComponent<RelationshipComponent>().parent_UID = parent.m_entityUID;
parent.getChildren().push_back(m_entityUID);
if (!parent.getComponent<RelationshipComponent>().addChildrenId(
getId())) {
DEER_CORE_ERROR(
"Max child count!!!, could not set parent {0} to entity {1}",
parent.getComponent<TagComponent>().tag.c_str(),
getComponent<TagComponent>().tag.c_str());
return;
}
m_parentID = parent.getId();
current_parent.getComponent<RelationshipComponent>().removeChildren(
getId());
getComponent<RelationshipComponent>().parent_id = parent.getId();
}
bool Entity::isDescendant(Entity& parent) {
if (m_entityUID == parent.m_entityUID)
return true;
if (isRoot())
return false;
bool Entity::isDescendantOf(Entity& parent) const {
DEER_CORE_ASSERT(isValid(), "Entity is not valid");
if (getId() == parent.getId()) return true;
if (isRoot()) return false;
return getParent().isDescendant(parent);
return getParent().isDescendantOf(parent);
}
Entity& Entity::duplicate() {
Entity& creation = m_environment->createEntity(getComponent<TagComponent>().tag + "(d)");
DEER_CORE_ASSERT(isValid(), "Entity is not valid");
Entity& creation = m_environment->createEntity(
getComponent<TagComponent>().tag + "(d)");
creation.getComponent<TransformComponent>() = getComponent<TransformComponent>();
Entity& parent = m_environment->getEntity(m_parentUID);
creation.setParent(parent);
creation.setParent(getParent());
creation.getComponent<TransformComponent>() =
getComponent<TransformComponent>();
#ifdef DEER_RENDER
if (m_environment->m_registry.any_of<MeshRenderComponent>(m_entityHandle))
creation.addComponent<MeshRenderComponent>(getComponent<MeshRenderComponent>());
if (m_environment->m_registry.any_of<MeshRenderComponent>(
m_entityHandle))
creation.addComponent<MeshRenderComponent>(
getComponent<MeshRenderComponent>());
if (m_environment->m_registry.any_of<CameraComponent>(m_entityHandle))
creation.addComponent<CameraComponent>(getComponent<CameraComponent>());
creation.addComponent<CameraComponent>(
getComponent<CameraComponent>());
if (m_environment->m_registry.any_of<TextureBindingComponent>(m_entityHandle))
creation.addComponent<TextureBindingComponent>(getComponent<TextureBindingComponent>());
if (m_environment->m_registry.any_of<TextureBindingComponent>(
m_entityHandle))
creation.addComponent<TextureBindingComponent>(
getComponent<TextureBindingComponent>());
#endif
return creation;
}
void Entity::destroy() {
DEER_CORE_ASSERT(isValid(), "Entity is not valid");
DEER_CORE_ASSERT(!isRoot(), "Can not destroy the root");
getParent().removeChild(*this);
if (m_environment->tryGetMainCamera() == m_entityUID)
m_environment->setMainCamera(nullEntity);
for (auto entt : getChildren()) {
m_environment->getEntity(entt).destroy();
}
m_environment->m_registry.destroy(m_entityHandle);
m_entityHandle = entt::null;
m_environment = nullptr;
m_entityUID = 0;
m_environment->destroyEntity(getId());
}
Entity& Entity::getParent() {
return m_environment->getEntity(m_parentUID);
}
std::vector<uint32_t>& Entity::getChildren() {
return getComponent<RelationshipComponent>().children;
Entity& Entity::getParent() const {
DEER_CORE_ASSERT(isValid(), "Entity is not valid");
return m_environment->getEntity(m_parentID);
}
glm::mat4 Entity::getWorldMatrix() {
if (isRoot())
return glm::mat4(1.0f);
if (isRoot()) return glm::mat4(1.0f);
return getParent().getWorldMatrix() * getRelativeMatrix();
}
@ -110,18 +92,4 @@ namespace Deer {
glm::mat4 Entity::getRelativeMatrix() {
return getComponent<TransformComponent>().getMatrix();
}
void Entity::updateInternalVars() {
TagComponent& tag = getComponent<TagComponent>();
RelationshipComponent& relation = getComponent<RelationshipComponent>();
m_entityUID = tag.entityUID;
m_parentUID = relation.parent_UID;
m_isRoot = relation.parent_UID == 0;
if (m_isRoot)
m_environment->m_rootEntity = tag.entityUID;
m_environment->m_entities[tag.entityUID] = *this;
}
}
} // namespace Deer

View File

@ -1,88 +1,134 @@
#include "Deer/Enviroment.h"
#include "Deer/Application.h"
#include "Deer/Asset.h"
#include "Deer/Components.h"
#include "Deer/Log.h"
#include "DeerRender/Render/Render.h"
#include "DeerRender/Render/RenderUtils.h"
#include "DeerRender/Render/Texture.h"
#include "Deer/Log.h"
namespace Deer {
Environment::Environment() {
entities = MakeScope<std::array<Entity, ENVIRONMENT_MAX_ENTITIES>>();
clear();
}
Environment::~Environment() { }
Environment::~Environment() {}
void Environment::clear() {
// Clear all existing entities and map
m_registry.clear();
m_entities.clear();
m_rootEntity = 0;
m_mainCamera = 0;
m_idCreationOffset = 0;
m_maxIdValue = 0;
// We set it to one because we count root
m_entityCount = 1;
m_rootEntity = pullEntityID();
entt::entity rootEntity = m_registry.create();
Entity entity = { rootEntity, this };
entity.addComponent<TagComponent>("root", m_rootEntity);
entity.addComponent<RelationshipComponent>();
entity.addComponent<TransformComponent>();
entity.m_isRoot = true;
entity.m_entityUID = m_rootEntity;
m_entities.insert({ m_rootEntity, entity });
createEntityWithId(0, "root");
}
Entity& Environment::getEntity(uint32_t id) {
DEER_CORE_ASSERT(m_entities.contains(id), "Entity id : {0} does not exist", id);
return m_entities[id];
Entity& Environment::getEntity(uint16_t id) const {
DEER_CORE_ASSERT(entityExists(id), "Entity id {0} does not exist", id);
Entity& refEntity = (*entities)[id];
return refEntity;
}
Entity& Environment::createEntity(const std::string& name)
{
uint32_t id;
bool Environment::entityExists(uint16_t id) const {
if (id < 0) return false;
if (id > m_maxIdValue) return false;
if (id >= ENVIRONMENT_MAX_ENTITIES) return false;
Entity& refEntity = (*entities)[id];
return refEntity.isValid();
}
Entity& Environment::createEntity(const std::string& name) {
uint16_t id;
do {
id = pullEntityID();
} while (m_entities.contains(id));
DEER_CORE_ASSERT(id < ENVIRONMENT_MAX_ENTITIES,
"Fatal error, max number of entities exited");
} while (entityExists(id));
entt::entity entityID = m_registry.create();
Entity entity = { entityID, this };
Entity& entity = (*entities)[id];
entity = {entityID, this, id};
entity.addComponent<TagComponent>(name, id);
entity.addComponent<RelationshipComponent>();
entity.addComponent<TransformComponent>();
entity.m_exists = true;
entity.m_entityUID = id;
entity.setParent(getRoot());
m_entities.insert({ id, entity });
return m_entities[id];
}
Entity Environment::createEmptyEntity() {
entt::entity entityID = m_registry.create();
Entity entity = { entityID, this };
m_entityCount++;
entity.m_parentID = 0;
if (!getRoot().getComponent<RelationshipComponent>().addChildrenId(
id)) {
DEER_CORE_ERROR("Root is full!");
}
return entity;
}
uint32_t Environment::tryGetMainCamera() {
return m_mainCamera;
Entity& Environment::createEntityWithId(uint16_t id,
const std::string& name) {
// We want to initialize all entities that are not initialized to a
// default state of invalid
for (int i = m_maxIdValue + 1; i < id; i++) {
Entity& nullEntity = (*entities)[i];
nullEntity.m_exists = false;
}
if (m_maxIdValue < id) m_maxIdValue = id;
Entity& entity = (*entities)[id];
entt::entity entityID = m_registry.create();
entity = {entityID, this, id};
entity.m_exists = true;
entity.addComponent<TagComponent>(name, id);
entity.addComponent<RelationshipComponent>();
entity.addComponent<TransformComponent>();
m_entityCount++;
if (id != 0) {
if (!getRoot().getComponent<RelationshipComponent>().addChildrenId(
id)) {
DEER_CORE_ERROR("Root is full!");
}
}
return entity;
}
void Environment::destroyEntity(uint16_t entityID) {
DEER_CORE_ASSERT(entityExists(entityID), "Entity id {0} does not exist",
entityID);
DEER_CORE_ASSERT(entityID == 0, "Can not destroy root");
Entity& entity = (*entities)[entityID];
entity.getParent().getComponent<RelationshipComponent>().removeChildren(
entityID);
RelationshipComponent& relationship =
entity.getComponent<RelationshipComponent>();
// We want to delete all childrens
for (int i = 0; i < relationship.childCount; i++) {
uint16_t childID = relationship.getChildrenId(i);
destroyEntity(childID);
}
if (m_mainCamera == entityID) m_mainCamera = 0;
if (entityID <= m_idCreationOffset) m_idCreationOffset = entityID - 1;
m_registry.destroy(entity.m_entityHandle);
entity.m_exists = false;
m_entityCount--;
}
uint16_t Environment::tryGetMainCamera() { return m_mainCamera; }
void Environment::setMainCamera(Entity& entity) {
if (!entity.isValid())
m_mainCamera = 0;
if (!entity.isValid()) m_mainCamera = 0;
m_mainCamera = entity.m_entityUID;
m_mainCamera = entity.getId();
}
Entity& Environment::getRoot() {
return m_entities[m_rootEntity];
}
}
} // namespace Deer

View File

@ -1,22 +1,23 @@
#include "Deer/Scene.h"
#include "Deer/Memory.h"
#include "Deer/Log.h"
#include "Deer/VoxelWorld.h"
#include "Deer/ComponentScript.h"
#include "Deer/Components.h"
#include "Deer/Enviroment.h"
#include "Deer/Log.h"
#include "Deer/Memory.h"
#include "Deer/ScriptEngine.h"
#include "Deer/VoxelWorld.h"
#include "Deer/Voxels/Chunk.h"
#include "Deer/Voxels/Layer.h"
#include "Deer/ScriptEngine.h"
#include "Deer/Components.h"
#include "Deer/ComponentScript.h"
#ifdef DEER_RENDER
#include "DeerRender/Voxels/VoxelWorldRenderData.h"
#endif
namespace Deer {
Scene::Scene() {
m_enviroment = Ref<Environment>(new Environment());
m_enviroment = MakeScope<Environment>();
m_voxelWorld = nullptr;
}
void Scene::beginExecution() {
@ -27,14 +28,17 @@ namespace Deer {
ScriptEngine::beginExecutionContext(this);
// Instantiate all the scripts
auto view = m_enviroment->m_registry.view<ScriptComponent, TagComponent>();
auto view =
m_enviroment->m_registry.view<ScriptComponent, TagComponent>();
for (auto& entID : view) {
auto& tagComponent = view.get<TagComponent>(entID);
auto& componentScript = view.get<ScriptComponent>(entID);
Entity& entity = m_enviroment->getEntity(tagComponent.entityUID);
componentScript.roeInstance = ScriptEngine::createComponentScriptInstance(componentScript.scriptID, entity);
componentScript.roeInstance =
ScriptEngine::createComponentScriptInstance(
componentScript.scriptID, entity);
componentScript.roeInstance->start();
}
}
@ -63,15 +67,13 @@ namespace Deer {
}
void Scene::createVoxelWorld(const VoxelWorldProps& props) {
m_voxelWorld = Ref<VoxelWorld>(new VoxelWorld(props));
m_voxelWorld = MakeScope<VoxelWorld>(props);
}
void Scene::deleteVoxelWorld() {
m_voxelWorld.reset();
}
void Scene::deleteVoxelWorld() { m_voxelWorld.reset(); }
void Scene::clear() {
m_enviroment->clear();
m_voxelWorld.reset();
}
}
} // namespace Deer

View File

@ -1,130 +1,74 @@
#include <sstream>
#include <string>
#include <vector>
#include "Deer/Scene.h"
#include "Deer/Scene/Serialization/Serialization.h"
#include "cereal/archives/json.hpp"
#include "cereal/archives/portable_binary.hpp"
#include "Deer/Scene/Serialization/Serialization.h"
#include <vector>
#include <string>
#include <sstream>
namespace Deer {
Scene loadSceneJson(uint8_t* data, uint32_t size);
Scene loadSceneBin(uint8_t* data, uint32_t size);
Scene SceneDataStore::loadScene(const Path& name) {
void SceneDataStore::loadScene(Scene& scene, const Path& name) {
Path realName;
realName = Path(DEER_SCENE_PATH) / (name.string() + ".dscn");
uint32_t size;
uint8_t* data = DataStore::readFile(realName, &size);
Scene scene_data;
scene_data = loadSceneJson(data, size);
delete[] data;
return scene_data;
}
Scene loadSceneJson(uint8_t* data, uint32_t size) {
std::string strData((char*)data, size);
std::istringstream stream(strData);
Scene scene;
{
cereal::JSONInputArchive archive(stream);
archive(cereal::make_nvp("scene", scene));
}
return scene;
delete[] data;
}
Scene loadSceneBin(uint8_t* data, uint32_t size) {
std::string strData((char*)data, size);
std::istringstream stream(strData);
Scene scene;
{
cereal::PortableBinaryInputArchive archive(stream);
archive(cereal::make_nvp("scene", scene));
}
return scene;
}
void SceneDataStore::deleteSceneJson(const Path& name) {
DataStore::deleteFile((Path(DEER_SCENE_PATH) / (name.generic_string() + ".dscn")));
}
void SceneDataStore::exportSceneJson(Scene& scene, const Path& name) {
is_server_serialization = false;
void SceneDataStore::exportScene(const Scene& scene, const Path& name) {
Path realName;
realName = Path(DEER_SCENE_PATH) / (name.string() + ".dscn");
std::stringstream output;
{
cereal::JSONOutputArchive archive(output);
archive(cereal::make_nvp("scene", scene));
}
Path savePath = Path(DEER_SCENE_PATH) / toLowerCasePath((name.generic_string() + ".dscn"));
std::string_view view = output.view();
DataStore::saveFile(savePath, (uint8_t*)view.data(), view.size());
DataStore::saveFile(realName, (uint8_t*)view.data(), view.size());
}
void exportSceneBin(Scene& scene, const Path& name) {
is_server_serialization = false;
void SceneDataStore::exportRuntimeScene(const Scene& scene) {
Path realName;
realName = Path(DEER_TEMP_PATH) / ("temp_scene.dbscn");
std::stringstream output;
{
cereal::PortableBinaryOutputArchive archive(output);
archive(cereal::make_nvp("scene", scene));
}
Path savePath = Path(DEER_BIN_PATH) / Path(DEER_SCENE_PATH) / toLowerCasePath((name.generic_string() + ".dbscn"));
std::string_view view = output.view();
DataStore::saveFile(savePath, (uint8_t*)view.data(), view.size());
DataStore::saveFile(realName, (uint8_t*)view.data(), view.size());
}
void SceneDataStore::exportScenesBin() {
std::vector<Path> scenes = DataStore::getFiles(DEER_SCENE_PATH, ".dscn");
for (Path& scene_path : scenes) {
uint32_t size;
uint8_t* data = DataStore::readFile(scene_path, &size);
Scene scene_data = loadSceneJson(data, size);
delete[] data;
Path name = scene_path.lexically_relative(DEER_SCENE_PATH);
name = name.root_path() / name.stem();
exportSceneBin(scene_data, name);
}
}
void SceneDataStore::exportRuntimeScene(Scene& scene) {
std::stringstream output;
{
cereal::PortableBinaryOutputArchive archive(output);
archive(cereal::make_nvp("scene", scene));
}
Path savePath = Path(DEER_TEMP_PATH) / "scene_runtime.dbscn";
std::string_view view = output.view();
DataStore::saveFile(savePath, (uint8_t*)view.data(), view.size());
}
Scene SceneDataStore::importRuntimeScene() {
Path loadPath = Path(DEER_TEMP_PATH) / "scene_runtime.dbscn";
void SceneDataStore::importRuntimeScene(Scene& scene) {
Path realName;
realName = Path(DEER_TEMP_PATH) / ("temp_scene.dbscn");
uint32_t size;
uint8_t* data = DataStore::readFile(loadPath, &size);
uint8_t* data = DataStore::readFile(realName, &size);
std::string strData((char*)data, size);
std::istringstream stream(strData);
{
cereal::PortableBinaryInputArchive archive(stream);
archive(cereal::make_nvp("scene", scene));
}
Scene scene_data = loadSceneBin(data, size);
delete[] data;
return scene_data;
}
}
} // namespace Deer

View File

@ -2,13 +2,14 @@
#include "Deer/Components.h"
namespace Deer {
// RELATIONSHIP COMPONENT
template<class Archive>
void serialize(Archive& archive,
RelationshipComponent& relationship) {
// RELATIONSHIP COMPONENT
template <class Archive>
void serialize(Archive& archive, RelationshipComponent& relationship) {
archive(cereal::make_nvp("parentId", relationship.parent_id));
archive(cereal::make_nvp("parentUID", relationship.parent_UID));
archive(cereal::make_nvp("childrensUIDs", relationship.children));
}
}
archive(cereal::make_size_tag(
static_cast<cereal::size_type>(relationship.childCount)));
for (int i = 0; i < relationship.childCount; i++)
archive(relationship.childrens[i]);
}
} // namespace Deer

View File

@ -1,83 +1,91 @@
#pragma once
#include "Deer/Components.h"
#include "Deer/Enviroment.h"
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
#include "EntitySerializationStruct.h"
namespace Deer {
template <class Archive, typename T>
void saveComponent(Archive& archive, const std::string& componentName, Entity const& m_entity) {
template <class Archive, typename T>
void saveComponent(Archive& archive, const std::string& componentName,
Entity const& m_entity) {
bool hasComponent = m_entity.hasComponent<T>();
archive(
cereal::make_nvp(("has_" + componentName).c_str(), hasComponent));
if (hasComponent) {
const T& component = m_entity.getComponent<T>();
archive(cereal::make_nvp(componentName.c_str(), component));
}
}
bool hasComponent = m_entity.hasComponent<T>();
archive(cereal::make_nvp(("has_" + componentName).c_str(), hasComponent));
if (hasComponent) {
T& component = m_entity.getComponent<T>();
archive(cereal::make_nvp(componentName.c_str(), component));
}
}
template <class Archive, typename T>
void loadComponent(Archive& archive, const std::string& componentName,
Entity const& m_entity) {
bool hasComponent;
archive(
cereal::make_nvp(("has_" + componentName).c_str(), hasComponent));
if (hasComponent) {
T& component = m_entity.addComponent<T>();
archive(cereal::make_nvp(componentName.c_str(), component));
}
}
// ENTITY
template <class Archive>
void save(Archive& archive, EntitySerializationStruct const& m_entity) {
const Entity& entity = m_entity.env->getEntity(m_entity.entityID);
template <class Archive, typename T>
void loadComponent(Archive& archive, const std::string& componentName, Entity const& m_entity) {
const TagComponent& name = entity.getComponent<TagComponent>();
archive(cereal::make_nvp("id", m_entity.entityID));
archive(cereal::make_nvp("name", name.tag));
bool hasComponent;
archive(cereal::make_nvp(("has_" + componentName).c_str(), hasComponent));
if (hasComponent) {
T& component = m_entity.addComponent<T>();
archive(cereal::make_nvp(componentName.c_str(), component));
}
}
// ENTITY
template<class Archive>
void save(Archive& archive,
Entity const& m_entity) {
const TransformComponent& transform =
entity.getComponent<TransformComponent>();
archive(cereal::make_nvp("transform", transform));
uint32_t id = m_entity.getUID();
TagComponent& name = m_entity.getComponent<TagComponent>();
archive(cereal::make_nvp("id", id));
archive(cereal::make_nvp("name", name.tag));
TransformComponent& transform = m_entity.getComponent<TransformComponent>();
archive(cereal::make_nvp("transform", transform));
RelationshipComponent& relation = m_entity.getComponent<RelationshipComponent>();
archive(cereal::make_nvp("relationship", relation));
const RelationshipComponent& relation =
entity.getComponent<RelationshipComponent>();
archive(cereal::make_nvp("relationship", relation));
#ifdef DEER_RENDER
if (!is_server_serialization) {
saveComponent<Archive, MeshRenderComponent>(archive, "meshRenderComponent", m_entity);
saveComponent<Archive, CameraComponent>(archive, "cameraComponent", m_entity);
saveComponent<Archive, TextureBindingComponent>(archive, "textureBindingComponent", m_entity);
}
if (!is_server_serialization) {
saveComponent<Archive, MeshRenderComponent>(
archive, "meshRenderComponent", entity);
saveComponent<Archive, CameraComponent>(archive, "cameraComponent",
entity);
saveComponent<Archive, TextureBindingComponent>(
archive, "textureBindingComponent", entity);
}
#endif
saveComponent<Archive, ScriptComponent>(archive, "scriptComponent", m_entity);
}
saveComponent<Archive, ScriptComponent>(archive, "scriptComponent",
entity);
}
template<class Archive>
void load(Archive& archive,
Entity& m_entity) {
uint32_t id;
std::string name;
archive(cereal::make_nvp("id", id));
archive(cereal::make_nvp("name", name));
m_entity.addComponent<TagComponent>() = TagComponent(name, id);
TransformComponent& transform = m_entity.addComponent<TransformComponent>();
archive(cereal::make_nvp("transform", transform));
RelationshipComponent& relationship = m_entity.addComponent<RelationshipComponent>();
archive(cereal::make_nvp("relationship", relationship));
template <class Archive>
void load(Archive& archive, EntitySerializationStruct& m_entity) {
uint16_t id;
std::string name;
archive(cereal::make_nvp("id", id));
archive(cereal::make_nvp("name", name));
Entity& entity = m_entity.env->createEntityWithId(id);
archive(cereal::make_nvp("transform",
entity.getComponent<TransformComponent>()));
RelationshipComponent& rc =
entity.getComponent<RelationshipComponent>();
archive(cereal::make_nvp("relationship", rc));
entity.setParent(m_entity.env->getEntity(rc.parent_id));
#ifdef DEER_RENDER
if (!is_server_serialization) {
loadComponent<Archive, MeshRenderComponent>(archive, "meshRenderComponent", m_entity);
loadComponent<Archive, CameraComponent>(archive, "cameraComponent", m_entity);
loadComponent<Archive, TextureBindingComponent>(archive, "textureBindingComponent", m_entity);
}
if (!is_server_serialization) {
loadComponent<Archive, MeshRenderComponent>(
archive, "meshRenderComponent", entity);
loadComponent<Archive, CameraComponent>(archive, "cameraComponent",
entity);
loadComponent<Archive, TextureBindingComponent>(
archive, "textureBindingComponent", entity);
}
#endif
loadComponent<Archive, ScriptComponent>(archive, "scriptComponent", m_entity);
loadComponent<Archive, ScriptComponent>(archive, "scriptComponent",
entity);
}
m_entity.updateInternalVars();
}
}
} // namespace Deer

View File

@ -0,0 +1,10 @@
#pragma once
#include <cstdint>
namespace Deer {
class Environment;
struct EntitySerializationStruct {
uint16_t entityID;
Environment* env;
};
} // namespace Deer

View File

@ -1,76 +1,57 @@
#pragma once
#include "Deer/Enviroment.h"
#include <cstdint>
#include <vector>
#include "Deer/Enviroment.h"
#include "EntitySerializationStruct.h"
namespace Deer {
struct EntityVector_Environment {
std::vector<Entity> entities;
const Ref<Environment>& environment;
EntityVector_Environment(const Ref<Environment>& _environment)
: environment(_environment) { }
};
struct EnvironmentEntity {
Environment& environment;
EnvironmentEntity(Environment& env) : environment(env) {}
};
template<class Archive>
void save(Archive& archive,
Ref<Environment> const& m_environment) {
EntityVector_Environment entityMap(m_environment);
auto view = m_environment->m_registry.view<TagComponent>();
template <class Archive>
void save(Archive& archive, const Deer::Environment& environment) {
EnvironmentEntity envEnt(const_cast<Deer::Environment&>(environment));
archive(cereal::make_nvp("entities", envEnt));
}
for (auto entity : view) {
TagComponent& tag = view.get<TagComponent>(entity);
entityMap.entities.push_back(m_environment->getEntity(tag.entityUID));
}
template <class Archive>
void load(Archive& archive, Deer::Environment& environment) {
EnvironmentEntity envEnt(environment);
archive(cereal::make_nvp("entities", envEnt));
}
// Sort to avoid conflicts
std::sort(entityMap.entities.begin(), entityMap.entities.end(), [](Entity& a, Entity& b) {
return a.getUID() < b.getUID();
});
template <class Archive>
void save(Archive& archive, EnvironmentEntity const& m_entities) {
archive(cereal::make_size_tag(static_cast<cereal::size_type>(
m_entities.environment.getEntityCount())));
uint32_t mainCameraUID = m_environment->tryGetMainCamera();
for (uint16_t i = 0; i < m_entities.environment.getEntityCount(); i++) {
while (!m_entities.environment.entityExists(i)) {
i++;
}
archive(cereal::make_nvp("entities", entityMap));
archive(cereal::make_nvp("mainCameraUID", mainCameraUID));
EntitySerializationStruct serializationStruct;
serializationStruct.env =
const_cast<Environment*>(&m_entities.environment);
serializationStruct.entityID = i;
}
archive(serializationStruct);
}
}
template<class Archive>
void load(Archive& archive,
Ref<Environment>& m_environment) {
EntityVector_Environment entityMap(m_environment);
template <class Archive>
void load(Archive& archive, EnvironmentEntity& m_entities) {
cereal::size_type size;
archive(cereal::make_size_tag(size));
uint32_t mainCameraUID;
for (int i = 0; i < size; i++) {
EntitySerializationStruct serializationStruct;
serializationStruct.env = &m_entities.environment;
archive(cereal::make_nvp("entities", entityMap));
archive(cereal::make_nvp("mainCameraUID", mainCameraUID));
if (mainCameraUID != 0)
m_environment->setMainCamera(m_environment->getEntity(mainCameraUID));
}
// ENVIRONMENT
template<class Archive>
void save(Archive& archive,
EntityVector_Environment const& m_entityVector) {
archive(cereal::make_size_tag(static_cast<cereal::size_type>(m_entityVector.entities.size()))); // number of elements
for (auto&& v : m_entityVector.entities)
archive(v);
}
template<class Archive>
void load(Archive& archive,
EntityVector_Environment& m_entityVector) {
cereal::size_type size;
archive(cereal::make_size_tag(size));
m_entityVector.entities.resize(static_cast<std::size_t>(size));
for (auto& v : m_entityVector.entities) {
v = m_entityVector.environment->createEmptyEntity();
archive(v);
}
}
}
archive(serializationStruct);
}
}
} // namespace Deer

View File

@ -1,12 +1,10 @@
#pragma once
#include "Deer/Scene.h"
namespace Deer {
template<class Archive>
void serialize(Archive& archive,
Scene& m_scene) {
archive(cereal::make_nvp("main_environment", m_scene.getMainEnviroment()));
}
}
template <class Archive>
void serialize(Archive& archive, Scene& m_scene) {
archive(
cereal::make_nvp("main_environment", m_scene.getMainEnviroment()));
}
} // namespace Deer

View File

@ -1,28 +1,26 @@
#pragma once
#include "Deer/Asset.h"
#include "cereal/cereal.hpp"
#include "cereal/types/vector.hpp"
#include "cereal/types/string.hpp"
#include "cereal/types/vector.hpp"
// Serialization Vars
#include "Deer/Scene/Serialization/SerializationGlobalVars.h"
// GENERICS
#include "Deer/Scene/Serialization/Vec3Serialization.h"
#include "Deer/Scene/Serialization/QuatSerialization.h"
#include "Deer/Scene/Serialization/Vec3Serialization.h"
// SCENE SPECIFIC
#include "Deer/Scene/Serialization/SceneSerialization.h"
#include "Deer/Scene/Serialization/EnvironmentSerialization.h"
#include "Deer/Scene/Serialization/EntitySerialization.h"
#include "Deer/Scene/Serialization/EnvironmentSerialization.h"
#include "Deer/Scene/Serialization/SceneSerialization.h"
// COMPONENTS SPECIFIC
#include "Deer/Scene/Serialization/Components/TransformComponentSerialization.h"
#include "Deer/Scene/Serialization/Components/RelationshipComponentSerialization.h"
#include "Deer/Scene/Serialization/Components/ScriptComponentSerialization.h"
#include "Deer/Scene/Serialization/Components/TransformComponentSerialization.h"
// RENDER SPECIFIC
#ifdef DEER_RENDER

View File

@ -1,20 +1,17 @@
#include "Deer/ScriptEngine.h"
#include "Deer/Log.h"
#include "Deer/Enviroment.h"
#include "angelscript.h"
#include "scriptbuilder.h"
#include "scriptstdstring.h"
#include "scriptmath.h"
#include "ScriptEngineFunctions.h"
#include "Deer/ComponentScript.h"
#include "Deer/Scene.h"
#include <filesystem>
#include "Deer/ComponentScript.h"
#include "Deer/Enviroment.h"
#include "Deer/Log.h"
#include "Deer/Scene.h"
#include "ScriptEngineFunctions.h"
#include "angelscript.h"
#include "scriptbuilder.h"
#include "scriptmath.h"
#include "scriptstdstring.h"
namespace fs = std::filesystem;
namespace Deer {
@ -22,30 +19,28 @@ namespace Deer {
asIScriptEngine* m_scriptEngine;
asIScriptModule* m_scriptModule;
Scene* m_scene;
bool m_isCompilationValid = false;
asIScriptContext* m_context;
ComponentScriptMap m_componentScripts;
void loadModuleFolder(const std::filesystem::path& modulePath, const char* moduleName);
void registerBaseComponents();
}
void ScriptEngine::shutdownScriptEngine() {
m_componentScripts.clear();
}
void loadModuleFolder(const std::filesystem::path& modulePath,
const char* moduleName);
void registerBaseComponents();
} // namespace ScriptEngine
void ScriptEngine::shutdownScriptEngine() { m_componentScripts.clear(); }
void ScriptEngine::beginExecutionContext(Scene* executingScene) {
m_scene = executingScene;
m_context = m_scriptEngine->CreateContext();
}
void ScriptEngine::endExecutionContext() {
m_context->Release();
}
void ScriptEngine::endExecutionContext() { m_context->Release(); }
void ScriptEngine::compileScriptEngine(const std::filesystem::path& modulePath) {
void ScriptEngine::compileScriptEngine(
const std::filesystem::path& modulePath) {
m_scriptEngine = asCreateScriptEngine();
m_isCompilationValid = true;
@ -53,7 +48,8 @@ namespace Deer {
loadModuleFolder(modulePath, "Deer");
m_scriptModule = m_scriptEngine->GetModule("Deer");
asITypeInfo* m_deerScript = m_scriptModule->GetTypeInfoByName("ComponentScript");
asITypeInfo* m_deerScript =
m_scriptModule->GetTypeInfoByName("ComponentScript");
int classCount = m_scriptModule->GetObjectTypeCount();
for (int i = 0; i < classCount; i++) {
@ -64,12 +60,13 @@ namespace Deer {
if (parent == m_deerScript) {
ComponentScript componentScript(type);
m_componentScripts.insert({ scriptID, componentScript });
m_componentScripts.insert({scriptID, componentScript});
}
}
}
Ref<ComponentScriptInstance> ScriptEngine::createComponentScriptInstance(const std::string& scriptID, Entity& scriptEntity) {
Ref<ComponentScriptInstance> ScriptEngine::createComponentScriptInstance(
const std::string& scriptID, Entity& scriptEntity) {
ComponentScript& script = getComponentScript(scriptID);
asITypeInfo* type = script.getTypeInfo();
@ -78,34 +75,43 @@ namespace Deer {
std::string factoryString(script.getName());
factoryString = factoryString + " @" + script.getName() + "()";
asIScriptFunction* function = type->GetFactoryByDecl(factoryString.c_str());
asIScriptFunction* function =
type->GetFactoryByDecl(factoryString.c_str());
if (!function) {
DEER_SCRIPT_ERROR("Function constructor not found for class {0}", script.getName());
DEER_SCRIPT_ERROR("Function constructor not found for class {0}",
script.getName());
return nullptr;
}
int r = m_context->Prepare(function);
if (r < 0) {
DEER_SCRIPT_ERROR("Failed to prepare constructor context for class {0}", script.getName());
DEER_SCRIPT_ERROR(
"Failed to prepare constructor context for class {0}",
script.getName());
return nullptr;
}
r = m_context->Execute();
if (r < 0) {
DEER_SCRIPT_ERROR("Failed to execute constructor for class {0}", script.getName());
DEER_SCRIPT_ERROR("Failed to execute constructor for class {0}",
script.getName());
return nullptr;
}
asIScriptObject* obj = *(asIScriptObject**)m_context->GetAddressOfReturnValue();
asIScriptObject* obj =
*(asIScriptObject**)m_context->GetAddressOfReturnValue();
obj->AddRef();
int entityPosition = script.getAttribute("entity").internalID;
unsigned int* entityValue = (unsigned int*)obj->GetAddressOfProperty(entityPosition);
unsigned int* entityValue =
(unsigned int*)obj->GetAddressOfProperty(entityPosition);
*entityValue = scriptEntity.getUID();
asIScriptFunction* updateFunction = type->GetMethodByDecl("void update()");
asIScriptFunction* startFunction = type->GetMethodByDecl("void start()");
*entityValue = scriptEntity.getId();
asIScriptFunction* updateFunction =
type->GetMethodByDecl("void update()");
asIScriptFunction* startFunction =
type->GetMethodByDecl("void start()");
instance->m_updateFunction = updateFunction;
instance->m_startFuction = startFunction;
instance->m_object = obj;
@ -113,30 +119,41 @@ namespace Deer {
return Ref<ComponentScriptInstance>(instance);
}
void ScriptEngine::loadModuleFolder(const std::filesystem::path& modulePath, const char* moduleName) {
void ScriptEngine::loadModuleFolder(const std::filesystem::path& modulePath,
const char* moduleName) {
CScriptBuilder builder;
int r = builder.StartNewModule(m_scriptEngine, moduleName);
DEER_SCRIPT_ASSERT(r >= 0, "Unrecoverable error while starting a new module. {0}", moduleName);
DEER_SCRIPT_ASSERT(
r >= 0, "Unrecoverable error while starting a new module. {0}",
moduleName);
try {
DEER_CORE_INFO("=== Loading Scripts ===");
for (const auto& entry : fs::recursive_directory_iterator(modulePath)) {
if (fs::is_regular_file(entry) && entry.path().extension() == ".as") {
for (const auto& entry :
fs::recursive_directory_iterator(modulePath)) {
if (fs::is_regular_file(entry) &&
entry.path().extension() == ".as") {
r = builder.AddSectionFromFile(
entry.path().generic_string().c_str());
DEER_SCRIPT_ASSERT(r >= 0,
"Please correct the errors in the "
"script and try again. {0}",
entry.path().generic_string().c_str());
r = builder.AddSectionFromFile(entry.path().generic_string().c_str());
DEER_SCRIPT_ASSERT(r >= 0, "Please correct the errors in the script and try again. {0}", entry.path().generic_string().c_str());
DEER_CORE_TRACE(" {0}", entry.path().filename().string().c_str());
DEER_CORE_TRACE(" {0}",
entry.path().filename().string().c_str());
}
}
} catch (const fs::filesystem_error& e) {
DEER_CORE_ERROR("Error while loading scripts, error: {0}", e.what());
DEER_CORE_ERROR("Error while loading scripts, error: {0}",
e.what());
}
r = builder.BuildModule();
if (r < 0) {
DEER_SCRIPT_INFO("Please correct the errors in the script and try again.");
DEER_SCRIPT_INFO(
"Please correct the errors in the script and try again.");
m_isCompilationValid = false;
}
}
@ -154,4 +171,4 @@ namespace Deer {
registerInputFunctions(m_scriptEngine);
registerEntityTransformFunctions(m_scriptEngine);
}
}
} // namespace Deer

View File

@ -1,201 +1,249 @@
#include "ScriptEngineFunctions.h"
#include "Deer/Scene.h"
#include "Deer/Enviroment.h"
#include "Deer/ScriptEngine.h"
#include "angelscript.h"
#include "Deer/Log.h"
#include "Deer/Scene.h"
#include "Deer/ScriptEngine.h"
#include "DeerRender/Input.h"
#include "angelscript.h"
#include "glm/glm.hpp"
namespace Deer {
void messageCallback(const asSMessageInfo* msg, void* param) {
if (msg->type == asMSGTYPE_WARNING) {
DEER_SCRIPT_WARN("({0} {1}) : {2} {3}", msg->row, msg->col, msg->message, msg->section);
}
else if (msg->type == asMSGTYPE_ERROR) {
DEER_SCRIPT_ERROR("({0} {1}) : {2} {3}", msg->row, msg->col, msg->message, msg->section);
}
else if (msg->type == asMSGTYPE_INFORMATION) {
DEER_SCRIPT_INFO("({0} {1}) : {2} {3}", msg->row, msg->col, msg->message, msg->section);
}
else {
DEER_SCRIPT_WARN("({0} {1}) : {2} {3}", msg->row, msg->col, msg->message, msg->section);
}
}
void messageCallback(const asSMessageInfo* msg, void* param) {
if (msg->type == asMSGTYPE_WARNING) {
DEER_SCRIPT_WARN("({0} {1}) : {2} {3}", msg->row, msg->col,
msg->message, msg->section);
} else if (msg->type == asMSGTYPE_ERROR) {
DEER_SCRIPT_ERROR("({0} {1}) : {2} {3}", msg->row, msg->col,
msg->message, msg->section);
} else if (msg->type == asMSGTYPE_INFORMATION) {
DEER_SCRIPT_INFO("({0} {1}) : {2} {3}", msg->row, msg->col,
msg->message, msg->section);
} else {
DEER_SCRIPT_WARN("({0} {1}) : {2} {3}", msg->row, msg->col,
msg->message, msg->section);
}
}
void print(std::string& msg) {
DEER_SCRIPT_INFO(msg.c_str());
}
void print(std::string& msg) { DEER_SCRIPT_INFO(msg.c_str()); }
glm::vec3 getEntityPosition(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return glm::vec3();
}
glm::vec3 getEntityPosition(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return glm::vec3();
}
Ref<Environment>& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment->getEntity(entityUID);
Environment& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment.getEntity(entityUID);
return entt.getComponent<TransformComponent>().position;
}
return entt.getComponent<TransformComponent>().position;
}
void setEntityPosition(glm::vec3 position, uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return;
}
void setEntityPosition(glm::vec3 position, uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return;
}
Ref<Environment>& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment->getEntity(entityUID);
Environment& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment.getEntity(entityUID);
entt.getComponent<TransformComponent>().position = position;
}
entt.getComponent<TransformComponent>().position = position;
}
glm::vec3 getEntityScale(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return glm::vec3();
}
glm::vec3 getEntityScale(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return glm::vec3();
}
Ref<Environment>& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment->getEntity(entityUID);
Environment& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment.getEntity(entityUID);
return entt.getComponent<TransformComponent>().scale;
}
return entt.getComponent<TransformComponent>().scale;
}
void setEntityScale(glm::vec3 scale, uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return;
}
void setEntityScale(glm::vec3 scale, uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return;
}
Ref<Environment>& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment->getEntity(entityUID);
Environment& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment.getEntity(entityUID);
entt.getComponent<TransformComponent>().scale = scale;
}
entt.getComponent<TransformComponent>().scale = scale;
}
uint32_t getEntityParent(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return 0;
}
uint32_t getEntityParent(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return 0;
}
Ref<Environment>& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment->getEntity(entityUID);
Environment& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment.getEntity(entityUID);
return entt.getParentUID();
}
return entt.getParentId();
}
bool isEntityValid(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1)
return false;
bool isEntityValid(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) return false;
Ref<Environment>& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment->getEntity(entityUID);
Environment& m_environment = ScriptEngine::m_scene->getMainEnviroment();
Entity& entt = m_environment.getEntity(entityUID);
return entt.isValid();
}
return entt.isValid();
}
void registerVec3(asIScriptEngine* engine) {
engine->RegisterObjectType("Vec3", sizeof(glm::vec3), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<glm::vec3>() | asOBJ_APP_CLASS_ALLFLOATS);
void registerVec3(asIScriptEngine* engine) {
engine->RegisterObjectType("Vec3", sizeof(glm::vec3),
asOBJ_VALUE | asOBJ_POD |
asGetTypeTraits<glm::vec3>() |
asOBJ_APP_CLASS_ALLFLOATS);
engine->RegisterObjectBehaviour("Vec3", asBEHAVE_CONSTRUCT, "void f()", asFUNCTIONPR([](void* memory) {
new (memory) glm::vec3();
}, (void*), void), asCALL_CDECL_OBJLAST);
engine->RegisterObjectBehaviour("Vec3", asBEHAVE_CONSTRUCT, "void f(float, float = 0, float = 0)", asFUNCTIONPR([](float x, float y, float z, void* memory) {
new (memory) glm::vec3(x, y, z);
}, (float, float, float, void*), void), asCALL_CDECL_OBJLAST);
engine->RegisterObjectProperty("Vec3", "float x", asOFFSET(glm::vec3, x));
engine->RegisterObjectProperty("Vec3", "float y", asOFFSET(glm::vec3, y));
engine->RegisterObjectProperty("Vec3", "float z", asOFFSET(glm::vec3, z));
engine->RegisterObjectBehaviour(
"Vec3", asBEHAVE_CONSTRUCT, "void f()",
asFUNCTIONPR([](void* memory) { new (memory) glm::vec3(); },
(void*), void),
asCALL_CDECL_OBJLAST);
engine->RegisterObjectBehaviour(
"Vec3", asBEHAVE_CONSTRUCT, "void f(float, float = 0, float = 0)",
asFUNCTIONPR([](float x, float y, float z,
void* memory) { new (memory) glm::vec3(x, y, z); },
(float, float, float, void*), void),
asCALL_CDECL_OBJLAST);
engine->RegisterObjectProperty("Vec3", "float x",
asOFFSET(glm::vec3, x));
engine->RegisterObjectProperty("Vec3", "float y",
asOFFSET(glm::vec3, y));
engine->RegisterObjectProperty("Vec3", "float z",
asOFFSET(glm::vec3, z));
engine->RegisterObjectMethod("Vec3", "Vec3 opAdd(const Vec3 &in) const",
asFUNCTIONPR([](const glm::vec3& a, const glm::vec3& b) -> glm::vec3 {
return a + b;
}, (const glm::vec3&, const glm::vec3&), glm::vec3), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opAdd(const Vec3 &in) const",
asFUNCTIONPR([](const glm::vec3& a,
const glm::vec3& b) -> glm::vec3 { return a + b; },
(const glm::vec3&, const glm::vec3&), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "Vec3 opSub(const Vec3 &in) const",
asFUNCTIONPR([](const glm::vec3& a, const glm::vec3& b) {
return a - b;
}, (const glm::vec3&, const glm::vec3&), glm::vec3), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opSub(const Vec3 &in) const",
asFUNCTIONPR(
[](const glm::vec3& a, const glm::vec3& b) { return a - b; },
(const glm::vec3&, const glm::vec3&), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "Vec3 opMul(float) const",
asFUNCTIONPR([](const glm::vec3& a, float scalar) {
return a * scalar;
}, (const glm::vec3&, float), glm::vec3), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opMul(float) const",
asFUNCTIONPR(
[](const glm::vec3& a, float scalar) { return a * scalar; },
(const glm::vec3&, float), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "Vec3 opDiv(float) const",
asFUNCTIONPR([](const glm::vec3& a, float scalar) {
return a / scalar;
}, (const glm::vec3&, float), glm::vec3), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opDiv(float) const",
asFUNCTIONPR(
[](const glm::vec3& a, float scalar) { return a / scalar; },
(const glm::vec3&, float), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "Vec3 normalize() const",
asFUNCTIONPR(glm::normalize, (const glm::vec3&), glm::vec3), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 normalize() const",
asFUNCTIONPR(glm::normalize, (const glm::vec3&), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "float getMagnitude() const",
asFUNCTIONPR(glm::length, (const glm::vec3&), float), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "float getMagnitude() const",
asFUNCTIONPR(glm::length, (const glm::vec3&), float),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "Vec3 opNeg() const",
asFUNCTIONPR([](const glm::vec3& a) {
return -a;
}, (const glm::vec3&), glm::vec3), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opNeg() const",
asFUNCTIONPR([](const glm::vec3& a) { return -a; },
(const glm::vec3&), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "bool opEquals(const Vec3 &in) const",
asFUNCTIONPR([](const glm::vec3& a, const glm::vec3& b) {
return a == b;
}, (const glm::vec3&, const glm::vec3&), bool), asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "bool opEquals(const Vec3 &in) const",
asFUNCTIONPR(
[](const glm::vec3& a, const glm::vec3& b) { return a == b; },
(const glm::vec3&, const glm::vec3&), bool),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "string opImplConv() const",
asFUNCTIONPR([](const glm::vec3& a) {
// Example string conversion using glm (you may need to format it)
char buffer[64];
snprintf(buffer, sizeof(buffer), "(%.2f, %.2f, %.2f)", a.x, a.y, a.z);
return std::string(buffer);
}, (const glm::vec3&), std::string), asCALL_CDECL_OBJFIRST);
}
engine->RegisterObjectMethod("Vec3", "string opImplConv() const",
asFUNCTIONPR(
[](const glm::vec3& a) {
// Example string conversion using
// glm (you may need to format it)
char buffer[64];
snprintf(buffer, sizeof(buffer),
"(%.2f, %.2f, %.2f)", a.x,
a.y, a.z);
return std::string(buffer);
},
(const glm::vec3&), std::string),
asCALL_CDECL_OBJFIRST);
}
void registerEntity(asIScriptEngine* engine) {
engine->RegisterObjectType("Entity", sizeof(unsigned int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
engine->RegisterObjectProperty("Entity", "uint uint32_t", 0);
void registerEntity(asIScriptEngine* engine) {
engine->RegisterObjectType(
"Entity", sizeof(unsigned int),
asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
engine->RegisterObjectProperty("Entity", "uint uint32_t", 0);
engine->RegisterObjectMethod("Entity", "Entity getParent()", asFUNCTION(Deer::getEntityParent), asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod("Entity", "bool isValid()", asFUNCTION(Deer::isEntityValid), asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod("Entity", "Entity getParent()",
asFUNCTION(Deer::getEntityParent),
asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod("Entity", "bool isValid()",
asFUNCTION(Deer::isEntityValid),
asCALL_CDECL_OBJLAST);
engine->RegisterGlobalFunction("Entity getEntity(uint)", asFUNCTIONPR([](uint32_t id) {
return id;
}, (uint32_t), uint32_t), asCALL_CDECL);
engine->RegisterGlobalFunction(
"Entity getEntity(uint)",
asFUNCTIONPR([](uint32_t id) { return id; }, (uint32_t), uint32_t),
asCALL_CDECL);
}
}
void registerDeerFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->SetMessageCallback(
asFUNCTION(Deer::messageCallback), 0, asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up angel script");
void registerDeerFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->SetMessageCallback(asFUNCTION(Deer::messageCallback), 0, asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up angel script");
r = scriptEngine->RegisterGlobalFunction("void print(const string &in)",
asFUNCTION(Deer::print),
asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0,
"Error in seting up void print(const string &in)");
}
r = scriptEngine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(Deer::print), asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up void print(const string &in)");
}
void registerInputFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->RegisterGlobalFunction(
"bool isKeyPressed(int)", asFUNCTION(Deer::Input::isKeyPressed),
asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up bool isKeyPressed(int)");
}
void registerInputFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->RegisterGlobalFunction("bool isKeyPressed(int)", asFUNCTION(Deer::Input::isKeyPressed), asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up bool isKeyPressed(int)");
}
void registerEntityTransformFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->RegisterObjectMethod(
"Entity", "Vec3 getPosition()", asFUNCTION(Deer::getEntityPosition),
asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up Vec3 getPosition()");
void registerEntityTransformFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->RegisterObjectMethod("Entity", "Vec3 getPosition()", asFUNCTION(Deer::getEntityPosition), asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up Vec3 getPosition()");
scriptEngine->RegisterObjectMethod("Entity", "void setPosition(Vec3)", asFUNCTION(Deer::setEntityPosition), asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up void setPosition(Vec3)");
r = scriptEngine->RegisterObjectMethod("Entity", "Vec3 getScale()", asFUNCTION(Deer::getEntityScale), asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up Vec3 getScale()");
scriptEngine->RegisterObjectMethod("Entity", "void setPosition(Vec3)",
asFUNCTION(Deer::setEntityPosition),
asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up void setPosition(Vec3)");
scriptEngine->RegisterObjectMethod("Entity", "void setScale(Vec3)", asFUNCTION(Deer::setEntityScale), asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up void setScale(Vec3)");
}
r = scriptEngine->RegisterObjectMethod("Entity", "Vec3 getScale()",
asFUNCTION(Deer::getEntityScale),
asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up Vec3 getScale()");
}
scriptEngine->RegisterObjectMethod("Entity", "void setScale(Vec3)",
asFUNCTION(Deer::setEntityScale),
asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up void setScale(Vec3)");
}
} // namespace Deer

View File

@ -1,4 +1,5 @@
#include "Deer/VoxelWorld.h"
#include "Deer/Log.h"
#include "Deer/Voxels/Chunk.h"
#include "Deer/Voxels/Layer.h"
@ -8,19 +9,22 @@
#endif
#include <math.h>
#include <cmath>
#include <vector>
namespace Deer {
VoxelWorld::VoxelWorld(const VoxelWorldProps& props)
: m_worldProps(props) {
VoxelWorld::VoxelWorld(const VoxelWorldProps& props) : m_worldProps(props) {
m_chunks = MakeScope<Chunk[]>(m_worldProps.getChunkCount());
m_layers = MakeScope<Layer[]>(m_worldProps.getLayerCount());
#ifdef DEER_RENDER
m_renderData = MakeScope<VoxelWorldRenderData>(m_worldProps.getChunkCount());
m_renderData =
MakeScope<VoxelWorldRenderData>(m_worldProps.getChunkCount());
#endif
}
VoxelWorld::~VoxelWorld() {}
uint16_t VoxelWorld::calculateLayerVoxelHeight(int x, int z) {
LayerVoxelID layerVoxelID;
LayerID layerID;
@ -32,7 +36,8 @@ namespace Deer {
chunkID.y = y;
Chunk& chunk = m_chunks[m_worldProps.getWorldChunkID(chunkID)];
uint8_t chunkVoxelHeight = chunk.calculateLayerVoxelHeight(layerVoxelID);
uint8_t chunkVoxelHeight =
chunk.calculateLayerVoxelHeight(layerVoxelID);
if (chunkVoxelHeight != 0) {
return chunkVoxelHeight + chunkID.y * CHUNK_SIZE_Y;
@ -40,4 +45,4 @@ namespace Deer {
}
return 0;
}
}
} // namespace Deer

View File

@ -1,20 +1,22 @@
#include "Deer/Scene.h"
#include "Deer/Enviroment.h"
#include "Deer/Components.h"
#include "Deer/Enviroment.h"
#include "Deer/VoxelWorld.h"
#include "DeerRender/Render/RenderCommand.h"
#include "Deer/Enviroment.h"
namespace Deer {
Scene::~Scene() {}
void Scene::render() {
uint32_t mainCamera = m_enviroment->tryGetMainCamera();
if (mainCamera == 0)
return;
if (mainCamera == 0) return;
Entity& m_cameraEntity = m_enviroment->getEntity(mainCamera);
SceneCamera sceneCamera;
sceneCamera.camera = m_cameraEntity.getComponent<CameraComponent>();
sceneCamera.transform = m_cameraEntity.getComponent<TransformComponent>();
sceneCamera.transform =
m_cameraEntity.getComponent<TransformComponent>();
Scene::render(sceneCamera);
}
@ -22,10 +24,9 @@ namespace Deer {
void Scene::render(SceneCamera sceneCamera) {
RenderCommand::setDepthBuffer(true);
m_enviroment->render(sceneCamera);
if (m_voxelWorld)
m_voxelWorld->render(sceneCamera);
if (m_voxelWorld) m_voxelWorld->render(sceneCamera);
RenderCommand::setDepthBuffer(false);
m_gizmoRenderer.render(sceneCamera);
}
}
} // namespace Deer

View File

@ -1,13 +1,12 @@
#pragma once
#include <queue>
#include <unordered_set>
#include <vector>
#include "Deer/Memory.h"
#include "Deer/Voxel.h"
#include "DeerRender/Render/VertexArray.h"
#include <queue>
#include <vector>
#include <unordered_set>
namespace Deer {
struct ChunkRender {
Ref<VertexArray> solidVoxel;
@ -36,30 +35,31 @@ namespace Deer {
};
class ChunkUpdateQueue {
public:
public:
// TODO: Add priority
void addChunk(ChunkID);
ChunkID pullChunk();
bool hasChunk();
private:
private:
std::queue<ChunkID> m_updateOrder;
std::unordered_set<ChunkID, ChunkIDHash> m_containingChunks;
};
struct VoxelWorldRenderData {
VoxelWorldRenderData(size_t chunkCount) {
chunksRender = MakeScope<ChunkRender[]>(chunkCount);
}
// Chunk render data
Scope<ChunkRender[]> chunksRender;
ChunkUpdateQueue chunkQueue;
// Voxel creation data
std::vector<uint32_t> indices;
std::vector<SolidVoxelVertexData> vertexData;
std::queue<VoxelCordinates> ambientLightPropagation;
std::queue<VoxelCordinates> voxelLightPropagation;
std::vector<VoxelCordinates> tmp_voxelLightSource;
};
}
struct VoxelWorldRenderData {
VoxelWorldRenderData(size_t chunkCount) {
chunksRender = MakeScope<ChunkRender[]>(chunkCount);
}
// Chunk render data
Scope<ChunkRender[]> chunksRender;
ChunkUpdateQueue chunkQueue;
// Voxel creation data
std::vector<uint32_t> indices;
std::vector<SolidVoxelVertexData> vertexData;
std::queue<VoxelCordinates> ambientLightPropagation;
std::queue<VoxelCordinates> voxelLightPropagation;
std::vector<VoxelCordinates> tmp_voxelLightSource;
};
} // namespace Deer

View File

@ -2,19 +2,19 @@
// v 1.61 WIP
//
// The MIT License(MIT)
//
//
// Copyright(c) 2016 Cedric Guillemet
//
//
// 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 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
@ -26,22 +26,25 @@
// -------------------------------------------------------------------------------------------
// History :
// 2019/11/03 View gizmo
// 2016/09/11 Behind camera culling. Scaling Delta matrix not multiplied by source matrix scales. local/world rotation and translation fixed. Display message is incorrect (X: ... Y:...) in local mode.
// 2016/09/09 Hatched negative axis. Snapping. Documentation update.
// 2016/09/04 Axis switch and translation plan autohiding. Scale transform stability improved
// 2016/09/01 Mogwai changed to Manipulate. Draw debug cube. Fixed inverted scale. Mixing scale and translation/rotation gives bad results.
// 2016/08/31 First version
// 2016/09/11 Behind camera culling. Scaling Delta matrix not multiplied by
// source matrix scales. local/world rotation and translation fixed. Display
// message is incorrect (X: ... Y:...) in local mode. 2016/09/09 Hatched
// negative axis. Snapping. Documentation update. 2016/09/04 Axis switch and
// translation plan autohiding. Scale transform stability improved 2016/09/01
// Mogwai changed to Manipulate. Draw debug cube. Fixed inverted scale. Mixing
// scale and translation/rotation gives bad results. 2016/08/31 First version
//
// -------------------------------------------------------------------------------------------
// Future (no order):
//
// - Multi view
// - display rotation/translation/scale infos in local/world space and not only local
// - display rotation/translation/scale infos in local/world space and not only
// local
// - finish local/world matrix application
// - OPERATION as bitmask
//
//
// -------------------------------------------------------------------------------------------
// Example
// Example
#if 0
void EditTransform(const Camera& camera, matrix_t& matrix)
{
@ -111,16 +114,17 @@ void EditTransform(const Camera& camera, matrix_t& matrix)
#define IMGUI_API
#endif
namespace ImGuizmo
{
// call inside your own window and before Manipulate() in order to draw gizmo to that window.
// Or pass a specific ImDrawList to draw to (e.g. ImGui::GetForegroundDrawList()).
IMGUI_API void SetDrawlist(ImDrawList* drawlist = nullptr);
namespace ImGuizmo {
// call inside your own window and before Manipulate() in order to draw
// gizmo to that window. Or pass a specific ImDrawList to draw to (e.g.
// ImGui::GetForegroundDrawList()).
IMGUI_API void SetDrawlist(ImDrawList *drawlist = nullptr);
// call BeginFrame right after ImGui_XXXX_NewFrame();
IMGUI_API void BeginFrame();
// return true if mouse cursor is over any gizmo control (axis, plan or screen component)
// return true if mouse cursor is over any gizmo control (axis, plan or
// screen component)
IMGUI_API bool IsOver();
// return true if mouse IsOver or if the gizmo is in moving state
@ -130,58 +134,71 @@ namespace ImGuizmo
// gizmo is rendered with gray half transparent color when disabled
IMGUI_API void Enable(bool enable);
// helper functions for manualy editing translation/rotation/scale with an input float
// translation, rotation and scale float points to 3 floats each
// helper functions for manualy editing translation/rotation/scale with an
// input float translation, rotation and scale float points to 3 floats each
// Angles are in degrees (more suitable for human editing)
// example:
// float matrixTranslation[3], matrixRotation[3], matrixScale[3];
// ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale);
// ImGui::InputFloat3("Tr", matrixTranslation, 3);
// ImGui::InputFloat3("Rt", matrixRotation, 3);
// ImGui::InputFloat3("Sc", matrixScale, 3);
// ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);
// ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation,
// matrixRotation, matrixScale); ImGui::InputFloat3("Tr", matrixTranslation,
// 3); ImGui::InputFloat3("Rt", matrixRotation, 3); ImGui::InputFloat3("Sc",
// matrixScale, 3);
// ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation,
// matrixRotation, matrixScale, gizmoMatrix.m16);
//
// These functions have some numerical stability issues for now. Use with caution.
IMGUI_API void DecomposeMatrixToComponents(const float *matrix, float *translation, float *rotation, float *scale);
IMGUI_API void RecomposeMatrixFromComponents(const float *translation, const float *rotation, const float *scale, float *matrix);
// These functions have some numerical stability issues for now. Use with
// caution.
IMGUI_API void DecomposeMatrixToComponents(const float *matrix,
float *translation,
float *rotation, float *scale);
IMGUI_API void RecomposeMatrixFromComponents(const float *translation,
const float *rotation,
const float *scale,
float *matrix);
IMGUI_API void SetRect(float x, float y, float width, float height);
// default is false
IMGUI_API void SetOrthographic(bool isOrthographic);
// Render a cube with face color corresponding to face normal. Usefull for debug/tests
IMGUI_API void DrawCubes(const float *view, const float *projection, const float *matrices, int matrixCount);
IMGUI_API void DrawGrid(const float *view, const float *projection, const float *matrix, const float gridSize);
// Render a cube with face color corresponding to face normal. Usefull for
// debug/tests
IMGUI_API void DrawCubes(const float *view, const float *projection,
const float *matrices, int matrixCount);
IMGUI_API void DrawGrid(const float *view, const float *projection,
const float *matrix, const float gridSize);
// call it when you want a gizmo
// Needs view and projection matrices.
// matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional
// Needs view and projection matrices.
// matrix parameter is the source matrix (where will be gizmo be drawn) and
// might be transformed by the function. Return deltaMatrix is optional
// translation is applied in world space
enum OPERATION
{
enum OPERATION {
TRANSLATE,
ROTATE,
SCALE,
BOUNDS,
};
enum MODE
{
LOCAL,
WORLD
};
enum MODE { LOCAL, WORLD };
IMGUI_API bool Manipulate(const float *view, const float *projection, OPERATION operation, MODE mode, float *matrix, float *deltaMatrix = NULL, float *snap = NULL, float *localBounds = NULL, float *boundsSnap = NULL);
//
// Please note that this cubeview is patented by Autodesk : https://patents.google.com/patent/US7782319B2/en
// It seems to be a defensive patent in the US. I don't think it will bring troubles using it as
// other software are using the same mechanics. But just in case, you are now warned!
//
IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);
IMGUI_API void SetID(int id);
// return true if the cursor is over the operation's gizmo
IMGUI_API bool IsOver(OPERATION op);
IMGUI_API bool Manipulate(const float *view, const float *projection,
OPERATION operation, MODE mode, float *matrix,
float *deltaMatrix = NULL, float *snap = NULL,
float *localBounds = NULL,
float *boundsSnap = NULL);
//
// Please note that this cubeview is patented by Autodesk :
// https://patents.google.com/patent/US7782319B2/en It seems to be a
// defensive patent in the US. I don't think it will bring troubles using it
// as other software are using the same mechanics. But just in case, you are
// now warned!
//
IMGUI_API void ViewManipulate(float *view, float length, ImVec2 position,
ImVec2 size, ImU32 backgroundColor);
IMGUI_API void SetID(int id);
// return true if the cursor is over the operation's gizmo
IMGUI_API bool IsOver(OPERATION op);
IMGUI_API void SetGizmoSizeClipSpace(float value);
};
}; // namespace ImGuizmo

View File

@ -1,246 +1,241 @@
#include "DeerStudio.h"
#include "Deer/Voxel.h"
#include "Deer/VoxelWorld.h"
#include <functional>
#include "Deer/DataStore.h"
#include "Deer/Scene.h"
#include "Deer/ScriptEngine.h"
#include "DeerStudio/Editor/PropertiesPannel.h"
#include "Deer/Voxel.h"
#include "Deer/VoxelWorld.h"
#include "DeerStudio/Editor/GamePannel.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Editor/PropertiesPannel.h"
#include "DeerStudio/Editor/SceneExplorer.h"
#include "DeerStudio/Editor/Terrain/TerrainEditor.h"
#include "DeerStudio/Editor/TreePannel.h"
#include "DeerStudio/Editor/Viewport.h"
#include "DeerStudio/Editor/Terrain/TerrainEditor.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Project.h"
#include "Style.h"
#include <functional>
namespace Deer {
int DeerStudioApplication::onPreInit() {
Path projectPath = Application::m_window->folderDialog(nullptr);
if (projectPath.empty())
return 1;
int DeerStudioApplication::onPreInit() {
Path projectPath = Application::m_window->folderDialog(nullptr);
if (projectPath.empty()) return 1;
DataStore::rootPath = projectPath;
VoxelData::createExampleVoxelData();
VoxelData::createExampleVoxelAspect();
VoxelData::loadVoxelsData();
VoxelData::loadVoxelsAspect();
return 0;
}
DataStore::rootPath = projectPath;
VoxelData::createExampleVoxelData();
VoxelData::createExampleVoxelAspect();
VoxelData::loadVoxelsData();
VoxelData::loadVoxelsAspect();
return 0;
}
int DeerStudioApplication::onInit() {
VoxelData::generateTextureAtlas();
VoxelData::loadVoxelsShaders();
ScriptEngine::compileScriptEngine(DataStore::rootPath / std::filesystem::path("scripts"));
int DeerStudioApplication::onInit() {
VoxelData::generateTextureAtlas();
VoxelData::loadVoxelsShaders();
ScriptEngine::compileScriptEngine(DataStore::rootPath /
std::filesystem::path("scripts"));
Icons::setupIcons();
Icons::setupIcons();
// IMGUI STYLE
ImGuiIO& io = ImGui::GetIO();
io.Fonts->Clear();
std::string fLoc = (DataStore::rootPath / "imgui.ini").generic_string();
char* filenameFLoc = new char[fLoc.size() + 1]();
strcpy(filenameFLoc, fLoc.c_str());
io.IniFilename = filenameFLoc;
ImFontConfig cnfg;
//cnfg.SizePixels = 26
Path rfPath = DataStore::rootPath / "editor/fonts/Roboto-Regular.ttf";
io.Fonts->AddFontFromFileTTF(rfPath.generic_string().c_str(), 18);
//io.Fonts->AddFontDefault(&cnfg);
setNatureStyle();
// IMGUI STYLE
ImGuiIO& io = ImGui::GetIO();
io.Fonts->Clear();
auto m_gamePannel = Ref<GamePannel>(new GamePannel());
std::string fLoc = (DataStore::rootPath / "imgui.ini").generic_string();
char* filenameFLoc = new char[fLoc.size() + 1]();
strcpy(filenameFLoc, fLoc.c_str());
io.IniFilename = filenameFLoc;
ImFontConfig cnfg;
// cnfg.SizePixels = 26
Path rfPath = DataStore::rootPath / "editor/fonts/Roboto-Regular.ttf";
io.Fonts->AddFontFromFileTTF(rfPath.generic_string().c_str(), 18);
// io.Fonts->AddFontDefault(&cnfg);
pannels.push_back(m_gamePannel);
setNatureStyle();
return 0;
}
auto m_gamePannel = Ref<GamePannel>(new GamePannel());
void DeerStudioApplication::onShutdown() {
if (Project::m_scene.getExecutingState())
Project::m_scene.endExecution();
pannels.push_back(m_gamePannel);
ScriptEngine::shutdownScriptEngine();
pannels.clear();
}
return 0;
}
void DeerStudioApplication::onRender(Timestep delta) {
for (auto pannel : pannels) {
pannel->onRender(delta);
}
void DeerStudioApplication::onShutdown() {
if (Project::m_scene.getExecutingState())
Project::m_scene.endExecution();
int windowWidth = Application::s_application->m_window->getWitdth();
int windowHeight = Application::s_application->m_window->getHeight();
}
ScriptEngine::shutdownScriptEngine();
pannels.clear();
}
void DeerStudioApplication::onUpdate(Timestep delta) {
if (Project::m_scene.getExecutingState())
Project::m_scene.updateInternalVars();
if (Project::m_scene.getVoxelWorld())
Project::m_scene.getVoxelWorld()->bakeNextChunk();
}
void DeerStudioApplication::onRender(Timestep delta) {
for (auto pannel : pannels) {
pannel->onRender(delta);
}
void DeerStudioApplication::onEvent(Event& e) {
for (auto& pannel : pannels)
pannel->onEventCallback(e);
int windowWidth = Application::s_application->m_window->getWitdth();
int windowHeight = Application::s_application->m_window->getHeight();
}
viewport_onEvent(e);
}
void DeerStudioApplication::onUpdate(Timestep delta) {
if (Project::m_scene.getExecutingState())
Project::m_scene.updateInternalVars();
if (Project::m_scene.isVoxelWorldInitialized())
Project::m_scene.getVoxelWorld().bakeNextChunk();
}
void DeerStudioApplication::onImGUI() {
static bool opt_fullscreen = true;
static bool opt_padding = false;
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
void DeerStudioApplication::onEvent(Event& e) {
for (auto& pannel : pannels) pannel->onEventCallback(e);
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
viewport_onEvent(e);
}
{
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
window_flags |= ImGuiWindowFlags_NoBackground;
}
void DeerStudioApplication::onImGUI() {
static bool opt_fullscreen = true;
static bool opt_padding = false;
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
static bool p_open = true;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::Begin("DockSpace Demo", &p_open, window_flags);
ImGui::PopStyleVar();
ImGui::PopStyleVar(2);
ImGuiWindowFlags window_flags =
ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
ImGuiID dockspace_id = ImGui::GetID("DockSpace Demo");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
{
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
window_flags |= ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus |
ImGuiWindowFlags_NoNavFocus;
window_flags |= ImGuiWindowFlags_NoBackground;
}
if (ImGui::BeginMenuBar()) {
drawMenuBar();
ImGui::EndMenuBar();
}
static bool p_open = true;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::Begin("DockSpace Demo", &p_open, window_flags);
ImGui::PopStyleVar();
ImGui::PopStyleVar(2);
for (auto pannel : pannels) {
pannel->onImGui();
}
ImGuiID dockspace_id = ImGui::GetID("DockSpace Demo");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
// ---- PANNELS -----
//sceneExplorer_onImGUI();
//treePannel_onImGui();
TerrainEditor::terrainEditor_onImGui();
viewport_onImGui();
// ---- PANNELS -----
if (ImGui::BeginMenuBar()) {
drawMenuBar();
ImGui::EndMenuBar();
}
Project::m_scene.getMainGizmoRenderer().refresh();
ImGui::End();
}
for (auto pannel : pannels) {
pannel->onImGui();
}
void DeerStudioApplication::drawMenuBar() {
if (ImGui::BeginMenu("Project")) {
if (ImGui::MenuItem("New project")) {
// TODO
}
if (ImGui::MenuItem("Open project")) {
// TODO
}
if (ImGui::MenuItem("Save project")) {
// TODO
}
if (ImGui::MenuItem("Save project as...")) {
// TODO
}
ImGui::Separator();
if (ImGui::MenuItem("Create binaries")) {
// ---- PANNELS -----
// sceneExplorer_onImGUI();
TreePannel::treePannel_onImGui();
PropertiesPannel::propertiesPannel_onImgui();
TerrainEditor::terrainEditor_onImGui();
viewport_onImGui();
// ---- PANNELS -----
}
if (ImGui::MenuItem("Export project")) {
SceneDataStore::exportScenesBin();
Project::m_scene.getMainGizmoRenderer().refresh();
ImGui::End();
}
std::vector<Path> scenes = DataStore::getFiles("scenes", ".dbscn");
DataStore::compressFiles(scenes, "bin/scene_data");
}
if (ImGui::MenuItem("Project settings")) {
// TODO
}
ImGui::EndMenu();
}
void DeerStudioApplication::drawMenuBar() {
if (ImGui::BeginMenu("Project")) {
if (ImGui::MenuItem("New project")) {
}
if (ImGui::MenuItem("Open project")) {
}
if (ImGui::MenuItem("Save project")) {
}
if (ImGui::MenuItem("Save project as...")) {
}
ImGui::Separator();
if (ImGui::MenuItem("Create binaries")) {
}
if (ImGui::MenuItem("Export project")) {
}
if (ImGui::MenuItem("Project settings")) {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Scene")) {
if (ImGui::MenuItem("New scene")) {
// TODO
Project::m_scene.clear();
SceneDataStore::exportSceneJson(Project::m_scene, "new_scene");
}
//if (Project::m_sceneSerializer->getCurrentScenePath() != "_NO_INITIALIZED_" && ImGui::MenuItem("Save scene")) {
// Project::m_sceneSerializer->serialize(Project::m_sceneSerializer->getCurrentScenePath());
//}
if (ImGui::MenuItem("Save scene")) {
SceneDataStore::exportSceneJson(Project::m_scene, "saved_scene");
}
if (ImGui::MenuItem("Save scene as...")) {
// TODO
}
if (ImGui::MenuItem("Load scene")) {
//Project::m_scene.swap(SceneDataStore::loadScene("new_scene"));
//SceneDataStore::exportSceneJson(Project::m_scene, "new_scene");
}
if (ImGui::MenuItem("Scene settings")) {
// TODO
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Scene")) {
if (ImGui::MenuItem("New scene")) {
// TODO
Project::m_scene.clear();
SceneDataStore::exportScene(Project::m_scene, "new_scene");
}
// if (Project::m_sceneSerializer->getCurrentScenePath() !=
// "_NO_INITIALIZED_" && ImGui::MenuItem("Save scene")) {
// Project::m_sceneSerializer->serialize(Project::m_sceneSerializer->getCurrentScenePath());
// }
if (ImGui::MenuItem("Save scene")) {
SceneDataStore::exportScene(Project::m_scene, "saved_scene");
}
if (ImGui::MenuItem("Save scene as...")) {
// TODO
}
if (ImGui::MenuItem("Load scene")) {
// Project::m_scene.swap(SceneDataStore::loadScene("new_scene"));
// SceneDataStore::exportScene(Project::m_scene,
// "new_scene");
}
if (ImGui::MenuItem("Scene settings")) {
// TODO
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Runtime")) {
if (ImGui::MenuItem("Start")) {
// TODO
}
if (ImGui::MenuItem("End")) {
// TODO
}
if (ImGui::MenuItem("Restart")) {
// TODO
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Runtime")) {
if (ImGui::MenuItem("Start")) {
// TODO
}
if (ImGui::MenuItem("End")) {
// TODO
}
if (ImGui::MenuItem("Restart")) {
// TODO
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Voxel")) {
if (ImGui::MenuItem("Voxel Pannel")) {
// TODO
}
if (ImGui::BeginMenu("Voxel")) {
if (ImGui::MenuItem("Voxel Pannel")) {
// TODO
}
ImGui::EndMenu();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Scripts")) {
if (ImGui::MenuItem("Reload scripts") && !Project::m_scene.getExecutingState()) {
ScriptEngine::shutdownScriptEngine();
ScriptEngine::compileScriptEngine(std::filesystem::path("scripts"));
}
if (ImGui::BeginMenu("Scripts")) {
if (ImGui::MenuItem("Reload scripts") &&
!Project::m_scene.getExecutingState()) {
ScriptEngine::shutdownScriptEngine();
ScriptEngine::compileScriptEngine(
std::filesystem::path("scripts"));
}
ImGui::EndMenu();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Help")) {
if (ImGui::MenuItem("Documentation")) {
// TODO
}
if (ImGui::MenuItem("Report bug")) {
// TODO
}
if (ImGui::MenuItem("About")) {
// TODO
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Help")) {
if (ImGui::MenuItem("Documentation")) {
// TODO
}
if (ImGui::MenuItem("Report bug")) {
// TODO
}
if (ImGui::MenuItem("About")) {
// TODO
}
ImGui::EndMenu();
}
}
}
void DeerStudioApplication::onChangeScene() {
ActiveEntity::clear();
}
}
void DeerStudioApplication::onChangeScene() { ActiveEntity::clear(); }
} // namespace Deer

View File

@ -1,91 +1,93 @@
#include "GamePannel.h"
#include "DeerStudio/Project.h"
#include "Deer/Enviroment.h"
#include "Deer/Scene.h"
#include "Deer/ScriptEngine.h"
#include "imgui.h"
#include <filesystem>
#include "Deer/Enviroment.h"
#include "Deer/Scene.h"
#include "Deer/ScriptEngine.h"
#include "DeerStudio/Project.h"
#include "imgui.h"
namespace Deer {
GamePannel::GamePannel() {
FrameBufferSpecification fbSpecs = FrameBufferSpecification(100, 100, { TextureBufferType::RGBA8 }, 1, false);
m_frameBuffer = FrameBuffer::create(fbSpecs);
}
GamePannel::GamePannel() {
FrameBufferSpecification fbSpecs = FrameBufferSpecification(
100, 100, {TextureBufferType::RGBA8}, 1, false);
m_frameBuffer = FrameBuffer::create(fbSpecs);
}
void GamePannel::onImGui() {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("Game Window");
ImGui::PopStyleVar();
void GamePannel::onImGui() {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("Game Window");
ImGui::PopStyleVar();
Ref<Environment> environment = Project::m_scene.getMainEnviroment();
uint32_t cameraUID = environment->tryGetMainCamera();
Environment& environment = Project::m_scene.getMainEnviroment();
uint32_t cameraUID = environment.tryGetMainCamera();
if (cameraUID == 0) {
ImGui::TextColored(ImVec4(.3f, .3f, .8f, 1.0f), "There is no camera");
if (cameraUID == 0) {
ImGui::TextColored(ImVec4(.3f, .3f, .8f, 1.0f),
"There is no camera");
if (!Project::m_scene.getExecutingState()) {
if (ScriptEngine::isCompilationValid() && ImGui::Button("Execute")) {
SceneDataStore::exportRuntimeScene(Project::m_scene);
Project::m_scene.beginExecution();
}
}
else {
if (ImGui::Button("Stop")) {
Project::m_scene.endExecution();
Project::m_scene = SceneDataStore::importRuntimeScene();
}
}
if (!Project::m_scene.getExecutingState()) {
if (ScriptEngine::isCompilationValid() &&
ImGui::Button("Execute")) {
SceneDataStore::exportRuntimeScene(Project::m_scene);
Project::m_scene.beginExecution();
}
} else {
if (ImGui::Button("Stop")) {
Project::m_scene.endExecution();
SceneDataStore::importRuntimeScene(Project::m_scene);
}
}
ImGui::End();
return;
}
ImGui::End();
return;
}
Entity& cameraEntity = environment->getEntity(cameraUID);
CameraComponent& cameraComponent = cameraEntity.getComponent<CameraComponent>();
Entity& cameraEntity = environment.getEntity(cameraUID);
CameraComponent& cameraComponent =
cameraEntity.getComponent<CameraComponent>();
ImVec2 contentRegionMin = ImGui::GetWindowContentRegionMin();
ImVec2 pos = ImGui::GetWindowPos();
pos.y += contentRegionMin.y;
ImVec2 contentRegionMin = ImGui::GetWindowContentRegionMin();
ImVec2 pos = ImGui::GetWindowPos();
pos.y += contentRegionMin.y;
ImVec2 windowSize = ImGui::GetContentRegionAvail();
ImVec2 cursorPos = ImGui::GetCursorPos();
ImVec2 windowSize = ImGui::GetContentRegionAvail();
ImVec2 cursorPos = ImGui::GetCursorPos();
if (m_lastWindowSize != *(glm::vec2*)&windowSize) {
m_lastWindowSize = { windowSize.x, windowSize.y };
m_frameBuffer->resize(windowSize.x, windowSize.y);
if (m_lastWindowSize != *(glm::vec2*)&windowSize) {
m_lastWindowSize = {windowSize.x, windowSize.y};
m_frameBuffer->resize(windowSize.x, windowSize.y);
cameraComponent.aspect = windowSize.x / windowSize.y;
}
cameraComponent.aspect = windowSize.x / windowSize.y;
}
m_frameBuffer->bind();
m_frameBuffer->clear();
unsigned char clearColor[4]{ 0, 0, 0, 255 };
m_frameBuffer->clearBuffer(0, &clearColor);
m_frameBuffer->bind();
m_frameBuffer->clear();
unsigned char clearColor[4]{0, 0, 0, 255};
m_frameBuffer->clearBuffer(0, &clearColor);
Project::m_scene.render();
m_frameBuffer->unbind();
Project::m_scene.render();
m_frameBuffer->unbind();
ImGui::Image((void*)(uint64_t)m_frameBuffer->getTextureBufferID(0), windowSize, ImVec2(0, 1), ImVec2(1, 0));
ImGui::Image((void*)(uint64_t)m_frameBuffer->getTextureBufferID(0),
windowSize, ImVec2(0, 1), ImVec2(1, 0));
ImGui::SetCursorPos(cursorPos);
ImGui::SetCursorPos(cursorPos);
if (!Project::m_scene.getExecutingState()) {
if (ScriptEngine::isCompilationValid() && ImGui::Button("Execute")) {
SceneDataStore::exportRuntimeScene(Project::m_scene);
Project::m_scene.beginExecution();
}
}
else {
if (ImGui::Button("Stop")) {
Project::m_scene.endExecution();
Project::m_scene = SceneDataStore::importRuntimeScene();
}
}
if (!Project::m_scene.getExecutingState()) {
if (ScriptEngine::isCompilationValid() &&
ImGui::Button("Execute")) {
SceneDataStore::exportRuntimeScene(Project::m_scene);
Project::m_scene.beginExecution();
}
} else {
if (ImGui::Button("Stop")) {
Project::m_scene.endExecution();
SceneDataStore::importRuntimeScene(Project::m_scene);
}
}
ImGui::End();
}
}
ImGui::End();
}
} // namespace Deer

View File

@ -1,22 +1,35 @@
#include "PropertiesPannel.h"
#include "DeerStudio/Project.h"
#include "DeerRender/Input.h"
#include "DeerRender/KeyCodes.h"
#include "DeerRender/Render/Texture.h"
#include "Deer/Asset.h"
#include "Deer/ScriptEngine.h"
#include "DeerRender/Input.h"
#include "DeerRender/KeyCodes.h"
#include "DeerRender/Render/Texture.h"
#include "DeerStudio/Project.h"
#include "imgui.h"
namespace Deer {
bool* getIsEditingState(ImGuiID id)
{
namespace PropertiesPannel {
void addComponentContext();
template <typename T>
bool collapsingComponentHeader(const std::string& componentName,
bool canDelete = true);
template <typename T>
void addComponentButton(const std::string& componentName);
void addScriptButton(const std::string& scriptID);
void drawMagicSlider(const std::string& text, float* value);
void drawMagicSlider3f(const std::string& text, float* value,
float defaultValue = 0);
} // namespace PropertiesPannel
bool* getIsEditingState(ImGuiID id) {
ImGuiStorage* storage = ImGui::GetStateStorage();
void* ptr = storage->GetVoidPtr(id);
if (ptr)
return (bool*)ptr;
if (ptr) return (bool*)ptr;
// If state doesn't exist, initialize it
bool* state = new bool(false);
@ -24,7 +37,7 @@ namespace Deer {
return state;
}
void PropertiesPannel::onImGui() {
void PropertiesPannel::propertiesPannel_onImgui() {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20, 20));
ImGui::Begin("Properties");
@ -49,7 +62,8 @@ namespace Deer {
addComponentContext();
ImGui::Dummy(ImVec2(0.0f, 10.0f));
if (collapsingComponentHeader<TransformComponent>("Transform Component", false)) {
if (collapsingComponentHeader<TransformComponent>("Transform Component",
false)) {
auto& transform = activeEntity.getComponent<TransformComponent>();
ImGui::Dummy(ImVec2(0.0f, 10.0f));
ImGui::Indent();
@ -58,12 +72,10 @@ namespace Deer {
glm::vec3 rotation = transform.getEulerAngles();
glm::vec3 lastRotation = rotation;
drawMagicSlider3f("Rotation", &rotation.x, 0);
if (rotation != lastRotation)
transform.setEulerAngles(rotation);
if (rotation != lastRotation) transform.setEulerAngles(rotation);
drawMagicSlider3f("Scale", &transform.scale.x, 1);
if (rotation != lastRotation)
transform.setEulerAngles(rotation);
if (rotation != lastRotation) transform.setEulerAngles(rotation);
ImGui::Unindent();
ImGui::Dummy(ImVec2(0.0f, 10.0f));
@ -90,7 +102,8 @@ namespace Deer {
ImGui::Dummy(ImVec2(0.0f, 10.0f));
}
if (collapsingComponentHeader<MeshRenderComponent>("Mesh Render Component")) {
if (collapsingComponentHeader<MeshRenderComponent>(
"Mesh Render Component")) {
ImGui::Dummy(ImVec2(0.0f, 10.0f));
ImGui::Indent();
@ -101,15 +114,19 @@ namespace Deer {
if (mesh.meshAssetID == 0)
meshName = " null ";
else
meshName = AssetManager::getAssetLocation(mesh.meshAssetID).generic_string();
meshName = AssetManager::getAssetLocation(mesh.meshAssetID)
.generic_string();
ImGui::Text("Mesh : ");
ImGui::SameLine();
ImGui::Button(meshName.c_str());
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_MESH")) {
std::string receivedData = std::string((const char*)payload->Data);
mesh.meshAssetID = AssetManager::loadAsset<Mesh>(receivedData);
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload("_MESH")) {
std::string receivedData =
std::string((const char*)payload->Data);
mesh.meshAssetID =
AssetManager::loadAsset<Mesh>(receivedData);
}
ImGui::EndDragDropTarget();
}
@ -119,15 +136,19 @@ namespace Deer {
if (mesh.shaderAssetID == 0)
shaderName = " null ";
else
shaderName = AssetManager::getAssetLocation(mesh.shaderAssetID).generic_string();
shaderName = AssetManager::getAssetLocation(mesh.shaderAssetID)
.generic_string();
ImGui::Text("Shader : ");
ImGui::SameLine();
ImGui::Button(shaderName.c_str());
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_SHADER")) {
std::string receivedData = std::string((const char*)payload->Data);
mesh.shaderAssetID = AssetManager::loadAsset<Shader>(receivedData);
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload("_SHADER")) {
std::string receivedData =
std::string((const char*)payload->Data);
mesh.shaderAssetID =
AssetManager::loadAsset<Shader>(receivedData);
}
ImGui::EndDragDropTarget();
}
@ -136,23 +157,26 @@ namespace Deer {
ImGui::Dummy(ImVec2(0.0f, 10.0f));
}
if (collapsingComponentHeader<TextureBindingComponent>("Texture Binding Component"))
{
if (collapsingComponentHeader<TextureBindingComponent>(
"Texture Binding Component")) {
ImGui::Dummy(ImVec2(0.0f, 10.0f));
ImGui::Indent();
TextureBindingComponent& textureBinding = activeEntity.getComponent<TextureBindingComponent>();
TextureBindingComponent& textureBinding =
activeEntity.getComponent<TextureBindingComponent>();
int textureBindingCount = 0;
for (int x = 0; x < MAX_TEXTURE_BINDINGS; x++) {
if (textureBinding.textureAssetID[x] == 0)
continue;
if (textureBinding.textureAssetID[x] == 0) continue;
ImGui::PushID(x);
textureBindingCount++;
std::string textureBindingName = AssetManager::getAssetLocation(textureBinding.textureAssetID[x]).generic_string();
std::string textureBindingName =
AssetManager::getAssetLocation(
textureBinding.textureAssetID[x])
.generic_string();
int currentID = textureBinding.textureBindID[x];
ImGui::Text("Texture : ");
@ -160,11 +184,14 @@ namespace Deer {
ImGui::Button(textureBindingName.c_str());
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_TEXTURE2D")) {
std::string receivedData = std::string((const char*)payload->Data);
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload("_TEXTURE2D")) {
std::string receivedData =
std::string((const char*)payload->Data);
textureBinding.textureAssetID[x]
= AssetManager::loadAsset<Texture2D>(std::filesystem::path(receivedData));
textureBinding.textureAssetID[x] =
AssetManager::loadAsset<Texture2D>(
std::filesystem::path(receivedData));
}
ImGui::EndDragDropTarget();
}
@ -173,7 +200,9 @@ namespace Deer {
ImGui::SameLine();
ImGui::InputInt("#bindingInputID", &currentID, 0);
currentID = (currentID < 0) ? 0 : (currentID > 12) ? 12 : currentID;
currentID = (currentID < 0) ? 0
: (currentID > 12) ? 12
: currentID;
textureBinding.textureBindID[x] = currentID;
if (ImGui::Button("Delete texture binding"))
@ -189,18 +218,20 @@ namespace Deer {
ImGui::Button("Add texture binding");
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_TEXTURE2D")) {
std::string receivedData = std::string((const char*)payload->Data);
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload("_TEXTURE2D")) {
std::string receivedData =
std::string((const char*)payload->Data);
for (int x = 0; x < 4; x++) {
if (textureBinding.textureAssetID[x] != 0)
continue;
if (textureBinding.textureAssetID[x] != 0) continue;
textureBinding.textureAssetID[x] = AssetManager::loadAsset<Texture2D>(std::filesystem::path(receivedData));
textureBinding.textureAssetID[x] =
AssetManager::loadAsset<Texture2D>(
std::filesystem::path(receivedData));
textureBinding.textureBindID[x] = 0;
break;
}
}
ImGui::EndDragDropTarget();
}
@ -210,15 +241,15 @@ namespace Deer {
ImGui::Dummy(ImVec2(0.0f, 10.0f));
}
if (collapsingComponentHeader<CameraComponent>("Camera Component"))
{
if (collapsingComponentHeader<CameraComponent>("Camera Component")) {
ImGui::Dummy(ImVec2(0.0f, 10.0f));
ImGui::Indent();
auto& camera = activeEntity.getComponent<CameraComponent>();
uint32_t currentMainCamera = activeEntity.getEnvironment()->tryGetMainCamera();
if (currentMainCamera == activeEntity.getUID())
uint32_t currentMainCamera =
activeEntity.getEnvironment()->tryGetMainCamera();
if (currentMainCamera == activeEntity.getId())
ImGui::Button("This is the main camera");
else if (ImGui::Button("Set main camera")) {
activeEntity.getEnvironment()->setMainCamera(activeEntity);
@ -238,13 +269,14 @@ namespace Deer {
ImGui::PopStyleVar();
}
void PropertiesPannel::drawMagicSlider(const std::string& text, float* value) {
void PropertiesPannel::drawMagicSlider(const std::string& text,
float* value) {
ImGuiID id = ImGui::GetID(text.c_str());
bool* isEditing = getIsEditingState(id);
if (*isEditing)
{
if (ImGui::InputFloat(text.c_str(), value, 0.0f, 0.0f, "%.3f", ImGuiInputTextFlags_EnterReturnsTrue))
if (*isEditing) {
if (ImGui::InputFloat(text.c_str(), value, 0.0f, 0.0f, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue))
*isEditing = false;
if (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0))
@ -254,76 +286,93 @@ namespace Deer {
}
ImGui::DragFloat(text.c_str(), value, 0.05f, 0.0f, 0.0f, "%.3f",
ImGuiSliderFlags_NoRoundToFormat);
ImGuiSliderFlags_NoRoundToFormat);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
if (ImGui::IsItemHovered() &&
ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
*isEditing = true;
}
void PropertiesPannel::drawMagicSlider3f(const std::string& text, float* value, float defaultValue) {
void PropertiesPannel::drawMagicSlider3f(const std::string& text,
float* value, float defaultValue) {
ImGui::Columns(4, 0, false);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2());
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); // Set FrameRounding to 0 for hard edges
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding,
0.0f); // Set FrameRounding to 0 for hard edges
ImGui::Text("%s", text.c_str());
ImGui::NextColumn();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.7f, 0.2f, 0.2f, 1.0f)); // Red background
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.6f, 0.2f, 0.2f, 1.0f)); // Darker red when hovered
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.4f, 0.2f, 0.2f, 1.0f)); // Even darker red when active
ImGui::PushStyleColor(
ImGuiCol_Button, ImVec4(0.7f, 0.2f, 0.2f, 1.0f)); // Red background
ImGui::PushStyleColor(
ImGuiCol_ButtonHovered,
ImVec4(0.6f, 0.2f, 0.2f, 1.0f)); // Darker red when hovered
ImGui::PushStyleColor(
ImGuiCol_ButtonActive,
ImVec4(0.4f, 0.2f, 0.2f, 1.0f)); // Even darker red when active
if (ImGui::Button((" X ##" + text).c_str()))
*value = defaultValue;
if (ImGui::Button((" X ##" + text).c_str())) *value = defaultValue;
ImGui::SameLine();
ImGui::PopStyleColor(3); // Restore original style
ImGui::PopStyleColor(3); // Restore original style
drawMagicSlider("##" + text + "_x", value);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); // Green background
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.2f, 0.6f, 0.2f, 1.0f)); // Darker green when hovered
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.2f, 0.4f, 0.2f, 1.0f)); // Even darker green when active
ImGui::PushStyleColor(
ImGuiCol_Button,
ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); // Green background
ImGui::PushStyleColor(
ImGuiCol_ButtonHovered,
ImVec4(0.2f, 0.6f, 0.2f, 1.0f)); // Darker green when hovered
ImGui::PushStyleColor(
ImGuiCol_ButtonActive,
ImVec4(0.2f, 0.4f, 0.2f, 1.0f)); // Even darker green when active
ImGui::NextColumn();
if (ImGui::Button((" Y ##" + text).c_str()))
value[1] = defaultValue;
if (ImGui::Button((" Y ##" + text).c_str())) value[1] = defaultValue;
ImGui::SameLine();
ImGui::PopStyleColor(3); // Restore original style
ImGui::PopStyleColor(3); // Restore original style
drawMagicSlider("##" + text + "_y", &value[1]);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.2f, 0.7f, 1.0f)); // Blue background
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.2f, 0.2f, 0.6f, 1.0f)); // Darker blue when hovered
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.2f, 0.2f, 0.4f, 1.0f)); // Even darker blue when active
ImGui::PushStyleColor(
ImGuiCol_Button,
ImVec4(0.2f, 0.2f, 0.7f, 1.0f)); // Blue background
ImGui::PushStyleColor(
ImGuiCol_ButtonHovered,
ImVec4(0.2f, 0.2f, 0.6f, 1.0f)); // Darker blue when hovered
ImGui::PushStyleColor(
ImGuiCol_ButtonActive,
ImVec4(0.2f, 0.2f, 0.4f, 1.0f)); // Even darker blue when active
ImGui::NextColumn();
if (ImGui::Button((" Z ##" + text).c_str()))
value[2] = defaultValue;
if (ImGui::Button((" Z ##" + text).c_str())) value[2] = defaultValue;
ImGui::SameLine();
ImGui::PopStyleColor(3); // Restore original style
ImGui::PopStyleColor(3); // Restore original style
drawMagicSlider("##" + text + "_z", &value[2]);
ImGui::Columns();
ImGui::PopStyleVar(2);
}
void PropertiesPannel::addComponentContext() {
float buttonWidth = ImGui::CalcTextSize(" + add Component ").x; // Example button width
float buttonWidth =
ImGui::CalcTextSize(" + add Component ").x; // Example button width
float windowWidth = ImGui::GetWindowSize().x;
float availableWidth = windowWidth - ImGui::GetCursorPosX();
// Place button at the right, with some padding (e.g., 10px)
ImGui::SetCursorPosX(windowWidth - buttonWidth - 20);
if (ImGui::Button(" + add Component ")) {//, ImVec2(ImGui::GetWindowContentRegionWidth(), 40)
if (ImGui::Button(
" + add Component ")) { //,
// ImVec2(ImGui::GetWindowContentRegionWidth(),
// 40)
// Opens a popup window when the button is clicked
ImGui::OpenPopup("Add Component Popup");
}
@ -331,15 +380,13 @@ namespace Deer {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10));
ImGui::SetNextWindowSize(ImVec2(240, 200));
// Create the popup window
if (ImGui::BeginPopup("Add Component Popup"))
{
if (ImGui::BeginPopup("Add Component Popup")) {
addComponentButton<MeshRenderComponent>("Mesh Render Component");
addComponentButton<TextureBindingComponent>("Texture Binding Component");
addComponentButton<TextureBindingComponent>(
"Texture Binding Component");
addComponentButton<CameraComponent>("Camera Component");
if (ImGui::BeginMenu("Scripts")) {
for (auto& script : ScriptEngine::getComponentScripts())
addScriptButton(script.first.c_str());
@ -351,14 +398,16 @@ namespace Deer {
ImGui::PopStyleVar();
}
template<typename T>
inline bool PropertiesPannel::collapsingComponentHeader(const std::string& componentName, bool canDelete)
{
if (!ActiveEntity::shareComponent<T>())
return false;
template <typename T>
inline bool PropertiesPannel::collapsingComponentHeader(
const std::string& componentName, bool canDelete) {
if (!ActiveEntity::shareComponent<T>()) return false;
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_OpenOnArrow;
bool collapsingHeader = ActiveEntity::shareComponent<T>() && ImGui::TreeNodeEx(componentName.c_str(), flags);
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_CollapsingHeader |
ImGuiTreeNodeFlags_DefaultOpen |
ImGuiTreeNodeFlags_OpenOnArrow;
bool collapsingHeader = ActiveEntity::shareComponent<T>() &&
ImGui::TreeNodeEx(componentName.c_str(), flags);
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup(componentName.c_str());
@ -366,7 +415,6 @@ namespace Deer {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10));
if (ImGui::BeginPopup(componentName.c_str())) {
if (ImGui::Selectable("reset")) {
for (auto& entity : ActiveEntity::entities)
entity->getComponent<T>() = T();
@ -393,9 +441,11 @@ namespace Deer {
}
void PropertiesPannel::addScriptButton(const std::string& scriptID) {
ImGuiSelectableFlags selectableFlag = (ActiveEntity::shareComponent<ScriptComponent>()) ? ImGuiSelectableFlags_Disabled : ImGuiSelectableFlags_None;
ImGuiSelectableFlags selectableFlag =
(ActiveEntity::shareComponent<ScriptComponent>())
? ImGuiSelectableFlags_Disabled
: ImGuiSelectableFlags_None;
if (ImGui::Selectable(scriptID.c_str(), false, selectableFlag)) {
for (auto& entity : ActiveEntity::entities) {
if (!entity->hasComponent<ScriptComponent>())
entity->addComponent<ScriptComponent>(scriptID);
@ -405,19 +455,18 @@ namespace Deer {
}
}
template<typename T>
void PropertiesPannel::addComponentButton(const std::string& componentName)
{
ImGuiSelectableFlags selectableFlag = (ActiveEntity::shareComponent<T>()) ? ImGuiSelectableFlags_Disabled : ImGuiSelectableFlags_None;
template <typename T>
void PropertiesPannel::addComponentButton(
const std::string& componentName) {
ImGuiSelectableFlags selectableFlag =
(ActiveEntity::shareComponent<T>()) ? ImGuiSelectableFlags_Disabled
: ImGuiSelectableFlags_None;
if (ImGui::Selectable(componentName.c_str(), false, selectableFlag)) {
for (auto& entity : ActiveEntity::entities) {
if (!entity->hasComponent<T>())
entity->addComponent<T>();
if (!entity->hasComponent<T>()) entity->addComponent<T>();
}
ImGui::CloseCurrentPopup();
}
}
}
} // namespace Deer

View File

@ -1,31 +1,10 @@
#pragma once
#include "DeerStudio/Editor/EditorPannel.h"
#include "DeerStudio/Editor/ActiveEntity.h"
#include "Deer/Memory.h"
#include "DeerStudio/Editor/ActiveEntity.h"
#include "DeerStudio/Editor/EditorPannel.h"
namespace Deer {
class PropertiesPannel : public EditorPannel {
public:
PropertiesPannel() { }
void onImGui() override;
private:
void addComponentContext();
private:
template<typename T>
bool collapsingComponentHeader(const std::string& componentName, bool canDelete = true);
template<typename T>
void addComponentButton(const std::string& componentName);
void addScriptButton(const std::string& scriptID);
void drawMagicSlider(const std::string& text, float* value);
void drawMagicSlider3f(const std::string& text, float* value, float defaultValue = 0);
};
}
namespace PropertiesPannel {
void propertiesPannel_onImgui();
} // namespace PropertiesPannel
} // namespace Deer

View File

@ -1,279 +1,296 @@
#include "SceneExplorer.h"
#include "DeerStudio/Project.h"
#include "DeerStudio/Editor/ActiveEntity.h"
#include "Deer/Path.h"
#include "Deer/DataStore.h"
#include "Deer/Scene.h"
#include "Deer/Log.h"
#include "DeerRender/Render/Texture.h"
#include "Icons.h"
#include "EditorUtils.h"
#include "imgui.h"
#include <regex>
#include <string>
#include "Deer/DataStore.h"
#include "Deer/Log.h"
#include "Deer/Path.h"
#include "Deer/Scene.h"
#include "DeerRender/Render/Texture.h"
#include "DeerStudio/Editor/ActiveEntity.h"
#include "DeerStudio/Project.h"
#include "EditorUtils.h"
#include "Icons.h"
#include "imgui.h"
namespace Deer {
Path m_currentScenePath("null");
Path m_currentSceneName;
Path m_loadSceneName;
Path m_deleteSceneName;
Path m_dialogSceneName;
Path m_currentScenePath("null");
Path m_currentSceneName;
Path m_loadSceneName;
Path m_deleteSceneName;
Path m_dialogSceneName;
void drawSceneExplorerFolder(const Path& path);
void drawSceneExplorerScene(const Path& path);
void saveSceneBeforeLoadingPopup();
void sceneDialogPopup();
void drawSceneExplorerFolder(const Path& path);
void drawSceneExplorerScene(const Path& path);
void saveSceneBeforeLoadingPopup();
void sceneDialogPopup();
void saveSceneName(const std::string&);
void createFolderName(const std::string& name);
void saveBeforeCreatingNew(bool save);
void saveSceneNameBeforeCreatingNew(const std::string& name);
void deleteScene();
void saveSceneName(const std::string&);
void createFolderName(const std::string& name);
void saveBeforeCreatingNew(bool save);
void saveSceneNameBeforeCreatingNew(const std::string& name);
void deleteScene();
void openFileExplorer(const std::string& relativePath);
void openFileExplorer(const std::string& relativePath);
void sceneExplorer_onImGUI() {
if (m_currentScenePath == "null")
m_currentScenePath = DataStore::rootPath / DEER_SCENE_PATH;
if (m_currentScenePath == "null")
m_currentScenePath = DataStore::rootPath / DEER_SCENE_PATH;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20, 10));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20, 10));
ImGui::Begin("Scene Explorer", (bool*)0, ImGuiWindowFlags_MenuBar);
ImGui::PopStyleVar();
ImGui::PopStyleVar();
if (ImGui::BeginMenuBar()) {
if (ImGui::MenuItem("Save")) {
if (m_currentSceneName == "")
ImGui::OpenPopup("SAVE_SCENE_NAME");
else
SceneDataStore::exportSceneJson(Project::m_scene, m_currentSceneName);
}
if (ImGui::BeginMenuBar()) {
if (ImGui::MenuItem("Save")) {
if (m_currentSceneName == "")
ImGui::OpenPopup("SAVE_SCENE_NAME");
else
SceneDataStore::exportScene(Project::m_scene,
m_currentSceneName);
}
if (ImGui::MenuItem("Save as")) {
ImGui::OpenPopup("SAVE_SCENE_NAME");
}
if (ImGui::MenuItem("New Scene")) {
ImGui::OpenPopup("SAVE_SCENE_BEFORE_CREATING_NEW");
}
if (ImGui::MenuItem("Save as")) {
ImGui::OpenPopup("SAVE_SCENE_NAME");
}
if (ImGui::MenuItem("New Scene")) {
ImGui::OpenPopup("SAVE_SCENE_BEFORE_CREATING_NEW");
}
if (ImGui::MenuItem("New folder")) {
ImGui::OpenPopup("CREATE_SCENE_FOLDER");
}
if (ImGui::MenuItem("New folder")) {
ImGui::OpenPopup("CREATE_SCENE_FOLDER");
}
if (ImGui::MenuItem("Explorer")) {
openFileExplorer(m_currentScenePath.generic_string());
}
if (ImGui::MenuItem("Explorer")) {
openFileExplorer(m_currentScenePath.generic_string());
}
stringInputPopup<saveSceneName>("SAVE_SCENE_NAME", "Scene name");
stringInputPopup<createFolderName>("CREATE_SCENE_FOLDER", "Folder name");
saveInputPopup<saveBeforeCreatingNew>("SAVE_SCENE_BEFORE_CREATING_NEW", "Do you want to save the scene before creating new?");
stringInputPopup<saveSceneNameBeforeCreatingNew>("SAVE_SCENE_NAME_CREATE_NEW", "Scene name");
stringInputPopup<saveSceneName>("SAVE_SCENE_NAME", "Scene name");
stringInputPopup<createFolderName>("CREATE_SCENE_FOLDER",
"Folder name");
saveInputPopup<saveBeforeCreatingNew>(
"SAVE_SCENE_BEFORE_CREATING_NEW",
"Do you want to save the scene before creating new?");
stringInputPopup<saveSceneNameBeforeCreatingNew>(
"SAVE_SCENE_NAME_CREATE_NEW", "Scene name");
ImGui::EndMenuBar();
}
ImGui::EndMenuBar();
}
ImGui::Text("%s", m_currentScenePath.generic_string().c_str());
ImGui::Text("%s", m_currentScenePath.generic_string().c_str());
ImGui::TextDisabled("Active Scene : ");
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.7f, 1), "%s", m_currentSceneName.generic_string().c_str());
setupColumns(ICON_MIN_SIZE + 80);
ImGui::TextDisabled("Active Scene : ");
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.7f, 1), "%s",
m_currentSceneName.generic_string().c_str());
if (m_currentScenePath != DEER_SCENE_PATH) {
drawSceneExplorerFolder("..");
setupColumns(ICON_MIN_SIZE + 80);
float cursorOffset = (ICON_MIN_SIZE - ImGui::CalcTextSize("..").x) / 2;
ImGui::SetCursorPos(ImVec2(cursorOffset + ImGui::GetCursorPos().x, ImGui::GetCursorPos().y));
ImGui::Text("..");
if (m_currentScenePath != DEER_SCENE_PATH) {
drawSceneExplorerFolder("..");
ImGui::NextColumn();
}
for (const auto& entry : std::filesystem::directory_iterator(m_currentScenePath)) {
if (entry.is_directory())
drawSceneExplorerFolder(entry.path());
else {
std::string extension = entry.path().filename().extension().string();
if (extension != ".dscn")
continue;
float cursorOffset =
(ICON_MIN_SIZE - ImGui::CalcTextSize("..").x) / 2;
ImGui::SetCursorPos(ImVec2(cursorOffset + ImGui::GetCursorPos().x,
ImGui::GetCursorPos().y));
ImGui::Text("..");
Path sceneName = entry.path().parent_path().lexically_relative(DEER_SCENE_PATH) / entry.path().stem();
drawSceneExplorerScene(sceneName);
}
ImGui::NextColumn();
}
float cursorOffset = (ICON_MIN_SIZE - ImGui::CalcTextSize(entry.path().stem().string().c_str()).x) / 2;
ImGui::SetCursorPos(ImVec2(cursorOffset + ImGui::GetCursorPos().x, ImGui::GetCursorPos().y));
ImGui::Text("%s", entry.path().stem().string().c_str());
for (const auto& entry :
std::filesystem::directory_iterator(m_currentScenePath)) {
if (entry.is_directory())
drawSceneExplorerFolder(entry.path());
else {
std::string extension =
entry.path().filename().extension().string();
if (extension != ".dscn") continue;
ImGui::NextColumn();
}
ImGui::Columns();
Path sceneName = entry.path().parent_path().lexically_relative(
DEER_SCENE_PATH) /
entry.path().stem();
drawSceneExplorerScene(sceneName);
}
saveSceneBeforeLoadingPopup();
sceneDialogPopup();
deleteInputPopup<deleteScene>("DELETE_SCENE", "Are you sure you want to delete the scene?");
float cursorOffset =
(ICON_MIN_SIZE -
ImGui::CalcTextSize(entry.path().stem().string().c_str()).x) /
2;
ImGui::SetCursorPos(ImVec2(cursorOffset + ImGui::GetCursorPos().x,
ImGui::GetCursorPos().y));
ImGui::Text("%s", entry.path().stem().string().c_str());
ImGui::NextColumn();
}
ImGui::Columns();
saveSceneBeforeLoadingPopup();
sceneDialogPopup();
deleteInputPopup<deleteScene>(
"DELETE_SCENE", "Are you sure you want to delete the scene?");
ImGui::End();
}
void drawSceneExplorerFolder(const Path& path) {
ImGui::Image((void*)(uint64_t)Icons::folder_icon->getTextureID(), ImVec2(ICON_MIN_SIZE, ICON_MIN_SIZE), ImVec2(0, 1), ImVec2(1, 0));
void drawSceneExplorerFolder(const Path& path) {
ImGui::Image((void*)(uint64_t)Icons::folder_icon->getTextureID(),
ImVec2(ICON_MIN_SIZE, ICON_MIN_SIZE), ImVec2(0, 1),
ImVec2(1, 0));
if (ImGui::IsItemClicked(0) && ImGui::IsMouseDoubleClicked(0)) {
if (path == "..")
m_currentScenePath = m_currentScenePath.parent_path();
else
m_currentScenePath = path;
}
}
if (ImGui::IsItemClicked(0) && ImGui::IsMouseDoubleClicked(0)) {
if (path == "..")
m_currentScenePath = m_currentScenePath.parent_path();
else
m_currentScenePath = path;
}
}
void drawSceneExplorerScene(const Path& path) {
ImGui::Image((void*)(uint64_t)Icons::scene_icon->getTextureID(), ImVec2(ICON_MIN_SIZE, ICON_MIN_SIZE), ImVec2(0, 1), ImVec2(1, 0));
void drawSceneExplorerScene(const Path& path) {
ImGui::Image((void*)(uint64_t)Icons::scene_icon->getTextureID(),
ImVec2(ICON_MIN_SIZE, ICON_MIN_SIZE), ImVec2(0, 1),
ImVec2(1, 0));
if (ImGui::IsItemClicked(0) && ImGui::IsMouseDoubleClicked(0)) {
ImGui::OpenPopup("SAVE_SCENE_BEFORE_LOADING");
m_loadSceneName = path;
}
if (ImGui::IsItemClicked(0) && ImGui::IsMouseDoubleClicked(0)) {
ImGui::OpenPopup("SAVE_SCENE_BEFORE_LOADING");
m_loadSceneName = path;
}
if (ImGui::IsItemClicked(1)) {
ImGui::OpenPopup("SCENE_DIALOG");
m_dialogSceneName = path;
}
}
if (ImGui::IsItemClicked(1)) {
ImGui::OpenPopup("SCENE_DIALOG");
m_dialogSceneName = path;
}
}
std::string sanitizeInput(const std::string& input) {
std::string sanitized;
for (char c : input) {
if (isalnum(c) || c == '_') {
sanitized += c;
}
}
return sanitized;
}
std::string sanitizeInput(const std::string& input) {
std::string sanitized;
for (char c : input) {
if (isalnum(c) || c == '_') {
sanitized += c;
}
}
return sanitized;
}
void saveSceneBeforeLoadingPopup() {
if (ImGui::BeginPopup("SAVE_SCENE_BEFORE_LOADING")) {
if (m_currentSceneName == "") {
Project::m_scene = SceneDataStore::loadScene(m_loadSceneName);
m_currentSceneName = m_loadSceneName;
ImGui::CloseCurrentPopup();
}
void saveSceneBeforeLoadingPopup() {
if (ImGui::BeginPopup("SAVE_SCENE_BEFORE_LOADING")) {
if (m_currentSceneName == "") {
SceneDataStore::loadScene(Project::m_scene, m_loadSceneName);
m_currentSceneName = m_loadSceneName;
ImGui::CloseCurrentPopup();
}
ImGui::Text("Do you want to save the current scene?");
ImGui::Text("Do you want to save the current scene?");
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(100, 255, 120, 255));
bool save = ImGui::Button("Save");
ImGui::PopStyleColor();
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 100, 120, 255));
ImGui::SameLine();
bool dont_save = ImGui::Button("Don't save");
ImGui::PopStyleColor();
ImGui::SameLine();
bool cancel = ImGui::Button("Cancel");
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(100, 255, 120, 255));
bool save = ImGui::Button("Save");
ImGui::PopStyleColor();
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 100, 120, 255));
ImGui::SameLine();
bool dont_save = ImGui::Button("Don't save");
ImGui::PopStyleColor();
ImGui::SameLine();
bool cancel = ImGui::Button("Cancel");
if (save) {
ActiveEntity::clear();
SceneDataStore::exportSceneJson(Project::m_scene, m_currentSceneName);
Project::m_scene = SceneDataStore::loadScene(m_loadSceneName);
m_currentSceneName = m_loadSceneName;
ImGui::CloseCurrentPopup();
}
else if (dont_save) {
ActiveEntity::clear();
Project::m_scene = SceneDataStore::loadScene(m_loadSceneName);
m_currentSceneName = m_loadSceneName;
ImGui::CloseCurrentPopup();
} if (cancel) {
ImGui::CloseCurrentPopup();
}
if (save) {
ActiveEntity::clear();
SceneDataStore::exportScene(Project::m_scene,
m_currentSceneName);
SceneDataStore::loadScene(Project::m_scene, m_loadSceneName);
m_currentSceneName = m_loadSceneName;
ImGui::CloseCurrentPopup();
} else if (dont_save) {
ActiveEntity::clear();
SceneDataStore::loadScene(Project::m_scene, m_loadSceneName);
m_currentSceneName = m_loadSceneName;
ImGui::CloseCurrentPopup();
}
if (cancel) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
ImGui::EndPopup();
}
}
void sceneDialogPopup() {
if (ImGui::BeginPopup("SCENE_DIALOG")) {
if (ImGui::MenuItem("Rename Scene")) {
ImGui::CloseCurrentPopup();
}
void sceneDialogPopup() {
if (ImGui::BeginPopup("SCENE_DIALOG")) {
if (ImGui::MenuItem("Rename Scene")) {
ImGui::CloseCurrentPopup();
}
if (ImGui::MenuItem("Delete Scene")) {
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
if (ImGui::MenuItem("Delete Scene")) {
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
ImGui::OpenPopup("DELETE_SCENE");
m_deleteSceneName = m_dialogSceneName;
return;
}
ImGui::EndPopup();
}
}
ImGui::OpenPopup("DELETE_SCENE");
m_deleteSceneName = m_dialogSceneName;
return;
}
ImGui::EndPopup();
}
}
void deleteScene() {
SceneDataStore::deleteSceneJson(m_deleteSceneName);
}
void createFolderName(const std::string& name) {
std::string correctInput = sanitizeInput(name);
// Implement delete scene
void deleteScene() {}
void createFolderName(const std::string& name) {
std::string correctInput = sanitizeInput(name);
if (name.size() != 0) {
DataStore::createFolder(m_currentScenePath / correctInput);
}
}
void saveSceneName(const std::string& name) {
std::string correctInput = sanitizeInput(name);
if (name.size() != 0) {
DataStore::createFolder(m_currentScenePath / correctInput);
}
}
void saveSceneName(const std::string& name) {
std::string correctInput = sanitizeInput(name);
if (name.size() != 0) {
Path fullName;
if (m_currentScenePath == DEER_SCENE_PATH)
fullName = correctInput;
else
fullName = m_currentScenePath.lexically_relative(DEER_SCENE_PATH) / correctInput;
if (name.size() != 0) {
Path fullName;
if (m_currentScenePath == DEER_SCENE_PATH)
fullName = correctInput;
else
fullName =
m_currentScenePath.lexically_relative(DEER_SCENE_PATH) /
correctInput;
m_currentSceneName = fullName;
SceneDataStore::exportSceneJson(Project::m_scene, fullName);
}
}
void saveBeforeCreatingNew(bool save) {
if (save) {
if (m_currentSceneName == "") {
ImGui::OpenPopup("SAVE_SCENE_NAME_CREATE_NEW");
return;
}
else {
ActiveEntity::clear();
SceneDataStore::exportSceneJson(Project::m_scene, m_currentSceneName);
Project::m_scene = Scene();
m_currentSceneName = Path();
}
}
else {
ActiveEntity::clear();
Project::m_scene = Scene();
m_currentSceneName = Path();
}
}
void saveSceneNameBeforeCreatingNew(const std::string& name) {
std::string correctInput = sanitizeInput(name);
m_currentSceneName = fullName;
SceneDataStore::exportScene(Project::m_scene, fullName);
}
}
void saveBeforeCreatingNew(bool save) {
if (save) {
if (m_currentSceneName == "") {
ImGui::OpenPopup("SAVE_SCENE_NAME_CREATE_NEW");
return;
} else {
ActiveEntity::clear();
SceneDataStore::exportScene(Project::m_scene,
m_currentSceneName);
Project::m_scene.clear();
m_currentSceneName = Path();
}
} else {
ActiveEntity::clear();
Project::m_scene.clear();
m_currentSceneName = Path();
}
}
void saveSceneNameBeforeCreatingNew(const std::string& name) {
std::string correctInput = sanitizeInput(name);
if (name.size() != 0) {
Path fullName;
if (m_currentScenePath == DEER_SCENE_PATH)
fullName = correctInput;
else
fullName = m_currentScenePath.lexically_relative(DEER_SCENE_PATH) / correctInput;
if (name.size() != 0) {
Path fullName;
if (m_currentScenePath == DEER_SCENE_PATH)
fullName = correctInput;
else
fullName =
m_currentScenePath.lexically_relative(DEER_SCENE_PATH) /
correctInput;
SceneDataStore::exportSceneJson(Project::m_scene, fullName);
ActiveEntity::clear();
Project::m_scene = Scene();
m_currentSceneName = Path();
}
}
}
SceneDataStore::exportScene(Project::m_scene, fullName);
ActiveEntity::clear();
Project::m_scene.clear();
m_currentSceneName = Path();
}
}
} // namespace Deer

View File

@ -24,8 +24,7 @@ namespace Deer {
void TerrainEditor::terrainEditor_onImGui() {
ImGui::Begin("Terrain Editor");
Ref<VoxelWorld>& voxelWorld = Project::m_scene.getVoxelWorld();
if (voxelWorld == nullptr) {
if (!Project::m_scene.isVoxelWorldInitialized()) {
if (ImGui::Button("Create Voxel World")) {
ImGui::OpenPopup(TERRAIN_EDITOR_CREATE_VOXEL_WORLD_POPUP_NAME);
}
@ -35,6 +34,7 @@ namespace Deer {
return;
}
VoxelWorld& voxelWorld = Project::m_scene.getVoxelWorld();
ImGui::Text("Edit mode: ");
setupColumns(ICON_BTN_MIN_SIZE + 16);

View File

@ -1,142 +1,155 @@
#include "TerrainEditor.h"
#include "DeerStudio/Project.h"
#include "DeerStudio/Editor/Viewport.h"
#include "DeerStudio/Editor/EditorUtils.h"
#include "DeerStudio/Editor/Icons.h"
#include "Deer/Log.h"
#include "Deer/Scene.h"
#include "Deer/Voxel.h"
#include "Deer/VoxelWorld.h"
#include "Deer/Scene.h"
#include "DeerRender/GizmoRenderer.h"
#include "DeerRender/Render/Texture.h"
#include "DeerStudio/Editor/EditorUtils.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Editor/Viewport.h"
#include "DeerStudio/Project.h"
#include "TerrainEditor.h"
#include "imgui.h"
namespace Deer {
namespace TerrainEditor {
VoxelCordinates selectedVoxelStart(-1, -1, -1);
VoxelCordinates selectedVoxelEnd(-1, -1, -1);
uint8_t voxelSelectMode = 0;
}
namespace TerrainEditor {
VoxelCordinates selectedVoxelStart(-1, -1, -1);
VoxelCordinates selectedVoxelEnd(-1, -1, -1);
uint8_t voxelSelectMode = 0;
} // namespace TerrainEditor
void TerrainEditor::boxSelect() {
ImGui::Separator();
ImGui::Spacing();
ImGui::Text("Select mode: ");
ImGui::SameLine();
if (voxelSelectMode == FACE_VOXEL_SELECT)
ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.6f, 1.0f), "%s","Face");
else
ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.6f, 1.0f), "%s","Voxel");
ImGui::Separator();
ImGui::Spacing();
setupColumns(ICON_BTN_MIN_SIZE + 16);
if (iconButton((ImTextureID)(uint64_t)Icons::face_voxel_selection_icon->getTextureID(), ICON_BTN_MIN_SIZE, voxelSelectMode == FACE_VOXEL_SELECT)) {
voxelSelectMode = FACE_VOXEL_SELECT;
}
ImGui::Text("Face");
ImGui::NextColumn();
if (iconButton((ImTextureID)(uint64_t)Icons::internal_voxel_selection_icon->getTextureID(), ICON_BTN_MIN_SIZE, voxelSelectMode == INTERNAL_VOXEL_SELECT)) {
voxelSelectMode = INTERNAL_VOXEL_SELECT;
}
ImGui::Text("Voxel");
ImGui::Columns();
void TerrainEditor::boxSelect() {
ImGui::Separator();
ImGui::Spacing();
ImGui::Text("Select mode: ");
ImGui::SameLine();
if (voxelSelectMode == FACE_VOXEL_SELECT)
ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.6f, 1.0f), "%s", "Face");
else
ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.6f, 1.0f), "%s", "Voxel");
if (!viewportIsActive()) {
if (selectedVoxelStart.isNull())
selectedVoxelStart.makeNull();
return;
}
ImGui::Separator();
ImGui::Spacing();
setupColumns(ICON_BTN_MIN_SIZE + 16);
if (iconButton((ImTextureID)(uint64_t)
Icons::face_voxel_selection_icon->getTextureID(),
ICON_BTN_MIN_SIZE,
voxelSelectMode == FACE_VOXEL_SELECT)) {
voxelSelectMode = FACE_VOXEL_SELECT;
}
ImGui::Text("Face");
ImGui::NextColumn();
if (iconButton((ImTextureID)(uint64_t)
Icons::internal_voxel_selection_icon->getTextureID(),
ICON_BTN_MIN_SIZE,
voxelSelectMode == INTERNAL_VOXEL_SELECT)) {
voxelSelectMode = INTERNAL_VOXEL_SELECT;
}
ImGui::Text("Voxel");
ImGui::Columns();
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left) || ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
if (voxelSelectMode == FACE_VOXEL_SELECT) {
selectedVoxelEnd = voxelFaceRayCoords;
} else {
selectedVoxelEnd = voxelRayCoords;
}
Project::m_scene.getVoxelWorld()->getVoxelWorldProps().clampCordinates(selectedVoxelEnd);
}
if (!viewportIsActive()) {
if (selectedVoxelStart.isNull()) selectedVoxelStart.makeNull();
return;
}
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) == 1) {
selectedVoxelStart = selectedVoxelEnd;
}
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left) ||
ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
if (voxelSelectMode == FACE_VOXEL_SELECT) {
selectedVoxelEnd = voxelFaceRayCoords;
} else {
selectedVoxelEnd = voxelRayCoords;
}
Project::m_scene.getVoxelWorld()
.getVoxelWorldProps()
.clampCordinates(selectedVoxelEnd);
}
if (ImGui::IsMouseClicked(ImGuiMouseButton_Middle) == 1) {
selectedVoxelStart.makeNull();
selectedVoxelEnd.makeNull();
}
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) == 1) {
selectedVoxelStart = selectedVoxelEnd;
}
}
if (ImGui::IsMouseClicked(ImGuiMouseButton_Middle) == 1) {
selectedVoxelStart.makeNull();
selectedVoxelEnd.makeNull();
}
}
void TerrainEditor::boxSelect_Visuals() {
void TerrainEditor::boxSelect_Visuals() {
VoxelWorld& voxelWorld = Project::m_scene.getVoxelWorld();
GizmoRenderer& gizmo = Project::m_scene.getMainGizmoRenderer();
Ref<VoxelWorld>& voxelWorld = Project::m_scene.getVoxelWorld();
GizmoRenderer& gizmo = Project::m_scene.getMainGizmoRenderer();
if (!selectedVoxelStart.isNull() && !selectedVoxelEnd.isNull()) {
VoxelCordinates min;
VoxelCordinates max;
if (!selectedVoxelStart.isNull() && !selectedVoxelEnd.isNull()) {
VoxelCordinates min;
VoxelCordinates max;
if (selectedVoxelEnd.x < selectedVoxelStart.x) {
min.x = selectedVoxelEnd.x;
max.x = selectedVoxelStart.x;
} else {
max.x = selectedVoxelEnd.x;
min.x = selectedVoxelStart.x;
}
if (selectedVoxelEnd.x < selectedVoxelStart.x) {
min.x = selectedVoxelEnd.x;
max.x = selectedVoxelStart.x;
} else {
max.x = selectedVoxelEnd.x;
min.x = selectedVoxelStart.x;
}
if (selectedVoxelEnd.y < selectedVoxelStart.y) {
min.y = selectedVoxelEnd.y;
max.y = selectedVoxelStart.y;
} else {
max.y = selectedVoxelEnd.y;
min.y = selectedVoxelStart.y;
}
if (selectedVoxelEnd.y < selectedVoxelStart.y) {
min.y = selectedVoxelEnd.y;
max.y = selectedVoxelStart.y;
} else {
max.y = selectedVoxelEnd.y;
min.y = selectedVoxelStart.y;
}
if (selectedVoxelEnd.z < selectedVoxelStart.z) {
min.z = selectedVoxelEnd.z;
max.z = selectedVoxelStart.z;
} else {
max.z = selectedVoxelEnd.z;
min.z = selectedVoxelStart.z;
}
if (selectedVoxelEnd.z < selectedVoxelStart.z) {
min.z = selectedVoxelEnd.z;
max.z = selectedVoxelStart.z;
} else {
max.z = selectedVoxelEnd.z;
min.z = selectedVoxelStart.z;
}
int debugVoxel = VoxelData::getVoxelID("debug");
int debugInternal = VoxelData::getVoxelID("debug_internal");
int debugVoxel = VoxelData::getVoxelID("debug");
int debugInternal = VoxelData::getVoxelID("debug_internal");
// External faces
// Z Face
for (int x = min.x; x <= max.x; x++) {
for (int y = min.y; y <= max.y; y++) {
gizmo.drawVoxelFace(x, y, min.z, debugVoxel, NORMAL_BACK,
5);
gizmo.drawVoxelFace(x, y, max.z, debugVoxel, NORMAL_FRONT,
5);
gizmo.drawVoxelFaceInverted(x, y, min.z, debugInternal,
NORMAL_BACK, 4);
gizmo.drawVoxelFaceInverted(x, y, max.z, debugInternal,
NORMAL_FRONT, 4);
}
}
// External faces
// Z Face
for (int x = min.x; x <= max.x; x++) {
for (int y = min.y; y <= max.y; y++) {
gizmo.drawVoxelFace(x, y, min.z, debugVoxel, NORMAL_BACK, 5);
gizmo.drawVoxelFace(x, y, max.z, debugVoxel, NORMAL_FRONT, 5);
gizmo.drawVoxelFaceInverted(x, y, min.z, debugInternal, NORMAL_BACK, 4);
gizmo.drawVoxelFaceInverted(x, y, max.z, debugInternal, NORMAL_FRONT, 4);
}
}
// Y Face
for (int x = min.x; x <= max.x; x++) {
for (int z = min.z; z <= max.z; z++) {
gizmo.drawVoxelFace(x, min.y, z, debugVoxel, NORMAL_DOWN,
5);
gizmo.drawVoxelFace(x, max.y, z, debugVoxel, NORMAL_UP, 5);
gizmo.drawVoxelFaceInverted(x, min.y, z, debugInternal,
NORMAL_DOWN, 4);
gizmo.drawVoxelFaceInverted(x, max.y, z, debugInternal,
NORMAL_UP, 4);
}
}
// Y Face
for (int x = min.x; x <= max.x; x++) {
for (int z = min.z; z <= max.z; z++) {
gizmo.drawVoxelFace(x, min.y, z, debugVoxel, NORMAL_DOWN, 5);
gizmo.drawVoxelFace(x, max.y, z, debugVoxel, NORMAL_UP, 5);
gizmo.drawVoxelFaceInverted(x, min.y, z, debugInternal, NORMAL_DOWN, 4);
gizmo.drawVoxelFaceInverted(x, max.y, z, debugInternal, NORMAL_UP, 4);
}
}
// X Face
for (int y = min.y; y <= max.y; y++) {
for (int z = min.z; z <= max.z; z++) {
gizmo.drawVoxelFace(min.x, y, z, debugVoxel, NORMAL_LEFT, 5);
gizmo.drawVoxelFace(max.x, y, z, debugVoxel, NORMAL_RIGHT, 5);
gizmo.drawVoxelFaceInverted(min.x, y, z, debugInternal, NORMAL_LEFT, 4);
gizmo.drawVoxelFaceInverted(max.x, y, z, debugInternal, NORMAL_RIGHT, 4);
}
}
}
}
}
// X Face
for (int y = min.y; y <= max.y; y++) {
for (int z = min.z; z <= max.z; z++) {
gizmo.drawVoxelFace(min.x, y, z, debugVoxel, NORMAL_LEFT,
5);
gizmo.drawVoxelFace(max.x, y, z, debugVoxel, NORMAL_RIGHT,
5);
gizmo.drawVoxelFaceInverted(min.x, y, z, debugInternal,
NORMAL_LEFT, 4);
gizmo.drawVoxelFaceInverted(max.x, y, z, debugInternal,
NORMAL_RIGHT, 4);
}
}
}
}
} // namespace Deer

View File

@ -84,7 +84,7 @@ namespace Deer {
props.chunkSizeZ = values[2];
Project::m_scene.createVoxelWorld(props);
Project::m_scene.getVoxelWorld()->fillVoxels(
Project::m_scene.getVoxelWorld().fillVoxels(
VoxelCordinates(0, 0, 0), VoxelCordinates(31, 8, 31),
Voxel(VoxelData::getVoxelID("wood")));

View File

@ -1,54 +1,56 @@
#include "TerrainEditor.h"
#include "DeerStudio/Project.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Editor/Viewport.h"
#include "DeerStudio/Editor/EditorUtils.h"
#include "Deer/Scene.h"
#include "Deer/Voxel.h"
#include "Deer/VoxelWorld.h"
#include "Deer/Scene.h"
#include "DeerRender/GizmoRenderer.h"
#include "DeerStudio/Editor/EditorUtils.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Editor/Viewport.h"
#include "DeerStudio/Project.h"
#include "TerrainEditor.h"
#include "imgui.h"
namespace Deer {
void TerrainEditor::empty() {
if (!viewportIsActive())
return;
void TerrainEditor::empty() {
if (!viewportIsActive()) return;
VoxelCordinates selectVoxel;
VoxelCordinates clampedCordinates;
selectVoxel = voxelRayCoords;
VoxelCordinates selectVoxel;
VoxelCordinates clampedCordinates;
selectVoxel = voxelRayCoords;
clampedCordinates = selectVoxel;
Project::m_scene.getVoxelWorld()->getVoxelWorldProps().clampCordinates(clampedCordinates);
clampedCordinates = selectVoxel;
Project::m_scene.getVoxelWorld().getVoxelWorldProps().clampCordinates(
clampedCordinates);
if (clampedCordinates != selectVoxel)
return;
VoxelCordinates min = selectedVoxelStart;
VoxelCordinates max = selectedVoxelEnd;
if (clampedCordinates != selectVoxel) return;
if (min.isNull() || max.isNull()) {
min = VoxelCordinates(selectVoxel.x - 16, selectVoxel.y - 16, selectVoxel.z - 16);
max = VoxelCordinates(selectVoxel.x + 15, selectVoxel.y + 15, selectVoxel.z + 15);
}
Project::m_scene.getVoxelWorld()->getVoxelWorldProps().clampAndSetMinMax(min, max);
VoxelCordinates min = selectedVoxelStart;
VoxelCordinates max = selectedVoxelEnd;
if (selectVoxel.x < min.x || selectVoxel.x > max.x ||
selectVoxel.y < min.y || selectVoxel.y > max.y ||
selectVoxel.z < min.z || selectVoxel.z > max.z)
return;
if (min.isNull() || max.isNull()) {
min = VoxelCordinates(selectVoxel.x - 16, selectVoxel.y - 16,
selectVoxel.z - 16);
max = VoxelCordinates(selectVoxel.x + 15, selectVoxel.y + 15,
selectVoxel.z + 15);
}
Project::m_scene.getVoxelWorld().getVoxelWorldProps().clampAndSetMinMax(
min, max);
for (int i = 0; i < 6; i++) {
Project::m_scene.getMainGizmoRenderer().drawVoxelFace(clampedCordinates.x, clampedCordinates.y, clampedCordinates.z,
VoxelData::getVoxelID("debug"), i, 0);
}
if (selectVoxel.x < min.x || selectVoxel.x > max.x ||
selectVoxel.y < min.y || selectVoxel.y > max.y ||
selectVoxel.z < min.z || selectVoxel.z > max.z)
return;
if (ImGui::GetMouseClickedCount(ImGuiMouseButton_Left)) {
Voxel voxel = Project::m_scene.getVoxelWorld()->readVoxel(selectVoxel);
Project::m_scene.getVoxelWorld()->remplaceVoxels(min, max, voxel, Voxel(0));
}
}
}
for (int i = 0; i < 6; i++) {
Project::m_scene.getMainGizmoRenderer().drawVoxelFace(
clampedCordinates.x, clampedCordinates.y, clampedCordinates.z,
VoxelData::getVoxelID("debug"), i, 0);
}
if (ImGui::GetMouseClickedCount(ImGuiMouseButton_Left)) {
Voxel voxel =
Project::m_scene.getVoxelWorld().readVoxel(selectVoxel);
Project::m_scene.getVoxelWorld().remplaceVoxels(min, max, voxel,
Voxel(0));
}
}
} // namespace Deer

View File

@ -52,7 +52,7 @@ namespace Deer {
}
clampedCordinates = selectVoxel;
Project::m_scene.getVoxelWorld()->getVoxelWorldProps().clampCordinates(
Project::m_scene.getVoxelWorld().getVoxelWorldProps().clampCordinates(
clampedCordinates);
if (clampedCordinates != selectVoxel) return;
@ -66,9 +66,8 @@ namespace Deer {
max = VoxelCordinates(selectVoxel.x + 15, selectVoxel.y + 15,
selectVoxel.z + 15);
}
Project::m_scene.getVoxelWorld()
->getVoxelWorldProps()
.clampAndSetMinMax(min, max);
Project::m_scene.getVoxelWorld().getVoxelWorldProps().clampAndSetMinMax(
min, max);
if (selectVoxel.x < min.x || selectVoxel.x > max.x ||
selectVoxel.y < min.y || selectVoxel.y > max.y ||
@ -83,8 +82,8 @@ namespace Deer {
if (ImGui::GetMouseClickedCount(ImGuiMouseButton_Left)) {
Voxel voxel =
Project::m_scene.getVoxelWorld()->readVoxel(selectVoxel);
Project::m_scene.getVoxelWorld()->remplaceVoxels(
Project::m_scene.getVoxelWorld().readVoxel(selectVoxel);
Project::m_scene.getVoxelWorld().remplaceVoxels(
min, max, voxel, Voxel(selectedVoxelID));
}
}

View File

@ -1,63 +1,73 @@
#include "TerrainEditor.h"
#include "DeerStudio/Project.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Editor/EditorUtils.h"
#include "Deer/Voxel.h"
#include "Deer/Scene.h"
#include "Deer/VoxelWorld.h"
#include "imgui.h"
#include <string>
#include "Deer/Scene.h"
#include "Deer/Voxel.h"
#include "Deer/VoxelWorld.h"
#include "DeerStudio/Editor/EditorUtils.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Project.h"
#include "TerrainEditor.h"
#include "imgui.h"
namespace Deer {
namespace TerrainEditor {
namespace TerrainEditor {
void deleteVoxelWorld();
}
void TerrainEditor::info() {
Ref<VoxelWorld>& voxelWorld = Project::m_scene.getVoxelWorld();
VoxelWorldProps worldProps = voxelWorld->getVoxelWorldProps();
void TerrainEditor::info() {
VoxelWorld& voxelWorld = Project::m_scene.getVoxelWorld();
VoxelWorldProps worldProps = voxelWorld.getVoxelWorldProps();
ImGui::Text("Voxel world chunk and voxel size:");
ImGui::Text(" x: %s chunks -> %s voxels", std::to_string(worldProps.chunkSizeX).c_str(), std::to_string(worldProps.chunkSizeX * CHUNK_SIZE_X).c_str());
ImGui::Text(" y: %s chunks -> %s voxels", std::to_string(worldProps.chunkSizeY).c_str(), std::to_string(worldProps.chunkSizeY * CHUNK_SIZE_Y).c_str());
ImGui::Text(" z: %s chunks -> %s voxels", std::to_string(worldProps.chunkSizeZ).c_str(), std::to_string(worldProps.chunkSizeZ * CHUNK_SIZE_Z).c_str());
ImGui::Text("Voxel world chunk and voxel size:");
ImGui::Text(
" x: %s chunks -> %s voxels",
std::to_string(worldProps.chunkSizeX).c_str(),
std::to_string(worldProps.chunkSizeX * CHUNK_SIZE_X).c_str());
ImGui::Text(
" y: %s chunks -> %s voxels",
std::to_string(worldProps.chunkSizeY).c_str(),
std::to_string(worldProps.chunkSizeY * CHUNK_SIZE_Y).c_str());
ImGui::Text(
" z: %s chunks -> %s voxels",
std::to_string(worldProps.chunkSizeZ).c_str(),
std::to_string(worldProps.chunkSizeZ * CHUNK_SIZE_Z).c_str());
ImGui::Separator();
ImGui::Separator();
int64_t voxelCount = CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z *
worldProps.chunkSizeX * worldProps.chunkSizeY *
worldProps.chunkSizeZ;
int64_t clientSize = voxelCount * (sizeof(Voxel) + sizeof(VoxelLight));
int64_t serverSize = voxelCount * (sizeof(Voxel));
int64_t voxelCount = CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z * worldProps.chunkSizeX * worldProps.chunkSizeY * worldProps.chunkSizeZ;
int64_t clientSize = voxelCount * (sizeof(Voxel) + sizeof(VoxelLight));
int64_t serverSize = voxelCount * (sizeof(Voxel));
ImGui::Text("%s", "Theorical max voxel count : ");
ImGui::SameLine();
ImGui::Text("%s", std::to_string(voxelCount).c_str());
ImGui::Text("%s", "Theorical max voxel count : ");
ImGui::SameLine();
ImGui::Text("%s", std::to_string(voxelCount).c_str());
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
ImGui::Separator();
ImGui::Text("%s", "Client theorical max size : ");
ImGui::Text(" %sB", std::to_string(clientSize).c_str());
ImGui::Text(" +%sKB", std::to_string(clientSize / 1024).c_str());
ImGui::Text(" +%sMB",
std::to_string(clientSize / (1024 * 1024)).c_str());
ImGui::Text(" +%sGB",
std::to_string(clientSize / (1024 * 1024 * 1024)).c_str());
ImGui::Text("%s", "Client theorical max size : ");
ImGui::Text(" %sB", std::to_string(clientSize).c_str());
ImGui::Text(" +%sKB", std::to_string(clientSize / 1024).c_str());
ImGui::Text(" +%sMB", std::to_string(clientSize / (1024 * 1024)).c_str());
ImGui::Text(" +%sGB", std::to_string(clientSize / (1024 * 1024 * 1024)).c_str());
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
ImGui::Separator();
ImGui::Text("%s", "Server theorical max size : ");
ImGui::Text(" %sB", std::to_string(serverSize).c_str());
ImGui::Text(" +%sKB", std::to_string(serverSize / 1024).c_str());
ImGui::Text(" +%sMB", std::to_string(serverSize / (1024 * 1024)).c_str());
ImGui::Text(" +%sGB", std::to_string(serverSize / (1024 * 1024 * 1024)).c_str());
ImGui::Separator();
ImGui::Spacing();
ImGui::Text("%s", "Server theorical max size : ");
ImGui::Text(" %sB", std::to_string(serverSize).c_str());
ImGui::Text(" +%sKB", std::to_string(serverSize / 1024).c_str());
ImGui::Text(" +%sMB",
std::to_string(serverSize / (1024 * 1024)).c_str());
ImGui::Text(" +%sGB",
std::to_string(serverSize / (1024 * 1024 * 1024)).c_str());
ImGui::Separator();
ImGui::Spacing();
if (ImGui::Button("Delete voxel world")) {
ImGui::OpenPopup("DELETE_VOXEL_WORLD");
@ -65,26 +75,25 @@ namespace Deer {
// TEMP
if (ImGui::Button("Create Ceiling")) {
Project::m_scene.getVoxelWorld()->fillVoxels(
VoxelCordinates(), VoxelCordinates(
32 * worldProps.chunkSizeX - 1,
16,
32 * worldProps.chunkSizeZ - 1),
Voxel(VoxelData::getVoxelID("wood")));
Project::m_scene.getVoxelWorld()->fillVoxels(
VoxelCordinates(1, 8, 1),
VoxelCordinates(
32 * worldProps.chunkSizeX - 2,
15,
32 * worldProps.chunkSizeZ - 2),
Voxel(VoxelData::getVoxelID("air")));
Project::m_scene.getVoxelWorld().fillVoxels(
VoxelCordinates(),
VoxelCordinates(32 * worldProps.chunkSizeX - 1, 16,
32 * worldProps.chunkSizeZ - 1),
Voxel(VoxelData::getVoxelID("wood")));
Project::m_scene.getVoxelWorld().fillVoxels(
VoxelCordinates(1, 8, 1),
VoxelCordinates(32 * worldProps.chunkSizeX - 2, 15,
32 * worldProps.chunkSizeZ - 2),
Voxel(VoxelData::getVoxelID("air")));
}
deleteInputPopup<deleteVoxelWorld>("DELETE_VOXEL_WORLD", "Are you sure you want to delete voxel world?");
}
deleteInputPopup<deleteVoxelWorld>(
"DELETE_VOXEL_WORLD",
"Are you sure you want to delete voxel world?");
}
void TerrainEditor::deleteVoxelWorld() {
Project::m_scene.deleteVoxelWorld();
}
}
} // namespace Deer

View File

@ -42,7 +42,7 @@ namespace Deer {
glm::vec3 rayDir = farPoint - nearPoint;
rayDir = glm::normalize(rayDir);
VoxelRayResult res = Project::m_scene.getVoxelWorld()->rayCast_editor(
VoxelRayResult res = Project::m_scene.getVoxelWorld().rayCast_editor(
viewport_sceneCamera.transform.position, rayDir, 50);
voxelRayCoords.makeNull();
@ -59,8 +59,8 @@ namespace Deer {
if (viewport_isActive && ImGui::GetMouseClickedCount(0) > 0) {
if (terrainEditMode == TerrainEditMode_Substract) {
if (res.hitPos.y >= 0) {
Project::m_scene.getVoxelWorld()->setVoxel(res.hitPos,
emptyVoxel);
Project::m_scene.getVoxelWorld().setVoxel(res.hitPos,
emptyVoxel);
}
} else if (terrainEditMode == TerrainEditMode_Add) {
VoxelCordinates position(
@ -68,7 +68,7 @@ namespace Deer {
res.hitPos.y + NORMAL_DIR(1, res.face),
res.hitPos.z + NORMAL_DIR(2, res.face));
Project::m_scene.getVoxelWorld()->setVoxel(
Project::m_scene.getVoxelWorld().setVoxel(
position, Voxel(selectedVoxelID));
}
}

View File

@ -1,43 +1,45 @@
#include "TreePannel.h"
#include "DeerStudio/Project.h"
#include "DeerStudio/Editor/ActiveEntity.h"
#include "Deer/Enviroment.h"
#include "Deer/Scene.h"
#include "DeerRender/Input.h"
#include "DeerRender/KeyCodes.h"
#include "Deer/Scene.h"
#include "Deer/Enviroment.h"
#include "DeerStudio/Editor/ActiveEntity.h"
#include "DeerStudio/Project.h"
#include "imgui.h"
namespace Deer {
void updateEntity(Entity& entity);
void updateReciveDragPayload(Entity& entity);
bool updateDragPayload(Entity* entity, const std::string& name);
void updateContextMenu();
void clickEntity(Entity& entity);
namespace TreePannel {
void updateEntity(Entity& entity);
void updateReciveDragPayload(Entity& entity);
bool updateDragPayload(Entity* entity, const std::string& name);
void updateContextMenu();
void clickEntity(Entity& entity);
bool m_isRightClickHandled;
Entity* m_contextMenuEntity = nullptr;
bool m_isRightClickHandled;
Entity* m_contextMenuEntity = nullptr;
} // namespace TreePannel
void treePannel_onImGui() {
void TreePannel::treePannel_onImGui() {
ImGui::Begin("Tree Pannel", (bool*)0, ImGuiWindowFlags_MenuBar);
m_isRightClickHandled = false;
Entity& root = Project::m_scene.getMainEnviroment()->getRoot();
Entity& root = Project::m_scene.getMainEnviroment().getRoot();
if (!m_contextMenuEntity)
m_contextMenuEntity = &root;
if (!m_contextMenuEntity) m_contextMenuEntity = &root;
if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("New")) {
if (ImGui::MenuItem("Entity")) {
Entity& entity = Project::m_scene.getMainEnviroment()->createEntity("new entity");
Entity& entity =
Project::m_scene.getMainEnviroment().createEntity(
"new entity");
entity.setParent(root);
}
if (ImGui::MenuItem("Camera")) {
Entity& entity = Project::m_scene.getMainEnviroment()->createEntity("new camera");
Entity& entity =
Project::m_scene.getMainEnviroment().createEntity(
"new camera");
entity.addComponent<CameraComponent>();
entity.setParent(root);
}
@ -47,8 +49,14 @@ namespace Deer {
}
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
for (auto& entityID : Project::m_scene.getMainEnviroment()->getRoot().getChildren()) {
Entity& childEntity = Project::m_scene.getMainEnviroment()->getEntity(entityID);
RelationshipComponent& relation =
Project::m_scene.getMainEnviroment()
.getRoot()
.getComponent<RelationshipComponent>();
for (int i = 0; i < relation.childCount; i++) {
Entity& childEntity =
Project::m_scene.getMainEnviroment().getEntity(
relation.getChildrenId(i));
updateEntity(childEntity);
}
ImGui::PopStyleVar();
@ -61,10 +69,12 @@ namespace Deer {
ImGui::InvisibleButton("DragDropSpace", spaceSize);
updateReciveDragPayload(root);
if (!m_isRightClickHandled && ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right) &&
!ImGui::IsAnyItemHovered()) {
if (!m_isRightClickHandled &&
ImGui::IsWindowHovered(
ImGuiHoveredFlags_AllowWhenBlockedByPopup |
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right) &&
!ImGui::IsAnyItemHovered()) {
m_contextMenuEntity = &root;
ImGui::OpenPopup("Entity Context Menu");
}
@ -73,20 +83,22 @@ namespace Deer {
ImGui::End();
}
void updateEntity(Entity& entity) {
void TreePannel::updateEntity(Entity& entity) {
auto& tag = entity.getComponent<TagComponent>();
auto& relationship = entity.getComponent<RelationshipComponent>();
std::string name = (tag.tag == "") ? "-" : tag.tag;
const void* entityID = reinterpret_cast<const void*>(static_cast<uintptr_t>(entity.getUID()));
const void* entityID = reinterpret_cast<const void*>(
static_cast<uintptr_t>(entity.getId()));
ImGui::Spacing();
//End of the tree
if (relationship.children.size() == 0) {
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth;
// End of the tree
if (relationship.childCount == 0) {
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf |
ImGuiTreeNodeFlags_NoTreePushOnOpen |
ImGuiTreeNodeFlags_SpanFullWidth;
if (ActiveEntity::contains(entity))
flags |= ImGuiTreeNodeFlags_Selected;
@ -105,7 +117,9 @@ namespace Deer {
return;
}
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanFullWidth;
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnDoubleClick |
ImGuiTreeNodeFlags_OpenOnArrow |
ImGuiTreeNodeFlags_SpanFullWidth;
if (ActiveEntity::contains(entity))
flags |= ImGuiTreeNodeFlags_Selected;
@ -113,8 +127,7 @@ namespace Deer {
flags |= ImGuiTreeNodeFlags_DefaultOpen;
if (ImGui::TreeNodeEx(entityID, flags, "%s", name.c_str())) {
if (!entity.isRoot())
updateDragPayload(&entity, tag.tag);
if (!entity.isRoot()) updateDragPayload(&entity, tag.tag);
updateReciveDragPayload(entity);
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
@ -125,17 +138,17 @@ namespace Deer {
clickEntity(entity);
for (auto& entityID : entity.getChildren()) {
updateReciveDragPayload(entity);
Entity& childEntity = Project::m_scene.getMainEnviroment()->getEntity(entityID);
RelationshipComponent& rc =
entity.getComponent<RelationshipComponent>();
for (int i = 0; i < rc.childCount; i++) {
uint16_t childID = rc.getChildrenId(i);
Entity& childEntity =
m_contextMenuEntity->getEnvironment()->getEntity(childID);
updateEntity(childEntity);
}
updateContextMenu();
ImGui::TreePop();
}
else {
} else {
clickEntity(entity);
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
@ -144,19 +157,18 @@ namespace Deer {
ImGui::OpenPopup("Entity Context Menu");
}
if (!entity.isRoot())
updateDragPayload(&entity, tag.tag);
if (!entity.isRoot()) updateDragPayload(&entity, tag.tag);
updateReciveDragPayload(entity);
}
}
void updateReciveDragPayload(Entity& entity) {
void TreePannel::updateReciveDragPayload(Entity& entity) {
if (ImGui::BeginDragDropTarget()) {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_ENTITY")) {
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload("_ENTITY")) {
Entity* receivedData = *(Entity**)payload->Data;
if (!entity.isDescendant(*receivedData))
if (!entity.isDescendantOf(*receivedData))
receivedData->setParent(entity);
}
@ -164,9 +176,9 @@ namespace Deer {
}
}
bool updateDragPayload(Entity* entity, const std::string& name) {
if (!ImGui::BeginDragDropSource())
return false;
bool TreePannel::updateDragPayload(Entity* entity,
const std::string& name) {
if (!ImGui::BeginDragDropSource()) return false;
ImGui::SetDragDropPayload("_ENTITY", &entity, sizeof(Entity*));
@ -175,9 +187,10 @@ namespace Deer {
return true;
}
void clickEntity(Entity& entity) {
void TreePannel::clickEntity(Entity& entity) {
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) {
if (!(Input::isKeyPressed(DEER_KEY_LEFT_CONTROL) || Input::isKeyPressed(DEER_KEY_LEFT_ALT)))
if (!(Input::isKeyPressed(DEER_KEY_LEFT_CONTROL) ||
Input::isKeyPressed(DEER_KEY_LEFT_ALT)))
ActiveEntity::clear();
if (Input::isKeyPressed(DEER_KEY_LEFT_ALT))
@ -187,19 +200,22 @@ namespace Deer {
}
}
void updateContextMenu() {
void TreePannel::updateContextMenu() {
bool callRename = false;
if (ImGui::BeginPopup("Entity Context Menu")) {
if (ImGui::MenuItem("New Entity")) {
Entity& entity = Project::m_scene.getMainEnviroment()->createEntity("new entity");
Entity& entity =
Project::m_scene.getMainEnviroment().createEntity(
"new entity");
entity.setParent(*m_contextMenuEntity);
ImGui::CloseCurrentPopup();
}
if (ImGui::MenuItem("New Camera")) {
Entity& entity = Project::m_scene.getMainEnviroment()->createEntity("new camera");
Entity& entity =
Project::m_scene.getMainEnviroment().createEntity(
"new camera");
entity.addComponent<CameraComponent>();
entity.setParent(*m_contextMenuEntity);
@ -214,29 +230,31 @@ namespace Deer {
callRename = true;
ImGui::CloseCurrentPopup();
}
if (!m_contextMenuEntity->isRoot() && ImGui::MenuItem("Duplicate")) {
if (!m_contextMenuEntity->isRoot() &&
ImGui::MenuItem("Duplicate")) {
m_contextMenuEntity->duplicate();
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (callRename)
ImGui::OpenPopup("Rename Entity Menu");
if (callRename) ImGui::OpenPopup("Rename Entity Menu");
if (ImGui::BeginPopup("Rename Entity Menu")) {
std::string& name = m_contextMenuEntity->getComponent<TagComponent>().tag;
std::string& name =
m_contextMenuEntity->getComponent<TagComponent>().tag;
char nameBuffer[256];
std::strncpy(nameBuffer, name.c_str(), sizeof(nameBuffer) - 1);
ImGui::Text("Rename");
if (ImGui::InputText("##", nameBuffer, 256, ImGuiInputTextFlags_EnterReturnsTrue)) {
m_contextMenuEntity->getComponent<TagComponent>().tag = nameBuffer;
if (ImGui::InputText("##", nameBuffer, 256,
ImGuiInputTextFlags_EnterReturnsTrue)) {
m_contextMenuEntity->getComponent<TagComponent>().tag =
nameBuffer;
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
}
} // namespace Deer

View File

@ -1,5 +1,7 @@
#pragma once
namespace Deer {
void treePannel_onImGui();
namespace TreePannel {
void treePannel_onImGui();
}
}

View File

@ -1,246 +1,265 @@
#include "Viewport.h"
#include <string>
#include "Deer/Enviroment.h"
#include "Deer/Scene.h"
#include "DeerRender/Events/KeyEvent.h"
#include "DeerRender/Events/MouseEvent.h"
#include "DeerRender/GizmoRenderer.h"
#include "DeerRender/Input.h"
#include "DeerRender/Render/FrameBuffer.h"
#include "DeerStudio/Editor/ActiveEntity.h"
#include "DeerStudio/Project.h"
#include "DeerRender/Render/FrameBuffer.h"
#include "DeerRender/GizmoRenderer.h"
#include "DeerRender/Events/MouseEvent.h"
#include "DeerRender/Events/KeyEvent.h"
#include "DeerRender/Input.h"
#include "Deer/Scene.h"
#include "Deer/Enviroment.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "glm/gtx/matrix_decompose.hpp"
#include "imgui.h"
// In this order
#include "ImGuizmo.h"
#include "glm/glm.hpp"
#include <string>
namespace Deer {
Ref<FrameBuffer> m_frameBuffer;
Ref<FrameBuffer> m_frameBuffer;
glm::vec2 m_lastWindowSize;
glm::vec2 m_lastMousePos;
glm::vec2 m_lastWindowSize;
glm::vec2 m_lastMousePos;
float viewport_relativeXMouse, viewport_relativeYMouse;
bool viewport_isActive;
SceneCamera viewport_sceneCamera(TransformComponent(glm::vec3(16, 16, -16)), CameraComponent());
float viewport_relativeXMouse, viewport_relativeYMouse;
bool viewport_isActive;
SceneCamera viewport_sceneCamera(TransformComponent(glm::vec3(16, 16, -16)),
CameraComponent());
bool m_lastMousePressedButton1;
bool m_handleClick;
bool m_lastMousePressedButton1;
bool m_handleClick;
float m_sensitivity = 0.005f;
float m_sensitivity = 0.005f;
enum class TransformMode {
Translate = 0,
Rotate = 1,
Scale = 2
};
enum class TransformMode { Translate = 0, Rotate = 1, Scale = 2 };
TransformMode m_transformMode = TransformMode::Translate;
TransformMode m_transformMode = TransformMode::Translate;
void processMovment();
bool viewport_onClickEvent(MouseButtonPressedEvent mouseEvent);
bool viewport_onKeyEvent(KeyPressedEvent keyEvent);
bool drawGizmos(int wPosX, int wPosY, int wSizeX, int wSizeY);
void processMovment();
bool viewport_onClickEvent(MouseButtonPressedEvent mouseEvent);
bool viewport_onKeyEvent(KeyPressedEvent keyEvent);
bool drawGizmos(int wPosX, int wPosY, int wSizeX, int wSizeY);
void viewport_onImGui() {
processMovment();
void viewport_onImGui() {
processMovment();
if (!m_frameBuffer) {
m_frameBuffer = FrameBuffer::create(FrameBufferSpecification(100, 100, { TextureBufferType::RGBA8, TextureBufferType::RED_INTEGER }, 4, false));
}
if (!m_frameBuffer) {
m_frameBuffer = FrameBuffer::create(FrameBufferSpecification(
100, 100,
{TextureBufferType::RGBA8, TextureBufferType::RED_INTEGER}, 4,
false));
}
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("Viewport");
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("Viewport");
ImVec2 contentRegionMin = ImGui::GetWindowContentRegionMin();
ImVec2 wPos = ImGui::GetWindowPos();
wPos.y += contentRegionMin.y;
ImVec2 contentRegionMin = ImGui::GetWindowContentRegionMin();
ImVec2 wPos = ImGui::GetWindowPos();
wPos.y += contentRegionMin.y;
if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)
&& ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
ImGui::SetWindowFocus();
}
if (ImGui::IsWindowHovered(
ImGuiHoveredFlags_AllowWhenBlockedByPopup |
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) &&
ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
ImGui::SetWindowFocus();
}
viewport_isActive = ImGui::IsWindowFocused();
ImVec2 windowSize = ImGui::GetContentRegionAvail();
viewport_isActive = ImGui::IsWindowFocused();
ImVec2 windowSize = ImGui::GetContentRegionAvail();
if (m_lastWindowSize != *(glm::vec2*)&windowSize) {
m_lastWindowSize = { windowSize.x, windowSize.y };
m_frameBuffer->resize(windowSize.x, windowSize.y);
viewport_sceneCamera.camera.aspect = (float)windowSize.x / (float)windowSize.y;
}
if (m_lastWindowSize != *(glm::vec2*)&windowSize) {
m_lastWindowSize = {windowSize.x, windowSize.y};
m_frameBuffer->resize(windowSize.x, windowSize.y);
viewport_sceneCamera.camera.aspect =
(float)windowSize.x / (float)windowSize.y;
}
m_frameBuffer->bind();
m_frameBuffer->clear();
int clearData = -1;
m_frameBuffer->clearBuffer(1, &clearData);
unsigned char clearColor[4]{ 15, 10, 10, 255 };
m_frameBuffer->clearBuffer(0, &clearColor);
m_frameBuffer->bind();
m_frameBuffer->clear();
int clearData = -1;
m_frameBuffer->clearBuffer(1, &clearData);
unsigned char clearColor[4]{15, 10, 10, 255};
m_frameBuffer->clearBuffer(0, &clearColor);
ImVec2 mPos = ImGui::GetMousePos();
ImVec2 mPos = ImGui::GetMousePos();
viewport_relativeXMouse = (mPos.x - wPos.x) / windowSize.x;
viewport_relativeYMouse = 1 - (mPos.y - wPos.y) / windowSize.y;
viewport_relativeXMouse = (mPos.x - wPos.x) / windowSize.x;
viewport_relativeYMouse = 1 - (mPos.y - wPos.y) / windowSize.y;
Project::m_scene.render(viewport_sceneCamera);
Project::m_scene.render(viewport_sceneCamera);
ImGui::Image((void*)(uint64_t)m_frameBuffer->getTextureBufferID(0), windowSize, ImVec2(0, 1), ImVec2(1, 0));
bool isUsingDrawGizmo = drawGizmos(wPos.x, wPos.y, windowSize.x, windowSize.y);
ImGui::Image((void*)(uint64_t)m_frameBuffer->getTextureBufferID(0),
windowSize, ImVec2(0, 1), ImVec2(1, 0));
bool isUsingDrawGizmo =
drawGizmos(wPos.x, wPos.y, windowSize.x, windowSize.y);
if (!isUsingDrawGizmo && m_handleClick) {
int relativeX, relativeY;
if (!isUsingDrawGizmo && m_handleClick) {
int relativeX, relativeY;
ImVec2 mPos = ImGui::GetMousePos();
relativeX = mPos.x - wPos.x;
relativeY = windowSize.y - (mPos.y - wPos.y);
ImVec2 mPos = ImGui::GetMousePos();
relativeX = mPos.x - wPos.x;
relativeY = windowSize.y - (mPos.y - wPos.y);
if (relativeX >= 0 && relativeX < windowSize.x &&
relativeY >= 0 && relativeY < windowSize.y) {
if (relativeX >= 0 && relativeX < windowSize.x && relativeY >= 0 &&
relativeY < windowSize.y) {
int id = m_frameBuffer->getTextureBufferPixel(1, relativeX,
relativeY);
int id = m_frameBuffer->getTextureBufferPixel(1, relativeX, relativeY);
if (!(Input::isKeyPressed(DEER_KEY_LEFT_CONTROL) ||
Input::isKeyPressed(DEER_KEY_LEFT_ALT)))
ActiveEntity::clear();
if (!(Input::isKeyPressed(DEER_KEY_LEFT_CONTROL) || Input::isKeyPressed(DEER_KEY_LEFT_ALT)))
ActiveEntity::clear();
if (id >= 0) {
Entity& selectedEntity =
Project::m_scene.getMainEnviroment().getEntity(
(uint32_t)id);
ActiveEntity::addEntity(selectedEntity);
}
}
}
if (id >= 0) {
Entity& selectedEntity = Project::m_scene.getMainEnviroment()->getEntity((uint32_t)id);
ActiveEntity::addEntity(selectedEntity);
}
}
}
m_handleClick = false;
m_handleClick = false;
m_frameBuffer->unbind();
ImGui::End();
ImGui::PopStyleVar();
}
m_frameBuffer->unbind();
ImGui::End();
ImGui::PopStyleVar();
}
void processMovment() {
if (!viewport_isActive) return;
void processMovment() {
if (!viewport_isActive)
return;
if (!Input::isKeyPressed(DEER_KEY_LEFT_CONTROL)) {
float vel = 1.5f;
if (Input::isKeyPressed(DEER_KEY_LEFT_SHIFT)) vel = 8;
if (Input::isKeyPressed(DEER_KEY_LEFT_ALT)) vel = 1.0f;
if (!Input::isKeyPressed(DEER_KEY_LEFT_CONTROL)) {
if (Input::isKeyPressed(DEER_KEY_W))
viewport_sceneCamera.transform.position +=
viewport_sceneCamera.transform.rotation *
glm::vec3(0, 0, 1) * 0.02f * vel;
float vel = 1.5f;
if (Input::isKeyPressed(DEER_KEY_LEFT_SHIFT))
vel = 8;
if (Input::isKeyPressed(DEER_KEY_LEFT_ALT))
vel = 1.0f;
if (Input::isKeyPressed(DEER_KEY_S))
viewport_sceneCamera.transform.position +=
viewport_sceneCamera.transform.rotation *
glm::vec3(0, 0, -1) * 0.02f * vel;
if (Input::isKeyPressed(DEER_KEY_W))
viewport_sceneCamera.transform.position += viewport_sceneCamera.transform.rotation * glm::vec3(0, 0, 1) * 0.02f * vel;
if (Input::isKeyPressed(DEER_KEY_D))
viewport_sceneCamera.transform.position +=
viewport_sceneCamera.transform.rotation *
glm::vec3(1, 0, 0) * 0.02f * vel;
if (Input::isKeyPressed(DEER_KEY_S))
viewport_sceneCamera.transform.position += viewport_sceneCamera.transform.rotation * glm::vec3(0, 0, -1) * 0.02f * vel;
if (Input::isKeyPressed(DEER_KEY_A))
viewport_sceneCamera.transform.position +=
viewport_sceneCamera.transform.rotation *
glm::vec3(-1, 0, 0) * 0.02f * vel;
if (Input::isKeyPressed(DEER_KEY_D))
viewport_sceneCamera.transform.position += viewport_sceneCamera.transform.rotation * glm::vec3(1, 0, 0) * 0.02f * vel;
if (Input::isKeyPressed(DEER_KEY_SPACE))
viewport_sceneCamera.transform.position.y += 0.02f;
}
if (Input::isKeyPressed(DEER_KEY_A))
viewport_sceneCamera.transform.position += viewport_sceneCamera.transform.rotation * glm::vec3(-1, 0, 0) * 0.02f * vel;
if (Input::isMouseButtonPressed(DEER_MOUSE_BUTTON_2)) {
float posX, posY;
Input::getMousePos(posX, posY);
glm::vec2 newMousePos = glm::vec2(posX, posY);
if (Input::isKeyPressed(DEER_KEY_SPACE))
viewport_sceneCamera.transform.position.y += 0.02f;
if (m_lastMousePressedButton1) {
glm::vec2 mouseDiff = newMousePos - m_lastMousePos;
}
glm::quat pitchQuat = glm::angleAxis(
mouseDiff.y * m_sensitivity, glm::vec3(1, 0, 0));
glm::quat yawQuat = glm::angleAxis(mouseDiff.x * m_sensitivity,
glm::vec3(0, 1, 0));
if (Input::isMouseButtonPressed(DEER_MOUSE_BUTTON_2)) {
float posX, posY;
Input::getMousePos(posX, posY);
glm::vec2 newMousePos = glm::vec2(posX, posY);
viewport_sceneCamera.transform.rotation =
yawQuat * viewport_sceneCamera.transform.rotation *
pitchQuat;
}
if (m_lastMousePressedButton1) {
glm::vec2 mouseDiff = newMousePos - m_lastMousePos;
m_lastMousePos = newMousePos;
m_lastMousePressedButton1 = true;
} else
m_lastMousePressedButton1 = false;
}
glm::quat pitchQuat = glm::angleAxis(mouseDiff.y * m_sensitivity, glm::vec3(1, 0, 0));
glm::quat yawQuat = glm::angleAxis(mouseDiff.x * m_sensitivity, glm::vec3(0, 1, 0));
bool drawGizmos(int wPosX, int wPosY, int wSizeX, int wSizeY) {
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
viewport_sceneCamera.transform.rotation = yawQuat * viewport_sceneCamera.transform.rotation * pitchQuat;
}
glm::mat4 camMatrix =
glm::inverse(viewport_sceneCamera.transform.getMatrix());
glm::mat4 projectionMatrix =
viewport_sceneCamera.camera.getMatrix() *
glm::scale(glm::mat4(1.0f), glm::vec3(1, 1, -1));
m_lastMousePos = newMousePos;
m_lastMousePressedButton1 = true;
}
else
m_lastMousePressedButton1 = false;
}
ImGuizmo::SetRect(wPosX, wPosY, wSizeX, wSizeY);
if (ActiveEntity::count() != 0) {
Entity& currentEntity = ActiveEntity::getEntity(0);
bool drawGizmos(int wPosX, int wPosY, int wSizeX, int wSizeY) {
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
glm::mat4 entity_matrix = currentEntity.getWorldMatrix();
glm::mat4 camMatrix = glm::inverse(viewport_sceneCamera.transform.getMatrix());
glm::mat4 projectionMatrix = viewport_sceneCamera.camera.getMatrix() * glm::scale(glm::mat4(1.0f), glm::vec3(1, 1, -1));
ImGuizmo::OPERATION operations;
ImGuizmo::SetRect(wPosX, wPosY, wSizeX, wSizeY);
if (ActiveEntity::count() != 0) {
ImGuizmo::Manipulate(
glm::value_ptr(camMatrix), glm::value_ptr(projectionMatrix),
(ImGuizmo::OPERATION)m_transformMode, ImGuizmo::MODE::LOCAL,
glm::value_ptr(entity_matrix));
Entity& currentEntity = ActiveEntity::getEntity(0);
if (ImGuizmo::IsUsing()) {
glm::mat4 parentMatrix =
currentEntity.getParent().getWorldMatrix();
glm::mat4 relativeMatrix =
glm::inverse(parentMatrix) * entity_matrix;
glm::mat4 entity_matrix = currentEntity.getWorldMatrix();
glm::vec3 skew;
glm::vec4 perspective;
ImGuizmo::OPERATION operations;
TransformComponent& t =
currentEntity.getComponent<TransformComponent>();
glm::decompose(relativeMatrix, t.scale, t.rotation, t.position,
skew, perspective);
ImGuizmo::Manipulate(glm::value_ptr(camMatrix), glm::value_ptr(projectionMatrix), (ImGuizmo::OPERATION)m_transformMode,
ImGuizmo::MODE::LOCAL, glm::value_ptr(entity_matrix));
return true;
}
}
if (ImGuizmo::IsUsing()) {
glm::mat4 parentMatrix = currentEntity.getParent().getWorldMatrix();
glm::mat4 relativeMatrix = glm::inverse(parentMatrix) * entity_matrix;
return false;
}
glm::vec3 skew;
glm::vec4 perspective;
void viewport_onEvent(Event& e) {
EventDispatcher dispatcher(e);
TransformComponent& t = currentEntity.getComponent<TransformComponent>();
glm::decompose(relativeMatrix, t.scale, t.rotation, t.position, skew, perspective);
dispatcher.dispatch<MouseButtonPressedEvent>(
Deer::viewport_onClickEvent);
dispatcher.dispatch<KeyPressedEvent>(Deer::viewport_onKeyEvent);
}
bool viewport_onClickEvent(MouseButtonPressedEvent mouseEvent) {
if (!viewport_isActive) return false;
return true;
}
}
if (mouseEvent.getMouseButton() == DEER_MOUSE_BUTTON_1)
m_handleClick = true;
return false;
}
return false;
}
bool viewport_onKeyEvent(KeyPressedEvent keyEvent) {
if (!viewport_isActive) return false;
void viewport_onEvent(Event& e) {
EventDispatcher dispatcher(e);
if (Input::isKeyPressed(DEER_KEY_T))
m_transformMode = TransformMode::Translate;
if (Input::isKeyPressed(DEER_KEY_R))
m_transformMode = TransformMode::Rotate;
if (Input::isKeyPressed(DEER_KEY_G))
m_transformMode = TransformMode::Scale;
dispatcher.dispatch<MouseButtonPressedEvent>(Deer::viewport_onClickEvent);
dispatcher.dispatch<KeyPressedEvent>(Deer::viewport_onKeyEvent);
}
bool viewport_onClickEvent(MouseButtonPressedEvent mouseEvent) {
if (!viewport_isActive)
return false;
if (Input::isKeyPressed(DEER_KEY_D) &&
Input::isKeyPressed(DEER_KEY_LEFT_CONTROL)) {
if (ActiveEntity::count() > 0)
ActiveEntity::getEntity(0).duplicate();
}
if (mouseEvent.getMouseButton() == DEER_MOUSE_BUTTON_1)
m_handleClick = true;
return false;
}
bool viewport_onKeyEvent(KeyPressedEvent keyEvent) {
if (!viewport_isActive)
return false;
if (Input::isKeyPressed(DEER_KEY_T))
m_transformMode = TransformMode::Translate;
if (Input::isKeyPressed(DEER_KEY_R))
m_transformMode = TransformMode::Rotate;
if (Input::isKeyPressed(DEER_KEY_G))
m_transformMode = TransformMode::Scale;
if (Input::isKeyPressed(DEER_KEY_D) && Input::isKeyPressed(DEER_KEY_LEFT_CONTROL)) {
if (ActiveEntity::count() > 0)
ActiveEntity::getEntity(0).duplicate();
}
return false;
}
}
return false;
}
} // namespace Deer

View File

@ -9,19 +9,20 @@ Size=400,400
Collapsed=0
[Window][Properties]
Pos=724,240
Size=569,648
Pos=2152,24
Size=408,1347
Collapsed=0
DockId=0x00000004,1
[Window][Game Window]
Pos=0,24
Size=2150,1347
Pos=526,24
Size=1624,1347
Collapsed=0
DockId=0x00000006,1
[Window][Tree Pannel]
Pos=0,24
Size=323,903
Size=524,1347
Collapsed=0
DockId=0x00000005,0
@ -32,8 +33,8 @@ Collapsed=0
DockId=0x00000004,0
[Window][Viewport]
Pos=0,24
Size=2150,1347
Pos=526,24
Size=1624,1347
Collapsed=0
DockId=0x00000006,0
@ -47,8 +48,8 @@ DockId=0x00000002,0
DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,24 Size=2560,1347 Split=Y
DockNode ID=0x00000001 Parent=0xA1672E74 SizeRef=2560,903 Split=X Selected=0x13926F0B
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=2150,779 Split=X Selected=0x13926F0B
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=323,779 Selected=0xBD1B42A3
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=1599,779 CentralNode=1 Selected=0x13926F0B
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=524,779 Selected=0xBD1B42A3
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=1624,779 CentralNode=1 Selected=0x13926F0B
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=408,779 Selected=0x2A2C795E
DockNode ID=0x00000002 Parent=0xA1672E74 SizeRef=2560,442 Selected=0xCF339702