diff --git a/Makefile b/Makefile index dd82303..90d5979 100644 --- a/Makefile +++ b/Makefile @@ -47,9 +47,9 @@ CREATE_FONT_SYMLINK := ln -nsf $(SB_DIR)"BPmono.ttf" . SDL_CFLAGS = $(shell $(SDLCONFIG) --cflags) SDL_LFLAGS := $(shell $(SDLCONFIG) --libs) SB_H_FILES := $(wildcard $(addprefix $(SB_SRC_DIR),*.hpp)) -SB_O_FILES := $(filter-out $(addprefix $(SB_SRC_DIR),filesystem.o),$(SB_H_FILES:.hpp=.o)) +SB_O_FILES := $(filter-out $(addprefix $(SB_SRC_DIR),filesystem.o Connection.o Carousel.o),$(SB_H_FILES:.hpp=.o)) SRC_H_FILES := $(wildcard $(addprefix $(SRC_DIR),*.hpp)) -SRC_O_FILES := $(filter-out $(addprefix $(SRC_DIR),Carousel.o),$(SRC_H_FILES:.hpp=.o)) +SRC_O_FILES := $(SRC_H_FILES:.hpp=.o) ##################################################################### # Targets for building [SPACE BOX], dependencies and project source # @@ -78,8 +78,8 @@ $(SB_SRC_DIR)GLObject.o : $(addprefix $(SB_SRC_DIR),Log.hpp) $(SB_SRC_DIR)Texture.o : $(addprefix $(SB_SRC_DIR),GLObject.hpp filesystem.hpp Log.hpp) $(SB_SRC_DIR)VBO.o : $(addprefix $(SB_SRC_DIR),Log.hpp GLObject.hpp Attributes.hpp extension.hpp) $(SB_SRC_DIR)Attributes.o : $(addprefix $(SB_SRC_DIR),Log.hpp extension.hpp) -$(SRC_DIR)Model.o : $(addprefix $(SB_SRC_DIR),extension.hpp Attributes.hpp Texture.hpp utility.hpp) $(addprefix $(SRC_DIR),Carousel.hpp) -$(SRC_DIR)Item.o : $(addprefix $(SB_SRC_DIR),Texture.hpp Log.hpp utility.hpp) $(addprefix $(SRC_DIR),Model.hpp Carousel.hpp) +$(SB_SRC_DIR)Model.o : $(addprefix $(SB_SRC_DIR),extension.hpp Attributes.hpp Texture.hpp utility.hpp Carousel.hpp) +$(SRC_DIR)Item.o : $(addprefix $(SB_SRC_DIR),Texture.hpp Log.hpp utility.hpp Model.hpp Carousel.hpp) $(SRC_DIR)Pudding.o : $(SRC_H_FILES) $(SB_H_FILES) %.o : %.cpp %.hpp $(CXX) $(CXXFLAGS) $< -c -o $@ diff --git a/lib/sb b/lib/sb index f793073..a812660 160000 --- a/lib/sb +++ b/lib/sb @@ -1 +1 @@ -Subproject commit f79307334847947a7d259c9c6ac0e915ef4949c4 +Subproject commit a8126605e87903c598ee2781c4ce8395a9294e96 diff --git a/src/Carousel.hpp b/src/Carousel.hpp deleted file mode 100644 index aa60fff..0000000 --- a/src/Carousel.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* _______________ ,----------------------------------------------------------------. - //`````````````\\ \ \ - //~~~~~~~~~~~~~~~\\ \ by @ohsqueezy & @sleepin \ - //=================\\ \ [ohsqueezy.itch.io] [sleepin.itch.io] \ - // \\ \ \ - // \\ \ code released under the zlib license [git.nugget.fun/pudding] \ - // ☆ GUNKISS ☆ \\ \ \ -//_________________________\\ `---------------------------------------------------------------*/ - -#ifndef CAROUSEL_H_ -#define CAROUSEL_H_ - -#include -#include -#include "utility.hpp" - -class Carousel -{ - -private: - - std::uint32_t offset = 0; - -public: - - template - auto current(Container& container) const - { - auto location = container.begin(); - if (location != container.end()) - { - std::advance(location, offset); - return location; - } - else - { - throw std::out_of_range("Container is empty"); - } - } - - template - void next(const Container& container) - { - offset = ++offset % container.size(); - } - - template - void previous(const Container& container) - { - offset = sb::mod(--offset, container.size()); - } - - template - void increment(const Container& container, int amount) - { - offset = sb::mod(offset + amount, container.size()); - } - - void beginning() - { - offset = 0; - } - - template - void end(const Container& container) - { - offset = container.size() - 1; - } - - /* Return true if the carousel currently points to the location at the beginning of the container. */ - bool at_beginning() const - { - return offset == 0; - } - - /* Return true if the carousel currently points to the location at the end of the container. */ - template - bool at_end(const Container& container) - { - return offset >= container.size() - 1; - } - -}; - -#endif diff --git a/src/Item.cpp b/src/Item.cpp index 27a73e7..25011f4 100644 --- a/src/Item.cpp +++ b/src/Item.cpp @@ -104,7 +104,7 @@ std::size_t Item::texture_count() return item_view.textures().size(); } -Plane& Item::view() +sb::Plane& Item::view() { return item_view; } diff --git a/src/Item.hpp b/src/Item.hpp index 4738658..171cae5 100644 --- a/src/Item.hpp +++ b/src/Item.hpp @@ -35,8 +35,8 @@ class Item private: nlohmann::json json = {}; - Plane item_view; - Carousel carousel; + sb::Plane item_view; + sb::Carousel carousel; std::string item_brand_name = "", item_product_name = "", item_upc = ""; void text_property(const std::string&, std::string&, const std::string&); @@ -60,7 +60,7 @@ public: void next_texture(); void previous_texture(); std::size_t texture_count(); - Plane& view(); + sb::Plane& view(); bool at_first() const; bool at_last(); void to_first(); diff --git a/src/Model.cpp b/src/Model.cpp deleted file mode 100644 index 8709a75..0000000 --- a/src/Model.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* _______________ ,----------------------------------------------------------------. - //`````````````\\ \ \ - //~~~~~~~~~~~~~~~\\ \ by @ohsqueezy & @sleepin \ - //=================\\ \ [ohsqueezy.itch.io] [sleepin.itch.io] \ - // \\ \ \ - // \\ \ code released under the zlib license [git.nugget.fun/pudding] \ - // ☆ GUNKISS ☆ \\ \ \ -//_________________________\\ `---------------------------------------------------------------*/ - -#include "Model.hpp" - -/* Default constructor for Model */ -Model::Model() {}; - -/* Construct a Model, adding Attributes each already wrapped in a shared pointer. The attributes should - * be passed as a map with each key being a name and each value being a shared pointer to attributes. */ -Model::Model(const std::map>& attributes_pack) -{ - for (auto attributes : attributes_pack) - { - this->attributes(attributes.second, attributes.first); - } -} - -/* Construct a Model, adding Attributes, which will each be wrapped in a shared pointer and stored in the - * created object. The attributes should be passed as a map with each key being a name and each value being - * an attributes object. */ -Model::Model(const std::map& attributes_pack) -{ - for (auto attributes : attributes_pack) - { - this->attributes(attributes.second, attributes.first); - } -} - -/* Construct a new model object by passing a list of names which will be used to initialize - * empty attributes objects with the given names */ -Model::Model(const std::initializer_list& names) -{ - for (const std::string& name : names) - { - this->attributes(sb::Attributes(), name); - } -} - -/* Get the entire map of attributes, each wrapped in its shared pointer held by this object. - * Can be used to iterate through the attributes. */ -std::map>& Model::attributes() -{ - return model_attributes; -} - -/* Get the attributes under name, wrapped in the shared pointer held by this object. This - * function uses the at method of std::map, so name must refer to attributes already - * stored in this model. Use this function to share ownership of the attributes or to gain - * access to the public interface of the attributes. */ -std::shared_ptr& Model::attributes(const std::string& name) -{ - return attributes().at(name); -} - -/* Get the attributes under name, wrapped in the shared pointer held by this object. This - * function uses operator[] or std::map, so this can be used to add new attributes to the - * object if they are wrapped in a shared pointer. */ -std::shared_ptr& Model::operator[](const std::string& name) -{ - auto element = attributes().find(name); - /* add an empty Attributes at name if it doesn't exist yet */ - if (element == attributes().end()) - { - attributes(sb::Attributes{}, name); - } - return attributes()[name]; -} - -/* Assign name to attributes, copy and wrap in a shared pointer. The model can share - * ownership of the created attribute memory with callers that request it. */ -void Model::attributes(const sb::Attributes& attributes, const std::string& name) -{ - this->attributes(std::make_shared(attributes), name); -} - -/* Assign name to attributes and share ownership. */ -void Model::attributes(const std::shared_ptr& attributes, const std::string& name) -{ - this->attributes()[name] = attributes; -} - -/* Enable all attributes. */ -void Model::enable() -{ - for (const auto& attributes : this->attributes()) - { - attributes.second->enable(); - } -} - -/* Disable all attributes. */ -void Model::disable() -{ - for (const auto& attributes : this->attributes()) - { - attributes.second->disable(); - } -} - -/* Return a reference to the texture container. */ -std::map& Model::textures() -{ - return model_textures; -} - -/* Get the texture at name. This can be used to read the texture memory, share ownership of it, or - * anything else a Texture object can be used for with direct calls to GL functions. */ -sb::Texture& Model::texture(const std::string& name) -{ - return textures().at(name); -} - -/* Get the default texture. The default texture must have previously been set with the default key as - * the name, which can be done using Model::texture(sb::Texture). */ -sb::Texture& Model::texture() -{ - return texture(DEFAULT_TEXTURE_NAME); -} - -/* Assign name to texture and share ownership. */ -void Model::texture(const sb::Texture& texture, const std::string& name) -{ - textures()[name] = texture; -} - -/* If no name is specified, use the default texture. This can be used to conveniently setup a model - * with only one texture. */ -void Model::texture(const sb::Texture& texture) -{ - this->texture(texture, DEFAULT_TEXTURE_NAME); -} - -/* Get the model's transformation matrix. */ -const glm::mat4& Model::transformation() const -{ - return model_transformation; -} - -/* Set the model's transformation matrix. */ -void Model::transformation(const glm::mat4& transformation) -{ - model_transformation = transformation; -} - -/* Return the size in bytes of the sum of the attributes. */ -std::size_t Model::size() -{ - std::size_t sum = 0; - for (const auto& attributes : this->attributes()) - { - sum += attributes.second->size(); - } - return sum; -} - -/* Return the transformation matrix. */ -Model::operator glm::mat4() const -{ - return model_transformation; -} - -/* Increment offset that indicates which tile texture is active. If offset reaches the end of the container, - * start over from the beginning. */ -void Background::next() -{ - carousel.next(textures()); -} - -/* Return the currently active texture. */ -sb::Texture& Background::current() -{ - return carousel.current(textures())->second; -} - -PlaneDoubleBuffer::PlaneDoubleBuffer() : Plane() -{ - texture(sb::Texture(), "front"); - texture(sb::Texture(), "back"); -} - -void PlaneDoubleBuffer::generate(const glm::vec2& size) -{ - for (sb::Texture* buffer : {&texture("front"), &texture("back")}) - { - buffer->generate(size); - } -} - -sb::Texture& PlaneDoubleBuffer::active() -{ - return swapped ? texture("back") : texture("front"); -} - -sb::Texture& PlaneDoubleBuffer::inactive() -{ - return swapped ? texture("front") : texture("back"); -} - -void PlaneDoubleBuffer::swap() -{ - swapped = !swapped; -} diff --git a/src/Model.hpp b/src/Model.hpp deleted file mode 100644 index 89d2c58..0000000 --- a/src/Model.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* _______________ ,----------------------------------------------------------------. - //`````````````\\ \ \ - //~~~~~~~~~~~~~~~\\ \ by @ohsqueezy & @sleepin \ - //=================\\ \ [ohsqueezy.itch.io] [sleepin.itch.io] \ - // \\ \ \ - // \\ \ code released under the zlib license [git.nugget.fun/pudding] \ - // ☆ GUNKISS ☆ \\ \ \ -//_________________________\\ `---------------------------------------------------------------*/ - -#ifndef MODEL_H_ -#define MODEL_H_ - -/* GL functions */ -#if defined(__EMSCRIPTEN__) -#include -#else -#include "glew/glew.h" -#endif - -#include -#include -#include -#include -#include -#include "glm/glm.hpp" -#include "Attributes.hpp" -#include "Texture.hpp" -#include "Carousel.hpp" - -class Model -{ - -private: - - inline static const std::string DEFAULT_TEXTURE_NAME = "default"; - std::map model_textures; - std::map> model_attributes; - glm::mat4 model_transformation {1.0f}; - -public: - - Model(); - Model(const std::map>&); - Model(const std::map&); - Model(const std::initializer_list&); - std::map>& attributes(); - std::shared_ptr& attributes(const std::string&); - void attributes(const sb::Attributes&, const std::string&); - void attributes(const std::shared_ptr&, const std::string&); - std::shared_ptr& operator[](const std::string&); - void enable(); - void disable(); - std::map& textures(); - sb::Texture& texture(const std::string&); - sb::Texture& texture(); - void texture(const sb::Texture&, const std::string&); - void texture(const sb::Texture&); - const glm::mat4& transformation() const; - void transformation(const glm::mat4&); - std::size_t size(); - operator glm::mat4() const; - -}; - -class Plane : public Model -{ - -public: - - inline const static std::shared_ptr position = std::make_shared(sb::Attributes{ - {-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f}, - {1.0f, 1.0f}, {1.0f, -1.0f}, {-1.0f, -1.0f} - }); - inline const static std::shared_ptr uv = std::make_shared(sb::Attributes{ - {0.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, - {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} - }); - - Plane() : Model(std::map>({{"position", position}, {"uv", uv}})) {} - -}; - -/*! - * A version of `Plane` that contains a `Carousel` for cycling through active `sb::Texture` objects. Only one - * `sb::Texture` is * active at a time, returned by `Background::current`. Carousel only goes forward, using - * `Background::next`. - */ -class Background : public Plane -{ - -private: - - Carousel carousel; - -public: - - void next(); - sb::Texture& current(); - -}; - -/*! - * A version of `Plane` which contains two texture objects, one of which is active at a time. A reference - * to the active `sb::Texture` object is available from `PlaneDoubleBuffer.active`, and the inactive object is - * available from `PlaneDoubleBuffer.inactive`. The buffers can be swapped using `PlaneDoubleBuffer.swap`. - */ -class PlaneDoubleBuffer : public Plane -{ - -private: - - bool swapped = false; - -public: - - PlaneDoubleBuffer(); - void generate(const glm::vec2&); - sb::Texture& active(); - sb::Texture& inactive(); - void swap(); - -}; - -#endif diff --git a/src/Pudding.cpp b/src/Pudding.cpp index 43431c0..4ebc2be 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -217,8 +217,8 @@ void Pudding::load_gl_context() flat_program = glCreateProgram(); glAttachShader(flat_program, vertex_shader); glAttachShader(flat_program, fragment_shader); - Plane::position->bind(0, flat_program, "in_position"); - Plane::uv->bind(1, flat_program, "vertex_uv"); + sb::Plane::position->bind(0, flat_program, "in_position"); + sb::Plane::uv->bind(1, flat_program, "vertex_uv"); /* load, configure and link the 3D world program */ vertex_shader = load_shader("src/shaders/mvp.vert", GL_VERTEX_SHADER); @@ -233,8 +233,8 @@ void Pudding::load_gl_context() /* Fill VBO with attribute data */ vbo.allocate(background.size() + pudding_model.size(), GL_STATIC_DRAW); - vbo.add(*Plane::position); - vbo.add(*Plane::uv); + vbo.add(*sb::Plane::position); + vbo.add(*sb::Plane::uv); vbo.add(*pudding_model.attributes("uv")); vbo.add(*pudding_model.attributes("position")); vbo.add(*pudding_model.attributes("color")); @@ -1452,6 +1452,19 @@ const bool& Request::finished() const return is_finished; } +/* Increment offset that indicates which tile texture is active. If offset reaches the end of the container, + * start over from the beginning. */ +void Background::next() +{ + carousel.next(textures()); +} + +/* Return the currently active texture. */ +sb::Texture& Background::current() +{ + return carousel.current(textures())->second; +} + /* Construct a Pad using a texture, a translation, a scale, and a callback function. A Pad is a Plane which can be clicked * to launch an arbitrary user function. It can be sized and placed by setting the translation and scale values. The translation * is relative to (0.0, 0.0), and the scale is relative to the Plane, which has opposite corners at (-1.0, -1.0) and (1.0, 1.0). @@ -1518,8 +1531,8 @@ void Pad::transform() } collision_box.size(2.0f * glm::vec2{scale.x, scale.y}, true); collision_box.center(translation_vector); - Model::transformation(glm::translate(glm::vec3{translation_vector.x, translation_vector.y, 0.0f}) * - glm::scale(scale) * glm::rotate(rotation_angle, ROTATION_AXIS)); + sb::Model::transformation(glm::translate(glm::vec3{translation_vector.x, translation_vector.y, 0.0f}) * + glm::scale(scale) * glm::rotate(rotation_angle, ROTATION_AXIS)); } /* Set the function that will run when a pad object is clicked. */ diff --git a/src/Pudding.hpp b/src/Pudding.hpp index d795783..4cfe7df 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -60,6 +60,7 @@ using namespace emscripten; #include "Model.hpp" #include "utility.hpp" #include "Box.hpp" +#include "Connection.hpp" /*! * This class is used for printing the running time of a function or lambda. It can be @@ -134,130 +135,22 @@ public: }; -/* A connection is an object containing a binary state of either on (connected) or off (not connected) - * and user supplied functions that run automatically on each state change. The functions each have the - * same return type, number of arguments, and argument types determined by the template arguments. - * - * Original test code: - * - * Connection<> connection_d(std::bind(&Game::print_frame_length_history, this)); - * connection_d.toggle(); - * Connection connection_f { - * std::function(&sb::mod), std::function(&sb::mod) }; - * Connection<> connection_g = connection_d; - * connection_g.toggle(); - * connection_g.disconnect(); - * int result; - * result = connection_f.connect(3, 5); - * std::cout << result << " "; - * std::cout << connection_f.disconnect(20, 6) << " "; - * result = connection_f.toggle(800, 120); - * std::cout << result << std::endl; - * result = connection_f.connect(111, 44); - * std::cout << result << std::endl; -*/ -template -class Connection +/*! + * A version of `Plane` that contains a `Carousel` for cycling through active `sb::Texture` objects. Only one + * `sb::Texture` is * active at a time, returned by `Background::current`. Carousel only goes forward, using + * `Background::next`. + */ +class Background : public sb::Plane { - + private: - - enum State : bool - { - STATE_OFF, - STATE_ON - }; - using callback = std::function; - - State connection_state = STATE_OFF; - callback on_connect_callback, on_disconnect_callback; + sb::Carousel carousel; public: - /* Without any arguments, the connection object will be in the disconnected state with empty functions. Otherwise, - * the supplied functions will be added to the connection object. The first function argument will be run on a - * connection, and the second function argument will be run on a disconnection. */ - Connection(callback on_connect_callback = callback(), callback on_disconnect_callback = callback()) - { - if (on_connect_callback) - { - on_connect(on_connect_callback); - if (on_disconnect_callback) - { - on_disconnect(on_disconnect_callback); - } - } - } - - /* Set the function that will run when a connection is made. */ - void on_connect(callback on_connect) - { - on_connect_callback = on_connect; - } - - /* Set the function that will run when a disconnection happens. */ - void on_disconnect(callback on_disconnect) - { - on_disconnect_callback = on_disconnect; - } - - /* Set state to Connection::STATE_ON and run response function. If return_type is non-void and the - * connection is already connected, the function will not run and the return value will be a default - * constructed value of the type return_type. Therefore, return_type must be default constructible. */ - return_type connect(arguments... args) - { - if (!*this) - { - connection_state = STATE_ON; - if (on_connect_callback) - { - return on_connect_callback(args...); - } - } - return return_type(); - } - - /* Set state to Connection::STATE_OFF and run response function. If return_type is non-void and the - * connection is already disconnected, the function will not run and the return value will be a default - * constructed value of the type return_type. Therefore, return_type must be default constructible. */ - return_type disconnect(arguments... args) - { - if (*this) - { - connection_state = STATE_OFF; - if (on_disconnect_callback) - { - return on_disconnect_callback(args...); - } - } - return return_type(); - } - - /* Set state to the opposite of current state, causing the appropriate response function to run. */ - return_type toggle(arguments... args) - { - if (*this) - { - return disconnect(args...); - } - else - { - return connect(args...); - } - } - - /* Return true if state is Connection::STATE_ON, false otherwise. */ - bool connected() - { - return connection_state; - } - - /* When called as a boolean, return the connection state. */ - operator bool() - { - return connected(); - } + void next(); + sb::Texture& current(); }; @@ -281,14 +174,14 @@ public: * std::cout << p.transformation() << std::endl << final_position << std::endl; * assert(final_position == glm::vec4({w.x, w.y, 0, 1})); */ -class Pad : public Plane +class Pad : public sb::Plane { private: inline static const glm::vec3 ROTATION_AXIS {0.0f, 0.0f, 1.0f}; using callback = std::function; - Connection<> connection; + sb::Connection<> connection; Box collision_box; float rotation_angle = 0.0f, scale_factor = 0.0f, scale_ratio = 1.0f; glm::vec2 translation_vector {0.0f, 0.0f}; @@ -427,7 +320,7 @@ private: std::string current_barcode, previous_barcode, current_config_barcode; std::vector items; Item incoming_item; - Carousel item_carousel; + sb::Carousel item_carousel; int effect_id = EFFECT_NONE, pudding_triangle_vertex_count = 0, pudding_fan_vertex_count = 0; #ifndef __EMSCRIPTEN__ cv::VideoCapture capture; @@ -440,8 +333,8 @@ private: std::map> uniform; GLuint flat_program, mvp_program; glm::mat4 projection, model {1.0f}, mvp; - Model pudding_model; - Plane plane, camera_view; + sb::Model pudding_model; + sb::Plane plane, camera_view; Background background; bool show_item = false; sb::VAO vao; @@ -583,7 +476,7 @@ private: #endif /* Open camera on connection and close on disconnection. */ - Connection<> camera_switch { + sb::Connection<> camera_switch { std::bind(&Pudding::open_camera, this), std::bind(&Pudding::close_camera, this) }; @@ -608,7 +501,7 @@ class Button private: - Connection connection; + sb::Connection connection; /* float threshold = 1.0f */ /* float force = 0.0f */