- fix sb::Pad to move the collision box when scaled or translated

- add warning about config JSON copy
- add setter for sb::Pad::_plane
- move point on circle functions from extension to math
This commit is contained in:
ohsqueezy 2023-09-16 21:04:43 -04:00
parent 4c3235c2ff
commit d882e111b3
7 changed files with 89 additions and 50 deletions

View File

@ -33,9 +33,16 @@ private:
Animation auto_refresher = Animation(std::bind(&Configuration::refresh, this));
fs::file_time_type config_file_modification_time;
nlohmann::json config;
std::vector<fs::path> files_to_refresh;
/*!
* @warning This JSON will be copied when the object is copied, and it is potentially a large copy because it can copy an arbitrary amount of
* JSON data. Because a game object by definition has a single configuration, this can be optimized in the future so that the JSON is stored
* in a member of the game object. Arguably it also doesn't make sense to be copying the data because the JSON is expected to change during
* runtime.
*/
nlohmann::json config;
/*!
* Fill the config JSON with default values set by the framework.
*/

View File

@ -48,7 +48,7 @@ namespace sb
using Reaction = std::function<ReturnType(bool, Arguments...)>;
sb::Switch<ReturnType, Arguments...> connection;
sb::Plane plane;
sb::Plane _plane;
Box box;
public:
@ -78,7 +78,7 @@ namespace sb
* @param rotation angle in radians to rotate the pad
*/
Pad(const sb::Plane& plane, glm::vec2 translation = {0.0f, 0.0f}, float scale = 1.0f, float ratio = 1.0f,
Reaction on_state_change = Reaction(), float rotation = 0.0f) : plane(plane)
Reaction on_state_change = Reaction(), float rotation = 0.0f) : _plane(plane)
{
box.size({2.0f, 2.0f}, true);
if (translation != glm::vec2{0.0f, 0.0f})
@ -96,6 +96,16 @@ namespace sb
this->on_state_change(on_state_change);
}
/*!
* Assign a new plane to the pad. The existing plane will be replaced.
*
* @param plane plane or plane derivative to represent the pad visually
*/
void plane(const sb::Plane& plane)
{
_plane = plane;
}
/*!
* Rotate the pad around its center by 90 degrees. If a count is given, rotate by 90 degrees that many times, so for example,
* a count of 3 will be a 270 degree rotation. If the count is negative, rotate -90 degrees.
@ -104,7 +114,7 @@ namespace sb
*/
void rotate(int count = 1)
{
plane.transform(glm::rotate(count * glm::half_pi<float>(), glm::vec3{0.0f, 0.0f, 1.0f}));
_plane.transform(glm::rotate(count * glm::half_pi<float>(), glm::vec3{0.0f, 0.0f, 1.0f}));
}
/*!
@ -129,8 +139,9 @@ namespace sb
{
scale.y *= ratio;
}
box.size({2.0f, 2.0f}, true);
box.scale({scale.x, scale.y}, true);
return plane.scale(scale);
return _plane.scale(scale);
}
/*!
@ -140,8 +151,9 @@ namespace sb
*/
const glm::mat4& translate(const glm::vec2& translation)
{
box.center({0.0f, 0.0f});
box.move(translation);
return plane.translate({translation.x, translation.y, 0.0f});
return _plane.translate({translation.x, translation.y, 0.0f});
}
/*!
@ -203,23 +215,23 @@ namespace sb
*/
void draw(GLuint transformation_uniform, glm::mat4 view, glm::mat4 projection, std::optional<GLuint> texture_flag_uniform = std::nullopt)
{
if (!plane.textures().empty())
if (!_plane.textures().empty())
{
if (texture_flag_uniform.has_value())
{
glUniform1i(texture_flag_uniform.value(), true);
}
plane.texture().bind();
_plane.texture().bind();
}
else if (texture_flag_uniform.has_value())
{
glUniform1i(texture_flag_uniform.value(), false);
}
glm::mat4 mvp = projection * view * plane.transformation();
glm::mat4 mvp = projection * view * _plane.transformation();
glUniformMatrix4fv(transformation_uniform, 1, GL_FALSE, &mvp[0][0]);
plane.enable();
glDrawArrays(GL_TRIANGLES, 0, plane.attributes("position")->count());
plane.disable();
_plane.enable();
glDrawArrays(GL_TRIANGLES, 0, _plane.attributes("position")->count());
_plane.disable();
}
/*!
@ -238,7 +250,7 @@ namespace sb
*/
std::size_t size() const
{
return plane.size();
return _plane.size();
}
};
}

View File

@ -72,13 +72,17 @@ namespace sb
offset = container.size() - 1;
}
/* Return true if the selection currently points to the location at the beginning of the container. */
/*!
* @return true if the selection currently points to the location at the beginning of the container
*/
bool at_beginning() const
{
return offset == 0;
}
/* Return true if the selection currently points to the location at the end of the container. */
/*!
* @return true if the selection currently points to the location at the end of the container
*/
bool at_end()
{
return offset >= container.size() - 1;

View File

@ -17,37 +17,6 @@ void sb::set_magnitude(glm::vec2& vector, float magnitude)
vector = glm::normalize(vector) * magnitude;
}
/* Return coordinates of a point x, y at specified angle on a circle described by center and radius */
glm::vec2 sb::point_on_circle(const glm::vec2& center, float radius, float angle)
{
return {center.x + std::sin(angle) * radius, center.y - std::cos(angle) * radius};
}
/* Return a point x, y at specified angle on a circle at the origin with specified radius (default 1) */
glm::vec2 sb::point_on_circle(float angle, float radius)
{
return point_on_circle({0, 0}, radius, angle);
}
/* Fill a pre-initialized vector with points evenly spaced around a circle starting at the angle offset (defaults to 0) */
void sb::points_on_circle(std::vector<glm::vec2>& points, int count, float radius, const glm::vec2& center, float offset)
{
float step = glm::two_pi<float>() / count;
for (int ii = 0; ii < count; ii++)
{
points.push_back(point_on_circle(center, radius, ii * step + offset));
}
}
/* Return a vector of count number of points evenly spaced around a circle starting at the angle offset (defaults to 0) */
std::vector<glm::vec2> sb::points_on_circle(int count, float radius, const glm::vec2& center, float offset)
{
std::vector<glm::vec2> points;
points.reserve(count);
points_on_circle(points, count, radius, center, offset);
return points;
}
Box sb::get_texture_box(SDL_Texture* texture)
{
int width, height;

View File

@ -58,10 +58,6 @@ namespace sb
enum scaler {scale2x, xbr};
void set_magnitude(glm::vec2&, float);
glm::vec2 point_on_circle(const glm::vec2&, float, float);
glm::vec2 point_on_circle(float, float = 1.0f);
void points_on_circle(std::vector<glm::vec2>&, int, float = 1.0f, const glm::vec2& = {0, 0}, float = 0.0f);
std::vector<glm::vec2> points_on_circle(int, float = 1.0f, const glm::vec2& = {0, 0}, float = 0.0f);
Box get_texture_box(SDL_Texture*);
glm::vec2 fit_and_preserve_aspect(const glm::vec2&, const glm::vec2&);
std::vector<std::vector<Box>> get_blinds_boxes(glm::vec2, float = 0.05f, int = 4);
@ -89,6 +85,7 @@ namespace sb
std::vector<fs::path> glob(fs::path);
fs::path get_next_file_name(fs::path, int = 0, std::string = "", std::string = "");
/*!
* Read the file at path into a string and return the string.
*

View File

@ -30,6 +30,28 @@ float sb::angle_ratio(float start, float end)
return sb::angle_difference(start, end) / glm::pi<float>();
}
glm::vec2 sb::point_on_circle(const glm::vec2& center, float angle, float radius)
{
return center + sb::angle_to_vector(angle, radius);
}
void sb::points_on_circle(std::vector<glm::vec2>& points, int count, float radius, const glm::vec2& center, float offset)
{
float step = glm::two_pi<float>() / count;
for (int ii = 0; ii < count; ii++)
{
points.push_back(point_on_circle(center, radius, ii * step + offset));
}
}
std::vector<glm::vec2> sb::points_on_circle(int count, float radius, const glm::vec2& center, float offset)
{
std::vector<glm::vec2> points;
points.reserve(count);
points_on_circle(points, count, radius, center, offset);
return points;
}
std::vector<glm::vec2> sb::bezier(const std::vector<glm::vec2>& control, int resolution)
{
std::vector<glm::vec2> points;

View File

@ -98,6 +98,34 @@ namespace sb
*/
float angle_ratio(float start, float end);
/*!
* Return the coordinates of a point on a circle at a given angle. The circle is passed by giving a center and radius.
*
* @param center vector representing the center of the circle
* @param angle angle along the circle, 0 being up, going clockwise
* @param radius radius of the circle
* @return a vector representing a point along the circle's edge at the given angle
*/
glm::vec2 point_on_circle(const glm::vec2& center, float angle, float radius = 1.0f);
/*!
* Fill a vector with count number of points evenly spaced around a circle starting at the angle offset (defaults to 0).
*
* @param points vector that will be filled with 2D vectors representing the requested points
* @param count number of points
* @param radius radius of the circle
* @param center 2D vector representing the center of the circle
* @param offset start calculating the points offset from 0 degrees (up on the screen)
*/
void points_on_circle(std::vector<glm::vec2>& points, int count, float radius = 1.0f, const glm::vec2& center = {0.0f, 0.0f}, float offset = 0.0f);
/*!
* Create and return a vector of count number of points evenly spaced around a circle starting at the angle offset (defaults to 0).
*
* @see points_on_circle(std::vector<glm::vec2>&, int, float, const glm::vec2&, float)
*/
std::vector<glm::vec2> points_on_circle(int count, float radius = 1.0f, const glm::vec2& center = {0.0f, 0.0f}, float offset = 0.0f);
/*!
* Calculate a 2D bezier curve from four 2D control points.
*