diff options
-rw-r--r-- | entityx/tags/TagsComponent.cc | 11 | ||||
-rw-r--r-- | entityx/tags/TagsComponent.h | 68 | ||||
-rw-r--r-- | entityx/tags/TagsComponent_test.cc | 56 |
3 files changed, 135 insertions, 0 deletions
diff --git a/entityx/tags/TagsComponent.cc b/entityx/tags/TagsComponent.cc new file mode 100644 index 0000000..0906d83 --- /dev/null +++ b/entityx/tags/TagsComponent.cc @@ -0,0 +1,11 @@ +/** + * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> + * All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. + * + * Author: Alec Thomas <alec@swapoff.org> + */ + +#include "entityx/tags/TagsComponent.h" diff --git a/entityx/tags/TagsComponent.h b/entityx/tags/TagsComponent.h new file mode 100644 index 0000000..d7151f9 --- /dev/null +++ b/entityx/tags/TagsComponent.h @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> + * All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. + * + * Author: Alec Thomas <alec@swapoff.org> + */ + +#pragma once + +#include <string> +#include <boost/unordered_set.hpp> +#include "entityx/Entity.h" + +namespace entityx { +namespace tags { + +/** + * Allow entities to be tagged with strings. + */ +class TagsComponent : public Component<TagsComponent> { + struct TagsPredicate { + TagsPredicate(const std::string &tag) : tag(tag) {} + + bool operator () (EntityManager &manager, Entity::Id id) { + auto tags = manager.component<TagsComponent>(id); + return tags != nullptr && tags->tags.find(tag) != tags->tags.end(); + } + + std::string tag; + }; + + public: + /** + * Construct a new TagsComponent with the given tags. + * + * eg. TagsComponent tags("a", "b", "c"); + */ + template <typename ... Args> + TagsComponent(const std::string &tag, const Args & ... tags) { + set_tags(tag, tags ...); + } + + /** + * Filter the provided view to only those entities with the given tag. + */ + static EntityManager::View view(const EntityManager::View &view, const std::string &tag) { + return EntityManager::View(view, TagsPredicate(tag)); + } + + boost::unordered_set<std::string> tags; + + private: + template <typename ... Args> + void set_tags(const std::string &tag1, const std::string &tag2, const Args & ... tags) { + this->tags.insert(tag1); + set_tags(tag2, tags ...); + } + + void set_tags(const std::string &tag) { + tags.insert(tag); + } +}; + +} +} diff --git a/entityx/tags/TagsComponent_test.cc b/entityx/tags/TagsComponent_test.cc new file mode 100644 index 0000000..a100812 --- /dev/null +++ b/entityx/tags/TagsComponent_test.cc @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> + * All rights reserved. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. + * + * Author: Alec Thomas <alec@swapoff.org> + */ + +#include <gtest/gtest.h> +#include "entityx/tags/TagsComponent.h" + +using namespace std; +using namespace boost; +using namespace entityx; +using namespace entityx::tags; + + +struct Position : public Component<Position> {}; + + +template <typename T> +int size(const T &t) { + int n = 0; + for (auto i : t) { + ++n; + (void)i; // Unused on purpose, suppress warning + } + return n; +} + + +TEST(TagsComponentTest, TestVariadicConstruction) { + auto tags = TagsComponent("player", "indestructible"); + unordered_set<string> expected; + expected.insert("player"); + expected.insert("indestructible"); + ASSERT_TRUE(expected == tags.tags); +} + +TEST(TagsComponentTest, TestEntitiesWithTag) { + EventManager ev; + EntityManager en(ev); + Entity a = en.create(); + a.assign<Position>(); + for (int i = 0; i < 99; ++i) { + auto e = en.create(); + e.assign<Position>(); + e.assign<TagsComponent>("positionable"); + } + a.assign<TagsComponent>("player", "indestructible"); + auto entities = en.entities_with_components<Position>(); + ASSERT_EQ(100, size(entities)); + ASSERT_EQ(1, size(TagsComponent::view(entities, "player"))); +} |