mirror of
https://github.com/gwm17/Specter.git
synced 2024-11-23 02:38:52 -05:00
Started commenting code properly. Core done.
This commit is contained in:
parent
b805cf9292
commit
060183e26f
|
@ -1,3 +1,10 @@
|
||||||
|
/*
|
||||||
|
Navigator.h
|
||||||
|
This header file contains all of the essential includes for a project made using the Navigator library.
|
||||||
|
Should be included into your main project files.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef NAVIGATOR_H
|
#ifndef NAVIGATOR_H
|
||||||
#define NAVIGATOR_H
|
#define NAVIGATOR_H
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
/*
|
||||||
|
Application.cpp
|
||||||
|
This is the main application class, master and controller of program flow. Contains a layer stack, where each layer represets an
|
||||||
|
aspect of the application. Based on the Application class written by @TheCherno during his tutorial series on making a game engine.
|
||||||
|
Check out his work to learn more!
|
||||||
|
|
||||||
|
Note that Application is a singleton. Should only ever be one application ever created in the project.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Renderer/RenderCommand.h"
|
#include "Renderer/RenderCommand.h"
|
||||||
#include "Editor/EditorLayer.h"
|
#include "Editor/EditorLayer.h"
|
||||||
|
@ -12,12 +22,12 @@ namespace Navigator {
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
|
||||||
m_window = std::unique_ptr<Window>(Window::Create());
|
m_window = std::unique_ptr<Window>(Window::Create());
|
||||||
m_window->SetEventCallback(BIND_EVENT_FUNCTION(Application::OnEvent));
|
m_window->SetEventCallback(BIND_EVENT_FUNCTION(Application::OnEvent)); //Allow window to pass events back
|
||||||
|
|
||||||
m_physicsLayer = new PhysicsLayer();
|
m_physicsLayer = new PhysicsLayer();
|
||||||
PushLayer(m_physicsLayer);
|
PushLayer(m_physicsLayer);
|
||||||
EditorLayer* editor = new EditorLayer(); //memory handled by layer stack
|
EditorLayer* editor = new EditorLayer(); //memory handled by layer stack
|
||||||
editor->SetEventCallbackFunc(BIND_EVENT_FUNCTION(Application::OnEvent));
|
editor->SetEventCallbackFunc(BIND_EVENT_FUNCTION(Application::OnEvent)); //Allow editor to pass events back
|
||||||
PushLayer(editor);
|
PushLayer(editor);
|
||||||
m_imgui_layer = new ImGuiLayer();
|
m_imgui_layer = new ImGuiLayer();
|
||||||
PushOverlay(m_imgui_layer);
|
PushOverlay(m_imgui_layer);
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
/*
|
||||||
|
Application.h
|
||||||
|
This is the main application class, master and controller of program flow. Contains a layer stack, where each layer represets an
|
||||||
|
aspect of the application. Based on the Application class written by @TheCherno during his tutorial series on making a game engine.
|
||||||
|
Check out his work to learn more!
|
||||||
|
|
||||||
|
Note that Application is a singleton. Should only ever be one application ever created in the project.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef APPLICATION_H
|
#ifndef APPLICATION_H
|
||||||
#define APPLICATION_H
|
#define APPLICATION_H
|
||||||
|
|
||||||
|
@ -41,11 +51,17 @@ namespace Navigator {
|
||||||
PhysicsLayer* m_physicsLayer;
|
PhysicsLayer* m_physicsLayer;
|
||||||
bool m_runFlag;
|
bool m_runFlag;
|
||||||
|
|
||||||
|
//Dark grey background
|
||||||
glm::vec4 m_bckgnd_color = {0.1f, 0.1f, 0.1f, 1.0f};
|
glm::vec4 m_bckgnd_color = {0.1f, 0.1f, 0.1f, 1.0f};
|
||||||
|
|
||||||
static Application* s_instance;
|
static Application* s_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function is left to be defined by the user. In principle we don't need to do this, as the Navigator library doesn't handle creation of the application,
|
||||||
|
but I like it and might be useful for changing to a system with a pre-defined entry point.
|
||||||
|
*/
|
||||||
Application* CreateApplication();
|
Application* CreateApplication();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
Cut.cpp
|
||||||
|
Cut related classes. A cut here is defined as a filter upon a histogram based on some range for a parameter or set of parameters.
|
||||||
|
|
||||||
|
CutParams is the underlying data that defines a cut (excluding the actual points).
|
||||||
|
|
||||||
|
Cut is the base class for all cut objects. Should not be used in practice. All cut objects have functions which can query what kind of cut it is. If one has the cut object,
|
||||||
|
Is1D() or Is2D() can be called. If one has the CutParams, a 1D cut will have y_par set to "None" while a 2D cut will have a valid parameter name.
|
||||||
|
|
||||||
|
Cut1D is a one-dimensional (single parameter cut) while Cut2D is a two-dimensional (two parameter cut). There are a few differences between 1D and 2D cuts.
|
||||||
|
A Cut1D only contains two values, a min and a max. The parameter is checked that it falls within these bounds.
|
||||||
|
A Cut2D contains a set of (x,y) points that form a closed polygon. The polygon may be convex. The parameter is checked that it falls within the polygon using similar methods
|
||||||
|
to flood-fill algorithms.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "Cut.h"
|
#include "Cut.h"
|
||||||
#include "implot.h"
|
#include "implot.h"
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,25 @@
|
||||||
#ifndef CUT_MAP_H
|
/*
|
||||||
#define CUT_MAP_H
|
Cut.h
|
||||||
|
Cut related classes. A cut here is defined as a filter upon a histogram based on some range for a parameter or set of parameters.
|
||||||
|
|
||||||
|
CutParams is the underlying data that defines a cut (excluding the actual points).
|
||||||
|
|
||||||
|
Cut is the base class for all cut objects. Should not be used in practice. All cut objects have functions which can query what kind of cut it is. If one has the cut object,
|
||||||
|
Is1D() or Is2D() can be called. If one has the CutParams, a 1D cut will have y_par set to "None" while a 2D cut will have a valid parameter name.
|
||||||
|
|
||||||
|
Cut1D is a one-dimensional (single parameter cut) while Cut2D is a two-dimensional (two parameter cut). There are a few differences between 1D and 2D cuts.
|
||||||
|
A Cut1D only contains two values, a min and a max. The parameter is checked that it falls within these bounds.
|
||||||
|
A Cut2D contains a set of (x,y) points that form a closed polygon. The polygon may be convex. The parameter is checked that it falls within the polygon using similar methods
|
||||||
|
to flood-fill algorithms.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
|
#ifndef CUT_H
|
||||||
|
#define CUT_H
|
||||||
|
|
||||||
#include "NavCore.h"
|
#include "NavCore.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace Navigator {
|
namespace Navigator {
|
||||||
|
|
||||||
struct NAV_API CutParams
|
struct NAV_API CutParams
|
||||||
|
@ -78,7 +92,6 @@ namespace Navigator {
|
||||||
private:
|
private:
|
||||||
std::vector<double> m_xpoints;
|
std::vector<double> m_xpoints;
|
||||||
std::vector<double> m_ypoints;
|
std::vector<double> m_ypoints;
|
||||||
const ImVec4 colorVec = {1.0, 0.0, 0.0, 0.5};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
|
/*
|
||||||
|
Histogram.cpp
|
||||||
|
Histogram related classes. We use a custom histogram class here because the ImPlot histograms are not a data structure, but rather just a function. This means that at every draw call for an ImPlot
|
||||||
|
histogram the entire data set will need to be properly binned and memory will need to be allocated to make histogram arrays. For our use case this is obviously bad. For one thing, data runs can have
|
||||||
|
thousands to millions of events. In the ImPlot paradigm we would need to loop over all of this data and bin it, not to mention explicitly store all of this data in memory for every histogram. I point this
|
||||||
|
out not to say that ImPlot histograms are bad intrinsically, because they definitely have a use for smaller data sets, but rather to explain why for this program I have re-invented the wheel somewhat.
|
||||||
|
|
||||||
|
HistogramParameters are the underlying data which define a histogram. This is grouped in a struct to easily pass these around for use in contexts like the Editor.
|
||||||
|
Every histogram has a set of histogram parameters.
|
||||||
|
|
||||||
|
Histogram is the base class of all histograms. Should not be used in practice. Every histogram contains functions to query what type of underlying histogram it is. If one has
|
||||||
|
the Histogram object, Is1D() or Is2D() can be called. If one only has the HistogramParameters, the values of x_par and y_par can be inspected. In particular, a 1D histogram will have
|
||||||
|
y_par set to "None", while a 2D histogram should have a valid parameter name for y_par.
|
||||||
|
|
||||||
|
Histogram1D is a one dimensional (single parameter) histogram. Histogram2D is a two dimensional (two parameter) histogram. The only real difference between these in practice, other than
|
||||||
|
the obvious two vs. one parameter thing, is that a Histogram2D contains methods to set the z-axis range (color scale) which ImPlot does not provide intrinsic access to from the plot itself.
|
||||||
|
When the range is set to (0,0), the color scale is set to the default (0, maxValue). Otherwise the color is scaled as appropriate. If you query a Histogram1D for its color scale you will recieve
|
||||||
|
a nullptr.
|
||||||
|
|
||||||
|
StatResults is a struct containing statistical information about a region of a histogram.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "Histogram.h"
|
#include "Histogram.h"
|
||||||
#include "implot.h"
|
#include "implot.h"
|
||||||
|
|
||||||
|
@ -64,11 +87,13 @@ namespace Navigator {
|
||||||
m_binCounts[i] = 0;
|
m_binCounts[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Again here yvalues can be ignored, only for compliance
|
||||||
StatResults Histogram1D::AnalyzeRegion(double x_min, double x_max, double y_min, double y_max)
|
StatResults Histogram1D::AnalyzeRegion(double x_min, double x_max, double y_min, double y_max)
|
||||||
{
|
{
|
||||||
int bin_min, bin_max;
|
int bin_min, bin_max;
|
||||||
StatResults results;
|
StatResults results;
|
||||||
|
|
||||||
|
//We clamp to the boundaries of the histogram
|
||||||
if (x_min <= m_params.min_x)
|
if (x_min <= m_params.min_x)
|
||||||
bin_min = 0;
|
bin_min = 0;
|
||||||
else
|
else
|
||||||
|
@ -96,6 +121,7 @@ namespace Navigator {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2D Histogram class
|
2D Histogram class
|
||||||
|
Note for 2D: Rendering is done from top left to bottom right. So ybins run from top to bottom (ymin is last row, ymax is first row)
|
||||||
*/
|
*/
|
||||||
Histogram2D::Histogram2D(const HistogramParameters& params) :
|
Histogram2D::Histogram2D(const HistogramParameters& params) :
|
||||||
Histogram(params)
|
Histogram(params)
|
||||||
|
@ -144,6 +170,12 @@ namespace Navigator {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Can only be used within an ImGui / ImPlot context!!
|
//Can only be used within an ImGui / ImPlot context!!
|
||||||
|
/*
|
||||||
|
Brief note on colormaps: There are several kinds of colormaps, each with specific use cases. But broadly, the two main categories are discrete and continuous.
|
||||||
|
Discrete maps are good for categorical data, and we use these as the standard for plots we draw. This is how you make cuts standout from your histograms.
|
||||||
|
But for the colors of the bins, we want a continuous scale, i.e. smooth variation on a single hue, as the color differences represent the value differences
|
||||||
|
relative to other bins. Hence the pushing of the Matplotlib virdis colormap. For more on colormaps, I suggest looking at matplotlib documentation.
|
||||||
|
*/
|
||||||
void Histogram2D::Draw()
|
void Histogram2D::Draw()
|
||||||
{
|
{
|
||||||
ImPlot::SetupAxes(m_params.x_par.c_str(), m_params.y_par.c_str());
|
ImPlot::SetupAxes(m_params.x_par.c_str(), m_params.y_par.c_str());
|
||||||
|
@ -167,6 +199,7 @@ namespace Navigator {
|
||||||
|
|
||||||
StatResults results;
|
StatResults results;
|
||||||
|
|
||||||
|
//We clamp to the boundaries of the histogram
|
||||||
if (x_min <= m_params.min_x)
|
if (x_min <= m_params.min_x)
|
||||||
xbin_min = 0;
|
xbin_min = 0;
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
|
/*
|
||||||
|
Histogram.h
|
||||||
|
Histogram related classes. We use a custom histogram class here because the ImPlot histograms are not a data structure, but rather just a function. This means that at every draw call for an ImPlot
|
||||||
|
histogram the entire data set will need to be properly binned and memory will need to be allocated to make histogram arrays. For our use case this is obviously bad. For one thing, data runs can have
|
||||||
|
thousands to millions of events. In the ImPlot paradigm we would need to loop over all of this data and bin it, not to mention explicitly store all of this data in memory for every histogram. I point this
|
||||||
|
out not to say that ImPlot histograms are bad intrinsically, because they definitely have a use for smaller data sets, but rather to explain why for this program I have re-invented the wheel somewhat.
|
||||||
|
|
||||||
|
HistogramParameters are the underlying data which define a histogram. This is grouped in a struct to easily pass these around for use in contexts like the Editor.
|
||||||
|
Every histogram has a set of histogram parameters.
|
||||||
|
|
||||||
|
Histogram is the base class of all histograms. Should not be used in practice. Every histogram contains functions to query what type of underlying histogram it is. If one has
|
||||||
|
the Histogram object, Is1D() or Is2D() can be called. If one only has the HistogramParameters, the values of x_par and y_par can be inspected. In particular, a 1D histogram will have
|
||||||
|
y_par set to "None", while a 2D histogram should have a valid parameter name for y_par.
|
||||||
|
|
||||||
|
Histogram1D is a one dimensional (single parameter) histogram. Histogram2D is a two dimensional (two parameter) histogram. The only real difference between these in practice, other than
|
||||||
|
the obvious two vs. one parameter thing, is that a Histogram2D contains methods to set the z-axis range (color scale) which ImPlot does not provide intrinsic access to from the plot itself.
|
||||||
|
When the range is set to (0,0), the color scale is set to the default (0, maxValue). Otherwise the color is scaled as appropriate. If you query a Histogram1D for its color scale you will recieve
|
||||||
|
a nullptr.
|
||||||
|
|
||||||
|
StatResults is a struct containing statistical information about a region of a histogram.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef HISTOGRAM_H
|
#ifndef HISTOGRAM_H
|
||||||
#define HISTOGRAM_H
|
#define HISTOGRAM_H
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
Layer.cpp
|
||||||
|
Layer is an abstract class representing an aspect of the application. Based entirely upon @TheCherno's tutorials in his game engine series.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "Layer.h"
|
#include "Layer.h"
|
||||||
|
|
||||||
namespace Navigator {
|
namespace Navigator {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
Layer.h
|
||||||
|
Layer is an abstract class representing an aspect of the application. Based entirely upon @TheCherno's tutorials in his game engine series.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef LAYER_H
|
#ifndef LAYER_H
|
||||||
#define LAYER_H
|
#define LAYER_H
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
/*
|
||||||
|
LayerStack.cpp
|
||||||
|
LayerStack is a container for Layers. Should only be owned by the Application. Layers are
|
||||||
|
managed by the LayerStack (memory-wise). There are two types of layers, overlays and regular layers.
|
||||||
|
Overlays are processed first in the event stack. This is entirely based upon @TheCherno's work shown in his
|
||||||
|
game engine tutorial series.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "LayerStack.h"
|
#include "LayerStack.h"
|
||||||
|
|
||||||
namespace Navigator {
|
namespace Navigator {
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
/*
|
||||||
|
LayerStack.h
|
||||||
|
LayerStack is a container for Layers. Should only be owned by the Application. Layers are
|
||||||
|
managed by the LayerStack (memory-wise). There are two types of layers, overlays and regular layers.
|
||||||
|
Overlays are processed first in the event stack. This is entirely based upon @TheCherno's work shown in his
|
||||||
|
game engine tutorial series.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef LAYER_STACK_H
|
#ifndef LAYER_STACK_H
|
||||||
#define LAYER_STACK_H
|
#define LAYER_STACK_H
|
||||||
|
|
||||||
|
@ -17,11 +26,12 @@ namespace Navigator {
|
||||||
void PushOverlay(Layer* layer);
|
void PushOverlay(Layer* layer);
|
||||||
void PopOverlay(Layer* layer);
|
void PopOverlay(Layer* layer);
|
||||||
|
|
||||||
|
//helpers for iterator for loops
|
||||||
std::vector<Layer*>::iterator begin() { return m_stack.begin(); }
|
std::vector<Layer*>::iterator begin() { return m_stack.begin(); }
|
||||||
std::vector<Layer*>::iterator end() { return m_stack.end(); }
|
std::vector<Layer*>::iterator end() { return m_stack.end(); }
|
||||||
private:
|
private:
|
||||||
std::vector<Layer*> m_stack; //These layers are owned by the LayerStack!
|
std::vector<Layer*> m_stack; //These layers are owned by the LayerStack!
|
||||||
unsigned int m_insertIndex=0;
|
unsigned int m_insertIndex=0; //used to keep track of where to put layers vs. overlays.
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
/*
|
||||||
|
Logger.cpp
|
||||||
|
Logging class which is a thin wrapper on the spdlog library. Must be initialized in the project at start (see NavProject main.cpp for example).
|
||||||
|
Again, strongly based upon @TheCherno's work, see his Hazel repository for more details.
|
||||||
|
|
||||||
|
Note Logger is a singleton. Should only ever be intialized once. Macros for calling the log provided to make clean looking code at the other side.
|
||||||
|
Consider making some logging calls only defined on Debug.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
/*
|
||||||
|
Logger.h
|
||||||
|
Logging class which is a thin wrapper on the spdlog library. Must be initialized in the project at start (see NavProject main.cpp for example).
|
||||||
|
Again, strongly based upon @TheCherno's work, see his Hazel repository for more details.
|
||||||
|
|
||||||
|
Note Logger is a singleton. Should only ever be intialized once. Macros for calling the log provided to make clean looking code at the other side.
|
||||||
|
Consider making some logging calls only defined on Debug.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef LOGGER_H
|
#ifndef LOGGER_H
|
||||||
#define LOGGER_H
|
#define LOGGER_H
|
||||||
|
|
||||||
|
@ -22,6 +32,7 @@ namespace Navigator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Macros for clean code. Different logging levels.
|
||||||
#define NAV_CRITICAL(...) ::Navigator::Logger::GetLogger()->critical(__VA_ARGS__)
|
#define NAV_CRITICAL(...) ::Navigator::Logger::GetLogger()->critical(__VA_ARGS__)
|
||||||
#define NAV_WARN(...) ::Navigator::Logger::GetLogger()->warn(__VA_ARGS__)
|
#define NAV_WARN(...) ::Navigator::Logger::GetLogger()->warn(__VA_ARGS__)
|
||||||
#define NAV_ERROR(...) ::Navigator::Logger::GetLogger()->error(__VA_ARGS__)
|
#define NAV_ERROR(...) ::Navigator::Logger::GetLogger()->error(__VA_ARGS__)
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#ifndef NAVCORE_H
|
#ifndef NAVCORE_H
|
||||||
#define NAVCORE_H
|
#define NAVCORE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
Have to handle Windows dll import/export behavior. Otherwise, NAV_API
|
||||||
|
is just an empty expression.
|
||||||
|
*/
|
||||||
#ifdef NAV_WINDOWS
|
#ifdef NAV_WINDOWS
|
||||||
#ifdef NAV_EXPORT
|
#ifdef NAV_EXPORT
|
||||||
#define NAV_API __declspec(dllexport)
|
#define NAV_API __declspec(dllexport)
|
||||||
|
@ -29,6 +32,7 @@
|
||||||
//Bit field setter
|
//Bit field setter
|
||||||
#define BIT(x) (1<<x)
|
#define BIT(x) (1<<x)
|
||||||
|
|
||||||
|
//Macro to bind a function using lambda expressions
|
||||||
#define BIND_EVENT_FUNCTION(x) [this](auto&&... args) -> decltype(auto) { return this->x(std::forward<decltype(args)>(args)...); }
|
#define BIND_EVENT_FUNCTION(x) [this](auto&&... args) -> decltype(auto) { return this->x(std::forward<decltype(args)>(args)...); }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
Parameter.cpp
|
||||||
|
Contains two data related structures, ParameterData and NavParameter. Parameter here refers to a value which
|
||||||
|
can be associated with the axis of a histogram. ParameterData is a two component struct which represents the state of a single parameter, which is stored
|
||||||
|
in the global SpectrumManager (see SpectrumManager documentation). NavParameter is an access point class for use within analysis. It provides scoped access to
|
||||||
|
the managed data. There are several important caveats to using the parameters this way, which is mostly related to synchronization:
|
||||||
|
|
||||||
|
- NavParameter contains no guarantee of thread safety. THIS IS BY DESIGN. NavParameters should only be created within the context of an AnalysisStage (see AnalysisStage documentation).
|
||||||
|
As long as this is true, there is no risk of accessing parameter data outside of the physics thread, and that thread explicitly handles calculation of parameters
|
||||||
|
and updating of histograms. DO NOT make a NavParameter outside of the AnalysisStage context.
|
||||||
|
- NavParameters must be bound to the active SpectrumManager. This is done using the BindParameter function of the manager; NavParameters are keyed based on their name string.
|
||||||
|
If two NavParameters are made that are both named "x1", they are in fact the same parameter. In this way, values can be passed from one AnalysisStage to another. If you make a stage
|
||||||
|
called InitialStage with a NavParameter named "x1" where x1 is set to 1.0, and then have a later stage called LaterStage with another NavParameter named x1, it implicitly has the value 1.0
|
||||||
|
due to it being set in the previous stage.
|
||||||
|
- Each NavParameter has a valid flag. This is a boolean which idicates whether or not the parameter is in a valid state (the data event contianed a value for this parameter). Before using a parameter
|
||||||
|
in a calculation one should check if the parameter is valid using the IsValid() function. When a parameter is set using the SetValue() function, the valid flag is set to true. After the event is completely
|
||||||
|
processed (all analysis stages have been run and histograms have been updated) the manager should be called to run InvalidateParameters() to set all parameters as invalid (valid flag false).
|
||||||
|
|
||||||
|
Those are the key points I can think of now. As more people use the code, I expect this section to grow and change.
|
||||||
|
|
||||||
|
Credit to nscldaq and in particular NSCLSpecTcl which provided the inspiration for this parameter model.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "Parameter.h"
|
#include "Parameter.h"
|
||||||
|
|
||||||
namespace Navigator {
|
namespace Navigator {
|
||||||
|
|
|
@ -1,17 +1,42 @@
|
||||||
|
/*
|
||||||
|
Parameter.h
|
||||||
|
Contains two data related structures, ParameterData and NavParameter. Parameter here refers to a value which
|
||||||
|
can be associated with the axis of a histogram. ParameterData is a two component struct which represents the state of a single parameter, which is stored
|
||||||
|
in the global SpectrumManager (see SpectrumManager documentation). NavParameter is an access point class for use within analysis. It provides scoped access to
|
||||||
|
the managed data. There are several important caveats to using the parameters this way, which is mostly related to synchronization:
|
||||||
|
|
||||||
|
- NavParameter contains no guarantee of thread safety. THIS IS BY DESIGN. NavParameters should only be created within the context of an AnalysisStage (see AnalysisStage documentation).
|
||||||
|
As long as this is true, there is no risk of accessing parameter data outside of the physics thread, and that thread explicitly handles calculation of parameters
|
||||||
|
and updating of histograms. DO NOT make a NavParameter outside of the AnalysisStage context.
|
||||||
|
- NavParameters must be bound to the active SpectrumManager. This is done using the BindParameter function of the manager; NavParameters are keyed based on their name string.
|
||||||
|
If two NavParameters are made that are both named "x1", they are in fact the same parameter. In this way, values can be passed from one AnalysisStage to another. If you make a stage
|
||||||
|
called InitialStage with a NavParameter named "x1" where x1 is set to 1.0, and then have a later stage called LaterStage with another NavParameter named x1, it implicitly has the value 1.0
|
||||||
|
due to it being set in the previous stage.
|
||||||
|
- Each NavParameter has a valid flag. This is a boolean which idicates whether or not the parameter is in a valid state (the data event contianed a value for this parameter). Before using a parameter
|
||||||
|
in a calculation one should check if the parameter is valid using the IsValid() function. When a parameter is set using the SetValue() function, the valid flag is set to true. After the event is completely
|
||||||
|
processed (all analysis stages have been run and histograms have been updated) the manager should be called to run InvalidateParameters() to set all parameters as invalid (valid flag false).
|
||||||
|
|
||||||
|
Those are the key points I can think of now. As more people use the code, I expect this section to grow and change rapidly.
|
||||||
|
|
||||||
|
Credit to nscldaq and in particular NSCLSpecTcl which provided the inspiration for this parameter model.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef PARAMETER_MAP_H
|
#ifndef PARAMETER_MAP_H
|
||||||
#define PARAMETER_MAP_H
|
#define PARAMETER_MAP_H
|
||||||
|
|
||||||
#include "NavCore.h"
|
#include "NavCore.h"
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace Navigator {
|
namespace Navigator {
|
||||||
|
|
||||||
|
//Underlying data
|
||||||
struct NAV_API ParameterData
|
struct NAV_API ParameterData
|
||||||
{
|
{
|
||||||
double value=0.0;
|
double value=0.0;
|
||||||
bool validFlag=false;
|
bool validFlag=false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Interface to parameter data
|
||||||
class NAV_API NavParameter
|
class NAV_API NavParameter
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
/*
|
||||||
|
SpectrumManager.cpp
|
||||||
|
SpectrumManager is the global resource management class. Controls everything related to spectra (histograms, cuts, parameters). Since
|
||||||
|
the manager must traverse threads, explicit synchronoization is handled through a mutex. To this end, excessive calls to the manager should be
|
||||||
|
avoided if possible, as this will increase the lock deadtime in the application, which is especially bad for online data sources.
|
||||||
|
|
||||||
|
Note that SpectrumManager is a singleton. There should only ever be one SpectrumManager with a given application.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "SpectrumManager.h"
|
#include "SpectrumManager.h"
|
||||||
|
|
||||||
#include "implot.h"
|
#include "implot.h"
|
||||||
|
@ -14,10 +24,12 @@ namespace Navigator {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************Histogram Functions Begin*************/
|
||||||
|
|
||||||
void SpectrumManager::AddHistogram(const HistogramParameters& params)
|
void SpectrumManager::AddHistogram(const HistogramParameters& params)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
if (params.y_par == "None")
|
if (params.y_par == "None") //Check dimensionality
|
||||||
m_histoMap[params.name].reset(new Histogram1D(params));
|
m_histoMap[params.name].reset(new Histogram1D(params));
|
||||||
else
|
else
|
||||||
m_histoMap[params.name].reset(new Histogram2D(params));
|
m_histoMap[params.name].reset(new Histogram2D(params));
|
||||||
|
@ -45,6 +57,7 @@ namespace Navigator {
|
||||||
iter->second->AddCutToBeApplied(cutname);
|
iter->second->AddCutToBeApplied(cutname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Use this to fill histograms. Currently can only be filled in bulk; maybe a use case for individual fills?
|
||||||
void SpectrumManager::UpdateHistograms()
|
void SpectrumManager::UpdateHistograms()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -52,7 +65,7 @@ namespace Navigator {
|
||||||
for (auto& pair : m_histoMap)
|
for (auto& pair : m_histoMap)
|
||||||
{
|
{
|
||||||
cutFlag = true;
|
cutFlag = true;
|
||||||
for (auto& cutname : pair.second->GetParameters().cutsAppliedTo)
|
for (auto& cutname : pair.second->GetParameters().cutsAppliedTo) //check the event against cuts
|
||||||
{
|
{
|
||||||
if (!IsInsideCut(cutname))
|
if (!IsInsideCut(cutname))
|
||||||
{
|
{
|
||||||
|
@ -101,7 +114,7 @@ namespace Navigator {
|
||||||
if (iter != m_histoMap.end())
|
if (iter != m_histoMap.end())
|
||||||
{
|
{
|
||||||
iter->second->Draw();
|
iter->second->Draw();
|
||||||
for (auto& cutname : iter->second->GetParameters().cutsDrawnUpon)
|
for (auto& cutname : iter->second->GetParameters().cutsDrawnUpon) //Draw all cuts made upon the histogram
|
||||||
DrawCut(cutname);
|
DrawCut(cutname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +129,7 @@ namespace Navigator {
|
||||||
return m_nullHistoResult;
|
return m_nullHistoResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//For 2D spectra, we want to allow zooming along the z-axis (color)
|
||||||
float* SpectrumManager::GetColorScaleRange(const std::string& name)
|
float* SpectrumManager::GetColorScaleRange(const std::string& name)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -140,6 +154,7 @@ namespace Navigator {
|
||||||
return std::vector<double>();
|
return std::vector<double>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Pass through for stats
|
||||||
StatResults SpectrumManager::AnalyzeHistogramRegion(const std::string& name, const ImPlotRect& region)
|
StatResults SpectrumManager::AnalyzeHistogramRegion(const std::string& name, const ImPlotRect& region)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -150,6 +165,8 @@ namespace Navigator {
|
||||||
return StatResults();
|
return StatResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//This function allows us to obtain the key histogram info in a list, avoiding excessive manager calls and thread-locks
|
||||||
|
//in something like the Editor.
|
||||||
std::vector<HistogramParameters> SpectrumManager::GetListOfHistograms()
|
std::vector<HistogramParameters> SpectrumManager::GetListOfHistograms()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -162,6 +179,12 @@ namespace Navigator {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************Histogram Functions End*************/
|
||||||
|
|
||||||
|
|
||||||
|
/*************Parameter Functions Begin*************/
|
||||||
|
|
||||||
|
//Bind a NavParameter instance to the manager. If the Parameter doesn't exist, make a new one, otherwise attach to extant memory
|
||||||
void SpectrumManager::BindParameter(NavParameter& param)
|
void SpectrumManager::BindParameter(NavParameter& param)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -174,6 +197,7 @@ namespace Navigator {
|
||||||
param.m_pdata = m_paramMap[param.GetName()];
|
param.m_pdata = m_paramMap[param.GetName()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Once an analysis pass is done and histograms filled, reset all parameters
|
||||||
void SpectrumManager::InvalidateParameters()
|
void SpectrumManager::InvalidateParameters()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -184,6 +208,7 @@ namespace Navigator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Similar to GetListOfHistograms, see that documentation
|
||||||
std::vector<std::string> SpectrumManager::GetListOfParameters()
|
std::vector<std::string> SpectrumManager::GetListOfParameters()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -197,11 +222,15 @@ namespace Navigator {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************Parameter Functions End*************/
|
||||||
|
|
||||||
|
/*************Cut Functions Begin*************/
|
||||||
|
|
||||||
void SpectrumManager::RemoveCut(const std::string& name)
|
void SpectrumManager::RemoveCut(const std::string& name)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
m_cutMap.erase(name);
|
m_cutMap.erase(name);
|
||||||
RemoveCutFromHistograms(name);
|
RemoveCutFromHistograms(name); //Once a cut is gone, remove all references to it.
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<double> SpectrumManager::GetCutXPoints(const std::string& name)
|
std::vector<double> SpectrumManager::GetCutXPoints(const std::string& name)
|
||||||
|
@ -224,6 +253,7 @@ namespace Navigator {
|
||||||
return null_result;
|
return null_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Similar to GetListOfHistograms, see that documentation
|
||||||
std::vector<CutParams> SpectrumManager::GetListOfCuts()
|
std::vector<CutParams> SpectrumManager::GetListOfCuts()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -234,13 +264,15 @@ namespace Navigator {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************Cut Functions End*************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Private Functions
|
Private Functions
|
||||||
Can only be called from within the SpectrumManager, therefore the lock should already have been aquired by
|
Can only be called from within the SpectrumManager, therefore the lock should already have been aquired by
|
||||||
whatever parent function calls them
|
whatever parent function calls them. No explicit synchronization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//private helper function; does not need thread-locked
|
//Can only be called by RemoveCut currently. May be a use case where this should be promoted to public to on the fly mod a gram.
|
||||||
void SpectrumManager::RemoveCutFromHistograms(const std::string& cutname)
|
void SpectrumManager::RemoveCutFromHistograms(const std::string& cutname)
|
||||||
{
|
{
|
||||||
for (auto& gram : m_histoMap)
|
for (auto& gram : m_histoMap)
|
||||||
|
@ -263,6 +295,7 @@ namespace Navigator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Obv. only need to draw a cut if its parent histogram is drawn.
|
||||||
void SpectrumManager::DrawCut(const std::string& name)
|
void SpectrumManager::DrawCut(const std::string& name)
|
||||||
{
|
{
|
||||||
auto iter = m_cutMap.find(name);
|
auto iter = m_cutMap.find(name);
|
||||||
|
@ -270,6 +303,7 @@ namespace Navigator {
|
||||||
iter->second->Draw();
|
iter->second->Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check if event passes a cut. Only used when filling histograms.
|
||||||
bool SpectrumManager::IsInsideCut(const std::string& name)
|
bool SpectrumManager::IsInsideCut(const std::string& name)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
/*
|
||||||
|
SpectrumManager.h
|
||||||
|
SpectrumManager is the global resource management class. Controls everything related to spectra (histograms, cuts, parameters). Since
|
||||||
|
the manager must traverse threads, explicit synchronoization is handled through a mutex. To this end, excessive calls to the manager should be
|
||||||
|
avoided if possible, as this will increase the lock deadtime in the application, which is especially bad for online data sources.
|
||||||
|
|
||||||
|
Note that SpectrumManager is a singleton. There should only ever be one SpectrumManager with a given application.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef SPECTRUM_MANAGER_H
|
#ifndef SPECTRUM_MANAGER_H
|
||||||
#define SPECTRUM_MANAGER_H
|
#define SPECTRUM_MANAGER_H
|
||||||
|
|
||||||
|
@ -19,6 +29,7 @@ namespace Navigator {
|
||||||
|
|
||||||
inline static SpectrumManager& GetInstance() { return *s_instance; }
|
inline static SpectrumManager& GetInstance() { return *s_instance; }
|
||||||
|
|
||||||
|
//To clear all managed spectra. Note that Parameters are left untouched.
|
||||||
inline void RemoveAllSpectra()
|
inline void RemoveAllSpectra()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -26,6 +37,7 @@ namespace Navigator {
|
||||||
m_cutMap.clear();
|
m_cutMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Histogram Functions*/
|
||||||
void AddHistogram(const HistogramParameters& params);
|
void AddHistogram(const HistogramParameters& params);
|
||||||
void RemoveHistogram(const std::string& name);
|
void RemoveHistogram(const std::string& name);
|
||||||
void AddCutToHistogramDraw(const std::string& cutname, const std::string& histoname);
|
void AddCutToHistogramDraw(const std::string& cutname, const std::string& histoname);
|
||||||
|
@ -39,11 +51,15 @@ namespace Navigator {
|
||||||
std::vector<double> GetBinData(const std::string& name);
|
std::vector<double> GetBinData(const std::string& name);
|
||||||
StatResults AnalyzeHistogramRegion(const std::string& name, const ImPlotRect& region);
|
StatResults AnalyzeHistogramRegion(const std::string& name, const ImPlotRect& region);
|
||||||
std::vector<HistogramParameters> GetListOfHistograms();
|
std::vector<HistogramParameters> GetListOfHistograms();
|
||||||
|
/********************/
|
||||||
|
|
||||||
|
/*Parameter Functions*/
|
||||||
void BindParameter(NavParameter& param);
|
void BindParameter(NavParameter& param);
|
||||||
void InvalidateParameters();
|
void InvalidateParameters();
|
||||||
std::vector<std::string> GetListOfParameters();
|
std::vector<std::string> GetListOfParameters();
|
||||||
|
/********************/
|
||||||
|
|
||||||
|
/*Cut Functions*/
|
||||||
inline void AddCut(const CutParams& params, double min, double max)
|
inline void AddCut(const CutParams& params, double min, double max)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(m_managerMutex);
|
std::lock_guard<std::mutex> guard(m_managerMutex);
|
||||||
|
@ -58,21 +74,24 @@ namespace Navigator {
|
||||||
std::vector<double> GetCutXPoints(const std::string& name);
|
std::vector<double> GetCutXPoints(const std::string& name);
|
||||||
std::vector<double> GetCutYPoints(const std::string& name);
|
std::vector<double> GetCutYPoints(const std::string& name);
|
||||||
std::vector<CutParams> GetListOfCuts();
|
std::vector<CutParams> GetListOfCuts();
|
||||||
|
/**************/
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//Only used from within manager
|
||||||
void RemoveCutFromHistograms(const std::string& cutname);
|
void RemoveCutFromHistograms(const std::string& cutname);
|
||||||
void DrawCut(const std::string& name);
|
void DrawCut(const std::string& name);
|
||||||
bool IsInsideCut(const std::string& name);
|
bool IsInsideCut(const std::string& name);
|
||||||
|
|
||||||
static SpectrumManager* s_instance;
|
static SpectrumManager* s_instance;
|
||||||
|
|
||||||
|
//Actual data
|
||||||
std::unordered_map<std::string, std::shared_ptr<Histogram>> m_histoMap;
|
std::unordered_map<std::string, std::shared_ptr<Histogram>> m_histoMap;
|
||||||
std::unordered_map<std::string, std::shared_ptr<Cut>> m_cutMap;
|
std::unordered_map<std::string, std::shared_ptr<Cut>> m_cutMap;
|
||||||
std::unordered_map<std::string, std::shared_ptr<ParameterData>> m_paramMap;
|
std::unordered_map<std::string, std::shared_ptr<ParameterData>> m_paramMap;
|
||||||
|
|
||||||
HistogramParameters m_nullHistoResult;
|
HistogramParameters m_nullHistoResult; //For handling bad query
|
||||||
|
|
||||||
std::mutex m_managerMutex;
|
std::mutex m_managerMutex; //synchronization
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
/*
|
||||||
|
SpectrumSerializer.h
|
||||||
|
SpectrumSerializer class providing method to write/read spectra (histograms and cuts) to/from a .nav file. These are formated text files.
|
||||||
|
Note that by virtue of the way that cuts work, they are written first.
|
||||||
|
|
||||||
|
A couple of notes:
|
||||||
|
- Writing/reading data is a pretty expensive concept from a thread-locking perspective. Not recommended for use during active analysis.
|
||||||
|
- Deserializing (reading) by default removes all current histograms and cuts. This avoids any issues with collisions, but may not always be desireable.
|
||||||
|
- There is no intrinsic checking of whether a parameter for a cut/histogram to be loaded exists within the current project. If you load something and the histograms
|
||||||
|
don't fill, it is most likely due to the parameter not being defined in the current project.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#include "SpectrumSerializer.h"
|
#include "SpectrumSerializer.h"
|
||||||
#include "SpectrumManager.h"
|
#include "SpectrumManager.h"
|
||||||
|
|
||||||
|
@ -122,7 +135,7 @@ namespace Navigator {
|
||||||
void SpectrumSerializer::DeserializeData()
|
void SpectrumSerializer::DeserializeData()
|
||||||
{
|
{
|
||||||
SpectrumManager& manager = SpectrumManager::GetInstance();
|
SpectrumManager& manager = SpectrumManager::GetInstance();
|
||||||
manager.RemoveAllSpectra();
|
manager.RemoveAllSpectra(); //When loading in, we remove all extant data, to avoid any potential collisions.
|
||||||
|
|
||||||
std::ifstream input(m_filename);
|
std::ifstream input(m_filename);
|
||||||
if (!input.is_open())
|
if (!input.is_open())
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
/*
|
||||||
|
SpectrumSerializer.h
|
||||||
|
SpectrumSerializer class providing method to write/read spectra (histograms and cuts) to/from a .nav file. These are formated text files.
|
||||||
|
Note that by virtue of the way that cuts work, they are written first.
|
||||||
|
|
||||||
|
A couple of notes:
|
||||||
|
- Writing/reading data is a pretty expensive concept from a thread-locking perspective. Not recommended for use during active analysis.
|
||||||
|
- Deserializing (reading) by default removes all current histograms and cuts. This avoids any issues with collisions, but may not always be desireable.
|
||||||
|
- There is no intrinsic checking of whether a parameter for a cut/histogram to be loaded exists within our framework. If you load something and the histograms
|
||||||
|
don't fill, it is most likely due to the parameter not being defined in the current project.
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef SPECTRUM_SERIALIZER_H
|
#ifndef SPECTRUM_SERIALIZER_H
|
||||||
#define SPECTRUM_SERIALIZER_H
|
#define SPECTRUM_SERIALIZER_H
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
Window.h
|
||||||
|
|
||||||
|
Abstract class for a window in Navigator. Based entirely upon the work of @TheCherno, see his Hazel repository. This exists primarily to allow for the option
|
||||||
|
to extend Navigator to other rendering backends, most likely Metal, or potentially DX12. See code in Platform for specific implementations (currently only for OpenGL).
|
||||||
|
|
||||||
|
GWM -- Feb 2022
|
||||||
|
*/
|
||||||
#ifndef WINDOW_H
|
#ifndef WINDOW_H
|
||||||
#define WINDOW_H
|
#define WINDOW_H
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user