-
Notifications
You must be signed in to change notification settings - Fork 1
/
Hook.hh
180 lines (162 loc) · 3.93 KB
/
Hook.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <imgui/imgui.h>
#include <sstream>
#include <string>
#include "Error.h"
#include "editor/Primary.h"
#include "util/Utility.h"
namespace Editor {
namespace Hook {
// This acts like a unique pointer for gizmos. It will handle freeing the gizmo
// memory when its destructor is called.
struct GizmoStorage
{
std::string mName;
GizmoBase* mGizmo;
GizmoStorage(const std::string& name, GizmoBase* gizmo):
mName(name), mGizmo(gizmo)
{}
GizmoStorage(GizmoStorage&& other):
mName(Util::Move(other.mName)), mGizmo(other.mGizmo)
{}
~GizmoStorage()
{
delete mGizmo;
}
GizmoStorage& operator=(GizmoStorage&& other)
{
delete mGizmo;
mName = Util::Move(other.mName);
mGizmo = other.mGizmo;
return *this;
}
};
extern Ds::Vector<GizmoStorage> nGizmoStore;
constexpr int nInvalidGizmoIndex = -1;
template<typename T>
int FindGizmoIndex()
{
std::string name(Util::GetLastName<T>());
for (int i = 0; i < nGizmoStore.Size(); ++i)
{
if (nGizmoStore[i].mName == name)
{
return i;
}
}
return nInvalidGizmoIndex;
}
template<typename T>
int GetExistingGizmoIndex()
{
int gizmoIndex = FindGizmoIndex<T>();
if (gizmoIndex == nInvalidGizmoIndex)
{
std::string fullName = Util::GetFullName<T>();
std::stringstream error;
error << "A gizmo for " << fullName << " has not been allocated.";
LogAbort(error.str().c_str());
}
return gizmoIndex;
}
template<typename T>
bool ActiveGizmo()
{
return FindGizmoIndex<T>() != nInvalidGizmoIndex;
}
template<typename T>
void StartGizmo()
{
std::string name(Util::GetLastName<T>());
Gizmo<T>* gizmo = alloc Gizmo<T>;
nGizmoStore.Emplace(name, (GizmoBase*)gizmo);
}
template<typename T>
void EndGizmo()
{
int gizmoIndex = GetExistingGizmoIndex<T>();
nGizmoStore.LazyRemove(gizmoIndex);
}
template<typename T>
bool RunGizmo(T* component, const World::Object& object)
{
int gizmoIndex = GetExistingGizmoIndex<T>();
Gizmo<T>* gizmo = (Gizmo<T>*)nGizmoStore[gizmoIndex].mGizmo;
return gizmo->Run(component, object);
}
template<typename T>
T* InspectComponent(const World::Object& object)
{
T* component = object.GetComponent<T>();
if (component == nullptr)
{
return nullptr;
}
std::string name(Util::GetLastName<T>());
if (ImGui::CollapsingHeader(name.c_str()))
{
std::string removeButtonLabel = "Remove " + name;
if (ImGui::Button(removeButtonLabel.c_str(), ImVec2(-1, 0)))
{
object.RemComponent<T>();
return nullptr;
}
Edit<T>(component);
return component;
}
return nullptr;
}
template<typename T>
T* InspectGizmoComponent(const World::Object& object)
{
T* component = InspectComponent<T>(object);
if (component != nullptr)
{
if (!ActiveGizmo<T>())
{
StartGizmo<T>();
}
bool editing = RunGizmo<T>(component, object);
nSuppressObjectPicking |= editing;
} else if (ActiveGizmo<T>())
{
EndGizmo<T>();
}
return component;
}
template<typename T>
void MakeComponentAvailable(const World::Object& object)
{
if (object.HasComponent<T>())
{
return;
}
std::string name(Util::GetLastName<T>());
if (ImGui::Button(name.c_str(), ImVec2(-1, 0)))
{
object.AddComponent<T>();
}
}
template<typename T>
void Edit(T* component)
{
std::string fullName = Util::GetFullName<T>();
std::stringstream error;
error << "There is no Edit<" << fullName << "> function defined.";
LogAbort(error.str().c_str());
}
template<typename T>
Gizmo<T>::Gizmo()
{
std::string fullName = Util::GetFullName<T>();
std::stringstream error;
error << "There is no Gizmo<" << fullName << "> structure defined.";
LogAbort(error.str().c_str());
}
// This function should never be called. By defining it, we can avoid obtuse
// compile and link errors and instead abort when one uses the generic Gizmo
// structure instead of their own specialization.
template<typename T>
bool Gizmo<T>::Run(T* component, const World::Object& object)
{}
} // namespace Hook
} // namespace Editor