For this guide we'll use the SampleApplicationBase
class. It is placed in "Samples\Common\Application.h" and implements the whole part of initializing and deinitializing Coherent UI GT. It also offers methods for creating and destroying views.
The first step of the initialization, is to initialize an instance of the Coherent::UIGT::UISystem
class. In SampleApplicationBase
, this is done in the Initialize
method. Here's sample code:
Coherent::UIGT::SystemSettings settings;settings.DebuggerPort = 9999;m_UISystem = InitializeUIGTSystem(COHERENT_UI_GT_LICENSE,settings,Coherent::LoggingGT::Debug,&m_LogHandler);
Next, you need to initialize the Coherent::UIGT::UISystemRenderer, this class is used for encapsulation of the rendering back-end of the UI system. To achieve this, you have to create renoir::RendererBackend and pass it to the CreateRenderer
method of the already created instance of the UISystem
. The backend implements an abstraction over the graphics device. You can use any of the provided backends (for DX11, OpenGL, etc.) or your own implementation
UISystemRenderer
's methods from a rendering thread.//Setup the rendering parametersCoherent::UIGT::RenderingParameters params;params.Type = CRDT_Software;//Check the application options and use the specified renderer typeswitch (m_Options.Renderer){case Coherent::Application::IRenderer::RE_OpenGL:params.Type = Coherent::UIGT::CRDT_OpenGL;break;case Coherent::Application::IRenderer::RE_DirectX9Ex:params.Type = Coherent::UIGT::CRDT_Dx9Ex;break;case Coherent::Application::IRenderer::RE_DirectX9:params.Type = Coherent::UIGT::CRDT_Dx9;break;case Coherent::Application::IRenderer::RE_DirectX11:params.Type = Coherent::UIGT::CRDT_Dx11;break;}//Get the Application's renderer device so Coherent UI GT can//use it for renderingparams.Device = m_Renderer->GetNativeDevice();//Create a system renderer with the rendering params filled from abovem_UISystemRenderer = m_UISystem->CreateRenderer(params);
UISystemRenderer
should be created before creating any views since it's used for the creation of a view renderer for the newly-created view.When de-initializing Coherent GT one should take care to destroy the UISystemRenderer
instance, the view renderers for every view created, the corresponding view textures and the views themselves, and then, the UISystem should be uninitialized.
You can checkout SampleApplicationBase::Uninitialize
's method about de-initialization.
The Sample Application class provides an SampleApplicationBase::AddView
that serves for creating a view. It takes two arguments - a Coherent::UIGT::ViewInfo structure and a std::string for the page url. You can checkout quickstart about filling the first one. Please note that if you specify a page with "coui://" as a scheme, you should also pass a valid pointer to an instance of the ResourceFileHandler
class (the SampleApplicationFramework provides an example of FileResourceHandler class for dealing with local resources). Otherwise, it is acceptable to leave nullptr. You can checkout the samples for usage.
First, the view is created by calling the CreateView
method of the UISystem
with the arguments given.
view = m_UISystem->CreateView(info, url.c_str());if (view){m_Views.push_back(view);// ...}
The next two steps are related to the rendering of the newly-created view. First, a texture is created for the view and is added to the application's vector of view textures. Then, in order to be able to draw the view, we create a view renderer. It's responsibility is drawing the view and should be destroyed before the view that it draws.
int texId = m_Renderer->CreateTexture(view->GetWidth(),view->GetHeight(),false,isDynamic,isRT,Coherent::Application::IRenderer::TFMT_ARGB8);m_ViewTextures.push_back(texId);auto viewRenderer = m_UISystemRenderer->CreateViewRenderer(view,(void*)m_Renderer->GetNativeTexture(texId),view->GetWidth(),view->GetHeight());m_ViewRenderers.push_back(ViewRendererPtr(viewRenderer));
In the sample application, it is alive as long as the view is alive - it is destroyed just before the view is destroyed on its removal from the application.
If you want to remove a particular view from the application, you can achieve this by calling Application::RemoveView
method. It simply destroys the view renderer and the view (in this order), thus freeing the resources used by the specified view. Destruction of view renderers and views goes hand in hand!
If you do not remove a view explicitly by calling RemoveView
it will be destroyed along with its corresponding view renderer upon uninitializing the application.
When using smart pointers for storing views and view renderers, destroying views requires simply resetting the smart pointer, this will actually call the appropriate Destroy()
methods.
m_ViewRenderers[m_CurrentView].reset(nullptr);m_ViewRenderers.erase(m_ViewRenderers.begin() + m_CurrentView);m_Views[m_CurrentView].reset(nullptr);m_Views.erase(m_Views.begin() + m_CurrentView);
Another way to do this is by calling the Destroy()
method yourself when there is no smart pointers involved.
m_ViewRenderers[m_CurrentView]->Destroy();m_ViewRenderers.erase(m_ViewRenderers.begin() + m_CurrentView);m_Views[m_CurrentView]->Destroy();m_Views.erase(m_Views.begin() + m_CurrentView);
The Update
, DrawScene
and ResizeRendering
methods are intentionally left empty, and are overridden and implemented in the samples, so as to match the specifics of the concrete sample.