Cogs.Core
GuiExtension.cpp
1#include "GuiExtension.h"
2
3#include "Context.h"
4#include "ExtensionRegistry.h"
5#include "Serialization/EntityReader.h"
6#include "Resources/ResourceStore.h"
7#include "Renderer/IRenderer.h"
8#include "Renderer/Tasks/RenderTaskFactory.h"
9#include "Renderer/RenderStateUpdater.h"
10#include "Renderer/InspectorGui/InspectorGuiRenderer.h"
11#include "Renderer/RenderTarget.h"
12
13#include "GuiComponent.h"
14#include "GuiRenderComponent.h"
15#include "GuiManager.h"
16
17#include "GuiSystem.h"
18#include "GuiRenderSystem.h"
19#include "GuiRenderTask.h"
20
21#include "Rendering/IGraphicsDevice.h"
22
23#include "Foundation/HashSequence.h"
24#include "Foundation/Logging/Logger.h"
25
26#if defined( _WIN32 )
27 #define GUI_EXT_API __declspec(dllexport)
28#else
29 #define GUI_EXT_API
30#endif
31
32namespace {
33 using namespace Cogs::Core;
34 Cogs::Logging::Log logger = Cogs::Logging::getLogger("GuiExtension");
35
36 RenderTask * createGuiRenderTask(RenderTaskContext*, const RenderTaskDefinition &, const PipelineOptions &)
37 {
38 return new GuiRenderTask();
39 }
40
41 void destroyGuiRenderTask(RenderTask ** task, RenderTaskContext *)
42 {
43 auto * myTask = dynamic_cast<GuiRenderTask*>(*task);
44 if (myTask) {
45 //myTask->~GuiRenderTask();
46 delete myTask;
47 *task = nullptr;
48 }
49 }
50
51
52 struct GuiRenderer : public IRendererExtension
53 {
54
55 void setupPipelines(const DrawContext * drawContext)
56 {
57 Context * context = drawContext->context;
58 Renderer * renderer = drawContext->renderer;
59 RenderTaskContext * taskContext = drawContext->taskContext;
60 RenderResources & resources = renderer->getRenderResources();
61 GuiRenderSystem * guiRenderSystem = static_cast<GuiRenderSystem*>(context->getExtensionSystem(GuiRenderSystem::getTypeId()));
62 RenderPipelineManager * pipelineManager = renderer->getPipelineManager();
63
64 for (auto & gui : guiRenderSystem->pool) {
65 if (gui.target) {
66 auto it = pipelineManager->instanceByKey(context, Cogs::hashSequence("Gui", reinterpret_cast<intptr_t>(&gui), gui.getGeneration()));
67 auto * instance = it.first;
68
69 if (it.second) {
70 instance->name = "GuiExtension";
71 instance->priority = 300;
72 instance->sanityCheck = &gui;
73 instance->options.push_back({ "Pass", "Offscreen" });
74 LOG_DEBUG(logger, "GuiRenderer added camera pipeline");
75 }
76 else {
77 assert(instance->sanityCheck == &gui);
78 }
79
80 RenderTexture * renderTexture = resources.getRenderTexture(gui.target);
81
82 size_t dataHash = 0;
83 if (renderTexture) {
84 if (!renderTexture->renderTarget) {
85 RenderTexture * depthTexture = resources.createRenderTexture();
86 depthTexture->description.flags = Cogs::TextureFlags::DepthBuffer;
87 depthTexture->description.format = Cogs::TextureFormat::R32_TYPELESS;
88 depthTexture->sizeSource = renderTexture;
89 renderTexture->depthTexture = depthTexture;
90
91 RenderTarget * renderTarget = resources.createRenderTarget();
92 renderTarget->textures.push_back(renderTexture);
93 renderTarget->depth = depthTexture;
94 renderTarget->width = renderTexture->description.width;
95 renderTarget->height = renderTexture->description.height;
96 renderTexture->renderTarget = renderTarget;
97 }
98
99 dataHash = Cogs::hashSequence(reinterpret_cast<intptr_t>(renderTexture),
100 reinterpret_cast<intptr_t>(renderTexture->renderTarget),
101 reinterpret_cast<intptr_t>(renderTexture->depthTexture));
102 }
103
104 if (it.second || instance->dataHash != dataHash) {
105 instance->dataHash = dataHash;
106
108 def.type = "GuiRender";
109
110 PipelineOptions options;
111 std::list<std::unique_ptr<SubContext>> subs;
112 auto guiTask = (GuiRenderTask *)createRenderTask(taskContext, def, subs, pipelineManager->getExpressionContextRoot(), options);
113 instance->pipeline.tasks.push_back(guiTask);
114
115 if (renderTexture) {
116 instance->pipeline.updateResources.add(renderTexture->depthTexture);
117 instance->pipeline.updateResources.add(renderTexture->renderTarget);
118 }
119
120 guiTask->guiRenderComponent = gui.getComponentHandle<GuiRenderComponent>();
121 guiTask->renderTexture = renderTexture;
122 instance->dataHash = dataHash;
123 }
124 }
125 }
126 }
127
128 void renderGuiInstances(const DrawContext * drawContext)
129 {
130 Context * context = drawContext->context;
131 GuiRenderSystem * guiRenderSystem = static_cast<GuiRenderSystem*>(context->getExtensionSystem(GuiRenderSystem::getTypeId()));
132 Renderer * renderer = drawContext->renderer;
133 InspectorGuiRenderer * inspectorGuiRenderer = renderer->getInspectorGuiRenderer();
134
135 for (auto & gui : guiRenderSystem->pool) {
136 if (!gui.target) {
137 GuiRenderTask guiRenderTask;
138 inspectorGuiRenderer->beginRender(context, renderer);
139 guiRenderTask.guiRenderComponent = gui.getComponentHandle<GuiRenderComponent>();
140
141 guiRenderTask.apply(drawContext->taskContext);
142
143 inspectorGuiRenderer->endRender(context, renderer);
144 }
145 }
146 }
147
148
149 void initialize(Context * /*context*/, Cogs::IGraphicsDevice * /*device*/) override
150 {
151 }
152
153 void handleEvent(uint32_t eventId, const DrawContext * drawContext) override
154 {
155 switch (eventId) {
157 setupPipelines(drawContext);
158 break;
160 renderGuiInstances(drawContext);
161 break;
162 }
163 }
164
165 void generateCommands(const RenderTaskContext * /*renderingContext*/, RenderList * /*renderList*/) override
166 {
167 }
168
169 };
170
171}
172
173
174
175namespace Cogs::Core
176{
177
178 struct GuiExtension : public Extension
179 {
180 static constexpr const char* cExtensionKey = "Gui";
181
182 GuiModuleAPI api = {
183 reinterpret_cast<LoadHTMLFn>(&GuiExtension::loadHTML),
184 reinterpret_cast<SetComponentHTMLFn>(&GuiExtension::setComponentHTML),
185 reinterpret_cast<SetInnerHTMLFn>(&GuiExtension::setInnerHTML),
186 };
187
189 {
190 ExtensionRegistry::add(this, COGS_CORE_VERSION_STRING);
191 }
192
193 virtual bool initializeStatic() override
194 {
195 GuiComponent::registerType();
196 GuiRenderComponent::registerType();
197 return true;
198 }
199
200 virtual bool initialize(Context * context) override
201 {
202 context->engine->addResourceManager(std::make_unique<GuiManager>(context));
203
204 addTaskType("GuiRender", createGuiRenderTask, destroyGuiRenderTask);
205
206
207 ExtensionRegistry::registerExtensionSystem<GuiSystem>(context, SystemPriority::PreTransform, 128);
208 ExtensionRegistry::registerExtensionSystem<GuiRenderSystem>(context, SystemPriority::PreTransform, 128);
209
210 // TODO: Fix this leak...
211 context->renderer->registerExtension(new GuiRenderer());
212 return true;
213 }
214
215 virtual const char * getExtensionKey() const override { return cExtensionKey; }
216 virtual const void * getPublicAPI() const override { return &api; }
217
218 static ResourceId loadHTML(Context* context, const char* path) {
219 GuiManager* manager = static_cast<GuiManager*>(context->engine->getResourceManagerByValueType(static_cast<int>(DefaultValueType::Gui)));
220
221 if (manager) {
222 GuiDocumentHandle document = manager->load(path, -1);
223
224 manager->processLoading();
225
226 if (document->getId() == NoResourceId) {
227 manager->setResourceId(document.resolve(), manager->getNextResourceId());
228 }
229 return document->getId();
230 }
231 return NoResourceId;
232 }
233
234 static void setComponentHTML(Context* context, GuiComponent* component, ResourceId id) {
235 GuiManager* manager = static_cast<GuiManager*>(context->engine->getResourceManagerByValueType(static_cast<int>(DefaultValueType::Gui)));
236
237 if (manager) {
238 component->document = manager->getHandle(id);
239 }
240 }
241
242 static void setInnerHTML(Context* context, GuiComponent* component, const char* elementId, const char* html) {
243 GuiSystem* guiSystem = static_cast<GuiSystem*>(context->getExtensionSystem(GuiSystem::getTypeId()));
244 GuiData& data = guiSystem->getData(component);
245
246 if (data.htmlDocument) {
247 std::shared_ptr<litehtml::element> element = findElement(data.htmlDocument->root(), elementId);
248
249 if (element) {
250 element->set_inner_html(html);
251 data.invalidated = true;
252 }
253 }
254 }
255
256 } guiExtensionInstance;
257
258}
259
260extern "C" GUI_EXT_API Cogs::Core::Extension* getExtension() {
261 return &Cogs::Core::guiExtensionInstance;
262}
static Reflection::TypeId getTypeId()
Get the type id of the component type used by the system.
ComponentPool< ComponentType > pool
Pool of components managed by the system.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
class ComponentSystemBase * getExtensionSystem(const uint16_t id)
Retrieve the system with the given id.
Definition: Context.cpp:415
class IRenderer * renderer
Renderer.
Definition: Context.h:228
std::unique_ptr< class Engine > engine
Engine instance.
Definition: Context.h:222
static void add(Extension *extension, StringView version)
Adds the given extension to the registry, ensuring the initialization methods are called at appropria...
Defines an extension to the renderer, capable of doing custom rendering.
Definition: IRenderer.h:123
virtual void handleEvent(uint32_t eventId, const DrawContext *renderingContext)=0
Called when rendering events occur.
virtual void initialize(class Context *context, IGraphicsDevice *device)=0
Initialize the extension using the given context and device.
virtual void registerExtension(IRendererExtension *extension)=0
Register an extension with the renderer.
Contains render resources used by the renderer.
Core renderer system.
Definition: Renderer.h:28
void setResourceId(ResourceBase *resource, ResourceId id) override
Assign the given id to a previously created resource.
ResourceId getNextResourceId() override
Get the next unique resource id.
void processLoading() final
Process loading resources.
ResourceHandle getHandle(const ResourceId id) const
Get a resource handle to the resource with the given id.
Represents a graphics device used to manage graphics resources and issue drawing commands.
Log implementation class.
Definition: LogManager.h:139
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
constexpr size_t hashSequence(const T &t, const U &u)
Hash the last two items in a sequence of objects.
Definition: HashSequence.h:8
Defines an extension to Cogs.Core and provides methods to override in order to initialize extension c...
virtual const void * getPublicAPI() const override
Retrieve a pointer to a struct containing all publicly available function pointers.
virtual const char * getExtensionKey() const override
Get the extensions unique key, used to check for extension presence and retrieve extension specific d...
virtual bool initialize(Context *context) override
Initialize extension for the given context.
virtual bool initializeStatic() override
Initialize extension statically.
@ RenderGui
Rendering GUI elements.
Definition: IRenderer.h:99
@ PreRender
Pre rendering happening for a given rendering context.
Definition: IRenderer.h:93
ResourceId getId() const
Get the resource id of this instance.
Definition: ResourceBase.h:215
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
@ PreTransform
Run before transformations are updated.
Definition: Engine.h:50
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
Definition: Flags.h:122