Impl saving image with "S"
This commit is contained in:
parent
099b0e65d6
commit
3d266137d7
3 changed files with 154 additions and 62 deletions
|
@ -29,6 +29,7 @@ namespace Tri {
|
||||||
ImGui::Text("Press \"R\" to undo.");
|
ImGui::Text("Press \"R\" to undo.");
|
||||||
ImGui::Text("Press \"C\" to change colors");
|
ImGui::Text("Press \"C\" to change colors");
|
||||||
ImGui::Text("Press \"B\" to change background color");
|
ImGui::Text("Press \"B\" to change background color");
|
||||||
|
ImGui::Text("Press \"S\" to save what was drawn as a png image");
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +69,26 @@ namespace Tri {
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void draw_save(Tri::State *state) {
|
||||||
|
if(state->get_flags().test(6)) {
|
||||||
|
auto *filenameBuffer = state->get_save_filename_buffer();
|
||||||
|
ImGui::Begin("Save");
|
||||||
|
ImGui::InputText("Filename", filenameBuffer->data(), filenameBuffer->size() - 1);
|
||||||
|
if(ImGui::Button("Save")) {
|
||||||
|
if(state->do_save()) {
|
||||||
|
state->close_save();
|
||||||
|
}
|
||||||
|
} else if(ImGui::Button("Cancel")) {
|
||||||
|
state->close_save();
|
||||||
|
}
|
||||||
|
auto string_view = state->failed_save_message();
|
||||||
|
if(!string_view.empty()) {
|
||||||
|
ImGui::TextUnformatted(string_view.data(), string_view.data() + string_view.size());
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
180
src/state.cpp
180
src/state.cpp
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <imgui-SFML.h>
|
#include <imgui-SFML.h>
|
||||||
|
|
||||||
|
@ -35,6 +36,8 @@ bgColor(sf::Color::Black)
|
||||||
pointCircle.setFillColor(sf::Color::White);
|
pointCircle.setFillColor(sf::Color::White);
|
||||||
pointCircle.setOutlineColor(sf::Color::Black);
|
pointCircle.setOutlineColor(sf::Color::Black);
|
||||||
pointCircle.setOutlineThickness(1.0f);
|
pointCircle.setOutlineThickness(1.0f);
|
||||||
|
|
||||||
|
saveFilenameBuffer.fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tri::State::~State() {
|
Tri::State::~State() {
|
||||||
|
@ -49,60 +52,64 @@ void Tri::State::handle_events() {
|
||||||
window.close();
|
window.close();
|
||||||
flags.reset(1);
|
flags.reset(1);
|
||||||
} else if(event.type == sf::Event::KeyPressed) {
|
} else if(event.type == sf::Event::KeyPressed) {
|
||||||
if(event.key.code == sf::Keyboard::H) {
|
if(!flags.test(6)) {
|
||||||
flags.flip(0);
|
if(event.key.code == sf::Keyboard::H) {
|
||||||
} else if(event.key.code == sf::Keyboard::U) {
|
flags.flip(0);
|
||||||
if(currentTri_state > 0) {
|
} else if(event.key.code == sf::Keyboard::U) {
|
||||||
switch(currentTri_state) {
|
if(currentTri_state > 0) {
|
||||||
case FIRST:
|
switch(currentTri_state) {
|
||||||
currentTri_state = CurrentState::NONE;
|
case FIRST:
|
||||||
break;
|
currentTri_state = CurrentState::NONE;
|
||||||
case SECOND:
|
break;
|
||||||
currentTri_state = CurrentState::FIRST;
|
case SECOND:
|
||||||
break;
|
currentTri_state = CurrentState::FIRST;
|
||||||
default:
|
break;
|
||||||
assert(!"Unreachable code");
|
default:
|
||||||
break;
|
assert(!"Unreachable code");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(trisIndex > 0) {
|
||||||
|
--trisIndex;
|
||||||
}
|
}
|
||||||
} else if(trisIndex > 0) {
|
} else if(event.key.code == sf::Keyboard::R) {
|
||||||
--trisIndex;
|
if(currentTri_state != CurrentState::NONE
|
||||||
|
&& currentTri_state < currentTri_maxState) {
|
||||||
|
switch(currentTri_state) {
|
||||||
|
case NONE:
|
||||||
|
currentTri_state = CurrentState::FIRST;
|
||||||
|
break;
|
||||||
|
case FIRST:
|
||||||
|
currentTri_state = CurrentState::SECOND;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"Unreachable code");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(tris.size() > trisIndex) {
|
||||||
|
++trisIndex;
|
||||||
|
} else if(currentTri_state < currentTri_maxState) {
|
||||||
|
switch(currentTri_state) {
|
||||||
|
case NONE:
|
||||||
|
currentTri_state = CurrentState::FIRST;
|
||||||
|
break;
|
||||||
|
case FIRST:
|
||||||
|
currentTri_state = CurrentState::SECOND;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"Unreachable code");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(event.key.code == sf::Keyboard::C) {
|
||||||
|
flags.flip(2);
|
||||||
|
} else if(event.key.code == sf::Keyboard::B) {
|
||||||
|
flags.flip(5);
|
||||||
|
} else if(event.key.code == sf::Keyboard::S) {
|
||||||
|
flags.flip(6);
|
||||||
}
|
}
|
||||||
} else if(event.key.code == sf::Keyboard::R) {
|
|
||||||
if(currentTri_state != CurrentState::NONE
|
|
||||||
&& currentTri_state < currentTri_maxState) {
|
|
||||||
switch(currentTri_state) {
|
|
||||||
case NONE:
|
|
||||||
currentTri_state = CurrentState::FIRST;
|
|
||||||
break;
|
|
||||||
case FIRST:
|
|
||||||
currentTri_state = CurrentState::SECOND;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(!"Unreachable code");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if(tris.size() > trisIndex) {
|
|
||||||
++trisIndex;
|
|
||||||
} else if(currentTri_state < currentTri_maxState) {
|
|
||||||
switch(currentTri_state) {
|
|
||||||
case NONE:
|
|
||||||
currentTri_state = CurrentState::FIRST;
|
|
||||||
break;
|
|
||||||
case FIRST:
|
|
||||||
currentTri_state = CurrentState::SECOND;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(!"Unreachable code");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(event.key.code == sf::Keyboard::C) {
|
|
||||||
flags.flip(2);
|
|
||||||
} else if(event.key.code == sf::Keyboard::B) {
|
|
||||||
flags.flip(5);
|
|
||||||
}
|
}
|
||||||
} else if(event.type == sf::Event::MouseButtonPressed) {
|
} else if(event.type == sf::Event::MouseButtonPressed) {
|
||||||
if(!flags.test(2) && !flags.test(5)) {
|
if(!flags.test(2) && !flags.test(5) && !flags.test(6)) {
|
||||||
switch(currentTri_state) {
|
switch(currentTri_state) {
|
||||||
case CurrentState::NONE:
|
case CurrentState::NONE:
|
||||||
currentTri[0] = sf::Vector2f(event.mouseButton.x, event.mouseButton.y);
|
currentTri[0] = sf::Vector2f(event.mouseButton.x, event.mouseButton.y);
|
||||||
|
@ -170,24 +177,14 @@ void Tri::State::update() {
|
||||||
Tri::draw_show_help(this);
|
Tri::draw_show_help(this);
|
||||||
Tri::draw_color_picker(this);
|
Tri::draw_color_picker(this);
|
||||||
Tri::draw_bg_color_picker(this);
|
Tri::draw_bg_color_picker(this);
|
||||||
|
Tri::draw_save(this);
|
||||||
Tri::draw_help(this);
|
Tri::draw_help(this);
|
||||||
|
|
||||||
ImGui::EndFrame();
|
ImGui::EndFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tri::State::draw() {
|
void Tri::State::draw() {
|
||||||
window.clear(bgColor);
|
draw_to_target(&window);
|
||||||
|
|
||||||
// draw tris
|
|
||||||
for(unsigned int i = 0; i < trisIndex; ++i) {
|
|
||||||
window.draw(tris[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw points
|
|
||||||
for(unsigned int i = 0; i < currentTri_state; ++i) {
|
|
||||||
pointCircle.setPosition(currentTri[i]);
|
|
||||||
window.draw(pointCircle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw gui stuff
|
// draw gui stuff
|
||||||
ImGui::SFML::Render(window);
|
ImGui::SFML::Render(window);
|
||||||
|
@ -195,6 +192,23 @@ void Tri::State::draw() {
|
||||||
window.display();
|
window.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tri::State::draw_to_target(sf::RenderTarget *target, bool draw_points) {
|
||||||
|
target->clear(bgColor);
|
||||||
|
|
||||||
|
// draw tris
|
||||||
|
for(unsigned int i = 0; i < trisIndex; ++i) {
|
||||||
|
target->draw(tris[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw points
|
||||||
|
if(draw_points) {
|
||||||
|
for(unsigned int i = 0; i < currentTri_state; ++i) {
|
||||||
|
pointCircle.setPosition(currentTri[i]);
|
||||||
|
target->draw(pointCircle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int Tri::State::get_width() const {
|
unsigned int Tri::State::get_width() const {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
@ -220,3 +234,45 @@ float* Tri::State::get_bg_color() {
|
||||||
flags.set(4);
|
flags.set(4);
|
||||||
return bgColorPickerColor;
|
return bgColorPickerColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tri::State::FilenameBufferType* Tri::State::get_save_filename_buffer() {
|
||||||
|
return &saveFilenameBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tri::State::do_save() {
|
||||||
|
sf::RenderTexture saveTexture;
|
||||||
|
if(!saveTexture.create(width, height)) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
puts("ERROR: Failed to create texture for saving");
|
||||||
|
#endif
|
||||||
|
failedSaveMessage = std::string("Failed to create texture for saving");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_to_target(&saveTexture, false);
|
||||||
|
saveTexture.display();
|
||||||
|
|
||||||
|
sf::Image saveImage = saveTexture.getTexture().copyToImage();
|
||||||
|
std::string filename = std::string(saveFilenameBuffer.data());
|
||||||
|
if(saveImage.saveToFile(filename)) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
printf("Saved to \"%s\"\n", filename.c_str());
|
||||||
|
#endif
|
||||||
|
failedSaveMessage.clear();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
printf("ERROR: Failed to save \"%s\"\n", filename.c_str());
|
||||||
|
#endif
|
||||||
|
failedSaveMessage = std::string("Failed to save (does the name end in \".png\"?)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view Tri::State::failed_save_message() const {
|
||||||
|
return failedSaveMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tri::State::close_save() {
|
||||||
|
flags.reset(6);
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include <SFML/System.hpp>
|
#include <SFML/System.hpp>
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
@ -22,6 +23,7 @@ namespace Tri {
|
||||||
* 3 - color picker color dirty
|
* 3 - color picker color dirty
|
||||||
* 4 - bg color picker color dirty
|
* 4 - bg color picker color dirty
|
||||||
* 5 - display bg color picker
|
* 5 - display bg color picker
|
||||||
|
* 6 - draw save
|
||||||
*/
|
*/
|
||||||
typedef std::bitset<64> BitsetType;
|
typedef std::bitset<64> BitsetType;
|
||||||
BitsetType flags;
|
BitsetType flags;
|
||||||
|
@ -44,11 +46,19 @@ namespace Tri {
|
||||||
float bgColorPickerColor[3];
|
float bgColorPickerColor[3];
|
||||||
sf::Color bgColor;
|
sf::Color bgColor;
|
||||||
|
|
||||||
|
typedef std::array<char, 256> FilenameBufferType;
|
||||||
|
FilenameBufferType saveFilenameBuffer;
|
||||||
|
std::string failedSaveMessage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void handle_events();
|
void handle_events();
|
||||||
void update();
|
void update();
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void draw_to_target(sf::RenderTarget *target, bool draw_points = true);
|
||||||
|
|
||||||
|
public:
|
||||||
unsigned int get_width() const;
|
unsigned int get_width() const;
|
||||||
unsigned int get_height() const;
|
unsigned int get_height() const;
|
||||||
|
|
||||||
|
@ -58,6 +68,11 @@ namespace Tri {
|
||||||
|
|
||||||
float* get_color();
|
float* get_color();
|
||||||
float* get_bg_color();
|
float* get_bg_color();
|
||||||
|
|
||||||
|
FilenameBufferType* get_save_filename_buffer();
|
||||||
|
bool do_save();
|
||||||
|
std::string_view failed_save_message() const;
|
||||||
|
void close_save();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue