diff --git a/CMakeLists.txt b/CMakeLists.txt index 36aa73537..589b90f49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,6 +272,7 @@ set ( noggit_ui_sources src/noggit/ui/noggit_tool.cpp src/noggit/ui/ObjectEditor.cpp src/noggit/ui/RotationEditor.cpp + src/noggit/ui/shadow_editor.cpp src/noggit/ui/slider_spinbox.cpp src/noggit/ui/TexturePicker.cpp src/noggit/ui/texture_swapper.cpp @@ -388,6 +389,7 @@ set ( noggit_ui_headers src/noggit/ui/noggit_tool.hpp src/noggit/ui/ObjectEditor.h src/noggit/ui/RotationEditor.h + src/noggit/ui/shadow_editor.hpp src/noggit/ui/slider_spinbox.hpp src/noggit/ui/TexturePicker.h src/noggit/ui/texture_swapper.hpp diff --git a/src/noggit/MapChunk.cpp b/src/noggit/MapChunk.cpp index 818a6ea7c..94f5d3bbb 100644 --- a/src/noggit/MapChunk.cpp +++ b/src/noggit/MapChunk.cpp @@ -1489,6 +1489,51 @@ void MapChunk::clear_shadows() _chunk_shadow.reset(); } +void MapChunk::set_shadow(math::vector_3d const& pos, float radius, bool add) +{ + if (misc::getShortestDist(pos.x, pos.z, xbase, zbase, CHUNKSIZE) > radius) + { + return; + } + + if (!_chunk_shadow) + { + _chunk_shadow = std::make_unique(); + } + + math::vector_3d p(xbase, 0.f, zbase); + + for (int ix = 0; ix < 64; ++ix) + { + p.z = zbase; + + for (int iz = 0; iz < 64; ++iz) + { + if (misc::getShortestDist(pos, p, TEXDETAILSIZE) <= radius) + { + std::uint64_t& value = _chunk_shadow.get()->data[iz]; + std::uint64_t flag = std::uint64_t(1) << ix; + + if (add) + { + value |= flag; + } + else + { + value &= ~flag; + } + } + + p.z += TEXDETAILSIZE; + } + + p.x += TEXDETAILSIZE; + } + + texture_set_changed(); + texture_set->require_update(); // shadows are tied with the alphamap +} + bool MapChunk::isHole(int i, int j) const { if (_preview_data) diff --git a/src/noggit/MapChunk.h b/src/noggit/MapChunk.h index 2a4352392..2e9bca291 100644 --- a/src/noggit/MapChunk.h +++ b/src/noggit/MapChunk.h @@ -211,6 +211,7 @@ class MapChunk void clear_texture_flags(); void clear_shadows(); + void set_shadow(math::vector_3d const& pos, float radius, bool add); //! \todo implement Action stack for these bool isHole(int i, int j) const; diff --git a/src/noggit/MapView.cpp b/src/noggit/MapView.cpp index 66c8d4130..575d48af5 100644 --- a/src/noggit/MapView.cpp +++ b/src/noggit/MapView.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include // noggit::ui::toolbar @@ -153,6 +154,10 @@ void MapView::setToolPropertyWidgetVisibility(editing_mode mode) _chunk_mover_dock->setVisible(!ui_hidden); _current_tool = _chunk_mover_ui; break; + case editing_mode::shadows: + _shadow_tool_dock->setVisible(!ui_hidden); + _current_tool = _shadow_tool; + break; } } @@ -301,6 +306,12 @@ void MapView::createGUI() _chunk_mover_dock->setWidget(_chunk_mover_ui); _tool_properties_docks.insert(_chunk_mover_dock); + // shadow tool + _shadow_tool_dock = new QDockWidget("Shadow Tool", this); + _shadow_tool = new noggit::ui::shadow_editor(_shadow_tool_dock); + _shadow_tool_dock->setWidget(_shadow_tool); + _tool_properties_docks.insert(_shadow_tool_dock); + for (auto widget : _tool_properties_docks) { connect(this, &QObject::destroyed, widget, &QObject::deleteLater); @@ -2503,6 +2514,9 @@ void MapView::draw_map() case editing_mode::chunk_mover: radius = _chunk_mover_ui->radius(); break; + case editing_mode::shadows: + radius = _shadow_tool->radius(); + break; } bool use_liquid_intersect = terrainMode == editing_mode::water && guiWater->use_liquids_intersect(); diff --git a/src/noggit/MapView.h b/src/noggit/MapView.h index 5edb6a9cd..1e3cdbb8f 100644 --- a/src/noggit/MapView.h +++ b/src/noggit/MapView.h @@ -43,6 +43,7 @@ namespace noggit class help; class minimap_widget; class shader_tool; + class shadow_editor; class terrain_tool; class texture_picker; class texturing_tool; @@ -334,5 +335,8 @@ public slots: noggit::ui::chunk_mover_ui* _chunk_mover_ui; QDockWidget* _chunk_mover_dock; + noggit::ui::shadow_editor* _shadow_tool; + QDockWidget* _shadow_tool_dock; + noggit::ui::noggit_tool* _current_tool = nullptr; }; diff --git a/src/noggit/World.cpp b/src/noggit/World.cpp index a7450a13d..6dbf3d225 100644 --- a/src/noggit/World.cpp +++ b/src/noggit/World.cpp @@ -2180,6 +2180,18 @@ void World::setHoleADT(math::vector_3d const& pos, bool hole) for_all_chunks_on_tile(pos, [&](MapChunk* chunk) { chunk->setHole(pos, true, hole); }); } +void World::set_shadow(math::vector_3d const& pos, float radius, bool add) +{ + for_all_chunks_in_range + ( pos, radius + , [&](MapChunk* chunk) + { + chunk->set_shadow(pos, radius, add); + return true; + } + ); +} + template void World::for_all_chunks_on_tile (math::vector_3d const& pos, Fun&& fun) diff --git a/src/noggit/World.h b/src/noggit/World.h index a2ee66cb6..8cc464a9d 100644 --- a/src/noggit/World.h +++ b/src/noggit/World.h @@ -285,6 +285,8 @@ class World void setHole(math::vector_3d const& pos, bool big, bool hole); void setHoleADT(math::vector_3d const& pos, bool hole); + void set_shadow(math::vector_3d const& pos, float radius, bool add); + ModelInstance* addM2 ( std::string const& filename , math::vector_3d newPos , float scale, math::degrees::vec3 rotation diff --git a/src/noggit/tool_enums.hpp b/src/noggit/tool_enums.hpp index 3e1716920..aeaf23f6d 100644 --- a/src/noggit/tool_enums.hpp +++ b/src/noggit/tool_enums.hpp @@ -83,6 +83,7 @@ enum class editing_mode #endif clearing, chunk_mover, + shadows, }; enum class water_opacity : int diff --git a/src/noggit/ui/Help.cpp b/src/noggit/ui/Help.cpp index 3c18c972c..e8b44a897 100644 --- a/src/noggit/ui/Help.cpp +++ b/src/noggit/ui/Help.cpp @@ -318,6 +318,14 @@ namespace noggit generate_hotkey_row({ font_noggit::t }, "\a - Toggle preview", chunk_mover_layout); generate_hotkey_row({ font_noggit::space, font_noggit::mmb }, "\a+\a - Change height offset", chunk_mover_layout); + + auto shadow_widget(new QWidget(this)); + auto shadow_layout(new QFormLayout(shadow_widget)); + + generate_hotkey_row({ font_noggit::shift, font_noggit::lmb }, "\a+\a - Add shadows", shadow_layout); + generate_hotkey_row({ font_noggit::ctrl, font_noggit::lmb }, "\a+\a - Remove shadows", shadow_layout); + generate_hotkey_row({ font_noggit::alt, font_noggit::lmb_drag }, "\a+\a - Change brush size", shadow_layout); + layout->addWidget(tabs); tabs->addTab(base_widget, "Base"); tabs->addTab(ground_widget, "Terrain"); @@ -328,6 +336,7 @@ namespace noggit tabs->addTab(flag_widget, "Flags/Hole/Area"); tabs->addTab(clearing_widget, "Clearing"); tabs->addTab(chunk_mover_widget, "Chunk Mover"); + tabs->addTab(shadow_widget, "Shadows"); } diff --git a/src/noggit/ui/Toolbar.cpp b/src/noggit/ui/Toolbar.cpp index a00501e3d..bf846fef2 100644 --- a/src/noggit/ui/Toolbar.cpp +++ b/src/noggit/ui/Toolbar.cpp @@ -24,6 +24,7 @@ namespace noggit #endif add_tool_icon(editing_mode::clearing, tr("Clearing Tool"), font_awesome::eraser); add_tool_icon(editing_mode::chunk_mover, tr("Chunk Mover"), font_awesome::arrowsalt); + add_tool_icon(editing_mode::shadows, tr("Shadows Editor"), font_awesome::cloudsun); } void toolbar::add_tool_icon(editing_mode mode, const QString& name, const font_awesome::icons& icon) diff --git a/src/noggit/ui/shadow_editor.cpp b/src/noggit/ui/shadow_editor.cpp new file mode 100644 index 000000000..e8601de9e --- /dev/null +++ b/src/noggit/ui/shadow_editor.cpp @@ -0,0 +1,46 @@ +// This file is part of Noggit3, licensed under GNU General Public License (version 3). + +#include +#include +#include + + +#include +#include + + +namespace noggit::ui +{ + shadow_editor::shadow_editor(QWidget* parent) + : noggit_tool(parent) + , _radius_property(10.f) + { + auto layout(new QFormLayout(this)); + + layout->addWidget(new slider_spinbox("Radius", &_radius_property, 0.f, 100.f, 2, this)); + } + + + void shadow_editor::tick(float dt, math::vector_3d const& cursor_pos, bool cursor_under_map, World* world) + { + if (!cursor_under_map && _left_mouse_button) + { + if (_mod_shift_down) + { + world->set_shadow(cursor_pos, _radius_property.get(), true); + } + if (_mod_ctrl_down) + { + world->set_shadow(cursor_pos, _radius_property.get(), false); + } + } + } + + void shadow_editor::mouse_move_event(QLineF const& relative_movement) + { + if (_left_mouse_button && _mod_alt_down) + { + change_radius(relative_movement.dx() / mouse_sensibility); + } + } +} diff --git a/src/noggit/ui/shadow_editor.hpp b/src/noggit/ui/shadow_editor.hpp new file mode 100644 index 000000000..9e01dfdf2 --- /dev/null +++ b/src/noggit/ui/shadow_editor.hpp @@ -0,0 +1,26 @@ +// This file is part of Noggit3, licensed under GNU General Public License (version 3). + +#pragma once + +#include +#include +#include + + +namespace noggit::ui +{ + class shadow_editor : public noggit_tool + { + public: + shadow_editor(QWidget* parent = nullptr); + + void change_radius(float change) { _radius_property.change(change); } + float radius() const { return _radius_property.get(); } + + virtual void tick(float dt, math::vector_3d const& cursor_pos, bool cursor_under_map, World* world) override; + virtual void mouse_move_event(QLineF const& relative_movement) override; + + private: + float_property _radius_property; + }; +}