Panagiotis Christopoulos Charitos 8 years ago
parent
commit
eb944ccb1a

+ 2 - 4
src/anki/Ui.h

@@ -5,8 +5,6 @@
 
 
 #pragma once
 #pragma once
 
 
-/// @defgroup ui User interface
+/// @defgroup ui User interface that is using nuklear library.
 
 
-#include <anki/ui/UiInterfaceImpl.h>
-#include <anki/ui/Canvas.h>
-#include <anki/ui/Widget.h>
+#include <anki/ui/UiManager.h>

+ 0 - 75
src/anki/ui/Canvas.cpp

@@ -1,75 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/ui/Canvas.h>
-#include <anki/ui/Widget.h>
-
-namespace anki
-{
-
-Canvas::Canvas(UiInterface* interface)
-	: m_interface(interface)
-{
-	m_rootWidget = newWidget<Widget>();
-
-	setSize(UVec2(128u));
-}
-
-Canvas::~Canvas()
-{
-	if(m_rootWidget)
-	{
-		m_rootWidget->markForDeletion();
-	}
-}
-
-void Canvas::update(F64 dt)
-{
-	// TODO
-}
-
-void Canvas::paint()
-{
-	Error err = m_rootWidget->visitTree([&](Widget& w) -> Error {
-		if(m_debugDrawEnabled)
-		{
-			U c = 0;
-			const UVec2& pos = w.getCanvasPosition();
-			const UVec2& size = w.getSize();
-
-			UVec2 lb = pos;
-			UVec2 rb = pos + UVec2(size.x(), 0u);
-			UVec2 rt = pos + size;
-			UVec2 lt = pos + UVec2(0u, size.y());
-
-			Array<UVec2, 2 * 4> positions;
-			positions[c++] = lb;
-			positions[c++] = rb;
-			positions[c++] = rb;
-			positions[c++] = rt;
-			positions[c++] = rt;
-			positions[c++] = lt;
-			positions[c++] = lt;
-			positions[c++] = lb;
-
-			m_interface->drawLines(
-				WeakArray<UVec2>(&positions[0], positions.getSize()), Vec4(1.0, 0.0, 0.0, 1.0), m_size);
-		}
-
-		return ErrorCode::NONE;
-	});
-	(void)err;
-
-	// m_interface->
-}
-
-void Canvas::setSize(const UVec2& size)
-{
-	m_size = size;
-	m_rootWidget->setRelativePosition(UVec2(0u));
-	m_rootWidget->setSize(size);
-}
-
-} // end namespace anki

+ 0 - 91
src/anki/ui/Canvas.h

@@ -1,91 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/ui/UiInterface.h>
-#include <anki/input/KeyCode.h>
-
-namespace anki
-{
-
-/// @addtogroup ui
-/// @{
-
-/// UI canvas. It's a container of widgets.
-class Canvas
-{
-public:
-	Canvas(UiInterface* interface);
-
-	~Canvas();
-
-	/// Create a new widget.
-	template<typename TWidget>
-	TWidget* newWidget()
-	{
-		TWidget* out = getAllocator().newInstance<TWidget>(this);
-		return out;
-	}
-
-	/// @name Input injection methods.
-	/// @{
-	void injectMouseMove(const UVec2& pos);
-
-	void injectKeyDown(KeyCode key);
-
-	void injectKeyUp(KeyCode key);
-
-	void injectText(const CString& text);
-
-	void injectMouseButtonDown(MouseButton button);
-	/// @}
-
-	/// Update the widgets.
-	void update(F64 dt);
-
-	/// Paint the widgets (if needed). Call after update.
-	void paint();
-
-	void setSize(const UVec2& size);
-
-	const UVec2& getSize() const
-	{
-		return m_size;
-	}
-
-	Bool getDebugDrawEnabled() const
-	{
-		return m_debugDrawEnabled;
-	}
-
-	void setDebugDrawEnabled()
-	{
-		m_debugDrawEnabled = true;
-	}
-
-#ifdef ANKI_BUILD
-	UiAllocator getAllocator() const
-	{
-		return m_interface->getAllocator();
-	}
-
-	Atomic<I32>& getMarkedForDeletionCount()
-	{
-		return m_markedForDeletionCount;
-	}
-#endif
-
-private:
-	WeakPtr<UiInterface> m_interface;
-	Atomic<I32> m_markedForDeletionCount = {0};
-	WeakPtr<Widget> m_rootWidget;
-
-	UVec2 m_size; ///< Virtual size of canvas.
-	Bool8 m_debugDrawEnabled = false;
-};
-/// @}
-
-} // end namespace anki

+ 31 - 17
src/anki/ui/Common.h

@@ -5,35 +5,49 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <anki/Math.h>
+#include <anki/ui/NuklearConfig.h>
 #include <anki/util/Allocator.h>
 #include <anki/util/Allocator.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
 // Forward
 // Forward
-class Widget;
-class Canvas;
-class UiImage;
+class UiManager;
 
 
 /// @addtogroup ui
 /// @addtogroup ui
 /// @{
 /// @{
+using UiAllocator = HeapAllocator<U8>;
 
 
-using UiAllocator = GenericMemoryPoolAllocator<U8>;
+const I32 FONT_TEXTURE_INDEX = 1;
 
 
-/// Color.
-using Color = Vec4;
-
-/// Rectangle
-class Rect
+/// Initialize a nk_allocator.
+template<typename TMemPool>
+inline nk_allocator makeNkAllocator(TMemPool* alloc)
 {
 {
-public:
-	UVec2 m_min;
-	UVec2 m_max;
-};
-
-/// Used in widget classes.
-#define ANKI_WIDGET friend class Canvas;
+	nk_allocator nkAlloc;
+	nkAlloc.userdata.ptr = alloc;
+
+	auto allocCallback = [](nk_handle handle, void*, nk_size size) -> void* {
+		ANKI_ASSERT(handle.ptr);
+		TMemPool* al = static_cast<TMemPool*>(handle.ptr);
+		return al->allocate(size, 16);
+	};
+
+	nkAlloc.alloc = allocCallback;
+
+	auto freeCallback = [](nk_handle handle, void* ptr) -> void {
+		ANKI_ASSERT(handle.ptr);
+		if(ptr)
+		{
+			TMemPool* al = static_cast<TMemPool*>(handle.ptr);
+			al->free(ptr);
+		}
+	};
+
+	nkAlloc.free = freeCallback;
+
+	return nkAlloc;
+}
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 75 - 115
src/anki/ui/Font.cpp

@@ -4,134 +4,94 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <anki/ui/Font.h>
 #include <anki/ui/Font.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include <anki/ui/UiManager.h>
+#include <anki/resource/ResourceManager.h>
+#include <anki/resource/ResourceFilesystem.h>
+#include <anki/gr/GrManager.h>
+#include <anki/gr/Buffer.h>
+#include <anki/gr/Texture.h>
+#include <anki/gr/CommandBuffer.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
-class FtFont
-{
-public:
-	FT_Library m_lib = 0;
-	FT_Face m_face = 0;
-
-	~FtFont()
-	{
-		if(m_face)
-		{
-			FT_Done_Face(m_face);
-		}
-
-		if(m_lib)
-		{
-			FT_Done_FreeType(m_lib);
-		}
-	}
-};
-
 Font::~Font()
 Font::~Font()
 {
 {
+	nk_font_atlas_clear(&m_atlas);
 }
 }
 
 
 Error Font::init(const CString& filename, U32 fontHeight)
 Error Font::init(const CString& filename, U32 fontHeight)
 {
 {
-	// Load font
+	// Load font in memory
+	ResourceFilePtr file;
+	ANKI_CHECK(m_manager->getResourceManager().getFilesystem().openFile(filename, file));
 	DynamicArrayAuto<U8> fontData(getAllocator());
 	DynamicArrayAuto<U8> fontData(getAllocator());
-	ANKI_CHECK(m_interface->readFile(filename, fontData));
-
-	// Create impl
-	FtFont ft;
-
-	// Create lib
-	if(FT_Init_FreeType(&ft.m_lib))
-	{
-		ANKI_LOGE("FT_Init_FreeType() failed");
-		return ErrorCode::FUNCTION_FAILED;
-	}
-
-	// Create face and set glyph size
-	if(FT_New_Memory_Face(ft.m_lib, &fontData[0], fontData.getSize(), 0, &ft.m_face))
-	{
-		ANKI_LOGE("FT_New_Face() failed");
-		return ErrorCode::FUNCTION_FAILED;
-	}
-
-	if(FT_Set_Pixel_Sizes(ft.m_face, 0, fontHeight))
-	{
-		ANKI_LOGE("FT_Set_Pixel_Sizes() failed");
-		return ErrorCode::FUNCTION_FAILED;
-	}
-
-	// Compute the atlas size
-	UVec2 imgSize(0u);
-	{
-		U width = 0, height = 0;
-
-		for(I c = FIRST_CHAR; c <= LAST_CHAR; ++c)
-		{
-			if(FT_Load_Char(ft.m_face, c, FT_LOAD_DEFAULT))
-			{
-				ANKI_LOGE("Loading character '%c' failed", c);
-				return ErrorCode::USER_DATA;
-			}
-
-			width += ft.m_face->glyph->bitmap.width;
-			height = max<U>(height, ft.m_face->glyph->bitmap.rows);
-		}
-
-		imgSize.x() = width;
-		imgSize.y() = height;
-	}
-
-	// Allocate bitmap for rasterization
-	DynamicArrayAuto<U8> bitmap(getAllocator());
-	bitmap.create(imgSize.x() * imgSize.y());
-	memset(&bitmap[0], 0, bitmap.getSize());
-
-	// Rasterize image to memory and get some glyph info
-	{
-		U xOffset = 0;
-
-		for(I c = FIRST_CHAR; c <= LAST_CHAR; ++c)
-		{
-			if(FT_Load_Char(ft.m_face, c, FT_LOAD_RENDER))
-			{
-				ANKI_LOGE("Loading character '%c' failed", c);
-				return ErrorCode::USER_DATA;
-			}
-
-			const U w = ft.m_face->glyph->bitmap.width;
-			const U h = ft.m_face->glyph->bitmap.rows;
-			WeakArray<U8> srcBitmap(ft.m_face->glyph->bitmap.buffer, w * h);
-
-			// Copy
-			for(U y = 0; y < h; ++y)
-			{
-				for(U x = 0; x < w; ++x)
-				{
-					bitmap[y * w + (x + xOffset)] = srcBitmap[y * w + x];
-				}
-			}
-
-			// Get glyph info
-			FontCharInfo& inf = m_chars[c - FIRST_CHAR];
-			inf.m_imageRect.m_min = UVec2(xOffset, 0);
-			inf.m_imageRect.m_max = inf.m_imageRect.m_min + UVec2(w, h);
-
-			inf.m_advance = UVec2(ft.m_face->glyph->advance.x >> 6, ft.m_face->glyph->advance.y >> 6);
-
-			inf.m_offset = IVec2(ft.m_face->glyph->bitmap_left, ft.m_face->glyph->bitmap_top - I(h));
-
-			// Advance
-			xOffset += w;
-		}
-	}
-
-	// Create image
-	ANKI_CHECK(m_interface->createR8Image(WeakArray<U8>(&bitmap[0], bitmap.getSize()), imgSize, m_img));
+	fontData.create(file->getSize());
+	ANKI_CHECK(file->read(&fontData[0], file->getSize()));
+
+	// Bake font
+	nk_allocator nkAlloc = makeNkAllocator(&getAllocator().getMemoryPool());
+	nk_font_atlas_init_custom(&m_atlas, &nkAlloc, &nkAlloc);
+	nk_font_atlas_begin(&m_atlas);
+	m_font = nk_font_atlas_add_from_memory(&m_atlas, &fontData[0], fontData.getSize(), fontHeight, nullptr);
+
+	int width, height;
+	const void* img = nk_font_atlas_bake(&m_atlas, &width, &height, NK_FONT_ATLAS_RGBA32);
+
+	// Create the texture
+	createTexture(img, width, height);
+
+	// End building
+	nk_handle texHandle;
+	texHandle.id = FONT_TEXTURE_INDEX;
+	nk_font_atlas_end(&m_atlas, texHandle, nullptr);
+
+	nk_font_atlas_cleanup(&m_atlas);
 
 
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
+void Font::createTexture(const void* data, U32 width, U32 height)
+{
+	ANKI_ASSERT(data && width > 0 && height > 0);
+
+	// Create and populate the buffer
+	PtrSize buffSize = width * height * 4 * 4;
+	BufferPtr buff = m_manager->getGrManager().newInstance<Buffer>(
+		buffSize, BufferUsageBit::BUFFER_UPLOAD_DESTINATION, BufferMapAccessBit::WRITE);
+	void* mapped = buff->map(0, buffSize, BufferMapAccessBit::WRITE);
+	memcpy(mapped, data, buffSize);
+	buff->unmap();
+
+	// Create the texture
+	TextureInitInfo texInit;
+	texInit.m_width = width;
+	texInit.m_height = height;
+	texInit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
+	texInit.m_usage =
+		TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::GENERATE_MIPMAPS;
+	texInit.m_usageWhenEncountered = TextureUsageBit::SAMPLED_FRAGMENT;
+	texInit.m_mipmapsCount = 2;
+	texInit.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
+	texInit.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
+
+	m_tex = m_manager->getGrManager().newInstance<Texture>(texInit);
+
+	// Do the copy
+	CommandBufferInitInfo cmdbInit;
+	cmdbInit.m_flags = CommandBufferFlag::TRANSFER_WORK | CommandBufferFlag::SMALL_BATCH;
+	CommandBufferPtr cmdb = m_manager->getGrManager().newInstance<CommandBuffer>(cmdbInit);
+
+	TextureSurfaceInfo surf(0, 0, 0, 0);
+
+	cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, surf);
+	cmdb->copyBufferToTextureSurface(buff, 0, buffSize, m_tex, surf);
+	cmdb->setTextureSurfaceBarrier(
+		m_tex, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::GENERATE_MIPMAPS, surf);
+	cmdb->generateMipmaps2d(m_tex, 0, 0);
+	cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::GENERATE_MIPMAPS, TextureUsageBit::SAMPLED_FRAGMENT, surf);
+
+	cmdb->flush();
+}
+
 } // end namespace anki
 } // end namespace anki

+ 17 - 39
src/anki/ui/Font.h

@@ -5,7 +5,8 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <anki/ui/UiInterface.h>
+#include <anki/ui/UiObject.h>
+#include <anki/gr/Texture.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -13,64 +14,41 @@ namespace anki
 /// @addtogroup ui
 /// @addtogroup ui
 /// @{
 /// @{
 
 
-class FontCharInfo
-{
-public:
-	UVec2 m_advance; ///< Char advance.
-	Rect m_imageRect; ///< The rect inside the image atlas.
-	IVec2 m_offset; ///< Left and top bearing.
-};
-
 /// Font class.
 /// Font class.
-class Font
+class Font : public UiObject
 {
 {
-	friend class IntrusivePtr<Font>;
-	friend IntrusivePtr<Font>::Deleter;
-
 public:
 public:
-	Font(UiInterface* interface)
-		: m_interface(interface)
+	Font(UiManager* manager)
+		: UiObject(manager)
 	{
 	{
 	}
 	}
 
 
 	~Font();
 	~Font();
 
 
+	Atomic<I32>& getRefcount()
+	{
+		return m_refcount;
+	}
+
 	/// Initialize the font.
 	/// Initialize the font.
 	ANKI_USE_RESULT Error init(const CString& filename, U32 fontHeight);
 	ANKI_USE_RESULT Error init(const CString& filename, U32 fontHeight);
 
 
 anki_internal:
 anki_internal:
-	/// Get info for a character.
-	const FontCharInfo& getCharInfo(char c) const
-	{
-		ANKI_ASSERT(c >= FIRST_CHAR);
-		return m_chars[c - ' '];
-	}
-
 	/// Get font image atlas.
 	/// Get font image atlas.
-	const UiImagePtr& getImage() const
+	const TexturePtr& getTexture() const
 	{
 	{
-		return m_img;
+		return m_tex;
 	}
 	}
 
 
 private:
 private:
-	static const char FIRST_CHAR = ' ';
-	static const char LAST_CHAR = 127;
-	static const U CHAR_COUNT = LAST_CHAR - FIRST_CHAR + 1;
-
-	WeakPtr<UiInterface> m_interface;
 	Atomic<I32> m_refcount = {0};
 	Atomic<I32> m_refcount = {0};
-	UiImagePtr m_img;
-	Array<FontCharInfo, CHAR_COUNT> m_chars;
 
 
-	Atomic<I32>& getRefcount()
-	{
-		return m_refcount;
-	}
+	nk_font_atlas m_atlas = {};
+	nk_font* m_font = nullptr;
 
 
-	UiAllocator getAllocator() const
-	{
-		return m_interface->getAllocator();
-	}
+	TexturePtr m_tex;
+
+	void createTexture(const void* data, U32 width, U32 height);
 };
 };
 
 
 using FontPtr = IntrusivePtr<Font>;
 using FontPtr = IntrusivePtr<Font>;

+ 30 - 0
src/anki/ui/NuklearConfig.h

@@ -0,0 +1,30 @@
+// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/util/Assert.h>
+
+#define NK_INCLUDE_FIXED_TYPES
+#define NK_INCLUDE_STANDARD_VARARGS
+// #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
+#define NK_INCLUDE_FONT_BAKING
+// #define NK_INCLUDE_DEFAULT_FONT
+// #define NK_INCLUDE_COMMAND_USERDATA
+// #define NK_BUTTON_TRIGGER_ON_RELEASE
+// #define NK_ZERO_COMMAND_MEMORY
+#define NK_ASSERT ANKI_ASSERT
+// #define NK_BUFFER_DEFAULT_INITIAL_SIZE
+// #define NK_MAX_NUMBER_BUFFER
+// #define NK_INPUT_MAX
+// #define NK_MEMSET
+// #define NK_MEMCPY
+// #define NK_SQRT
+// #define NK_SIN
+// #define NK_COS
+// #define NK_STRTOD
+// #define NK_DTOA
+// #define NK_VSNPRINTF
+#include <nuklear/nuklear.h>

+ 12 - 0
src/anki/ui/NuklearImpl.cpp

@@ -0,0 +1,12 @@
+// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#define NK_IMPLEMENTATION
+#include <anki/ui/NuklearConfig.h>

+ 0 - 88
src/anki/ui/UiInterface.h

@@ -1,88 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/ui/UiObject.h>
-
-namespace anki
-{
-
-/// @addtogroup ui
-/// @{
-
-using UiImagePtr = IntrusivePtr<UiImage>;
-
-/// Interfacing UI system with external systems.
-class UiInterface
-{
-public:
-	UiInterface(UiAllocator alloc)
-		: m_alloc(alloc)
-	{
-	}
-
-	virtual ~UiInterface() = default;
-
-	UiAllocator getAllocator() const
-	{
-		return m_alloc;
-	}
-
-	/// @name Image related methods.
-	/// @{
-	virtual ANKI_USE_RESULT Error loadImage(const CString& filename, UiImagePtr& img) = 0;
-
-	/// Create a 8bit image. Used for fonts.
-	virtual ANKI_USE_RESULT Error createR8Image(const WeakArray<U8>& data, const UVec2& size, UiImagePtr& img) = 0;
-	/// @}
-
-	/// @name Misc methods.
-	/// @{
-	virtual ANKI_USE_RESULT Error readFile(const CString& filename, DynamicArrayAuto<U8>& data) = 0;
-	/// @}
-
-	/// @name Painting related methods.
-	/// @{
-	virtual void drawImage(UiImagePtr image, const Rect& uvs, const Rect& drawingRect, const UVec2& canvasSize) = 0;
-
-	virtual void drawLines(const WeakArray<UVec2>& lines, const Color& color, const UVec2& canvasSize) = 0;
-	/// @}
-
-protected:
-	UiAllocator m_alloc;
-};
-
-/// UI image interface.
-class UiImage
-{
-	friend class IntrusivePtr<UiImage>;
-	friend IntrusivePtr<UiImage>::Deleter;
-
-public:
-	UiImage(UiInterface* interface)
-		: m_alloc(interface->getAllocator())
-	{
-	}
-
-	virtual ~UiImage() = default;
-
-private:
-	UiAllocator m_alloc;
-	Atomic<I32> m_refcount = {0};
-
-	Atomic<I32>& getRefcount()
-	{
-		return m_refcount;
-	}
-
-	UiAllocator getAllocator() const
-	{
-		return m_alloc;
-	}
-};
-/// @}
-
-} // end namespace anki

+ 0 - 224
src/anki/ui/UiInterfaceImpl.cpp

@@ -1,224 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/ui/UiInterfaceImpl.h>
-#include <anki/resource/ResourceManager.h>
-#include <anki/resource/GenericResource.h>
-
-namespace anki
-{
-
-struct Vertex
-{
-	Vec2 m_pos;
-	Vec2 m_uv;
-	Array<U8, 4> m_color;
-};
-
-UiInterfaceImpl::UiInterfaceImpl(UiAllocator alloc)
-	: UiInterface(alloc)
-{
-}
-
-UiInterfaceImpl::~UiInterfaceImpl()
-{
-}
-
-Error UiInterfaceImpl::init(GrManager* gr, ResourceManager* rc)
-{
-	// Load shaders
-	ANKI_CHECK(rc->loadResource("shaders/UiLines.vert.glsl", m_stages[StageId::LINES].m_vShader));
-
-	ANKI_CHECK(rc->loadResource("shaders/UiLines.frag.glsl", m_stages[StageId::LINES].m_fShader));
-
-// Init pplines
-#if 0
-	PipelineInitInfo ppinit;
-	ppinit.m_vertex.m_bindingCount = 1;
-	ppinit.m_vertex.m_bindings[0].m_stride = sizeof(Vertex);
-	ppinit.m_vertex.m_attributeCount = 3;
-	ppinit.m_vertex.m_attributes[0].m_format = PixelFormat(ComponentFormat::R32G32, TransformFormat::FLOAT);
-	ppinit.m_vertex.m_attributes[0].m_offset = 0;
-	ppinit.m_vertex.m_attributes[1].m_format = PixelFormat(ComponentFormat::R32G32, TransformFormat::FLOAT);
-	ppinit.m_vertex.m_attributes[1].m_offset = sizeof(Vec2);
-	ppinit.m_vertex.m_attributes[2].m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
-	ppinit.m_vertex.m_attributes[2].m_offset = sizeof(Vec2) * 2;
-
-	ppinit.m_inputAssembler.m_topology = PrimitiveTopology::LINES;
-
-	ppinit.m_depthStencil.m_depthWriteEnabled = false;
-	ppinit.m_depthStencil.m_depthCompareFunction = CompareOperation::ALWAYS;
-
-	ppinit.m_color.m_attachmentCount = 1;
-	ppinit.m_color.m_attachments[0].m_format = PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM);
-	ppinit.m_color.m_attachments[0].m_srcBlendFactor = BlendFactor::SRC_ALPHA;
-	ppinit.m_color.m_attachments[0].m_dstBlendFactor = BlendFactor::ONE_MINUS_SRC_ALPHA;
-
-	ppinit.m_shaders[U(ShaderType::VERTEX)] = m_stages[StageId::LINES].m_vShader->getGrShader();
-	ppinit.m_shaders[U(ShaderType::FRAGMENT)] = m_stages[StageId::LINES].m_fShader->getGrShader();
-	m_stages[StageId::LINES].m_ppline = gr->newInstance<Pipeline>(ppinit);
-#endif
-
-	// Init buffers
-	for(U s = 0; s < StageId::COUNT; ++s)
-	{
-		for(U i = 0; i < m_stages[s].m_vertBuffs.getSize(); ++i)
-		{
-			m_stages[s].m_vertBuffs[i] =
-				gr->newInstance<Buffer>(MAX_VERTS * sizeof(Vertex), BufferUsageBit::VERTEX, BufferMapAccessBit::WRITE);
-		}
-	}
-
-// Init resource groups
-#if 0
-	for(U s = 0; s < StageId::COUNT; ++s)
-	{
-		for(U i = 0; i < m_stages[s].m_rcGroups.getSize(); ++i)
-		{
-			ResourceGroupInitInfo rcinit;
-			rcinit.m_vertexBuffers[0].m_buffer = m_stages[s].m_vertBuffs[i];
-
-			if(s == StageId::TEXTURED_TRIANGLES)
-			{
-				// TODO
-			}
-
-			m_stages[s].m_rcGroups[i] = gr->newInstance<ResourceGroup>(rcinit);
-		}
-	}
-#endif
-
-	return ErrorCode::NONE;
-}
-
-void UiInterfaceImpl::beginRendering(CommandBufferPtr cmdb)
-{
-	m_cmdb = cmdb;
-
-	// Map buffers
-	for(U s = 0; s < StageId::COUNT; ++s)
-	{
-		BufferPtr buff = m_stages[s].m_vertBuffs[m_timestamp];
-
-		m_vertMappings[s] = static_cast<Vertex*>(buff->map(0, sizeof(Vertex) * MAX_VERTS, BufferMapAccessBit::WRITE));
-
-		m_vertCounts[s] = 0;
-	}
-}
-
-void UiInterfaceImpl::endRendering()
-{
-	m_cmdb.reset(nullptr);
-
-	for(U s = 0; s < StageId::COUNT; ++s)
-	{
-		BufferPtr buff = m_stages[s].m_vertBuffs[m_timestamp];
-		buff->unmap();
-	}
-
-	m_timestamp = (m_timestamp + 1) % MAX_FRAMES_IN_FLIGHT;
-}
-
-void UiInterfaceImpl::drawLines(const WeakArray<UVec2>& positions, const Color& color, const UVec2& canvasSize)
-{
-	StageId stageId = StageId::LINES;
-
-	ANKI_ASSERT(m_vertCounts[stageId] + positions.getSize() <= MAX_VERTS);
-
-	// m_cmdb->bindPipeline(m_stages[StageId::LINES].m_ppline);
-	// m_cmdb->bindResourceGroup(m_stages[StageId::LINES].m_rcGroups[m_timestamp], 0, nullptr);
-	// m_cmdb->drawArrays(positions.getSize(), 1, m_vertCounts[stageId]);
-
-	for(const UVec2& pos : positions)
-	{
-		Vertex v;
-		v.m_pos = Vec2(pos.x(), pos.y()) / Vec2(canvasSize.x(), canvasSize.y()) * 2.0 - 1.0;
-		v.m_uv = Vec2(0.0);
-		Color c = color * 255.0;
-		v.m_color = {{U8(c[0]), U8(c[1]), U8(c[2]), U8(c[3])}};
-
-		m_vertMappings[stageId][m_vertCounts[stageId]] = v;
-
-		++m_vertCounts[stageId];
-	}
-}
-
-void UiInterfaceImpl::drawImage(UiImagePtr image, const Rect& uvs, const Rect& drawingRect, const UVec2& canvasSize)
-{
-	StageId stageId = StageId::TEXTURED_TRIANGLES;
-
-	ANKI_ASSERT(m_vertCounts[stageId] + 4 <= MAX_VERTS);
-}
-
-Error UiInterfaceImpl::loadImage(const CString& filename, IntrusivePtr<UiImage>& img)
-{
-	TextureResourcePtr texture;
-	ANKI_CHECK(m_rc->loadResource(filename, texture));
-	UiImageImpl* impl = getAllocator().newInstance<UiImageImpl>(this);
-	impl->m_resource = texture;
-	impl->m_texture = texture->getGrTexture();
-
-	img.reset(impl);
-
-	return ErrorCode::NONE;
-}
-
-Error UiInterfaceImpl::createR8Image(const WeakArray<U8>& data, const UVec2& size, IntrusivePtr<UiImage>& img)
-{
-#if 0
-	ANKI_ASSERT(data.getSize() == size.x() * size.y());
-
-	// Calc mip count
-	U s = min(size.x(), size.y());
-	U mipCount = 0;
-	while(s > 0)
-	{
-		++mipCount;
-		s /= 2;
-	}
-
-	// Allocate the texture
-	TextureInitInfo tinit;
-	tinit.m_width = size.x();
-	tinit.m_height = size.y();
-	tinit.m_format = PixelFormat(ComponentFormat::R8, TransformFormat::UNORM);
-	tinit.m_mipmapsCount = mipCount;
-	tinit.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
-	tinit.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
-
-	TexturePtr tex = m_gr->newInstance<Texture>(tinit);
-
-	// Load data
-	CommandBufferPtr cmdb = m_gr->newInstance<CommandBuffer>(CommandBufferInitInfo());
-	TransientMemoryToken token;
-	void* loadData = m_gr->allocateFrameTransientMemory(data.getSize(), BufferUsageBit::TEXTURE_UPLOAD_SOURCE, token);
-	memcpy(loadData, &data[0], data.getSize());
-	cmdb->uploadTextureSurface(tex, TextureSurfaceInfo(0, 0, 0, 0), token);
-
-	// Gen mips
-	cmdb->generateMipmaps2d(tex, 0, 0);
-	cmdb->flush();
-
-	// Create the UiImage
-	UiImageImpl* impl = getAllocator().newInstance<UiImageImpl>(this);
-	impl->m_texture = tex;
-	img.reset(impl);
-#endif
-
-	return ErrorCode::NONE;
-}
-
-Error UiInterfaceImpl::readFile(const CString& filename, DynamicArrayAuto<U8>& data)
-{
-	GenericResourcePtr rsrc;
-	ANKI_CHECK(m_rc->loadResource(filename, rsrc));
-
-	data.create(rsrc->getData().getSize());
-	memcpy(&data[0], &rsrc->getData()[0], data.getSize());
-
-	return ErrorCode::NONE;
-}
-
-} // end namespace anki

+ 0 - 98
src/anki/ui/UiInterfaceImpl.h

@@ -1,98 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/ui/UiInterface.h>
-#include <anki/Gr.h>
-#include <anki/resource/ShaderResource.h>
-#include <anki/resource/TextureResource.h>
-
-namespace anki
-{
-
-// Forward
-class GrManager;
-struct Vertex;
-
-/// @addtogroup ui
-/// @{
-
-/// Implements UiImage.
-class UiImageImpl : public UiImage
-{
-public:
-	UiImageImpl(UiInterface* i)
-		: UiImage(i)
-	{
-	}
-
-	TextureResourcePtr m_resource;
-	TexturePtr m_texture;
-};
-
-/// Implements UiInterface.
-class UiInterfaceImpl final : public UiInterface
-{
-public:
-	UiInterfaceImpl(UiAllocator alloc);
-
-	~UiInterfaceImpl();
-
-	ANKI_USE_RESULT Error init(GrManager* gr, ResourceManager* rc);
-
-	ANKI_USE_RESULT Error loadImage(const CString& filename, IntrusivePtr<UiImage>& img) override;
-
-	ANKI_USE_RESULT Error createR8Image(
-		const WeakArray<U8>& data, const UVec2& size, IntrusivePtr<UiImage>& img) override;
-
-	ANKI_USE_RESULT Error readFile(const CString& filename, DynamicArrayAuto<U8>& data) override;
-
-	void drawImage(UiImagePtr image, const Rect& uvs, const Rect& drawingRect, const UVec2& canvasSize) override;
-
-	void drawLines(const WeakArray<UVec2>& positions, const Color& color, const UVec2& canvasSize) override;
-
-	void beginRendering(CommandBufferPtr cmdb);
-
-	void endRendering();
-
-private:
-	const U MAX_VERTS = 128;
-	WeakPtr<GrManager> m_gr;
-	WeakPtr<ResourceManager> m_rc;
-
-	enum StageId
-	{
-		LINES,
-		TEXTURED_TRIANGLES,
-		COUNT
-	};
-
-	class Stage
-	{
-	public:
-		ShaderResourcePtr m_vShader;
-		ShaderResourcePtr m_fShader;
-		Array<BufferPtr, MAX_FRAMES_IN_FLIGHT> m_vertBuffs;
-	};
-
-	Array<Stage, StageId::COUNT> m_stages;
-
-	class ResourceGroupKey
-	{
-	public:
-		StageId m_stage;
-		U64 m_textureId;
-	};
-
-	// Intermediate
-	U8 m_timestamp = 0; ///< Local timestamp.
-	CommandBufferPtr m_cmdb;
-	Array<WeakPtr<Vertex>, StageId::COUNT> m_vertMappings;
-	Array<U32, StageId::COUNT> m_vertCounts;
-};
-/// @}
-
-} // end namespace anki

+ 23 - 0
src/anki/ui/UiManager.cpp

@@ -0,0 +1,23 @@
+// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/ui/UiManager.h>
+
+namespace anki
+{
+
+Error UiManager::init(HeapAllocator<U8> alloc, ResourceManager* resources, GrManager* gr)
+{
+	ANKI_ASSERT(resources);
+	ANKI_ASSERT(gr);
+
+	m_alloc = alloc;
+	m_resources = resources;
+	m_gr = gr;
+
+	return ErrorCode::NONE;
+}
+
+} // end namespace anki

+ 52 - 0
src/anki/ui/UiManager.h

@@ -0,0 +1,52 @@
+// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/ui/Common.h>
+
+namespace anki
+{
+
+// Forward
+class ResourceManager;
+class GrManager;
+
+/// @addtogroup ui
+/// @{
+
+/// UI manager.
+class UiManager
+{
+public:
+	UiManager();
+
+	~UiManager();
+
+	ANKI_USE_RESULT Error init(HeapAllocator<U8> alloc, ResourceManager* resources, GrManager* gr);
+
+	UiAllocator getAllocator() const
+	{
+		return m_alloc;
+	}
+
+	ResourceManager& getResourceManager()
+	{
+		return *m_resources;
+	}
+
+	GrManager& getGrManager()
+	{
+		return *m_gr;
+	}
+
+private:
+	UiAllocator m_alloc;
+	ResourceManager* m_resources = nullptr;
+	GrManager* m_gr = nullptr;
+};
+/// @}
+
+} // end namespace anki

+ 2 - 2
src/anki/ui/UiObject.cpp

@@ -4,14 +4,14 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <anki/ui/UiObject.h>
 #include <anki/ui/UiObject.h>
-#include <anki/ui/Canvas.h>
+#include <anki/ui/UiManager.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
 UiAllocator UiObject::getAllocator() const
 UiAllocator UiObject::getAllocator() const
 {
 {
-	return m_canvas->getAllocator();
+	return m_manager->getAllocator();
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 5 - 16
src/anki/ui/UiObject.h

@@ -6,7 +6,6 @@
 #pragma once
 #pragma once
 
 
 #include <anki/ui/Common.h>
 #include <anki/ui/Common.h>
-#include <anki/util/Ptr.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -18,28 +17,18 @@ namespace anki
 class UiObject
 class UiObject
 {
 {
 public:
 public:
-	UiObject(Canvas* canvas)
-		: m_canvas(canvas)
+	UiObject(UiManager* manager)
+		: m_manager(manager)
 	{
 	{
-		ANKI_ASSERT(canvas);
+		ANKI_ASSERT(manager);
 	}
 	}
 
 
 	virtual ~UiObject() = default;
 	virtual ~UiObject() = default;
 
 
 	UiAllocator getAllocator() const;
 	UiAllocator getAllocator() const;
 
 
-	Canvas& getCanvas()
-	{
-		return *m_canvas;
-	}
-
-	const Canvas& getCanvas() const
-	{
-		return *m_canvas;
-	}
-
-private:
-	WeakPtr<Canvas> m_canvas;
+protected:
+	UiManager* m_manager;
 };
 };
 /// @}
 /// @}
 
 

+ 0 - 60
src/anki/ui/Widget.cpp

@@ -1,60 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/ui/Widget.h>
-#include <anki/ui/Canvas.h>
-
-namespace anki
-{
-
-Widget::Widget(Canvas* canvas)
-	: UiObject(canvas)
-{
-	markForRepaint();
-}
-
-Widget::~Widget()
-{
-	ANKI_ASSERT(isMarkedForDeletion());
-	Hierarchy<Widget>::destroy(getAllocator());
-}
-
-void Widget::markForDeletion()
-{
-	if(!isMarkedForDeletion())
-	{
-		m_flags.set(MARKED_FOR_DELETION);
-		getCanvas().getMarkedForDeletionCount().fetchAdd(1);
-	}
-
-	Error err = visitChildren([](Widget& obj) -> Error {
-		obj.markForDeletion();
-		return ErrorCode::NONE;
-	});
-
-	(void)err;
-}
-
-void Widget::setRelativePosition(const UVec2& pos)
-{
-	m_posLocal = pos;
-	markForRepaint();
-}
-
-void Widget::setSizeLimits(const UVec2& min, const UVec2& max)
-{
-	m_minSize = min;
-	m_maxSize = max;
-	markForRepaint();
-}
-
-void Widget::setSize(const UVec2& size)
-{
-	m_size.x() = clamp(size.x(), m_minSize.x(), m_maxSize.x());
-	m_size.y() = clamp(size.y(), m_minSize.y(), m_maxSize.y());
-	markForRepaint();
-}
-
-} // end namespace anki

+ 0 - 121
src/anki/ui/Widget.h

@@ -1,121 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/ui/UiObject.h>
-#include <anki/util/Hierarchy.h>
-#include <anki/util/BitMask.h>
-
-namespace anki
-{
-
-/// @addtogroup ui
-/// @{
-
-/// Widget state.
-enum class WidgetState : U8
-{
-	DEFAULT,
-	HOVER,
-	ACTIVATED,
-	VISIBLE,
-	ENABLED
-};
-
-/// UI widget.
-class Widget : public UiObject, private Hierarchy<Widget>
-{
-	ANKI_WIDGET
-	friend Hierarchy<Widget>;
-
-public:
-	Widget(Canvas* canvas);
-
-	~Widget();
-
-	void markForDeletion();
-
-	Bool isMarkedForDeletion() const
-	{
-		return m_flags.get(MARKED_FOR_DELETION);
-	}
-
-	virtual void paint()
-	{
-	}
-
-	/// Set position relatively to the parent.
-	void setRelativePosition(const UVec2& pos);
-
-	const UVec2& getRelativePosition() const
-	{
-		return m_posLocal;
-	}
-
-	const UVec2& getCanvasPosition() const
-	{
-		return m_posCanvas;
-	}
-
-	/// Set prefered size.
-	void setSize(const UVec2& size);
-
-	const UVec2& getSize() const
-	{
-		return m_size;
-	}
-
-	/// Set the limts of size. The widget cannot exceede those.
-	void setSizeLimits(const UVec2& min, const UVec2& max);
-
-	void addWidget(Widget* widget)
-	{
-		addChild(getAllocator(), widget);
-	}
-
-	void addWidgetGridLayout(Widget* widget, U colum, U row);
-
-	Widget* getParentWidget()
-	{
-		return getParent();
-	}
-
-	const Widget* getParentWidget() const
-	{
-		return getParent();
-	}
-
-#ifdef ANKI_BUILD
-	void markForRepaint()
-	{
-		m_flags.set(NEEDS_REPAINT, true);
-	}
-
-	Bool isMarkedForRepaint() const
-	{
-		return m_flags.get(NEEDS_REPAINT);
-	}
-#endif
-
-private:
-	enum
-	{
-		MARKED_FOR_DELETION = 1 << 0,
-		NEEDS_REPAINT = 1 << 1
-	};
-
-	UVec2 m_minSize = UVec2(0u);
-	UVec2 m_maxSize = UVec2(MAX_U32);
-	UVec2 m_size = UVec2(0u);
-
-	UVec2 m_posLocal = UVec2(0u); ///< Local space.
-	UVec2 m_posCanvas = UVec2(0u); ///< World space.
-
-	BitMask<U8> m_flags;
-};
-/// @}
-
-} // end namespace anki

+ 1 - 1
src/anki/util/Assert.h

@@ -25,7 +25,7 @@ void akassert(const char* exprTxt, const char* file, int line, const char* func)
 	{                                                                                                                  \
 	{                                                                                                                  \
 		if(!(x))                                                                                                       \
 		if(!(x))                                                                                                       \
 		{                                                                                                              \
 		{                                                                                                              \
-			akassert(#x, ANKI_FILE, __LINE__, ANKI_FUNC);                                                              \
+			anki::akassert(#x, ANKI_FILE, __LINE__, ANKI_FUNC);                                                        \
 		}                                                                                                              \
 		}                                                                                                              \
 	} while(0)
 	} while(0)
 #define ANKI_ASSERTS_ENABLED 1
 #define ANKI_ASSERTS_ENABLED 1