Compare commits

..
5 Commits
Author SHA1 Message Date
shadesandgrays ede15af1fd fix raylib submodule url 2026-07-22 20:39:20 +01:00
shadesandgrays d342a1f650 relatively okay i guess 2026-07-22 20:20:50 +01:00
shadesandgrays 0dd2186471 fixed export 2026-07-22 19:51:33 +01:00
shadesandgrays 12d80df8ad fix engine variant added tests 2026-07-22 16:49:46 +01:00
shadesandgrays f4ad43b05f minor update 2026-07-22 12:34:18 +01:00
24 changed files with 971 additions and 248 deletions
+1
View File
@@ -2,6 +2,7 @@
build/ build/
build-desktop/ build-desktop/
build-web/ build-web/
dist/
bin/ bin/
web/ web/
debug/ debug/
+1 -1
View File
@@ -3,7 +3,7 @@
url = git@github.com:ShadesAndGrays/Asset-Packer.git url = git@github.com:ShadesAndGrays/Asset-Packer.git
[submodule "vendor/raylib"] [submodule "vendor/raylib"]
path = vendor/raylib path = vendor/raylib
url = git@github.com:ShadesAndGrays/Asset-Packer.git url = https://github.com/raysan5/raylib.git
[submodule "vendor/rlImGui"] [submodule "vendor/rlImGui"]
path = vendor/rlImGui path = vendor/rlImGui
url = https://github.com/raylib-extras/rlImGui.git url = https://github.com/raylib-extras/rlImGui.git
+100 -54
View File
@@ -1,82 +1,120 @@
cmake_minimum_required(VERSION 4.4.0) cmake_minimum_required(VERSION 3.25)
project(my_app LANGUAGES CXX) project(varicle LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
file( GLOB_RECURSE # ------------------------------------------------------------------------------
SRC # 1. Platform & Dist Paths
CONFIGURE # ------------------------------------------------------------------------------
"src/*cpp"
"src/*.hpp"
)
if(BUILD_FOR_WEB OR EMSCRIPTEN)
set(DIST_PLATFORM "web")
else()
set(DIST_PLATFORM "desktop")
endif()
#------------------------------------------------------------------------------------------ # Automatically route 'cmake --install' into 'dist/desktop' or 'dist/web'
# Subdirectories if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
#------------------------------------------------------------------------------------------ set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/dist/${DIST_PLATFORM}" CACHE PATH "Dist directory" FORCE)
endif()
set(BUILD_EXAMPLES OFF) include(GNUInstallDirs)
# ------------------------------------------------------------------------------
# 2. Vendored Dependencies (Internal)
# ------------------------------------------------------------------------------
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(vendor/raylib) add_subdirectory(vendor/raylib)
add_subdirectory(vendor/asset-packer) add_subdirectory(vendor/asset-packer)
file(GLOB IMGUI_SOURCES "vendor/imgui/*.cpp")
file(GLOB IMGUI_HEADERS "vendor/imgui/*.h")
file(GLOB RLIMGUI_HEADERS "vendor/rlImGui/*.h")
#------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# GUI # 3. Main Framework Target (Single Monolithic Library)
#------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
file(GLOB_RECURSE ENGINE_SRC "src/engine/*.cpp")
#ImGui # Put ImGui, rlImGui, and Engine sources ALL into one binary!
set(IMGUI_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/imgui") add_library(${PROJECT_NAME}_lib STATIC
${ENGINE_SRC}
add_library(imgui STATIC ${IMGUI_SOURCES}
${IMGUI_DIR}/imgui.cpp vendor/rlImGui/rlImGui.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
) )
target_include_directories(imgui PUBLIC ${IMGUI_DIR})
# rlImGui set_target_properties(${PROJECT_NAME}_lib PROPERTIES OUTPUT_NAME "varicle")
set(RLIMGUI_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/rlImGui")
add_library(rlImGui STATIC target_include_directories(${PROJECT_NAME}_lib PUBLIC
${RLIMGUI_DIR}/rlImGui.cpp $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/imgui>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/rlImGui>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/entt>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/json>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
target_include_directories(rlImGui PUBLIC ${RLIMGUI_DIR}) target_link_libraries(${PROJECT_NAME}_lib PUBLIC
target_link_libraries(rlImGui PUBLIC imgui raylib)
#------------------------------------------------------------------------------------------
# Executable
#------------------------------------------------------------------------------------------
add_executable(${PROJECT_NAME} ${SRC})
# Export ImGui headers so anything linking to 'imgui' gets them automatically
target_include_directories(${PROJECT_NAME} PRIVATE vendor/entt src)
target_link_libraries(${PROJECT_NAME} PRIVATE
AssetPacker::assetpacker AssetPacker::assetpacker
rlImGui
imgui
raylib raylib
) )
#------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Make Assets # 4. Clean Export & Install
#------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Install engine library + raylib
install(TARGETS ${PROJECT_NAME}_lib assetpacker_lib
EXPORT ${PROJECT_NAME}Targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# Copy header files straight into dist/include for consumer projects
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp")
install(FILES ${IMGUI_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/imgui )
install(FILES ${RLIMGUI_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rlImGui )
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/vendor/entt/entt" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/vendor/json/json.hpp" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/json )
# Standard CMake package export
install(EXPORT ${PROJECT_NAME}Targets
FILE ${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
# ------------------------------------------------------------------------------
# 5. Standalone Sandbox App / Executable
# ------------------------------------------------------------------------------
# file(GLOB_RECURSE APP_SRC "src/*.cpp")
# add_executable(${PROJECT_NAME} ${APP_SRC})
#
# target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_lib)
#
# if(EMSCRIPTEN)
# set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html")
# target_link_options(${PROJECT_NAME} PRIVATE
# "-sUSE_GLFW=3"
# "-sASYNCIFY"
# "--shell-file" "${CMAKE_CURRENT_SOURCE_DIR}/html/shell_custom.html"
# )
# endif()
# #------------------------------------------------------------------------------------------
# # Make Assets
# #------------------------------------------------------------------------------------------
#
set(BUILD_ASSET_DIR "${CMAKE_CURRENT_BINARY_DIR}/assets") set(BUILD_ASSET_DIR "${CMAKE_CURRENT_BINARY_DIR}/assets")
set(PACKED_DATA_FILE "${CMAKE_CURRENT_BINARY_DIR}/data.dat") set(PACKED_DATA_FILE "${CMAKE_CURRENT_BINARY_DIR}/data.dat")
#
add_custom_target( pack-asset add_custom_target( pack-asset
COMMAND ${CMAKE_COMMAND} -E copy_directory COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/assets" "${CMAKE_CURRENT_SOURCE_DIR}/assets"
@@ -99,9 +137,9 @@ add_custom_target( pack-asset
) )
# ------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------
# WebAssembly / Emscripten Configurations # # WebAssembly / Emscripten Configurations
# ------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------
if(EMSCRIPTEN) if(EMSCRIPTEN)
# Output an HTML page instead of a raw binary # Output an HTML page instead of a raw binary
@@ -121,8 +159,16 @@ if(EMSCRIPTEN)
endif() endif()
add_custom_target( run add_custom_target( run
COMMAND ${PROJECT_NAME} COMMAND ${PROJECT_NAME}
DEPENDS ${PROJECT_NAME} DEPENDS ${PROJECT_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) )
if (BUILD_EXAMPLES)
add_subdirectory(examples/example1)
add_subdirectory(examples/example2)
endif()
# enable_testing()
# add_subdirectory(tests)
+284
View File
@@ -0,0 +1,284 @@
cmake_minimum_required(VERSION 3.25)
project(varicle LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
# Default install location: <your-project-folder>/dist
set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/dist" CACHE PATH "Local export directory" FORCE)
endif()
file( GLOB_RECURSE
SRC
CONFIGURE
"src/*cpp"
"src/*.hpp"
)
#------------------------------------------------------------------------------------------
# DiSt
#------------------------------------------------------------------------------------------
if(BUILD_FOR_WEB OR EMSCRIPTEN)
set(DIST_PLATFORM "web")
else()
set(DIST_PLATFORM "desktop")
endif()
set(DIST_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dist/${DIST_PLATFORM}")
#------------------------------------------------------------------------------------------
# Subdirectories
#------------------------------------------------------------------------------------------
set(BUILD_EXAMPLES OFF)
add_subdirectory(vendor/raylib)
add_subdirectory(vendor/asset-packer)
#------------------------------------------------------------------------------------------
# HEADERS AND SOURCE FILES
#------------------------------------------------------------------------------------------
#ImGui
set(IMGUI_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/imgui")
add_library(imgui STATIC
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_demo.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/imgui_widgets.cpp
)
# target_include_directories(imgui PUBLIC ${IMGUI_DIR})
file(GLOB IMGUI_HEADERS
CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/vendor/imgui/*.h"
)
target_include_directories(imgui PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/imGui>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_sources(imgui INTERFACE
FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/vendor/
FILES ${IMGUI_HEADERS}
)
# rlImGui
file(GLOB RLIMGUI_HEADERS
CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/vendor/rlImGui/*.h"
)
set(RLIMGUI_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/rlImGui")
add_library(rlImGui STATIC
${RLIMGUI_DIR}/rlImGui.cpp
)
# target_include_directories(rlImGui PUBLIC ${RLIMGUI_DIR})
target_link_libraries(rlImGui PUBLIC imgui raylib)
target_include_directories(rlImGui PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/rlImGui>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_sources(rlImGui INTERFACE
FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/vendor/
FILES ${RLIMGUI_HEADERS}
)
#------------------------------------------------------------------------------------------
# Framework Library
#------------------------------------------------------------------------------------------
include(GNUInstallDirs)
file( GLOB_RECURSE
ENGINE_SRC
CONFIGURE
"src/engine/*cpp"
"src/engine/*.hpp"
)
add_library(${PROJECT_NAME}_lib ${ENGINE_SRC})
set_target_properties(${PROJECT_NAME}_lib PROPERTIES
OUTPUT_NAME "varicle"
)
target_include_directories(${PROJECT_NAME}_lib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/entt>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_link_libraries(${PROJECT_NAME}_lib PUBLIC
AssetPacker::assetpacker
rlImGui
imgui
raylib
)
target_sources(${PROJECT_NAME}_lib PUBLIC
FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/
FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/engine
)
# FRAMEWORK DEPENDECIES
#entt
add_library(entt INTERFACE)
target_include_directories(entt INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/entt>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_sources(entt INTERFACE
FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/vendor/entt
FILES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/entt/entt/entt.hpp
)
#json
add_library(json INTERFACE)
target_include_directories(json INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vendor/json>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>/json
)
target_sources(json INTERFACE
FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/vendor/json
FILES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/json/json.hpp
)
install(TARGETS ${PROJECT_NAME}_lib raylib entt json assetpacker_lib imgui rlImGui
EXPORT ${PROJECT_NAME}Targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # Static libs (.a / .lib)
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # Shared libs (.so / .dylib)
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # Windows DLLs (.dll)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/engine
FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(EXPORT ${PROJECT_NAME}Targets
FILE ${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
# 2. GENERATE the Config file (THIS IS THE MISSING PIECE!)
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/varicleConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/varicleConfig.cmake"
INSTALL_DESTINATION lib/cmake/varicle
)
# 3. INSTALL the Config file alongside varicleTargets.cmake
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/varicleConfig.cmake"
DESTINATION lib/cmake/varicle
)
#------------------------------------------------------------------------------------------
# Executable
#------------------------------------------------------------------------------------------
add_executable(${PROJECT_NAME} ${SRC})
# Export ImGui headers so anything linking to 'imgui' gets them automatically
target_include_directories(${PROJECT_NAME} PRIVATE vendor/entt src)
target_link_libraries(${PROJECT_NAME} PRIVATE
AssetPacker::assetpacker
rlImGui
imgui
raylib
)
#------------------------------------------------------------------------------------------
# Make Assets
#------------------------------------------------------------------------------------------
set(BUILD_ASSET_DIR "${CMAKE_CURRENT_BINARY_DIR}/assets")
set(PACKED_DATA_FILE "${CMAKE_CURRENT_BINARY_DIR}/data.dat")
add_custom_target( pack-asset
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/assets"
"${BUILD_ASSET_DIR}"
# 2. Pass relative paths to assetpacker!
# Because WORKING_DIRECTORY is ${CMAKE_CURRENT_BINARY_DIR},
# 'assets' resolves to './assets' and 'data.dat' resolves to './data.dat'
# Set execution context so relative paths inside assetpacker work
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMAND AssetPacker::packer "assets/"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/assets" AssetPacker::packer
COMMENT "Copying assets folder and packing via relative paths..."
VERBATIM
)
# ------------------------------------------------------------------------------
# WebAssembly / Emscripten Configurations
# ------------------------------------------------------------------------------
if(EMSCRIPTEN)
# Output an HTML page instead of a raw binary
set_target_properties(${PROJECT_NAME} PROPERTIES
OUTPUT_NAME "index"
SUFFIX ".html"
)
# Pass Emscripten linker flags
target_link_options(${PROJECT_NAME} PRIVATE
"-sUSE_GLFW=3" # Needed for Raylib web builds
"-sASYNCIFY" # Allows main loop to yield to the browser
"--shell-file" "${CMAKE_CURRENT_SOURCE_DIR}/html/shell_custom.html" # (Optional) Custom HTML shell
# Pre-pack your assets directory into the WebAssembly virtual filesystem
"--preload-file" "${CMAKE_CURRENT_BINARY_DIR}/data.dat@/data.dat"
)
endif()
add_custom_target( run
COMMAND ${PROJECT_NAME}
DEPENDS ${PROJECT_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
enable_testing()
add_subdirectory(tests)
+14
View File
@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.25)
project(example1 LANGUAGES CXX)
file(GLOB_RECURSE SRCS "src/*.cpp")
MESSAGE(STATUS ${SRCS})
add_executable(${PROJECT_NAME} ${SRCS})
target_include_directories(${PROJECT_NAME} PRIVATE src)
target_link_libraries(${PROJECT_NAME} PRIVATE varicle_lib)
@@ -5,7 +5,7 @@
#include "engine/ecs/components.hpp" #include "engine/ecs/components.hpp"
#include "engine/scene/scene.hpp" #include "engine/scene/scene.hpp"
#include "game/scenes/menu-scene/menu.hpp" #include "scenes/menu-scene/menu.hpp"
#include <entt/entt.hpp> #include <entt/entt.hpp>
#include <raylib.h> #include <raylib.h>
@@ -28,7 +28,7 @@ void MenuScene::init() {
registry.emplace<varicle::GlobalTransform2D>(e, 650.0f, 150.0f, 1.0f,0.0f); registry.emplace<varicle::GlobalTransform2D>(e, 650.0f, 150.0f, 1.0f,0.0f);
// registry.emplace<Position>(e, 650.0f, 150.0f); // registry.emplace<Position>(e, 650.0f, 150.0f);
registry.emplace<Sprite>(e, "assets/bird.png", 0.0f, 0.f, 100.f, 100.f, registry.emplace<Sprite>(e, "assets/bird.png", 0.0f, 0.f, 100.f, 100.f,
false, false, 0.f); true, false, 0.f);
auto img = auto img =
LoadImageFromTexture(*asset_loader.get_texture("assets/bird.png")); LoadImageFromTexture(*asset_loader.get_texture("assets/bird.png"));
SetWindowIcon(img); SetWindowIcon(img);
+14
View File
@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.25)
project(example2 LANGUAGES CXX)
file(GLOB_RECURSE SRCS "src/*.cpp")
MESSAGE(STATUS ${SRCS})
add_executable(${PROJECT_NAME} ${SRCS})
target_include_directories(${PROJECT_NAME} PRIVATE src)
target_link_libraries(${PROJECT_NAME} PRIVATE varicle_lib)
+1
View File
@@ -0,0 +1 @@
#pragma once
+32
View File
@@ -0,0 +1,32 @@
#include "engine/core/application.hpp"
#include "engine/core/engine-variant/engine-variant-property.hpp"
#include "engine/core/engine-variant/engine-variant.hpp"
#include "engine/core/service-locator.hpp"
#include "engine/ecs/components.hpp"
#include "engine/scene/scene.hpp"
#include "scenes/menu-scene/menu.hpp"
#include <entt/entt.hpp>
#include <raylib.h>
class Game : public varicle::Application {
public:
void on_init() override {
auto &scene_manager =
varicle::ServiceLocator::get<varicle::SceneManager>();
scene_manager.register_scene(
"menu", []() { return std::make_unique<MenuScene>(); });
change_scene("menu");
}
void on_shutdown() override {}
};
int main() {
Game game;
game.run();
return 0;
}
@@ -0,0 +1,95 @@
#include "menu.hpp"
#include "engine/asset/raylib-asset.hpp"
#include "engine/core/engine-variant/engine-variant-property.hpp"
#include "engine/core/engine-variant/engine-variant.hpp"
#include "engine/core/service-locator.hpp"
#include "engine/ecs/components.hpp"
#include "engine/render/render-system.hpp"
#include <imgui.h>
#include <iostream>
#include <memory>
using namespace entt::literals;
void MenuScene::init() {
using namespace varicle;
ServiceLocator::provide(std::make_unique<RaylibAssetLoader>());
auto &asset_loader = ServiceLocator::get<RaylibAssetLoader>();
asset_loader.load_asset("assets/bird.png");
auto x = asset_loader.get_reader().get_asset_list();
for (auto i : x) {
std::cout << i << std::endl;
}
auto e = registry.create();
registry.emplace<varicle::GlobalTransform2D>(e, 650.0f, 150.0f, 1.0f,0.0f);
// registry.emplace<Position>(e, 650.0f, 150.0f);
registry.emplace<Sprite>(e, "assets/bird.png", 0.0f, 0.f, 100.f, 100.f,
true, false, 0.f);
auto img =
LoadImageFromTexture(*asset_loader.get_texture("assets/bird.png"));
SetWindowIcon(img);
UnloadImage(img);
auto &p_database = varicle::ServiceLocator::get<PropertyDatabase>();
registry.emplace<varicle::LocalTransform2D>(e, 100.0f, 100.0f, 10.0f,
5.0f);
EngineVariant current_pos =
p_database.get_value(registry, e, "global_position"_hs);
EngineVariant current_scale =
p_database.get_value(registry, e, "scale"_hs);
EngineVariant current_rot =
p_database.get_value(registry, e, "rotation"_hs);
std::cout << current_pos << current_scale << current_rot << std::endl;
}
void MenuScene::update(float dt) {}
void MenuScene::render() {
varicle::update_render_system(registry);
DrawCircleV({650,400},100,PURPLE);
}
void MenuScene::ui() {
// Get the current screen/viewport size
ImVec2 screen_size = ImGui::GetIO().DisplaySize;
// size of button container
ImVec2 vbox_size = ImVec2(200.0f, 250.0f);
// set next container to be center of the screen
ImVec2 screen_center = ImVec2(screen_size.x * 0.5f, screen_size.y * 0.5f);
ImGui::SetNextWindowPos(screen_center, ImGuiCond_Always,
ImVec2(0.5f, 0.5f));
ImGui::SetNextWindowSize(vbox_size);
// remove sub window decoration
ImGuiWindowFlags flags =
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground;
ImGui::Begin("VBoxContainer", nullptr, flags);
// set button width to be size fill container
ImVec2 button_size = ImVec2(ImGui::GetContentRegionAvail().x, 50.0f);
// ImGui::SetCursorPos(centeredPos);
if (ImGui::Button("Play", button_size)) {
v::ServiceLocator::get<v::SceneManager>().switch_to_scene("main");
}
ImGui::Dummy(ImVec2(0, 10)); // Gap
if (ImGui::Button("Quit", button_size)) {
v::ServiceLocator::get<v::SceneManager>().quit();
}
ImGui::End();
}
@@ -0,0 +1,15 @@
#pragma once
#include "engine/scene/scene.hpp"
#include <entt/entt.hpp>
namespace v = varicle;
class MenuScene : public v::Scene {
public:
entt::registry registry;
void init() override;
void update(float dt) override;
void render() override;
void ui() override;
};
@@ -2,8 +2,12 @@
#include "engine-variant.hpp" #include "engine-variant.hpp"
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; namespace varicle {
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
template <class... Ts> struct overloaded : Ts... {
using Ts::operator()...;
};
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
enum class OpType { enum class OpType {
Assign, // Replace the old value entirely Assign, // Replace the old value entirely
@@ -13,62 +17,95 @@ enum class OpType {
}; };
struct VariantOpRequest { struct VariantOpRequest {
EngineVariant* target; // The variable we want to change EngineVariant *target; // The variable we want to change
OpType operation; // How we want to change it OpType operation; // How we want to change it
EngineVariant operand; // The value we are using to make the change EngineVariant operand; // The value we are using to make the change
float alpha; // Used ONLY for Lerp (0.0 to 1.0) float alpha; // Used ONLY for Lerp (0.0 to 1.0)
}; };
class VariantOpManager{ class VariantOpManager {
public: public:
VariantOpManager(){} VariantOpManager() {}
void ExecuteOperation(const VariantOpRequest& req) { void ExecuteOperation(const VariantOpRequest &req) {
if (req.target == nullptr) return; if (req.target == nullptr)
return;
switch (req.operation){ switch (req.operation) {
case OpType::Assign: case OpType::Assign:
req.target->data = req.operand.data; req.target->data = req.operand.data;
req.target->type = req.operand.type;
break; break;
case OpType::Add: case OpType::Add:
req.target->data = std::visit( req.target->data = std::visit(
overloaded{ overloaded{
[](float p, float n) -> EngineVariant::InternalVariant {return p + n;}, [](float p, float n) -> EngineVariant::InternalVariant {
[](Vec2 p, Vec2 n) -> EngineVariant::InternalVariant {return p + n;}, return p + n;
[](Vec3 p, Vec3 n) -> EngineVariant::InternalVariant {return p + n;}, },
[](Vec4 p, Vec4 n) -> EngineVariant::InternalVariant {return p + n;}, [](Vec2 p, Vec2 n) -> EngineVariant::InternalVariant {
return p + n;
// Fallback },
[](auto p, auto n) -> EngineVariant::InternalVariant {return p;}, [](Vec3 p, Vec3 n) -> EngineVariant::InternalVariant {
},req.target->data,req.operand.data); return p + n;
break; },
[](Vec4 p, Vec4 n) -> EngineVariant::InternalVariant {
case OpType::Lerp: return p + n;
req.target->data = std::visit(overloaded{
[&](float p, float n) -> EngineVariant::InternalVariant { return p + (n - p) * req.alpha; },
[&](Vec2 p, Vec2 n) -> EngineVariant::InternalVariant { return Vec2Lerp(p, n, req.alpha); },
[&](Vec3 p, Vec3 n) -> EngineVariant::InternalVariant { return Vec3Lerp(p, n, req.alpha); },
[&](Vec4 p, Vec4 n) -> EngineVariant::InternalVariant { return Vec4Lerp(p, n, req.alpha); },
[&](const std::string& p, const std::string& n) -> EngineVariant::InternalVariant {
return req.alpha >= 0.5f ? n : p; // Discrete switch for strings
}, },
// Fallback // Fallback
[](auto p, auto n) -> EngineVariant::InternalVariant { return p; } [](auto p, auto n) -> EngineVariant::InternalVariant {
}, req.target->data, req.operand.data); return p;
},
},
req.target->data, req.operand.data);
break;
case OpType::Lerp:
req.target->data = std::visit(
overloaded{
[&](float p, float n) -> EngineVariant::InternalVariant {
return p + (n - p) * req.alpha;
},
[&](Vec2 p, Vec2 n) -> EngineVariant::InternalVariant {
return vec2_lerp(p, n, req.alpha);
},
[&](Vec3 p, Vec3 n) -> EngineVariant::InternalVariant {
return vec3_lerp(p, n, req.alpha);
},
[&](Vec4 p, Vec4 n) -> EngineVariant::InternalVariant {
return vec4_lerp(p, n, req.alpha);
},
[&](const std::string &p, const std::string &n)
-> EngineVariant::InternalVariant {
return req.alpha >= 0.5f
? n
: p; // Discrete switch for strings
},
// Fallback
[](auto p, auto n) -> EngineVariant::InternalVariant {
return p;
}},
req.target->data, req.operand.data);
break; break;
case OpType::Multiply: case OpType::Multiply:
req.target->data = std::visit(overloaded{ req.target->data = std::visit(
[](float p, float n) -> EngineVariant::InternalVariant { return p * n; }, overloaded{
[](Vec2 p, float n) -> EngineVariant::InternalVariant { return p * n; }, // Scale a vector! [](float p, float n) -> EngineVariant::InternalVariant {
[](auto p, auto n) -> EngineVariant::InternalVariant { return p; } return p * n;
}, req.target->data, req.operand.data); },
[](Vec2 p, float n) -> EngineVariant::InternalVariant {
return p * n;
}, // Scale a vector!
[](auto p, auto n) -> EngineVariant::InternalVariant {
return p;
}},
req.target->data, req.operand.data);
break; break;
} }
} }
}; };
} // namespace varicle
@@ -0,0 +1,32 @@
#pragma once
#include <entt/entt.hpp>
namespace varicle {
namespace PropertyID {
using namespace entt::literals;
// Guaranteed unique & typo-proof at compile time!
constexpr auto TransformPosition = "transform:position"_hs;
constexpr auto TransformScale = "transform:scale"_hs;
constexpr auto TransformRotation = "transform:rotation"_hs;
constexpr auto GlobalTransformPosition = "global_transform:position"_hs;
constexpr auto GlobalTransformScale = "global_transform:scale"_hs;
constexpr auto GlobalTransformRotation = "global_transform:rotation"_hs;
constexpr auto VelocityX = "velocity:x"_hs;
constexpr auto VelocityY = "velocity:y"_hs;
constexpr auto SpriteRotation = "sprite:rotation"_hs;
constexpr auto SpriteTexture = "sprite:texture"_hs;
constexpr auto SpriteOffsetX = "sprite:offset:x"_hs;
constexpr auto SpriteOffsetY = "sprite:offset:y"_hs;
constexpr auto SpriteWidth = "sprite:width"_hs;
constexpr auto SpriteHeight = "sprite:height"_hs;
constexpr auto SpriteFlipV = "sprite:flip_v"_hs;
constexpr auto SpriteFlipH = "sprite:flip_h"_hs;
} // namespace PropertyID
} // namespace varicle
@@ -6,10 +6,12 @@
#include <functional> #include <functional>
#include <unordered_map> #include <unordered_map>
namespace varicle {
using VariantGetter = using VariantGetter =
std::function<EngineVariant(const entt::registry &, entt::entity)>; std::function<EngineVariant(const entt::registry &, entt::entity)>;
using VariantSetter = std::function<void(entt::registry &, entt::entity, using VariantSetter =
const EngineVariant &)>; std::function<bool(entt::registry &, entt::entity, const EngineVariant &)>;
struct PropertyRef { struct PropertyRef {
uint32_t property_id; uint32_t property_id;
@@ -20,10 +22,11 @@ struct PropertyRef {
return getter ? getter(reg, e) : EngineVariant(); return getter ? getter(reg, e) : EngineVariant();
} }
void set(entt::registry &reg, entt::entity e, bool set(entt::registry &reg, entt::entity e,
const EngineVariant &value) const { const EngineVariant &value) const {
if (setter) if (setter)
setter(reg, e, value); return setter(reg, e, value);
return false;
} }
}; };
@@ -31,24 +34,33 @@ class PropertyRegistry {
public: public:
template <typename Component, typename T> template <typename Component, typename T>
static PropertyRef bind_field(uint32_t prop_hash, T Component::*member) { static PropertyRef bind_field(uint32_t prop_hash, T Component::*member) {
return PropertyRef{.property_id = prop_hash, return PropertyRef{
.property_id = prop_hash,
.setter = .setter = [member, prop_hash](entt::registry &reg, entt::entity e,
[member](entt::registry &reg, entt::entity e, const EngineVariant &val) -> bool {
const EngineVariant &val) { auto *comp = reg.try_get<Component>(e);
if (auto *comp = reg.try_get<Component>(e)) { if (!comp) {
(*comp).*member = val.Get<T>(); return false;
} }
if (const T *val_ptr = val.try_get<T>()) {
(*comp).*member = *val_ptr;
return true;
}
// Type mismatch caught safely!
std::cout << "[WARN] Property type mismatch: cannot assign "
"value to property hash "
<< prop_hash << "\n";
return false;
}, },
.getter = [member](const entt::registry &reg, .getter = [member](const entt::registry &reg,
entt::entity e) -> EngineVariant { entt::entity e) -> EngineVariant {
if (auto *component = if (auto *component = reg.try_get<Component>(e)) {
reg.try_get<Component>(e)) {
return EngineVariant((*component).*member); return EngineVariant((*component).*member);
} }
return EngineVariant(); return EngineVariant();
} }};
};
} }
}; };
@@ -70,13 +82,13 @@ class PropertyDatabase {
return EngineVariant(); return EngineVariant();
} }
bool set_value(entt::registry &reg, entt::entity e, bool set_value(entt::registry &reg, entt::entity e, uint32_t prop_hash,
uint32_t prop_hash, const EngineVariant &value) const { const EngineVariant &value) const {
auto it = properites.find(prop_hash); auto it = properites.find(prop_hash);
if (it != properites.end()) { if (it != properites.end()) {
it->second.set(reg, e, value); it->second.set(reg, e, value);
return true;
} }
return false; return false;
} }
}; };
} // namespace varicle
@@ -3,11 +3,11 @@
#include <string> #include <string>
#include <variant> #include <variant>
namespace varicle {
// Overload helper pattern // Overload helper pattern
template <class... Ts> struct Overloaded : Ts... { template <typename... Ts> struct Overloaded : Ts... {
using Ts::operator()...; using Ts::operator()...;
}; };
template <class... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;
struct Vec2 { struct Vec2 {
float x = 0.0f; float x = 0.0f;
@@ -58,14 +58,14 @@ struct Vec4 {
}; };
// Standalone Interpolation Helpers // Standalone Interpolation Helpers
inline Vec2 Vec2Lerp(const Vec2 &s, const Vec2 &e, float a) { inline Vec2 vec2_lerp(const Vec2 &s, const Vec2 &e, float a) {
return {s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a}; return {s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a};
} }
inline Vec3 Vec3Lerp(const Vec3 &s, const Vec3 &e, float a) { inline Vec3 vec3_lerp(const Vec3 &s, const Vec3 &e, float a) {
return {s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a, return {s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a,
s.z + (e.z - s.z) * a}; s.z + (e.z - s.z) * a};
} }
inline Vec4 Vec4Lerp(const Vec4 &s, const Vec4 &e, float a) { inline Vec4 vec4_lerp(const Vec4 &s, const Vec4 &e, float a) {
return {s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a, s.z + (e.z - s.z) * a, return {s.x + (e.x - s.x) * a, s.y + (e.y - s.y) * a, s.z + (e.z - s.z) * a,
s.w + (e.w - s.w) * a}; s.w + (e.w - s.w) * a};
} }
@@ -75,8 +75,8 @@ enum class VariantType { Null, Float, Vector2, Vector3, Vector4, String };
class EngineVariant { class EngineVariant {
public: public:
using InternalVariant = using InternalVariant = std::variant<std::monostate, float, Vec2, Vec3,
std::variant<std::monostate, float, Vec2, Vec3, Vec4, std::string, bool>; Vec4, std::string, bool>;
EngineVariant() : data(std::monostate{}) {} EngineVariant() : data(std::monostate{}) {}
EngineVariant(float v) : data(v) {} EngineVariant(float v) : data(v) {}
@@ -86,10 +86,12 @@ class EngineVariant {
EngineVariant(std::string v) : data(v) {} EngineVariant(std::string v) : data(v) {}
EngineVariant(bool v) : data(v) {} EngineVariant(bool v) : data(v) {}
template <typename T> T Get() const { return std::get<T>(data); } template <typename T> T get() const { return std::get<T>(data); }
template <typename T> T *TryGet() { return std::get_if<T>(&data); } template <typename T> const T *try_get() const {
return std::get_if<T>(&data);
}
std::string ToString() const { std::string to_string() const {
return std::visit( return std::visit(
Overloaded{[](std::monostate) { return std::string("!"); }, Overloaded{[](std::monostate) { return std::string("!"); },
[](float v) { return std::to_string(v); }, [](float v) { return std::to_string(v); },
@@ -109,41 +111,34 @@ class EngineVariant {
std::to_string(v.w) + ")"; std::to_string(v.w) + ")";
}, },
[](const std::string &s) { return s; }, [](const std::string &s) { return s; },
[](const bool &b) { return std::string(b ? "true" : "false"); }}, [](const bool &b) {
return std::string(b ? "true" : "false");
}},
data); data);
} }
friend std::ostream &operator<<(std::ostream &os, friend std::ostream &operator<<(std::ostream &os,
const EngineVariant &variant) { const EngineVariant &variant) {
return os << variant.GetTypeName() << variant.ToString(); return os << variant.get_type_name() << variant.to_string();
} }
private: private:
InternalVariant data; InternalVariant data;
std::string GetTypeName() const { std::string get_type_name() const {
return std::visit( return std::visit(
[](auto &&arg) -> std::string { Overloaded{
using T = std::decay_t<decltype(arg)>; [](std::monostate) -> std::string { return "Null"; },
if constexpr (std::is_same_v<T, std::monostate>) [](bool) -> std::string { return "Bool"; },
return "Null"; [](float) -> std::string { return "Float"; },
else if constexpr (std::is_same_v<T, float>) [](const Vec2 &) -> std::string { return "Vec2"; },
return "Float"; [](const Vec3 &) -> std::string { return "Vec3"; },
else if constexpr (std::is_same_v<T, Vec2>) [](const Vec4 &) -> std::string { return "Vec4"; },
return "Vec2"; [](const std::string &) -> std::string { return "String"; },
else if constexpr (std::is_same_v<T, Vec3>) [](const auto &) -> std::string { return "Unknown"; }},
return "Vec3";
else if constexpr (std::is_same_v<T, Vec4>)
return "Vec4";
else if constexpr (std::is_same_v<T, std::string>)
return "String";
else if constexpr (std::is_same_v<T, bool>)
return "Bool";
else
return "Unknown";
},
data); data);
} }
friend class VariantOpManager; friend class VariantOpManager;
}; };
} // namespace varicle
+47 -40
View File
@@ -1,5 +1,6 @@
#include "bindings.hpp" #include "bindings.hpp"
#include "components.hpp" #include "components.hpp"
#include "engine/core/engine-variant/engine-variant-property-id.hpp"
using namespace entt::literals; using namespace entt::literals;
@@ -9,84 +10,90 @@ void varicle::register_all_component_properties(PropertyDatabase &db) {
// LocalTransform2D // LocalTransform2D
//---------------------------------------------------------- //----------------------------------------------------------
db.register_property( db.register_property(
"position"_hs, PropertyID::TransformPosition,
PropertyRegistry::bind_field("position"_hs, PropertyRegistry::bind_field(PropertyID::TransformPosition,
&varicle::LocalTransform2D::position)); &varicle::LocalTransform2D::position));
db.register_property("scale"_hs, db.register_property(
PropertyRegistry::bind_field( PropertyID::TransformScale,
"scale"_hs, &varicle::LocalTransform2D::scale)); PropertyRegistry::bind_field(PropertyID::TransformScale,
&varicle::LocalTransform2D::scale));
db.register_property( db.register_property(
"rotation"_hs, PropertyID::TransformRotation,
PropertyRegistry::bind_field("rotation"_hs, PropertyRegistry::bind_field(PropertyID::TransformRotation,
&varicle::LocalTransform2D::rotation)); &varicle::LocalTransform2D::rotation));
//---------------------------------------------------------- //----------------------------------------------------------
// GlobalTransform2D // GlobalTransform2D
//---------------------------------------------------------- //----------------------------------------------------------
db.register_property( db.register_property(
"global_position"_hs, PropertyID::GlobalTransformPosition,
PropertyRegistry::bind_field("global_position"_hs, PropertyRegistry::bind_field(PropertyID::GlobalTransformPosition,
&varicle::GlobalTransform2D::position)); &varicle::GlobalTransform2D::position));
db.register_property("global_scale"_hs, db.register_property(
PropertyRegistry::bind_field( PropertyID::GlobalTransformScale,
"global_scale"_hs, &varicle::GlobalTransform2D::scale)); PropertyRegistry::bind_field(PropertyID::GlobalTransformScale,
&varicle::GlobalTransform2D::scale));
db.register_property( db.register_property(
"global_rotation"_hs, PropertyID::GlobalTransformRotation,
PropertyRegistry::bind_field("global_rotation"_hs, PropertyRegistry::bind_field(PropertyID::GlobalTransformRotation,
&varicle::GlobalTransform2D::rotation)); &varicle::GlobalTransform2D::rotation));
//---------------------------------------------------------- //----------------------------------------------------------
// Velocity // Velocity
//---------------------------------------------------------- //----------------------------------------------------------
db.register_property( db.register_property(PropertyID::VelocityX,
"velocity:x"_hs, PropertyRegistry::bind_field(PropertyID::VelocityX,
PropertyRegistry::bind_field("velocity:x"_hs, &varicle::Velocity::dx)); &varicle::Velocity::dx));
db.register_property( db.register_property(PropertyID::VelocityY,
"velocity:y"_hs, PropertyRegistry::bind_field(PropertyID::VelocityY,
PropertyRegistry::bind_field("velocity:y"_hs, &varicle::Velocity::dy)); &varicle::Velocity::dy));
//---------------------------------------------------------- //----------------------------------------------------------
// Sprite // Sprite
//---------------------------------------------------------- //----------------------------------------------------------
db.register_property( db.register_property(
"sprite:texture_path"_hs, PropertyID::SpriteTexture,
PropertyRegistry::bind_field("sprite:texture_path"_hs, &varicle::Sprite::texture_path)); PropertyRegistry::bind_field(PropertyID::SpriteTexture,
&varicle::Sprite::texture_path));
db.register_property( db.register_property(
"sprite:offset:y"_hs, PropertyID::SpriteOffsetY,
PropertyRegistry::bind_field("sprite:offset:y"_hs, &varicle::Sprite::offset_y)); PropertyRegistry::bind_field(PropertyID::SpriteOffsetY,
&varicle::Sprite::offset_y));
db.register_property( db.register_property(
"sprite:offset:x"_hs, PropertyID::SpriteOffsetX,
PropertyRegistry::bind_field("sprite:offset:x"_hs, &varicle::Sprite::offset_x)); PropertyRegistry::bind_field(PropertyID::SpriteOffsetX,
&varicle::Sprite::offset_x));
db.register_property(PropertyID::SpriteWidth,
PropertyRegistry::bind_field(PropertyID::SpriteWidth,
&varicle::Sprite::width));
db.register_property( db.register_property(
"sprite:width"_hs, PropertyID::SpriteHeight,
PropertyRegistry::bind_field("sprite:width"_hs, &varicle::Sprite::width)); PropertyRegistry::bind_field(PropertyID::SpriteHeight,
&varicle::Sprite::height));
db.register_property( db.register_property(
"sprite:height"_hs, PropertyID::SpriteFlipH,
PropertyRegistry::bind_field("sprite:height"_hs, &varicle::Sprite::height)); PropertyRegistry::bind_field(PropertyID::SpriteFlipH,
&varicle::Sprite::flip_h));
db.register_property( db.register_property(
"sprite:flip_h"_hs, PropertyID::SpriteFlipV,
PropertyRegistry::bind_field("sprite:flip_h"_hs, &varicle::Sprite::flip_h)); PropertyRegistry::bind_field(PropertyID::SpriteFlipV,
&varicle::Sprite::flip_v));
db.register_property( db.register_property(
"sprite:flip_v"_hs, PropertyID::SpriteRotation,
PropertyRegistry::bind_field("sprite:flip_v"_hs, &varicle::Sprite::flip_v)); PropertyRegistry::bind_field(PropertyID::SpriteRotation,
&varicle::Sprite::rotation));
db.register_property(
"sprite:rotation"_hs,
PropertyRegistry::bind_field("sprite:rotation"_hs, &varicle::Sprite::rotation));
} }
+22 -27
View File
@@ -3,55 +3,50 @@
#include "engine/core/service-locator.hpp" #include "engine/core/service-locator.hpp"
#include "engine/ecs/components.hpp" #include "engine/ecs/components.hpp"
#include<raylib.h>
#include <entt/entt.hpp> #include <entt/entt.hpp>
#include <raylib.h>
namespace varicle { namespace varicle {
void update_render_system(entt::registry &registry){ void update_render_system(entt::registry &registry) {
auto view = registry.view<const Sprite, const GlobalTransform2D>(); auto view = registry.view<const Sprite, const GlobalTransform2D>();
for (entt::entity entity : view){ for (entt::entity entity : view) {
const Sprite &sprite = view.get<Sprite>(entity); const Sprite &sprite = view.get<Sprite>(entity);
auto [global_position,global_scale,global_rotation] = view.get<GlobalTransform2D>(entity); auto [global_position, global_scale, global_rotation] =
auto texture = ServiceLocator::get<RaylibAssetLoader>().get_texture(sprite.texture_path); view.get<GlobalTransform2D>(entity);
auto texture = ServiceLocator::get<RaylibAssetLoader>().get_texture(
sprite.texture_path);
float width = sprite.width * global_scale; float width = sprite.width * global_scale;
float height = sprite.height * global_scale; float height = sprite.height * global_scale;
float rotation = sprite.rotation + global_rotation; float rotation = sprite.rotation + global_rotation;
if (texture){ if (texture) {
DrawTexturePro( DrawTexturePro(
*(texture), *(texture),
Rectangle{ Rectangle{
0, 0.0f,
0, 0.0f,
(float)texture->width, static_cast<float>(sprite.flip_h ? -texture->width
(float)texture->height, : texture->width),
static_cast<float>(sprite.flip_v ? -texture->height
: texture->height),
}, },
Rectangle { Rectangle{
sprite.offset_x + global_position.x, sprite.offset_x + global_position.x,
sprite.offset_y + global_position.y, sprite.offset_y + global_position.y,
width, width,
height, height,
}, },
Vector2 {width * 0.5f, height*0.5f}, Vector2{width * 0.5f, height * 0.5f}, rotation, WHITE);
rotation,
WHITE);
}else{ } else {
DrawRectanglePro(Rectangle { DrawRectanglePro(
sprite.offset_x + global_position.x, Rectangle{sprite.offset_x + global_position.x,
sprite.offset_y + global_position.y, sprite.offset_y + global_position.y, width, height},
width, Vector2{width * 0.5f, height * 0.5f}, rotation, PURPLE);
height
},
Vector2 {width * 0.5f, height*0.5f},
rotation,
PURPLE
);
} }
} }
}
} }
} // namespace varicle
+50
View File
@@ -0,0 +1,50 @@
cmake_minimum_required(VERSION 3.25)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(farm-space LANGUAGES CXX)
add_executable(${PROJECT_NAME} src/main.cpp)
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_SOURCE_DIR}/dist/include
)
target_link_directories(${PROJECT_NAME} PUBLIC
${CMAKE_SOURCE_DIR}/dist/lib
)
target_link_libraries(${PROJECT_NAME} PUBLIC
varicle
raylib
assetpacker
)
if(EMSCRIPTEN)
# Output an HTML page instead of a raw binary
set_target_properties(${PROJECT_NAME} PROPERTIES
OUTPUT_NAME "index"
SUFFIX ".html"
)
# Pass Emscripten linker flags
target_link_options(${PROJECT_NAME} PRIVATE
"-sUSE_GLFW=3" # Needed for Raylib web builds
"-sASYNCIFY" # Allows main loop to yield to the browser
"--shell-file" "${CMAKE_CURRENT_SOURCE_DIR}/html/shell_custom.html" # (Optional) Custom HTML shell
# Pre-pack your assets directory into the WebAssembly virtual filesystem
"--preload-file" "${CMAKE_CURRENT_BINARY_DIR}/data.dat@/data.dat"
)
elseif(WIN32)
target_link_libraries(farm-space PRIVATE winmm opengl32 gdi32)
endif()
add_custom_target(run
COMMAND ${PROJECT_NAME}
DEPENDS ${PROJECT_NAME}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
+14
View File
@@ -0,0 +1,14 @@
file(GLOB TEST_SOURCES "*.cpp")
# Loop through each .cpp file and build a separate executable for it!
foreach(TEST_FILE ${TEST_SOURCES})
# Extract filename without path/extension (e.g., "test_property_reflection")
get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)
# Create individual target for this specific test
add_executable(${TEST_NAME} ${TEST_FILE})
target_link_libraries(${TEST_NAME} PRIVATE varicle_lib)
# Register each as an individual test with CTest
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
endforeach()
+79
View File
@@ -0,0 +1,79 @@
#include <iostream>
#include <cassert>
#include "engine/ecs/bindings.hpp"
#include "engine/ecs/components.hpp"
#include "engine/core/engine-variant/engine-variant.hpp"
#include "engine/core/engine-variant/engine-variant-property.hpp"
#include "engine/core/engine-variant/engine-variant-property-id.hpp"
#include <entt/entt.hpp>
using namespace varicle;
int main() {
std::cout << "[TEST] Starting Property Reflection & Type Safety Tests...\n";
// Setup ECS Registry & Property DB
entt::registry registry;
PropertyDatabase propDB;
register_all_component_properties(propDB);
// Create an Entity with LocalTransform2D & Sprite
entt::entity player = registry.create();
registry.emplace<LocalTransform2D>(player, Vec2{10.0f, 20.0f}, 1.5f);
registry.emplace<Sprite>(player,"",0.f,0.f,120.f,120.f,false,false,45.0f);
// =========================================================================
// TEST 1: Reading Values via PropertyID (Getter)
// =========================================================================
{
Vec2 pos = propDB.get_value(registry,player,varicle::PropertyID::TransformPosition).get<Vec2>();
float scale = propDB.get_value(registry,player,varicle::PropertyID::TransformScale).get<float>();
float rot = propDB.get_value(registry,player,varicle::PropertyID::SpriteRotation).get<float>();
assert(pos.x == 10.0f && pos.y == 20.0f && "Transform position getter failed!");
assert(scale == 1.5f && "Transform scale getter failed!");
assert(rot == 45.0f && "Sprite rotation getter failed!");
std::cout << " [PASS] Test 1: Getters retrieved correct values.\n";
}
// =========================================================================
// TEST 2: Writing Values via PropertyID (Setter)
// =========================================================================
{
propDB.set_value(registry,player,varicle::PropertyID::TransformPosition, Vec2{100.0f, 200.0f});
std::cout << "setting value: " << (propDB.set_value(registry,player,varicle::PropertyID::SpriteRotation, 90.0f) ? "success" : "failed");
propDB.set_value(registry,player,varicle::PropertyID::SpriteFlipH, true);
// Verify the actual component struct in EnTT was mutated directly!
const auto& transform = registry.get<LocalTransform2D>(player);
const auto& sprite = registry.get<Sprite>(player);
assert(transform.position.x == 100.0f && transform.position.y == 200.0f && "Position write failed!");
assert(sprite.rotation == 90.0f && "Rotation write failed!");
assert(sprite.flip_h == true && "FlipH write failed!");
std::cout << " [PASS] Test 2: Setters successfully mutated component struct.\n";
}
// =========================================================================
// TEST 3: Type Safety Guard (Attempting Wrong Type Assignment)
// =========================================================================
{
std::cout << " [INFO] Expecting type safety warning below:\n";
// Try to push a std::string into a float property (SpriteRotation)
EngineVariant badType(std::string("WrongTypeData"));
propDB.set_value(registry,player,varicle::PropertyID::SpriteRotation, badType);
// Verify value was NOT modified because type mismatch was caught
const auto& sprite = registry.get<Sprite>(player);
assert(sprite.rotation == 90.0f && "Type safety guard failed! Wrong type was written!");
std::cout << " [PASS] Test 3: Type Safety Guard blocked invalid type write.\n";
}
std::cout << "\n[SUCCESS] All reflection tests passed successfully!\n";
return 0;
}