connection class accepts callback functions

This commit is contained in:
frank 2021-11-04 01:16:46 -04:00
parent 392371d0c5
commit c9868db346
6 changed files with 158 additions and 52 deletions

View File

@ -44,7 +44,7 @@ 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 utility.o),$(SB_H_FILES:.hpp=.o))
SB_O_FILES := $(filter-out $(addprefix $(SB_SRC_DIR),filesystem.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))
@ -75,8 +75,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) $(addprefix $(SRC_DIR),Carousel.hpp)
$(SRC_DIR)Item.o : $(addprefix $(SB_SRC_DIR),Texture.hpp Log.hpp) $(addprefix $(SRC_DIR),Model.hpp Carousel.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)
$(SRC_DIR)Pudding.o : $(SRC_H_FILES) $(SB_H_FILES)
%.o : %.cpp %.hpp
$(CPPC) $(CPP_FLAGS) $< -c -o $@

View File

@ -47,7 +47,7 @@
"enabled": true,
"json-save": true,
"json-save-directory": "local/scans",
"barcode": "1250245567",
"barcode": "",
"capture-device": "/dev/video0"
},
"api":

2
lib/sb

@ -1 +1 @@
Subproject commit dd736f341fb49380a4d33d14859c7632853d06e0
Subproject commit 863db5467bfc625df916ac9a04e9d14aa13d7e55

View File

@ -47,13 +47,13 @@ public:
template<typename Container>
auto previous(const Container& container)
{
offset = sb::mod<int>(--offset, container.size());
offset = sb::mod(--offset, container.size());
}
template<typename Container>
auto increment(const Container& container, int amount)
{
offset = sb::mod<int>(offset + amount, container.size());
offset = sb::mod(offset + amount, container.size());
}
template<typename Container>

View File

@ -277,14 +277,7 @@ void Pudding::respond(SDL_Event& event)
}
else if (get_delegate().compare(event, "toggle-camera"))
{
if (capture.isOpened())
{
capture.release();
}
else
{
initialize_camera();
}
camera_switch.toggle();
}
else if (get_delegate().compare(event, "toggle-item"))
{

View File

@ -17,6 +17,7 @@
#include <thread>
#include <memory>
#include <stdexcept>
#include <functional>
#include <curl/curl.h>
#include "SDL.h"
#include "SDL_image.h"
@ -42,6 +43,133 @@
#include "Model.hpp"
#include "utility.hpp"
/* 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<int, int, int> connection_f {
* std::function<int(int, int)>(&sb::mod), std::function<int(int, int)>(&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<typename return_type = void, typename... arguments>
class Connection
{
private:
enum State : bool
{
STATE_OFF,
STATE_ON
};
using callback = std::function<return_type(arguments...)>;
State connection_state = STATE_OFF;
callback on_connect_callback, on_disconnect_callback;
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();
}
};
class Pudding : public Game
{
@ -115,6 +243,12 @@ private:
bool item_display_active() const;
static int capture_frame(void*);
/* Initialize camera on connection and release on disconnection. */
Connection<> camera_switch {
std::bind(&Pudding::initialize_camera, this),
[&] { capture.release(); }
};
public:
Pudding();
@ -127,16 +261,14 @@ public:
};
/* Apply force until reaching a threshold. Use a connection object to run user functions
* when force reaches threshold and when force goes below threshold.
*
* - shares single Plane (vertices in VBO and UV in VBO)
* - each has different Texture
* - each has different response to click
* - shares collision with mouse code
* - each has different position
*/
* when force reaches threshold and when force goes below threshold. */
class Button
{
private:
Connection<> connection;
/* threshold */
/* force */
/* close */
@ -144,41 +276,22 @@ class Button
/* apply */
/* remove */
/* weighted depression rate */
/* Animation (?) */
};
class Pad
/* Drawable class that is a plane containing a button. Each instance:
*
* - Shares vertices and UV in VBO
* - Has its own Texture representing the button on-screen
* - Has its own response to click
* - Shares mouse collision code
* - Has its own translate + scale transformation
*/
class Pad : public Plane
{
};
/* 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; }
Button button;
};