Jump to content

Implementation CoherentGT GUI sample


photo

Recommended Posts

Hi,

At the last time I make a few tests about implementing Coherent GT GUI framework into Unigine (just display layer).

This is just prototype, needs refactoring (especially see header file) and maybe some optimize.

It's not documented anywhere, so I would like to share with it:

AppWorldLogic.h:

#include <RenoirBackends/dx11backend/Dx11Backend.h>

#include "ResourceFileHandler.h"
#include <Coherent/UIGT/UISystem.h>
#include <Coherent/UIGT/View.h>
#include <Coherent/UIGT/IDiskCache.h>
#include <Coherent/UIGT/ResourceHandler.h>
#include <Coherent/UIGT/LicenseGT.h>
#include <Coherent/UIGT/UISystemListener.h>
#include <Coherent/UIGT/ViewInfo.h>

#include <UnigineLogic.h>
#include <UnigineStreams.h>

#include "UnigineEngine.h"
#include "UnigineGui.h"
#include "UnigineWidgets.h"
#include "UnigineEditor.h"
#include "UnigineTextures.h"
#include "UnigineApp.h"
#include "UnigineMaterials.h"



#include <windows.h>
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#if !defined(NOMINMAX)
#define NOMINMAX
#endif
#if defined(COHERENT_PLATFORM_DURANGO)
#include <d3d11_x.h>
#else
#include <d3d11.h>
#endif
#include <d3d11_1.h>

#include "RenoirBackends/Common/Types.h"
#include "RenoirBackends/Common/ComHelpers.h"
#include <cassert>

#if defined(COHERENT_SUPPORT_VS2013)
#ifdef COHERENT_EXPORT
#define COHERENT_RENDERERBACKEND_API __declspec(dllexport)
#else
#define COHERENT_RENDERERBACKEND_API __declspec(dllimport)
#endif
#endif



using namespace Unigine;

class AppWorldLogic : public Unigine::WorldLogic {
	
	int createdHUD = false;
	Coherent::UIGT::UISystem* system;
	Coherent::UIGT::View* view;
	Coherent::UIGT::ViewRenderer* viewRenderer;
	Coherent::UIGT::UISystemRenderer* systemRenderer;
	Coherent::UIGT::NativeRenderTarget rt;

	FileResourceHandler fileHandler;

	ID3D11Device* device;
	renoir::Dx11Backend* backend;

	WidgetSpritePtr hud;
	Engine* engine;
	Editor* editor;

	WidgetLabelPtr widget_label;
	TexturePtr my_texture;
	TexturePtr my_texture_ds;
	ID3D11DepthStencilView* DSV;

	ID3D11RenderTargetView* TextureRTV;
	NodePtr cube;

public:
	AppWorldLogic();
	virtual ~AppWorldLogic();
	
	virtual int init();
	
	virtual int update();
	virtual int render();
	virtual int flush();
	
	virtual int shutdown();
	virtual int destroy();
	
	virtual int save(const Unigine::StreamPtr &stream);
	virtual int restore(const Unigine::StreamPtr &stream);

	void createHUDWidgetSprite();
	void createLabel();
	void createDSTexture();

	int SetWidgetSpriteTexture(Unigine::WidgetSpritePtr sprite);
};

AppWorldLogic.cpp:


void AppWorldLogic::createHUDWidgetSprite()
{
	GuiPtr gui = Gui::get();
	hud = WidgetSprite::create(gui);
	hud->setPosition(0, 0);
	hud->setWidth(1600);
	hud->setHeight(900);
	hud->setLayerBlendFunc(0, Gui::BLEND_ONE, Gui::BLEND_ONE_MINUS_SRC_ALPHA);
	
	gui->addChild(hud->getWidget(), Gui::ALIGN_OVERLAP);
}

void AppWorldLogic::createLabel()
{
	// getting a pointer to the system GUI
	GuiPtr gui = Gui::get();

	// creating a label widget and setting up its caption
	widget_label = WidgetLabel::create(gui, "Label text");

	// setting a tooltip
	widget_label->setToolTip("This is a label");

	// rearranging label size
	widget_label->arrange();

	// setting label position
	widget_label->setPosition(10, 10);

	// adding created label widget to the system GUI
	gui->addChild(widget_label->getWidget(), Gui::ALIGN_OVERLAP | Gui::ALIGN_FIXED);
}

void AppWorldLogic::createDSTexture()
{
	my_texture_ds = Texture::create();

	const int width = int(view->GetWidth());
	const int height = int(view->GetHeight());
	int flags = Unigine::Texture::FILTER_LINEAR | Unigine::Texture::USAGE_RENDER;
	my_texture_ds->create2D(width, height, Unigine::Texture::FORMAT_RGBA8, flags);
}

int AppWorldLogic::SetWidgetSpriteTexture(Unigine::WidgetSpritePtr sprite)
{
	my_texture = Texture::create();

	const int width = int(view->GetWidth());
	const int height = int(view->GetHeight());
	int flags = Unigine::Texture::FILTER_LINEAR | Unigine::Texture::USAGE_RENDER;
	my_texture->create2D(width, height, Unigine::Texture::FORMAT_RGBA8, flags);

	sprite->setRender(my_texture);

	return 1;
}

int AppWorldLogic::init() {
	// Write here code to be called on world initialization: initialize resources for your world scene during the world start.

	/// Configure the System settings in a Coherent::UIGT::SystemSettings variable.
	/// Only set a debugger port for debugging purposes everything else is
	/// by default.
	//! [System]
	Coherent::UIGT::SystemSettings settings;
	settings.DebuggerPort = 19999;
	

	system = InitializeUIGTSystem(COHERENT_UI_GT_LICENSE,
		settings,
		Coherent::LoggingGT::Info);
	//! [System]

	/// Configure the View settings in a Coherent::UIGT::ViewInfo variable.
	/// Create the FileResourceHandler if you want to work with "coui" resources.
	/// Set the full path to the html document you want to load.
	/// Create the View using the System->CreateView.
	//! [View]
	const char* resourcePath = "coui://uiresources/minRes/MainUI.html";
	Coherent::UIGT::ViewInfo info;
	info.Width = 1600;
	info.Height = 900;
	info.IsTransparent = true;
	info.ResourceHandlerInstance = &fileHandler; /// Required for resources loaded via the coui:// protocol to work

	view = system->CreateView(info, resourcePath);
	//! [View]

	createHUDWidgetSprite();
	createLabel();
	SetWidgetSpriteTexture(hud);
	createDSTexture();

	/// Create and initialize the rendering backend for DirectX11
	/// You can use your own backend if it inherits from the RendererBackend interface.
	////! [Backend]
	device = static_cast<ID3D11Device*>(Unigine::App::get()->getD3D11Device());
	backend = new renoir::Dx11Backend(device, false);

	backend->InitializeStaticResources();
	////! [Backend]

	/// Create the System Renderer using the system->CreateRenderer method and the backend.
	//! [SystemRenderer]
	systemRenderer = system->CreateRenderer(backend, backend);
	//! [SystemRenderer]

	///// Create the View Renderer using the systemRenderer->CreateViewRenderer method and
	///// the textures from the DirectX initialization.
	////! [ViewRenderer]
	DSV = static_cast<ID3D11DepthStencilView*>(my_texture->getD3D11DepthStencilView());
	TextureRTV = static_cast<ID3D11RenderTargetView*>(my_texture->getD3D11RenderTargetView());

	rt.Texture = TextureRTV;
	rt.DepthStencilTexture = DSV;
	viewRenderer = systemRenderer->CreateViewRenderer(view, rt, view->GetWidth(), view->GetHeight(), 1);
	////! [ViewRenderer]

	Materials *materials = Materials::get();
	MaterialPtr m = materials->findMaterial("mesh_base");
	int num = m->findTexture("albedo");
	m->setTexture(num, my_texture);

	return 1;
}

// start of the main loop
int AppWorldLogic::update() {
	// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
	
	////! [Loop]
	///// Advances the timers of the UI. Should be called each frame.
	system->Advance();
	///// Layouts the content of the page. You should call this method each frame
	///// after calling Advance on the UI system
	unsigned frameId = view->Layout();
	///// Paints the View in the user supplied texture when using hardware
	///// rendering.
	viewRenderer->Paint(frameId);

	return 1;
}

int AppWorldLogic::render() {
	// The engine calls this function before rendering each render frame: correct behavior after the state of the node has been updated.

	return 1;
}

int AppWorldLogic::flush() {
	// Write here code to be called before updating each physics frame: control physics in your application and put non-rendering calculations.
	// The engine calls flush() with the fixed rate (60 times per second by default) regardless of the FPS value.
	// WARNING: do not create, delete or change transformations of nodes here, because rendering is already in progress.
	
	return 1;
}
// end of the main loop

int AppWorldLogic::shutdown() {
	// Write here code to be called on world shutdown: delete resources that were created during world script execution to avoid memory leaks.
	
	return 1;
}

int AppWorldLogic::destroy() {
	// Write here code to be called when the video mode is changed or the application is restarted (i.e. video_restart is called). It is used to reinitialize the graphics context.
	
	///// The order of resource destruction is really important!
	////! [Destruction]
	viewRenderer->Destroy();
	viewRenderer = nullptr;

	view->Destroy();
	view = nullptr;

	systemRenderer->Destroy();
	systemRenderer = nullptr;

	system->Uninitialize();
	system = nullptr;
	////! [Destruction]

	return 1;
}

Also you will need a ResourceFileHandler.h file that come and for e.g. dx11backend project from CoherentGT (I can't share it here because of license agreement).

For work it needs an object witrh "mesh_base" material at scene. Also it needs minRes files from sample delivered with CoherentGT in data folder.

It will display a Coherent GUI at the screen and at object in scene.

  • Like 2
Link to comment
  • 7 months later...

Hi all,

Sorry for reviving this thread but I'm experiencing some challenges integrating CoherentGT in our project.

We are trying to render CoherentGT onto a plane in the Unigine world and are using the Vive.

The Code above works as of Unigine SDK v2.7.1 and CoherentGT can render its UI into Unigine. However, the Vive screen mirror is being overlayed onto the CoherentGT UI. I believe this is because CoherentGT uses the same d3d11device as the Unigine::App window and renders the screen mirror along with Coherent. I can mitigate this by setting the Unigine::App width and height to 1, but we lose our app screen mirror view, which we do not want.

What would be the best way to give  CoherentGT a separate d3d11device for it to render its UI so the Vive screen mirror doesn’t get overlayed onto it?

Link to comment
×
×
  • Create New...