Something went wrong on our end
Select Git revision
-
Sebastian Freitag authoredSebastian Freitag authored
engine.hpp 6.12 KiB
//------------------------------------------------------------------------------
// Project Phoenix
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualization Group.
//------------------------------------------------------------------------------
// License
//
// Licensed under the 3-Clause BSD License (the "License");
// you may not use this file except in compliance with the License.
// See the file LICENSE for the full text.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//------------------------------------------------------------------------------
#ifndef LIBRARY_PHX_ENGINE_HPP_
#define LIBRARY_PHX_ENGINE_HPP_
#include <algorithm>
#include <chrono>
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include "phx/suppress_warnings.hpp"
SUPPRESS_WARNINGS_BEGIN
#define BOOST_BIND_NO_PLACEHOLDERS
#include "boost/signals2/connection.hpp"
#include "boost/signals2/signal.hpp"
SUPPRESS_WARNINGS_END
#include "phx/behavior.hpp"
#include "phx/export.hpp"
#include "phx/frame_timer.hpp"
#include "phx/loggable.hpp"
#include "phx/scene.hpp"
#include "phx/system.hpp"
namespace phx {
SUPPRESS_WARNINGS_BEGIN_PADDED
class PHOENIX_EXPORT Engine final : public Loggable {
public:
Engine();
Engine(const Engine&) = delete;
Engine(Engine&&) = default;
~Engine();
Engine& operator=(const Engine&) = delete;
Engine& operator=(Engine&&) = default;
template <typename SystemType, typename... SystemArguments>
SystemType* CreateSystem(SystemArguments&&... arguments) {
static_assert(std::is_base_of<System, SystemType>::value,
"The type does not inherit from System.");
auto system =
std::unique_ptr<SystemType>(new SystemType(this, arguments...));
systems_.push_back(std::move(system));
return static_cast<SystemType*>(systems_.back().get());
}
template <typename SystemType>
SystemType* GetSystem() {
static_assert(std::is_base_of<System, SystemType>::value,
"The type does not inherit from System.");
auto iterator = std::find_if(systems_.begin(), systems_.end(),
SystemMatchPredicate<SystemType>);
return iterator != systems_.end()
? static_cast<SystemType*>(iterator->get())
: nullptr;
}
template <typename SystemType>
std::vector<SystemType*> GetSystems() {
static_assert(std::is_base_of<System, SystemType>::value,
"The type does not inherit from System.");
std::vector<SystemType*> systems;
for (const auto& system : systems_) {
if (SystemMatchPredicate<SystemType>(system)) {
systems.push_back(static_cast<SystemType*>(system.get()));
}
}
return systems;
}
template <typename SystemType>
void RemoveSystem() {
static_assert(std::is_base_of<System, SystemType>::value,
"The type does not inherit from System.");
systems_.erase(std::remove_if(systems_.begin(), systems_.end(),
SystemMatchPredicate<SystemType>),
systems_.end());
}
void Run();
void Stop();
std::string ToString() const override;
bool IsRunning() const;
void SetScene(std::shared_ptr<Scene> new_scene);
std::shared_ptr<Scene> GetScene() const;
// Parameters to the callback are: (old scene, new scene)
boost::signals2::connection AddSceneChangedCallback(
const std::function<void(std::shared_ptr<Scene>, std::shared_ptr<Scene>)>&
callback);
const FrameTimer& GetFrameTimer();
// Syntax sugar for scene access.
std::vector<Entity*> GetEntities() const;
template <typename... Components>
std::vector<Entity*> GetEntitiesWithComponents() const;
template <typename Component>
std::vector<Component*> GetFirstComponents() const;
template <typename... Components>
std::vector<std::tuple<Components*...>> GetFirstComponentsMany() const;
// Update order
class UpdateOrder {
public:
explicit UpdateOrder(Engine* engine) : engine_(engine) {}
void MoveToFront(System* system) const;
void MoveToBack(System* system) const;
void MoveAfter(System* system, System* after) const;
void MoveBefore(System* system, System* before) const;
private:
std::vector<std::unique_ptr<System>>::iterator FindSystem(
System* system) const;
void MoveBeforeRelative(System* system, System* relative_to,
int distance) const;
Engine* engine_;
};
const UpdateOrder& GetUpdateOrder() const { return update_order_; }
private:
template <typename SystemType>
static bool SystemMatchPredicate(const std::unique_ptr<System>& iteratee) {
return (dynamic_cast<SystemType*>(iteratee.get()) != nullptr);
}
void UpdateSystems();
std::vector<std::unique_ptr<System>> systems_;
bool is_running_ = false;
std::shared_ptr<Scene> scene_;
boost::signals2::signal<void(std::shared_ptr<Scene>, std::shared_ptr<Scene>)>
scene_changed_signal_;
FrameTimer frame_timer_;
UpdateOrder update_order_ = UpdateOrder(this);
};
template <typename... Components>
std::vector<Entity*> Engine::GetEntitiesWithComponents() const {
if (!scene_) return std::vector<Entity*>();
return scene_->GetEntitiesWithComponents<Components...>();
}
template <typename Component>
std::vector<Component*> Engine::GetFirstComponents() const {
if (!scene_) return std::vector<Component*>();
return scene_->GetFirstComponents<Component>();
}
template <typename... Components>
std::vector<std::tuple<Components*...>> Engine::GetFirstComponentsMany() const {
if (!scene_) return std::vector<std::tuple<Components*...>>();
return scene_->GetFirstComponentsMany<Components...>();
}
SUPPRESS_WARNINGS_END
} // namespace phx
#endif // LIBRARY_PHX_ENGINE_HPP_