diff --git a/CopiumEngine/CopiumEngine.vcxproj b/CopiumEngine/CopiumEngine.vcxproj
index f0a2c9d..08bf85e 100644
--- a/CopiumEngine/CopiumEngine.vcxproj
+++ b/CopiumEngine/CopiumEngine.vcxproj
@@ -180,6 +180,7 @@
+
@@ -213,6 +214,7 @@
+
@@ -249,6 +251,7 @@
+
@@ -280,6 +283,9 @@
+
+
+
@@ -302,6 +308,7 @@
+
diff --git a/CopiumEngine/CopiumEngine.vcxproj.filters b/CopiumEngine/CopiumEngine.vcxproj.filters
index f6736cb..76a1787 100644
--- a/CopiumEngine/CopiumEngine.vcxproj.filters
+++ b/CopiumEngine/CopiumEngine.vcxproj.filters
@@ -219,6 +219,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -485,5 +491,20 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/CopiumEngine/src/copium/asset/AssetRef.cpp b/CopiumEngine/src/copium/asset/AssetRef.cpp
index 9842da7..8fea83a 100644
--- a/CopiumEngine/src/copium/asset/AssetRef.cpp
+++ b/CopiumEngine/src/copium/asset/AssetRef.cpp
@@ -5,51 +5,17 @@
namespace Copium
{
AssetRef::AssetRef(AssetHandle handle)
- : handle{handle}, refCounter{new int{1}}
+ : handle{handle}
{}
AssetRef::~AssetRef()
{
- if (refCounter == nullptr)
- return;
-
- (*refCounter)--;
- if (*refCounter == 0)
+ if (refCounter.LastRef())
{
AssetManager::UnloadAsset(handle);
- delete refCounter;
}
}
- AssetRef::AssetRef(const AssetRef& other)
- : handle{other.handle}, refCounter{other.refCounter}
- {
- (*refCounter)++;
- }
-
- AssetRef::AssetRef(AssetRef&& other)
- : handle{other.handle}, refCounter{other.refCounter}
- {
- other.refCounter = nullptr;
- }
-
- AssetRef& AssetRef::operator=(const AssetRef& rhs)
- {
- handle = rhs.handle;
- refCounter = rhs.refCounter;
-
- (*refCounter)++;
- return *this;
- }
-
- AssetRef& AssetRef::operator=(AssetRef&& rhs)
- {
- handle = rhs.handle;
- refCounter = rhs.refCounter;
- rhs.refCounter = nullptr;
- return *this;
- }
-
AssetRef::operator AssetHandle() const
{
return handle;
diff --git a/CopiumEngine/src/copium/asset/AssetRef.h b/CopiumEngine/src/copium/asset/AssetRef.h
index 2885265..3cf4dea 100644
--- a/CopiumEngine/src/copium/asset/AssetRef.h
+++ b/CopiumEngine/src/copium/asset/AssetRef.h
@@ -1,6 +1,7 @@
#pragma once
#include "copium/asset/AssetMeta.h"
+#include "copium/util/RefCounter.h"
namespace Copium
{
@@ -8,18 +9,12 @@ namespace Copium
{
private:
AssetHandle handle;
- int* refCounter;
+ RefCounter refCounter;
public:
AssetRef(AssetHandle handle);
~AssetRef();
- AssetRef(const AssetRef& other);
- AssetRef(AssetRef&& other);
-
- AssetRef& operator=(const AssetRef& rhs);
- AssetRef& operator=(AssetRef&& rhs);
-
operator AssetHandle() const;
};
diff --git a/CopiumEngine/src/copium/core/Application.cpp b/CopiumEngine/src/copium/core/Application.cpp
index ae13e4c..f527d3a 100644
--- a/CopiumEngine/src/copium/core/Application.cpp
+++ b/CopiumEngine/src/copium/core/Application.cpp
@@ -77,7 +77,7 @@ namespace Copium
Vulkan::GetSwapChain().SubmitToGraphicsQueue(*commandBuffer);
Vulkan::GetSwapChain().EndPresent();
- return !glfwWindowShouldClose(Vulkan::GetWindow().GetWindow());
+ return !Vulkan::GetWindow().ShouldClose();
}
EventResult Application::OnEvent(const Event& event)
@@ -100,13 +100,6 @@ namespace Copium
return EventResult::Focus;
}
- case EventType::KeyPress:
- {
- const KeyPressEvent& keyPressEvent = static_cast(event);
- CP_INFO("%d", keyPressEvent.GetButton());
-
- return EventResult::Handled;
- }
case EventType::MouseScroll:
{
const MouseScrollEvent& mouseScrollEvent = static_cast(event);
diff --git a/CopiumEngine/src/copium/core/Scene.cpp b/CopiumEngine/src/copium/core/Scene.cpp
index bbaba39..33a87c4 100644
--- a/CopiumEngine/src/copium/core/Scene.cpp
+++ b/CopiumEngine/src/copium/core/Scene.cpp
@@ -7,14 +7,17 @@
#include "copium/ecs/Entity.h"
#include "copium/ecs/System.h"
#include "copium/event/MouseMoveEvent.h"
+#include "copium/example/CameraFollowPlayerSystem.h"
#include "copium/example/CameraUpdateSystem.h"
#include "copium/example/Components.h"
#include "copium/example/FrameCountSystem.h"
+#include "copium/example/HealthChangeSystem.h"
+#include "copium/example/HealthComponentListener.h"
+#include "copium/example/HealthDisplaySystem.h"
#include "copium/example/MouseFollowSystem.h"
-#include "copium/example/RenderSystem.h"
#include "copium/example/PhysicsSystem.h"
#include "copium/example/PlayerControllerSystem.h"
-#include "copium/example/CameraFollowPlayerSystem.h"
+#include "copium/example/RenderSystem.h"
#include
#include
@@ -30,11 +33,14 @@ namespace Copium
ecs->AddSystem();
ecs->AddSystem();
+ ecs->AddSystem();
+ ecs->AddSystem();
ecs->AddSystem();
ecs->AddSystem(&viewMatrix, &projectionMatrix, &invPvMatrix);
ecs->AddSystem(&invPvMatrix);
ecs->AddSystem();
ecs->AddSystem(renderer.get(), descriptorSetRenderer.get(), &commandBuffer, &viewMatrix, &projectionMatrix); // better way to store the RenderSystem data?
+ ecs->SetComponentListener();
// TODO: Load from scene file
for (int y = 0; y < 10; y++)
@@ -72,6 +78,7 @@ namespace Copium
Entity entityPlayer = Entity::Create(ecs.get());
entityPlayer.AddComponent(entityCamera);
+ entityPlayer.AddComponent(10, 10);
entityPlayer.AddComponent(0.1f, glm::vec2{0.0f, 0.0f}, glm::vec2{0.0f, 0.0f});
entityPlayer.AddComponent(glm::vec2{0.0f}, glm::vec2{1.0f});
entityPlayer.AddComponent(AssetRef{AssetManager::LoadAsset("fox2.meta")}, glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 1.0f});
diff --git a/CopiumEngine/src/copium/core/SwapChain.cpp b/CopiumEngine/src/copium/core/SwapChain.cpp
index 5f45b87..b79191f 100644
--- a/CopiumEngine/src/copium/core/SwapChain.cpp
+++ b/CopiumEngine/src/copium/core/SwapChain.cpp
@@ -4,6 +4,8 @@
#include "copium/core/Vulkan.h"
#include "copium/sampler/Image.h"
+#include
+
namespace Copium
{
SwapChainSupportDetails::SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice)
diff --git a/CopiumEngine/src/copium/core/Window.cpp b/CopiumEngine/src/copium/core/Window.cpp
index ef59fa3..e0fcf10 100644
--- a/CopiumEngine/src/copium/core/Window.cpp
+++ b/CopiumEngine/src/copium/core/Window.cpp
@@ -12,6 +12,8 @@
#include "copium/event/WindowResizeEvent.h"
#include "copium/event/WindowFocusEvent.h"
+#include
+
namespace Copium
{
Window::Window(const std::string& windowName, int width, int height, WindowMode mode)
@@ -27,6 +29,22 @@ namespace Copium
glfwDestroyWindow(window);
}
+ bool Window::ShouldClose() const
+ {
+ return glfwWindowShouldClose(window);
+
+ }
+
+ int Window::GetWidth() const
+ {
+ return width;
+ }
+
+ int Window::GetHeight() const
+ {
+ return height;
+ }
+
VkSurfaceKHR Window::GetSurface() const
{
return surface;
diff --git a/CopiumEngine/src/copium/core/Window.h b/CopiumEngine/src/copium/core/Window.h
index e89db90..af90d39 100644
--- a/CopiumEngine/src/copium/core/Window.h
+++ b/CopiumEngine/src/copium/core/Window.h
@@ -3,11 +3,17 @@
#include "copium/util/Common.h"
#include "copium/util/Enum.h"
-#include
+#include
+
+#define CP_WINDOW_MODE_ENUMS \
+ Fullscreen, \
+ BorderlessWindowed, \
+ Windowed
-#define CP_WINDOW_MODE_ENUMS Fullscreen, BorderlessWindowed, Windowed
CP_ENUM_CREATOR(Copium, WindowMode, CP_WINDOW_MODE_ENUMS);
+struct GLFWwindow;
+
namespace Copium
{
class Window final
@@ -24,6 +30,10 @@ namespace Copium
Window(const std::string& windowName, int width, int height, WindowMode mode);
~Window();
+ bool ShouldClose() const;
+
+ int GetWidth() const;
+ int GetHeight() const;
VkSurfaceKHR GetSurface() const;
GLFWwindow* GetWindow();
diff --git a/CopiumEngine/src/copium/ecs/ComponentListener.cpp b/CopiumEngine/src/copium/ecs/ComponentListener.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/CopiumEngine/src/copium/ecs/ComponentListener.h b/CopiumEngine/src/copium/ecs/ComponentListener.h
new file mode 100644
index 0000000..71087df
--- /dev/null
+++ b/CopiumEngine/src/copium/ecs/ComponentListener.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "copium/ecs/ECSManager.h"
+
+namespace Copium
+{
+ template
+ class ComponentListener
+ {
+ public:
+ using component_type = Component;
+ friend class ECSManager;
+ protected:
+ ECSManager* manager;
+ public:
+ virtual void Added(EntityId entityId, Component& component) {}
+ virtual void Removed(EntityId entityId, Component& component) {}
+ };
+}
diff --git a/CopiumEngine/src/copium/ecs/ComponentPool.h b/CopiumEngine/src/copium/ecs/ComponentPool.h
index e250141..40df656 100644
--- a/CopiumEngine/src/copium/ecs/ComponentPool.h
+++ b/CopiumEngine/src/copium/ecs/ComponentPool.h
@@ -3,6 +3,7 @@
#include "copium/ecs/Config.h"
#include "copium/ecs/EntitySet.h"
#include "copium/ecs/ComponentPoolBase.h"
+#include "copium/ecs/ComponentListener.h"
#include
@@ -14,8 +15,18 @@ namespace Copium
using Iterator = typename std::vector::iterator;
private:
std::vector components;
+ ComponentListener* listener = nullptr;
public:
+ ComponentPool()
+ {}
+
+ ~ComponentPool() override
+ {
+ if(listener)
+ delete listener;
+ }
+
ComponentPool(EntityId entity, const Component& component)
{
Emplace(entity, component);
@@ -25,21 +36,27 @@ namespace Copium
{
components.push_back(component);
entities.Emplace(entity);
+ if(listener)
+ listener->Added(entity, components.back());
return components.back();
}
- void Pop()
- {
- components.pop_back();
- entities.Pop();
- }
-
- bool Erase(EntityId entity)
+ bool Erase(EntityId entity) override
{
size_t index = entities.Find(entity);
if (!entities.Erase(entity))
return false;
- components.erase(components.begin() + index);
+ if (listener)
+ {
+ auto it = components.begin() + index;
+ Component component = *it;
+ components.erase(it);
+ listener->Removed(entity, component);
+ }
+ else
+ {
+ components.erase(components.begin() + index);
+ }
return true;
}
@@ -61,13 +78,18 @@ namespace Copium
return nullptr;
}
+ void SetComponentListener(ComponentListener* listener)
+ {
+ ComponentPool::listener = listener;
+ }
+
Component& operator[](size_t index)
{
CP_ASSERT(index < components.size(), "Index Out of Bound Exception");
return components[index];
}
- size_t Size()
+ size_t Size() override
{
return components.size();
}
diff --git a/CopiumEngine/src/copium/ecs/ComponentPoolBase.h b/CopiumEngine/src/copium/ecs/ComponentPoolBase.h
index c73806d..58ffa70 100644
--- a/CopiumEngine/src/copium/ecs/ComponentPoolBase.h
+++ b/CopiumEngine/src/copium/ecs/ComponentPoolBase.h
@@ -15,7 +15,6 @@ namespace Copium
virtual ~ComponentPoolBase() = default;
virtual size_t Size() = 0;
- virtual void Pop() = 0;
virtual bool Erase(EntityId entity) = 0;
std::vector& GetEntities();
const std::vector& GetEntities() const;
diff --git a/CopiumEngine/src/copium/ecs/ECSManager.h b/CopiumEngine/src/copium/ecs/ECSManager.h
index 242abf8..e3cc344 100644
--- a/CopiumEngine/src/copium/ecs/ECSManager.h
+++ b/CopiumEngine/src/copium/ecs/ECSManager.h
@@ -48,6 +48,25 @@ namespace Copium
bool ValidEntity(EntityId entity);
void Each(std::function function);
+ template
+ void SetComponentListener(const Args&... args)
+ {
+ using Component = typename Listener::component_type;
+ auto pool = GetComponentPool();
+ Listener* listener = new Listener{args...};
+ listener->manager = this;
+ if (pool)
+ {
+ pool->SetComponentListener(listener);
+ }
+ else
+ {
+ ComponentPool* pool{new ComponentPool{}};
+ componentPool.emplace(GetComponentId(), pool);
+ pool->SetComponentListener(listener);
+ }
+ }
+
template
std::tuple AddComponents(EntityId entity, Components&&... components)
{
diff --git a/CopiumEngine/src/copium/event/Input.cpp b/CopiumEngine/src/copium/event/Input.cpp
index 8a88c5b..c0d64a1 100644
--- a/CopiumEngine/src/copium/event/Input.cpp
+++ b/CopiumEngine/src/copium/event/Input.cpp
@@ -1,6 +1,9 @@
#include "copium/event/Input.h"
#include "copium/util/Common.h"
+#include "copium/core/Vulkan.h"
+
+#include
namespace Copium
{
@@ -63,6 +66,11 @@ namespace Copium
return mousePos;
}
+ glm::vec2 Input::GetMouseWindowPos()
+ {
+ return glm::vec2{(mousePos.x + 1.0f) * 0.5f * Vulkan::GetWindow().GetWidth(), (1.0f - mousePos.y) * 0.5f * Vulkan::GetWindow().GetHeight()};
+ }
+
void Input::OnKey(int keyCode, bool pressed)
{
CP_ASSERT(keyCode >= 0 && keyCode < MAX_NUM_KEYS, "KeyCode is out of range");
@@ -85,5 +93,6 @@ namespace Copium
void Input::Update()
{
memset(keyEventList, false, sizeof(keyEventList));
+ memset(mouseEventList, false, sizeof(mouseEventList));
}
}
diff --git a/CopiumEngine/src/copium/event/Input.h b/CopiumEngine/src/copium/event/Input.h
index 05b284c..92b7dfd 100644
--- a/CopiumEngine/src/copium/event/Input.h
+++ b/CopiumEngine/src/copium/event/Input.h
@@ -35,6 +35,7 @@ namespace Copium
static bool IsMouseDown(int button);
static bool IsMouseUp(int button);
+ static glm::vec2 GetMouseWindowPos();
static glm::vec2 GetMousePos();
static void OnKey(int keyCode, bool pressed);
diff --git a/CopiumEngine/src/copium/example/Components.h b/CopiumEngine/src/copium/example/Components.h
index 7322a67..a7dab89 100644
--- a/CopiumEngine/src/copium/example/Components.h
+++ b/CopiumEngine/src/copium/example/Components.h
@@ -57,4 +57,13 @@ namespace Copium
{
Entity camera;
};
+
+ struct HealthC
+ {
+ int current;
+ int max;
+
+ Entity background;
+ Entity foreground;
+ };
}
\ No newline at end of file
diff --git a/CopiumEngine/src/copium/example/HealthChangeSystem.h b/CopiumEngine/src/copium/example/HealthChangeSystem.h
new file mode 100644
index 0000000..0de9195
--- /dev/null
+++ b/CopiumEngine/src/copium/example/HealthChangeSystem.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "copium/ecs/System.h"
+#include "copium/example/Components.h"
+#include "copium/event/Input.h"
+
+namespace Copium
+{
+ class HealthChangeSystem : public System
+ {
+
+ void RunEntity(Entity entity, HealthC& health) override
+ {
+ if (Input::IsKeyPressed(CP_KEY_K))
+ health.current++;
+ if (Input::IsKeyPressed(CP_KEY_J))
+ health.current--;
+ health.current = std::clamp(health.current, 0, health.max);
+ }
+ };
+}
diff --git a/CopiumEngine/src/copium/example/HealthComponentListener.h b/CopiumEngine/src/copium/example/HealthComponentListener.h
new file mode 100644
index 0000000..cd64a12
--- /dev/null
+++ b/CopiumEngine/src/copium/example/HealthComponentListener.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "copium/ecs/ComponentListener.h"
+#include "copium/example/Components.h"
+#include "copium/util/Common.h"
+
+namespace Copium
+{
+ class HealthComponentListener : public ComponentListener
+ {
+ void Added(EntityId entityId, HealthC& health) override
+ {
+ CP_ASSERT(!health.background, "Health already has background entity assigned");
+ CP_ASSERT(!health.foreground, "Health already has foreground entity assigned");
+
+ health.background = Entity::Create(manager);
+ health.background.AddComponent(glm::vec2{0.0f, 0.0f}, glm::vec2{1.0f, 0.2f});
+ health.background.AddComponent(glm::vec3{0.9f, 0.2f, 0.2f});
+
+ health.foreground = Entity::Create(manager);
+ health.foreground.AddComponent(glm::vec2{0.0f, 0.0f}, glm::vec2{std::clamp(health.current, 0, health.max) / (float)health.max, 0.2f});
+ health.foreground.AddComponent(glm::vec3{0.2f, 0.9f, 0.2f});
+ }
+
+ void Removed(EntityId entityId, HealthC& health) override
+ {
+ CP_ASSERT(health.background, "Health already removed background entity");
+ CP_ASSERT(health.foreground, "Health already removed foreground entity");
+
+ health.background.Destroy();
+ health.foreground.Destroy();
+ }
+ };
+
+}
diff --git a/CopiumEngine/src/copium/example/HealthDisplaySystem.h b/CopiumEngine/src/copium/example/HealthDisplaySystem.h
new file mode 100644
index 0000000..5785b13
--- /dev/null
+++ b/CopiumEngine/src/copium/example/HealthDisplaySystem.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "copium/ecs/System.h"
+#include "copium/example/Components.h"
+
+
+namespace Copium
+{
+ class HealthDisplaySystem : public System
+ {
+ void RunEntity(Entity entity, HealthC& health, TransformC& transform) override
+ {
+ TransformC& foregroundTransform = health.foreground.GetComponent();
+ foregroundTransform.position = transform.position + glm::vec2{0.0f, transform.size.y * 1.13};
+ foregroundTransform.size = glm::vec2{std::clamp(health.current, 0, health.max) / (float)health.max, 0.2f};
+
+ TransformC& backgroundTransform = health.background.GetComponent();
+ backgroundTransform.position = transform.position + glm::vec2{0.0f, transform.size.y * 1.13};
+ }
+ };
+
+}
\ No newline at end of file
diff --git a/CopiumEngine/src/copium/example/PlayerControllerSystem.h b/CopiumEngine/src/copium/example/PlayerControllerSystem.h
index e8917ec..4ff3235 100644
--- a/CopiumEngine/src/copium/example/PlayerControllerSystem.h
+++ b/CopiumEngine/src/copium/example/PlayerControllerSystem.h
@@ -18,8 +18,19 @@ namespace Copium
if (Input::IsKeyDown(CP_KEY_A)) force.x -= 1.0f;
if (Input::IsKeyDown(CP_KEY_D)) force.x += 1.0f;
- glm::normalize(force);
- physics.force += force * magnitude;
+ if (force.x != 0 || force.y != 0)
+ {
+ force = glm::normalize(force);
+ physics.force += force * magnitude;
+ }
+
+ if (Input::IsKeyPressed(CP_KEY_H))
+ {
+ if (entity.HasComponent())
+ entity.RemoveComponent();
+ else
+ entity.AddComponent(8, 10);
+ }
}
};
}
diff --git a/CopiumEngine/src/copium/main.cpp b/CopiumEngine/src/copium/main.cpp
index a675239..b6ab848 100644
--- a/CopiumEngine/src/copium/main.cpp
+++ b/CopiumEngine/src/copium/main.cpp
@@ -16,10 +16,9 @@ int main(int argc, char** argv)
Copium::Application application;
while (application.Update())
{
- glfwPollEvents();
-
- Copium::EventDispatcher::Dispatch();
Copium::Input::Update();
+ glfwPollEvents();
+ Copium::EventDispatcher::Dispatch();
}
}
Copium::Vulkan::Destroy();
diff --git a/CopiumEngine/src/copium/util/RefCounter.cpp b/CopiumEngine/src/copium/util/RefCounter.cpp
new file mode 100644
index 0000000..9229303
--- /dev/null
+++ b/CopiumEngine/src/copium/util/RefCounter.cpp
@@ -0,0 +1,72 @@
+#include "copium/util/RefCounter.h"
+
+#include "copium/util/Common.h"
+
+namespace Copium
+{
+ RefCounter::RefCounter()
+ : refCounter{new int{1}}
+ {}
+
+ RefCounter::~RefCounter()
+ {
+ if (Valid())
+ {
+ (*refCounter)--;
+ if (*refCounter == 0)
+ {
+ delete refCounter;
+ refCounter = nullptr;
+ }
+ }
+ }
+
+ RefCounter::RefCounter(RefCounter&& rhs)
+ : refCounter(rhs.refCounter)
+ {
+ CP_ASSERT(Valid(), "RefCounter : Moving a deleted RefCounter");
+ rhs.refCounter = nullptr;
+ }
+
+ RefCounter::RefCounter(const RefCounter& rhs)
+ : refCounter{rhs.refCounter}
+ {
+ CP_ASSERT(Valid(), "RefCounter : Copying a deleted RefCounter");
+ (*refCounter)++;
+ }
+
+ RefCounter& RefCounter::operator=(RefCounter&& rhs)
+ {
+ CP_ASSERT(Valid(), "operator= : Moving a deleted RefCounter");
+
+ refCounter = rhs.refCounter;
+ rhs.refCounter = nullptr;
+ return *this;
+ }
+
+ RefCounter& RefCounter::operator=(const RefCounter& rhs)
+ {
+ CP_ASSERT(Valid(), "operator= : Copying a deleted RefCounter");
+
+ refCounter = rhs.refCounter;
+ (*refCounter)++;
+ return *this;
+ }
+
+ bool RefCounter::Valid() const
+ {
+ return refCounter != nullptr;
+ }
+
+ bool RefCounter::LastRef() const
+ {
+ return Valid() && *refCounter == 1;
+ }
+
+ int RefCounter::Counter() const
+ {
+ CP_ASSERT(Valid(), "Counter : referencing a deleted RefCounter");
+
+ return *refCounter;
+ }
+}
diff --git a/CopiumEngine/src/copium/util/RefCounter.h b/CopiumEngine/src/copium/util/RefCounter.h
new file mode 100644
index 0000000..f286c25
--- /dev/null
+++ b/CopiumEngine/src/copium/util/RefCounter.h
@@ -0,0 +1,24 @@
+#pragma once
+
+namespace Copium
+{
+ class RefCounter final
+ {
+ private:
+ int* refCounter;
+
+ public:
+ RefCounter();
+ ~RefCounter();
+
+ RefCounter(RefCounter&& rhs);
+ RefCounter(const RefCounter& rhs);
+
+ RefCounter& operator=(RefCounter&& rhs);
+ RefCounter& operator=(const RefCounter& rhs);
+
+ bool Valid() const;
+ bool LastRef() const;
+ int Counter() const;
+ };
+}