diff --git a/.gitignore b/.gitignore index 13d419a..04e2c30 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,6 @@ *.so *.a *.out -build/ -dist/ -target/ # Dependencies node_modules/ @@ -18,26 +15,28 @@ venv/ __pycache__/ .mypy_cache/ .pytest_cache/ +target/ .gradle/ -julia-*/ -zig*/ -# Editors and IDEs +# Logs and temp files +*.log +*.tmp +*.swp + +# Editors .vscode/ .idea/ -*.swp -*.swo -*.tmp # System files .DS_Store Thumbs.db + +# Environment .env .env.local *.env.* -# Logs and coverage -*.log +# Coverage coverage/ htmlcov/ .coverage @@ -61,8 +60,4 @@ htmlcov/ *.Z *.lz *.lzo -*.tar.gz -*.tar.bz2 -*.tar.xz -*.tar.zst ``` \ No newline at end of file diff --git a/FarmEngine/assets/shaders/terrain.frag.glsl b/FarmEngine/assets/shaders/terrain.frag.glsl index 2763660..e91c76c 100644 --- a/FarmEngine/assets/shaders/terrain.frag.glsl +++ b/FarmEngine/assets/shaders/terrain.frag.glsl @@ -13,6 +13,10 @@ layout(binding = 2) uniform sampler2D normalMap; layout(binding = 3) uniform sampler2D roughnessMap; layout(binding = 4) uniform sampler2D metalnessMap; +layout(binding = 0) uniform CameraData { + vec3 cameraPosition; +} cameraData; + layout(binding = 5) uniform LightData { vec3 position; vec3 color; @@ -45,7 +49,7 @@ void main() { // Lighting vec3 lightDir = normalize(position - fragPosition); - vec3 viewDir = normalize(cameraPosition - fragPosition); + vec3 viewDir = normalize(cameraData.cameraPosition - fragPosition); vec3 halfDir = normalize(lightDir + viewDir); // Diffuse (Lambert) diff --git a/FarmEngine/core/Engine.h b/FarmEngine/core/Engine.h index 580ef8c..f453b7b 100644 --- a/FarmEngine/core/Engine.h +++ b/FarmEngine/core/Engine.h @@ -7,6 +7,10 @@ namespace farm { +// Alias for FarmEngine namespace to maintain backward compatibility +namespace EngineNS = FarmEngine; + + // Forward declarations class Window; class Renderer; diff --git a/FarmEngine/core/ecs/ECS.cpp b/FarmEngine/core/ecs/ECS.cpp index 7fdc8d2..832673a 100644 --- a/FarmEngine/core/ecs/ECS.cpp +++ b/FarmEngine/core/ecs/ECS.cpp @@ -31,8 +31,8 @@ void ECS::destroyEntity(EntityID entity) { // Limpiar componentes for (auto& componentList : components) { - if (componentList.second && entity < componentList.second->size()) { - (*componentList.second)[entity].reset(); + if (entity < componentList.size()) { + componentList[entity].reset(); } } diff --git a/FarmEngine/core/ecs/ECS.h b/FarmEngine/core/ecs/ECS.h index 362a51e..f4bd2b9 100644 --- a/FarmEngine/core/ecs/ECS.h +++ b/FarmEngine/core/ecs/ECS.h @@ -56,8 +56,8 @@ class ECS { private: std::vector entities; std::vector availableIDs; - std::unordered_map>> components; - std::unordered_map componentTypeToIndex; + std::vector>> components; + std::unordered_map componentTypeToIndex; uint32_t nextComponentIndex = 0; @@ -68,18 +68,18 @@ class ECS { // Template implementations template T& ECS::addComponent(EntityID entity, Args&&... args) { + if (entity >= entities.size() || !entities[entity].active) { + throw std::out_of_range("Invalid or inactive entity ID"); + } + auto index = getComponentTypeIndex(); if (index >= components.size()) { components.resize(index + 1); } - if (!components[index]) { - components[index] = std::vector>(); - } - - while (components[index]->size() <= entity) { - components[index]->push_back(nullptr); + while (components[index].size() <= entity) { + components[index].push_back(nullptr); } auto component = std::make_unique(std::forward(args)...); @@ -94,13 +94,17 @@ T& ECS::addComponent(EntityID entity, Args&&... args) { template T* ECS::getComponent(EntityID entity) { + if (entity >= entities.size() || !entities[entity].active) { + return nullptr; + } + auto index = getComponentTypeIndex(); - if (index >= components.size() || !components[index]) { + if (index >= components.size()) { return nullptr; } - if (entity >= components[index]->size()) { + if (entity >= components[index].size()) { return nullptr; } @@ -109,9 +113,13 @@ T* ECS::getComponent(EntityID entity) { template void ECS::removeComponent(EntityID entity) { + if (entity >= entities.size() || !entities[entity].active) { + return; + } + auto index = getComponentTypeIndex(); - if (index < components.size() && components[index] && entity < components[index]->size()) { + if (index < components.size() && entity < components[index].size()) { components[index][entity].reset(); entities[entity].mask.reset(index); } @@ -119,9 +127,19 @@ void ECS::removeComponent(EntityID entity) { template uint32_t ECS::getComponentTypeIndex() { - static uint32_t index = []() { - return nextComponentIndex++; - }(); + auto key = std::type_index(typeid(T)); + + auto it = componentTypeToIndex.find(key); + if (it != componentTypeToIndex.end()) { + return it->second; + } + + if (nextComponentIndex >= MAX_COMPONENTS) { + throw std::overflow_error("Maximum number of component types exceeded"); + } + + uint32_t index = nextComponentIndex++; + componentTypeToIndex[key] = index; return index; } diff --git a/FarmEngine/core/memory/MemoryManager.cpp b/FarmEngine/core/memory/MemoryManager.cpp index e1176e5..81edb78 100644 --- a/FarmEngine/core/memory/MemoryManager.cpp +++ b/FarmEngine/core/memory/MemoryManager.cpp @@ -17,7 +17,7 @@ void* MemoryManager::allocate(size_t size, MemoryTag tag) { void* ptr = malloc(size); if (ptr) { - AllocationHeader header{size, tag, allocationCounter++}; + AllocationHeader header{ptr, size, tag, allocationCounter++}; allocations.push_back(header); totalAllocated += size; } @@ -28,11 +28,10 @@ void* MemoryManager::allocate(size_t size, MemoryTag tag) { void MemoryManager::deallocate(void* ptr) { if (!ptr) return; - // Buscar y remover la asignación + // Buscar y remover la asignación por puntero auto it = std::find_if(allocations.begin(), allocations.end(), [ptr](const AllocationHeader& h) { - // En una implementación real, compararíamos punteros reales - return false; // Simplificado para este ejemplo + return h.ptr == ptr; }); if (it != allocations.end()) { @@ -50,21 +49,28 @@ void* MemoryManager::reallocate(void* ptr, size_t newSize) { return nullptr; } + // Find old allocation to get old size + size_t oldSize = 0; + auto it = std::find_if(allocations.begin(), allocations.end(), + [ptr](const AllocationHeader& h) { + return h.ptr == ptr; + }); + + if (it != allocations.end()) { + oldSize = it->size; + } + void* newPtr = realloc(ptr, newSize); if (newPtr) { - // Find and update allocation header - auto it = std::find_if(allocations.begin(), allocations.end(), - [ptr, newPtr](const AllocationHeader& h) { - // In real implementation, compare actual pointers - return false; // Simplified for this example - }); - if (it != allocations.end()) { + // Update existing record totalAllocated -= it->size; + it->ptr = newPtr; it->size = newSize; totalAllocated += newSize; } else { - AllocationHeader header{newSize, MemoryTag::None, allocationCounter++}; + // Create new record if old one wasn't found + AllocationHeader header{newPtr, newSize, MemoryTag::None, allocationCounter++}; allocations.push_back(header); totalAllocated += newSize; } diff --git a/FarmEngine/core/memory/MemoryManager.h b/FarmEngine/core/memory/MemoryManager.h index 44032d9..c6717cf 100644 --- a/FarmEngine/core/memory/MemoryManager.h +++ b/FarmEngine/core/memory/MemoryManager.h @@ -47,6 +47,7 @@ class MemoryManager { MemoryManager& operator=(const MemoryManager&) = delete; struct AllocationHeader { + void* ptr; size_t size; MemoryTag tag; uint32_t id; diff --git a/FarmEngine/platform/input/Input.cpp b/FarmEngine/platform/input/Input.cpp new file mode 100644 index 0000000..8f42e49 --- /dev/null +++ b/FarmEngine/platform/input/Input.cpp @@ -0,0 +1,317 @@ +#include "Input.h" +#include + +namespace FarmEngine { + +// Keyboard implementation +Keyboard& Keyboard::getInstance() { + static Keyboard instance; + return instance; +} + +bool Keyboard::isKeyPressed(KeyCode key) const { + int index = static_cast(key); + if (index < 0 || index >= static_cast(currentKeys.size())) { + return false; + } + return currentKeys[index]; +} + +bool Keyboard::isKeyJustPressed(KeyCode key) const { + int index = static_cast(key); + if (index < 0 || index >= static_cast(justPressed.size())) { + return false; + } + return justPressed[index]; +} + +bool Keyboard::isKeyJustReleased(KeyCode key) const { + int index = static_cast(key); + if (index < 0 || index >= static_cast(justReleased.size())) { + return false; + } + return justReleased[index]; +} + +void Keyboard::setKeyCallback(std::function callback) { + keyCallback = std::move(callback); +} + +void Keyboard::setKeyState(KeyCode key, bool pressed) { + int index = static_cast(key); + if (index < 0 || index >= static_cast(currentKeys.size())) { + return; + } + + bool previousState = currentKeys[index]; + currentKeys[index] = pressed; + + if (pressed && !previousState) { + justPressed[index] = true; + } else if (!pressed && previousState) { + justReleased[index] = true; + } + + if (keyCallback) { + keyCallback(key, pressed ? InputAction::Press : InputAction::Release); + } +} + +void Keyboard::processFrame() { + // Reset just pressed/released states + std::fill(justPressed.begin(), justPressed.end(), false); + std::fill(justReleased.begin(), justReleased.end(), false); + + // Update previous state + previousKeys = currentKeys; +} + +// Mouse implementation +Mouse& Mouse::getInstance() { + static Mouse instance; + return instance; +} + +bool Mouse::isButtonPressed(MouseButton button) const { + int index = static_cast(button); + if (index < 0 || index >= static_cast(currentButtons.size())) { + return false; + } + return currentButtons[index]; +} + +bool Mouse::isButtonJustPressed(MouseButton button) const { + int index = static_cast(button); + if (index < 0 || index >= static_cast(justPressed.size())) { + return false; + } + return justPressed[index]; +} + +bool Mouse::isButtonJustReleased(MouseButton button) const { + int index = static_cast(button); + if (index < 0 || index >= static_cast(justReleased.size())) { + return false; + } + return justReleased[index]; +} + +void Mouse::resetScroll() { + scrollX = 0.0; + scrollY = 0.0; +} + +void Mouse::setButtonCallback(std::function callback) { + buttonCallback = std::move(callback); +} + +void Mouse::setScrollCallback(std::function callback) { + scrollCallback = std::move(callback); +} + +void Mouse::setMotionCallback(std::function callback) { + motionCallback = std::move(callback); +} + +void Mouse::setButtonState(MouseButton button, bool pressed) { + int index = static_cast(button); + if (index < 0 || index >= static_cast(currentButtons.size())) { + return; + } + + bool previousState = currentButtons[index]; + currentButtons[index] = pressed; + + if (pressed && !previousState) { + justPressed[index] = true; + } else if (!pressed && previousState) { + justReleased[index] = true; + } + + if (buttonCallback) { + buttonCallback(button, pressed ? InputAction::Press : InputAction::Release); + } +} + +void Mouse::setPosition(double x, double y) { + posX = x; + posY = y; + delta.x = static_cast(x - prevX); + delta.y = static_cast(y - prevY); + prevX = x; + prevY = y; + + if (motionCallback) { + motionCallback(x, y); + } +} + +void Mouse::setScroll(double x, double y) { + scrollX = x; + scrollY = y; + + if (scrollCallback) { + scrollCallback(x, y); + } +} + +void Mouse::processFrame() { + // Reset just pressed/released states + std::fill(justPressed.begin(), justPressed.end(), false); + std::fill(justReleased.begin(), justReleased.end(), false); + + // Update previous state + previousButtons = currentButtons; + + // Reset delta + delta = glm::vec2(0.0f, 0.0f); +} + +// Gamepad implementation +Gamepad& Gamepad::getInstance() { + static Gamepad instance; + return instance; +} + +bool Gamepad::isButtonPressed(Button::Type button) const { + int index = static_cast(button); + if (index < 0 || index >= static_cast(buttons.size())) { + return false; + } + return buttons[index]; +} + +float Gamepad::getAxis(Axis::Type axis) const { + int index = static_cast(axis); + if (index < 0 || index >= static_cast(axes.size())) { + return 0.0f; + } + return axes[index]; +} + +void Gamepad::setConnectionCallback(std::function callback) { + connectionCallback = std::move(callback); +} + +void Gamepad::setConnected(bool connected) { + bool wasConnected = this->connected; + this->connected = connected; + + if (connectionCallback && wasConnected != connected) { + connectionCallback(connected); + } +} + +void Gamepad::setButtonState(Button::Type button, bool pressed) { + int index = static_cast(button); + if (index < 0 || index >= static_cast(buttons.size())) { + return; + } + buttons[index] = pressed; +} + +void Gamepad::setAxisState(Axis::Type axis, float value) { + int index = static_cast(axis); + if (index < 0 || index >= static_cast(axes.size())) { + return; + } + axes[index] = value; +} + +// InputManager implementation +InputManager& InputManager::getInstance() { + static InputManager instance; + return instance; +} + +void InputManager::initialize() { + // Initialize keyboard + auto& keyboard = Keyboard::getInstance(); + + // Initialize mouse + auto& mouse = Mouse::getInstance(); + + // Initialize gamepad + auto& gamepad = Gamepad::getInstance(); +} + +void InputManager::cleanup() { + // Cleanup if needed +} + +void InputManager::update() { + Keyboard::getInstance().processFrame(); + Mouse::getInstance().processFrame(); +} + +void InputManager::setInputMode(InputMode mode) { + currentMode = mode; +} + +void InputManager::bindAction(const std::string& actionName, KeyCode key) { + actionBindings[actionName].keys.push_back(key); +} + +void InputManager::bindAction(const std::string& actionName, MouseButton button) { + actionBindings[actionName].buttons.push_back(button); +} + +bool InputManager::isActionPressed(const std::string& actionName) const { + auto it = actionBindings.find(actionName); + if (it == actionBindings.end()) { + return false; + } + + const auto& binding = it->second; + + // Check keys + for (KeyCode key : binding.keys) { + if (Keyboard::getInstance().isKeyPressed(key)) { + return true; + } + } + + // Check buttons + for (MouseButton button : binding.buttons) { + if (Mouse::getInstance().isButtonPressed(button)) { + return true; + } + } + + return false; +} + +void InputManager::bindAxis(const std::string& axisName, KeyCode positive, KeyCode negative) { + axisBindings[axisName] = {positive, negative}; +} + +float InputManager::getAxisValue(const std::string& axisName) const { + auto it = axisBindings.find(axisName); + if (it == axisBindings.end()) { + return 0.0f; + } + + const auto& binding = it->second; + float value = 0.0f; + + if (Keyboard::getInstance().isKeyPressed(binding.positive)) { + value += 1.0f; + } + + if (Keyboard::getInstance().isKeyPressed(binding.negative)) { + value -= 1.0f; + } + + return value; +} + +void InputManager::setVibration(float leftMotor, float rightMotor, float duration) { + // TODO: Implement gamepad vibration + (void)leftMotor; + (void)rightMotor; + (void)duration; +} + +InputManager::~InputManager() = default; + +} // namespace FarmEngine diff --git a/FarmEngine/platform/input/Input.h b/FarmEngine/platform/input/Input.h index e24b0cd..d5beca3 100644 --- a/FarmEngine/platform/input/Input.h +++ b/FarmEngine/platform/input/Input.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace FarmEngine { @@ -81,10 +81,10 @@ class Keyboard { private: Keyboard() = default; - std::vector currentKeys; - std::vector previousKeys; - std::vector justPressed; - std::vector justReleased; + std::array currentKeys{}; + std::array previousKeys{}; + std::array justPressed{}; + std::array justReleased{}; std::function keyCallback; }; @@ -129,10 +129,10 @@ class Mouse { double prevX = 0.0, prevY = 0.0; glm::vec2 delta{0.0f, 0.0f}; - std::vector currentButtons; - std::vector previousButtons; - std::vector justPressed; - std::vector justReleased; + std::array currentButtons{}; + std::array previousButtons{}; + std::array justPressed{}; + std::array justReleased{}; double scrollX = 0.0, scrollY = 0.0; @@ -179,8 +179,8 @@ class Gamepad { Gamepad() = default; bool connected = false; - std::vector buttons; - std::vector axes; + std::array buttons{}; + std::array axes{}; std::function connectionCallback; }; diff --git a/FarmEngine/renderer/2d/SpriteRenderer.h b/FarmEngine/renderer/2d/SpriteRenderer.h index f3787a8..75e53a9 100644 --- a/FarmEngine/renderer/2d/SpriteRenderer.h +++ b/FarmEngine/renderer/2d/SpriteRenderer.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace FarmEngine { diff --git a/FarmEngine/renderer/3d/MeshRenderer.h b/FarmEngine/renderer/3d/MeshRenderer.h index 3b3c544..b939514 100644 --- a/FarmEngine/renderer/3d/MeshRenderer.h +++ b/FarmEngine/renderer/3d/MeshRenderer.h @@ -156,7 +156,7 @@ class Renderer3D { void setViewProjection(const glm::mat4& view, const glm::mat4& projection); // Stats - uint32_t getDrawCalls() const { return drawCalls; } + uint32_t getDrawCalls() const { return drawCallCount; } uint32_t getTriangleCount() const { return triangleCount; } private: @@ -183,8 +183,8 @@ class Renderer3D { glm::mat4 viewMatrix; glm::mat4 projectionMatrix; - uint32_t drawCalls; - uint32_t triangleCount; + uint32_t drawCallCount = 0; + uint32_t triangleCount = 0; }; } // namespace FarmEngine diff --git a/FarmEngine/renderer/passes/RenderPasses.h b/FarmEngine/renderer/passes/RenderPasses.h index afd4cf5..41972d5 100644 --- a/FarmEngine/renderer/passes/RenderPasses.h +++ b/FarmEngine/renderer/passes/RenderPasses.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include namespace FarmEngine { diff --git a/FarmEngine/tools/inspector/Inspector.h b/FarmEngine/tools/inspector/Inspector.h index 6ca78df..2d4aa39 100644 --- a/FarmEngine/tools/inspector/Inspector.h +++ b/FarmEngine/tools/inspector/Inspector.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include namespace FarmEngine {