diff --git a/3rdparty/imguizmo b/3rdparty/imguizmo index b10e91756d..4d3445248b 160000 --- a/3rdparty/imguizmo +++ b/3rdparty/imguizmo @@ -1 +1 @@ -Subproject commit b10e91756d32395f5c1fefd417899b657ed7cb88 +Subproject commit 4d3445248b9d598b92e877d752fd1f7fe6c1f134 diff --git a/examples_tests b/examples_tests index 779ce1fe46..d9dfdd9eb4 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 779ce1fe4630135f82c1bcee1c57e3a37c3fa5cf +Subproject commit d9dfdd9eb42540e8c036ea43a4466942b4b3d3a3 diff --git a/include/nbl/builtin/hlsl/algorithm.hlsl b/include/nbl/builtin/hlsl/algorithm.hlsl index 66442a11a1..1aaaa02cd8 100644 --- a/include/nbl/builtin/hlsl/algorithm.hlsl +++ b/include/nbl/builtin/hlsl/algorithm.hlsl @@ -73,20 +73,16 @@ namespace impl rhs ^= lhs; lhs ^= rhs; } -#else - template - NBL_CONSTEXPR_FUNC void swap(NBL_REF_ARG(T) lhs, NBL_REF_ARG(T) rhs) - { - std::swap(lhs, rhs); - } #endif } +#ifdef __HLSL_VERSION template NBL_CONSTEXPR_FUNC void swap(NBL_REF_ARG(T) lhs, NBL_REF_ARG(T) rhs) { impl::swap(lhs, rhs); } +#endif namespace impl diff --git a/include/nbl/builtin/hlsl/matrix_utils/transformation_matrix_utils.hlsl b/include/nbl/builtin/hlsl/matrix_utils/transformation_matrix_utils.hlsl index dc2cdf3f02..918cdc7e60 100644 --- a/include/nbl/builtin/hlsl/matrix_utils/transformation_matrix_utils.hlsl +++ b/include/nbl/builtin/hlsl/matrix_utils/transformation_matrix_utils.hlsl @@ -8,25 +8,25 @@ namespace nbl { namespace hlsl { -//TODO: stolen from cameraz branch, don't have epsilonEqual here, maybe uncomment when merging from imguizmo-lights branch -//// TODO: -> move somewhere else and nbl:: to implement it -//template -//bool isOrthoBase(const T& x, const T& y, const T& z, const E epsilon = 1e-6) -//{ -// auto isNormalized = [](const auto& v, const auto& epsilon) -> bool -// { -// return glm::epsilonEqual(glm::length(v), 1.0, epsilon); -// }; -// -// auto isOrthogonal = [](const auto& a, const auto& b, const auto& epsilon) -> bool -// { -// return glm::epsilonEqual(glm::dot(a, b), 0.0, epsilon); -// }; -// -// return isNormalized(x, epsilon) && isNormalized(y, epsilon) && isNormalized(z, epsilon) && -// isOrthogonal(x, y, epsilon) && isOrthogonal(x, z, epsilon) && isOrthogonal(y, z, epsilon); -//} -//// <- + +// TODO: -> move somewhere else and nbl:: to implement it +template +bool isOrthoBase(const T& x, const T& y, const T& z, const E epsilon = 1e-6) +{ + auto isNormalized = [](const auto& v, const auto& epsilon) -> bool + { + return glm::epsilonEqual(glm::length(v), 1.0, epsilon); + }; + + auto isOrthogonal = [](const auto& a, const auto& b, const auto& epsilon) -> bool + { + return glm::epsilonEqual(glm::dot(a, b), 0.0, epsilon); + }; + + return isNormalized(x, epsilon) && isNormalized(y, epsilon) && isNormalized(z, epsilon) && + isOrthogonal(x, y, epsilon) && isOrthogonal(x, z, epsilon) && isOrthogonal(y, z, epsilon); +} +// <- template matrix getMatrix3x4As4x4(const matrix& mat) diff --git a/include/nbl/core/decl/smart_refctd_ptr.h b/include/nbl/core/decl/smart_refctd_ptr.h index 7c231fea4b..74fdf61693 100644 --- a/include/nbl/core/decl/smart_refctd_ptr.h +++ b/include/nbl/core/decl/smart_refctd_ptr.h @@ -144,6 +144,15 @@ smart_refctd_ptr move_and_dynamic_cast(smart_refctd_ptr& smart_ptr); template< class U, class T > smart_refctd_ptr move_and_dynamic_cast(smart_refctd_ptr&& smart_ptr) {return move_and_dynamic_cast(smart_ptr);} +template +struct is_smart_refctd_ptr : std::false_type {}; + +template +struct is_smart_refctd_ptr> : std::true_type {}; + +template +inline constexpr bool is_smart_refctd_ptr_v = is_smart_refctd_ptr::value; + } // end namespace nbl::core /* diff --git a/include/nbl/core/math/glslFunctions.h b/include/nbl/core/math/glslFunctions.h index 2bd17cd642..1412be95d5 100644 --- a/include/nbl/core/math/glslFunctions.h +++ b/include/nbl/core/math/glslFunctions.h @@ -362,6 +362,7 @@ NBL_FORCE_INLINE vectorSIMDf cross(const vectorSIMDf& a, const vect template NBL_FORCE_INLINE T normalize(const T& v) { + // TODO: THIS CREATES AMGIGUITY WITH GLM:: NAMESPACE! auto d = dot(v, v); #ifdef __NBL_FAST_MATH return v * core::inversesqrt(d); @@ -371,6 +372,7 @@ NBL_FORCE_INLINE T normalize(const T& v) } // TODO : matrixCompMult, outerProduct, inverse +// Arek: old and to be killed (missing .tcc include?), no definition in Nabla causing linker errors template NBL_FORCE_INLINE T transpose(const T& m); template<> diff --git a/include/nbl/ext/ImGui/ImGui.h b/include/nbl/ext/ImGui/ImGui.h index 5f3c1d5f08..9456ae0e4f 100644 --- a/include/nbl/ext/ImGui/ImGui.h +++ b/include/nbl/ext/ImGui/ImGui.h @@ -99,6 +99,15 @@ class UI final : public core::IReferenceCounted //! optional, no cache used if not provided core::smart_refctd_ptr pipelineCache = nullptr; + + struct PrecompiledShaders + { + core::smart_refctd_ptr vertex = nullptr; + core::smart_refctd_ptr fragment = nullptr; + }; + + //! optional, precompiled spirv shaders + std::optional spirv = std::nullopt; }; //! parameters which may change every frame, used with the .update call to interact with ImGuiIO; we require a very *required* minimum - if you need to cover more IO options simply get the IO with ImGui::GetIO() to customize them (they all have default values you can change before calling the .update) diff --git a/include/nbl/ext/ScreenShot/ScreenShot.h b/include/nbl/ext/ScreenShot/ScreenShot.h index 4e71749cd7..64f5e526d1 100644 --- a/include/nbl/ext/ScreenShot/ScreenShot.h +++ b/include/nbl/ext/ScreenShot/ScreenShot.h @@ -27,7 +27,12 @@ inline core::smart_refctd_ptr createScreenShot( const ACCESS_FLAGS accessMask, const IImage::LAYOUT imageLayout) { - assert(bool(logicalDevice->getPhysicalDevice()->getQueueFamilyProperties().begin()[queue->getFamilyIndex()].queueFlags.value & IQueue::FAMILY_FLAGS::TRANSFER_BIT)); + { + const auto queueFlags = logicalDevice->getPhysicalDevice()->getQueueFamilyProperties().begin()[queue->getFamilyIndex()].queueFlags; + const auto required = core::bitflag(IQueue::FAMILY_FLAGS::TRANSFER_BIT) | IQueue::FAMILY_FLAGS::GRAPHICS_BIT | IQueue::FAMILY_FLAGS::COMPUTE_BIT; + if (!queueFlags.hasAnyFlag(required)) + logicalDevice->getLogger()->log("ScreenShot: queue family %u lacks transfer/graphics/compute flags; continuing anyway.", system::ILogger::ELL_WARNING, queue->getFamilyIndex()); + } auto fetchedImageViewParmas = gpuImageView->getCreationParameters(); auto gpuImage = fetchedImageViewParmas.image; @@ -35,12 +40,17 @@ inline core::smart_refctd_ptr createScreenShot( if(!fetchedGpuImageParams.usage.hasFlags(IImage::EUF_TRANSFER_SRC_BIT)) { - assert(false); + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: source image missing TRANSFER_SRC usage.", system::ILogger::ELL_ERROR); return nullptr; } if (isBlockCompressionFormat(fetchedGpuImageParams.format)) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: block-compressed formats are not supported.", system::ILogger::ELL_ERROR); return nullptr; + } core::smart_refctd_ptr gpuTexelBuffer; @@ -48,10 +58,28 @@ inline core::smart_refctd_ptr createScreenShot( { // commandbuffer should refcount the pool, so it should be 100% legal to drop at the end of the scope auto gpuCommandPool = logicalDevice->createCommandPool(queue->getFamilyIndex(),IGPUCommandPool::CREATE_FLAGS::TRANSIENT_BIT); + if (!gpuCommandPool) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to create command pool.", system::ILogger::ELL_ERROR); + return nullptr; + } gpuCommandPool->createCommandBuffers(IGPUCommandPool::BUFFER_LEVEL::PRIMARY, 1u, &gpuCommandBuffer); - assert(gpuCommandBuffer); + if (!gpuCommandBuffer) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to create command buffer.", system::ILogger::ELL_ERROR); + return nullptr; + } + } + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: recording command buffer.", system::ILogger::ELL_INFO); + if (!gpuCommandBuffer->begin(IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT)) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to begin command buffer.", system::ILogger::ELL_ERROR); + return nullptr; } - gpuCommandBuffer->begin(IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT); { auto extent = gpuImage->getMipSize(); @@ -68,9 +96,27 @@ inline core::smart_refctd_ptr createScreenShot( bufferCreationParams.size = extent.x*extent.y*extent.z*getTexelOrBlockBytesize(fetchedGpuImageParams.format); bufferCreationParams.usage = IBuffer::EUF_TRANSFER_DST_BIT; gpuTexelBuffer = logicalDevice->createBuffer(std::move(bufferCreationParams)); + if (!gpuTexelBuffer) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to create GPU texel buffer.", system::ILogger::ELL_ERROR); + return nullptr; + } auto gpuTexelBufferMemReqs = gpuTexelBuffer->getMemoryReqs(); gpuTexelBufferMemReqs.memoryTypeBits &= logicalDevice->getPhysicalDevice()->getDownStreamingMemoryTypeBits(); + if (!gpuTexelBufferMemReqs.memoryTypeBits) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: no down-streaming memory type for texel buffer.", system::ILogger::ELL_ERROR); + return nullptr; + } auto gpuTexelBufferMem = logicalDevice->allocate(gpuTexelBufferMemReqs, gpuTexelBuffer.get()); + if (!gpuTexelBufferMem.isValid()) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to allocate texel buffer memory.", system::ILogger::ELL_ERROR); + return nullptr; + } IGPUCommandBuffer::SPipelineBarrierDependencyInfo info = {}; decltype(info)::image_barrier_t barrier = {}; @@ -102,7 +148,12 @@ inline core::smart_refctd_ptr createScreenShot( gpuCommandBuffer->pipelineBarrier(EDF_NONE,info); } } - gpuCommandBuffer->end(); + if (!gpuCommandBuffer->end()) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to end command buffer.", system::ILogger::ELL_ERROR); + return nullptr; + } auto signalSemaphore = logicalDevice->createSemaphore(0); @@ -124,22 +175,63 @@ inline core::smart_refctd_ptr createScreenShot( info.waitSemaphores = { &waitSemaphoreInfo, &waitSemaphoreInfo + 1 }; } - queue->submit({ &info, &info + 1}); + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: submitting copy command buffer.", system::ILogger::ELL_INFO); + if (queue->submit({ &info, &info + 1}) != IQueue::RESULT::SUCCESS) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to submit copy command buffer.", system::ILogger::ELL_ERROR); + return nullptr; + } ISemaphore::SWaitInfo waitInfo{ signalSemaphore.get(), 1u}; + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: waiting for copy completion.", system::ILogger::ELL_INFO); if (logicalDevice->blockForSemaphores({&waitInfo, &waitInfo + 1}) != ISemaphore::WAIT_RESULT::SUCCESS) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to wait for copy completion.", system::ILogger::ELL_ERROR); return nullptr; + } core::smart_refctd_ptr cpuImageView; { const auto gpuTexelBufferSize = gpuTexelBuffer->getSize(); // If you get validation errors from the `invalidateMappedMemoryRanges` we need to expose VK_WHOLE_BUFFER equivalent constant - ILogicalDevice::MappedMemoryRange mappedMemoryRange(gpuTexelBuffer->getBoundMemory().memory,0u,gpuTexelBufferSize); + auto* allocation = gpuTexelBuffer->getBoundMemory().memory; + if (!allocation) + return nullptr; - if (gpuTexelBuffer->getBoundMemory().memory->haveToMakeVisible()) + bool mappedHere = false; + if (!allocation->getMappedPointer()) + { + const IDeviceMemoryAllocation::MemoryRange range = { 0u, gpuTexelBufferSize }; + if (!allocation->map(range, IDeviceMemoryAllocation::EMCAF_READ)) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to map texel buffer memory.", system::ILogger::ELL_ERROR); + return nullptr; + } + mappedHere = true; + } + + ILogicalDevice::MappedMemoryRange mappedMemoryRange(allocation,0u,gpuTexelBufferSize); + if (allocation->haveToMakeVisible()) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: invalidating mapped range.", system::ILogger::ELL_INFO); logicalDevice->invalidateMappedMemoryRanges(1u,&mappedMemoryRange); + } auto cpuNewImage = ICPUImage::create(std::move(fetchedGpuImageParams)); + if (!cpuNewImage) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to create CPU image.", system::ILogger::ELL_ERROR); + if (mappedHere) + allocation->unmap(); + return nullptr; + } auto regions = core::make_refctd_dynamic_array>(1u); ICPUImage::SBufferCopy& region = regions->front(); @@ -155,10 +247,22 @@ inline core::smart_refctd_ptr createScreenShot( region.imageExtent = cpuNewImage->getCreationParameters().extent; auto cpuNewTexelBuffer = ICPUBuffer::create({ gpuTexelBufferSize }); + if (!cpuNewTexelBuffer) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: failed to create CPU buffer.", system::ILogger::ELL_ERROR); + if (mappedHere) + allocation->unmap(); + return nullptr; + } + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: copying GPU data to CPU buffer.", system::ILogger::ELL_INFO); { - memcpy(cpuNewTexelBuffer->getPointer(), gpuTexelBuffer->getBoundMemory().memory->getMappedPointer(), gpuTexelBuffer->getSize()); + memcpy(cpuNewTexelBuffer->getPointer(), allocation->getMappedPointer(), gpuTexelBuffer->getSize()); } cpuNewImage->setBufferAndRegions(core::smart_refctd_ptr(cpuNewTexelBuffer), regions); + if (mappedHere) + allocation->unmap(); { auto newCreationParams = cpuNewImage->getCreationParameters(); @@ -190,6 +294,12 @@ inline bool createScreenShot( { assert(outFile->getFlags()&system::IFile::ECF_WRITE); auto cpuImageView = createScreenShot(logicalDevice,queue,semaphore,gpuImageView,accessMask,imageLayout); + if (!cpuImageView) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: GPU readback failed, no image to write.", system::ILogger::ELL_ERROR); + return false; + } IAssetWriter::SAssetWriteParams writeParams(cpuImageView.get()); return assetManager->writeAsset(outFile,writeParams); } @@ -205,6 +315,12 @@ inline bool createScreenShot( const ACCESS_FLAGS accessMask = ACCESS_FLAGS::MEMORY_WRITE_BITS) { auto cpuImageView = createScreenShot(logicalDevice,queue,semaphore,gpuImageView,accessMask,imageLayout); + if (!cpuImageView) + { + if (auto* logger = logicalDevice->getLogger()) + logger->log("ScreenShot: GPU readback failed, no image to write.", system::ILogger::ELL_ERROR); + return false; + } IAssetWriter::SAssetWriteParams writeParams(cpuImageView.get()); return assetManager->writeAsset(filename.string(),writeParams); // TODO: Use std::filesystem::path } @@ -212,4 +328,4 @@ inline bool createScreenShot( } // namespace nbl::ext::ScreenShot -#endif \ No newline at end of file +#endif diff --git a/include/nbl/ui/KeyCodes.h b/include/nbl/ui/KeyCodes.h index b6d05aed36..fb749cb801 100644 --- a/include/nbl/ui/KeyCodes.h +++ b/include/nbl/ui/KeyCodes.h @@ -266,6 +266,136 @@ constexpr char keyCodeToChar(E_KEY_CODE code, bool shiftPressed) return result; } +constexpr E_KEY_CODE stringToKeyCode(std::string_view str) +{ + if (str == "BACKSPACE") return EKC_BACKSPACE; + if (str == "TAB") return EKC_TAB; + if (str == "CLEAR") return EKC_CLEAR; + if (str == "ENTER") return EKC_ENTER; + if (str == "LEFT_SHIFT") return EKC_LEFT_SHIFT; + if (str == "RIGHT_SHIFT") return EKC_RIGHT_SHIFT; + if (str == "LEFT_CONTROL") return EKC_LEFT_CONTROL; + if (str == "RIGHT_CONTROL") return EKC_RIGHT_CONTROL; + if (str == "LEFT_ALT") return EKC_LEFT_ALT; + if (str == "RIGHT_ALT") return EKC_RIGHT_ALT; + if (str == "PAUSE") return EKC_PAUSE; + if (str == "CAPS_LOCK") return EKC_CAPS_LOCK; + if (str == "ESCAPE") return EKC_ESCAPE; + if (str == "SPACE") return EKC_SPACE; + if (str == "PAGE_UP") return EKC_PAGE_UP; + if (str == "PAGE_DOWN") return EKC_PAGE_DOWN; + if (str == "END") return EKC_END; + if (str == "HOME") return EKC_HOME; + if (str == "LEFT_ARROW") return EKC_LEFT_ARROW; + if (str == "RIGHT_ARROW") return EKC_RIGHT_ARROW; + if (str == "DOWN_ARROW") return EKC_DOWN_ARROW; + if (str == "UP_ARROW") return EKC_UP_ARROW; + if (str == "SELECT") return EKC_SELECT; + if (str == "PRINT") return EKC_PRINT; + if (str == "EXECUTE") return EKC_EXECUTE; + if (str == "PRINT_SCREEN") return EKC_PRINT_SCREEN; + if (str == "INSERT") return EKC_INSERT; + if (str == "DELETE") return EKC_DELETE; + if (str == "HELP") return EKC_HELP; + if (str == "LEFT_WIN") return EKC_LEFT_WIN; + if (str == "RIGHT_WIN") return EKC_RIGHT_WIN; + if (str == "APPS") return EKC_APPS; + if (str == "COMMA") return EKC_COMMA; + if (str == "PERIOD") return EKC_PERIOD; + if (str == "SEMICOLON") return EKC_SEMICOLON; + if (str == "OPEN_BRACKET") return EKC_OPEN_BRACKET; + if (str == "CLOSE_BRACKET") return EKC_CLOSE_BRACKET; + if (str == "BACKSLASH") return EKC_BACKSLASH; + if (str == "APOSTROPHE") return EKC_APOSTROPHE; + if (str == "ADD") return EKC_ADD; + if (str == "SUBTRACT") return EKC_SUBTRACT; + if (str == "MULTIPLY") return EKC_MULTIPLY; + if (str == "DIVIDE") return EKC_DIVIDE; + + if (str == "A" || str == "a") return EKC_A; + if (str == "B" || str == "b") return EKC_B; + if (str == "C" || str == "c") return EKC_C; + if (str == "D" || str == "d") return EKC_D; + if (str == "E" || str == "e") return EKC_E; + if (str == "F" || str == "f") return EKC_F; + if (str == "G" || str == "g") return EKC_G; + if (str == "H" || str == "h") return EKC_H; + if (str == "I" || str == "i") return EKC_I; + if (str == "J" || str == "j") return EKC_J; + if (str == "K" || str == "k") return EKC_K; + if (str == "L" || str == "l") return EKC_L; + if (str == "M" || str == "m") return EKC_M; + if (str == "N" || str == "n") return EKC_N; + if (str == "O" || str == "o") return EKC_O; + if (str == "P" || str == "p") return EKC_P; + if (str == "Q" || str == "q") return EKC_Q; + if (str == "R" || str == "r") return EKC_R; + if (str == "S" || str == "s") return EKC_S; + if (str == "T" || str == "t") return EKC_T; + if (str == "U" || str == "u") return EKC_U; + if (str == "V" || str == "v") return EKC_V; + if (str == "W" || str == "w") return EKC_W; + if (str == "X" || str == "x") return EKC_X; + if (str == "Y" || str == "y") return EKC_Y; + if (str == "Z" || str == "z") return EKC_Z; + + if (str == "0") return EKC_0; + if (str == "1") return EKC_1; + if (str == "2") return EKC_2; + if (str == "3") return EKC_3; + if (str == "4") return EKC_4; + if (str == "5") return EKC_5; + if (str == "6") return EKC_6; + if (str == "7") return EKC_7; + if (str == "8") return EKC_8; + if (str == "9") return EKC_9; + + if (str == "F1") return EKC_F1; + if (str == "F2") return EKC_F2; + if (str == "F3") return EKC_F3; + if (str == "F4") return EKC_F4; + if (str == "F5") return EKC_F5; + if (str == "F6") return EKC_F6; + if (str == "F7") return EKC_F7; + if (str == "F8") return EKC_F8; + if (str == "F9") return EKC_F9; + if (str == "F10") return EKC_F10; + if (str == "F11") return EKC_F11; + if (str == "F12") return EKC_F12; + if (str == "F13") return EKC_F13; + if (str == "F14") return EKC_F14; + if (str == "F15") return EKC_F15; + if (str == "F16") return EKC_F16; + if (str == "F17") return EKC_F17; + if (str == "F18") return EKC_F18; + if (str == "F19") return EKC_F19; + if (str == "F20") return EKC_F20; + if (str == "F21") return EKC_F21; + if (str == "F22") return EKC_F22; + if (str == "F23") return EKC_F23; + if (str == "F24") return EKC_F24; + + if (str == "NUMPAD_0") return EKC_NUMPAD_0; + if (str == "NUMPAD_1") return EKC_NUMPAD_1; + if (str == "NUMPAD_2") return EKC_NUMPAD_2; + if (str == "NUMPAD_3") return EKC_NUMPAD_3; + if (str == "NUMPAD_4") return EKC_NUMPAD_4; + if (str == "NUMPAD_5") return EKC_NUMPAD_5; + if (str == "NUMPAD_6") return EKC_NUMPAD_6; + if (str == "NUMPAD_7") return EKC_NUMPAD_7; + if (str == "NUMPAD_8") return EKC_NUMPAD_8; + if (str == "NUMPAD_9") return EKC_NUMPAD_9; + + if (str == "NUM_LOCK") return EKC_NUM_LOCK; + if (str == "SCROLL_LOCK") return EKC_SCROLL_LOCK; + + if (str == "VOLUME_MUTE") return EKC_VOLUME_MUTE; + if (str == "VOLUME_UP") return EKC_VOLUME_UP; + if (str == "VOLUME_DOWN") return EKC_VOLUME_DOWN; + + return EKC_NONE; +} + enum E_MOUSE_BUTTON : uint8_t { EMB_LEFT_BUTTON, @@ -276,5 +406,75 @@ enum E_MOUSE_BUTTON : uint8_t EMB_COUNT, }; +// Unambiguous set of "codes" to represent various mouse actions we support with Nabla - equivalent of E_KEY_CODE +enum E_MOUSE_CODE : uint8_t +{ + EMC_NONE = 0, + + // I know its E_MOUSE_BUTTON, this enum *must* be more abstract to standardize mouse + EMC_LEFT_BUTTON, + EMC_RIGHT_BUTTON, + EMC_MIDDLE_BUTTON, + EMC_BUTTON_4, + EMC_BUTTON_5, + + // and this is kinda SMouseEvent::E_EVENT_TYPE::EET_SCROLL + EMC_VERTICAL_POSITIVE_SCROLL, + EMC_VERTICAL_NEGATIVE_SCROLL, + EMC_HORIZONTAL_POSITIVE_SCROLL, + EMC_HORIZONTAL_NEGATIVE_SCROLL, + + // SMouseEvent::E_EVENT_TYPE::EET_MOVEMENT + EMC_RELATIVE_POSITIVE_MOVEMENT_X, + EMC_RELATIVE_POSITIVE_MOVEMENT_Y, + EMC_RELATIVE_NEGATIVE_MOVEMENT_X, + EMC_RELATIVE_NEGATIVE_MOVEMENT_Y, + + EMC_COUNT, +}; + +constexpr std::string_view mouseCodeToString(E_MOUSE_CODE code) +{ + switch (code) + { + case EMC_LEFT_BUTTON: return "LEFT_BUTTON"; + case EMC_RIGHT_BUTTON: return "RIGHT_BUTTON"; + case EMC_MIDDLE_BUTTON: return "MIDDLE_BUTTON"; + case EMC_BUTTON_4: return "BUTTON_4"; + case EMC_BUTTON_5: return "BUTTON_5"; + + case EMC_VERTICAL_POSITIVE_SCROLL: return "VERTICAL_POSITIVE_SCROLL"; + case EMC_VERTICAL_NEGATIVE_SCROLL: return "VERTICAL_NEGATIVE_SCROLL"; + case EMC_HORIZONTAL_POSITIVE_SCROLL: return "HORIZONTAL_POSITIVE_SCROLL"; + case EMC_HORIZONTAL_NEGATIVE_SCROLL: return "HORIZONTAL_NEGATIVE_SCROLL"; + + case EMC_RELATIVE_POSITIVE_MOVEMENT_X: return "RELATIVE_POSITIVE_MOVEMENT_X"; + case EMC_RELATIVE_POSITIVE_MOVEMENT_Y: return "RELATIVE_POSITIVE_MOVEMENT_Y"; + case EMC_RELATIVE_NEGATIVE_MOVEMENT_X: return "RELATIVE_NEGATIVE_MOVEMENT_X"; + case EMC_RELATIVE_NEGATIVE_MOVEMENT_Y: return "RELATIVE_NEGATIVE_MOVEMENT_Y"; + + default: return "NONE"; + } +} + +constexpr E_MOUSE_CODE stringToMouseCode(std::string_view str) +{ + if (str == "LEFT_BUTTON") return EMC_LEFT_BUTTON; + if (str == "RIGHT_BUTTON") return EMC_RIGHT_BUTTON; + if (str == "MIDDLE_BUTTON") return EMC_MIDDLE_BUTTON; + if (str == "BUTTON_4") return EMC_BUTTON_4; + if (str == "BUTTON_5") return EMC_BUTTON_5; + if (str == "VERTICAL_POSITIVE_SCROLL") return EMC_VERTICAL_POSITIVE_SCROLL; + if (str == "VERTICAL_NEGATIVE_SCROLL") return EMC_VERTICAL_NEGATIVE_SCROLL; + if (str == "HORIZONTAL_POSITIVE_SCROLL") return EMC_HORIZONTAL_POSITIVE_SCROLL; + if (str == "HORIZONTAL_NEGATIVE_SCROLL") return EMC_HORIZONTAL_NEGATIVE_SCROLL; + if (str == "RELATIVE_POSITIVE_MOVEMENT_X") return EMC_RELATIVE_POSITIVE_MOVEMENT_X; + if (str == "RELATIVE_POSITIVE_MOVEMENT_Y") return EMC_RELATIVE_POSITIVE_MOVEMENT_Y; + if (str == "RELATIVE_NEGATIVE_MOVEMENT_X") return EMC_RELATIVE_NEGATIVE_MOVEMENT_X; + if (str == "RELATIVE_NEGATIVE_MOVEMENT_Y") return EMC_RELATIVE_NEGATIVE_MOVEMENT_Y; + + return EMC_NONE; +} + } #endif diff --git a/include/nbl/ui/SInputEvent.h b/include/nbl/ui/SInputEvent.h index d791d08e53..9575f626d4 100644 --- a/include/nbl/ui/SInputEvent.h +++ b/include/nbl/ui/SInputEvent.h @@ -55,7 +55,6 @@ struct SMouseEvent : SEventBase IWindow* window; }; - struct SKeyboardEvent : SEventBase { inline SKeyboardEvent(std::chrono::microseconds ts) : SEventBase(ts) { } diff --git a/src/nbl/ext/ImGui/ImGui.cpp b/src/nbl/ext/ImGui/ImGui.cpp index 4c7c96953e..8da3f6c481 100644 --- a/src/nbl/ext/ImGui/ImGui.cpp +++ b/src/nbl/ext/ImGui/ImGui.cpp @@ -154,7 +154,14 @@ core::smart_refctd_ptr UI::createPipeline(SCreation smart_refctd_ptr vertex, fragment; } shaders; - { + if (creationParams.spirv.has_value()) + { + auto& spirv = creationParams.spirv.value(); + shaders.vertex = spirv.vertex; + shaders.fragment = spirv.fragment; + } + else + { //! proxy the system, we will touch it gently auto system = smart_refctd_ptr(creationParams.assetManager->getSystem()); @@ -1488,4 +1495,4 @@ void UI::setContext(void* imguiContext) { ImGui::SetCurrentContext(reinterpret_cast(imguiContext)); } -} \ No newline at end of file +}