Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions engine/includes/components/component.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class ENGINE_EXPORT Component : public Object {

TString tr(const TString &source);

void addTag(const TString &tag);
void removeTag(const TString &tag);

virtual void composeComponent();

virtual void drawGizmos();
Expand All @@ -68,6 +71,13 @@ class ENGINE_EXPORT Component : public Object {
virtual void onReferenceDestroyed();

private:
void changeScene(Scene *current, Scene *changed);

private:
friend class Actor;

std::vector<uint32_t> m_tags;

bool m_enable;

};
Expand Down
17 changes: 16 additions & 1 deletion engine/includes/components/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,36 @@ class ENGINE_EXPORT Scene : public Object {
A_NOPROPERTIES()
A_METHODS(
A_METHOD(Object *, Scene::find),
A_METHOD(World *, Scene::world)
A_METHOD(World *, Scene::world),
A_METHOD(void, Scene::addToGroup),
A_METHOD(void, Scene::removeFromGroup)
)

public:
Scene();
Scene(const Scene &origin);

World *world() const;

void addToGroup(Object *object, const TString &group);
void addToGroupByHash(Object *object, uint32_t hash);

void removeFromGroup(Object *object, const TString &group);
void removeFromGroupByHash(Object *object, uint32_t hash);

ObjectList &getObjectsInGroup(const TString &group);
ObjectList &getObjectsInGroupByHash(uint32_t hash);

Map *map() const;
void setMap(Map *map);

bool isModified() const;
void setModified(bool flag);

private:
std::mutex m_mutex;
std::unordered_map<uint32_t, Object::ObjectList> m_groups;

mutable Map *m_map;

bool m_modified;
Expand Down
4 changes: 4 additions & 0 deletions engine/includes/components/world.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class ENGINE_EXPORT World : public Object {

void setRayCastHandler(RayCastCallback callback, System *system);

std::list<Scene *> &scenes();

public: // signals
void sceneLoaded();
void sceneUnloaded();
Expand All @@ -60,6 +62,8 @@ class ENGINE_EXPORT World : public Object {
void addChild(Object *child, int32_t position = -1) override;

private:
std::list<Scene *> m_scenes;

RayCastCallback m_rayCastCallback;
System *m_rayCastSystem;

Expand Down
11 changes: 8 additions & 3 deletions engine/src/components/actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,21 @@ void Actor::setHierarchyEnabled(bool enabled) {
*/
void Actor::setScene(Scene *scene) {
if(m_scene != scene) {
m_scene = scene;
if(m_scene && m_scene->world()) {
m_scene->world()->graphUpdated();
if(scene && scene->world()) {
scene->world()->graphUpdated();
}
for(auto it : getChildren()) {
Actor *child = dynamic_cast<Actor *>(it);
if(child) {
child->setScene(scene);
} else {
Component *component = dynamic_cast<Component *>(it);
if(component) {
component->changeScene(m_scene, scene);
}
}
}
m_scene = scene;
}
}

Expand Down
59 changes: 54 additions & 5 deletions engine/src/components/component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include "system.h"

#include <algorithm>

namespace {
const char *gResource("Resource");
};
Expand Down Expand Up @@ -41,7 +43,11 @@ Actor *Component::actor() const {
Returns a Scene which the Component is attached to.
*/
Scene *Component::scene() const {
return actor()->scene();
Actor *actor = Component::actor();
if(actor) {
return actor->scene();
}
return nullptr;
}
/*!
Returns a World which the Component is attached to.
Expand Down Expand Up @@ -80,9 +86,9 @@ bool Component::isEnabledInHierarchy() const {
Returns a transform attached to this Actor.
*/
Transform *Component::transform() const {
Actor *act = actor();
if(act) {
return act->transform();
Actor *actor = Component::actor();
if(actor) {
return actor->transform();
}
return nullptr;
}
Expand Down Expand Up @@ -112,11 +118,41 @@ Actor *Component::instantiate(Prefab *prefab, Vector3 position, Quaternion rotat
return result;
}
/*!
Returns a translated version of \a source text; otherwise returns source text if no appropriate translated std::string is available.
Returns a translated version of \a source text; otherwise returns source text if no appropriate translated string is available.
*/
TString Component::tr(const TString &source) {
return Engine::translate(source);
}
/*!
Adds a \a tag for current component.
Automatically adds component to specific Scene group.
*/
void Component::addTag(const TString &tag) {
uint32_t hash = Mathf::hashString(tag);
auto it = std::find(m_tags.begin(), m_tags.end(), hash);
if(it == m_tags.end()) {
Scene *scene = Component::scene();
if(scene) {
scene->addToGroupByHash(this, hash);
}
}
}
/*!
Removes a \a tag for current component.
Automatically removes component from specific Scene group.
*/
void Component::removeTag(const TString &tag) {
uint32_t hash = Mathf::hashString(tag);
auto it = std::find(m_tags.begin(), m_tags.end(), hash);
if(it != m_tags.end()) {
m_tags.erase(it);

Scene *scene = Component::scene();
if(scene) {
scene->removeFromGroupByHash(this, hash);
}
}
}
/*!
\internal
*/
Expand Down Expand Up @@ -285,6 +321,19 @@ VariantMap Component::saveUserData() const {
}
return result;
}
/*!
This method will be called automatically when \a current scene will be \a changed to a new one.
*/
void Component::changeScene(Scene *current, Scene *changed) {
for(auto it : m_tags) {
if(current) {
current->removeFromGroupByHash(this, it);
}
if(current) {
changed->addToGroupByHash(this, it);
}
}
}
/*!
\internal
*/
Expand Down
52 changes: 52 additions & 0 deletions engine/src/components/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,65 @@ Scene::Scene() :
m_map(nullptr),
m_modified(false) {

}

Scene::Scene(const Scene &origin) :
m_groups(origin.m_groups),
m_map(origin.m_map),
m_modified(origin.m_modified) {

}
/*!
Returns the World to which the scene belongs.
*/
World *Scene::world() const {
return static_cast<World *>(parent());
}
/*!
Adds \a object to \a group.
*/
void Scene::addToGroup(Object *object, const TString &group) {
addToGroupByHash(object, static_cast<uint32_t>(Mathf::hashString(group)));
}
/*!
Adds \a object to a group with specific \a hash.
*/
void Scene::addToGroupByHash(Object *object, uint32_t hash) {
std::lock_guard<std::mutex> lock(m_mutex);

m_groups[hash].push_back(object);
}
/*!
Removes \a object from \a group.
*/
void Scene::removeFromGroup(Object *object, const TString &group) {
removeFromGroupByHash(object, static_cast<uint32_t>(Mathf::hashString(group)));
}
/*!
Removes \a object from a group with specific \a hash.
*/
void Scene::removeFromGroupByHash(Object *object, uint32_t hash) {
std::lock_guard<std::mutex> lock(m_mutex);

auto it = m_groups.find(hash);
if(it != m_groups.end()) {
it->second.remove(object);
}
}
/*!
Returns a list of objects in \a group.
*/
Object::ObjectList &Scene::getObjectsInGroup(const TString &group) {
return getObjectsInGroupByHash(static_cast<uint32_t>(Mathf::hashString(group)));
}
/*!
Returns a list of objects from a group with specific \a hash.
*/
Object::ObjectList &Scene::getObjectsInGroupByHash(uint32_t hash) {
std::lock_guard<std::mutex> lock(m_mutex);

return m_groups[hash];
}
/*!
\internal
*/
Expand Down
54 changes: 33 additions & 21 deletions engine/src/components/world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "components/scene.h"
#include "resources/map.h"

#include <algorithm>

/*!
\class World
\brief A root object in the scene graph hierarchy.
Expand Down Expand Up @@ -40,7 +42,9 @@ void World::setActive(bool flag) {
Create an empty new Scene at runtime with the given \a name.
*/
Scene *World::createScene(const TString &name) {
return Engine::objectCreate<Scene>(name, this);
Scene *result = Engine::objectCreate<Scene>(name, this);
m_scenes.push_back(result);
return result;
}
/*!
Loads the scene stored in the .map files by the it's \a path.
Expand All @@ -54,13 +58,14 @@ Scene *World::loadScene(const TString &path, bool additive) {
if(additive) {
scene->setParent(this);
} else {
for(auto it : getChildren()) {
for(auto it : m_scenes) {
if(it != scene) {
unloadScene(dynamic_cast<Scene *>(it));
unloadScene(it);
}
}
scene->setParent(this);
}
m_scenes.push_back(scene);
sceneLoaded();
return scene;
}
Expand All @@ -73,17 +78,15 @@ Scene *World::loadScene(const TString &path, bool additive) {
void World::unloadScene(Scene *scene) {
Map *map = scene->map();
if(map) {
m_scenes.remove(scene);
scene->setParent(map);
Engine::unloadResource(map);

sceneUnloaded();
if(m_activeScene == scene) {
Scene *newScene = nullptr;
for(auto it : getChildren()) {
newScene = dynamic_cast<Scene *>(it);
if(newScene != nullptr) {
break;
}
if(!m_scenes.empty()) {
newScene = m_scenes.front();
}
setActiveScene(newScene);
}
Expand All @@ -93,19 +96,14 @@ void World::unloadScene(Scene *scene) {
Unloads all from the World.
*/
void World::unloadAll() {
Object::ObjectList copyList(getChildren());
for(auto it : copyList) {
Scene *scene = dynamic_cast<Scene *>(it);
if(scene) {
Map *map = scene->map();
if(map) {
scene->setParent(map);
Engine::unloadResource(map);
}
} else {
delete it;
for(auto it : m_scenes) {
Map *map = it->map();
if(map) {
it->setParent(map);
Engine::unloadResource(map);
}
}
m_scenes.clear();
setActiveScene(nullptr);
}
/*!
Expand Down Expand Up @@ -162,6 +160,12 @@ void World::setRayCastHandler(RayCastCallback callback, System *system) {
m_rayCastCallback = callback;
m_rayCastSystem = system;
}
/*!
Returns list of all scenes.
*/
std::list<Scene *> &World::scenes() {
return m_scenes;
}
/*!
Emmits signal when scene has been loaded.
*/
Expand Down Expand Up @@ -191,8 +195,16 @@ void World::graphUpdated() {
*/
void World::addChild(Object *child, int32_t position) {
Object::addChild(child, position);
if(m_activeScene == nullptr && dynamic_cast<Scene *>(child)) {
setActiveScene(static_cast<Scene *>(child));

Scene *scene = dynamic_cast<Scene *>(child);
if(scene) {
auto it = std::find(m_scenes.begin(), m_scenes.end(), scene);
if(it != m_scenes.end()) {
m_scenes.push_back(scene);
}
}
if(m_activeScene == nullptr && scene) {
setActiveScene(scene);
}
}

Loading