# FocusTerra Realtime Wave Simulator
This repository contains all files that make up the realtime wave simulator exhibit at FocusTerra.

While the project was originally developed on macOS, it was later ported to Windows (Visual Studio 2019).

Dependencies are OpenGL, ImGui and SDL, and all of them are contained in this repository.

# Table of Contents
[TOC]

# Project Organization
The repo is organized in the following folders:
- `src` (and subfolders) contains all `.cpp`
- `include` (and subfolders) contains all headers
- `shaders` contains all GLSL shaders
- `lib` contains libraries
- `FocusTerra` contains the Visual Studio project file
- `FocusTerra\x64\Release` and `FocusTerra\x64\Debug` contain the executables
- `build` is left over from the macOS days (contains a currently broken `Makefile`)

# Resources
Resources are organized in a single folder called `ft_top`. It contains the following:
- A folder `bin` that contains the executable and `SDL2.dll`
- A folder `fonts` that contains the font used by the GUI, namely `Cousine-Regular.ttf`
- A folder `resource` that contains
    - The colour palette in `ft_palette.conf`, `ft_palette.texture`
    - The Image Button images in the folder `images`
    - A folder `textures` that contains the predefined structure textures. There are two versions, one for the FocusTerra resolution (in `rocket`), and one for Pascal's resolution (in `home`).
- A folder `shaders` that contains the used GLSL shaders.

The program accesses these resources at runtime.

## File Formats
This section describes the file formats external files are expected to follow.

### GUI Images
Gui Images, such as the button textures, are loaded using `stbi`. The exact calls can be found in `GuiHandler::load_image_to_texture_`. The important parts are
```c++
data = stbi_load(file.c_str(), &width, &height, &nrChannels, STBI_rgb_alpha);
//...
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
```
Images are expected to be RGBA, i.e. to have an alpha channel. Not being very fluent in image formats, I believe this is the only limitation. 
To be save, I'll state that images are expected to be loadable with the above calls.

### Damping Textures
Damping Textures, such as those used by `PatternHandler` and `WaveHandler`, are 2D textures and they are composed of two files: 
- a `.conf` file that describes several properties of the texture,
- a `.texture` file that contains the texture data.
These two files are expected to be in the same directory. By convention, the name of the texture does never include any file extensions. 
Thus a texture with name `my_damping_map` will consist of the two files `my_damping_map.conf` and `my_damping_map.texture`.

A sample `.conf` file with comments is shown below. 
Its screen dimensions are what the FocusTerra touchscreen supports natively. 
Note that the comments are not allowed in real files.
```c++
3840 //screen width in pixels
2160 //screen height in pixels
4440 //texture width in texels
3360 //texture height in texels
0    //screen offset left in texels
600  //screen offset right in texels
600  //screen offset bottom in texels
600  //screen offset top in texels
```

The meaning of the offsets is the following: In this application, we simulate a larger region than what's drawn on the screen. 
Thus what's drawn on the screen is just a rectangular region within the texture. 
To describe the placement of this region, we use the number of pixels between the screen region and the texture boundaries in all four directions.
That's what these offsets describe.

Note that only if all damping textures agree with the dimensions specified in the application, will the program run correctly. Anything else will give you UB.

A `.texture` file contains `4 * texture_width * texture_height` floating point values. Each group of four is to be interpreted as the RGBA values of a single texel.
Successive values are delimited with a single space. After each `4 * texture_width` values, a newline is expected.

Texture uploading is done via the following call:
```c++
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, texture_width, texture_height, 0, GL_RGBA, GL_FLOAT, data_target.data());
```

One peculiarity to be aware of is the use of different axis conventions. 
Images typically have the origin in the lower left corner with y-axis pointing upwards, while OpenGL has the origin in the top left corner with the y-axis pointing **downwards**. 
This means that the first four floats in the file describe the top left texel, and the first `4 * texture_width` values describe the top most row of texels.
This is only important when using damping textures that are asymmetric with respect to the horizontal. 
If it is a problem, consider either flipping the image, or look into calling `stbi_set_flip_vertically_on_load(true)`. This can also be taken care of shader side.

### Colour Palettes
A colour palette, like that loaded by `WaveHandler::load_palette_` and used to draw the waves in a custom colour scheme, is a 1D texture. 
Most of the conventions for [Damping Textures](#damping-textures) also apply here. The differences are:
- The `.conf` file only contains one integer, the number of texels in the texture
- The `.texture` file still contains four space-denominated floats per texel (RGBA), but there is a newline after each texel.

As things stand now, the lowest wave point maps to the first texel, and the highest wave point maps to the last texel.

Similarly to 2D textures, here we upload the data via
```c++
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, palette_.size()/4, 0, GL_RGBA, GL_FLOAT, palette_.data());
```

# Building the Project
## Windows
In order to build the project, the following steps must be followed
- Open the project in Visual Studio 2019
- Make sure the following files are excluded from the build (`Rightclick`, `Properties`, `Excluded from Build`, `Yes`:
    - `block.hpp`
    - `blockchain_handler.hpp`
    - `block.cpp`
    - `blockchain_handler.cpp`
    - `imgui_example_sdl_opengl3.cpp`
    - `main.cpp`
    - `main_3d.cpp`
    - `main_refactored.cpp`
- There should be a lot of include-errors reported. To fix this, adjust the paths:
    - In the `Solution Explorer`, right click on `FocusTerra` and select `Properties`
    - Navigate to `VCC Directories` and adjust the `Include Directories`. They should point to
        - `include`
        - `include\imgui`
        - `SDL2-2.0.14\include` (e.g. in WindowsSDL, or vclib (not in project))
    - Also adjust the `Library Directories`. They should point to `SDL2-2.0.14\lib\x64`.
    - The linked libraries can be seen in `Linker`, `Input`, `Additional Dependencies`. They should not require change, and should include `SDL2.lib`, `SDL2main.lib` and `opengl32.lib`.
- Open `main_testing.cpp`. This contains the `main` function. Adjust it for the target system:
    - Adjust the screen resolution using the `#defines` at the top. Predefined are the resolutions for the FocusTerra screen and for Pascal's screen.
    - Adjust the `top_path` to point to the resource folder (i.e. `ft_top`).
    - Adjust the Derived paths, where necessary. Potentially the `tex_path` may need adjustment.
    - Adjust the `tex_offscreen_*` variables to reflect the used texture dimensions.
- Open `input_handler.cpp`.
    - For a touchscreen, send an event after the `SDL_FINGER*` cases. On non-touch devices, send events after the `SDL_MOUSE*` events.
- Open `slim_blockchain_handler.cpp`
    - Depending on the system, uncomment or comment out the section marked `Uncomment on a touchscreen`.
- Open `drawing_handler.cpp`
    - Depending on the system, uncomment or comment out the section marked `Uncomment on a touchscreen`.
- Open `gui_handler.cpp`
    - Depending on the system, change the gui drawcall towards the end in `GuiHandler::update`.
    - Depending on the system, comment out or uncomment the two sections marked `Uncomment on a touchscreen`.
- Rightclick on `FocusTerra`, select `Build`.
- When the building is finished, create a `ft_top` folder according to the specifications above, and place the executable in the `bin` folder. If there are library issues, also place a copy of `SDL2.dll` in the `bin` folder.
- Now the application is ready to be run.

## macOS
Building on macOS is currently not supported.

# User Manual
Todo

# Documentation
The following is a documentation for all the code used in the project. As the project is currently at development halt, there are a few known issues that can not be addressed for the time being. They are pointed out in their respective sections.
## Architecture
The application is split into different modules, each module handles a subset of the total functionality. The major modules and their responsibilities are
- **`WaveHandler`**
  - Handle the wave textures
  - Handle integration of the wave equation
  - Handle rendering the wave
  - Handle certain texture initialisations for other modules *(this should be changed)*
- **`InputHandler`**
  - Interface with SDL to fetch user input
  - Translate user input to a usable format (`Pevent`)
  - Communicate user input to other modules
- **`GuiHandler`**
  - Interface with `ImGui`
  - Draw the GUI
  - Communicate GUI input to other modules
- **`SlimBlockchainHandler`**
  - Handle the "Spielen" functionality (place, move, remove blocks)
  - Draw to wave and damping textures to implement "Spielen"
- **`DrawingHandler`**
  - Handle the "Zeichnen" and "Radieren" functionality (draw strokes)
  - Draw to wave and damping textures to implement "Zeichnen" and "Radieren"
- **`PatternHandler`**
  - Handle all predefined structure placements
  - Draw structures to damping textures 
- **`TimeoutHandler`**
  - Handle the Timeout functionality (if no user input for N seconds, post reset requests for everyone)
- **`Toolbox`**
  - Store information needed by several other modules ("global state")
  - Implement an event chain where current events are stored
  - Implement a mailbox to enable the passing of messages

Much like the name suggests, the `Toolbox` is passed around from one module to the next, and each can then access everything stored within it. 
Each module can see all information and decide how it reacts to the current combination of state, messages and events (user input).
The logical flow of the application game loop goes as follows:
1. `InputHandler` fetches and writes new user input into the `Toolbox` event chain
2. `TimeoutHandler` checks if there is any user input, and if timeout occurs posts reset requests to the `Toolbox` mailbox targeting all other modules
3. `GuiHandler` checks if user input targets the GUI, updates the global state (e.g. change source frequency, change game mode to "Zeichnen") and posts appropriate messages for other modules (e.g. place structure)
4. `WaveHandler` checks if any messages that target it have been posted
5. `SlimBlockchainHandler` reacts to its messages and user input
6. `DrawingHandler` reacts to its messages and user input
7. `PatternHandler` reacts to its messages and user input
8. Now all state has been updated, all messages posted and handled and damping textures are final
9.  `WaveHandler` generates the new damping texture and timesteps the wave
10. `WaveHandler` renders the new wave to the screen
11. `GuiHandler` renders the GUI to the screen
12. Renderbuffers are swapped and the frame ends


## Classes
### Drawer ([drawer.hpp](include/drawer.hpp), [drawer.cpp](src/drawer.cpp))
**Description**
  
 A `Drawer` is an object that can draw a single line of segments to the screen. 
 It handles single touch of the `Zeichnen` functionality. 
 Note that this class relies on the caller to its methods to take care of the Opengl state (using shaders, binding buffers, etc.). 
 See `DrawingHandler` for more information on how this class is to be used.
 The coordinates used are typically OpenGL coordinates, i.e. in the range [-1, 1].

**Usage**
- Construct object (e.g. when new finger goes down)
- `start_drawing` with initial position (e.g. with finger down position)
- Upon new location (e.g. finger motion to new position), setup Opengl state (use shader `draw`, bind FBO, bind VAO, **bind VBO**, set viewport, bind textures) and call `draw`. Call `redraw` with all required FBO/texture combinations.
- Destruct when drawing this line is finished (e.g. finger is lifted)


**Constructors and Destructors**

- **`Drawer(Toolbox&)`**
  - Notes: The argument is unused. It should be removed.
- **`Drawer(const Drawer&) = default`**
- **`~Drawer() = default`**

**Public Function Members**
- **`void start_drawing(const float x, const float y)`**
  - Description: Start drawing at coordinates (`x`, `y`) (typically fingerdown location). Doesn't draw anything. 
  - Preconditions:
  - Postconditions:Drawing start is set to (x, y).
  - Notes: Nothing is drawn by this function. (x, y) are typically the fingerdown coordinates.
- **`bool draw(const float x, const float y, Toolbox& tb, bool drawing)`**
  - Description: Draw a stroke from the last position to (x, y), with strokewidth controlled by `drawing` (`true`->`tb.drawing_width`, `false`->`tb.erasing_width`).
  - Preconditions: A `GL_ARRAY_BUFFER` is bound and the Opengl state is set as desired
  - Postconditions: The points of the new segment have been calculated and uploaded to the currently bound `GL_ARRAY_BUFFER`, a call to `glDrawArrays` has been done to draw the segment.
    Returns `true` if something was drawn, and `false` else (typically when new point is same as last point).
  - Notes:
- **`void redraw(Toolbox&)`**
  - Description: Redraws the last drawn stroke.
  - Preconditions: `draw` has been called at least once, and since the last call to `draw`, the then-bound `GL_ARRAY_BUFFER` has not been modified.
  - Postconditions: A drawcall `glDrawArrays` has been issued.
  - Notes: 
- **`void erase(const float x, const float y, Toolbox& tb)`** **DEPRECATED**
  - Notes: Use `draw(x, y, tb, false)` instead.
- **`int num_drawn()`**
  - Description: Returns the number of calls to `draw` and `erase` that have been performed by this object.
  - Preconditions: 
  - Postconditions: 
  - Notes: 
  
    

**Private Function Members**
- **`bool calculate_points_(Toolbox& tb, bool drawing)`**
  - Description: Calculate the triangulation of the stroke represented by the internal parameters, and store them in `points_`.
    The stroke width is controlled by `drawing` (`true`->`tb.drawing_width`, `false`->`tb.erasing_width`).
  - Preconditions: The points (`x0_`, `y0_`) and (`x1_`, `y1_`) are set as desired.
  - Postconditions: If the points (`x0_`, `y0_`), (`x1_`, `y1_`) are the same, false has been returned and the call has no effect.
    Else, `true` has been returned, and the vertices that make up the segment between these two points with the desired width have been calculated and stored in `points_`.
  - Notes: 


**Public Data Members**
  
N/A

**Private Data Members**
- `float x0_, y0_, x1_, y1_`: Internal representation of old ('0') and new ('1') points.
- `int num_drawn_`: Number of calls to `draw` and `erase`.
- `std::vector<float> points_`: Vertex coordinates that represent the stroke between old and new points, as calculated by `calculate_points_`.

**Notes**

N/A

### DrawingHandler ([drawing_handler.hpp](include/drawing_handler.hpp), [drawing_handler.cpp](src/drawing_handler.cpp))
**Description**

This class handles all aspects of the `Zeichnen` / `Radieren` functionality. It constructs `Drawer` objects on demand, manages their OpenGL infrastructure and chooses appropriate rendering targets.

**Usage**

- Construct one object at the start of the application with a fully initialized `Toolbox`
- In each frame, call `update(Toolbox&)`

**Constructors and Destructors**

- **`DrawingHandler(Toolbox&)`**
  - Notes: `Toolbox` is needed to find shader sources and obtain handles to the damping and wave textures.
- **`~DrawingHandler()`**

**Public Function Members**

- **`void update(Toolbox&)`**
  - Description: Handles messages directed to it, parses events and takes the necessary actions (spawn / delete `Drawer`s, draw with `Drawer`s using correct infrastructure).
  - Preconditions: The object is initialized correctly.
  - Postconditions: The desired portions have been drawn to static damping and to the wave 1 texture.
  - Notes: 
- **`size_t num_drawers()`**
  - Description: Returns the current number of active `Drawer`s.
  - Preconditions: 
  - Postconditions: 
  - Notes: 

**Private Function Members**

- **`void draw_(Toolbox&)`**
  - Notes: Does nothing.
- **`bool in_wave_window_(const Toolbox&, const Pevent&) const`**
  - Description: Check if an event is within the wave window.
  - Preconditions: 
  - Postconditions: Returns `true` if the event is in the wave window, and `false` else (i.e. when event is in the GUI window).
  - Notes: 
- **`std::array<float, 2> drawerCoordinates_(const Pevent&, const Toolbox&)`**
  - Description: Compute drawer coordinates of a `Pevent`.
  - Preconditions: 
  - Postconditions: 
  - Notes: The method `Drawer::draw` should be called with the return values of this function.

**Public Data Members**

N/A

**Private Data Members**

- `std::list<std::pair<Drawer, SDL_FingerID> > drawpairs_`: List of `Drawer`s and the corresponding `SDL_FingerID` that spawned/controls them.
- `int previous_mstate_`: `tb.mstate` from previous frame
- `float draw_value_, erase_value_`: **DEPRECATED**
- `GLuint vao_, vbo_`: Vertex Array Object and Vertex Buffer Object that are used by the `Drawer`s
- `GLuint fbo_, fbo_wave_`: Framebuffers that target the static damping texture (`fbo_`) and the wave texture 1 (`fbo_wave_`)
- `Shader shader_draw_`: Shader that is used.

**Notes**

Todo

### EfficientBlock ([efficient_block.hpp](include/efficient_block.hpp), [efficient_block.cpp](src/efficient_block.cpp))
**Description**

Represents a rectangular block. Scaled down version of the previous `Block`, optimized for current feature set.

**Usage**

 - Construct object
 - Call `xywh` to obtain an efficient representation of the properties, convert it to vertices and draw them
   - Note: This should be batched for peak performance (see `SlimBlockchainHandler`)
 - Check if a point is inside the block using `is_inside`
 - Obtain the dimensions using `width` and `height`
 - Move the block to a new position using `translate`
 - Mark the block for removal using `request_removal`
 - Check if a block has been marked for removal using `needs_removal`

**Constructors and Destructors**

- **`EfficientBlock()`**
- **`EfficientBlock(const EfficientBlock&)`**
- **`EfficientBlock(int w, int h, int xoffset, int yoffset)`**
  - Note: (`xoffset`, `yoffset`) are the coordinates of the lower left corner, with origin in the top left corner of the texture.

**Public Function Members**

- **`void request_removal()`**
  - Description: Mark block for removal
  - Preconditions: 
  - Postconditions: Block is marked for removal
  - Notes: 
- **`void translate(int new_x, int new_y)`**
  - Description: Translate block to new (LLC) texel-coordinates.
  - Preconditions: 
  - Postconditions: Block has been translated to (`new_x`, `new_y`).
  - Notes: 
- **`bool needs_removal() const`**
  - Description: Check if block is marked for removal.
  - Preconditions: 
  - Postconditions: Returns `true` if block has been marked for removal, and `false` else.
  - Notes: 
- **`glm::ivec4 xywh() const`**
  - Description: Get coordinates and dimensions of block.
  - Preconditions: 
  - Postconditions: Returns a `glm::ivec4`; `[0]`->x, `[1]`->y, `[2]`->width, `[3]`->height.
  - Notes: 
- **`bool is_inside(int x, int y) const`**
  - Description: Check if a point lies within the block.
  - Preconditions: 
  - Postconditions: Returns `true` if point (`x`, `y`) is inside the block, `false` else.
  - Notes: 
- **`int width() const`**
  - Description: Get the width of the block.
  - Preconditions: 
  - Postconditions: Returns the width of the block in texels.
  - Notes: 
- **`int height() const`**
  - Description: Get the height of the block.
  - Preconditions: 
  - Postconditions: Returns the height of the block in texels.
  - Notes: 

    
**Private Function Members**

N/A

**Public Data Members**

N/A

**Private Data Members**

- `glm::ivec4 xywh_`: Coordinates and dimensions of block
- `bool needs_removal_`: Is block marked for removal?

**Notes**

Todo

### EventLogger ([event_logger.hpp](include/event_logger.hpp), [event_logger.cpp](src/event_logger.cpp))
**Description**

Logs events directly from the `Toolbox` and sorts them by type in 16-deep circular buffers. Used exclusively for debugging.

**Usage**

- Construct object
- Once the events are collected in the `Toolbox`, call `push_events`
- Convert `Pevent`s to strings using `ptos`

**Constructors and Destructors**

- **`EventLogger()`**
- **`EventLogger(const EventLogger&)`**

**Public Function Members**

- **`void push_events(Toolbox&)`**
  - Description: Catch events from `Toolbox`
  - Preconditions: New events have been captured by the `Toolbox`
  - Postconditions: The events have been sorted into their corresponding circular buffer
  - Notes: 


**Non-Member Functions**

- **`std::string ptos(const Pevent&, const Toolbox&)`**
  - Description: Convert a `Pevent` to a `std::string`.
  - Preconditions: 
  - Postconditions: Returns a `std::string` that describes the `Pevent`.
  - Notes: The `Toolbox` argument is used for coordinate transformation.


**Private Function Members**

N/A

**Public Data Members**

- `unsigned i_down, i_up, i_move, i_other`: Index where next event is to be inserted.
- `std::array<Pevent, 16> events_down`: Events of down-type.
- `std::array<Pevent, 16> events_up`: Events of up-type.
- `std::array<Pevent, 16> events_move`: Events of move-type.
- `std::array<Pevent, 16> events_other`: Events of other-type.

**Private Data Members**

N/A

**Notes**

N/A

### GuiHandler ([gui_handler.hpp](include/gui_handler.hpp), [gui_handler.cpp](src/gui_handler.cpp))
**Description**

Draws and controls all functionality related to the GUI.

**Usage**

- Construct object with fraction of screen occupied by the gui
- Call `init` with a `Toolbox` that has a fully initialized `Infrastructure`
- In each frame, call
  - `update` to queue drawing and update state
  - `render` to draw the GUI before swapping screen buffers

**Constructors and Destructors**

- **`GuiHandler(float)`**

**Public Function Members**

- **`void init(Toolbox& tb, const std::string path_img, const std::string path_ttf)`**
  - Description: Initialize all GUI related infrastructure
  - Preconditions: Fully setup `Toolbox`, correct paths to images and fonts
  - Postconditions: Fonts and images have been loaded, ImGui is fully initialized.
  - Notes: 
- **`void update(Toolbox& tb)`**
  - Description: Update the GUI
  - Preconditions: 
  - Postconditions: Tasks performed:
    - Check if application has to quit and handle this
    - Check if there is a new finger that controls the GUI, or if the controlling finger was released
    - Handle any input to the GUI, pass it on to ImGui for processing
    - Construct the GUI
  - Notes: 
- **`void render(Toolbox& tb)`**
  - Description: Render the GUI to the screenbuffer.
  - Preconditions: 
  - Postconditions: The GUI is drawn on the screenbuffer.
  - Notes: 


**Private Function Members**

- **`bool isInGuiWindow_(const Pevent&) const`**
  - Description: Check if a `Pevent` is within the GUI window.
  - Preconditions: 
  - Postconditions: Returns `true` if the `Pevent` is within the GUI window, `false` else.
  - Notes: 
- **`void draw_gui_(Toolbox& tb)`**
  - Description: Construct a semi-old version of the GUI
  - Preconditions: All resources have been loaded
  - Postconditions: 
  - Notes: 
- **`void draw_gui_ft_(Toolbox& tb)`**
  - Description: Construct the GUI used at FocusTerra
  - Preconditions: All resources have been loaded.
  - Postconditions: 
  - Notes: 
- **`void draw_old_gui_(Toolbox& tb)`**
  - Description: Construct the old GUI.
  - Preconditions: All resources have been loaded
  - Postconditions: 
  - Notes: 
- **`void load_button_textures_(const std::string path)`**
  - Description: Load all necessary images into textures.
  - Preconditions: All images can be found in `path`, and they all have the correct format.
  - Postconditions: All images have been uploaded to the GPU as textures and can be accessed with the corresponding private members `btex_*_*`.
  - Notes: 
- **`void load_image_to_texture_(const std::string file, GLuint& texture)`**
  - Description: Load an image (rgba) from file into an OpenGL texture using stbi.
  - Preconditions: The target image has format RGBA
  - Postconditions: The image has been uploaded to the GPU as a texture, and its handle has been copied into the address specified by `texture`
  - Notes: 


**Public Data Members**

N/A

**Private Data Members**

- `float gui_pos_`: Portion of screen occupied by GUI
- `ImGuiIO io_`: ImGui IO object
- `SDL_Event next_event_`: Next event for event chains that span several frames (raising, lowering finger)
- `SDL_FingerID fingerID_`: Finger currently controlling the GUI
- `SDL_TouchID deviceID_`: ID of the currently connected touch device (read: touchscreen)
- `bool lowering_finger_`: Are we in the event chain of lowering a finger?
- `bool raising_finger_`: Are we in the event chain of raising a finger?
- `ImFont* font_`: Font used by ImGui
- `GLuint btex_*_on, btex_*_off`: 12 OpenGL texture handles corresponding to images drawn in GUI
- `EventLogger evlog`: EventLogger, only present while debugging

**Notes**

N/A

### Infrastructure ([infrastructure.hpp](include/infrastructure.hpp), [infrastructure.cpp](src/infrastructure.cpp))
**Description**

Creates and stores the SDL and OpenGL infrastructures (window, renderer, context).

**Usage**

- Default construct object
- Call `init`
- at end of life, call `quit`

**Constructors and Destructors**

- **`Infrastructure(SDL_Window*, SDL_RENDERER*, SDL_GLContext)`**
- **`Infrastructure()`**
- **`Infrastructure(const Infrastructure&)`**

**Public Function Members**

- **`SDL_Window* window() const`**
  - Description: Return the window
  - Preconditions: N/A
  - Postconditions: The window is returned
  - Notes: N/A
- **`SDL_Renderer* renderer() const`**
  - Description: Return the renderer
  - Preconditions: N/A
  - Postconditions: The renderer is returned
  - Notes: N/A
- **`SDL_Context context() const`**
  - Description: Return the context
  - Preconditions: N/A
  - Postconditions: The context is returned
  - Notes: N/A
- **`bool init(const std::string name, const int width, const int height)`**
  - Description: Initialize everything
  - Preconditions: `name` is the window name, `width` and `height` are width and height of the window in pixels
  - Postconditions: An OpenGL context has been created and connected to the `SDL_Window`. The OpenGL functions have been loaded via glad.
  - Notes: N/A
- **`void destroy()`**
  - Description: Destruct all resources
  - Preconditions: N/A
  - Postconditions: All resources have been destroyed
  - Notes: N/A
- **`void quit()`**
  - Description: Quit the application
  - Preconditions: N/A
  - Postconditions: All resources have been destroyed and the application has quit
  - Notes: N/A

**Private Function Members**

N/A

**Public Data Members**

N/A

**Private Data Members**

- `SDL_Window* window_`: Window
- `SDL_Renderer* renderer_`: Renderer
- `SDL_Context context_`: Context


**Notes**

N/A

### InputHandler ([input_handler.hpp](include/input_handler.hpp), [input_handler.cpp](src/input_handler.cpp))
**Description**

Reads all input from SDL, preprocesses it and stores it in the `Toolbox` event chain

**Usage**

- Construct object
- At the beginning of each frame, call `update` to update the `Toolbox` event chain

**Constructors and Destructors**

- **`InputHandler()`**

**Public Function Members**

- **`void update(Toolbox& tb)`**
  - Description: Collect all current SDL events and store them as `Pevent`s in the toolbox `events`
  - Preconditions: N/A
  - Postconditions: The toolbox `events` have been updated
  - Notes: N/A

**Private Function Members**

N/A

**Public Data Members**

N/A

**Private Data Members**

N/A

**Notes**

N/A

### Message ([message.hpp](include/message.hpp), [message.cpp](src/message.cpp))
**Description**

Represents a message to one of the components

**Usage**

- Construct object using a message, e.g. `WAVEMESSAGE::RESET_DAMPING` or `PATTERNMESSAGE::PATTERN_SSH` (see `*MESSAGE` types in [enums](#enums-enumshpp))
- Read messages using the pattern
```c++
Message m (getSomeMessage());
if(m.target == MESSAGETARGET::WAVE){
    WAVEMESSAGE message = std::get<WAVEMESSAGE>(m.message);
    switch(message){
        case WAVEMESSAGE::RESET_WAVE:
            //process RESET_WAVE here
            break;
        case WAVEMESSAGE::RESET_DAMPING:
            //process RESET_DAMPING here
            break;
        default:
            break;
    }
}
```

**Constructors and Destructors**

- **`Message()`**
- **`Message(BLOCKCHAINMESSAGE message)`**
- **`Message(DRAWERMESSAGE message)`**
- **`Message(GUIMESSAGE message)`**
- **`Message(WAVEMESSAGE message)`**
- **`Message(PATTERNMESSAGE message)`**

**Public Function Members**

N/A

**Private Function Members**

N/A

**Public Data Members**

- `MESSAGETARGET target`
- `std::variant<BLOCKCHAINMESSAGE, DRAWERMESSAGE, GUIMESSAGE, WAVEMESSAGE, PATTERNMESSAGE> message`
- `bool handled`

**Private Data Members**

N/A

**Notes**

Access the correct message by first checking the `target`, and then calling `T message = std::get<T>(m.message)`, where `T` is the message type.

### PatternHandler ([pattern_handler.hpp](include/pattern_handler.hpp), [pattern_handler.cpp](src/pattern_handler.cpp))
**Description**

Handles the placement of predefined patterns.

**Usage**

- Construct object
- Call `update` once per frame

**Constructors and Destructors**

- **`PatternHandler()`**
- **`PatternHandler(const PatternHandler&)`**
- **`PatternHandler(Toolbox& tb)`**
  - Notes: This constructor sets up the necessary OpenGL objects and loads the textures

**Public Function Members**

- **`void update(Toolbox& tb)`**
  - Description: Checks the mailbox, and upon requests draws the desired structure into the static damping texture
  - Preconditions: Correctly constructed object
  - Postconditions: All messages concerning patterns have been handled
  - Notes: N/A

**Private Function Members**

- **`bool load_damping_texture_(const Toolbox& tb, const std::string file, GLuint* texture_target)`**
  - Description: Load a damping texture from file, upload it to the GPU and return the texture handler in the `GLuint` out argument.
  - Preconditions: `file` is the texture file without extension, `texture_target` is an out argument
  - Postconditions: The texture has been uploaded to the GPU and has handler `texture_target`
  - Notes: N/A

**Public Data Members**

N/A

**Private Data Members**

- `GLuint texture_*_`

**Notes**

N/A

### Pevent ([pevent.hpp](include/pevent.hpp), [pevent.cpp](src/pevent.cpp))
**Description**

Stores `SDL_Event`s in a more convenient way.

**Usage**

- Use a [`PeventFactory`](#peventfactory-peventhpp-peventcpp) to construct objects of this type

**Constructors and Destructors**

- **`Pevent()`**
- **`Pevent(const SDL_Event&)`**

**Public Function Members**

N/A

**Private Function Members**

N/A

**Public Data Members**

- `SDL_Event event`
- `unsigned itcoord_x, itcoord_y`
- `float fscoord_x, fscoord_y`
- `PEVENTTYPE type`
- `SDL_FingerID finger_id`

**Private Data Members**

N/A

**Notes**

Objects of this type should be constructed by something like the `PeventFactory`.

### PeventFactory ([pevent.hpp](include/pevent.hpp), [pevent.cpp](src/pevent.cpp))
**Description**

Constructs `Pevent` objects.

**Usage**

- Construct object using non-trivial constructor
- call `operator()` to construct a `Pevent` from an `SDL_Event`

**Constructors and Destructors**

- **`PeventFactory()`**
- **`PeventFactory(const int screen_w, const int screen_h, const int texture_w, const int texture_h, const int texoffset_left, const int texoffset_right, const int texoffset_bottom, const int texoffset_top)`**
  - This constructor should be changed to take a `Toolbox` instead.

**Public Function Members**

- **`Pevent operator()(const SDL_Event&) const`**
  - Description: Generate a `Pevent` from and `SDL_Event`
  - Preconditions: N/A
  - Postconditions: Returns a `Pevent` that corresponds to the `SDL_Event` passed as argument.
  - Notes: N/A

**Private Function Members**

N/A

**Public Data Members**

N/A

**Private Data Members**

- `int screen_w_, screen_h_`: screen width and height in pixels
- `int texture_w_, texture_h_`: texture width and height in texels
- `int texoffset_left_, texoffset_right_, texoffset_bottom_, texoffset_top_`: screen offsets in the texture (buffer sizes)

**Notes**

N/A

### Shader ([shader.hpp](include/shader.hpp), [shader.cpp](src/shader.cpp))
**Description**

Represents a GLSL shader.

**Usage**

- Construct object from vertex and fragment shader sources, e.g.
```c++
Shader stepshader((shader_path_ + "stepwave.vert").c_str(), (shader_path_ + "stepwave.frag").c_str());
```
- Make the shader current by calling `use()` (before setting uniforms and rendering)
- Set uniforms using the `set*` functions

**Constructors and Destructors**

- **`Shader()`**
- **`Shader(const char* vertexPath, const char* fragmentPath)`**
  - Notes: This is the correct way to initialize a shader from sources.
- **`Shader(const Shader&)`**
- **`Shader& operator=(const Shader&)`**
- **`~Shader()`**

**Public Function Members**

- **`void clean_up()`**
  - Description: Clean up the OpenGL resources associated with this shader
  - Preconditions: N/A
  - Postconditions: N/A
  - Notes: N/A
- **`void use()`**
  - Description: Activates the shader
  - Preconditions: Correctly constructed object
  - Postconditions: The shader program is used
  - Notes: N/A
- **`void setBool(const std::string& name, bool value) const`**
  - Description: Set a boolean uniform
  - Preconditions: `name` is the name of the target uniform, `value` the target value.
  - Postconditions: The target uniform has been set to `value`
  - Notes: N/A
- **`void setInt(const std::string& name, int value) const`**
  - Description: Set an integer uniform
  - Preconditions: `name` is the name of the target uniform, `value` the target value.
  - Postconditions: The target uniform has been set to `value`
  - Notes: N/A
- **`void setFloat(const std::string& name, float value) const`**
  - Description: Set a float uniform
  - Preconditions: `name` is the name of the target uniform, `value` the target value.
  - Postconditions: The target uniform has been set to `value`
  - Notes: N/A
- **`void setVec2(const std::string& name, glm::vec2 value) const`**
  - Description: Set a vec2 uniform
  - Preconditions: `name` is the name of the target uniform, `value` the target value.
  - Postconditions: The target uniform has been set to `value`
  - Notes: N/A
- **`void setVec3(const std::string& name, glm::vec3 value) const`**
  - Description: Set a vec3 uniform
  - Preconditions: `name` is the name of the target uniform, `value` the target value.
  - Postconditions: The target uniform has been set to `value`
  - Notes: N/A
- **`void setVec4(const std::string& name, glm::vec4 value) const`**
  - Description: Set a vec4 uniform
  - Preconditions: `name` is the name of the target uniform, `value` the target value.
  - Postconditions: The target uniform has been set to `value`
  - Notes: N/A
- **`void setMat(const std::string& name, glm::mat4 value) const`**
  - Description: Set a mat4 uniform
  - Preconditions: `name` is the name of the target uniform, `value` the target value.
  - Postconditions: The target uniform has been set to `value`
  - Notes: N/A

**Private Function Members**

N/A

**Public Data Members**

- `unsigned int ID`: OpenGL handle of the shader program

**Private Data Members**

N/A

**Notes**

N/A

### SlimBlockchainHandler ([slim_blockchain_handler.hpp](include/slim_blockchain_handler.hpp), [slim_blockchain_handler.cpp](src/slim_blockchain_handler.cpp))
**Description**

Handles everything related to rectangular blocks, especially the immediate mode (`Spielen`). 
Drawing is handled in a batched manner: There are eraselists and drawlists that store objects that are to be drawn or erased.
The drawcalls are issued at the very end of the update-cycle, all in one.

**Usage**

- Construct object from a `Toolbox`. Note that the toolbox must be fully initialized.
- Once per frame, call `update`

**Constructors and Destructors**

- **`SlimBlockchainHandler(Toolbox& tb)`**

**Public Function Members**

- **`void update(Toolbox& tb)`**
  - Description: Update the toolbox - first handle messages, then handle events, update erase-/drawlists (dynamic and static) and finally draw the updated state to the dynamic damping and wave 1 textures.
  - Preconditions: Fully initialized object
  - Postconditions: The state has been updated and drawn to the necessary textures
  - Notes: N/A
- **`size_t num_blocks()`**
  - Description: Get the current number of active blocks
  - Preconditions: N/A
  - Postconditions: The number of blocks is returned
  - Notes: N/A

**Private Function Members**

- **`void clear_blocks_()`**
  - Description: Erases all current blocks
  - Preconditions: N/A
  - Postconditions: All blocks have been erased, `dragpairs_` and `blockchain_` are empty
  - Notes: N/A
- **`void update_blocks_(const Toolbox&, bool reload_all)`**
  - Description: Updates the state of the block tracking. First, the draw-/eraselists are checked for duplicated inputs (e.g. draw at R, erase at R, draw at R', erase at R', draw at R'').
    Then the vertices of blocks to be drawn / erased are calculated, and the queues are executed in the order: erase dynamic blocks, draw static blocks, draw dynamic blocks.
  - Preconditions: N/A
  - Postconditions: N/A
  - Notes: N/A
- **`bool in_wave_window_(const Toolbox&, const Pevent&) const`**
  - Description: Check if a `Pevent` is within the wave window
  - Preconditions: N/A
  - Postconditions: Returns `true` if the passed `Pevent` is in the wave window, `false` else
  - Notes: N/A
- **`void xywhs_to_vertices_(const Toolbox&, const std::vector<bool>& duplicates, const std::vector<glm::ivec4>& xywhs, std::vector<float>& vertices) const`**
  - Description: Calculate all vertices corresponding to the `EfficientBlock` `xywh` coordinates stored in `xywhs` and store them in `vertices`, while ignoring `xywhs[i]` if `duplicates[i] == true`. 
  - Preconditions: N/A
  - Postconditions: The vertices corresponding to the non-duplicate marked `xywhs` coordinates have been calculated and are stored in `vertices`. Previous contents of `vertices` have been deleted.
  - Notes: If duplicates are not tracked (e.g. for static blocks, which can't be erased), pass `std::vector<bool>(xywhs.size(), false)` as `duplicates`.
- **`void find_dynamic_duplicates_()`**
  - Description: Find duplicates in the dynamic draw-/eraselists and store them in the members `drawlist_dynamic_duplicates_` and `eraselist_dynamic_duplicates_`, respectively
  - Preconditions: N/A
  - Postconditions: The dynamic duplicate storing members have been updated according to the current dynamic draw-/eraselists
  - Notes: This takes care that one erase can only delete one draw.

**Public Data Members**

N/A

**Private Data Members**

- `int previous_mstate_`: The tb.mstate of the previous frame
- `std::list<EfficientBlock> blockchain_`: list of current `EfficientBlocks`
- `std::list<std::pair<EfficientBlock*, SDL_FingerID> > dragpairs_`: list of blocks and their controlling finger
- `Shader shader_drawblocks_`: Shader used to draw blocks
- `GLuint vao_, vbo_`: OpenGL infrastructure, vertex array object and vertex buffer object
- `GLuint fbo_wave_, fbo_dynamic_, fbo_static_`: framebuffer objects targeting the wave 1 texture, the dynamic damping texture, and the static damping texture, respectively
- `std::vector<glm::ivec4> drawlist_static_`: xywh coordinates of blocks to be drawn to the static damping texture
- `std::vector<glm::ivec4> drawlist_dynamic_`: xywh coordinates of blocks to be drawn to the dynamic damping texture
- `std::vector<glm::ivec4> eraselist_dynamic_`: xywh coordinates of blocks to be erased from the dynamic damping texture
- `std::vector<bool> drawlist_dynamic_duplicates_`: marks which indices of the dynamic drawlist are duplicates (i.e. paired with an entry of the dynamic eraselist)
- `std::vector<bool> eraselist_dynamic_duplicates_`: marks which indices of the dynamic eraselist are duplicates (i.e. paired with an entry of the dynamic drawlist)

**Notes**

One should unify all the framebuffers used over all objects, they could be collected in the `Toolbox`. The same is true for functions that check whether a `Pevent` is in the GUI or in the wave window.
There used to be issues with this class, because duplicates were not tracked / tracked incorrectly. For example, one frame can contain several move commands, e.g. move to R, then move to R'. 
Because erasing is completed before drawing is started, this would leave blocks at R and R', unless the draw and erase at R are marked as net-0x90.

### TimeoutHandler ([timeout_handler.hpp](include/timeout_handler.hpp), [timeout_handler.cpp](src/timeout_handler.cpp))
**Description**

Keeps track of the time since the last user input, and resets the state of the application when a set threshold is surpassed.

**Usage**

- Construct object with the desired timeout
- After the `events` list of the toolbox has been filled, and before anyone else gets access to the toolbox, call `update`

**Constructors and Destructors**

- **`TimeoutHandler(int seconds_to_timeout)`**
  - Notes: This constructs a timeout handler with timeout `seconds_to_timeout`

**Public Function Members**

- **`void update(Toolbox& tb)`**
  - Description: Check how much time has passed since an event has last come in, and if it exceeds the timeout, post reset messages and reset the timer.
  - Preconditions: N/A
  - Postconditions: If the timer exceeds the timeout, a reset has been posted. If `tb.events` is not empty or the timer has exceeded the timeout, the timer has been reset.
  - Notes: The reset messages need to be adjusted if more components are added. Potentially, one could add a messagetarget `ALL`, with a message `RESET` everyone listens to.

**Private Function Members**

N/A

**Public Data Members**

N/A

**Private Data Members**

- `int seconds_to_timeout_`: Number of seconds that constitute a timeout
- `std::chrono::time_point<std::chrono::high_resolution_clock> time_last_input_`: Time of last user input

**Notes**

N/A

### Toolbox ([toolbox.hpp](include/toolbox.hpp), [toolbox.cpp](src/toolbox.cpp))
**Description**

Stores all information needed by several components. Has a mailbox to which messages to other components can be posted and a event chain where user input is stored. 
The Toolbox is passed from one component to the next, so each component has all the tools when it needs to perform a specific task.

**Usage**

- Construct object with all necessary parameters
- Finish initialization by having a `WaveHandler` call `generate_and_transfer_textures` on this object
- At the beginning of every frame, call `newFrame`

**Constructors and Destructors**

- **`Toolbox(const int screen_w, const int screen_h, const int texture_w, const int texture_h, const int texoffset_left, const int texoffset_right, const int texoffset_bottom, const int texoffset_top, const std::string shaderpath, const std::string texturepath, const std::string resourcepath)`**

**Public Function Members**

- **`void newFrame()`**
  - Description: Start a new frame
  - Preconditions: N/A
  - Postconditions: `mailbox` and `events` have been cleared
  - Notes: Call this function at the very beginning of each frame

**Private Function Members**

N/A

**Public Data Members**

Check the source, there are ~50 members and they are well documented.

**Private Data Members**

N/A

**Notes**

For full initialization, this class needs external objects. More precisely, after construction, it needs a `WaveHandler` to call `WaveHandler::generate_and_transfer_textures` on it.
Else the textures stay un-initialized.

### WaveHandler ([wave_handler.hpp](include/wave_handler.hpp), [wave_handler.cpp](src/wave_handler.cpp))
**Description**

Handles simulation and rendering of the wave.

**Usage**

- Construct object
- Call `initialize`
- Initialize the toolbox using `generate_and_transfer_textures`
- In each frame, after the GUI has been updated, call `update`
- Once each module has processed the toolbox, step the wave
  - Call `prepare_step`
  - Then call `step` with the desired number of double steps
- Just before the GUI is rendered, call `render`

**Constructors and Destructors**

- **`WaveHandler(Toolbox&)`**

**Public Function Members**

- **`bool initialize(const std::string damping_file, const std::string palette_file)`**
  - Description: Fully initialize the object (especially shaders, textures, framebuffers and other OpenGL infrastructure)
  - Preconditions: N/A
  - Postconditions: The object is fully initialized
  - Notes: Without a call to this function, the object is not functional.
- **`void update(Toolbox&)`**
  - Description: Handle all messages addressed to this object
  - Preconditions: N/A
  - Postconditions: All relevant messages have been handled
  - Notes: N/A
- **`void prepare_step()`**
  - Description: Prepare for timestepping by combining the dynamic and static damping textures into one texture.
  - Preconditions: N/A
  - Postconditions: The texture `tex_comp_damp_` has been updated
  - Notes: N/A
- **`bool step(Toolbox& tb, const int num_dsteps)`**
  - Description: Perform `num_dsteps` double-timesteps on the wave
  - Preconditions: N/A
  - Postconditions: 2*`num_dsteps` timesteps have been performed and the latest step is stored in `tex_comp_wave_1_`.
  - Notes: Always returns `true`
- **`bool render()`**
  - Description: Render `tex_comp_damp_` and `tex_wave_1_` using the color scheme `tex_palette_` to the current screenbuffer using shader `shdr_2d_`
  - Preconditions: N/A
  - Postconditions: The state has been rendered
  - Notes: Always returns `true`
- **`GLuint get_damping_tex() const`**
  - Description: Get the combined damping texture
  - Preconditions: N/A
  - Postconditions: The combined damping texture handler is returned
  - Notes: N/A
- **`unsigned get_width() const`**
  - Description: Get the window width
  - Preconditions: N/A
  - Postconditions: The window width is returned
  - Notes: N/A
- **`unsigned get_height() const`**
  - Description: Get the window height
  - Preconditions: N/A
  - Postconditions: The window height is returned
  - Notes: N/A
- **`void generate_and_transfer_textures(Toolbox&)`**
  - Description: Generate textures and transfer these and existing textures to the `Toolbox`.
  - Preconditions: N/A
  - Postconditions: Three textures have been generated and initialized correctly: `tb.tex_damp_clean`, `tb.tex_wave_clean`, `tb.tex_const_zero`.
    Four textures have been transferred to the `Toolbox`: `tex_comp_damp_dynamic_`, `tex_comp_damp_static_`, `tex_comp_wave_0_`, `tex_comp_wave_1_`
  - Notes: This function has to be called to fully initialize the `Toolbox`

**Private Function Members**

- **`bool initialize_2D_data_()`**
  - Description: Initialize OpenGL infrastructure to perform timesteps
  - Preconditions: N/A
  - Postconditions: The objects `num_elements_2d`, `vao_2d_`, `vbo_2d_`, `ebo_2d_` have been initialized
  - Notes: N/A
- **`bool initialize_3D_data_()`**
  - Description: Do not call
  - Preconditions: N/A
  - Postconditions: N/A
  - Notes: N/A
- **`bool initialize_comp_data_(const std::string)`**
  - Description: Initialize damping and wave textures, and time stepping framebuffers
  - Preconditions: The argument specifies the damping file, without extension.
  - Postconditions: The vanilla damping profile has been loaded from file, or a backup has been generated in case the file is missing. 
    The damping textures `tex_comp_damp_`, `tex_comp_damp_dynamic_`, `tex_comp_damp_static_` have been generated and initialized. 
    The wave textures `tex_comp_wave_0_` and `tex_comp_wave_1_` have been generated and initialized. 
    The framebuffers `fb_comp_0_`, `fb_comp_1_`, `fb_comp_damp_` have been generated and initialized.
  - Notes: Always returns `true`
- **`bool initialize_render_data_(const std::string)`**
  - Description: Load the colour palette and upload it to the GPU, initialize rendering infrastructure
  - Preconditions: The argument specifies a file where the colour palette texture can be found (without extension)
  - Postconditions: The colour palette has been loaded from file and uploaded to the GPU in texture `tex_palette_`.
    The rendering infrastructure, namely `vao_render_`, `vbo_render_`, `ebo_render_` have been generated and initialized.
  - Notes: Always returns `true`, except when the colour palette file is invalid.
- **`bool initialize_shaders_()`**
  - Description: Initialize all shaders
  - Preconditions: N/A
  - Postconditions: The following shaders have been initialized from source: `shdr_step_`(stepwave), `shdr_2d_`(render2d), `shdr_2d_dbg_`(render2d), `shdr_damp_`(combine_damping) and their uniforms have been set
  - Notes: Always returns `true`
- **`bool load_damping_(const std::string)`**
  - Description: Load a damping texture from file into `tex_damp_data_`
  - Preconditions: The argument specifies a damping file without file extension
  - Postconditions: The damping texture has been loaded into `tex_damp_data_`. On success, `true` has been returned, `false` else.
  - Notes: In the same directory, there needs to be a `.conf` and a `.texture` file with the specified name.
    This function is very inefficient and can be optimized.
- **`bool load_palette_(const std::string)`**
  - Description: Load the colour palette texture from file into `palette_`
  - Preconditions: The argument specifies the palette file without file extension
  - Postconditions: The colour palette texture has been loaded into `palette_`. On success, `true` has been returned, `false` else.
  - Notes: In the same directory, there needs to be a `.conf` and a `.texture` file with the specified name.

**Public Data Members**

N/A

**Private Data Members**
Only relevant members are listed

- `const int width_, height_`: Window dimensions
- `const int texwidth_, texheight_`: Texture dimensions
- `const int texoffset_left_, texoffset_right_, texoffset_bottom_, texoffset_top_`: Offsets in pixels in textures from the screen
- `const std::string shader_path_`: Path to shaders
- `GLuint vbo_2d_, vao_2d_, ebo_2d_, num_elements_2d_`: Timestepping OpenGL infrastructure
- `GLuint vbo_render_, vao_render_, ebo_render_, num_elements_render_`: Rendering OpenGL infrastructure
- `GLuint fb_comp_0_, fb_comp_1_, fb_comp_damp_`: Framebuffers targeting wave texture 0 `tex_comp_wave_0_`, wave texture 1 `tex_comp_wave_1_` and the combined damping texture `tex_comp_damp_`, respectively.
- `GLuint tex_comp_wave_0_, tex_comp_wave_1_`: Wave textures 0 and 1, between which timestepping happens. The latest state is always in `tex_comp_wave_1_`, and the first step of a chain goes from 1 to 0.
- `GLuint tex_comp_damp_`: Combined damping texture
- `GLuint tex_comp_damp_dynamic_, tex_comp_damp_static_`: Dynamic damping texture (for obstacles that are dynamic like "Spielen" blocks) and static damping texture (for static obstacles like drawings and predefined structures)
- `std::vector<float> palette_`: colour palette texture data
- `GLuint tex_palette_`: Colour palette texture handle
- `Shader shdr_step_, shdr_2d_, shdr_2d_dbg_, shdr_damp_`: Shaders used for timestepping, rendering (without and with debugging) and damping combination
- `std::vector<float> tex_wave_data_, tex_damp_data_`: The vanilla wave and damping texture data

**Notes**

This class predates the Toolbox and is not yet well integrated into the flow. All member functions assume the object is fully initialized.

## Enums ([enums.hpp](include/enums.hpp))

### Global States

**`MSTATE`** (Mouse State): `IMMEDIATE` (Spielen), `PLACE`, `DELETE`, `MOVE`, `DRAW` (Zeichnen), `Erase` (Radieren)

**`SSTATE`** (Source State): `RUN`, `STOP`

**`GSTATE`** (Game State): `RUN`, `FREEZE`, `EXIT`

### Message Targets

**`MESSAGETARGET`**: `BLOCKCHAIN`, `DRAWER`, `GUI`, `WAVE`, `PATTERN`

### Message Types

**`BLOCKCHAINMESSAGE`**: `CLEAR`, `PATTERN_SINGLESLIT`, `PATTERN_DOUBLESLIT`, `PATTER_LATTICE`, `PATTERN_WAVEGUIDE`, `PATTERN_SSH`, `PATTERN_FRESNEL`
- Note: `PATTERN_*` messages don't do anything, they are no longer listened for by the `SlimBlockchainHandler`.

**`PATTERNMESSAGE`**: `PATTERN_SINGLESLIT`, `PATTERN_DOUBLESLIT`, `PATTER_LATTICE`, `PATTERN_WAVEGUIDE`, `PATTERN_SSH`, `PATTERN_FRESNEL`

**`DRAWERMESSAGE`**: `CLEAR`

**`GUIMESSAGE`**: n/a

**`WAVEMESSAGE`**: `RESET_WAVE`, `RESET_DAMPING`, `DIMENSION_2D`, `DIMENSION_3D`, `DEBUG_ON`, `DEBUG_OFF`

### Pevent Types

**`PEVENTTYPE`** (Possible `Pevent` types): `DOWN`, `UP`, `MOVE`, `OTHER`

## ImGui Customization
The ImGui library has been customized in the following way:
- **`imgui_widgets.cpp`**:
    - `ImGui::PlotEx`: Removed tooltip
- **`imgui_impl_sdl.h`**:
    - `ImGui_ImplSDL2_Touch_ProcessEvent`: Added declaration
    - `ImGui_ImplSDL2_Touch_UpdateMousePosAndButtons`: Added declaration
- **`imgui_impl_sdl.cpp`**:
    - `ImGui_ImplSDL2_Touch_ProcessEvent`: Added implementation
    - `ImGui_ImplSDL2_Touch_UpdateMousePosAndButtons`: Added implementation
    - `ImGui_ImplSDL2_NewFrame`: Changed to call `ImGui_ImplSDL2_Touch_UpdateMousePosAndButtons` instead of `ImGui_ImplSDL2_UpdateMousePosAndButtons`
- **Notes**:
    - On touch devices, one should generally call `ImGui_ImplSDL2_Touch_ProcessEvent` rather than `ImGui_ImplSDL2_ProcessEvent`
    - To run `ImGui` demos, one must revert the change to `ImGui_ImplSDL2_NewFrame` (see comments).

## GLSL Shaders
### **combine_damping** ([`combine_damping.vert`](shaders/combine_damping.vert), [`combine_damping.frag`](shaders/combine_damping.frag))

This shader takes two damping textures and renders the combination of the two. Combination is performed using `min`.

Layout:
```glsl
layout (location = 0) in vec3 verCoords;
layout (location = 1) in vec2 texCoords;
```

Uniforms:
```glsl
uniform sampler2D tex_damping_static; //static damping
uniform sampler2D tex_damping_dynamic; //dynamic damping
```

### **copy_texture** ([`copy_texture.vert`](shaders/copy_texture.vert), [`copy_texture.frag`](shaders/copy_texture.frag))

This shader copies a `source_texture` to the output

Layout:
```glsl
layout (location = 0) in vec2 verCoords;
layout (location = 1) in vec2 texCoords;
```

Uniforms:
```glsl
uniform sampler2D source_texture;
```

### **draw** ([`draw.vert`](shaders/draw.vert), [`draw.frag`](shaders/draw.frag))

This shader is used to draw, in the sense of "Zeichnen" and "Radieren".

Layout:
```glsl
layout (location = 0) in vec3 verCoords;
```

Uniforms:
```glsl
uniform sampler2D source_texture;
```

### **draw_blocks** ([`draw_blocks.vert`](shaders/draw_blocks.vert), [`draw_blocks.frag`](shaders/draw_blocks.frag))

This shader is used to draw blocks (see `SlimBlockchainHandler`).

Layout:
```glsl
layout (location = 0) in vec2 verCoords;
layout (location = 1) in vec2 texCoords;
```

Uniforms:
```glsl
uniform float color_multiplier;
uniform sampler2D source_texture;
```

### **render2d** ([`render2d.vert`](shaders/render2d.vert), [`render2d.frag`](shaders/render2d.frag))

This shader is used to render the current wave state with a custom colour palette, along with the current damping.

Layout:
```glsl
layout (location = 0) in vec3 verCoords;
layout (location = 1) in vec2 texCoords;
```

Uniforms:
```glsl
uniform sampler2D tex_wave; //wave
uniform sampler2D tex_damp; //damping
uniform sampler1D tex_palette; //colour palette
```

### **stepwave** ([`stepwave.vert`](shaders/stepwave.vert), [`stepwave.frag`](shaders/stepwave.frag))

This shader takes an input wave and damping texture, and renders the state of the wave one timestep in the future.

Layout:
```glsl
layout (location = 0) in vec3 verCoords;
layout (location = 1) in vec2 texCoords;
```

Uniforms:
```glsl
uniform float dx;
uniform float dy;
uniform float c1;
uniform float c2;
uniform float t;
uniform float amplitude;
uniform float frequency;
uniform sampler2D tex_wave;
uniform sampler2D tex_damp;
```

## Workflow: Sample `main` function
```c++
#include <glad/glad.h>
#include <SDL.h>
#include <toolbox.hpp>
#include <wave_handler.hpp>
#include <infrastructure.hpp>
#include <iostream>
#include <input_handler.hpp>
#include <gui_handler.hpp>
#include <slim_blockchain_handler.hpp>
#include <drawing_handler.hpp>
#include <chrono>
#include <thread>
#include <pattern_handler.hpp>
#include <timeout_handler.hpp>

/*Screen resolution*/
#define WIDTH 3840
#define HEIGHT 2160


int main(int argc, char** argv) {
#ifndef NDEBUG
	std::cout << "DEBUGGING" << std::endl;
#endif

	/*Paths*/
    std::string top_path = "C:\\Users\\Executor\\Desktop\\ft_top\\";

	//Derived paths
	std::string rsc_path = top_path + "resource\\"; //resources top path
	std::string img_path = rsc_path + "images\\"; //images for GUI
	std::string tex_path = rsc_path + "textures\\rocket\\"; //textures
	std::string font_path = top_path + "fonts\\"; //fonts
	std::string shd_path = top_path + "shaders\\"; //shaders

	//Expected texture dimensions
	int tex_offscreen_left = 0;
	int tex_offscreen_right = 600;
	int tex_offscreen_bottom = 600;
	int tex_offscreen_top = 600;
	int texwidth = WIDTH + tex_offscreen_left + tex_offscreen_right;
	int texheight = HEIGHT + tex_offscreen_bottom + tex_offscreen_top;

    //First construct a Toolbox and a WaveHandler
	Toolbox tb(WIDTH, HEIGHT, texwidth, texheight, tex_offscreen_left, tex_offscreen_right, 
                tex_offscreen_bottom, tex_offscreen_top, shd_path, tex_path, rsc_path);
	WaveHandler waves(tb);
	waves.initialize(tex_path + "bare", rsc_path + "ft_palette");

    //Finish Toolbox initialization using the WaveHandler
	waves.generate_and_transfer_textures(tb);

    //Now construct the other modules
	InputHandler ioHandler;
	GuiHandler guiHandler(0.15f);
	guiHandler.init(tb, img_path, font_path);
	SlimBlockchainHandler bch(tb);
	DrawingHandler drah(tb);
	PatternHandler paha(tb);
	TimeoutHandler tiha(600);
	
	//Scale Gui
	ImGui::GetStyle().ScaleAllSizes(2.f);

    //Game Loop
	while (tb.g_state != static_cast<int>(GSTATE::EXIT)) {

		//Start of new frame
		//Clear Toolbox
		tb.newFrame();

		//I/O Handler update
		ioHandler.update(tb);

		//Timeout Handler update
		tiha.update(tb);

		//Gui Handler
		guiHandler.update(tb);

		//Waves Handler update
		waves.update(tb);

        /*Perform updates that may alter the damping textures*/
		//Blockchain Handler update
		bch.update(tb);

		//Drawing Handler update
		drah.update(tb);

		//Pattern Handler update
		paha.update(tb);

        /*Damping textures are final, now we can step the wave*/
		//Wave Handler stepping
		waves.prepare_step();
		waves.step(tb, 6);

        /*Finally, we render first the wave and then the GUI on top*/
		//Wave Handler rendering
		waves.render();

		//Gui Handler rendering
		guiHandler.render(tb);

		//Swap Windows
		SDL_GL_SwapWindow(tb.infra.window());

		//Check for OpenGL errors
#ifndef NDEBUG
		GLint err = glGetError();
		if (err != GL_NO_ERROR) {
			std::cout << "Error Code: " << err << std::endl;
			std::cout << "GL_NO_ERROR: " << GL_NO_ERROR << std::endl;
			std::cout << "GL_INVALID_ENUM: " << GL_INVALID_ENUM << std::endl;
			std::cout << "GL_INVALID_VALUE: " << GL_INVALID_VALUE << std::endl;
			std::cout << "GL_INVALID_OPERATION: " << GL_INVALID_OPERATION << std::endl;
			std::cout << "GL_INVALID_FRAMEBUFFER_OPERATION: " << GL_INVALID_FRAMEBUFFER_OPERATION << std::endl;
			std::cout << "GL_OUT_OF_MEMORY: " << GL_OUT_OF_MEMORY << std::endl;
		}

		//Potential delay for single frame debugging
		//std::this_thread::sleep_for(std::chrono::milliseconds(1000));
#endif
	}

	return 0;
}
```