Browse Source

More UI work. Have a working prototype

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
a6835b3ba9

+ 8 - 2
programs/Ui.ankiprog

@@ -16,7 +16,7 @@ http://www.anki3d.org/LICENSE
 
 layout(location = 0) in vec2 in_pos;
 layout(location = 1) in vec2 in_uv;
-layout(location = 3) in vec4 in_col;
+layout(location = 2) in vec4 in_col;
 
 layout(location = 0) out vec2 out_uv;
 layout(location = 1) out vec4 out_col;
@@ -26,12 +26,18 @@ out gl_PerVertex
 	vec4 gl_Position;
 };
 
+layout(ANKI_UBO_BINDING(0, 0)) uniform u_
+{
+	vec4 u_transform; // x: x scale, y: y scale, z: x transl, w: y transl
+};
+
 void main()
 {
 	out_uv = in_uv;
 	out_col = in_col;
 
-	gl_Position = vec4(in_pos, 0.0, 1.0);
+	vec2 pos = u_transform.xy * in_pos + u_transform.zw;
+	gl_Position = vec4(pos, 0.0, 1.0);
 }
 			]]></source>
 		</shader>

+ 1 - 1
src/anki/core/App.cpp

@@ -210,7 +210,7 @@ Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb,
 	//
 	m_input = m_heapAlloc.newInstance<Input>();
 
-	ANKI_CHECK(m_input->create(m_window));
+	ANKI_CHECK(m_input->init(m_window));
 
 	//
 	// ThreadPool

+ 1 - 1
src/anki/gr/gl/CommandBuffer.cpp

@@ -941,7 +941,7 @@ void CommandBuffer::drawElements(
 		idxBytes = sizeof(U32);
 	}
 
-	firstIndex = firstIndex + m_impl->m_state.m_idx.m_offset / idxBytes;
+	firstIndex = firstIndex * idxBytes + m_impl->m_state.m_idx.m_offset;
 
 	DrawElementsIndirectInfo info(count, instanceCount, firstIndex, baseVertex, baseInstance);
 	m_impl->pushBackNewCommand<Cmd>(convertPrimitiveTopology(topology), m_impl->m_state.m_idx.m_indexType, info);

+ 5 - 5
src/anki/input/Input.h

@@ -42,10 +42,10 @@ public:
 		ANKI_ASSERT(m_nativeWindow == nullptr);
 	}
 
-	ANKI_USE_RESULT Error create(NativeWindow* nativeWindow)
+	ANKI_USE_RESULT Error init(NativeWindow* nativeWindow)
 	{
 		reset();
-		return init(nativeWindow);
+		return initInternal(nativeWindow);
 	}
 
 	U getKey(KeyCode i) const
@@ -53,7 +53,7 @@ public:
 		return m_keys[static_cast<U>(i)];
 	}
 
-	U getMouseButton(U32 i) const
+	U getMouseButton(MouseButton i) const
 	{
 		return m_mouseBtns[i];
 	}
@@ -108,7 +108,7 @@ private:
 	Array<U32, static_cast<U>(KeyCode::COUNT)> m_keys;
 
 	/// Mouse btns. Supporting 3 btns & wheel. @see keys
-	Array<U32, 8> m_mouseBtns;
+	Array<U32, U(MouseButton::COUNT)> m_mouseBtns;
 	/// @}
 
 	Vec2 m_mousePosNdc = Vec2(2.0); ///< The coords are in the NDC space
@@ -118,7 +118,7 @@ private:
 	Bool8 m_lockCurs = false;
 
 	/// Initialize the platform's input system
-	ANKI_USE_RESULT Error init(NativeWindow* nativeWindow);
+	ANKI_USE_RESULT Error initInternal(NativeWindow* nativeWindow);
 
 	/// Destroy the platform specific input system
 	void destroy();

+ 37 - 5
src/anki/input/InputSdl.cpp

@@ -12,7 +12,27 @@
 namespace anki
 {
 
-Error Input::init(NativeWindow* nativeWindow)
+static MouseButton sdlMouseButtonToAnKi(const U32 sdl)
+{
+	MouseButton out = MouseButton::COUNT;
+
+	switch(sdl)
+	{
+	case SDL_BUTTON_LEFT:
+		out = MouseButton::LEFT;
+		break;
+	case SDL_BUTTON_RIGHT:
+		out = MouseButton::RIGHT;
+		break;
+	case SDL_BUTTON_MIDDLE:
+		out = MouseButton::MIDDLE;
+		break;
+	}
+
+	return out;
+}
+
+Error Input::initInternal(NativeWindow* nativeWindow)
 {
 	ANKI_ASSERT(nativeWindow);
 	m_nativeWindow = nativeWindow;
@@ -306,18 +326,30 @@ Error Input::handleEvents()
 		{
 		case SDL_KEYDOWN:
 			akkey = m_impl->m_sdlToAnki[event.key.keysym.sym];
-			m_keys[static_cast<U>(akkey)] = 1;
+			m_keys[akkey] = 1;
 			break;
 		case SDL_KEYUP:
 			akkey = m_impl->m_sdlToAnki[event.key.keysym.sym];
-			m_keys[static_cast<U>(akkey)] = 0;
+			m_keys[akkey] = 0;
 			break;
 		case SDL_MOUSEBUTTONDOWN:
-			// XXX
+		{
+			MouseButton mb = sdlMouseButtonToAnKi(event.button.button);
+			if(mb != MouseButton::COUNT)
+			{
+				m_mouseBtns[mb] = 1;
+			}
 			break;
+		}
 		case SDL_MOUSEBUTTONUP:
-			// XXX
+		{
+			MouseButton mb = sdlMouseButtonToAnKi(event.button.button);
+			if(mb != MouseButton::COUNT)
+			{
+				m_mouseBtns[mb] = 0;
+			}
 			break;
+		}
 		case SDL_MOUSEMOTION:
 			m_mousePosNdc.x() = (F32)event.button.x / m_nativeWindow->getWidth() * 2.0 - 1.0;
 			m_mousePosNdc.y() = -((F32)event.button.y / m_nativeWindow->getHeight() * 2.0 - 1.0);

+ 3 - 1
src/anki/input/KeyCode.h

@@ -268,7 +268,9 @@ enum class MouseButton
 {
 	LEFT,
 	MIDDLE,
-	RIGHT
+	RIGHT,
+
+	COUNT
 };
 
 } // end namespace anki

+ 40 - 3
src/anki/ui/Canvas.cpp

@@ -8,6 +8,7 @@
 #include <anki/ui/UiManager.h>
 #include <anki/resource/ResourceManager.h>
 #include <anki/core/StagingGpuMemoryManager.h>
+#include <anki/input/Input.h>
 
 namespace anki
 {
@@ -59,7 +60,23 @@ Error Canvas::init(FontPtr font)
 
 void Canvas::handleInput()
 {
-	// TODO
+	// Start
+	const Input& in = m_manager->getInput();
+	nk_input_begin(&m_nkCtx);
+
+	Array<U32, 4> viewport = {{0, 0, 1920, 1080}}; // TODO
+
+	// Handle mouse
+	Vec2 mousePosf = in.getMousePosition() / 2.0f + 0.5f;
+	mousePosf.y() = 1.0f - mousePosf.y();
+	UVec2 mousePos(mousePosf.x() * viewport[2], mousePosf.y() * viewport[3]);
+
+	nk_input_motion(&m_nkCtx, mousePos.x(), mousePos.y());
+	nk_input_button(&m_nkCtx, NK_BUTTON_LEFT, mousePos.x(), mousePos.y(), in.getMouseButton(MouseButton::LEFT) > 1);
+	nk_input_button(&m_nkCtx, NK_BUTTON_RIGHT, mousePos.x(), mousePos.y(), in.getMouseButton(MouseButton::RIGHT) > 1);
+
+	// Done
+	nk_input_end(&m_nkCtx);
 }
 
 void Canvas::beginBuilding()
@@ -80,6 +97,8 @@ void Canvas::endBuilding()
 
 void Canvas::appendToCommandBuffer(CommandBufferPtr cmdb)
 {
+	Array<U32, 4> viewport = {{0, 0, 1920, 1080}}; // TODO
+
 	//
 	// Allocate vertex data
 	//
@@ -151,6 +170,18 @@ void Canvas::appendToCommandBuffer(CommandBufferPtr cmdb)
 	//
 	// Draw
 	//
+
+	// Uniforms
+	StagingGpuMemoryToken uboToken;
+	Vec4* trf = static_cast<Vec4*>(
+		m_manager->getStagingGpuMemoryManager().allocateFrame(sizeof(Vec4), StagingGpuMemoryType::UNIFORM, uboToken));
+	trf->x() = 2.0f / (viewport[2] - viewport[0]);
+	trf->y() = -2.0f / (viewport[3] - viewport[1]);
+	trf->z() = -1.0f;
+	trf->w() = 1.0f;
+	cmdb->bindUniformBuffer(0, 0, uboToken.m_buffer, uboToken.m_offset, uboToken.m_range);
+
+	// Vert & idx buffers
 	cmdb->bindVertexBuffer(0, vertCtx.m_token.m_buffer, vertCtx.m_token.m_offset, sizeof(Vert));
 	cmdb->setVertexAttribute(0, 0, PixelFormat(ComponentFormat::R32G32, TransformFormat::FLOAT), 0);
 	cmdb->setVertexAttribute(1, 0, PixelFormat(ComponentFormat::R32G32, TransformFormat::FLOAT), sizeof(Vec2));
@@ -158,11 +189,11 @@ void Canvas::appendToCommandBuffer(CommandBufferPtr cmdb)
 
 	cmdb->bindIndexBuffer(idxCtx.m_token.m_buffer, idxCtx.m_token.m_offset, IndexType::U16);
 
-	cmdb->setViewport(0, 0, 1024, 1024); // TODO
+	cmdb->setViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
 
+	// Prog & tex
 	cmdb->bindShaderProgram(m_texGrProg);
 	ShaderProgramPtr boundProg = m_texGrProg;
-	cmdb->setBlendFactors(0, BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA);
 
 	const nk_draw_command* cmd = nullptr;
 	U offset = 0;
@@ -192,6 +223,12 @@ void Canvas::appendToCommandBuffer(CommandBufferPtr cmdb)
 			boundProg = progToBind;
 		}
 
+		// Other state
+		cmdb->setBlendFactors(0, BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA);
+		cmdb->setDepthWrite(false);
+		cmdb->setDepthCompareOperation(CompareOperation::ALWAYS);
+		cmdb->setCullMode(FaceSelectionBit::FRONT);
+
 		// TODO set scissor
 
 		// Draw

+ 5 - 1
src/anki/ui/Font.cpp

@@ -33,7 +33,11 @@ Error Font::init(const CString& filename, U32 fontHeight)
 	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);
+
+	struct nk_font_config cfg = nk_font_config(fontHeight);
+	cfg.oversample_h = 8;
+	cfg.oversample_v = 8;
+	m_font = nk_font_atlas_add_from_memory(&m_atlas, &fontData[0], fontData.getSize(), fontHeight, &cfg);
 
 	int width, height;
 	const void* img = nk_font_atlas_bake(&m_atlas, &width, &height, NK_FONT_ATLAS_RGBA32);

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

@@ -6,6 +6,7 @@
 #pragma once
 
 #include <anki/util/Assert.h>
+#include <cstring>
 
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_STANDARD_VARARGS
@@ -27,4 +28,5 @@
 // #define NK_STRTOD
 // #define NK_DTOA
 // #define NK_VSNPRINTF
+#define NK_MEMCPY memcpy
 #include <nuklear/nuklear.h>

+ 3 - 1
src/anki/ui/UiManager.cpp

@@ -17,16 +17,18 @@ UiManager::~UiManager()
 }
 
 Error UiManager::init(
-	HeapAllocator<U8> alloc, ResourceManager* resources, GrManager* gr, StagingGpuMemoryManager* gpuMem)
+	HeapAllocator<U8> alloc, ResourceManager* resources, GrManager* gr, StagingGpuMemoryManager* gpuMem, Input* input)
 {
 	ANKI_ASSERT(resources);
 	ANKI_ASSERT(gr);
 	ANKI_ASSERT(gpuMem);
+	ANKI_ASSERT(input);
 
 	m_alloc = alloc;
 	m_resources = resources;
 	m_gr = gr;
 	m_gpuMem = gpuMem;
+	m_input = input;
 
 	return ErrorCode::NONE;
 }

+ 13 - 2
src/anki/ui/UiManager.h

@@ -14,6 +14,7 @@ namespace anki
 class ResourceManager;
 class GrManager;
 class StagingGpuMemoryManager;
+class Input;
 
 /// @addtogroup ui
 /// @{
@@ -26,8 +27,11 @@ public:
 
 	~UiManager();
 
-	ANKI_USE_RESULT Error init(
-		HeapAllocator<U8> alloc, ResourceManager* resources, GrManager* gr, StagingGpuMemoryManager* gpuMem);
+	ANKI_USE_RESULT Error init(HeapAllocator<U8> alloc,
+		ResourceManager* resources,
+		GrManager* gr,
+		StagingGpuMemoryManager* gpuMem,
+		Input* input);
 
 	UiAllocator getAllocator() const
 	{
@@ -52,6 +56,12 @@ public:
 		return *m_gpuMem;
 	}
 
+	const Input& getInput() const
+	{
+		ANKI_ASSERT(m_input);
+		return *m_input;
+	}
+
 	/// Create a new UI object.
 	template<typename T, typename... Args>
 	ANKI_USE_RESULT Error newInstance(IntrusivePtr<T>& ptr, Args&&... args)
@@ -65,6 +75,7 @@ private:
 	ResourceManager* m_resources = nullptr;
 	GrManager* m_gr = nullptr;
 	StagingGpuMemoryManager* m_gpuMem = nullptr;
+	Input* m_input = nullptr;
 };
 /// @}
 

+ 21 - 4
tests/ui/Ui.cpp

@@ -7,6 +7,7 @@
 #include <anki/core/Config.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/Ui.h>
+#include <anki/Input.h>
 #include <anki/core/StagingGpuMemoryManager.h>
 
 namespace anki
@@ -29,7 +30,16 @@ public:
 	void build(CanvasPtr canvas) final
 	{
 		nk_context* ctx = &canvas->getContext();
-		nk_begin(ctx, "Window", nk_rect(10, 10, 200, 800), NK_WINDOW_NO_SCROLLBAR);
+
+		if(nk_begin(ctx,
+			   "Window name",
+			   nk_rect(10, 10, 200, 800),
+			   NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | NK_WINDOW_MINIMIZABLE | NK_WINDOW_TITLE))
+		{
+			nk_layout_row_dynamic(ctx, 30, 1);
+			nk_label(ctx, "Label0", NK_TEXT_ALIGN_LEFT);
+			nk_label(ctx, "Label1", NK_TEXT_ALIGN_LEFT);
+		}
 
 		nk_end(ctx);
 	}
@@ -40,20 +50,23 @@ ANKI_TEST(Ui, Ui)
 	Config cfg;
 	initConfig(cfg);
 	cfg.set("vsync", 1);
-	cfg.set("debugContext", 1);
+	cfg.set("debugContext", 0);
 
 	NativeWindow* win = createWindow(cfg);
+	Input* in = new Input();
 	GrManager* gr = createGrManager(cfg, win);
 	PhysicsWorld* physics;
 	ResourceFilesystem* fs;
 	ResourceManager* resource = createResourceManager(cfg, gr, physics, fs);
 	UiManager* ui = new UiManager();
 
+	ANKI_TEST_EXPECT_NO_ERR(in->init(win));
+
 	StagingGpuMemoryManager* stagingMem = new StagingGpuMemoryManager();
 	ANKI_TEST_EXPECT_NO_ERR(stagingMem->init(gr, cfg));
 
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
-	ANKI_TEST_EXPECT_NO_ERR(ui->init(alloc, resource, gr, stagingMem));
+	ANKI_TEST_EXPECT_NO_ERR(ui->init(alloc, resource, gr, stagingMem, in));
 
 	{
 		FontPtr font;
@@ -67,12 +80,15 @@ ANKI_TEST(Ui, Ui)
 
 		FramebufferPtr fb = createDefaultFb(*gr);
 
-		U iterations = 200;
+		U iterations = 300;
 		while(iterations--)
 		{
+			ANKI_TEST_EXPECT_NO_ERR(in->handleEvents());
 			HighRezTimer timer;
 			timer.start();
 
+			canvas->handleInput();
+
 			canvas->beginBuilding();
 			label->build(canvas);
 			canvas->endBuilding();
@@ -106,6 +122,7 @@ ANKI_TEST(Ui, Ui)
 	delete physics;
 	delete fs;
 	delete gr;
+	delete in;
 	delete win;
 }