From 9457b112cd2d0be20871fa2a07c5364687582177 Mon Sep 17 00:00:00 2001 From: Jean Tampon Date: Mon, 29 Nov 2021 23:08:29 +0100 Subject: [PATCH] Adding toolbox --- include/common/dynamic_blur.hpp | 162 +++++++++++++++++++++++++ include/common/viewport_handler.hpp | 6 + include/editor/ world_view.hpp | 48 ++++++++ include/editor/GUI/button.hpp | 4 +- include/editor/GUI/named_container.hpp | 10 +- include/editor/GUI/scene.hpp | 11 +- include/editor/GUI/text_label.hpp | 17 ++- include/editor/editor_scene.hpp | 105 ++++------------ include/editor/game_view.hpp | 48 +------- include/editor/tool_selector.hpp | 4 +- include/editor/toolbox.hpp | 3 + include/simulation/simulation.hpp | 1 + src/main.cpp | 64 +++++----- 13 files changed, 300 insertions(+), 183 deletions(-) create mode 100644 include/common/dynamic_blur.hpp create mode 100644 include/editor/ world_view.hpp diff --git a/include/common/dynamic_blur.hpp b/include/common/dynamic_blur.hpp new file mode 100644 index 00000000..2f026fb7 --- /dev/null +++ b/include/common/dynamic_blur.hpp @@ -0,0 +1,162 @@ +#pragma once +#include +#include + +constexpr char VERTEX_SHADER_SRC[] = +"void main() \ +{ \ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; \ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \ +}"; + +constexpr char FRAG_X_SHADER_SRC[] = +"uniform sampler2D texture; \ +uniform float WIDTH; \ +float WIDTH_STEP = 1.0 / WIDTH; \ +void main() \ +{ \ + vec2 pos = gl_TexCoord[0].xy; \ + vec2 offset = vec2(WIDTH_STEP, 0.0); \ + vec4 color = texture2D(texture, pos) * 0.383; \ + color += texture2D(texture, pos + offset * 1.5) * 0.242; \ + color += texture2D(texture, pos + offset * 2.5) * 0.061; \ + color += texture2D(texture, pos + offset * 3.5) * 0.006; \ + color += texture2D(texture, pos - offset * 1.5) * 0.242; \ + color += texture2D(texture, pos - offset * 2.5) * 0.061; \ + color += texture2D(texture, pos - offset * 3.5) * 0.006; \ + gl_FragColor = vec4(color.xyz, 1.0); \ +}"; + +constexpr char FRAG_Y_SHADER_SRC[] = +"uniform sampler2D texture; \ +uniform float HEIGHT; \ +float HEIGHT_STEP = 1.0 / HEIGHT; \ +void main() \ +{ \ + vec2 pos = gl_TexCoord[0].xy; \ + vec2 offset = vec2(0.0, HEIGHT_STEP); \ + vec4 color = texture2D(texture, pos) * 0.383; \ + color += texture2D(texture, pos + offset * 1.5) * 0.242; \ + color += texture2D(texture, pos + offset * 2.5) * 0.061; \ + color += texture2D(texture, pos + offset * 3.5) * 0.006; \ + color += texture2D(texture, pos - offset * 1.5) * 0.242; \ + color += texture2D(texture, pos - offset * 2.5) * 0.061; \ + color += texture2D(texture, pos - offset * 3.5) * 0.006; \ + gl_FragColor = vec4(color.xyz, 1.0); \ +}"; + +class Blur +{ +public: + Blur(sf::Vector2u render_size, int32_t iterations, float quality = 1.0f) + : m_render_size({static_cast(render_size.x * quality), static_cast(render_size.y * quality)}) + , m_iterations(iterations) + , m_quality(quality) + { + createTextures(); + createShaders(); + } + + sf::Sprite& apply(const sf::Texture& texture) + { + // Retrieve texture content and downscale it + sf::Sprite sprite(texture); + uint32_t current_buffer = 0; + m_textures[current_buffer].draw(sprite); + for (int32_t i(0); i= 0; i -= 3) { + current_buffer = blurPass(current_buffer, i); + } + m_textures[current_buffer].display(); + m_result.setTexture(m_textures[current_buffer].getTexture()); + return m_result; + } + +private: + sf::Vector2i m_render_size; + int32_t m_iterations; + sf::RenderTexture m_textures[2]; + float m_quality; + + // Shaders + sf::Shader m_horizontal; + sf::Shader m_vertical; + sf::Sprite m_result; + + // Methods + void createTextures() + { + // Initialize textures + m_textures[0].create(m_render_size.x, m_render_size.y); + m_textures[1].create(m_render_size.x, m_render_size.y); + m_textures[0].setSmooth(true); + m_textures[1].setSmooth(true); + m_textures[0].setRepeated(true); + m_textures[1].setRepeated(true); + // Update clear + m_textures[0].display(); + m_textures[1].display(); + } + + void createShaders() + { + m_horizontal.loadFromMemory(VERTEX_SHADER_SRC, FRAG_X_SHADER_SRC); + m_vertical.loadFromMemory(VERTEX_SHADER_SRC, FRAG_Y_SHADER_SRC); + // Set pixel steps in shader + m_horizontal.setUniform("WIDTH", static_cast(m_render_size.x)); + m_vertical.setUniform("HEIGHT", static_cast(m_render_size.y)); + } + + void clear(uint32_t texture_id) + { + m_textures[texture_id].clear(sf::Color::Black); + } + + void draw(const sf::Sprite& sprite, uint32_t dest_buffer, const sf::Shader& shader) + { + clear(dest_buffer); + m_textures[dest_buffer].draw(sprite, &shader); + } + + void draw(const sf::Sprite& sprite, uint32_t dest_buffer) + { + clear(dest_buffer); + m_textures[dest_buffer].draw(sprite); + } + + const sf::Texture& getTexture(uint32_t source_buffer) + { + return m_textures[source_buffer].getTexture(); + } + + uint32_t blurPass(uint32_t source_buffer, int32_t downscale) + { + // Initialize scales and rectangle + const auto inv_scale = static_cast(1 << downscale); + const float scale = 1.0f / inv_scale; + const int32_t current_pass_size_x = m_render_size.x >> downscale; + const int32_t current_pass_size_y = m_render_size.y >> downscale; + // Draw from source to target with separate blur passes + sf::Sprite sprite; + sprite.setScale(scale, scale); + sprite.setTexture(getTexture(source_buffer)); + draw(sprite, !source_buffer); + + sprite.setScale(1.0f, 1.0f); + sprite.setTexture(getTexture(!source_buffer)); + sprite.setTextureRect({0, 0, current_pass_size_x, current_pass_size_y}); + draw(sprite, source_buffer, m_horizontal); + + sprite.setTexture(getTexture(source_buffer)); + draw(sprite, !source_buffer, m_vertical); + + const float safe_scale = 1.0f; + sprite.setScale(inv_scale * safe_scale, inv_scale * safe_scale); + sprite.setTexture(getTexture(!source_buffer)); + draw(sprite, source_buffer); + + return source_buffer; + } +}; diff --git a/include/common/viewport_handler.hpp b/include/common/viewport_handler.hpp index 6541b5ab..623a5fd6 100644 --- a/include/common/viewport_handler.hpp +++ b/include/common/viewport_handler.hpp @@ -77,6 +77,7 @@ struct ViewportHandler setFocus(state.center); } + [[nodiscard]] const sf::RenderStates& getRenderState() const { return state.state; @@ -87,6 +88,11 @@ struct ViewportHandler state.mouse_position = relative_click_position; state.clicking = true; } + + void click() + { + state.clicking = true; + } void unclick() { diff --git a/include/editor/ world_view.hpp b/include/editor/ world_view.hpp new file mode 100644 index 00000000..1a3f4bd5 --- /dev/null +++ b/include/editor/ world_view.hpp @@ -0,0 +1,48 @@ +#pragma once +#include "GUI/item.hpp" +#include "render/renderer.hpp" + + +namespace edtr +{ + +struct WorldView : GUI::Item +{ + World& world; + Renderer renderer; + + explicit + WorldView(sf::Vector2f size_, World& world_) + : GUI::Item(size_) + , world(world_) + { + } + + void initializeEventCallbacks() override + { + addEventCallback(sf::Event::MouseWheelScrolled, [&](sfev::CstEv e){renderer.vp_handler.wheelZoom(e.mouseWheelScroll.delta);}); + addKeyPressedCallback(sf::Keyboard::R, [&](sfev::CstEv e){renderer.vp_handler.reset();}); + } + + void onClick(sf::Vector2f relative_click_position, sf::Mouse::Button) override + { + renderer.vp_handler.click(relative_click_position); + } + + void onUnclick(sf::Mouse::Button) override + { + renderer.vp_handler.unclick(); + } + + void onMouseMove(sf::Vector2f new_mouse_position) override + { + renderer.vp_handler.setMousePosition(new_mouse_position); + } + + void render(sf::RenderTarget& target) override + { + renderer.render(world, target); + } +}; + +} diff --git a/include/editor/GUI/button.hpp b/include/editor/GUI/button.hpp index 4c21b09f..3ca967b3 100644 --- a/include/editor/GUI/button.hpp +++ b/include/editor/GUI/button.hpp @@ -33,13 +33,13 @@ struct DefaultButton : public GUI::Item struct Button : public DefaultButton { - float angle_radius = 10.0f; + float angle_radius = 5.0f; SPtr label; Button(const std::string& text, ButtonCallBack callback) : DefaultButton(callback) { - label = create(text, 32); + label = create(text, 14); label->catch_event = false; addItem(label); } diff --git a/include/editor/GUI/named_container.hpp b/include/editor/GUI/named_container.hpp index 3d63bb1e..81f41e2c 100644 --- a/include/editor/GUI/named_container.hpp +++ b/include/editor/GUI/named_container.hpp @@ -14,13 +14,13 @@ struct NamedContainer : public Container NamedContainer(const std::string& name, Container::Orientation orientation = Container::Orientation::Vertical) : Container(Container::Orientation::Vertical) { - padding = 10.0f; - spacing = 5.0f; + padding = 7.0f; + spacing = 0.0f; size_type.y = Size::FitContent; - label = create(name, 24); + label = create(name, 14); label->setColor(sf::Color(100, 100, 100)); - label->setHeight(30.0f); + label->setHeight(20.0f); label->setAlignement(Alignement::Left); root = create(orientation); @@ -38,7 +38,7 @@ struct NamedContainer : public Container void render(sf::RenderTarget& target) override { - const float angle_radius = 20.0f; + const float angle_radius = 10.0f; RoundedRectangle background(size, position, angle_radius); const uint8_t background_intensity = 220; background.setFillColor(sf::Color(background_intensity, background_intensity, background_intensity)); diff --git a/include/editor/GUI/scene.hpp b/include/editor/GUI/scene.hpp index be575915..5d75a933 100644 --- a/include/editor/GUI/scene.hpp +++ b/include/editor/GUI/scene.hpp @@ -12,17 +12,18 @@ struct Scene { using Ptr = std::shared_ptr; - sf::RenderWindow& window; - sfev::EventManager event_manager; - sf::Vector2f mouse_position; - + sf::RenderWindow& window; + sfev::EventManager event_manager; + sf::Vector2f mouse_position; + Item root; Scene(sf::RenderWindow& window_) : window(window_) , event_manager(window_, false) - , root(toVector2f(window_.getSize())) + , root(toVector2f(window_.getSize())) { + const auto size = window_.getSize(); initializeEventsCallbacks(); } diff --git a/include/editor/GUI/text_label.hpp b/include/editor/GUI/text_label.hpp index dd9a0efa..4142e797 100644 --- a/include/editor/GUI/text_label.hpp +++ b/include/editor/GUI/text_label.hpp @@ -35,6 +35,7 @@ struct TextLabel : public Item void onSizeChange() override { + updateOrigin(); updateTextPosition(); } @@ -61,10 +62,14 @@ struct TextLabel : public Item const auto text_bounds = text.getGlobalBounds(); switch (alignement) { case Alignement::Center: - text.setOrigin(text_bounds.width * 0.5f, text_bounds.height); + text.setOrigin(text_bounds.width * 0.5f - size.x * 0.5f, text_bounds.height - size.y * 0.5f); break; case Alignement::Left: text.setOrigin({}); + break; + case Alignement::Right: + text.setOrigin(text_bounds.width - size.x, 0.0f); + break; default: break; } @@ -72,15 +77,7 @@ struct TextLabel : public Item void updateTextPosition() { - switch (alignement) { - case Alignement::Center: - text.setPosition(position + size * 0.5f); - break; - case Alignement::Left: - text.setPosition(position); - default: - break; - } + text.setPosition(position); } void render(sf::RenderTarget& target) override diff --git a/include/editor/editor_scene.hpp b/include/editor/editor_scene.hpp index b31ac4c6..8b58ae19 100644 --- a/include/editor/editor_scene.hpp +++ b/include/editor/editor_scene.hpp @@ -8,6 +8,10 @@ #include "GUI/empty_item.hpp" #include "GUI/named_container.hpp" #include "tool_selector.hpp" +#include "simulation/world/world.hpp" +#include "render/renderer.hpp" +#include "simulation/config.hpp" +#include "editor/ world_view.hpp" namespace edtr @@ -17,104 +21,47 @@ struct EditorScene : public GUI::Scene { using Ptr = std::shared_ptr; + World world; - SPtr toolbox; - SPtr renderer; + SPtr renderer; SPtr color_picker; SPtr color_saver; SPtr set_color_button; SPtr tool_selector; - + + explicit EditorScene(sf::RenderWindow& window) : GUI::Scene(window) + , world(Conf::WORLD_WIDTH, Conf::WORLD_HEIGHT) { + Conf::loadTextures(); initialize(); } + + ~EditorScene() + { + std::cout << "Exiting, clean resources" << std::endl; + Conf::freeTextures(); + } void initialize() { + MapLoader::loadMap(world, "res/map.png"); + const sf::Vector2u window_size = window.getSize(); - toolbox = create(sf::Vector2f(450.0f, to(window_size.y))); - color_picker = create(); - color_saver = create(); + + renderer = create(toVector2f(window_size), world); + + toolbox = create(sf::Vector2f(350.0f, to(window_size.y))); tool_selector = create(); - - // Atoms editing group - SPtr atom_editing = create(GUI::Container::Orientation::Horizontal); - atom_editing->size_type.y = GUI::Size::FitContent; - atom_editing->padding = 0.0f; - - // Brush radius - SPtr brush_radius_group = create("Brush radius"); - // Slider - SPtr slider = create(10.0f, 1.0f); - root.watch(slider, [this, slider](){ - }); - brush_radius_group->addItem(slider); - - // Brush selector - SPtr brush_type_group = create("Brush mode"); - brush_type_group->addItem(tool_selector); - root.watch(tool_selector, [this](){ + auto container = create("Tools", GUI::Container::Orientation::Horizontal); + container->addItem(tool_selector); + toolbox->addItem(container); - }); - - // Colors - SPtr colors = create("Color picker", GUI::Container::Orientation::Vertical); - colors->name = "Colors Group"; - SPtr atom_color = create(GUI::Container::Orientation::Horizontal); - set_color_button = create("Set Color", [&](){}); - const float color_button_height = 80.0f; - set_color_button->setHeight(color_button_height); - atom_color->size_type.y = GUI::Size::FitContent; - atom_color->padding = 0.0f; - // Add buttons to atom_color - atom_color->addItem(set_color_button); - atom_color->addItem(color_saver->current_color_add); - // Add items to scene - colors->addItem(atom_color); - colors->addItem(color_picker); - colors->addItem(color_saver); - // Create GUI elements - // Force toolbox to fit window's height - toolbox->size_type.y = GUI::Size::Fixed; - - const float edit_button_height = 100.0f; - SPtr create_atoms = create("Add", [&](){ - }); - create_atoms->setHeight(edit_button_height); - - SPtr delete_atoms = create("Remove", [&](){ - }); - delete_atoms->setHeight(edit_button_height); - - root.watch(color_saver, [&](){ - set_color_button->color = color_saver->loaded_color; - }); - // Add buttons to atom_editing - atom_editing->addItem(create_atoms); - atom_editing->addItem(delete_atoms); - toolbox->addItem(atom_editing); - toolbox->addItem(brush_radius_group); - toolbox->addItem(brush_type_group); - toolbox->addItem(create()); - toolbox->addItem(colors, "Colors Group"); - - toolbox->watch(color_picker, [&](){ - updateInterfaceColor(); - }); - + addItem(renderer); addItem(toolbox, "Toolbox"); - - updateInterfaceColor(); - } - - void updateInterfaceColor() - { - color_saver->current_color_add->setColor(color_picker->getColor()); - set_color_button->color = color_picker->getColor(); } }; diff --git a/include/editor/game_view.hpp b/include/editor/game_view.hpp index 11cb1b6c..10c077f5 100644 --- a/include/editor/game_view.hpp +++ b/include/editor/game_view.hpp @@ -1,7 +1,5 @@ #pragma once -#include -#include #include "GUI/item.hpp" @@ -11,51 +9,19 @@ namespace edtr struct GameView : public GUI::Item { bool pause = false; - Engine engine; ViewportHandler vp_handler; - bool moving_object; - uint64_t last_object; - + + explicit GameView(sf::Vector2f size_) : GUI::Item(size_) - , engine(512, 512) , vp_handler(size) { - PhysicObject ground(512, 4, 0.0f, 0.0f); - ground.setBottomStatic(); - ground.position = Vec2(256.0f, 508.0f); - engine.addEntity(ground); - - vp_handler.setFocus(Vec2(256.0f, 410.0f)); vp_handler.setZoom(7.5f); } - void resetObjects() - { - - } - - void addEntity(const PhysicObject& e) - { - pause = true; - moving_object = true; - last_object = engine.addEntity(e); - engine.getRef(last_object).physic_object->need_break_check = true; - engine.checkForParts(); - } - void initializeEventCallbacks() override { addEventCallback(sf::Event::MouseWheelScrolled, [&](sfev::CstEv e){vp_handler.wheelZoom(e.mouseWheelScroll.delta);}); - addKeyPressedCallback(sf::Keyboard::Space, [&](sfev::CstEv){play_stop();}); - } - - void play_stop() - { - if (pause) { - moving_object = false; - } - pause = !pause; } void onClick(sf::Vector2f relative_click_position, sf::Mouse::Button) override @@ -71,23 +37,15 @@ struct GameView : public GUI::Item void onMouseMove(sf::Vector2f new_mouse_position) override { vp_handler.setMousePosition(new_mouse_position); - if (moving_object) { - const sf::Vector2f world_pos = vp_handler.getMouseWorldPosition(); - engine.getRef(last_object).physic_object->position = Vec2(world_pos.x, world_pos.y); - } } void update() override { - constexpr float dt = 1.0f / 60.0f; - if (!pause) { - engine.update(dt); - } + } void render(sf::RenderTarget& target) override { - engine.render(target, vp_handler.getRenderState()); GUI::Item::render(target); } }; diff --git a/include/editor/tool_selector.hpp b/include/editor/tool_selector.hpp index f1303747..c848f2b5 100644 --- a/include/editor/tool_selector.hpp +++ b/include/editor/tool_selector.hpp @@ -29,7 +29,7 @@ struct ToolOption : public GUI::Button void render(sf::RenderTarget& target) override { - const float angle_radius = 10.0f; + const float angle_radius = 5.0f; const sf::Vector2f current_padding = sf::Vector2f(select_padding, select_padding); const sf::Vector2f inner_size = size - 2.0f * current_padding; const sf::Vector2f inner_offset = 0.5f * (size - inner_size); @@ -64,7 +64,7 @@ struct ToolSelector : public GUI::Container , current_tool(Tool::BrushCreate) { padding = 0.0f; - setHeight(70.0f); + setHeight(30.0f); tool_create = create("Create", [this](){ current_tool = Tool::BrushCreate; select(tool_create); diff --git a/include/editor/toolbox.hpp b/include/editor/toolbox.hpp index 997eec07..a9161a5a 100644 --- a/include/editor/toolbox.hpp +++ b/include/editor/toolbox.hpp @@ -3,12 +3,15 @@ #include "color_picker.hpp" #include "GUI/container.hpp" #include "slider.hpp" +#include "common/dynamic_blur.hpp" + namespace edtr { struct Toolbox : public GUI::Container { + explicit Toolbox(sf::Vector2f size_, sf::Vector2f position_ = {}) : GUI::Container(GUI::Container::Orientation::Vertical, size_, position_) {} diff --git a/include/simulation/simulation.hpp b/include/simulation/simulation.hpp index d725ba61..674a228c 100644 --- a/include/simulation/simulation.hpp +++ b/include/simulation/simulation.hpp @@ -21,6 +21,7 @@ struct Simulation FightSystem fight_system; sf::Clock clock; + explicit Simulation(sf::Window& window) : world(Conf::WORLD_WIDTH, Conf::WORLD_HEIGHT) , renderer() diff --git a/src/main.cpp b/src/main.cpp index 6942db2e..b87985c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,55 +5,49 @@ #include "simulation/world/distance_field_builder.hpp" #include "simulation/simulation.hpp" #include "editor/editor_scene.hpp" +#include "editor/game_scene.hpp" int main() { - Conf::loadTextures(); - if (!Conf::loadUserConf()) { - std::cout << "Couldn't find 'conf.txt', loading default" << std::endl; + if (Conf::loadUserConf()) { + std::cout << "OK" << std::endl; + } else { + std::cout << "Not OK" << std::endl; } - sf::ContextSettings settings; settings.antialiasingLevel = 1; int32_t window_style = Conf::USE_FULLSCREEN ? sf::Style::Fullscreen : sf::Style::Default; sf::RenderWindow window(sf::VideoMode(Conf::WIN_WIDTH, Conf::WIN_HEIGHT), "AntSim", window_style, settings); window.setFramerateLimit(60); - Simulation simulation(window); - const float margin = 160.0f; - simulation.createColony(margin, margin); - simulation.createColony(Conf::WORLD_WIDTH - margin, Conf::WORLD_HEIGHT - margin); - simulation.loadMap("res/map.png"); - simulation.renderer.vp_handler.reset(); - - sf::Clock clock; - RMean fps(100); - sf::Text fps_text; - sf::Font fps_font; - fps_font.loadFromFile("res/font.ttf"); - fps_text.setFont(fps_font); - fps_text.setCharacterSize(32); - fps_text.setFillColor(sf::Color::White); - fps_text.setPosition(10.0f, 10.0f); - const float dt = 0.016f; + // Main scenes + GUI::Scene::Ptr editor = create(window); + GUI::Scene::Ptr game = edtr::createGameScene(window); + GUI::Scene::Ptr current_scene = editor; + // Add switches + const sf::Vector2f switch_size(120.0f, 40.0f); + SPtr editor_to_game = create("To Game View", [&](){ + current_scene = game; + }); + editor_to_game->setSize(switch_size); + editor->addItem(editor_to_game, "ToGame", GUI::Alignement::Right); + SPtr game_to_editor = create("To Editor View", [&](){ + current_scene = editor; + }); + game_to_editor->setSize(switch_size); + game->getByName("view")->addItem(game_to_editor, "", GUI::Alignement::Right); while (window.isOpen()) { - // Update simulation - simulation.processEvents(); - simulation.update(dt); - // Update FPS metric - fps_text.setString(toStr(fps.get())); - // Render simulation - window.clear(sf::Color(94, 87, 87)); - simulation.render(window); - window.draw(fps_text); - window.display(); - // Add render time to the counter - fps.addValue(1.0f / clock.restart().asSeconds()); + current_scene->update(); + // Render + window.clear(); + current_scene->render(); + window.display(); } - // Free textures - Conf::freeTextures(); + + current_scene = nullptr; + editor = nullptr; return 0; }