- add untransform, transform, and specialized transforms to Model class

- reset viewport on window resize events
- add boolean assignment operator to Switch class
- throw error if GL object is generated before GL context is created
- add Selection container
- add string conversion to Box
This commit is contained in:
ohsqueezy 2023-05-24 22:49:05 -04:00
parent 3ba3be4496
commit 7140e8a3eb
12 changed files with 270 additions and 40 deletions

View File

@ -606,6 +606,10 @@ std::string Box::string() const
return output.str();
}
Box::operator std::string() const
{
return string();
}
/* Feed a string representation of the box to the passed ostream */
std::ostream& std::operator<<(std::ostream& out, const Box& box)

View File

@ -100,6 +100,13 @@ public:
virtual std::string class_name() const { return "Box"; }
std::string string() const;
/*!
* Convert the box to a string when it is passed in a string context.
*
* @return string representation of the box
*/
operator std::string() const;
};
namespace std

View File

@ -45,7 +45,8 @@ void Configuration::set_defaults()
{"debug", false},
{"show-cursor", false},
{"render-test-spacing", 2},
{"render driver", "opengl"}
{"render driver", "opengl"},
{"fluid resize", false}
};
config["audio"] = {
{"default-sfx-root", "resource/sfx"},

View File

@ -1,19 +1,20 @@
/* /\ +--------------------------------------------------------------+
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
\ / / | copy, and modify without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - originally created at [http://nugget.fun] |
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+-------------*/
/* +------------------------------------------------------+
____/ \____ /| - Open source game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
| ~~~~~~~~~~~~ | +------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+-------------*/
#include "Display.hpp"
/* Create a Display instance and subscribe to commands */
sb::Display::Display(Node* parent) : Node(parent)
{
get_delegate().subscribe(&Display::respond, this);
delegate().subscribe(&Display::respond, this);
delegate().subscribe(&Display::respond, this, SDL_WINDOWEVENT);
}
/* Return the (x, y) size in pixels of the window as an integer vector */
@ -154,13 +155,30 @@ SDL_Surface* sb::Display::screen_surface_from_pixels(unsigned char* pixels, bool
return surface;
}
/* Handle fullscreen request */
void sb::Display::respond(SDL_Event& event)
{
if (get_delegate().compare(event, "fullscreen"))
{
toggle_fullscreen();
}
else if (event.type == SDL_WINDOWEVENT)
{
/* Handle a full window resize event, and only handle intermediate size change events if fluid resize is enabled. */
if (event.window.event == SDL_WINDOWEVENT_RESIZED || (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED && configuration()["display"]["fluid resize"]))
{
std::ostringstream message;
message << "Resizing window to " << event.window.data1 << "x" << event.window.data2;
sb::Log::Level level = event.window.event == SDL_WINDOWEVENT_RESIZED ? sb::Log::INFO : sb::Log::DEBUG;
sb::Log::log(message, level);
/* Resize the GL viewport */
if (SDL_GL_GetCurrentContext() != nullptr)
{
glViewport(0, 0, event.window.data1, event.window.data2);
sb::Log::gl_errors("After glViewport resize");
}
}
}
}
/* Use SDL window flags to determine if fullscreen is on or off and use SDL fullscreen

View File

@ -39,7 +39,18 @@ namespace sb
void screen_pixels(unsigned char*, int, int, int = 0, int = 0) const;
SDL_Surface* screen_surface() const;
SDL_Surface* screen_surface_from_pixels(unsigned char*, bool) const;
void respond(SDL_Event&);
/*!
* Respond to full screen requests and window resize events. If fluid resize is enabled in the configuration, respond to
* resize events as the screen is being resized, otherwise respond once when the resize is finished.
*
* The dispay object subscribes to SDL events in its constructor, so this function will be called automatically by
* sb::Delegate::dispatch when an event happens.
*
* @param event an SDL event
*/
void respond(SDL_Event& event);
void toggle_fullscreen() const;
};

View File

@ -35,12 +35,19 @@ GLObject::GLObject(deleter_function deleter) : deleter(deleter) {}
*/
void GLObject::generate(generator_function generator)
{
GLuint id;
generator(1, &id);
this->id(id);
std::ostringstream message;
message << "Generated ID " << this->id() << " for GL object";
sb::Log::log(message, sb::Log::DEBUG);
if (SDL_GL_GetCurrentContext() != nullptr)
{
GLuint id;
generator(1, &id);
this->id(id);
std::ostringstream message;
message << "Generated ID " << this->id() << " for GL object";
sb::Log::log(message, sb::Log::DEBUG);
}
else
{
throw std::runtime_error("Cannot generate ID for GL object before GL context is created");
}
}
/* Set the shared pointer to point to a new GLuint with specified ID value */

View File

@ -114,7 +114,7 @@ Game::Game()
/* Create a window with dimensions set in the config, centered, and flagged to be usable in OpenGL context */
_window = SDL_CreateWindow(
configuration()["display"]["title"].get_ref<const std::string&>().c_str(), SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, window_size.x, window_size.y, SDL_WINDOW_OPENGL);
SDL_WINDOWPOS_CENTERED, window_size.x, window_size.y, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (_window == nullptr)
{
sb::Log::sdl_error("Could not create window");

View File

@ -48,7 +48,7 @@ sb::Model::Model(const std::initializer_list<std::string>& names)
* Can be used to iterate through the attributes. */
std::map<std::string, std::shared_ptr<sb::Attributes>>& sb::Model::attributes()
{
return model_attributes;
return _attributes;
}
/* Get the attributes under name, wrapped in the shared pointer held by this object. This
@ -108,7 +108,7 @@ void sb::Model::disable()
/* Return a reference to the texture container. */
std::map<std::string, sb::Texture>& sb::Model::textures()
{
return model_textures;
return _textures;
}
/* Get the texture at name. This can be used to read the texture memory, share ownership of it, or
@ -151,18 +151,44 @@ void sb::Model::texture(const sb::Texture& texture)
this->texture(texture, DEFAULT_TEXTURE_NAME);
}
/* Get the model's transformation matrix. */
const glm::mat4& sb::Model::transformation() const
{
return model_transformation;
return _transformation;
}
/* Set the model's transformation matrix. */
void sb::Model::transformation(const glm::mat4& transformation)
const glm::mat4& sb::Model::transform(const glm::mat4& transformation)
{
model_transformation = transformation;
_transformation *= transformation;
return this->transformation();
}
const glm::mat4& sb::Model::untransform()
{
_transformation = glm::mat4(1.0f);
return transformation();
}
const glm::mat4& sb::Model::scale(const glm::vec3& scale)
{
return transform(glm::scale(scale));
}
const glm::mat4& sb::Model::scale(float scale)
{
return this->scale(glm::vec3(scale));
}
const glm::mat4& sb::Model::rotate(float angle, glm::vec3 axis)
{
return transform(glm::rotate(angle, axis));
}
const glm::mat4& sb::Model::translate(glm::vec3 translation)
{
return transform(glm::translate(translation));
}
/* Return the size in bytes of the sum of the attributes. */
std::size_t sb::Model::size()
{
@ -177,7 +203,7 @@ std::size_t sb::Model::size()
/* Return the transformation matrix. */
sb::Model::operator glm::mat4() const
{
return model_transformation;
return _transformation;
}
sb::PlaneDoubleBuffer::PlaneDoubleBuffer() : Plane()

View File

@ -40,9 +40,9 @@ namespace sb
private:
inline static const std::string DEFAULT_TEXTURE_NAME = "default";
std::map<std::string, sb::Texture> model_textures;
std::map<std::string, std::shared_ptr<sb::Attributes>> model_attributes;
glm::mat4 model_transformation {1.0f};
std::map<std::string, sb::Texture> _textures;
std::map<std::string, std::shared_ptr<sb::Attributes>> _attributes;
glm::mat4 _transformation {1.0f};
public:
@ -62,8 +62,64 @@ namespace sb
sb::Texture& texture();
void texture(const sb::Texture&, const std::string&);
void texture(const sb::Texture&);
/*!
* @return a constanst reference to the model's transformation matrix
*/
const glm::mat4& transformation() const;
void transformation(const glm::mat4&);
/*!
* Apply the given transformation matrix to the model's current transformation matrix.
*
* @return the model's new transformation matrix
*/
const glm::mat4& transform(const glm::mat4& transformation);
/*!
* Resets the model's transformation to the identity matrix.
*
* @return the model's new transformation matrix, the identity matrix
*/
const glm::mat4& untransform();
/*!
* Specialized version of transform(const glm::mat4&) that builds a scale transformation from an x, y, z vector and
* applies it to the model's transformation matrix.
*
* @param scale x, y, z scale
* @return the model's new transformation matrix
*/
const glm::mat4& scale(const glm::vec3& scale);
/*!
* Scale all dimensions by the same amount.
* @overload scale(const glm::vec3&)
*/
const glm::mat4& scale(float scale);
/*!
* Specialized version of transform(const glm::mat4&) that builds a rotation matrix from an angle in radians and an axis
* vector and applies it to the model's transformation matrix.
*
* The axis is the vector around which the model will be rotated. For example, to rotate a 2D plane around the origin, use
* the z-axis: `glm::vec3(0.0f, 0.0f, 1.0f)`.
*
* @param angle angle in radians
* @param axis axis to rotate the model around
* @return the model's new transformation matrix
*/
const glm::mat4& rotate(float angle, glm::vec3 axis);
/*!
* Specialized version of transform(const glm::mat4&) that builds a translation matrix from a 3D translation vector
* indicating the distance to translate along each axis and applies it to the model's transformation matrix.
*
* @param translation distance to translate in the x, y, and z dimensions
* @return the model's new transformation matrix
*/
const glm::mat4& translate(glm::vec3 translation);
std::size_t size();
operator glm::mat4() const;

85
src/Selection.hpp Normal file
View File

@ -0,0 +1,85 @@
/* +------------------------------------------------------+
____/ \____ /| - Open source game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
| ~~~~~~~~~~~~ | +------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+-------------*/
#pragma once
#include <cstdint>
#include <iterator>
#include "utility.hpp"
namespace sb
{
template<typename Container>
class Selection
{
private:
std::uint32_t offset = 0;
const Container& container;
public:
Selection(const Container& container) : container(container) {}
auto current() const
{
auto location = container.begin();
if (location != container.end())
{
std::advance(location, offset);
return location;
}
else
{
throw std::out_of_range("No options currently in selection");
}
}
void next()
{
offset = ++offset % container.size();
}
void previous()
{
offset = sb::mod(--offset, container.size());
}
void increment(int amount)
{
offset = sb::mod(offset + amount, container.size());
}
void beginning()
{
offset = 0;
}
void end()
{
offset = container.size() - 1;
}
/* 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. */
bool at_end()
{
return offset >= container.size() - 1;
}
};
}

View File

@ -99,6 +99,8 @@ namespace sb
*/
Switch(Reaction reaction = Reaction()) : reaction(reaction) {}
Switch(bool state, Reaction reaction = Reaction()) : state(state), reaction(reaction) {}
return_type flip(arguments... args)
{
state = !state;
@ -115,14 +117,6 @@ namespace sb
this->reaction = reaction;
}
/*!
* @return true if state is Switch::STATE_ON, false otherwise
*/
bool on()
{
return state;
}
/*!
* @return when called as a boolean, return state
*/
@ -131,5 +125,24 @@ namespace sb
return on();
}
/*!
* Assign the switch object's state using the assignment operator with a boolean value.
*
* @param state state the switch will be set to
*/
Switch<return_type, arguments...>& operator=(bool state)
{
this->state = state;
return *this;
}
/*!
* @return true if state is Switch::STATE_ON, false otherwise
*/
bool on()
{
return state;
}
};
}

View File

@ -55,6 +55,8 @@
namespace sb
{
static inline const glm::vec3 ZAXIS {0.0f, 0.0f, 1.0f};
/*!
* Convert a vector described by the given angle and magnitude to an X and Y offset vector.
*