diff --git a/src/entity/components/camera-component.cpp b/src/entity/components/camera-component.cpp new file mode 100644 index 0000000..2f4f81f --- /dev/null +++ b/src/entity/components/camera-component.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#include "camera-component.hpp" + +ComponentBase* CameraComponent::clone() const +{ + CameraComponent* component = new CameraComponent(); + component->camera = camera; + + return component; +} + diff --git a/src/entity/components/camera-component.hpp b/src/entity/components/camera-component.hpp new file mode 100644 index 0000000..de2f60e --- /dev/null +++ b/src/entity/components/camera-component.hpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#ifndef CAMERA_COMPONENT_HPP +#define CAMERA_COMPONENT_HPP + +#include "../component.hpp" +#include "component-type.hpp" + +#include +using namespace Emergent; + +class CameraComponent: public Component +{ +public: + virtual ComponentBase* clone() const; + + Camera camera; +}; + +#endif // CAMERA_COMPONENT_HPP + diff --git a/src/entity/components/component-type.hpp b/src/entity/components/component-type.hpp index 9c03646..910659d 100644 --- a/src/entity/components/component-type.hpp +++ b/src/entity/components/component-type.hpp @@ -25,6 +25,7 @@ enum class ComponentType ANIMATION, ANT_HILL, BEHAVIOR, + CAMERA, COLLISION, LEGGED_LOCOMOTION, MODEL, diff --git a/src/entity/systems/camera-system.cpp b/src/entity/systems/camera-system.cpp new file mode 100644 index 0000000..adae601 --- /dev/null +++ b/src/entity/systems/camera-system.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#include "camera-system.hpp" + +CameraSystem::CameraSystem(ComponentManager* componentManager): + System(componentManager), + cameraGroup(componentManager) +{ + cameraGroup.addGroupObserver(this); +} + +CameraSystem::~CameraSystem() +{} + +void CameraSystem::update(float t, float dt) +{ + auto members = cameraGroup.getMembers(); + for (const CameraGroup::Member* member: *members) + { + CameraComponent* camera = std::get<0>(member->components); + TransformComponent* transform = std::get<1>(member->components); + } +} + +void CameraSystem::memberRegistered(const CameraGroup::Member* member) +{} + +void CameraSystem::memberUnregistered(const CameraGroup::Member* member) +{} + +void CameraSystem::handleEvent(const MouseMovedEvent& event) +{} + diff --git a/src/entity/systems/camera-system.hpp b/src/entity/systems/camera-system.hpp new file mode 100644 index 0000000..8f0388d --- /dev/null +++ b/src/entity/systems/camera-system.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#ifndef CAMERA_SYSTEM_HPP +#define CAMERA_SYSTEM_HPP + +#include "../entity-group.hpp" +#include "../components/camera-component.hpp" +#include "../components/model-component.hpp" +#include "../components/transform-component.hpp" +#include "../system.hpp" + +#include +using namespace Emergent; + +typedef EntityGroup CameraGroup; + +class CameraSystem: + public System, + public CameraGroup::Observer, + public EventHandler +{ +public: + CameraSystem(ComponentManager* componentManager); + virtual ~CameraSystem(); + + virtual void update(float t, float dt); + +private: + virtual void memberRegistered(const CameraGroup::Member* member); + virtual void memberUnregistered(const CameraGroup::Member* member); + virtual void handleEvent(const MouseMovedEvent& event); + CameraGroup cameraGroup; +}; + +#endif // CAMERA_SYSTEM_HPP + diff --git a/src/entity/systems/render-system.cpp b/src/entity/systems/render-system.cpp index 86416f5..a5a2fc1 100644 --- a/src/entity/systems/render-system.cpp +++ b/src/entity/systems/render-system.cpp @@ -21,10 +21,12 @@ RenderSystem::RenderSystem(ComponentManager* componentManager, SceneLayer* scene): System(componentManager), - modelEntityGroup(componentManager), + cameraGroup(componentManager), + modelGroup(componentManager), scene(scene) { - modelEntityGroup.addGroupObserver(this); + cameraGroup.addGroupObserver(this); + modelGroup.addGroupObserver(this); } RenderSystem::~RenderSystem() @@ -32,8 +34,17 @@ RenderSystem::~RenderSystem() void RenderSystem::update(float t, float dt) { - auto members = modelEntityGroup.getMembers(); - for (const ModelEntityGroup::Member* member: *members) + // Update transform of all cameras + for (const CameraGroup::Member* member: *cameraGroup.getMembers()) + { + CameraComponent* camera = std::get<0>(member->components); + TransformComponent* transform = std::get<1>(member->components); + + camera->camera.setTransform(transform->transform); + } + + // Update transform of all model instances + for (const ModelGroup::Member* member: *modelGroup.getMembers()) { ModelComponent* model = std::get<0>(member->components); TransformComponent* transform = std::get<1>(member->components); @@ -42,13 +53,25 @@ void RenderSystem::update(float t, float dt) } } -void RenderSystem::memberRegistered(const ModelEntityGroup::Member* member) +void RenderSystem::memberRegistered(const CameraGroup::Member* member) +{ + CameraComponent* camera = std::get<0>(member->components); + scene->addObject(&camera->camera); +} + +void RenderSystem::memberUnregistered(const CameraGroup::Member* member) +{ + CameraComponent* camera = std::get<0>(member->components); + scene->removeObject(&camera->camera); +} + +void RenderSystem::memberRegistered(const ModelGroup::Member* member) { ModelComponent* model = std::get<0>(member->components); scene->addObject(&model->model); } -void RenderSystem::memberUnregistered(const ModelEntityGroup::Member* member) +void RenderSystem::memberUnregistered(const ModelGroup::Member* member) { ModelComponent* model = std::get<0>(member->components); scene->removeObject(&model->model); diff --git a/src/entity/systems/render-system.hpp b/src/entity/systems/render-system.hpp index 444ad3f..0bb24eb 100644 --- a/src/entity/systems/render-system.hpp +++ b/src/entity/systems/render-system.hpp @@ -20,6 +20,7 @@ #ifndef RENDER_SYSTEM_HPP #define RENDER_SYSTEM_HPP +#include "../components/camera-component.hpp" #include "../components/model-component.hpp" #include "../components/transform-component.hpp" #include "../entity-group.hpp" @@ -28,14 +29,16 @@ #include using namespace Emergent; -typedef EntityGroup ModelEntityGroup; +typedef EntityGroup CameraGroup; +typedef EntityGroup ModelGroup; /** * Abstract base class for entity systems. */ -class RenderSystem: public - System, - ModelEntityGroup::Observer +class RenderSystem: + public System, + public CameraGroup::Observer, + public ModelGroup::Observer { public: RenderSystem(ComponentManager* componentManager, SceneLayer* scene); @@ -44,11 +47,14 @@ public: virtual void update(float t, float dt); private: - ModelEntityGroup modelEntityGroup; + CameraGroup cameraGroup; + ModelGroup modelGroup; SceneLayer* scene; - virtual void memberRegistered(const ModelEntityGroup::Member* member); - virtual void memberUnregistered(const ModelEntityGroup::Member* member); + virtual void memberRegistered(const CameraGroup::Member* member); + virtual void memberUnregistered(const CameraGroup::Member* member); + virtual void memberRegistered(const ModelGroup::Member* member); + virtual void memberUnregistered(const ModelGroup::Member* member); }; #endif // RENDER_SYSTEM_HPP diff --git a/src/entity/systems/tool-system.cpp b/src/entity/systems/tool-system.cpp index 91311ea..9a28b3b 100644 --- a/src/entity/systems/tool-system.cpp +++ b/src/entity/systems/tool-system.cpp @@ -21,10 +21,10 @@ ToolSystem::ToolSystem(ComponentManager* componentManager): System(componentManager), - tools(componentManager), + toolGroup(componentManager), picked(false) { - tools.addGroupObserver(this); + toolGroup.addGroupObserver(this); } ToolSystem::~ToolSystem() @@ -34,7 +34,7 @@ void ToolSystem::update(float t, float dt) { pick(); - auto members = tools.getMembers(); + auto members = toolGroup.getMembers(); for (const ToolGroup::Member* member: *members) { ModelComponent* model = std::get<0>(member->components); @@ -83,7 +83,6 @@ void ToolSystem::pick() void ToolSystem::memberRegistered(const ToolGroup::Member* member) { ToolComponent* tool = std::get<1>(member->components); - tool->active = false; } void ToolSystem::memberUnregistered(const ToolGroup::Member* member) diff --git a/src/entity/systems/tool-system.hpp b/src/entity/systems/tool-system.hpp index 1b9e214..0adc9b5 100644 --- a/src/entity/systems/tool-system.hpp +++ b/src/entity/systems/tool-system.hpp @@ -31,9 +31,6 @@ using namespace Emergent; typedef EntityGroup ToolGroup; -/** - * Abstract base class for entity systems. - */ class ToolSystem: public System, public ToolGroup::Observer, @@ -59,7 +56,7 @@ private: const Camera* pickingCamera; Vector4 pickingViewport; bool picked; - ToolGroup tools; + ToolGroup toolGroup; }; #endif // TOOL_SYSTEM_HPP diff --git a/src/game.cpp b/src/game.cpp index b7541f2..dbbc274 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -18,6 +18,7 @@ */ #include "game.hpp" +#include "resources/csv-table.hpp" #include "states/game-state.hpp" #include "states/splash-state.hpp" #include "states/sandbox-state.hpp" @@ -45,6 +46,7 @@ #include "entity/systems/sound-system.hpp" #include "entity/systems/collision-system.hpp" #include "entity/systems/render-system.hpp" +#include "entity/systems/camera-system.hpp" #include "entity/systems/tool-system.hpp" #include "entity/systems/locomotion-system.hpp" #include "entity/systems/behavior-system.hpp" @@ -243,145 +245,30 @@ void Game::setup() // Load settings loadSettings(); - // Load strings - loadStrings(); - - // Determine number of available languages - languageCount = (*stringTable)[0].size() - 1; - - // Match language code with language index - languageIndex = 0; - CSVRow* languageCodes = &(*stringTable)[0]; - for (std::size_t i = 1; i < languageCodes->size(); ++i) - { - if (language == (*languageCodes)[i]) - { - languageIndex = i - 1; - break; - } - } + // Setup localization (load strings, select language, ...) + setupLocalization(); - // Get display resolution - const Display* display = deviceManager->getDisplays()->front(); - int displayWidth = std::get<0>(display->getDimensions()); - int displayHeight = std::get<1>(display->getDimensions()); + setupWindow(); - if (fullscreen) - { - w = static_cast(fullscreenResolution.x); - h = static_cast(fullscreenResolution.y); - } - else - { - w = static_cast(windowedResolution.x); - h = static_cast(windowedResolution.y); - } + setupGraphics(); - // Determine window position - int x = std::get<0>(display->getPosition()) + displayWidth / 2 - w / 2; - int y = std::get<1>(display->getPosition()) + displayHeight / 2 - h / 2; + setupUI(); - // Read title string - std::string title = getString(getLanguageIndex(), "title"); + setupControls(); - // Create window - window = windowManager->createWindow(title.c_str(), x, y, w, h, fullscreen, WindowFlag::RESIZABLE); - if (!window) - { - throw std::runtime_error("Game::Game(): Failed to create window."); - } + setupGameplay(); - // Set v-sync mode - window->setVSync(vsync); + setupDebugging(); - // Setup step scheduler - double maxFrameDuration = 0.25; - double stepFrequency = 60.0; - stepScheduler.setMaxFrameDuration(maxFrameDuration); - stepScheduler.setStepFrequency(stepFrequency); - timestep = stepScheduler.getStepPeriod(); - // Setup performance sampling - performanceSampler.setSampleSize(15); - // Get DPI and convert font size to pixels - dpi = display->getDPI(); - fontSizePX = fontSizePT * (1.0f / 72.0f) * dpi; - // Setup control profile - keyboard = deviceManager->getKeyboards()->front(); - mouse = deviceManager->getMice()->front(); - closeControl.bindKey(keyboard, Scancode::ESCAPE); - closeControl.setActivatedCallback(std::bind(&Application::close, this, EXIT_SUCCESS)); - fullscreenControl.bindKey(keyboard, Scancode::F11); - fullscreenControl.setActivatedCallback(std::bind(&Game::toggleFullscreen, this)); - openRadialMenuControl.bindKey(keyboard, Scancode::LSHIFT); - moveForwardControl.bindKey(keyboard, Scancode::W); - moveBackControl.bindKey(keyboard, Scancode::S); - moveLeftControl.bindKey(keyboard, Scancode::A); - moveRightControl.bindKey(keyboard, Scancode::D); - //rotateCCWControl.bindKey(keyboard, Scancode::Q); - //rotateCWControl.bindKey(keyboard, Scancode::E); - moveRightControl.bindKey(keyboard, Scancode::D); - zoomInControl.bindKey(keyboard, Scancode::EQUALS); - zoomInControl.bindMouseWheelAxis(mouse, MouseWheelAxis::POSITIVE_Y); - zoomOutControl.bindKey(keyboard, Scancode::MINUS); - zoomOutControl.bindMouseWheelAxis(mouse, MouseWheelAxis::NEGATIVE_Y); - adjustCameraControl.bindMouseButton(mouse, 2); - dragCameraControl.bindMouseButton(mouse, 3); - toggleNestViewControl.bindKey(keyboard, Scancode::N); - toggleWireframeControl.bindKey(keyboard, Scancode::V); - screenshotControl.bindKey(keyboard, Scancode::F12); - toggleEditModeControl.bindKey(keyboard, Scancode::TAB); - controlProfile.registerControl("close", &closeControl); - controlProfile.registerControl("fullscreen", &fullscreenControl); - controlProfile.registerControl("open-radial-menu", &openRadialMenuControl); - controlProfile.registerControl("move-forward", &moveForwardControl); - controlProfile.registerControl("move-back", &moveBackControl); - controlProfile.registerControl("move-left", &moveLeftControl); - controlProfile.registerControl("move-right", &moveRightControl); - controlProfile.registerControl("rotate-ccw", &rotateCCWControl); - controlProfile.registerControl("rotate-cw", &rotateCWControl); - controlProfile.registerControl("zoom-in", &zoomInControl); - controlProfile.registerControl("zoom-out", &zoomOutControl); - controlProfile.registerControl("adjust-camera", &adjustCameraControl); - controlProfile.registerControl("drag-camera", &dragCameraControl); - controlProfile.registerControl("toggle-nest-view", &toggleNestViewControl); - controlProfile.registerControl("toggle-wireframe", &toggleWireframeControl); - controlProfile.registerControl("screenshot", &screenshotControl); - controlProfile.registerControl("toggle-edit-mode", &toggleEditModeControl); - // Save default control bindings - std::string bindingsPath = getConfigPath() + "/bindings/"; - if (!pathExists(bindingsPath)) - { - createDirectory(bindingsPath); - } - controlProfile.save(bindingsPath + "default.csv"); - - // Load control bindings - std::string controlProfileFilename = getConfigPath() + "/bindings/" + controlProfileName + ".csv"; - controlProfile.load(controlProfileFilename, deviceManager); - - wireframe = false; - toggleWireframeControl.setActivatedCallback(std::bind(&Game::toggleWireframe, this)); - screenshotControl.setActivatedCallback(std::bind(&Game::queueScreenshot, this)); screenshotQueued = false; // Create scene scene = new Scene(&stepInterpolator); - TestEvent event1, event2, event3; - event1.id = 1; - event2.id = 2; - event3.id = 3; - - - eventDispatcher.subscribe(this); - eventDispatcher.schedule(event1, 1.0); - eventDispatcher.schedule(event2, 10.0); - eventDispatcher.schedule(event3, 1.0); - // Load model resources try { @@ -471,27 +358,6 @@ void Game::setup() Shader* shader = resourceManager->load("depth-pass.glsl"); - /* - VertexFormat format; - format.addAttribute(0); - format.addAttribute(1); - format.addAttribute(2); - - VertexBuffer* vb = graphicsContext->createVertexBuffer(format); - vb->resize(1000); - vb->setData(bla, 0, 1000); - - IndexBuffer* ib = graphicsContext->createIndexBuffer(); - ib->resize(300); - ib->setData(bla, 0, 300); - - graphicsContext->bind(framebuffer); - graphicsContext->bind(shader); - graphicsContext->bind(vb); - graphicsContext->bind(ib); - graphicsContext->draw(100, TRIANGLES); - */ - cameraRig = nullptr; orbitCam = new OrbitCam(); orbitCam->attachCamera(&camera); @@ -780,71 +646,7 @@ void Game::setup() antLabelPinHole->setTexture(hudSpriteSheetTexture); antLabelPinHole->setTextureBounds(normalizeTextureBounds(hudTextureAtlas.getBounds("label-pin-hole"), hudTextureAtlasBounds)); antLabelContainer->addChild(antLabelPinHole); - - notificationBoxImage = new UIImage(); - notificationBoxImage->setTexture(hudSpriteSheetTexture); - notificationBoxImage->setTextureBounds(normalizeTextureBounds(hudTextureAtlas.getBounds("notification-box"), hudTextureAtlasBounds)); - notificationBoxImage->setVisible(false); - hudContainer->addChild(notificationBoxImage); - - // Construct show notification animation clip - notificationCount = 0; - AnimationChannel* channel2; - showNotificationClip.setInterpolator(easeOutQuint); - channel2 = showNotificationClip.addChannel(0); - channel2->insertKeyframe(0.0f, Vector2(0.0f, 0.0f)); - channel2->insertKeyframe(0.5f, Vector2(32.0f, 1.0f)); - showNotificationAnimation.setClip(&showNotificationClip); - showNotificationAnimation.setSpeed(1.0f); - showNotificationAnimation.setTimeFrame(showNotificationClip.getTimeFrame()); - animator.addAnimation(&showNotificationAnimation); - - showNotificationAnimation.setAnimateCallback - ( - [this](std::size_t id, const Vector2& values) - { - notificationBoxImage->setVisible(true); - notificationBoxImage->setTintColor(Vector4(Vector3(1.0f), values.y)); - //notificationBoxImage->setTranslation(Vector2(0.0f, -32.0f + values.x)); - } - ); - showNotificationAnimation.setEndCallback - ( - [this]() - { - hideNotificationAnimation.rewind(); - hideNotificationAnimation.play(); - } - ); - - // Construct hide notification animation clip - hideNotificationClip.setInterpolator(easeOutQuint); - AnimationChannel* channel; - channel = hideNotificationClip.addChannel(0); - channel->insertKeyframe(0.0f, 1.0f); - channel->insertKeyframe(10.5f, 1.0f); - channel->insertKeyframe(12.0f, 0.0f); - hideNotificationAnimation.setClip(&hideNotificationClip); - hideNotificationAnimation.setSpeed(1.0f); - hideNotificationAnimation.setTimeFrame(hideNotificationClip.getTimeFrame()); - animator.addAnimation(&hideNotificationAnimation); - hideNotificationAnimation.setAnimateCallback - ( - [this](std::size_t id, float opacity) - { - notificationBoxImage->setTintColor(Vector4(Vector3(1.0f), opacity)); - } - ); - hideNotificationAnimation.setEndCallback - ( - [this]() - { - notificationBoxImage->setVisible(false); - --notificationCount; - popNotification(); - } - ); - + // Construct box selection boxSelectionImageBackground = new UIImage(); boxSelectionImageBackground->setAnchor(Anchor::CENTER); @@ -911,6 +713,7 @@ void Game::setup() // Construct fade-in animation clip fadeInClip.setInterpolator(easeOutCubic); + AnimationChannel* channel; channel = fadeInClip.addChannel(0); channel->insertKeyframe(0.0f, 1.0f); channel->insertKeyframe(1.0f, 0.0f); @@ -1004,10 +807,6 @@ void Game::setup() ); animator.addAnimation(&cameraFlashAnimation); - // Setup default compositor - { - defaultCompositor.load(nullptr); - } // Setup shadow map pass and compositor { @@ -1160,7 +959,6 @@ void Game::setup() brush->setOrbitCam(orbitCam); defaultLayer->addObject(brush->getModelInstance()); - glEnable(GL_MULTISAMPLE); // performanceSampler.setSampleSize(30); @@ -1174,6 +972,7 @@ void Game::setup() // Initialize systems soundSystem = new SoundSystem(componentManager); collisionSystem = new CollisionSystem(componentManager); + cameraSystem = new CameraSystem(componentManager); renderSystem = new RenderSystem(componentManager, defaultLayer); toolSystem = new ToolSystem(componentManager); toolSystem->setPickingCamera(&camera); @@ -1200,6 +999,7 @@ void Game::setup() systemManager->addSystem(collisionSystem); systemManager->addSystem(toolSystem); systemManager->addSystem(particleSystem); + systemManager->addSystem(cameraSystem); systemManager->addSystem(renderSystem); EntityID sidewalkPanel; @@ -1211,7 +1011,7 @@ void Game::setup() EntityID antNest = createInstanceOf("ant-nest"); setTranslation(antNest, Vector3(20, 0, 40)); - lollipop = createInstanceOf("lollipop"); + EntityID lollipop = createInstanceOf("lollipop"); setTranslation(lollipop, Vector3(30.0f, 3.5f * 0.5f, -30.0f)); setRotation(lollipop, glm::angleAxis(glm::radians(8.85f), Vector3(1.0f, 0.0f, 0.0f))); @@ -1260,10 +1060,6 @@ void Game::setup() changeState(splashState); } -void Game::input() -{ -} - void Game::update(float t, float dt) { this->time = t; @@ -1283,14 +1079,27 @@ void Game::update(float t, float dt) // Update animations animator.animate(dt); - std::stringstream stream; - stream.precision(2); - stream << std::fixed << (performanceSampler.getMeanFrameDuration() * 1000.0f); - fpsLabel->setText(stream.str()); + if (fpsLabel->isVisible()) + { + std::stringstream stream; + stream.precision(2); + stream << std::fixed << (performanceSampler.getMeanFrameDuration() * 1000.0f); + fpsLabel->setText(stream.str()); + } uiRootElement->update(); +} - controlProfile.update(); +void Game::input() +{ + /* + if (useToolControl.isActive() && !useToolControl.wasActive()) + { + intentSystem.queueIntent(Intent::USE_TOOL); + } + */ + + controls.update(); } void Game::render() @@ -1341,9 +1150,217 @@ void Game::handleEvent(const WindowResizedEvent& event) resizeUI(event.width, event.height); } -void Game::handleEvent(const TestEvent& event) +void Game::setupLocalization() { - std::cout << "Event received!!! ID: " << event.id << std::endl; + // Load strings + loadStrings(); + + // Determine number of available languages + languageCount = (*stringTable)[0].size() - 1; + + // Match language code with language index + languageIndex = 0; + CSVRow* languageCodes = &(*stringTable)[0]; + for (std::size_t i = 1; i < languageCodes->size(); ++i) + { + if (language == (*languageCodes)[i]) + { + languageIndex = i - 1; + break; + } + } +} + +void Game::setupWindow() +{ + // Get display resolution + const Display* display = deviceManager->getDisplays()->front(); + int displayWidth = std::get<0>(display->getDimensions()); + int displayHeight = std::get<1>(display->getDimensions()); + + if (fullscreen) + { + w = static_cast(fullscreenResolution.x); + h = static_cast(fullscreenResolution.y); + } + else + { + w = static_cast(windowedResolution.x); + h = static_cast(windowedResolution.y); + } + + // Determine window position + int x = std::get<0>(display->getPosition()) + displayWidth / 2 - w / 2; + int y = std::get<1>(display->getPosition()) + displayHeight / 2 - h / 2; + + // Read title string + std::string title = getString(getLanguageIndex(), "title"); + + // Create window + window = windowManager->createWindow(title.c_str(), x, y, w, h, fullscreen, WindowFlag::RESIZABLE); + if (!window) + { + throw std::runtime_error("Game::Game(): Failed to create window."); + } + + // Set v-sync mode + window->setVSync(vsync); +} + +void Game::setupGraphics() +{ + + glEnable(GL_MULTISAMPLE); +} + +void Game::setupUI() +{ + // Get DPI and convert font size to pixels + const Display* display = deviceManager->getDisplays()->front(); + dpi = display->getDPI(); + fontSizePX = fontSizePT * (1.0f / 72.0f) * dpi; +} + +void Game::setupControls() +{ + // Get keyboard and mouse + keyboard = deviceManager->getKeyboards()->front(); + mouse = deviceManager->getMice()->front(); + + // Build the master control set + controls.addControl(&toggleFullscreenControl); + controls.addControl(&screenshotControl); + controls.addControl(&exitControl); + controls.addControl(&menuUpControl); + controls.addControl(&menuDownControl); + controls.addControl(&menuLeftControl); + controls.addControl(&menuRightControl); + controls.addControl(&menuBackControl); + controls.addControl(&moveForwardControl); + controls.addControl(&moveBackControl); + controls.addControl(&moveLeftControl); + controls.addControl(&moveRightControl); + controls.addControl(&zoomInControl); + controls.addControl(&zoomOutControl); + controls.addControl(&orbitCCWControl); + controls.addControl(&orbitCWControl); + controls.addControl(&adjustCameraControl); + controls.addControl(&dragCameraControl); + controls.addControl(&openToolMenuControl); + controls.addControl(&useToolControl); + controls.addControl(&toggleEditModeControl); + controls.addControl(&toggleWireframeControl); + + // Build the system control set + systemControls.addControl(&exitControl); + systemControls.addControl(&toggleFullscreenControl); + systemControls.addControl(&screenshotControl); + + // Build the menu control set + menuControls.addControl(&menuUpControl); + menuControls.addControl(&menuDownControl); + menuControls.addControl(&menuLeftControl); + menuControls.addControl(&menuRightControl); + menuControls.addControl(&menuSelectControl); + menuControls.addControl(&menuBackControl); + + // Build the camera control set + cameraControls.addControl(&moveForwardControl); + cameraControls.addControl(&moveBackControl); + cameraControls.addControl(&moveLeftControl); + cameraControls.addControl(&moveRightControl); + cameraControls.addControl(&zoomInControl); + cameraControls.addControl(&zoomOutControl); + cameraControls.addControl(&orbitCCWControl); + cameraControls.addControl(&orbitCWControl); + cameraControls.addControl(&adjustCameraControl); + cameraControls.addControl(&dragCameraControl); + + // Build the tool control set + toolControls.addControl(&openToolMenuControl); + toolControls.addControl(&useToolControl); + + // Build the editor control set + editorControls.addControl(&toggleEditModeControl); + + // Setup control callbacks + exitControl.setActivatedCallback(std::bind(&Application::close, this, EXIT_SUCCESS)); + toggleFullscreenControl.setActivatedCallback(std::bind(&Game::toggleFullscreen, this)); + screenshotControl.setActivatedCallback(std::bind(&Game::queueScreenshot, this)); + toggleWireframeControl.setActivatedCallback(std::bind(&Game::toggleWireframe, this)); + + // Map controls + inputMapper->map(&exitControl, keyboard, Scancode::ESCAPE); + inputMapper->map(&toggleFullscreenControl, keyboard, Scancode::F11); + inputMapper->map(&screenshotControl, keyboard, Scancode::F12); + inputMapper->map(&openToolMenuControl, keyboard, Scancode::LSHIFT); + inputMapper->map(&moveForwardControl, keyboard, Scancode::W); + inputMapper->map(&moveBackControl, keyboard, Scancode::S); + inputMapper->map(&moveLeftControl, keyboard, Scancode::A); + inputMapper->map(&moveRightControl, keyboard, Scancode::D); + inputMapper->map(&orbitCCWControl, keyboard, Scancode::Q); + inputMapper->map(&orbitCWControl, keyboard, Scancode::E); + inputMapper->map(&zoomInControl, mouse, MouseWheelAxis::POSITIVE_Y); + inputMapper->map(&zoomInControl, keyboard, Scancode::EQUALS); + inputMapper->map(&zoomOutControl, mouse, MouseWheelAxis::NEGATIVE_Y); + inputMapper->map(&zoomOutControl, keyboard, Scancode::MINUS); + inputMapper->map(&adjustCameraControl, mouse, 2); + inputMapper->map(&dragCameraControl, mouse, 3); + inputMapper->map(&toggleWireframeControl, keyboard, Scancode::V); + inputMapper->map(&toggleEditModeControl, keyboard, Scancode::TAB); + + /* + controlProfile.registerControl("exit", &exitControl); + controlProfile.registerControl("toggle-fullscreen", &toggleFullscreenControl); + controlProfile.registerControl("open-tool-menu", &openToolMenuControl); + controlProfile.registerControl("move-forward", &moveForwardControl); + controlProfile.registerControl("move-back", &moveBackControl); + controlProfile.registerControl("move-left", &moveLeftControl); + controlProfile.registerControl("move-right", &moveRightControl); + controlProfile.registerControl("orbit-ccw", &orbitCCWControl); + controlProfile.registerControl("orbit-cw", &orbitCWControl); + controlProfile.registerControl("zoom-in", &zoomInControl); + controlProfile.registerControl("zoom-out", &zoomOutControl); + controlProfile.registerControl("adjust-camera", &adjustCameraControl); + controlProfile.registerControl("drag-camera", &dragCameraControl); + controlProfile.registerControl("toggle-wireframe", &toggleWireframeControl); + controlProfile.registerControl("screenshot", &screenshotControl); + controlProfile.registerControl("toggle-edit-mode", &toggleEditModeControl); + */ + + /* + // Save default control bindings + std::string bindingsPath = getConfigPath() + "/bindings/"; + if (!pathExists(bindingsPath)) + { + createDirectory(bindingsPath); + } + controlProfile.save(bindingsPath + "default.csv"); + + // Load control bindings + std::string controlProfileFilename = getConfigPath() + "/bindings/" + controlProfileName + ".csv"; + controlProfile.load(controlProfileFilename, deviceManager); + */ + +} + +void Game::setupGameplay() +{ + // Setup step scheduler + double maxFrameDuration = 0.25; + double stepFrequency = 60.0; + stepScheduler.setMaxFrameDuration(maxFrameDuration); + stepScheduler.setStepFrequency(stepFrequency); + timestep = stepScheduler.getStepPeriod(); +} + +void Game::setupDebugging() +{ + // Setup performance sampling + performanceSampler.setSampleSize(15); + + // Disable wireframe drawing + wireframe = false; } void Game::resetSettings() @@ -1580,10 +1597,6 @@ void Game::resizeUI(int w, int h) antTag->setAnchor(Anchor::CENTER); antTag->setDimensions(Vector2(antLabelContainer->getDimensions().x, antPin->getDimensions().y)); - Rect notificationBoxBounds = hudTextureAtlas.getBounds("notification-box"); - notificationBoxImage->setDimensions(Vector2(notificationBoxBounds.getWidth(), notificationBoxBounds.getHeight())); - notificationBoxImage->setAnchor(Vector2(0.5f, 0.0f)); - float cameraGridLineWidth = 2.0f; float cameraReticleDiameter = 6.0f; cameraGridContainer->setDimensions(Vector2(w, h)); @@ -1820,10 +1833,6 @@ void Game::selectTool(int toolIndex) { currentTool->setActive(true); } - else - { - pushNotification("Invalid tool."); - } } if (1) @@ -1837,24 +1846,9 @@ void Game::selectTool(int toolIndex) } } -void Game::pushNotification(const std::string& text) -{ - std::cout << text << std::endl; - ++notificationCount; - - if (notificationCount == 1) - { - popNotification(); - } -} - -void Game::popNotification() +EntityID Game::createInstance() { - if (notificationCount > 0) - { - showNotificationAnimation.rewind(); - showNotificationAnimation.play(); - } + return entityManager->createEntity(); } EntityID Game::createInstanceOf(const std::string& templateName) @@ -1873,6 +1867,17 @@ void Game::destroyInstance(EntityID entity) entityManager->destroyEntity(entity); } +void Game::addComponent(EntityID entity, ComponentBase* component) +{ + componentManager->addComponent(entity, component); +} + +void Game::removeComponent(EntityID entity, ComponentType type) +{ + ComponentBase* component = componentManager->removeComponent(entity, type); + delete component; +} + void Game::setTranslation(EntityID entity, const Vector3& translation) { TransformComponent* component = static_cast(componentManager->getComponent(entity, ComponentType::TRANSFORM)); diff --git a/src/game.hpp b/src/game.hpp index f6c7460..b987ac3 100644 --- a/src/game.hpp +++ b/src/game.hpp @@ -24,7 +24,6 @@ using namespace Emergent; #include "entity/entity-id.hpp" -#include "resources/csv-table.hpp" #include #include #include @@ -44,7 +43,6 @@ class LightingRenderPass; class SilhouetteRenderPass; class FinalRenderPass; class ResourceManager; -typedef std::vector> CSVTable; class CameraRig; class OrbitCam; class FreeCam; @@ -59,28 +57,17 @@ class SystemManager; class SoundSystem; class CollisionSystem; class RenderSystem; +class CameraSystem; class ToolSystem; class BehaviorSystem; class SteeringSystem; class LocomotionSystem; - -class TestEvent: public Event -{ - public: - inline EventBase* clone() const - { - TestEvent* event = new TestEvent(); - event->id = id; - return event; - } - - int id; -}; - +class ComponentBase; +enum class ComponentType; +typedef std::vector> CSVTable; class Game: - public Application, - public EventHandler + public Application { public: /** @@ -136,8 +123,6 @@ public: void fadeOut(float duration, const Vector3& color, std::function callback); void selectTool(int toolIndex); - void pushNotification(const std::string& text); - void popNotification(); private: virtual void setup(); @@ -146,7 +131,14 @@ private: virtual void render(); virtual void exit(); virtual void handleEvent(const WindowResizedEvent& event); - virtual void handleEvent(const TestEvent& event); + + void setupLocalization(); + void setupWindow(); + void setupGraphics(); + void setupUI(); + void setupControls(); + void setupGameplay(); + void setupDebugging(); void resetSettings(); void loadSettings(); @@ -164,8 +156,11 @@ private: public: + EntityID createInstance(); EntityID createInstanceOf(const std::string& templateName); void destroyInstance(EntityID entity); + void addComponent(EntityID entity, ComponentBase* component); + void removeComponent(EntityID entity, ComponentType type); void setTranslation(EntityID entity, const Vector3& translation); void setRotation(EntityID entity, const Quaternion& rotation); void setScale(EntityID entity, const Vector3& scale); @@ -205,25 +200,51 @@ public: // Input Mouse* mouse; Keyboard* keyboard; - ControlProfile controlProfile; - Control fullscreenControl; - Control closeControl; - Control openRadialMenuControl; + + // Master control set + ControlSet controls; + + // System control set + ControlSet systemControls; + Control exitControl; + Control toggleFullscreenControl; + Control screenshotControl; + + // Menu control set + ControlSet menuControls; + Control menuUpControl; + Control menuDownControl; + Control menuLeftControl; + Control menuRightControl; + Control menuSelectControl; + Control menuBackControl; + + // Camera control set + ControlSet cameraControls; Control moveForwardControl; Control moveBackControl; Control moveLeftControl; Control moveRightControl; - Control rotateCCWControl; - Control rotateCWControl; Control zoomInControl; Control zoomOutControl; + Control orbitCCWControl; + Control orbitCWControl; Control adjustCameraControl; Control dragCameraControl; - Control toggleNestViewControl; - Control toggleWireframeControl; - Control screenshotControl; + + // Tool control set + ControlSet toolControls; + Control openToolMenuControl; + Control useToolControl; + + // Editor control set + ControlSet editorControls; Control toggleEditModeControl; + // Debug control set + ControlSet debugControls; + Control toggleWireframeControl; + // Logic float time; float timestep; @@ -261,8 +282,6 @@ public: UIImage* radialMenuSelectorImage; UIImage* blackoutImage; UIImage* cameraFlashImage; - UIImage* notificationBoxImage; - int notificationCount; UIContainer* antTag; UIContainer* antLabelContainer; UILabel* fpsLabel; @@ -334,10 +353,6 @@ public: AnimationClip fadeOutClip; std::function fadeInEndCallback; std::function fadeOutEndCallback; - Animation showNotificationAnimation; - Animation hideNotificationAnimation; - AnimationClip showNotificationClip; - AnimationClip hideNotificationClip; Animation cameraFlashAnimation; AnimationClip cameraFlashClip; @@ -367,14 +382,13 @@ public: SystemManager* systemManager; SoundSystem* soundSystem; CollisionSystem* collisionSystem; + CameraSystem* cameraSystem; RenderSystem* renderSystem; ToolSystem* toolSystem; BehaviorSystem* behaviorSystem; SteeringSystem* steeringSystem; LocomotionSystem* locomotionSystem; - EntityID lollipop; - bool screenshotQueued; // Settings diff --git a/src/states/sandbox-state.cpp b/src/states/sandbox-state.cpp index d253477..bd86812 100755 --- a/src/states/sandbox-state.cpp +++ b/src/states/sandbox-state.cpp @@ -86,7 +86,7 @@ void SandboxState::execute() game->lightingPass->setTime(game->time); bool menuClosed = false; - if (game->openRadialMenuControl.isActive() && !game->openRadialMenuControl.wasActive()) + if (game->openToolMenuControl.isActive() && !game->openToolMenuControl.wasActive()) { game->radialMenuContainer->setVisible(true); game->hudContainer->setVisible(false); @@ -95,7 +95,7 @@ void SandboxState::execute() selectorVector = Vector2(0.0f); game->mouse->setRelativeMode(true); } - else if (!game->openRadialMenuControl.isActive() && game->openRadialMenuControl.wasActive()) + else if (!game->openToolMenuControl.isActive() && game->openToolMenuControl.wasActive()) { game->radialMenuContainer->setVisible(false); //game->hudContainer->setVisible(true); @@ -132,11 +132,11 @@ void SandboxState::execute() } float rotationAngle = glm::radians(180.0f) * game->timestep; - if (game->rotateCCWControl.isActive()) + if (game->orbitCCWControl.isActive()) { game->orbitCam->rotate(-rotationAngle); } - if (game->rotateCWControl.isActive()) + if (game->orbitCWControl.isActive()) { game->orbitCam->rotate(rotationAngle); } @@ -311,11 +311,6 @@ void SandboxState::execute() game->mouse->warp(game->window, game->w / 2, game->h / 2); noPick = false; } - - if (game->toggleNestViewControl.isActive() && !game->toggleNestViewControl.wasActive()) - { - game->fadeOut(0.5f, Vector3(0.0f), std::bind(&Game::fadeIn, game, 0.5f, Vector3(0.0f), nullptr)); - } } void SandboxState::exit()