Commit 2fa06238 authored by Johannes Braun's avatar Johannes Braun
Browse files

Added some documentation.

parent c7e5ace7
......@@ -12,8 +12,6 @@ constexpr int bla()
int main()
{
anystuff.push_back(std::make_any<int>(10));
bool b = true;
}
\ No newline at end of file
......@@ -13,16 +13,46 @@ namespace glare::core
{
class AnimationManager;
/**
* \brief An animation structure you can set up and then add to the AnimationManager to play it.
*/
struct Animation
{
friend class AnimationManager;
/**
* \brief The Animation duration in seconds.
*/
double duration;
/**
* \brief The time the animation will wait before starting when adding it to the AnimationManager.
*/
double start_delay = 0;
std::function<void(double, double)> on_update;
/**
* \brief Will get called on each update.
*/
std::function<void(double time, double value)> on_update;
/**
* \brief Will get called after the start delay.
*/
std::function<void()> on_start;
/**
* \brief Will get called after the full Animation time.
*/
std::function<void()> on_finish;
/**
* \brief Will get called when removing the Animation prematurely from the AnimationManager
*/
std::function<void()> on_cancel;
/**
* \brief Can be used to transform the raw linear value to your desired output. (Examples: quadratic, root, bouncing etc.)
*/
std::function<double(double)> interpolator = [](double value) { return value; };
private:
......@@ -33,17 +63,32 @@ namespace glare::core
bool mark_finished = false;
};
/**
* \brief The AnimationManager is like an animation observer and updater. You can add an animation which will then immediately started.
* The update() call on each frame will then update the animation progress values.
*/
class AnimationManager
{
public:
AnimationManager();
~AnimationManager();
//-----------------------
/**
* \brief Add an animation to the animation queue. It will be started on the next update() call.
*/
size_t addAnimation(std::shared_ptr<Animation> animation);
size_t addAnimation(const Animation &animation);
/**
* \brief End and release the given animation from the animation queue.
*/
static void stopAnimation(std::shared_ptr<Animation> animation);
void stopAnimation(unsigned animation_id);
/**
* \brief Update all pending animations.
*/
void update();
private:
......
......@@ -5,6 +5,9 @@
namespace glare::core
{
/**
* \brief A container for the basic OpenAL stuff.
*/
class AudioContext
{
public:
......
......@@ -5,22 +5,36 @@
#include <util/audio.h>
namespace glare::core
{
namespace fs = std::experimental::filesystem;
/**
* \brief Represents an OpenAL based audio file storage. The contained sound can be played with a SoundSource.
*/
class SoundBuffer
{
namespace fs = std::experimental::filesystem;
public:
/**
* \brief Loads a .wav file from file system.
*/
explicit SoundBuffer(const fs::path &from_file);
class SoundBuffer
{
public:
SoundBuffer(const fs::path &from_file);
unsigned id() const;
/**
* \return The OpenAL buffer handle id.
*/
unsigned id() const;
static al::BufferFormat format(unsigned bits_per_sample, unsigned channels);
/**
* \brief Converts the input parameters to an equivalent buffer format.
*/
static al::BufferFormat format(unsigned bits_per_sample, unsigned channels);
private:
al::BufferFormat m_format;
al::handle::buffer m_handle;
audio::wave_data m_data;
};
}
private:
al::BufferFormat m_format;
al::handle::buffer m_handle;
audio::wave_data m_data;
};
}
#endif //INCLUDE_SOUND_BUFFER_H
......@@ -14,8 +14,7 @@ namespace glare::core
SoundSource::SoundSource(unsigned buffer)
: SoundSource()
{
m_buffer_id = buffer;
al::sourcei(m_source, al::SourceParam::eBuffer, m_buffer_id);
setBuffer(buffer);
}
void SoundSource::update()
......@@ -48,4 +47,20 @@ namespace glare::core
m_looping = looping;
al::sourcei(m_source, al::SourceParam::eLooping, m_looping);
}
bool SoundSource::isLooping() const
{
return m_looping;
}
void SoundSource::setBuffer(unsigned buffer)
{
m_buffer_id = buffer;
al::sourcei(m_source, al::SourceParam::eBuffer, m_buffer_id);
}
unsigned SoundSource::getBuffer() const
{
return m_buffer_id;
}
}
......@@ -6,11 +6,18 @@
namespace glare::core
{
/**
* \brief Can be attached to a scene graph to either play a sound locally or globally. Uses the id of a SoundBuffer to play sounds.
*/
class SoundSource : public GraphNodeComponent
{
public:
SoundSource();
SoundSource(unsigned buffer);
/**
* \brief Important for local sound sources: Updates the position and velocity of this sound source.
*/
void update() override;
void play() const;
......@@ -18,6 +25,9 @@ namespace glare::core
void stop() const;
void setLooping(bool looping);
bool isLooping() const;
void setBuffer(unsigned buffer);
unsigned getBuffer() const;
private:
al::handle::source m_source;
......
......@@ -12,6 +12,10 @@
namespace glare::core
{
/**
* \brief An objectified OpenGL buffer representation. Uses the bindless buffer approach from later OpenGL Versions (4.5+)
* \tparam TBuffer The OpenGL buffer type. May be any of those in gl::BufferType.
*/
template<gl::BufferType TBuffer>
class Buffer
{
......@@ -23,22 +27,57 @@ namespace glare::core
Buffer& operator=(Buffer&& other) = default;
~Buffer();
void bind() const;
/**
* \brief Binds the shader to a defined shader storage binding point retrieved from the shader program itself.
*/
void bind(unsigned point) const;
void unbind() const;
/**
* \return The buffer handle id
*/
unsigned id() const;
uint64_t residentAddress() const;
bool resident() const;
/**
* \return The gpu address of the bindless buffer (if made resident). Usually, it's better to just call makeResident(...) and retrieve it's value.
*/
uint64_t residentAddress() const;
/**
* \brief Makes the buffer resident only if it's not already. Returns the resulting gpu address.
*/
uint64_t makeResident(gl::Access access);
void makeNonResident() const;
bool resident() const;
/**
* \brief Uploads the data to the buffer.
* \tparam T The type of the uploaded data.
* \param count The the length of the T* data array. NOT the data size!
*/
template<typename T> void upload(size_t count, const T* data, gl::BufferUsage usage) const;
/**
* \brief Same as upload(size_t, const T*, gl::BufferUsage), but for std vectors.
*/
template<typename T> void upload(const std::vector<T>& data, gl::BufferUsage usage) const;
/**
* \brief Just reserves a needed amount of memory and does not upload any real data.
* \param count The number of elements to reserve. NOT the data size!
*/
template<typename T = uint8_t> void reserve(size_t count, gl::BufferUsage usage) const;
/**
* \brief Downloads the set amount of data off of the buffer and copies it to a std vector.
* \tparam T The type of the resulting data elements.
* \param count The number of elements to download.
* \param offset The first element index to download.
*/
template<typename T> std::vector<T> download(size_t count, size_t offset = 0) const;
/**
* \brief Downloads the data off of the buffer and creates a non-persistent data pointer to it which will be invalidated when calling unmap().
*/
template<typename TReturn = void> TReturn* map(size_t count, size_t offset, gl::BufferMapBit flags) const;
template<typename TReturn = void> TReturn* map(size_t count, gl::BufferMapBit flags) const;
void unmap() const;
......@@ -60,25 +99,12 @@ namespace glare::core
makeNonResident();
}
template<gl::BufferType TBuffer>
void Buffer<TBuffer>::bind() const
{
gl::bindBuffer(TBuffer, m_handle);
}
template<gl::BufferType TBuffer>
void Buffer<TBuffer>::bind(unsigned point) const
{
bind();
gl::bindBufferBase(TBuffer, point, m_handle);
}
template<gl::BufferType TBuffer>
void Buffer<TBuffer>::unbind() const
{
gl::bindBuffer(TBuffer, 0);
}
template<gl::BufferType TBuffer>
unsigned Buffer<TBuffer>::id() const
{
......@@ -102,7 +128,6 @@ namespace glare::core
{
if (!resident())
{
bind();
gl::makeNamedBufferResident(m_handle, access);
gl::getNamedBufferParameterui64v(m_handle, gl::GetNamedBufferParameters::eGPUAddress, &m_resident_address);
}
......
......@@ -14,15 +14,25 @@
namespace glare::core
{
/**
* \brief A frame buffer object wrapper for varying types of attachment textures.
* \tparam TTextureBase The base type of attachment textures. (Texture2D, Texture2DMultisample etc.)
*/
template<template<gl::TextureFormat, gl::TextureInternalFormat, gl::Type> typename TTextureBase>
class Framebuffer
{
public:
static constexpr bool is_multisampled = texture_color_type::is_multisampled;
// The type of texture used for color attachments
using texture_color_type = TTextureBase<gl::TextureFormat::eRGBA, gl::TextureInternalFormat::eRGBA32Float, gl::Type::eFloat>;
using texture_depth_type = TTextureBase<gl::TextureFormat::eDepthComponent, gl::TextureInternalFormat::eDepthComponent32Float, gl::Type::eFloat>;
static constexpr bool is_multisampled = texture_color_type::is_multisampled;
// The type of texture used for the depth attachment
using texture_depth_type = TTextureBase<gl::TextureFormat::eDepthComponent, gl::TextureInternalFormat::eDepthComponent32Float, gl::Type::eFloat>;
/**
* \param samples Only used when using a multisampled texture.
*/
Framebuffer(unsigned width, unsigned height, unsigned samples = 1);
Framebuffer(Framebuffer& other) = delete;
Framebuffer& operator=(Framebuffer& other) = delete;
......@@ -30,9 +40,20 @@ namespace glare::core
Framebuffer& operator=(Framebuffer&& other) = default;
~Framebuffer();
/**
* \brief Resizes all attachments to the new resolution.
* \param samples Only used when using a multisampled texture.
*/
void resize(unsigned width, unsigned height, unsigned samples);
/**
* \brief Set this framebuffer as active to receive rendered things.
*/
void activate() const;
/**
* \brief Set the default framebuffer as active.
*/
void deactivate() const;
void attach(gl::Attachment attachment);
......
......@@ -5,7 +5,7 @@
namespace glare::core
{
class OpenGLState : public Singleton<OpenGLState>
class OpenGLState : Singleton<OpenGLState>
{
public:
static void capture();
......
......@@ -34,21 +34,19 @@ namespace glare::core
class Program
{
public:
// generic, usable for pretty much all shader programs
explicit Program(const std::vector<std::shared_ptr<Shader>> &shaders);
// usable especially for compute shaders
explicit Program(std::shared_ptr<Shader> shader);
explicit Program(const fs::path& shader_file);
// again, usable for compute shaders.
void dispatch1d(unsigned global_x, unsigned local_x);
void dispatch2d(unsigned global_x, unsigned local_x, unsigned global_y, unsigned local_y);
void dispatch3d(unsigned global_x, unsigned local_x, unsigned global_y, unsigned local_y, unsigned global_z, unsigned local_z);
///////////////////////////////////////////////////////////////////////////////
////// GENERIC SHADER PROGRAM FUNCTIONS
///////////////////////////////////////////////////////////////////////////////
explicit Program(const std::vector<std::shared_ptr<Shader>> &shaders);
// We're getting generic again
void use() const;
/**
* \brief Uploads a value to the given uniform variable. Will try to automatically convert the type if not already fitting.
*
* (DEBUG MODE ONLY:) Checks the type and notifies the user if it's not right.
*/
template<typename T> void uniform(const std::string &name, const T& data) const;
void bindSubroutine(gl::ShaderType stage, const std::string& uniform, const std::string& subroutine);
......@@ -69,6 +67,19 @@ namespace glare::core
unsigned id() const;
///////////////////////////////////////////////////////////////////////////////
////// COMPUTE SHADER ORIENTED FUNCTIONS
///////////////////////////////////////////////////////////////////////////////
// Only compute shaders will take only one shader.
explicit Program(std::shared_ptr<Shader> shader);
explicit Program(const fs::path& shader_file);
// again, only usable for compute shaders.
void dispatch1d(unsigned global_x, unsigned local_x);
void dispatch2d(unsigned global_x, unsigned local_x, unsigned global_y, unsigned local_y);
void dispatch3d(unsigned global_x, unsigned local_x, unsigned global_y, unsigned local_y, unsigned global_z, unsigned local_z);
private:
void collectUniforms();
void collectSubroutines(const std::vector<std::shared_ptr<Shader>> &shaders);
......
......@@ -9,10 +9,15 @@ namespace glare::core
{
namespace fs = std::experimental::filesystem;
/**
* \brief An OpenGL shader object to be attached to a shader program.
*/
class Shader
{
public:
// Needs an identifer so we'll give it one. TODO: For what reason again?
Shader(gl::ShaderType type, const std::string& source, const std::string& identifier);
Shader(gl::ShaderType type, const fs::path& path);
Shader(gl::ShaderType type);
Shader(Shader& other) = delete;
......
......@@ -7,12 +7,22 @@
namespace glare::core
{
/**
* \brief A kind of helper class for loading shader includes, checking extensions and precompiling shader code.
*/
class ShaderSystem
{
public:
/**
* \brief Loads all shaders from the shader directory and constructs as many named strings.
*/
static void initialize();
static void terminate();
/**
* \brief Reformats the code in a suitable way to be compiled. Also checks the extensions used in the source code.
*/
static void precompile(std::string &source);
private:
......
......@@ -21,7 +21,7 @@ namespace glare::core
void removeComponent(std::shared_ptr<T> component);
template<typename TComponentDerived, typename... TArgs>
std::shared_ptr<TComponentDerived> makeComponent(TArgs ... args);
std::shared_ptr<TComponentDerived> makeComponent(TArgs... args);
template<typename T>
std::shared_ptr<T> getComponent() const;
......@@ -29,6 +29,11 @@ namespace glare::core
template<typename T>
std::vector<std::shared_ptr<TComponent>> getComponents() const;
/**
* \brief Iterates through all components calling the loop function with each one.
* Iterator stability will be achieved by iterating via vector index instead of vector iterators.
* This will enable the component to remove/detach itself while being iterated over with minimal impact.
*/
void iterateComponentsStable(std::function<void(TComponent& component)> loop);
bool hasComponents() const;
......
......@@ -14,18 +14,38 @@ namespace glare::core
class Node : public ComponentContainer<NodeType, ComponentType>
{
public:
using StableChildIterator = stable_vector_iterator<std::shared_ptr<NodeType>>;
class PreOrderIterator;
class BacktrackIterator;
class ConstBacktrackIterator;
int attach(std::shared_ptr<NodeType> node);
void detach(std::shared_ptr<NodeType> node);
/**
* \brief Detaches the node itself from it's parent. Can be used to fully delete a node/subtree by letting the return value go out of scope.
*/
std::shared_ptr<NodeType> detachSelf();
void clearChildren();
// Those can be overridden in case you want to be notified when adding/removing nodes.
virtual void onNodeAttached(std::shared_ptr<NodeType> node);
virtual void onNodeDetached(std::shared_ptr<NodeType> node);
std::shared_ptr<NodeType> parent() const;
const std::vector<std::shared_ptr<NodeType>>& children();
/**
* \brief Will create a child if there is none attached with the given name yet.
*/
std::shared_ptr<NodeType> child(const std::string& name);
/**
* \brief Will not create a child if none having the given name is found. Instead just returns a nullptr.
*/
std::shared_ptr<NodeType> child(const std::string& name) const;
unsigned childCount() const;
bool isRoot() const;
......@@ -36,62 +56,74 @@ namespace glare::core
std::shared_ptr<NodeType> find(std::string name);
template <typename TComponent> std::shared_ptr<NodeType> find();
using StableChildIterator = stable_vector_iterator<std::shared_ptr<NodeType>>;
/**
* \brief Iterate over parents of parents of parents of ... etc.
*/
BacktrackIterator iterateBack();
ConstBacktrackIterator iterateBack() const;
class PreOrderIterator : std::iterator<std::forward_iterator_tag, NodeType>
{
public:
explicit PreOrderIterator(NodeType* root);
/**
* \brief Iterate over the tree via pre-order (parent, then children)
*/
PreOrderIterator iterateTree();
PreOrderIterator begin();
PreOrderIterator end();
/**
* \brief Iterates over the children using the vector indices instead of a vector iterator to enable letting children remove themselves while iterating.
*/
StableChildIterator iterateChildren();
PreOrderIterator& operator++();
bool operator!=(const PreOrderIterator& other);
NodeType& operator*();
private:
NodeType* m_current_node;
std::stack<unsigned> m_child_counter;
};
protected:
std::weak_ptr<NodeType> m_parent;
std::vector<std::shared_ptr<NodeType>> m_children;
};
class BacktrackIterator : std::iterator<std::forward_iterator_tag, NodeType>
{
public:
explicit BacktrackIterator(NodeType* root);
template <typename NodeType, typename ComponentType>
class Node<NodeType, ComponentType>::PreOrderIterator : std::iterator<std::forward_iterator_tag, NodeType>
{
public:
explicit PreOrderIterator(NodeType* root);
BacktrackIterator begin();
BacktrackIterator end();
PreOrderIterator begin();
PreOrderIterator end();
BacktrackIterator& operator++();
bool operator!=(const BacktrackIterator& other);
NodeType& operator*();
private:
NodeType* m_current_node;
};
PreOrderIterator& operator++();
bool operator!=(const PreOrderIterator& other);
NodeType& operator*();
private:
NodeType* m_current_node;
std::stack<unsigned> m_child_counter;
};
class ConstBacktrackIterator : std::iterator<std::forward_iterator_tag, NodeType>
{
public:
explicit ConstBacktrackIterator(const NodeType* root);
template <typename NodeType, typename ComponentType>
class Node<NodeType, ComponentType>::BacktrackIterator : std::iterator<std::forward_iterator_tag, NodeType>
{
public:
explicit BacktrackIterator(NodeType* root);
ConstBacktrackIterator begin();
ConstBacktrackIterator end();
BacktrackIterator begin();
BacktrackIterator end();
ConstBacktrackIterator& operator++();
bool operator!=(const ConstBacktrackIterator& other) const;
const NodeType& operator*() const;
private:
const NodeType* m_current_node;
};
BacktrackIterator& operator++();
bool operator!=(const