vertex buffer object class for adding attribute data to gpu
This commit is contained in:
parent
25e2a7ad4f
commit
cdf4b8ce0e
|
@ -47,7 +47,7 @@
|
|||
"enabled": true,
|
||||
"json-save": true,
|
||||
"json-save-directory": "local/scans",
|
||||
"barcode": "045496591922",
|
||||
"barcode": "037600110754",
|
||||
"capture-device": "/dev/video0"
|
||||
},
|
||||
"api":
|
||||
|
|
2
lib/sb
2
lib/sb
|
@ -1 +1 @@
|
|||
Subproject commit 3baaa7624e42880a47d55b2e659038019131ee02
|
||||
Subproject commit 3e5e0fcbb8aedd5c4ce15aa850e88511af17ad5e
|
178
src/Pudding.cpp
178
src/Pudding.cpp
|
@ -92,30 +92,30 @@ void Pudding::set_pudding_model(
|
|||
/* triangle that includes top two vertices and first base vertex */
|
||||
start_vertex = &layer_top_ring[ii];
|
||||
end_vertex = &layer_top_ring[(ii + 1) % layer_top_ring.size()];
|
||||
pudding_attributes["vertices"].add(start_vertex->x, layer_top_y, start_vertex->y);
|
||||
pudding_attributes["position"].add(start_vertex->x, layer_top_y, start_vertex->y);
|
||||
pudding_attributes["uv"].add(ring_start_vertex_u, layer_top_percent);
|
||||
pudding_attributes["vertices"].add(end_vertex->x, layer_top_y, end_vertex->y);
|
||||
pudding_attributes["position"].add(end_vertex->x, layer_top_y, end_vertex->y);
|
||||
pudding_attributes["uv"].add(ring_start_vertex_u + u_step, layer_top_percent);
|
||||
pudding_attributes["color"].extend(*layer_top_color, 2);
|
||||
pudding_attributes["vertices"].add(layer_base_ring[ii].x, layer_base_y, layer_base_ring[ii].y);
|
||||
pudding_attributes["position"].add(layer_base_ring[ii].x, layer_base_y, layer_base_ring[ii].y);
|
||||
pudding_attributes["uv"].add(ring_start_vertex_u, layer_base_percent);
|
||||
pudding_attributes["color"].add(*layer_bottom_color);
|
||||
/* triangle that includes bottom two vertices and second top vertex */
|
||||
start_vertex = &layer_base_ring[ii];
|
||||
pudding_attributes["vertices"].add(start_vertex->x, layer_base_y, start_vertex->y);
|
||||
pudding_attributes["position"].add(start_vertex->x, layer_base_y, start_vertex->y);
|
||||
pudding_attributes["uv"].add(ring_start_vertex_u, layer_base_percent);
|
||||
pudding_attributes["colors"].add(*layer_bottom_color);
|
||||
pudding_attributes["vertices"].add(end_vertex->x, layer_top_y, end_vertex->y);
|
||||
pudding_attributes["color"].add(*layer_bottom_color);
|
||||
pudding_attributes["position"].add(end_vertex->x, layer_top_y, end_vertex->y);
|
||||
pudding_attributes["uv"].add(ring_start_vertex_u + u_step, layer_top_percent);
|
||||
pudding_attributes["color"].add(*layer_top_color);
|
||||
end_vertex = &layer_base_ring[(ii + 1) % layer_base_ring.size()];
|
||||
pudding_attributes["vertices"].add(end_vertex->x, layer_base_y, end_vertex->y);
|
||||
pudding_attributes["position"].add(end_vertex->x, layer_base_y, end_vertex->y);
|
||||
pudding_attributes["uv"].add(ring_start_vertex_u + u_step, layer_base_percent);
|
||||
pudding_attributes["color"].add(*layer_bottom_color);
|
||||
ring_start_vertex_u += u_step;
|
||||
}
|
||||
}
|
||||
pudding_triangle_vertex_count = pudding_attributes["vertices"].count();
|
||||
pudding_triangle_vertex_count = pudding_attributes["position"].count();
|
||||
/* process the top and bottom of pudding, filling each face with a triangle fan */
|
||||
float y = max_y;
|
||||
const glm::vec3* face_color = &PUDDING_BROWN;
|
||||
|
@ -123,7 +123,7 @@ void Pudding::set_pudding_model(
|
|||
for (float radius : {top_radius, base_radius})
|
||||
{
|
||||
/* first point in a GL_TRIANGLE_FAN is the center */
|
||||
pudding_attributes["vertices"].add(0.0f, y, 0.0f);
|
||||
pudding_attributes["position"].add(0.0f, y, 0.0f);
|
||||
pudding_attributes["uv"].add(0.0f, 0.0f);
|
||||
layer_top_ring.clear();
|
||||
sb::points_on_circle(layer_top_ring, ring_vertex_count, radius);
|
||||
|
@ -132,22 +132,25 @@ void Pudding::set_pudding_model(
|
|||
{
|
||||
start_vertex = &layer_top_ring[ii];
|
||||
/* for GL_TRIANGLE_FAN we just need to add an outer vertex */
|
||||
pudding_attributes["vertices"].add(start_vertex->x, y, start_vertex->y);
|
||||
pudding_attributes["position"].add(start_vertex->x, y, start_vertex->y);
|
||||
pudding_attributes["uv"].add(*start_vertex);
|
||||
/* connect the ring on the last vertex */
|
||||
if (ii == layer_top_ring.size() - 1)
|
||||
{
|
||||
end_vertex = &layer_top_ring[(ii + 1) % layer_top_ring.size()];
|
||||
pudding_attributes["vertices"].add(end_vertex->x, y, end_vertex->y);
|
||||
pudding_attributes["position"].add(end_vertex->x, y, end_vertex->y);
|
||||
pudding_attributes["uv"].add(*end_vertex);
|
||||
}
|
||||
}
|
||||
/* single color for the entire layer_top_ring */
|
||||
pudding_attributes["colors"].extend(*face_color, layer_top_ring.size() + 2);
|
||||
pudding_attributes["color"].extend(*face_color, layer_top_ring.size() + 2);
|
||||
y = min_y;
|
||||
face_color = &PUDDING_YELLOW;
|
||||
}
|
||||
pudding_fan_vertex_count = (pudding_attributes["vertices"].count() - pudding_triangle_vertex_count) / 2;
|
||||
pudding_fan_vertex_count = (pudding_attributes["position"].count() - pudding_triangle_vertex_count) / 2;
|
||||
pudding_attributes["position"].index(0);
|
||||
pudding_attributes["color"].index(1);
|
||||
pudding_attributes["uv"].index(2);
|
||||
}
|
||||
|
||||
/* Create GL context via super class and load vertices, UV data, and shaders */
|
||||
|
@ -184,7 +187,6 @@ void Pudding::load_gl_context()
|
|||
* will be copied in one after the other, offset to after the previous data location. The same buffer offset will
|
||||
* be passed to the vertex attributes for each data. */
|
||||
vbo.generate();
|
||||
vbo.target(GL_ARRAY_BUFFER);
|
||||
vbo.bind();
|
||||
/* Load two shader programs, one for rendering the flat objects, and one for rendering the 3D model. Load and configure
|
||||
* the flat shader program first. */
|
||||
|
@ -193,46 +195,27 @@ void Pudding::load_gl_context()
|
|||
flat_program = glCreateProgram();
|
||||
glAttachShader(flat_program, vertex_shader);
|
||||
glAttachShader(flat_program, fragment_shader);
|
||||
glBindAttribLocation(flat_program, rectangle_attributes["position"].index(), "in_position");
|
||||
glBindAttribLocation(flat_program, rectangle_attributes["uv"].index(), "vertex_uv");
|
||||
glBindAttribLocation(flat_program, rectangle_attributes["position"], "in_position");
|
||||
glBindAttribLocation(flat_program, rectangle_attributes["uv"], "vertex_uv");
|
||||
/* load, configure and link the 3D world program */
|
||||
vertex_shader = load_shader("src/mvp.vert", GL_VERTEX_SHADER);
|
||||
fragment_shader = load_shader("src/mvp.frag", GL_FRAGMENT_SHADER);
|
||||
mvp_program = glCreateProgram();
|
||||
glAttachShader(mvp_program, vertex_shader);
|
||||
glAttachShader(mvp_program, fragment_shader);
|
||||
glBindAttribLocation(mvp_program, 2, "in_position");
|
||||
glBindAttribLocation(mvp_program, 3, "in_color");
|
||||
glBindAttribLocation(mvp_program, 4, "vertex_uv");
|
||||
glBindAttribLocation(mvp_program, pudding_attributes["position"], "in_position");
|
||||
glBindAttribLocation(mvp_program, pudding_attributes["color"], "in_color");
|
||||
glBindAttribLocation(mvp_program, pudding_attributes["uv"], "vertex_uv");
|
||||
sb::Log::gl_errors("after loading shaders");
|
||||
/* allocate space for vertices, UV and colors, and copy rectangle vertices in at initialization */
|
||||
GLsizeiptr vbo_size = rectangle_attributes["position"].size() + rectangle_attributes["uv"].size() + pudding_attributes["uv"].size() +
|
||||
pudding_attributes["vertices"].size() + pudding_attributes["colors"].size();
|
||||
glBufferData(GL_ARRAY_BUFFER, vbo_size, rectangle_attributes["position"], GL_STATIC_DRAW);
|
||||
/* specify the rectangle vertex attributes as consecutive 2D float coords */
|
||||
glVertexAttribPointer(rectangle_attributes["position"].index(), rectangle_attributes["position"].dimensions(),
|
||||
rectangle_attributes["position"].type(), GL_FALSE, 0, nullptr);
|
||||
/* copy rectangle UV data into the VBO, offset to after the vertex data, set up attributes */
|
||||
GLintptr offset = rectangle_attributes["position"].size();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, offset, rectangle_attributes["uv"].size(), rectangle_attributes["uv"]);
|
||||
glVertexAttribPointer(rectangle_attributes["uv"].index(), rectangle_attributes["uv"].dimensions(),
|
||||
rectangle_attributes["uv"].type(), GL_FALSE, 0, reinterpret_cast<GLvoid*>(offset));
|
||||
/* copy pudding vertices into VBO, offset to after the rectangle UV, and set up vertex attributes for 3D */
|
||||
offset += rectangle_attributes["uv"].size();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, offset, pudding_attributes["vertices"].size(), pudding_attributes["vertices"]);
|
||||
glVertexAttribPointer(2, pudding_attributes["vertices"].dimensions(), pudding_attributes["vertices"].type(),
|
||||
GL_FALSE, 0, reinterpret_cast<GLvoid*>(offset));
|
||||
/* copy pudding color values into VBO, offset to after pudding vertices and set as 3D */
|
||||
offset += pudding_attributes["vertices"].size();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, offset, pudding_attributes["colors"].size(), pudding_attributes["colors"]);
|
||||
glVertexAttribPointer(3, pudding_attributes["colors"].dimensions(), pudding_attributes["colors"].type(),
|
||||
GL_FALSE, 0, reinterpret_cast<GLvoid*>(offset));
|
||||
/* copy pudding UV values into VBO, offset to after pudding color vertices and set as 2D */
|
||||
offset += pudding_attributes["colors"].size();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, offset, pudding_attributes["uv"].size(), pudding_attributes["uv"]);
|
||||
glVertexAttribPointer(4, pudding_attributes["uv"].dimensions(), pudding_attributes["uv"].type(),
|
||||
GL_FALSE, 0, reinterpret_cast<GLvoid*>(offset));
|
||||
sb::Log::gl_errors("after loading attributes");
|
||||
/* Fill VBO with attribute data */
|
||||
vbo.allocate(rectangle_attributes["position"].size() + rectangle_attributes["uv"].size() + pudding_attributes["uv"].size() +
|
||||
pudding_attributes["position"].size() + pudding_attributes["color"].size(), GL_STATIC_DRAW);
|
||||
vbo.add(rectangle_attributes["position"]);
|
||||
vbo.add(rectangle_attributes["uv"]);
|
||||
vbo.add(pudding_attributes["uv"]);
|
||||
vbo.add(pudding_attributes["position"]);
|
||||
vbo.add(pudding_attributes["color"]);
|
||||
sb::Log::gl_errors("after filling VBO");
|
||||
/* link shaders */
|
||||
link_shader(flat_program);
|
||||
link_shader(mvp_program);
|
||||
|
@ -762,10 +745,11 @@ void Pudding::update()
|
|||
glUseProgram(flat_program);
|
||||
glUniform1f(flat_time_uniform_location, time_seconds);
|
||||
/* disable pudding attributes and enable rectangle attributes */
|
||||
glDisableVertexAttribArray(2);
|
||||
glDisableVertexAttribArray(3);
|
||||
glEnableVertexAttribArray(rectangle_attributes["position"].index());
|
||||
glEnableVertexAttribArray(rectangle_attributes["uv"].index());
|
||||
glDisableVertexAttribArray(pudding_attributes["position"]);
|
||||
glDisableVertexAttribArray(pudding_attributes["color"]);
|
||||
glDisableVertexAttribArray(pudding_attributes["uv"]);
|
||||
glEnableVertexAttribArray(rectangle_attributes["position"]);
|
||||
glEnableVertexAttribArray(rectangle_attributes["uv"]);
|
||||
glUniform1i(flat_texture_uniform_location, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
tiles[current_tile_index].bind();
|
||||
|
@ -787,19 +771,19 @@ void Pudding::update()
|
|||
/* pass the mvp matrix to the shader */
|
||||
glUniformMatrix4fv(mvp_uniform_location, 1, GL_FALSE, &mvp[0][0]);
|
||||
/* disable rectangle attributes and enable pudding attributes */
|
||||
glDisableVertexAttribArray(rectangle_attributes["position"].index());
|
||||
glDisableVertexAttribArray(rectangle_attributes["uv"].index());
|
||||
glEnableVertexAttribArray(2);
|
||||
glDisableVertexAttribArray(rectangle_attributes["position"]);
|
||||
glDisableVertexAttribArray(rectangle_attributes["color"]);
|
||||
glEnableVertexAttribArray(pudding_attributes["position"]);
|
||||
if (items.size() == 0)
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glEnableVertexAttribArray(3);
|
||||
glEnableVertexAttribArray(pudding_attributes["color"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glEnableVertexAttribArray(3);
|
||||
glEnableVertexAttribArray(4);
|
||||
glEnableVertexAttribArray(pudding_attributes["color"]);
|
||||
glEnableVertexAttribArray(pudding_attributes["uv"]);
|
||||
GLuint pudding_texture_location = glGetUniformLocation(mvp_program, "pudding_texture");
|
||||
glUniform1i(pudding_texture_location, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
@ -825,8 +809,9 @@ void Pudding::update()
|
|||
/* switch to flat shader for item and camera */
|
||||
glUseProgram(flat_program);
|
||||
/* disable pudding attributes and enable rectangle attributes */
|
||||
glDisableVertexAttribArray(2);
|
||||
glDisableVertexAttribArray(3);
|
||||
glDisableVertexAttribArray(pudding_attributes["position"]);
|
||||
glDisableVertexAttribArray(pudding_attributes["color"]);
|
||||
glDisableVertexAttribArray(pudding_attributes["uv"]);
|
||||
glEnableVertexAttribArray(rectangle_attributes["position"].index());
|
||||
glEnableVertexAttribArray(rectangle_attributes["uv"].index());
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
@ -909,32 +894,46 @@ void vao_deleter(GLuint* id)
|
|||
glDeleteVertexArrays(1, id);
|
||||
}
|
||||
|
||||
Buffer::Buffer() : GLObject(buffer_deleter) {}
|
||||
Buffer::Buffer() : Buffer(GL_INVALID_ENUM) {}
|
||||
|
||||
/* Forward the GL generate function to the base class */
|
||||
Buffer::Buffer(GLenum target) : GLObject(buffer_deleter), buffer_target(target) {}
|
||||
|
||||
/* Forward the GL generate function to the base class. */
|
||||
void Buffer::generate()
|
||||
{
|
||||
GLObject::generate(glGenBuffers);
|
||||
}
|
||||
|
||||
/* Set the type of data being held in this buffer */
|
||||
/* Set the target for this buffer. */
|
||||
void Buffer::target(GLenum target)
|
||||
{
|
||||
buffer_target = target;
|
||||
}
|
||||
|
||||
/* Return the type of data being held in this buffer as a GLenum */
|
||||
/* Return the GL enum for target */
|
||||
GLenum Buffer::target() const
|
||||
{
|
||||
return buffer_target;
|
||||
}
|
||||
|
||||
/* Bind this Buffer to the current GL context */
|
||||
/* Bind this Buffer to the current GL context. An exception will be thrown if the target has not
|
||||
* been set. */
|
||||
void Buffer::bind() const
|
||||
{
|
||||
if (target() == GL_INVALID_ENUM)
|
||||
{
|
||||
throw std::invalid_argument("target must be set before binding buffer");
|
||||
}
|
||||
glBindBuffer(target(), id());
|
||||
}
|
||||
|
||||
/* Set the target and bind the buffer. */
|
||||
void Buffer::bind(GLenum target)
|
||||
{
|
||||
this->target(target);
|
||||
bind();
|
||||
}
|
||||
|
||||
/* This function gets passed to the abstract base class for deleting the Buffer data when the ID
|
||||
* pointer goes out of scope (when all instances of this Buffer and its copies are out of scope) */
|
||||
void buffer_deleter(GLuint* id)
|
||||
|
@ -943,3 +942,54 @@ void buffer_deleter(GLuint* id)
|
|||
SDL_Log("destroying buffer ID %i", *id);
|
||||
glDeleteBuffers(1, id);
|
||||
}
|
||||
|
||||
/* Initialize a Vertex Buffer Object. The base class will be initalized with a target of
|
||||
* GL_ARRAY_BUFFER. */
|
||||
VBO::VBO() : Buffer(GL_ARRAY_BUFFER) {}
|
||||
|
||||
/* Allocate size bytes of vertex attribute memory on the GPU. Usage should be one of GL_STREAM_DRAW,
|
||||
* GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, GL_DYNAMIC_DRAW,
|
||||
* GL_DYNAMIC_READ, or GL_DYNAMIC_COPY. The memory will be uninitialized. */
|
||||
void VBO::allocate(GLsizeiptr size, GLenum usage)
|
||||
{
|
||||
glBufferData(target(), size, nullptr, usage);
|
||||
/* Debug */
|
||||
std::ostringstream message;
|
||||
message << "After allocating memory for " << *this;
|
||||
sb::Log::gl_errors(message.str());
|
||||
}
|
||||
|
||||
/* Set memory in the GPU buffer to the values of the attribute data using glBufferSubData. The memory
|
||||
* set is a contiguous area from the object's current byte offset value to the offset plus the size in
|
||||
* bytes of the attributes. After the memory is set, the offset is set to the end of the area.
|
||||
*
|
||||
* Define an array of vertex attribute data on the GPU by passing the attributes's index, dimensions,
|
||||
* normalization state, and type to glVertexAttribPointer, along with the buffer object's current
|
||||
* offset. */
|
||||
void VBO::add(sb::Attributes& attributes)
|
||||
{
|
||||
/* Set memory */
|
||||
glBufferSubData(target(), offset, attributes.size(), attributes);
|
||||
/* Debug */
|
||||
std::ostringstream initialization_message;
|
||||
initialization_message << "After setting " << attributes.size() << "bytes in " << *this;
|
||||
sb::Log::gl_errors(initialization_message.str());
|
||||
/* Define array */
|
||||
glVertexAttribPointer(
|
||||
attributes.index(), attributes.dimensions(), attributes.type(), attributes.normalized(), 0, reinterpret_cast<GLvoid*>(offset));
|
||||
/* Debug */
|
||||
std::ostringstream pointer_message;
|
||||
pointer_message << "After defining attribute pointer for <Attributes (" << attributes.dimensions() << "D, id: " <<
|
||||
attributes.index() << ", size:" << attributes.size() << ")>";
|
||||
sb::Log::gl_errors(pointer_message.str());
|
||||
/* Increase offset */
|
||||
offset += attributes.size();
|
||||
}
|
||||
|
||||
/* Overload the stream operator to support adding the attributes in a VBO. Add each attributes object to
|
||||
* the output stream. */
|
||||
std::ostream& operator<<(std::ostream& out, const VBO& vbo)
|
||||
{
|
||||
out << "<Vertex Buffer Object (id: " << vbo.id() << ")>";
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <functional>
|
||||
#include <curl/curl.h>
|
||||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
|
@ -62,32 +64,45 @@ class Buffer : public GLObject
|
|||
|
||||
private:
|
||||
|
||||
GLenum buffer_target, buffer_usage;
|
||||
std::uint32_t buffer_add_use_count = 0, buffer_calculated_size = 0;
|
||||
GLenum buffer_target = GL_INVALID_ENUM;
|
||||
|
||||
protected:
|
||||
|
||||
GLenum target() const;
|
||||
|
||||
public:
|
||||
|
||||
Buffer();
|
||||
Buffer(GLenum, GLenum);
|
||||
|
||||
void generate();
|
||||
Buffer(GLenum);
|
||||
void target(GLenum);
|
||||
GLenum target() const;
|
||||
void generate();
|
||||
void bind() const;
|
||||
void allocate(GLsizeiptr);
|
||||
void allocate(GLenum, GLenum, GLsizeiptr);
|
||||
|
||||
template<typename T>
|
||||
sb::Attributes add(VAO& vao, std::vector<T> vertex_attributes)
|
||||
{
|
||||
vao.increment();
|
||||
// glVertexAttribPointer(vao.counted(),
|
||||
}
|
||||
void bind(GLenum);
|
||||
|
||||
};
|
||||
|
||||
void buffer_deleter(GLuint*);
|
||||
|
||||
class VBO;
|
||||
|
||||
std::ostream& operator<<(std::ostream&, const VBO&);
|
||||
|
||||
class VBO : public Buffer
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
GLintptr offset = 0;
|
||||
|
||||
public:
|
||||
|
||||
VBO();
|
||||
void allocate(GLsizeiptr, GLenum);
|
||||
void add(sb::Attributes&);
|
||||
friend std::ostream& operator<<(std::ostream&, const VBO&);
|
||||
|
||||
};
|
||||
|
||||
class Pudding : public Game
|
||||
{
|
||||
|
||||
|
@ -134,7 +149,7 @@ private:
|
|||
flat_time_uniform_location, scroll_uniform_location;
|
||||
glm::mat4 projection, model = glm::mat4(1.0f), mvp;
|
||||
std::map<std::string, sb::Attributes> rectangle_attributes, pudding_attributes = {
|
||||
{"vertices", sb::Attributes()},
|
||||
{"position", sb::Attributes()},
|
||||
{"uv", sb::Attributes()},
|
||||
{"color", sb::Attributes()}
|
||||
};
|
||||
|
@ -144,7 +159,7 @@ private:
|
|||
Texture capture_texture_front_buffer, capture_texture_back_buffer;
|
||||
Texture& capture_texture = capture_texture_front_buffer;
|
||||
VAO vao;
|
||||
Buffer vbo;
|
||||
VBO vbo, other_vbo;
|
||||
|
||||
void set_pudding_model(float, float, int, int = 1, float = -1, float = 1, float = 0.3f);
|
||||
void load_gl_context();
|
||||
|
@ -183,12 +198,53 @@ class Plane : public Model
|
|||
{
|
||||
};
|
||||
|
||||
class Billboard : public Plane
|
||||
/* Apply force until reaching a threshold. Use a connection object to run user functions
|
||||
* when force reaches threshold and when force goes below threshold. */
|
||||
class Button
|
||||
{
|
||||
/* threshold */
|
||||
/* force */
|
||||
/* close */
|
||||
/* open */
|
||||
/* apply */
|
||||
/* remove */
|
||||
/* weighted depression rate */
|
||||
/* Animation (?) */
|
||||
};
|
||||
|
||||
class Pad
|
||||
{
|
||||
};
|
||||
|
||||
class Button : public Billboard
|
||||
/* An abstract base class of an object in a state of either connected or not connected.
|
||||
* When the state changes, functions that must be overriden by a derived class are run,
|
||||
* one for each state change: from on to off, and from off to on. */
|
||||
class Connection
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
enum State
|
||||
{
|
||||
STATE_DISCONNECTED,
|
||||
STATE_CONNECTED
|
||||
};
|
||||
State connection_state = STATE_DISCONNECTED;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void on_connect() = 0;
|
||||
virtual void on_disconnect() = 0;
|
||||
|
||||
public:
|
||||
|
||||
Connection() {}
|
||||
State state() { return connection_state; }
|
||||
void connect() { if (state() != STATE_CONNECTED) { connection_state = STATE_CONNECTED; on_connect(); } }
|
||||
void disconnect() { if (state() != STATE_DISCONNECTED) { connection_state = STATE_DISCONNECTED; on_disconnect(); } }
|
||||
void toggle() { if (state() == STATE_CONNECTED) disconnect(); else connect(); }
|
||||
bool connected() { return connection_state == STATE_DISCONNECTED ? false : true; }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue