Browse Source

Event+Asset+Keycodes: Add keybind for taking screenshots

master
Riyyi 2 months ago
parent
commit
03e8210165
  1. 5
      src/inferno/application.cpp
  2. 47
      src/inferno/asset/texture.cpp
  3. 3
      src/inferno/asset/texture.h
  4. 31
      src/inferno/event/keyevent.h
  5. 19
      src/inferno/keycodes.cpp
  6. 4
      src/inferno/keycodes.h
  7. 6
      src/inferno/window.cpp

5
src/inferno/application.cpp

@ -274,6 +274,11 @@ bool Application::onKeyPress(KeyPressEvent& e)
m_window->setShouldClose(true); m_window->setShouldClose(true);
} }
if (e.getKey() == keyCode("GLFW_KEY_F12")) {
ruc::info("Taking screenshot..");
Texture::saveScreenshotPNG("screenshot.png", m_window->getWidth(), m_window->getHeight());
}
return true; return true;
} }

47
src/inferno/asset/texture.cpp

@ -13,6 +13,8 @@
#include "ruc/meta/assert.h" #include "ruc/meta/assert.h"
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "stb/stb_image.h" #include "stb/stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb/stb_image_write.h"
#include "inferno/asset/texture.h" #include "inferno/asset/texture.h"
@ -23,6 +25,51 @@ Texture::~Texture()
glDeleteTextures(1, &m_id); glDeleteTextures(1, &m_id);
} }
// -----------------------------------------
void Texture::savePNG(std::string_view path, std::shared_ptr<Texture> texture)
{
texture->bind();
// Allocate memory
uint32_t dataFormat = texture->m_dataFormat == GL_RGBA ? 4 : 3;
size_t dataSize = texture->m_width * texture->m_height * dataFormat;
std::vector<unsigned char> data(dataSize);
// Read texture data from the GPU
glGetTexImage(GL_TEXTURE_2D, 0, texture->m_dataFormat, texture->m_dataType, data.data());
// Write image to a file
stbi_flip_vertically_on_write(1);
stbi_write_png(
path.data(),
texture->m_width,
texture->m_height,
dataFormat,
data.data(),
texture->m_width * dataFormat);
texture->unbind();
}
void Texture::saveScreenshotPNG(std::string_view path, uint32_t width, uint32_t height)
{
// Allocate memory
size_t dataSize = width * height * 4;
std::vector<unsigned char> data(dataSize);
// Set the pack alignment to 1 (to avoid row alignment issues)
glPixelStorei(GL_PACK_ALIGNMENT, 1);
// Read the pixels from the default framebuffer
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
stbi_flip_vertically_on_write(1);
stbi_write_png(path.data(), width, height, 4, data.data(), width * 4);
}
// -----------------------------------------
void Texture::init(uint32_t width, uint32_t height, uint8_t channels) void Texture::init(uint32_t width, uint32_t height, uint8_t channels)
{ {
init(width, height, init(width, height,

3
src/inferno/asset/texture.h

@ -22,6 +22,9 @@ class Texture : public Asset {
public: public:
virtual ~Texture(); virtual ~Texture();
static void savePNG(std::string_view path, std::shared_ptr<Texture> texture);
static void saveScreenshotPNG(std::string_view path, uint32_t width, uint32_t height);
void init(uint32_t width, uint32_t height, uint8_t channels); void init(uint32_t width, uint32_t height, uint8_t channels);
void init(uint32_t width, uint32_t height, uint32_t internalFormat, uint32_t dataFormat, uint32_t dataType); void init(uint32_t width, uint32_t height, uint32_t internalFormat, uint32_t dataFormat, uint32_t dataType);

31
src/inferno/event/keyevent.h

@ -14,24 +14,27 @@ namespace Inferno {
class KeyEvent : public Event { class KeyEvent : public Event {
public: public:
inline int getKey() const { return m_key; } int getKey() const { return m_key; }
int getMods() const { return m_mods; }
EVENT_CLASS_CATEGORY(InputEventCategory | KeyEventCategory) EVENT_CLASS_CATEGORY(InputEventCategory | KeyEventCategory)
protected: protected:
KeyEvent(int key) KeyEvent(int key, int mods)
: m_key(key) : m_key(key)
, m_mods(mods)
{ {
} }
private: private:
int m_key; int m_key { 0 };
int m_mods { 0 };
}; };
class KeyPressEvent : public KeyEvent { class KeyPressEvent final : public KeyEvent {
public: public:
KeyPressEvent(int key) KeyPressEvent(int key, int mods)
: KeyEvent(key) : KeyEvent(key, mods)
{ {
} }
@ -45,10 +48,10 @@ public:
EVENT_CLASS_TYPE(KeyPress) EVENT_CLASS_TYPE(KeyPress)
}; };
class KeyReleaseEvent : public KeyEvent { class KeyReleaseEvent final : public KeyEvent {
public: public:
KeyReleaseEvent(int key) KeyReleaseEvent(int key, int mods)
: KeyEvent(key) : KeyEvent(key, mods)
{ {
} }
@ -59,13 +62,13 @@ public:
return ss.str(); return ss.str();
} }
EVENT_CLASS_TYPE(KeyPress) EVENT_CLASS_TYPE(KeyRelease)
}; };
class KeyRepeatEvent : public KeyEvent { class KeyRepeatEvent final : public KeyEvent {
public: public:
KeyRepeatEvent(int key) KeyRepeatEvent(int key, int mods)
: KeyEvent(key) : KeyEvent(key, mods)
{ {
} }
@ -76,7 +79,7 @@ public:
return ss.str(); return ss.str();
} }
EVENT_CLASS_TYPE(KeyPress) EVENT_CLASS_TYPE(KeyRepeat)
}; };
} // namespace Inferno } // namespace Inferno

19
src/inferno/keycodes.cpp

@ -139,14 +139,33 @@ static std::unordered_map<std::string_view, int> keys({
{ MAP_KEY(GLFW_KEY_MENU) }, { MAP_KEY(GLFW_KEY_MENU) },
}); });
static std::unordered_map<std::string_view, int> modifiers({
{ MAP_KEY(GLFW_MOD_SHIFT) },
{ MAP_KEY(GLFW_MOD_CONTROL) },
{ MAP_KEY(GLFW_MOD_ALT) },
{ MAP_KEY(GLFW_MOD_SUPER) },
{ MAP_KEY(GLFW_MOD_CAPS_LOCK) }, // State, not really a modifier
{ MAP_KEY(GLFW_MOD_NUM_LOCK) }, // State, not really a modifier
});
// ----------------------------------------- // -----------------------------------------
// Example usage:
// event.getKey() == keyCode("GLFW_KEY_ESCAPE")
int keyCode(std::string_view name) int keyCode(std::string_view name)
{ {
VERIFY(keys.find(name) != keys.end(), "could not find key code: {}", name); VERIFY(keys.find(name) != keys.end(), "could not find key code: {}", name);
return keys.at(name); return keys.at(name);
} }
// Example usage:
// event.getMods() & keyMod("GLFW_MOD_SHIFT")
int keyMod(std::string_view name)
{
VERIFY(modifiers.find(name) != modifiers.end(), "could not find key modifier: {}", name);
return modifiers.at(name);
}
std::string_view keyName(int key) std::string_view keyName(int key)
{ {
auto it = std::find_if(keys.begin(), keys.end(), [key](const auto& keybind) { auto it = std::find_if(keys.begin(), keys.end(), [key](const auto& keybind) {

4
src/inferno/keycodes.h

@ -13,6 +13,8 @@
namespace Inferno { namespace Inferno {
int keyCode(std::string_view name); int keyCode(std::string_view name);
std::string_view keyName(int); int keyMod(std::string_view name);
std::string_view keyName(int key);
} // namespace Inferno } // namespace Inferno

6
src/inferno/window.cpp

@ -122,17 +122,17 @@ void Window::initialize()
switch (action) { switch (action) {
case GLFW_PRESS: { case GLFW_PRESS: {
KeyPressEvent event(key); KeyPressEvent event(key, mods);
w.m_eventCallback(event); w.m_eventCallback(event);
break; break;
} }
case GLFW_RELEASE: { case GLFW_RELEASE: {
KeyReleaseEvent event(key); KeyReleaseEvent event(key, mods);
w.m_eventCallback(event); w.m_eventCallback(event);
break; break;
} }
case GLFW_REPEAT: { case GLFW_REPEAT: {
KeyRepeatEvent event(key); KeyRepeatEvent event(key, mods);
w.m_eventCallback(event); w.m_eventCallback(event);
break; break;
} }

Loading…
Cancel
Save