🎉 begin project
This commit is contained in:
commit
8da6ddc689
29 changed files with 1261 additions and 0 deletions
20
.clang-format
Normal file
20
.clang-format
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Regroup
|
||||
SortIncludes: Never
|
||||
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
*.h text eol=lf
|
||||
*.cpp text eol=lf
|
||||
*.glsl text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.js text eol=lf
|
||||
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/cmake-build-debug/
|
||||
/cmake-build-release/
|
||||
/build/
|
||||
/build-release/
|
||||
/build-debug/
|
||||
/cmake-build*
|
||||
.idea/
|
||||
.vscode/
|
||||
.vs/
|
||||
Binaries/
|
||||
Intermediates/
|
||||
_audioConfig.ini
|
||||
MonoDebugger.log
|
||||
mono_crash.*.json
|
||||
VeAuralize.log
|
||||
.vqjs
|
||||
.cache
|
||||
bin/
|
||||
Vendor/
|
||||
lib/
|
||||
TODO.md
|
||||
25
CMake/CMakeLists.txt
Normal file
25
CMake/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
macro(add_sources)
|
||||
get_property(tmp GLOBAL PROPERTY SRCS)
|
||||
file(RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach (_src ${ARGN})
|
||||
if (_relPath)
|
||||
list(APPEND tmp "${_relPath}/${_src}")
|
||||
else ()
|
||||
list(APPEND tmp "${_src}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
set_property(GLOBAL PROPERTY SRCS ${tmp})
|
||||
endmacro()
|
||||
|
||||
macro(add_module_sources)
|
||||
get_property(tmp GLOBAL PROPERTY MODULE_SRCS)
|
||||
file(RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach (_src ${ARGN})
|
||||
if (_relPath)
|
||||
list(APPEND tmp "${_relPath}/${_src}")
|
||||
else ()
|
||||
list(APPEND tmp "${_src}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
set_property(GLOBAL PROPERTY MODULE_SRCS ${tmp})
|
||||
endmacro()
|
||||
34
CMakeLists.txt
Normal file
34
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
cmake_minimum_required(VERSION 3.31)
|
||||
project(VUI LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib/${CMAKE_SYSTEM_NAME}/)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib/${CMAKE_SYSTEM_NAME}/)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_SYSTEM_NAME}/)
|
||||
set(IS_DEBUG_BUILD CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
||||
# AVX :)
|
||||
if (MSVC)
|
||||
add_definitions(/MP /arch:AVX2 /W4)
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
add_definitions(-mavx2 -Wall -Wextra)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(CMake)
|
||||
add_subdirectory(Source)
|
||||
|
||||
get_property(source_files GLOBAL PROPERTY SRCS)
|
||||
get_property(module_source_files GLOBAL PROPERTY MODULE_SRCS)
|
||||
add_library(VUI STATIC ${source_files})
|
||||
target_sources(VUI
|
||||
PUBLIC
|
||||
FILE_SET CXX_MODULES FILES
|
||||
${module_source_files}
|
||||
)
|
||||
set_property(TARGET VUI PROPERTY COMPILE_WARNING_AS_ERROR ON)
|
||||
target_compile_features(VUI PUBLIC cxx_std_23)
|
||||
|
||||
|
||||
add_executable(VUI_EX main.cppm)
|
||||
target_link_libraries(VUI_EX PRIVATE VUI)
|
||||
target_compile_features(VUI_EX PUBLIC cxx_std_23)
|
||||
112
CMakePresets.json
Normal file
112
CMakePresets.json
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"version": 6,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 21,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "ninja-multi-vcpkg",
|
||||
"displayName": "Ninja Multi-Config",
|
||||
"description": "Configure with vcpkg toolchain and generate Ninja project files for all configurations",
|
||||
"binaryDir": "${sourceDir}/builds/${presetName}",
|
||||
"generator": "Ninja Multi-Config",
|
||||
"toolchainFile": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "ninja-vcpkg-debug",
|
||||
"configurePreset": "ninja-multi-vcpkg",
|
||||
"displayName": "Build (Debug)",
|
||||
"description": "Build with Ninja/vcpkg (Debug)",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "ninja-vcpkg-release",
|
||||
"configurePreset": "ninja-multi-vcpkg",
|
||||
"displayName": "Build (Release)",
|
||||
"description": "Build with Ninja/vcpkg (Release)",
|
||||
"configuration": "Release"
|
||||
},
|
||||
{
|
||||
"name": "ninja-vcpkg",
|
||||
"configurePreset": "ninja-multi-vcpkg",
|
||||
"displayName": "Build",
|
||||
"description": "Build with Ninja/vcpkg",
|
||||
"hidden": true
|
||||
},
|
||||
{
|
||||
"name": "ninja-vcpkg-check-format",
|
||||
"configurePreset": "ninja-multi-vcpkg",
|
||||
"displayName": "Build",
|
||||
"targets": [
|
||||
"check-format"
|
||||
],
|
||||
"description": "Build with Ninja/vcpkg check-format"
|
||||
},
|
||||
{
|
||||
"name": "ninja-vcpkg-format",
|
||||
"configurePreset": "ninja-multi-vcpkg",
|
||||
"displayName": "Build",
|
||||
"targets": [
|
||||
"format"
|
||||
],
|
||||
"description": "Build with Ninja/vcpkg format"
|
||||
}
|
||||
],
|
||||
"workflowPresets": [
|
||||
{
|
||||
"name": "format",
|
||||
"steps": [
|
||||
{
|
||||
"name": "ninja-multi-vcpkg",
|
||||
"type": "configure"
|
||||
},
|
||||
{
|
||||
"name": "ninja-vcpkg-format",
|
||||
"type": "build"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "check-format",
|
||||
"steps": [
|
||||
{
|
||||
"name": "ninja-multi-vcpkg",
|
||||
"type": "configure"
|
||||
},
|
||||
{
|
||||
"name": "ninja-vcpkg-check-format",
|
||||
"type": "build"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"testPresets": [
|
||||
{
|
||||
"name": "test-ninja-vcpkg",
|
||||
"configurePreset": "ninja-multi-vcpkg",
|
||||
"hidden": true
|
||||
},
|
||||
{
|
||||
"name": "test-debug",
|
||||
"description": "Test (Debug)",
|
||||
"displayName": "Test (Debug)",
|
||||
"configuration": "Debug",
|
||||
"inherits": [
|
||||
"test-ninja-vcpkg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "test-release",
|
||||
"description": "Test (Release)",
|
||||
"displayName": "Test (Release)",
|
||||
"configuration": "Release",
|
||||
"inherits": [
|
||||
"test-ninja-vcpkg"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
19
LICENSE
Normal file
19
LICENSE
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
zlib License
|
||||
|
||||
Copyright (C) 2025 VersusTuneZ
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
74
README.md
Normal file
74
README.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# UI – Versus UI
|
||||
VUI (short for Versus UI) is a lightweight and modern UI framework written in C++. It provides a clean and intuitive API for building native user interfaces with a focus on simplicity, performance, and extensibility.
|
||||
|
||||
Inspired by RGFW and GLFW
|
||||
|
||||
> ![Warning]
|
||||
> Work in Progress
|
||||
> VUI is currently in early development and is not yet production-ready.
|
||||
|
||||
|
||||
# ✨ Features
|
||||
- Basic windowing support
|
||||
- Event handling (keyboard, mouse, etc.)
|
||||
- Modular and easy-to-use API
|
||||
- Lightweight and efficient
|
||||
|
||||
# 🖥️ Platform Support
|
||||
- ✅ Windows (currently supported)
|
||||
- ⏳ Linux (planned)
|
||||
|
||||
> macOS and other platforms may be considered in the future.
|
||||
|
||||
# 🚧 Project Status
|
||||
VUI is a heavy Work In Progress. Many components are still being developed, and APIs may change frequently. Your feedback and contributions are welcome to help shape the future of the project!
|
||||
|
||||
# 📦 Getting Started
|
||||
> Note: This project currently targets Windows only.
|
||||
|
||||
Prerequisites
|
||||
- A C++23 (or later) compatible compiler
|
||||
- CMake 3.16+
|
||||
|
||||
# Build Instructions
|
||||
```bash
|
||||
git clone https://git.vstz.dev/vstz/VUI.git
|
||||
cd vui
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
# 🛠️ Usage
|
||||
Here’s a simple example of using VUI:
|
||||
|
||||
```cpp
|
||||
#include <vui/VUI.h>
|
||||
|
||||
int main() {
|
||||
VUI::WindowManager::Create(800, 600, "Example Window");
|
||||
while (VUI::WindowManager::HasOpen()) {
|
||||
VUI::WindowManager::Update();
|
||||
double dt = VUI::GetDeltaTime();
|
||||
// ...
|
||||
if (VUI::Input::IsKeyPressed(VUI::KeyCodes::ESCAPE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
More examples and documentation will be added as the project matures.
|
||||
|
||||
# 📅 Roadmap
|
||||
- Basic window creation
|
||||
- Event system (keyboard/mouse)
|
||||
- Linux support
|
||||
- Layout system
|
||||
- Widgets (buttons, sliders, etc.)
|
||||
- Theming & styling
|
||||
- High-DPI support
|
||||
|
||||
# 🤝 Contributing
|
||||
Contributions are welcome! If you're interested in helping build VUI, feel free to open issues, submit pull requests, or discuss ideas.
|
||||
|
||||
5
Source/CMakeLists.txt
Normal file
5
Source/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
add_subdirectory(Core)
|
||||
add_subdirectory(Input)
|
||||
add_subdirectory(Platform)
|
||||
add_subdirectory(Types)
|
||||
add_module_sources(VUI.cppm)
|
||||
5
Source/Core/CMakeLists.txt
Normal file
5
Source/Core/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
add_module_sources(
|
||||
VUI.cppm
|
||||
Window.cppm
|
||||
WindowManager.cppm
|
||||
)
|
||||
36
Source/Core/VUI.cppm
Normal file
36
Source/Core/VUI.cppm
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
module;
|
||||
#include <cstdint>
|
||||
|
||||
export module VUI:Time;
|
||||
|
||||
import :TimeInternal;
|
||||
|
||||
static uint64_t s_TimerOffset{0};
|
||||
static double s_LastTime{0};
|
||||
static double s_DeltaTime{0};
|
||||
|
||||
namespace VUI {
|
||||
export double GetDeltaTime() { return s_DeltaTime; };
|
||||
export double GetTime() {
|
||||
return static_cast<double>(GetTimerValue() - s_TimerOffset) /
|
||||
static_cast<double>(GetTimerFrequency());
|
||||
};
|
||||
export uint64_t GetTimeNs() {
|
||||
return static_cast<uint64_t>(
|
||||
static_cast<double>(GetTimerValue() - s_TimerOffset) * 1e9 /
|
||||
static_cast<double>(GetTimerFrequency()));
|
||||
}
|
||||
export void SetTime(const uint64_t time) {
|
||||
const auto dTimerValue = static_cast<double>(GetTimerValue());
|
||||
const auto dTime = static_cast<double>(time);
|
||||
const auto dFrequency = static_cast<double>(GetTimerFrequency());
|
||||
s_TimerOffset = static_cast<uint64_t>(dTimerValue - dTime * dFrequency);
|
||||
};
|
||||
export uint64_t GetTimeOffset() { return s_TimerOffset; }
|
||||
|
||||
export void UpdateDeltaTime() {
|
||||
const auto time = GetTime();
|
||||
s_DeltaTime = time - s_LastTime;
|
||||
s_LastTime = time;
|
||||
};
|
||||
} // namespace VUI
|
||||
54
Source/Core/Window.cppm
Normal file
54
Source/Core/Window.cppm
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
module;
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "../PlatformDetection.h"
|
||||
|
||||
export module VUI:Window;
|
||||
|
||||
import :Ref;
|
||||
import :Geometry;
|
||||
import :Input;
|
||||
|
||||
namespace VUI {
|
||||
struct WindowManager;
|
||||
std::uint64_t s_Handle = 0;
|
||||
|
||||
export struct WindowSpecification {
|
||||
uint32_t width{1280};
|
||||
uint32_t height{720};
|
||||
std::string title{"vui"};
|
||||
};
|
||||
|
||||
export struct Window : RefCounted {
|
||||
virtual void pullEvents() = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void resize(uint32_t width, uint32_t height) = 0;
|
||||
virtual void updateTitle(const std::string &title) = 0;
|
||||
|
||||
bool isOpen() const { return m_IsOpen; }
|
||||
[[nodiscard]] uint32_t getWidth() const { return m_Specification.width; }
|
||||
[[nodiscard]] uint32_t getHeight() const { return m_Specification.height; }
|
||||
[[nodiscard]] std::string getTitle() const { return m_Specification.title; }
|
||||
[[nodiscard]] uint64_t getHandle() const { return m_WindowHandle; }
|
||||
|
||||
protected:
|
||||
static void UpdateKey(uint32_t key, bool isDown);
|
||||
virtual void createWindow() = 0;
|
||||
bool m_IsOpen{false};
|
||||
std::uint64_t m_WindowHandle{0};
|
||||
WindowSpecification m_Specification{};
|
||||
|
||||
UPoint m_WindowPosition{};
|
||||
|
||||
Window() = default;
|
||||
friend Ref;
|
||||
friend WindowManager;
|
||||
};
|
||||
|
||||
void Window::UpdateKey(const uint32_t key, const bool isDown) {
|
||||
Input::UpdateKey(key, isDown);
|
||||
}
|
||||
} // namespace VUI
|
||||
91
Source/Core/WindowManager.cppm
Normal file
91
Source/Core/WindowManager.cppm
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
module;
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
export module VUI:WindowManager;
|
||||
|
||||
import :Window;
|
||||
import :PlatformWindow;
|
||||
import :Time;
|
||||
|
||||
namespace VUI {
|
||||
|
||||
export struct WindowManager {
|
||||
static Ref<Window> Create(uint32_t width, uint32_t height,
|
||||
const std::string &title);
|
||||
static Ref<Window> Create(const WindowSpecification &);
|
||||
static void Manage(const Ref<Window> &window);
|
||||
|
||||
static void Update();
|
||||
static void Close(Ref<Window> &);
|
||||
static void CloseByTitle(const std::string &title);
|
||||
static void CloseAll();
|
||||
static bool HasOpenWindows();
|
||||
|
||||
protected:
|
||||
std::vector<Ref<Window>> m_Windows{};
|
||||
friend Window;
|
||||
};
|
||||
|
||||
static WindowManager s_WindowManager = {};
|
||||
|
||||
Ref<Window> WindowManager::Create(uint32_t width, uint32_t height,
|
||||
const std::string &title) {
|
||||
return Create(WindowSpecification{width, height, title});
|
||||
}
|
||||
|
||||
Ref<Window> WindowManager::Create(const WindowSpecification &specification) {
|
||||
if (GetTimeOffset() == 0)
|
||||
SetTime(0);
|
||||
|
||||
auto window = Windowing::CreateWindowRef();
|
||||
window->m_Specification = specification;
|
||||
window->m_WindowHandle = s_Handle++;
|
||||
window->createWindow();
|
||||
Manage(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
void WindowManager::Manage(const Ref<Window> &window) {
|
||||
s_WindowManager.m_Windows.push_back(window);
|
||||
}
|
||||
|
||||
void WindowManager::Update() {
|
||||
Input::PostFrameUpdate();
|
||||
UpdateDeltaTime();
|
||||
for (auto &window : s_WindowManager.m_Windows) {
|
||||
window->pullEvents();
|
||||
}
|
||||
std::erase_if(s_WindowManager.m_Windows,
|
||||
[](Ref<Window> &window) { return !window->isOpen(); });
|
||||
}
|
||||
|
||||
void WindowManager::Close(Ref<Window> &refWindow) {
|
||||
if (!refWindow)
|
||||
return;
|
||||
refWindow->close();
|
||||
std::erase_if(s_WindowManager.m_Windows, [&refWindow](auto &window) {
|
||||
return !window->isOpen() || window == refWindow;
|
||||
});
|
||||
}
|
||||
void WindowManager::CloseByTitle(const std::string &title) {
|
||||
std::erase_if(s_WindowManager.m_Windows, [&title](Ref<Window> &window) {
|
||||
if (window->getTitle() == title) {
|
||||
window->close();
|
||||
}
|
||||
return !window->isOpen();
|
||||
});
|
||||
}
|
||||
void WindowManager::CloseAll() {
|
||||
for (auto &window : s_WindowManager.m_Windows) {
|
||||
window->close();
|
||||
}
|
||||
s_WindowManager.m_Windows.clear();
|
||||
}
|
||||
bool WindowManager::HasOpenWindows() {
|
||||
return !s_WindowManager.m_Windows.empty();
|
||||
}
|
||||
|
||||
} // namespace VUI
|
||||
5
Source/Input/CMakeLists.txt
Normal file
5
Source/Input/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
add_module_sources(
|
||||
InputCodes.cppm
|
||||
Input.cppm
|
||||
Keys.cppm
|
||||
)
|
||||
59
Source/Input/Input.cppm
Normal file
59
Source/Input/Input.cppm
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
module;
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
export module VUI:Input;
|
||||
|
||||
import :InputCodes;
|
||||
import :Keys;
|
||||
|
||||
namespace VUI {
|
||||
struct WindowManager;
|
||||
struct Window;
|
||||
constexpr uint32_t DownMask = 1;
|
||||
constexpr uint32_t RepeatMask = 1 << 2;
|
||||
|
||||
static std::array<uint8_t, std::to_underlying(KeyCodes::KEYLAST)> s_Keys{};
|
||||
|
||||
static constexpr std::array<KeyCodes, Keys> InputKeys = InitKeys();
|
||||
|
||||
export struct Input {
|
||||
static bool IsKeyDown(const KeyCodes key) {
|
||||
return s_Keys[std::to_underlying(key)] & DownMask;
|
||||
}
|
||||
|
||||
static bool IsKeyPressed(const KeyCodes key) {
|
||||
const auto value = s_Keys[std::to_underlying(key)];
|
||||
return value & DownMask && !(value & RepeatMask);
|
||||
}
|
||||
|
||||
static bool IsKeyRepeat(const KeyCodes key) {
|
||||
return s_Keys[std::to_underlying(key)] & RepeatMask;
|
||||
}
|
||||
|
||||
private:
|
||||
static void UpdateKey(uint32_t key, bool isDown);
|
||||
static void PostFrameUpdate();
|
||||
friend WindowManager;
|
||||
friend Window;
|
||||
};
|
||||
|
||||
void Input::UpdateKey(const uint32_t key, const bool isDown) {
|
||||
assert(key < InputKeys.size() && "Keycode out of range");
|
||||
const uint8_t keyCode = std::to_underlying(InputKeys[key]);
|
||||
uint8_t value = s_Keys[keyCode];
|
||||
if (isDown) {
|
||||
value |= DownMask;
|
||||
} else {
|
||||
value &= ~(DownMask | RepeatMask);
|
||||
}
|
||||
s_Keys[keyCode] = value;
|
||||
}
|
||||
|
||||
void Input::PostFrameUpdate() {
|
||||
for (uint8_t &s_key : s_Keys)
|
||||
s_key |= s_key & DownMask ? RepeatMask : 0;
|
||||
}
|
||||
} // namespace VUI
|
||||
124
Source/Input/InputCodes.cppm
Normal file
124
Source/Input/InputCodes.cppm
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
module;
|
||||
#include <cstdint>
|
||||
|
||||
export module VUI:InputCodes;
|
||||
|
||||
namespace VUI {
|
||||
export enum class KeyCodes : uint8_t {
|
||||
keyNULL,
|
||||
ESCAPE,
|
||||
BACKTICK,
|
||||
N0,
|
||||
N1,
|
||||
N2,
|
||||
N3,
|
||||
N4,
|
||||
N5,
|
||||
N6,
|
||||
N7,
|
||||
N8,
|
||||
N9,
|
||||
|
||||
MINUS,
|
||||
EQUALS,
|
||||
BACKSPACE,
|
||||
TAB,
|
||||
SPACE,
|
||||
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
|
||||
PERIOD,
|
||||
COMMA,
|
||||
SLASH,
|
||||
BRACKET,
|
||||
CLOSEBRACKET,
|
||||
SEMICOLON,
|
||||
APOSTROPHE,
|
||||
BACKSLASH,
|
||||
RETURN,
|
||||
DELETE_KEY,
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
|
||||
CAPSLOCK,
|
||||
SHIFT_L,
|
||||
CONTROL_L,
|
||||
ALT_L,
|
||||
SUPER_L,
|
||||
SHIFT_R,
|
||||
CONTROL_R,
|
||||
ALT_R,
|
||||
SUPER_R,
|
||||
UP,
|
||||
DOWN,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
|
||||
INSERT,
|
||||
END,
|
||||
HOME,
|
||||
PAGEUP,
|
||||
PAGEDOWN,
|
||||
|
||||
NUMLOCK,
|
||||
KP_SLASH,
|
||||
MULTIPLY,
|
||||
KP_MINUS,
|
||||
KP_1,
|
||||
KP_2,
|
||||
KP_3,
|
||||
KP_4,
|
||||
KP_5,
|
||||
KP_6,
|
||||
KP_7,
|
||||
KP_8,
|
||||
KP_9,
|
||||
KP_0,
|
||||
KP_PERIOD,
|
||||
KP_RETURN,
|
||||
KEYLAST,
|
||||
};
|
||||
|
||||
export enum class MouseCodes {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
MIDDLE,
|
||||
WHEEL_UP,
|
||||
WHEEL_DOWN,
|
||||
};
|
||||
} // namespace VUI
|
||||
120
Source/Input/Keys.cppm
Normal file
120
Source/Input/Keys.cppm
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
module;
|
||||
#include "../PlatformDetection.h"
|
||||
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
export module VUI:Keys;
|
||||
|
||||
import :InputCodes;
|
||||
|
||||
namespace VUI {
|
||||
export constexpr int Keys = VUI_OS_VALUE(136, 0x15C + 1, 128);
|
||||
|
||||
export constexpr std::array<KeyCodes, Keys> InitKeys() {
|
||||
auto keys = std::array<KeyCodes, Keys>{};
|
||||
keys[VUI_OS_VALUE(49, 0x029, 50)] = KeyCodes::BACKTICK;
|
||||
keys[VUI_OS_VALUE(19, 0x00B, 29)] = KeyCodes::N0;
|
||||
keys[VUI_OS_VALUE(10, 0x002, 18)] = KeyCodes::N1;
|
||||
keys[VUI_OS_VALUE(11, 0x003, 19)] = KeyCodes::N2;
|
||||
keys[VUI_OS_VALUE(12, 0x004, 20)] = KeyCodes::N3;
|
||||
keys[VUI_OS_VALUE(13, 0x005, 21)] = KeyCodes::N4;
|
||||
keys[VUI_OS_VALUE(14, 0x006, 23)] = KeyCodes::N5;
|
||||
keys[VUI_OS_VALUE(15, 0x007, 22)] = KeyCodes::N6;
|
||||
keys[VUI_OS_VALUE(16, 0x008, 26)] = KeyCodes::N7;
|
||||
keys[VUI_OS_VALUE(17, 0x009, 28)] = KeyCodes::N8;
|
||||
keys[VUI_OS_VALUE(18, 0x00A, 25)] = KeyCodes::N9;
|
||||
keys[VUI_OS_VALUE(65, 0x039, 49)] = KeyCodes::SPACE;
|
||||
keys[VUI_OS_VALUE(38, 0x01E, 0)] = KeyCodes::A;
|
||||
keys[VUI_OS_VALUE(56, 0x030, 11)] = KeyCodes::B;
|
||||
keys[VUI_OS_VALUE(54, 0x02E, 8)] = KeyCodes::C;
|
||||
keys[VUI_OS_VALUE(40, 0x020, 2)] = KeyCodes::D;
|
||||
keys[VUI_OS_VALUE(26, 0x012, 14)] = KeyCodes::E;
|
||||
keys[VUI_OS_VALUE(41, 0x021, 3)] = KeyCodes::F;
|
||||
keys[VUI_OS_VALUE(42, 0x022, 5)] = KeyCodes::G;
|
||||
keys[VUI_OS_VALUE(43, 0x023, 4)] = KeyCodes::H;
|
||||
keys[VUI_OS_VALUE(31, 0x017, 34)] = KeyCodes::I;
|
||||
keys[VUI_OS_VALUE(44, 0x024, 38)] = KeyCodes::J;
|
||||
keys[VUI_OS_VALUE(45, 0x025, 40)] = KeyCodes::K;
|
||||
keys[VUI_OS_VALUE(46, 0x026, 37)] = KeyCodes::L;
|
||||
keys[VUI_OS_VALUE(58, 0x032, 46)] = KeyCodes::M;
|
||||
keys[VUI_OS_VALUE(57, 0x031, 45)] = KeyCodes::N;
|
||||
keys[VUI_OS_VALUE(32, 0x018, 31)] = KeyCodes::O;
|
||||
keys[VUI_OS_VALUE(33, 0x019, 35)] = KeyCodes::P;
|
||||
keys[VUI_OS_VALUE(24, 0x010, 12)] = KeyCodes::Q;
|
||||
keys[VUI_OS_VALUE(27, 0x013, 15)] = KeyCodes::R;
|
||||
keys[VUI_OS_VALUE(39, 0x01F, 1)] = KeyCodes::S;
|
||||
keys[VUI_OS_VALUE(28, 0x014, 17)] = KeyCodes::T;
|
||||
keys[VUI_OS_VALUE(30, 0x016, 32)] = KeyCodes::U;
|
||||
keys[VUI_OS_VALUE(55, 0x02F, 9)] = KeyCodes::V;
|
||||
keys[VUI_OS_VALUE(25, 0x011, 13)] = KeyCodes::W;
|
||||
keys[VUI_OS_VALUE(53, 0x02D, 7)] = KeyCodes::X;
|
||||
keys[VUI_OS_VALUE(29, 0x015, 16)] = KeyCodes::Y;
|
||||
keys[VUI_OS_VALUE(52, 0x02C, 6)] = KeyCodes::Z;
|
||||
keys[VUI_OS_VALUE(60, 0x034, 47)] = KeyCodes::PERIOD;
|
||||
keys[VUI_OS_VALUE(59, 0x033, 43)] = KeyCodes::COMMA;
|
||||
keys[VUI_OS_VALUE(61, 0x035, 44)] = KeyCodes::SLASH;
|
||||
keys[VUI_OS_VALUE(34, 0x01A, 33)] = KeyCodes::BRACKET;
|
||||
keys[VUI_OS_VALUE(35, 0x01B, 30)] = KeyCodes::CLOSEBRACKET;
|
||||
keys[VUI_OS_VALUE(47, 0x027, 41)] = KeyCodes::SEMICOLON;
|
||||
keys[VUI_OS_VALUE(48, 0x028, 39)] = KeyCodes::APOSTROPHE;
|
||||
keys[VUI_OS_VALUE(51, 0x02B, 42)] = KeyCodes::BACKSLASH;
|
||||
keys[VUI_OS_VALUE(36, 0x01C, 36)] = KeyCodes::RETURN;
|
||||
keys[VUI_OS_VALUE(119, 0x153, 118)] = KeyCodes::DELETE_KEY;
|
||||
keys[VUI_OS_VALUE(77, 0x145, 72)] = KeyCodes::NUMLOCK;
|
||||
keys[VUI_OS_VALUE(106, 0x135, 82)] = KeyCodes::KP_SLASH;
|
||||
keys[VUI_OS_VALUE(63, 0x037, 76)] = KeyCodes::MULTIPLY;
|
||||
keys[VUI_OS_VALUE(82, 0x04A, 67)] = KeyCodes::KP_MINUS;
|
||||
keys[VUI_OS_VALUE(87, 0x04F, 84)] = KeyCodes::KP_1;
|
||||
keys[VUI_OS_VALUE(88, 0x050, 85)] = KeyCodes::KP_2;
|
||||
keys[VUI_OS_VALUE(89, 0x051, 86)] = KeyCodes::KP_3;
|
||||
keys[VUI_OS_VALUE(83, 0x04B, 87)] = KeyCodes::KP_4;
|
||||
keys[VUI_OS_VALUE(84, 0x04C, 88)] = KeyCodes::KP_5;
|
||||
keys[VUI_OS_VALUE(85, 0x04D, 89)] = KeyCodes::KP_6;
|
||||
keys[VUI_OS_VALUE(79, 0x047, 90)] = KeyCodes::KP_7;
|
||||
keys[VUI_OS_VALUE(80, 0x048, 92)] = KeyCodes::KP_8;
|
||||
keys[VUI_OS_VALUE(81, 0x049, 93)] = KeyCodes::KP_9;
|
||||
keys[VUI_OS_VALUE(90, 0x052, 83)] = KeyCodes::KP_0;
|
||||
keys[VUI_OS_VALUE(91, 0x053, 65)] = KeyCodes::KP_PERIOD;
|
||||
keys[VUI_OS_VALUE(104, 0x11C, 77)] = KeyCodes::KP_RETURN;
|
||||
keys[VUI_OS_VALUE(20, 0x00C, 27)] = KeyCodes::MINUS;
|
||||
keys[VUI_OS_VALUE(21, 0x00D, 24)] = KeyCodes::EQUALS;
|
||||
keys[VUI_OS_VALUE(22, 0x00E, 51)] = KeyCodes::BACKSPACE;
|
||||
keys[VUI_OS_VALUE(23, 0x00F, 48)] = KeyCodes::TAB;
|
||||
keys[VUI_OS_VALUE(66, 0x03A, 57)] = KeyCodes::CAPSLOCK;
|
||||
keys[VUI_OS_VALUE(50, 0x02A, 56)] = KeyCodes::SHIFT_L;
|
||||
keys[VUI_OS_VALUE(37, 0x01D, 59)] = KeyCodes::CONTROL_L;
|
||||
keys[VUI_OS_VALUE(64, 0x038, 58)] = KeyCodes::ALT_L;
|
||||
keys[VUI_OS_VALUE(133, 0x15B, 55)] = KeyCodes::SUPER_L;
|
||||
#if !defined(VUI_APPLE)
|
||||
keys[VUI_OS_VALUE(105, 0x11D, 59)] = KeyCodes::CONTROL_R;
|
||||
keys[VUI_OS_VALUE(135, 0x15C, 55)] = KeyCodes::SUPER_R;
|
||||
keys[VUI_OS_VALUE(62, 0x036, 56)] = KeyCodes::SHIFT_R;
|
||||
keys[VUI_OS_VALUE(108, 0x138, 58)] = KeyCodes::ALT_R;
|
||||
#endif
|
||||
keys[VUI_OS_VALUE(67, 0x03B, 127)] = KeyCodes::F1;
|
||||
keys[VUI_OS_VALUE(68, 0x03C, 121)] = KeyCodes::F2;
|
||||
keys[VUI_OS_VALUE(69, 0x03D, 100)] = KeyCodes::F3;
|
||||
keys[VUI_OS_VALUE(70, 0x03E, 119)] = KeyCodes::F4;
|
||||
keys[VUI_OS_VALUE(71, 0x03F, 97)] = KeyCodes::F5;
|
||||
keys[VUI_OS_VALUE(72, 0x040, 98)] = KeyCodes::F6;
|
||||
keys[VUI_OS_VALUE(73, 0x041, 99)] = KeyCodes::F7;
|
||||
keys[VUI_OS_VALUE(74, 0x042, 101)] = KeyCodes::F8;
|
||||
keys[VUI_OS_VALUE(75, 0x043, 102)] = KeyCodes::F9;
|
||||
keys[VUI_OS_VALUE(76, 0x044, 110)] = KeyCodes::F10;
|
||||
keys[VUI_OS_VALUE(95, 0x057, 104)] = KeyCodes::F11;
|
||||
keys[VUI_OS_VALUE(96, 0x058, 112)] = KeyCodes::F12;
|
||||
keys[VUI_OS_VALUE(111, 0x148, 126)] = KeyCodes::UP;
|
||||
keys[VUI_OS_VALUE(116, 0x150, 125)] = KeyCodes::DOWN;
|
||||
keys[VUI_OS_VALUE(113, 0x14B, 123)] = KeyCodes::LEFT;
|
||||
keys[VUI_OS_VALUE(114, 0x14D, 124)] = KeyCodes::RIGHT;
|
||||
keys[VUI_OS_VALUE(118, 0x152, 115)] = KeyCodes::INSERT;
|
||||
keys[VUI_OS_VALUE(115, 0x14F, 120)] = KeyCodes::END;
|
||||
keys[VUI_OS_VALUE(112, 0x149, 117)] = KeyCodes::PAGEUP;
|
||||
keys[VUI_OS_VALUE(117, 0x151, 122)] = KeyCodes::PAGEDOWN;
|
||||
keys[VUI_OS_VALUE(9, 0x001, 53)] = KeyCodes::ESCAPE;
|
||||
keys[VUI_OS_VALUE(110, 0x147, 116)] = KeyCodes::HOME;
|
||||
|
||||
return keys;
|
||||
}
|
||||
} // namespace VUI
|
||||
5
Source/Platform/CMakeLists.txt
Normal file
5
Source/Platform/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
add_subdirectory(Linux)
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
add_subdirectory(Windows)
|
||||
endif ()
|
||||
4
Source/Platform/Windows/CMakeLists.txt
Normal file
4
Source/Platform/Windows/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
add_module_sources(
|
||||
Time.cppm
|
||||
Window.cppm
|
||||
)
|
||||
19
Source/Platform/Windows/Time.cppm
Normal file
19
Source/Platform/Windows/Time.cppm
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
module;
|
||||
#include <cstdint>
|
||||
#include "Windows.h"
|
||||
|
||||
export module VUI:TimeInternal;
|
||||
|
||||
namespace VUI {
|
||||
export uint64_t GetTimerValue() {
|
||||
uint64_t value{0};
|
||||
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&value));
|
||||
return value;
|
||||
}
|
||||
|
||||
export uint64_t GetTimerFrequency() {
|
||||
uint64_t frequency{0};
|
||||
QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&frequency));
|
||||
return frequency;
|
||||
}
|
||||
} // namespace VUI
|
||||
160
Source/Platform/Windows/Window.cppm
Normal file
160
Source/Platform/Windows/Window.cppm
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
module;
|
||||
|
||||
#include <Windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <stdexcept>
|
||||
|
||||
export module VUI:PlatformWindow;
|
||||
|
||||
import :Window;
|
||||
import :Ref;
|
||||
|
||||
namespace VUI::Windowing {
|
||||
const char *CLASS_NAME = "VUI";
|
||||
bool s_windowInit = false;
|
||||
|
||||
struct Win32Window : Window {
|
||||
Win32Window();
|
||||
~Win32Window() override;
|
||||
|
||||
void pullEvents() override;
|
||||
void close() override;
|
||||
void resize(uint32_t width, uint32_t height) override;
|
||||
void updateTitle(const std::string &title) override;
|
||||
static LRESULT CALLBACK WindowProc(HWND, UINT uMsg, WPARAM, LPARAM);
|
||||
|
||||
protected:
|
||||
void createWindow() override;
|
||||
void handleEvent(HWND, UINT message, WPARAM, LPARAM);
|
||||
|
||||
private:
|
||||
HWND m_Window{nullptr};
|
||||
HINSTANCE m_Instance{nullptr};
|
||||
friend Window;
|
||||
};
|
||||
|
||||
export Ref<Window> CreateWindowRef() { return Ref<Window>(new Win32Window()); }
|
||||
|
||||
Win32Window::Win32Window() : Window() { m_Instance = GetModuleHandle(nullptr); }
|
||||
Win32Window::~Win32Window() { DestroyWindow(m_Window); }
|
||||
|
||||
void Win32Window::pullEvents() {
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, m_Window, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void Win32Window::close() {
|
||||
CloseWindow(m_Window);
|
||||
m_IsOpen = false;
|
||||
}
|
||||
|
||||
void Win32Window::resize(uint32_t width, uint32_t height) {
|
||||
m_Specification.width = width;
|
||||
m_Specification.height = height;
|
||||
|
||||
SetWindowPos(m_Window, nullptr, static_cast<int>(m_WindowPosition.x),
|
||||
static_cast<int>(m_WindowPosition.y),
|
||||
static_cast<int>(m_Specification.width),
|
||||
static_cast<int>(m_Specification.height), 0);
|
||||
}
|
||||
|
||||
void Win32Window::updateTitle(const std::string &title) {
|
||||
m_Specification.title = title;
|
||||
SetWindowText(m_Window, title.c_str());
|
||||
}
|
||||
|
||||
LRESULT CALLBACK Win32Window::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
|
||||
if (uMsg == WM_CREATE) {
|
||||
auto *pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA,
|
||||
reinterpret_cast<LONG_PTR>(
|
||||
static_cast<Win32Window *>(pCreate->lpCreateParams)));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
auto impl =
|
||||
reinterpret_cast<Win32Window *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (impl != nullptr) {
|
||||
impl->handleEvent(hwnd, uMsg, wParam, lParam);
|
||||
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
void registerClass(HINSTANCE hInstance) {
|
||||
WNDCLASS wc = {};
|
||||
|
||||
wc.lpfnWndProc = Win32Window::WindowProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.lpszClassName = CLASS_NAME;
|
||||
|
||||
RegisterClass(&wc);
|
||||
}
|
||||
|
||||
void Win32Window::createWindow() {
|
||||
if (!s_windowInit) {
|
||||
registerClass(m_Instance);
|
||||
s_windowInit = true;
|
||||
}
|
||||
|
||||
m_Window = CreateWindowEx(0, CLASS_NAME, m_Specification.title.c_str(),
|
||||
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr,
|
||||
m_Instance, this);
|
||||
|
||||
m_IsOpen = m_Window != nullptr;
|
||||
if (m_Window == nullptr) {
|
||||
throw std::runtime_error("Failed to create window.");
|
||||
}
|
||||
resize(m_Specification.width, m_Specification.height);
|
||||
ShowWindow(m_Window, SW_NORMAL);
|
||||
}
|
||||
void Win32Window::handleEvent(HWND, UINT message, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
switch (message) {
|
||||
case WM_MOVE: {
|
||||
m_WindowPosition.x = LOWORD(lParam);
|
||||
m_WindowPosition.y = HIWORD(lParam);
|
||||
break;
|
||||
}
|
||||
case WM_SIZE: {
|
||||
m_Specification.width = LOWORD(lParam);
|
||||
m_Specification.height = HIWORD(lParam);
|
||||
break;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP: {
|
||||
uint32_t scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
|
||||
if (scancode == 0)
|
||||
scancode = MapVirtualKeyW(static_cast<UINT>(wParam), MAPVK_VK_TO_VSC);
|
||||
|
||||
switch (scancode) {
|
||||
case 0x54: scancode = 0x137; break;
|
||||
case 0x146: scancode = 0x45; break;
|
||||
case 0x136: scancode = 0x36; break;
|
||||
default: break;
|
||||
}
|
||||
UpdateKey(scancode, message == WM_KEYDOWN);
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEMOVE: {
|
||||
// TODO: Handle MouseMove
|
||||
Point rect(static_cast<float>(GET_X_LPARAM(lParam)),
|
||||
static_cast<float>(GET_Y_LPARAM(lParam)));
|
||||
break;
|
||||
}
|
||||
case WM_CLOSE: {
|
||||
this->m_IsOpen = false;
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY: PostQuitMessage(0);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace VUI::Windows
|
||||
25
Source/PlatformDetection.h
Normal file
25
Source/PlatformDetection.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||
#define VUI_WINDOWS 1
|
||||
#elif __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#define VUI_APPLE 1
|
||||
#elif __ANDROID__
|
||||
#define VUI_ANDROID 1
|
||||
#elif __linux__
|
||||
#define VUI_LINUX 1
|
||||
#elif __unix__ // all unices not caught above
|
||||
#define VUI_UNIX 1
|
||||
#elif defined(_POSIX_VERSION)
|
||||
#define VUI_POSIX 1
|
||||
#else
|
||||
#error "Unknown compiler"
|
||||
#endif
|
||||
|
||||
#if defined(VUI_LINUX)
|
||||
#define VUI_OS_VALUE(l, w, m) l
|
||||
#elif defined(VUI_WINDOWS)
|
||||
#define VUI_OS_VALUE(l, w, m) w
|
||||
#elif defined(VUI_APPLE)
|
||||
#define VUI_OS_VALUE(l, w, m) m
|
||||
#endif
|
||||
4
Source/Types/CMakeLists.txt
Normal file
4
Source/Types/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
add_module_sources(
|
||||
Geometry.cppm
|
||||
Ref.cppm
|
||||
)
|
||||
45
Source/Types/Geometry.cppm
Normal file
45
Source/Types/Geometry.cppm
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
module;
|
||||
#include <cstdint>
|
||||
|
||||
export module VUI:Geometry;
|
||||
|
||||
namespace VUI {
|
||||
export struct Point {
|
||||
float x{0};
|
||||
float y{0};
|
||||
};
|
||||
|
||||
export struct UPoint {
|
||||
uint32_t x{0};
|
||||
uint32_t y{0};
|
||||
};
|
||||
|
||||
export struct URect {
|
||||
uint32_t x{0};
|
||||
uint32_t y{0};
|
||||
uint32_t width{0};
|
||||
uint32_t height{0};
|
||||
};
|
||||
|
||||
export struct Rect {
|
||||
float x{0};
|
||||
float y{0};
|
||||
float width{0};
|
||||
float height{0};
|
||||
};
|
||||
|
||||
// replace with glm
|
||||
export struct Vec3 {
|
||||
float x{0};
|
||||
float y{0};
|
||||
float z{0};
|
||||
};
|
||||
|
||||
export struct Vec4 {
|
||||
float x{0};
|
||||
float y{0};
|
||||
float z{0};
|
||||
float w{0};
|
||||
};
|
||||
|
||||
} // namespace VUI
|
||||
137
Source/Types/Ref.cppm
Normal file
137
Source/Types/Ref.cppm
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
module;
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
export module VUI:Ref;
|
||||
|
||||
namespace VUI {
|
||||
|
||||
export struct RefCounted {
|
||||
virtual ~RefCounted() = default;
|
||||
|
||||
void incrementRefCount() const { ++m_RefCount; }
|
||||
void decrementRefCount() const { --m_RefCount; }
|
||||
|
||||
[[nodiscard]] std::uint32_t getRefCount() const { return m_RefCount.load(); }
|
||||
|
||||
private:
|
||||
mutable std::atomic<uint32_t> m_RefCount = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
concept IsRefCounted = std::is_base_of_v<RefCounted, T>;
|
||||
|
||||
export template <typename T> class Ref {
|
||||
public:
|
||||
static_assert(IsRefCounted<T>, "Should be RefCounted");
|
||||
Ref() : m_Instance(nullptr) {}
|
||||
|
||||
explicit Ref(std::nullptr_t) : m_Instance(nullptr) {}
|
||||
|
||||
explicit Ref(T *instance) : m_Instance(instance) { incRef(); }
|
||||
|
||||
template <typename T2> explicit Ref(const Ref<T2> &other) {
|
||||
m_Instance = static_cast<T *>(other.m_Instance);
|
||||
incRef();
|
||||
}
|
||||
|
||||
template <typename T2> explicit Ref(Ref<T2> &&other) {
|
||||
m_Instance = static_cast<T *>(other.m_Instance);
|
||||
other.m_Instance = nullptr;
|
||||
}
|
||||
|
||||
~Ref() { decRef(); }
|
||||
|
||||
Ref(const Ref &other) : m_Instance(other.m_Instance) { incRef(); }
|
||||
|
||||
Ref &operator=(std::nullptr_t) {
|
||||
decRef();
|
||||
m_Instance = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ref &operator=(const Ref &other) {
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
other.incRef();
|
||||
decRef();
|
||||
|
||||
m_Instance = other.m_Instance;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T2> Ref &operator=(const Ref<T2> &other) {
|
||||
other.incRef();
|
||||
decRef();
|
||||
|
||||
m_Instance = other.m_Instance;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T2> Ref &operator=(Ref<T2> &&other) {
|
||||
decRef();
|
||||
|
||||
m_Instance = other.m_Instance;
|
||||
other.m_Instance = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() { return m_Instance != nullptr; }
|
||||
operator bool() const { return m_Instance != nullptr; }
|
||||
|
||||
T *operator->() { return m_Instance; }
|
||||
const T *operator->() const { return m_Instance; }
|
||||
|
||||
T &operator*() { return *m_Instance; }
|
||||
const T &operator*() const { return *m_Instance; }
|
||||
|
||||
T *value() { return m_Instance; }
|
||||
const T *value() const { return m_Instance; }
|
||||
|
||||
void reset(T *instance = nullptr) {
|
||||
decRef();
|
||||
m_Instance = instance;
|
||||
}
|
||||
|
||||
template <typename T2> Ref<T2> as() const { return Ref<T2>(*this); }
|
||||
|
||||
template <typename... Args> static Ref Create(Args &&...args) {
|
||||
return Ref(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
bool operator==(const Ref &other) const {
|
||||
return m_Instance == other.m_Instance;
|
||||
}
|
||||
|
||||
bool operator!=(const Ref &other) const { return !(*this == other); }
|
||||
|
||||
bool equals(const Ref &other) {
|
||||
if (!m_Instance || !other.m_Instance)
|
||||
return false;
|
||||
|
||||
return m_Instance == other.m_Instance;
|
||||
}
|
||||
|
||||
private:
|
||||
void incRef() const {
|
||||
if (m_Instance) {
|
||||
m_Instance->incrementRefCount();
|
||||
}
|
||||
}
|
||||
|
||||
void decRef() const {
|
||||
if (m_Instance) {
|
||||
m_Instance->decrementRefCount();
|
||||
|
||||
if (m_Instance->getRefCount() == 0) {
|
||||
delete m_Instance;
|
||||
m_Instance = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T2> friend class Ref;
|
||||
mutable T *m_Instance;
|
||||
};
|
||||
} // namespace VUI
|
||||
15
Source/VUI.cppm
Normal file
15
Source/VUI.cppm
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export module VUI;
|
||||
|
||||
// Core
|
||||
// Window
|
||||
export import :Time;
|
||||
export import :Window;
|
||||
export import :WindowManager;
|
||||
|
||||
// Input Handling
|
||||
export import :Input;
|
||||
export import :InputCodes;
|
||||
|
||||
// Types
|
||||
export import :Geometry;
|
||||
export import :Ref;
|
||||
16
main.cppm
Normal file
16
main.cppm
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import VUI;
|
||||
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
struct Me final : VUI::RefCounted {
|
||||
|
||||
};
|
||||
|
||||
int main() {
|
||||
VUI::WindowManager::Create(1280, 720, "VUI");
|
||||
while (VUI::WindowManager::HasOpenWindows()) {
|
||||
VUI::WindowManager::Update();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
14
vcpkg-configuration.json
Normal file
14
vcpkg-configuration.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"default-registry": {
|
||||
"kind": "git",
|
||||
"baseline": "47364fbc300756f64f7876b549d9422d5f3ec0d3",
|
||||
"repository": "https://github.com/microsoft/vcpkg"
|
||||
},
|
||||
"registries": [
|
||||
{
|
||||
"kind": "artifact",
|
||||
"location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
|
||||
"name": "microsoft"
|
||||
}
|
||||
]
|
||||
}
|
||||
8
vcpkg.json
Normal file
8
vcpkg.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "vui",
|
||||
"version": "2025.1.1",
|
||||
"dependencies": [
|
||||
"vulkan",
|
||||
"vulkan-memory-allocator"
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue