Merge branch 'tools_rewrite' into 'ground_effects_editor'

Tools rewrite

See merge request T1ti/noggit-red!4
This commit is contained in:
T1ti
2024-09-06 20:16:57 +00:00
65 changed files with 5795 additions and 3568 deletions

View File

@@ -106,8 +106,12 @@ FIND_PACKAGE(OpenGL REQUIRED)
FIND_PACKAGE(Json REQUIRED) FIND_PACKAGE(Json REQUIRED)
FIND_PACKAGE(lodepng REQUIRED) FIND_PACKAGE(lodepng REQUIRED)
set(FASTNOISE2_NOISETOOL OFF CACHE BOOL "") FetchContent_Declare(
FIND_PACKAGE(FastNoise2 REQUIRED) FastNoise2
GIT_REPOSITORY https://github.com/Auburn/FastNoise2.git
GIT_TAG v0.10.0-alpha
)
FetchContent_MakeAvailable(FastNoise2)
FIND_PACKAGE(Sol2 REQUIRED) FIND_PACKAGE(Sol2 REQUIRED)
FIND_PACKAGE(Qt5 COMPONENTS Widgets OpenGLExtensions Gui Network Xml Multimedia REQUIRED) FIND_PACKAGE(Qt5 COMPONENTS Widgets OpenGLExtensions Gui Network Xml Multimedia REQUIRED)

View File

@@ -544,7 +544,7 @@ void Noggit::Action::finish()
} }
if (_post) if (_post)
(_map_view->*_post)(); _post();
} }
float* Noggit::Action::getChunkTerrainOriginalData(MapChunk* chunk) float* Noggit::Action::getChunkTerrainOriginalData(MapChunk* chunk)
@@ -578,9 +578,9 @@ bool Noggit::Action::getBlockCursor() const
} }
void Noggit::Action::setPostCallback(auto(MapView::*method)()->void) void Noggit::Action::setPostCallback(std::function<void()> function)
{ {
_post = method; _post = function;
} }

View File

@@ -18,6 +18,8 @@
#include <QObject> #include <QObject>
#include <ClientData.hpp> #include <ClientData.hpp>
#include <functional>
class MapView; class MapView;
class MapChunk; class MapChunk;
@@ -115,7 +117,7 @@ namespace Noggit
float getDelta() const; float getDelta() const;
void setBlockCursor(bool state); void setBlockCursor(bool state);
bool getBlockCursor() const; bool getBlockCursor() const;
void setPostCallback(auto(MapView::*method)()->void); void setPostCallback(std::function<void()> function);
bool getTag() { return _tag; }; bool getTag() { return _tag; };
void setTag(bool tag) { _tag = tag; }; void setTag(bool tag) { _tag = tag; };
@@ -184,7 +186,7 @@ namespace Noggit
tsl::robin_map<unsigned, std::vector<unsigned>> _object_operations; tsl::robin_map<unsigned, std::vector<unsigned>> _object_operations;
auto(MapView::*_post)()->void = nullptr; std::function<void()> _post;
}; };
} }

9
src/noggit/Input.hpp Normal file
View File

@@ -0,0 +1,9 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
namespace Noggit
{
constexpr float XSENS = 15.0f;
constexpr float YSENS = 15.0f;
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,22 +5,17 @@
#include <math/ray.hpp> #include <math/ray.hpp>
#include <noggit/Misc.h> #include <noggit/Misc.h>
#include <noggit/Selection.h> #include <noggit/Selection.h>
#include <noggit/BoolToggleProperty.hpp>
#include <noggit/Camera.hpp> #include <noggit/Camera.hpp>
#include <noggit/tool_enums.hpp> #include <noggit/tool_enums.hpp>
#include <noggit/ui/ObjectEditor.h>
#include <noggit/ui/MinimapCreator.hpp>
#include <noggit/ui/UidFixWindow.hpp> #include <noggit/ui/UidFixWindow.hpp>
#include <noggit/unsigned_int_property.hpp>
#include <noggit/ui/tools/AssetBrowser/Ui/AssetBrowser.hpp> #include <noggit/ui/tools/AssetBrowser/Ui/AssetBrowser.hpp>
#include <noggit/ui/tools/ViewportGizmo/ViewportGizmo.hpp> #include <noggit/ui/tools/ViewportGizmo/ViewportGizmo.hpp>
#include <noggit/ui/tools/ViewportManager/ViewportManager.hpp> #include <noggit/ui/tools/ViewportManager/ViewportManager.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <noggit/TabletManager.hpp> #include <noggit/TabletManager.hpp>
#include <external/qtimgui/QtImGui.h> #include <external/qtimgui/QtImGui.h>
#include <opengl/texture.hpp> #include <opengl/texture.hpp>
#include <opengl/scoped.hpp> #include <opengl/scoped.hpp>
#include <optional> #include <noggit/Tool.hpp>
#include <QtCore/QElapsedTimer> #include <QtCore/QElapsedTimer>
#include <QtCore/QSettings> #include <QtCore/QSettings>
@@ -51,6 +46,7 @@ namespace Noggit::Ui::Windows
namespace Noggit namespace Noggit
{ {
class Tool;
namespace Ui::Tools::ViewToolbar::Ui namespace Ui::Tools::ViewToolbar::Ui
{ {
@@ -59,18 +55,7 @@ namespace Noggit
namespace Ui::Tools namespace Ui::Tools
{ {
class BrushStack; class ToolPanel;
class LightEditor;
namespace ChunkManipulator
{
class ChunkManipulatorPanel;
}
}
namespace Scripting
{
class scripting_tool;
} }
class Camera; class Camera;
@@ -79,21 +64,9 @@ namespace Noggit
namespace Ui namespace Ui
{ {
class detail_infos; class detail_infos;
class flatten_blur_tool;
class help; class help;
class minimap_widget; class minimap_widget;
class ShaderTool;
class TerrainTool;
class texture_picker;
class texturing_tool;
class toolbar; class toolbar;
class water;
class zone_id_browser;
class texture_palette_small;
class hole_tool;
struct tileset_chooser;
class ObjectPalette;
class GroundEffectsTool;
} }
} }
@@ -171,12 +144,6 @@ public:
Noggit::BoolToggleProperty _show_minimap_window = { false }; Noggit::BoolToggleProperty _show_minimap_window = { false };
private: private:
int _selected_area_id = -1;
[[nodiscard]]
math::ray intersect_ray() const;
selection_result intersect_result(bool terrain_only);
void doSelection(bool selectTerrainOnly, bool mouseMove = false);
void update_cursor_pos(); void update_cursor_pos();
display_mode _display_mode; display_mode _display_mode;
@@ -196,26 +163,13 @@ private:
float mTimespeed; float mTimespeed;
void ResetSelectedObjectRotation(); void ResetSelectedObjectRotation();
void snap_selected_models_to_the_ground();
void DeleteSelectedObjects();
void changeZoneIDValue (int set);
QPointF _last_mouse_pos; QPointF _last_mouse_pos;
float mh, mv, rh, rv; // mh = left click x, rv = right click y
float keyx = 0, keyy = 0, keyz = 0, keyr = 0, keys = 0;
bool MoveObj;
float numpad_moveratio = 0.001f;
glm::vec3 objMove; glm::vec3 objMove;
std::vector<selection_type> lastSelected; std::vector<selection_type> lastSelected;
bool _rotation_editor_need_update = false;
bool _texture_picker_need_update = false;
bool _area_picker_need_update = false;
// Vars for the ground editing toggle mode store the status of some // Vars for the ground editing toggle mode store the status of some
// view settings when the ground editing mode is switched on to // view settings when the ground editing mode is switched on to
// restore them if switch back again // restore them if switch back again
@@ -243,8 +197,6 @@ private:
uid_fix_mode _uid_fix; uid_fix_mode _uid_fix;
bool _from_bookmark; bool _from_bookmark;
bool saving_minimap = false;
Noggit::Ui::toolbar* _toolbar; Noggit::Ui::toolbar* _toolbar;
Noggit::Ui::Tools::ViewToolbar::Ui::ViewToolbar* _view_toolbar; Noggit::Ui::Tools::ViewToolbar::Ui::ViewToolbar* _view_toolbar;
Noggit::Ui::Tools::ViewToolbar::Ui::ViewToolbar* _secondary_toolbar; Noggit::Ui::Tools::ViewToolbar::Ui::ViewToolbar* _secondary_toolbar;
@@ -261,7 +213,10 @@ signals:
void resized(); void resized();
void saved(); void saved();
void updateProgress(int value); void updateProgress(int value);
void selectionUpdated(); void selectionUpdated(std::vector<selection_type>& selection);
void menuToggleChanged(bool value);
void rotationChanged();
void trySetBrushTexture(QImage* image, QWidget* sender);
public slots: public slots:
void on_exit_prompt(); void on_exit_prompt();
void ShowContextMenu(QPoint pos); void ShowContextMenu(QPoint pos);
@@ -284,16 +239,9 @@ public:
void tick (float dt); void tick (float dt);
void change_selected_wmo_nameset(int set); void change_selected_wmo_nameset(int set);
void change_selected_wmo_doodadset(int set); void change_selected_wmo_doodadset(int set);
void saveMinimap(MinimapRenderSettings* settings);
void initMinimapSave() { saving_minimap = true; };
auto setBrushTexture(QImage const* img) -> void; auto setBrushTexture(QImage const* img) -> void;
Noggit::Camera* getCamera() { return &_camera; }; Noggit::Camera* getCamera() { return &_camera; };
void randomizeTerrainRotation();
void randomizeTexturingRotation();
void randomizeShaderRotation();
void randomizeStampRotation();
void onSettingsSave(); void onSettingsSave();
void updateRotationEditor() { _rotation_editor_need_update = true; };
void setCameraDirty() { _camera_moved_since_last_draw = true; }; void setCameraDirty() { _camera_moved_since_last_draw = true; };
[[nodiscard]] [[nodiscard]]
@@ -308,15 +256,6 @@ public:
[[nodiscard]] [[nodiscard]]
QWidget *getLeftSecondaryToolbar(); QWidget *getLeftSecondaryToolbar();
[[nodiscard]]
QWidget* getActiveStampModeItem();
[[nodiscard]]
Noggit::Ui::flatten_blur_tool* getFlattenTool() { return flattenTool; };
[[nodiscard]]
Noggit::Ui::GroundEffectsTool* getGroundEffectsTool();
[[nodiscard]] [[nodiscard]]
Noggit::NoggitRenderContext getRenderContext() { return _context; }; Noggit::NoggitRenderContext getRenderContext() { return _context; };
@@ -329,14 +268,8 @@ public:
[[nodiscard]] [[nodiscard]]
Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget* getAssetBrowserWidget() { return _asset_browser; }; Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget* getAssetBrowserWidget() { return _asset_browser; };
[[nodiscard]] glm::vec3 cursorPosition() const;
Noggit::Ui::object_editor* getObjectEditor() { return objectEditor; }; void cursorPosition(glm::vec3 position);
[[nodiscard]]
QDockWidget* getObjectPalette() { return _object_palette_dock; };
[[nodiscard]]
QDockWidget* getTexturePalette() { return _texture_palette_dock; };
private: private:
enum Modifier enum Modifier
@@ -353,15 +286,17 @@ private:
{ {
Qt::Key key; Qt::Key key;
size_t modifiers; size_t modifiers;
std::function<void()> function; std::function<void()> onPress;
std::function<void()> onRelease;
std::function<bool()> condition; std::function<bool()> condition;
HotKey (Qt::Key k, size_t m, std::function<void()> f, std::function<bool()> c) HotKey (Qt::Key k, size_t m, std::function<void()> f, std::function<bool()> c, std::function<void()> r = []{})
: key (k), modifiers (m), function (f), condition (c) {} : key (k), modifiers (m), onPress(f), onRelease{r}, condition (c) {}
}; };
std::forward_list<HotKey> hotkeys; std::forward_list<HotKey> hotkeys;
void addHotkey(Qt::Key key, size_t modifiers, std::function<void()> function, std::function<bool()> condition = [] { return true; }); void addHotkey(Qt::Key key, size_t modifiers, std::function<void()> function, std::function<bool()> condition = [] { return true; });
void addHotkey(Qt::Key key, size_t modifiers, StringHash hotkeyName);
QElapsedTimer _startup_time; QElapsedTimer _startup_time;
qreal _last_update = 0.f; qreal _last_update = 0.f;
@@ -389,7 +324,6 @@ private:
Noggit::Ui::Windows::NoggitWindow* _main_window; Noggit::Ui::Windows::NoggitWindow* _main_window;
glm::vec4 normalized_device_coords (int x, int y) const; glm::vec4 normalized_device_coords (int x, int y) const;
float aspect_ratio() const;
Noggit::TabletManager* _tablet_manager; Noggit::TabletManager* _tablet_manager;
@@ -402,31 +336,17 @@ private:
QLabel* _status_database; QLabel* _status_database;
Noggit::BoolToggleProperty _locked_cursor_mode = {false}; Noggit::BoolToggleProperty _locked_cursor_mode = {false};
Noggit::BoolToggleProperty _move_model_to_cursor_position = {true};
Noggit::BoolToggleProperty _move_model_snap_to_objects = { true };
Noggit::BoolToggleProperty _snap_multi_selection_to_ground = {false};
Noggit::BoolToggleProperty _rotate_along_ground = {true };
Noggit::BoolToggleProperty _rotate_doodads_along_doodads = { false }; Noggit::BoolToggleProperty _rotate_doodads_along_doodads = { false };
Noggit::BoolToggleProperty _rotate_doodads_along_wmos = { false }; Noggit::BoolToggleProperty _rotate_doodads_along_wmos = { false };
Noggit::BoolToggleProperty _rotate_along_ground_smooth = {true };
Noggit::BoolToggleProperty _rotate_along_ground_random = {false };
Noggit::BoolToggleProperty _use_median_pivot_point = {true};
Noggit::BoolToggleProperty _display_all_water_layers = {true};
Noggit::unsigned_int_property _displayed_water_layer = {0};
Noggit::object_paste_params _object_paste_params;
Noggit::BoolToggleProperty _show_node_editor = {false}; Noggit::BoolToggleProperty _show_node_editor = {false};
Noggit::BoolToggleProperty _show_minimap_borders = {true}; Noggit::BoolToggleProperty _show_minimap_borders = {true};
Noggit::BoolToggleProperty _show_minimap_skies = {false}; Noggit::BoolToggleProperty _show_minimap_skies = {false};
Noggit::BoolToggleProperty _show_keybindings_window = {false}; Noggit::BoolToggleProperty _show_keybindings_window = {false};
Noggit::BoolToggleProperty _show_texture_palette_window = {false};
Noggit::BoolToggleProperty _show_texture_palette_small_window = {false};
Noggit::BoolToggleProperty _showStampPalette{false}; Noggit::BoolToggleProperty _showStampPalette{false};
Noggit::Ui::minimap_widget* _minimap; Noggit::Ui::minimap_widget* _minimap;
QDockWidget* _minimap_dock; QDockWidget* _minimap_dock;
QDockWidget* _texture_palette_dock;
QDockWidget* _object_palette_dock;
void move_camera_with_auto_height (glm::vec3 const&); void move_camera_with_auto_height (glm::vec3 const&);
@@ -435,33 +355,14 @@ private:
void unloadOpenglData() override; void unloadOpenglData() override;
Noggit::Ui::help* _keybindings; Noggit::Ui::help* _keybindings;
Noggit::Ui::tileset_chooser* TexturePalette;
Noggit::Ui::detail_infos* guidetailInfos; Noggit::Ui::detail_infos* guidetailInfos;
Noggit::Ui::zone_id_browser* ZoneIDBrowser;
Noggit::Ui::texture_palette_small* _texture_palette_small;
Noggit::Ui::ObjectPalette* _object_palette;
Noggit::Ui::texture_picker* TexturePicker;
Noggit::Ui::water* guiWater;
Noggit::Ui::object_editor* objectEditor;
Noggit::Ui::flatten_blur_tool* flattenTool;
Noggit::Ui::TerrainTool* terrainTool;
Noggit::Ui::ShaderTool* shaderTool;
Noggit::Ui::texturing_tool* texturingTool;
Noggit::Ui::hole_tool* holeTool;
Noggit::Ui::MinimapCreator* minimapTool;
Noggit::Ui::Tools::BrushStack* stampTool;
Noggit::Ui::Tools::LightEditor* lightEditor;
Noggit::Ui::Tools::ChunkManipulator::ChunkManipulatorPanel* _chunk_manipulator;
Noggit::Scripting::scripting_tool* scriptingTool;
OpenGL::texture* const _texBrush; OpenGL::texture* const _texBrush;
Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget* _asset_browser; Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget* _asset_browser = nullptr;
QDockWidget* _asset_browser_dock; QDockWidget* _asset_browser_dock;
QDockWidget* _node_editor_dock; QDockWidget* _node_editor_dock;
QDockWidget* _texture_browser_dock;
QDockWidget* _texture_picker_dock;
QDockWidget* _detail_infos_dock; QDockWidget* _detail_infos_dock;
Noggit::Ui::Tools::ToolPanel* _tool_panel_dock; Noggit::Ui::Tools::ToolPanel* _tool_panel_dock;
@@ -479,33 +380,14 @@ private:
bool _needs_redraw = false; bool _needs_redraw = false;
bool _unload_tiles = true; bool _unload_tiles = true;
unsigned _mmap_async_index = 0;
unsigned _mmap_render_index = 0;
std::optional<QImage> _mmap_combined_image;
OpenGL::Scoped::deferred_upload_buffers<2> _buffers; OpenGL::Scoped::deferred_upload_buffers<2> _buffers;
QRubberBand* _area_selection;
public: public:
private: private:
void setupViewportOverlay(); void setupViewportOverlay();
void setupRaiseLowerUi();
void setupFlattenBlurUi();
void setupTexturePainterUi();
void setupHoleCutterUi();
void setupAreaDesignatorUi();
void setupFlagUi();
void setupWaterEditorUi();
void setupVertexPainterUi();
void setupObjectEditorUi();
void setupMinimapEditorUi();
void setupStampUi();
void setupLightEditorUi();
void setupScriptingUi();
void setupChunkManipulatorUi();
void setupNodeEditor(); void setupNodeEditor();
void setupAssetBrowser(); void setupAssetBrowser();
void setupDetailInfos(); void setupDetailInfos();
@@ -517,10 +399,60 @@ private:
void setupEditMenu(); void setupEditMenu();
void setupAssistMenu(); void setupAssistMenu();
void setupViewMenu(); void setupViewMenu();
void setupToolsMenu();
void setupHelpMenu(); void setupHelpMenu();
void setupHotkeys(); void setupHotkeys();
void setupClientMenu(); void setupClientMenu();
void setupMainToolbar(); void setupMainToolbar();
QWidget* _overlay_widget; QWidget* _overlay_widget;
std::vector<std::unique_ptr<Noggit::Tool>> _tools;
size_t _activeToolIndex = 0;
std::unique_ptr<Noggit::Tool>& activeTool();
void activeTool(editing_mode newTool);
public:
[[nodiscard]]
Noggit::Ui::Tools::ViewToolbar::Ui::ViewToolbar* getLeftSecondaryViewToolbar();
[[nodiscard]]
QSettings* settings();
[[nodiscard]]
Noggit::Ui::Windows::NoggitWindow* mainWindow();
[[nodiscard]]
bool isUiHidden() const;
[[nodiscard]]
bool drawAdtGrid() const;
[[nodiscard]]
bool drawHoleGrid() const;
void invalidate();
void selectObjects(std::array<glm::vec2, 2> selection_box, float depth);
void doSelection(bool selectTerrainOnly, bool mouseMove = false);
void DeleteSelectedObjects();
void snap_selected_models_to_the_ground();
[[nodiscard]]
bool isRotatingCamera() const;
[[nodiscard]]
float aspect_ratio() const;
[[nodiscard]]
math::ray intersect_ray() const;
[[nodiscard]]
selection_result intersect_result(bool terrain_only);
[[nodiscard]]
std::shared_ptr<Noggit::Project::NoggitProject>& project();
[[nodiscard]]
float timeSpeed() const;
}; };

View File

@@ -0,0 +1,53 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
class QListWidget;
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <vector>
#include <string>
enum MinimapGenMode
{
CURRENT_ADT,
SELECTED_ADTS,
MAP
};
struct MinimapRenderSettings
{
MinimapGenMode export_mode = CURRENT_ADT;
std::string file_format = ".blp";
// Render settings
int resolution = 512;
bool draw_m2 = false;
bool draw_wmo = true;
bool draw_water = true;
bool draw_adt_grid = false;
bool draw_elevation = false;
bool draw_shadows = false;
bool use_filters = false;
bool combined_minimap = false;
// Selection
// std::array<bool, 4096> selected_tiles = {false};
std::vector<char> selected_tiles = std::vector<char>( size_t{4096}, false, {} );
// Filtering
QListWidget* m2_model_filter_include = nullptr;
QListWidget* m2_instance_filter_include = nullptr;
QListWidget* wmo_model_filter_exclude = nullptr;
QListWidget* wmo_instance_filter_exclude = nullptr;
// Lighting. Based on default eastern kingdom global light settings (lightparams 12)
glm::vec3 diffuse_color = {1.0, 0.532352924, 0.0};
glm::vec3 ambient_color = {0.407770514, 0.508424163, 0.602650642};
glm::vec4 ocean_color_light = {0.0693173409, 0.294008732, 0.348329663, 0.75};
glm::vec4 ocean_color_dark = {0.000762581825, 0.113907099, 0.161220074, 1.0};
glm::vec4 river_color_light = {0.308351517, 0.363725543, 0.0798838138, 0.5};
glm::vec4 river_color_dark = {0.19945538, 0.320697188, 0.332425594, 1.0};
};

40
src/noggit/StringHash.hpp Normal file
View File

@@ -0,0 +1,40 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <cstdint>
struct StringHash
{
uint64_t hash;
consteval explicit StringHash(uint64_t value)
: hash{ value }
{
}
[[nodiscard]]
constexpr operator uint64_t()
{
return hash;
}
};
consteval auto operator""_hash(char const* str, size_t len)
{
// djb2 hash
uint64_t hash = 5381;
for (size_t i = 0; i < len; ++i)
{
hash = ((hash << 5) + hash) + static_cast<int>(str[i]);
}
return StringHash{ hash };
}
consteval bool operator==(StringHash a, StringHash b)
{
return a.hash == b.hash;
}

247
src/noggit/Tool.cpp Normal file
View File

@@ -0,0 +1,247 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "Tool.hpp"
#include <noggit/MapView.h>
#include <noggit/BoolToggleProperty.hpp>
#include <noggit/ActionManager.hpp>
#include <noggit/MinimapRenderSettings.hpp>
#include <QAction>
#include <QObject>
#include <QMenu>
namespace Noggit
{
Tool::Tool(MapView* mapView)
: _mapView{ mapView }
{
}
MapView* const Tool::mapView()
{
return _mapView;
}
void Tool::onHotkeyPress(StringHash name)
{
if (auto&& itr = _hotkeys.find(name); itr != _hotkeys.end())
{
itr->second.onPress();
}
}
void Tool::onHotkeyRelease(StringHash name)
{
if (auto&& itr = _hotkeys.find(name); itr != _hotkeys.end())
{
itr->second.onRelease();
}
}
bool Tool::hotkeyCondition(StringHash name)
{
if (auto&& itr = _hotkeys.find(name); itr != _hotkeys.end())
{
return itr->second.condition();
}
return false;
}
unsigned int Tool::actionModality() const
{
return 0;
}
void Tool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
}
void Tool::postUiSetup()
{
}
ToolDrawParameters Tool::drawParameters() const
{
return {};
}
float Tool::brushRadius() const
{
return 0.0f;
}
bool Tool::useMultiselectionPivot() const
{
return false;
}
bool Tool::useMedianPivotPoint() const
{
return false;
}
void Tool::onSelected()
{
}
void Tool::onDeselected()
{
}
void Tool::onTick(float deltaTime, TickParameters const& params)
{
}
bool Tool::preRender()
{
return true;
}
void Tool::postRender()
{
}
void Tool::onMousePress(MousePressParameters const& params)
{
}
void Tool::onMouseRelease(MouseReleaseParameters const& params)
{
}
void Tool::onMouseMove(MouseMoveParameters const& params)
{
}
void Tool::onMouseWheel(MouseWheelParameters const& params)
{
}
void Tool::hidePopups()
{
}
void Tool::onFocusLost()
{
}
void Tool::saveSettings()
{
}
void Tool::registerMenuItems(QMenu* menu)
{
}
void Tool::registerContextMenuItems(QMenu* menu)
{
}
void Tool::addHotkey(StringHash name, Hotkey hotkey)
{
if (auto&& itr = _hotkeys.find(name); itr != _hotkeys.end())
{
// If you get here and you're sure the name you're using isn't already used by this tool,
// then you may have run into a hash collision and we need to re-evaluate the hashing algorithm.
// Or, just change the name and move on...
throw std::exception{ "There's already a hotkey with this name!" };
}
_hotkeys[name] = hotkey;
}
void Tool::addMenuTitle(QMenu* menu, char const* title)
{
menu->addSeparator();
auto* pLabel = new QLabel(title);
pLabel->setAlignment(Qt::AlignCenter);
auto* separator = new QWidgetAction(_mapView);
separator->setDefaultWidget(pLabel);
menu->addAction(separator);
menu->addSeparator();
}
void Tool::addMenuItem(QMenu* menu, char const* title, QKeySequence shortcut, BoolToggleProperty& property)
{
QAction* action(new QAction(title, _mapView));
action->setShortcut(shortcut);
action->setCheckable(true);
action->setChecked(property.get());
menu->addAction(action);
QObject::connect(action, &QAction::toggled
, &property, &Noggit::BoolToggleProperty::set
);
QObject::connect(&property, &Noggit::BoolToggleProperty::changed
, action, &QAction::setChecked
);
}
void Tool::addMenuItem(QMenu* menu, char const* title, BoolToggleProperty& property)
{
QAction* action(new QAction(title, _mapView));
action->setCheckable(true);
action->setChecked(property.get());
menu->addAction(action);
QObject::connect(action, &QAction::toggled
, &property, &Noggit::BoolToggleProperty::set
);
QObject::connect(&property, &Noggit::BoolToggleProperty::changed
, action, &QAction::setChecked
);
}
void Tool::addMenuItem(QMenu* menu, char const* title, QKeySequence shortcut, std::function<void()> onAction)
{
auto action(menu->addAction(title));
action->setShortcut(shortcut);
auto callback = onAction;
QObject::connect(action, &QAction::triggered, [this, callback]()
{
if (NOGGIT_CUR_ACTION) \
return;
callback();
});
}
void Tool::addMenuItem(QMenu* menu, char const* title, QKeySequence shortcut, bool enabled, std::function<void()> onAction)
{
auto action(menu->addAction(title));
action->setShortcut(shortcut);
action->setEnabled(enabled);
auto callback = onAction;
QObject::connect(action, &QAction::triggered, [this, callback]()
{
if (NOGGIT_CUR_ACTION) \
return;
callback();
});
}
void Tool::addMenuItem(QMenu* menu, char const* title, char const* tooltip, bool enabled, std::function<void()> onAction)
{
auto action(menu->addAction(title));
action->setToolTip(tooltip);
action->setEnabled(enabled);
auto callback = onAction;
QObject::connect(action, &QAction::triggered, [this, callback]()
{
if (NOGGIT_CUR_ACTION) \
return;
callback();
});
}
void Tool::addMenuItem(QMenu* menu, char const* title, std::function<void()> onAction)
{
auto action(menu->addAction(title));
QObject::connect(action, &QAction::triggered, onAction);
}
void Tool::addMenuSeperator(QMenu* menu)
{
menu->addSeparator();
}
}

208
src/noggit/Tool.hpp Normal file
View File

@@ -0,0 +1,208 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include "tool_enums.hpp"
#include "ToolDrawParameters.hpp"
#include "StringHash.hpp"
#include <noggit/ui/FontNoggit.hpp>
#include <glm/vec3.hpp>
#include <QLineF>
#include <QPoint>
#include <string>
#include <functional>
#include <unordered_map>
class MapView;
class QWheelEvent;
class QMenu;
namespace Noggit
{
struct BoolToggleProperty;
namespace Ui::Tools
{
class ToolPanel;
}
struct TickParameters
{
display_mode displayMode = display_mode::in_3D;
bool underMap = false;
bool left_mouse = false;
bool right_mouse = false;
bool mod_shift_down = false;
bool mod_ctrl_down = false;
bool mod_alt_down = false;
bool mod_num_down = false;
glm::vec3 dir = { 1.0f, 0.0f, 0.0f };
glm::vec3 dirUp = { 1.0f, 0.0f, 0.0f };
glm::vec3 dirRight = { 0.0f, 0.0f, 1.0f };
};
struct MousePressParameters
{
Qt::MouseButton button = Qt::MouseButton::NoButton;
QPoint mouse_position;
bool mod_ctrl_down = false;
};
struct MouseReleaseParameters
{
Qt::MouseButton button = Qt::MouseButton::NoButton;
QPoint mouse_position;
bool mod_ctrl_down = false;
};
struct MouseMoveParameters
{
display_mode displayMode = display_mode::in_3D;
bool left_mouse = false;
bool right_mouse = false;
bool mod_shift_down = false;
bool mod_ctrl_down = false;
bool mod_alt_down = false;
bool mod_num_down = false;
bool mod_space_down = false;
QLineF relative_movement;
QPoint mouse_position;
};
struct MouseWheelParameters
{
QWheelEvent& event;
bool mod_shift_down = false;
bool mod_ctrl_down = false;
bool mod_alt_down = false;
bool mod_num_down = false;
bool mod_space_down = false;
};
class Tool
{
protected:
struct Hotkey
{
std::function<void()> onPress;
std::function<void()> onRelease = [] {};
std::function<bool()> condition;
};
public:
explicit Tool(MapView* mapView);
virtual ~Tool() = default;
[[nodiscard]]
MapView* const mapView();
// will be called whenever a user presses a hotkey
void onHotkeyPress(StringHash name);
// will be called after a user pressed a hotkey
void onHotkeyRelease(StringHash name);
// will be called before onHotkeyPress to see if it needs to be called
[[nodiscard]]
bool hotkeyCondition(StringHash name);
// Returns the current action modality to cancel the current action on mismatch
[[nodiscard]]
virtual unsigned int actionModality() const;
// The name displayed in the toolbar
[[nodiscard]]
virtual char const* name() const = 0;
[[nodiscard]]
virtual editing_mode editingMode() const = 0;
// The icon displayed in the toolbar
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const = 0;
// UI setup code goes here
virtual void setupUi(Ui::Tools::ToolPanel* toolPanel);
// UI setup code that relies on other UI elements being initialized goes here
virtual void postUiSetup();
// If you need menu items, register them here
virtual void registerMenuItems(QMenu* menu);
// If you need context menu items, register them here
virtual void registerContextMenuItems(QMenu* menu);
// Returns the ToolDrawParameters required by the renderer to draw tool specific objects (like the brush for texturing mode)
[[nodiscard]]
virtual ToolDrawParameters drawParameters() const;
[[nodiscard]]
virtual float brushRadius() const;
[[nodiscard]]
virtual bool useMultiselectionPivot() const;
[[nodiscard]]
virtual bool useMedianPivotPoint() const;
// will be called whenever this tool gets selected by the user
virtual void onSelected();
// will be called whenever the user selects a different tool
virtual void onDeselected();
// will be called every tick
virtual void onTick(float deltaTime, TickParameters const& params);
// will be called before the map gets drawn. May return false to skip rendering the map
virtual bool preRender();
// will be called after the map got drawn
virtual void postRender();
// will be called whenever a mouse button is pressed
virtual void onMousePress(MousePressParameters const& params);
virtual void onMouseRelease(MouseReleaseParameters const& params);
// will be called whenever the mouse moves
virtual void onMouseMove(MouseMoveParameters const& params);
// will be called when the user scrolls the mouse wheel
virtual void onMouseWheel(MouseWheelParameters const& params);
// Hide your tools' popups!
virtual void hidePopups();
// The main window's focus was lost
virtual void onFocusLost();
// Save tool-specific settings to disk
virtual void saveSettings();
protected:
void addHotkey(StringHash name, Hotkey hotkey);
void addMenuTitle(QMenu* menu, char const* title);
void addMenuItem(QMenu* menu, char const* title, QKeySequence shortcut, BoolToggleProperty& property);
void addMenuItem(QMenu* menu, char const* title, BoolToggleProperty& property);
void addMenuItem(QMenu* menu, char const* title, QKeySequence shortcut, std::function<void()> onAction);
void addMenuItem(QMenu* menu, char const* title, QKeySequence shortcut, bool enabled, std::function<void()> onAction);
void addMenuItem(QMenu* menu, char const* title, char const* tooltip, bool enabled, std::function<void()> onAction);
void addMenuItem(QMenu* menu, char const* title, std::function<void()> onAction);
void addMenuSeperator(QMenu* menu);
private:
MapView* _mapView = nullptr;
std::unordered_map<decltype(StringHash::hash), Hotkey> _hotkeys;
};
}

View File

@@ -0,0 +1,31 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include "tool_enums.hpp"
#include "MinimapRenderSettings.hpp"
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
struct MinimapRenderSettings;
namespace Noggit
{
struct ToolDrawParameters
{
float radius = 0.0f;
float inner_radius = 0.0f;
float angle = 0.0f;
float orientation = 0.0f;
glm::vec3 ref_pos;
bool angled_mode = false;
bool use_ref_pos = false;
bool show_unpaintable_chunks = false;
CursorType cursor_type = CursorType::CIRCLE;
eTerrainType terrain_type = eTerrainType::eTerrainType_Flat;
int displayed_water_layer = -1;
glm::vec4 cursor_color = { 1.f, 1.f, 1.f, 1.f };
MinimapRenderSettings minimapRenderSettings;
};
}

View File

@@ -0,0 +1,17 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
namespace Noggit
{
struct object_paste_params
{
float minRotation = -180.f;
float maxRotation = 180.f;
float minTilt = -5.f;
float maxTilt = 5.f;
float minScale = 0.9f;
float maxScale = 1.1f;
bool rotate_on_terrain = true;
};
}

View File

@@ -0,0 +1,122 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "AreaTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/ZoneIDBrowser.h>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
namespace Noggit
{
AreaTool::AreaTool(MapView* mapView)
: Tool{ mapView }
{
addHotkey("setAreaId"_hash, {
.onPress = [=] {
if (_selectedAreaId != -1)
{
NOGGIT_ACTION_MGR->beginAction(mapView, Noggit::ActionFlags::eCHUNKS_AREAID);
mapView->getWorld()->setAreaID(mapView->getCamera()->position, _selectedAreaId, true);
NOGGIT_ACTION_MGR->endAction();
}},
.condition = [=] { return mapView->get_editing_mode() == editing_mode::areaid && !NOGGIT_CUR_ACTION; }
});
}
AreaTool::~AreaTool()
{
}
char const* AreaTool::name() const
{
return "Area Designator";
}
editing_mode AreaTool::editingMode() const
{
return editing_mode::areaid;
}
Ui::FontNoggit::Icons AreaTool::icon() const
{
return Ui::FontNoggit::TOOL_AREA_DESIGNATOR;
}
void AreaTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_areaTool = new Noggit::Ui::zone_id_browser(mapView());
toolPanel->registerTool(name(), _areaTool);
_areaTool->setMapID(mapView()->getWorld()->getMapID());
QObject::connect(_areaTool, &Noggit::Ui::zone_id_browser::selected
, [this](int area_id) { _selectedAreaId = area_id; }
);
}
ToolDrawParameters AreaTool::drawParameters() const
{
return ToolDrawParameters();
}
void AreaTool::registerMenuItems(QMenu* menu)
{
addMenuTitle(menu, "Area Designator");
addMenuItem(menu, "Set Area ID", [=] {
if (_selectedAreaId == -1)
{
return;
}
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_AREAID);
mapView()->getWorld()->setAreaID(mapView()->getCamera()->position, _selectedAreaId, true);
NOGGIT_ACTION_MGR->endAction();
});
}
void AreaTool::onSelected()
{
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_areaid_overlay = true;
}
void AreaTool::onDeselected()
{
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_areaid_overlay = false;
}
void AreaTool::onTick(float deltaTime, TickParameters const& params)
{
if (!mapView()->getWorld()->has_selection() || params.underMap || !params.left_mouse)
{
return;
}
if (params.mod_shift_down)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_AREAID,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
// draw the selected AreaId on current selected chunk
mapView()->getWorld()->setAreaID(mapView()->cursorPosition(), _selectedAreaId, false, _areaTool->brushRadius());
}
else if (params.mod_ctrl_down)
{
for (auto&& selection : mapView()->getWorld()->current_selection())
{
MapChunk* chnk(std::get<selected_chunk_type>(selection).chunk);
int newID = chnk->getAreaID();
_selectedAreaId = newID;
_areaTool->setZoneID(newID);
}
}
}
void AreaTool::onMouseMove(MouseMoveParameters const& params)
{
if (params.left_mouse && params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_areaTool->changeRadius(params.relative_movement.dx() / XSENS);
}
}
}

View File

@@ -0,0 +1,48 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Ui
{
class zone_id_browser;
}
class AreaTool final : public Tool
{
public:
AreaTool(MapView* mapView);
~AreaTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void registerMenuItems(QMenu* menu) override;
virtual void onSelected();
virtual void onDeselected();
void onTick(float deltaTime, TickParameters const& params) override;
void onMouseMove(MouseMoveParameters const& params) override;
private:
Ui::zone_id_browser* _areaTool = nullptr;
int _selectedAreaId = -1;
};
}

View File

@@ -0,0 +1,43 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "ChunkTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/tools/ChunkManipulator/ChunkManipulatorPanel.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
namespace Noggit
{
ChunkTool::ChunkTool(MapView* mapView)
: Tool{ mapView }
{
}
ChunkTool::~ChunkTool()
{
delete _chunkManipulator;
}
char const* ChunkTool::name() const
{
return "Chunk Manipulator";
}
editing_mode ChunkTool::editingMode() const
{
return editing_mode::chunk;
}
Ui::FontNoggit::Icons ChunkTool::icon() const
{
return Ui::FontNoggit::INFO;
}
void ChunkTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_chunkManipulator = new Noggit::Ui::Tools::ChunkManipulator::ChunkManipulatorPanel(mapView(), mapView());
toolPanel->registerTool(name(), _chunkManipulator);
}
}

View File

@@ -0,0 +1,34 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Ui::Tools::ChunkManipulator
{
class ChunkManipulatorPanel;
}
class ChunkTool final : public Tool
{
public:
ChunkTool(MapView* mapView);
~ChunkTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
private:
Ui::Tools::ChunkManipulator::ChunkManipulatorPanel* _chunkManipulator = nullptr;
};
}

View File

@@ -0,0 +1,187 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "FlattenBlurTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/Input.hpp>
#include <noggit/MapView.h>
#include <noggit/ui/FlattenTool.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <noggit/ui/tools/ViewToolbar/Ui/ViewToolbar.hpp>
namespace Noggit
{
FlattenBlurTool::FlattenBlurTool(MapView* mapView)
: Tool{ mapView }
{
addHotkey("nextType"_hash, Hotkey{
.onPress = [this] { _flattenTool->nextFlattenType(); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::flatten_blur && !NOGGIT_CUR_ACTION; },
});
addHotkey("toggleAngle"_hash, Hotkey{
.onPress = [this] { _flattenTool->toggleFlattenAngle(); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::flatten_blur && !NOGGIT_CUR_ACTION; },
});
addHotkey("nextMode"_hash, Hotkey{
.onPress = [this, mv = mapView]
{
mv->getLeftSecondaryViewToolbar()->nextFlattenMode();
_flattenTool->nextFlattenMode();
},
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::flatten_blur && !NOGGIT_CUR_ACTION; },
});
addHotkey("toggleLock"_hash, Hotkey{
.onPress = [this] { _flattenTool->toggleFlattenLock(); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::flatten_blur && !NOGGIT_CUR_ACTION; },
});
addHotkey("lockCursor"_hash, Hotkey{
.onPress = [this, mv = mapView] { _flattenTool->lockPos(mv->cursorPosition()); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::flatten_blur && !NOGGIT_CUR_ACTION; },
});
addHotkey("increaseRadius"_hash, Hotkey{
.onPress = [this] { _flattenTool->changeRadius(0.01f); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::flatten_blur && !NOGGIT_CUR_ACTION; },
});
addHotkey("decreaseRadius"_hash, Hotkey{
.onPress = [this] { _flattenTool->changeRadius(-0.01f); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::flatten_blur && !NOGGIT_CUR_ACTION; },
});
}
FlattenBlurTool::~FlattenBlurTool()
{
delete _flattenTool;
}
char const* FlattenBlurTool::name() const
{
return "Flatten | Blur";
}
editing_mode FlattenBlurTool::editingMode() const
{
return editing_mode::flatten_blur;
}
Ui::FontNoggit::Icons FlattenBlurTool::icon() const
{
return Ui::FontNoggit::TOOL_FLATTEN_BLUR;
}
void FlattenBlurTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_flattenTool = new Noggit::Ui::flatten_blur_tool(mapView());
toolPanel->registerTool(name(), _flattenTool);
}
void FlattenBlurTool::postUiSetup()
{
QObject::connect(mapView()->getLeftSecondaryViewToolbar()
, &Ui::Tools::ViewToolbar::Ui::ViewToolbar::updateStateRaise
, [this](bool newState)
{
_flattenTool->_flatten_mode.raise = newState;
}
);
QObject::connect(mapView()->getLeftSecondaryViewToolbar()
, &Ui::Tools::ViewToolbar::Ui::ViewToolbar::updateStateLower
, [this](bool newState)
{
_flattenTool->_flatten_mode.lower = newState;
}
);
}
void FlattenBlurTool::onTick(float deltaTime, TickParameters const& params)
{
if (!mapView()->getWorld()->has_selection() || !params.left_mouse)
{
return;
}
if (params.displayMode == display_mode::in_3D && !params.underMap)
{
if (params.mod_shift_down)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
_flattenTool->flatten(mapView()->getWorld(), mapView()->cursorPosition(), deltaTime);
}
else if (params.mod_ctrl_down)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eCTRL
| Noggit::ActionModalityControllers::eLMB);
_flattenTool->blur(mapView()->getWorld(), mapView()->cursorPosition(), deltaTime);
}
}
}
ToolDrawParameters FlattenBlurTool::drawParameters() const
{
return
{
.radius = _flattenTool->brushRadius(),
.angle = _flattenTool->angle(),
.orientation = _flattenTool->orientation(),
.ref_pos = _flattenTool->ref_pos(),
.angled_mode = _flattenTool->angled_mode(),
.use_ref_pos = _flattenTool->use_ref_pos(),
};
}
void FlattenBlurTool::onMouseMove(MouseMoveParameters const& params)
{
if (params.left_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_flattenTool->changeRadius(params.relative_movement.dx() / XSENS);
}
if (params.mod_space_down)
{
_flattenTool->changeSpeed(params.relative_movement.dx() / 30.0f);
}
}
}
void FlattenBlurTool::onMouseWheel(MouseWheelParameters const& params)
{
auto&& delta_for_range
([&](float range)
{
//! \note / 8.f for degrees, / 40.f for smoothness
return (params.mod_ctrl_down ? 0.01f : 0.1f)
* range
// alt = horizontal delta
* (params.mod_alt_down ? params.event.angleDelta().x() : params.event.angleDelta().y())
/ 320.f
;
}
);
if (params.mod_alt_down)
{
_flattenTool->changeOrientation(delta_for_range(360.f));
}
else if (params.mod_shift_down)
{
_flattenTool->changeAngle(delta_for_range(89.f));
}
else if (params.mod_space_down)
{
//! \note not actual range
_flattenTool->changeHeight(delta_for_range(40.f));
}
}
}

View File

@@ -0,0 +1,45 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Ui
{
class flatten_blur_tool;
}
class FlattenBlurTool final : public Tool
{
public:
FlattenBlurTool(MapView* mapView);
~FlattenBlurTool();
[[nodiscard]]
char const* name() const override;
[[nodiscard]]
editing_mode editingMode() const override;
[[nodiscard]]
Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
void postUiSetup() override;
void onTick(float deltaTime, TickParameters const& params) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onMouseMove(MouseMoveParameters const& params) override;
void onMouseWheel(MouseWheelParameters const& params) override;
private:
Ui::flatten_blur_tool* _flattenTool = nullptr;
};
}

View File

@@ -0,0 +1,113 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "HoleTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/hole_tool.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
namespace Noggit
{
HoleTool::HoleTool(MapView* mapView)
: Tool{ mapView }
{
addHotkey("unsetAdtHole"_hash, Hotkey{
.onPress = [=] {
NOGGIT_ACTION_MGR->beginAction(mapView, Noggit::ActionFlags::eCHUNKS_HOLES);
mapView->getWorld()->setHoleADT(mapView->getCamera()->position, false);
NOGGIT_ACTION_MGR->endAction();
},
.condition = [=] { return mapView->get_editing_mode() == editing_mode::holes && !NOGGIT_CUR_ACTION; },
});
addHotkey("setAdtHole"_hash, Hotkey{
.onPress = [=] {
NOGGIT_ACTION_MGR->beginAction(mapView, Noggit::ActionFlags::eCHUNKS_HOLES);
mapView->getWorld()->setHoleADT(mapView->getCamera()->position, true);
NOGGIT_ACTION_MGR->endAction();
},
.condition = [=] { return mapView->get_editing_mode() == editing_mode::holes && !NOGGIT_CUR_ACTION; },
});
}
HoleTool::~HoleTool()
{
delete _holeTool;
}
char const* HoleTool::name() const
{
return "Hole Cutter";
}
editing_mode HoleTool::editingMode() const
{
return editing_mode::holes;
}
Ui::FontNoggit::Icons HoleTool::icon() const
{
return Ui::FontNoggit::TOOL_HOLE_CUTTER;
}
void HoleTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_holeTool = new Noggit::Ui::hole_tool(mapView());
toolPanel->registerTool(name(), _holeTool);
}
ToolDrawParameters HoleTool::drawParameters() const
{
return
{
.radius = _holeTool->brushRadius(),
};
}
void HoleTool::onSelected()
{
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_lines = true;
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_hole_lines = true;
}
void HoleTool::onDeselected()
{
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_lines = mapView()->drawAdtGrid();
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_hole_lines = mapView()->drawHoleGrid();
}
void HoleTool::onTick(float deltaTime, TickParameters const& params)
{
if (!mapView()->getWorld()->has_selection() || !params.left_mouse)
{
return;
}
auto mv = mapView();
// no undermap check here, else it's impossible to remove holes
if (params.mod_shift_down)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_HOLES,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
mv->getWorld()->setHole(mv->cursorPosition(), _holeTool->brushRadius(), params.mod_alt_down, false);
}
else if (params.mod_ctrl_down && !params.underMap)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_HOLES,
Noggit::ActionModalityControllers::eCTRL
| Noggit::ActionModalityControllers::eLMB);
mv->getWorld()->setHole(mv->cursorPosition(), _holeTool->brushRadius(), params.mod_alt_down, true);
}
}
void HoleTool::onMouseMove(MouseMoveParameters const& params)
{
if (params.left_mouse && params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_holeTool->changeRadius(params.relative_movement.dx() / XSENS);
}
}
}

View File

@@ -0,0 +1,45 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Ui
{
class hole_tool;
}
class HoleTool final : public Tool
{
public:
HoleTool(MapView* mapView);
~HoleTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onSelected() override;
void onDeselected() override;
void onTick(float deltaTime, TickParameters const& params) override;
void onMouseMove(MouseMoveParameters const& params) override;
private:
Ui::hole_tool* _holeTool = nullptr;
};
}

View File

@@ -0,0 +1,71 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "ImpassTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
namespace Noggit
{
ImpassTool::ImpassTool(MapView* mapView)
: Tool{ mapView }
{
}
char const* ImpassTool::name() const
{
return "Impass Designator";
}
editing_mode ImpassTool::editingMode() const
{
return editing_mode::impass;
}
Ui::FontNoggit::Icons ImpassTool::icon() const
{
return Ui::FontNoggit::TOOL_IMPASS_DESIGNATOR;
}
void ImpassTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
// Dummy, because the toolbar requires a widget for every tool
toolPanel->registerTool(name(), new QWidget{mapView()});
}
void ImpassTool::onSelected()
{
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_impass_overlay = true;
}
void ImpassTool::onDeselected()
{
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_impass_overlay = false;
}
void ImpassTool::onTick(float deltaTime, TickParameters const& params)
{
if (!mapView()->getWorld()->has_selection() || params.underMap || !params.left_mouse)
{
return;
}
// todo: replace this -- why and with what?
if (params.mod_shift_down)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_FLAGS,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
mapView()->getWorld()->mapIndex.setFlag(true, mapView()->cursorPosition(), 0x2);
}
else if (params.mod_ctrl_down)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_FLAGS,
Noggit::ActionModalityControllers::eCTRL
| Noggit::ActionModalityControllers::eLMB);
mapView()->getWorld()->mapIndex.setFlag(false, mapView()->cursorPosition(), 0x2);
}
}
}

View File

@@ -0,0 +1,32 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
class ImpassTool final : public Tool
{
public:
ImpassTool(MapView* mapView);
~ImpassTool() = default;
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
virtual void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
void onSelected() override;
void onDeselected() override;
void onTick(float deltaTime, TickParameters const& params) override;
};
}

View File

@@ -0,0 +1,49 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "LightTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/tools/LightEditor/LightEditor.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
namespace Noggit
{
LightTool::LightTool(MapView* mapView)
: Tool{ mapView }
{
}
LightTool::~LightTool()
{
delete _lightEditor;
}
char const* LightTool::name() const
{
return "Light Editor";
}
editing_mode LightTool::editingMode() const
{
return editing_mode::light;
}
Ui::FontNoggit::Icons LightTool::icon() const
{
return Ui::FontNoggit::TOOL_LIGHT;
}
void LightTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_lightEditor = new Noggit::Ui::Tools::LightEditor(mapView(), mapView());
toolPanel->registerTool(name(), _lightEditor);
}
void LightTool::onTick(float deltaTime, TickParameters const& params)
{
if (mapView()->timeSpeed() > 0.0f)
_lightEditor->UpdateWorldTime();
}
}

View File

@@ -0,0 +1,36 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Ui::Tools
{
class LightEditor;
}
class LightTool final : public Tool
{
public:
LightTool(MapView* mapView);
~LightTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
void onTick(float deltaTime, TickParameters const& params) override;
private:
Ui::Tools::LightEditor* _lightEditor = nullptr;
};
}

View File

@@ -0,0 +1,299 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "MinimapTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/project/CurrentProject.hpp>
#include <noggit/ui/MinimapCreator.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <noggit/ui/windows/noggitWindow/NoggitWindow.hpp>
#include <QDir>
#include <QStatusBar>
namespace Noggit
{
MinimapTool::MinimapTool(MapView* mapView)
: Tool{ mapView }
{
}
MinimapTool::~MinimapTool()
{
delete _minimapTool;
}
char const* MinimapTool::name() const
{
return "Minimap Editor";
}
editing_mode MinimapTool::editingMode() const
{
return editing_mode::minimap;
}
Ui::FontNoggit::Icons MinimapTool::icon() const
{
return Ui::FontNoggit::TOOL_MINIMAP_EDITOR;
}
void MinimapTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
auto mv = mapView();
_minimapTool = new Noggit::Ui::MinimapCreator(mv, mv->getWorld(), mv);
toolPanel->registerTool(name(), _minimapTool);
QObject::connect(_minimapTool, &Ui::MinimapCreator::onSave, [=] {
saving_minimap = true;
});
}
ToolDrawParameters MinimapTool::drawParameters() const
{
return
{
.radius = _minimapTool->brushRadius(),
.minimapRenderSettings = *_minimapTool->getMinimapRenderSettings(),
};
}
void MinimapTool::onSelected()
{
mapView()->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_selection_overlay = true;
mapView()->getMinimapWidget()->use_selection(_minimapTool->getSelectedTiles());
}
void MinimapTool::onTick(float deltaTime, TickParameters const& params)
{
if (!mapView()->getWorld()->has_selection() || !params.left_mouse)
{
return;
}
}
bool MinimapTool::preRender()
{
if (!saving_minimap)
{
return true;
}
auto mv = mapView();
auto world = mv->getWorld();
auto settings = _minimapTool->getMinimapRenderSettings();
mv->setCameraDirty();
OpenGL::context::scoped_setter const _(::gl, mv->context());
mv->makeCurrent();
bool mmap_render_success = false;
static QProgressBar* progress;
static QPushButton* cancel_btn;
auto init = [=](int max) {
progress = new QProgressBar(nullptr);
progress->setMinimum(0);
progress->setMaximum(max);
mv->mainWindow()->statusBar()->addPermanentWidget(progress);
cancel_btn = new QPushButton(nullptr);
cancel_btn->setText("Cancel");
QObject::connect(cancel_btn, &QPushButton::clicked,
[=]
{
_mmap_async_index = 0;
_mmap_render_index = 0;
saving_minimap = false;
progress->deleteLater();
cancel_btn->deleteLater();
_mmap_combined_image.reset();
});
mv->mainWindow()->statusBar()->addPermanentWidget(cancel_btn);
QObject::connect(mv, &MapView::updateProgress,
[=](int value)
{
// This weirdness is required due to a bug on Linux when QT repaint crashes due to too many events
// being passed through. TODO: this potentially only masks the issue, which may reappear on faster
// hardware.
if (progress->value() != value)
progress->setValue(value);
});
// setup combined image if necessary
if (settings->combined_minimap)
{
_mmap_combined_image.emplace(8192, 8192, QImage::Format_RGBA8888);
_mmap_combined_image->fill(Qt::black);
}
};
auto save = [=, &mmap_render_success]()
{
while (!world->mapIndex.hasTile({ _mmap_async_index / 64, _mmap_async_index % 64 }))
{
++_mmap_async_index;
}
TileIndex tile = TileIndex(_mmap_async_index / 64, _mmap_async_index % 64);
if (world->mapIndex.hasTile(tile))
{
OpenGL::context::scoped_setter const _(::gl, mv->context());
mv->makeCurrent();
mmap_render_success = world->renderer()->saveMinimap(tile, settings, _mmap_combined_image);
_mmap_render_index++;
emit mv->updateProgress(_mmap_render_index);
if (!mmap_render_success)
{
LogError << "Minimap rendered incorrectly for tile: " << tile.x << "_" << tile.z << std::endl;
}
}
};
switch (settings->export_mode)
{
case MinimapGenMode::CURRENT_ADT:
{
TileIndex tile = TileIndex(mv->getCamera()->position);
if (world->mapIndex.hasTile(tile))
{
mmap_render_success = world->renderer()->saveMinimap(tile, settings, _mmap_combined_image);
}
if (mmap_render_success)
{
world->mapIndex.saveMinimapMD5translate();
}
saving_minimap = false;
break;
}
case MinimapGenMode::MAP:
{
// init progress
if (!_mmap_async_index)
{
init(world->mapIndex.getNumExistingTiles());
}
if (!saving_minimap)
return false;
if (_mmap_async_index < 4096 && static_cast<int>(_mmap_render_index) < progress->maximum())
{
save();
_mmap_async_index++;
}
else
{
finishSaving(progress, cancel_btn, world, settings);
}
//_main_window->statusBar()->showMessage("Minimap rendering done.", 2000);
break;
}
case MinimapGenMode::SELECTED_ADTS:
{
auto selected_tiles = _minimapTool->getSelectedTiles();
// init progress
if (!_mmap_async_index)
{
int n_selected_tiles = 0;
for (int i = 0; i < 4096; ++i)
{
if (selected_tiles->at(i))
n_selected_tiles++;
}
init(n_selected_tiles);
}
if (!saving_minimap)
return false;
if (_mmap_async_index < 4096 && static_cast<int>(_mmap_render_index) < progress->maximum())
{
if (selected_tiles->at(_mmap_async_index))
{
save();
}
_mmap_async_index++;
}
else
{
finishSaving(progress, cancel_btn, world, settings);
}
break;
}
}
//minimapTool->progressUpdate(0);
return !saving_minimap;
}
void MinimapTool::onMouseMove(MouseMoveParameters const& params)
{
if (params.left_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_minimapTool->changeRadius(params.relative_movement.dx() / XSENS);
}
if (params.mod_shift_down || params.mod_ctrl_down)
{
mapView()->doSelection(false, true);
}
}
}
void MinimapTool::finishSaving(QProgressBar* progress, QPushButton* cancel_btn, World* world, MinimapRenderSettings* settings)
{
_mmap_async_index = 0;
_mmap_render_index = 0;
saving_minimap = false;
progress->deleteLater();
cancel_btn->deleteLater();
world->mapIndex.saveMinimapMD5translate();
// save combined minimap
if (settings->combined_minimap)
{
QString image_path = QString(std::string(world->basename + "_combined_minimap.png").c_str());
QString str = QString(Noggit::Project::CurrentProject::get()->ProjectPath.c_str());
if (!(str.endsWith('\\') || str.endsWith('/')))
{
str += "/";
}
QDir dir(str + "/textures/minimap/");
if (!dir.exists())
dir.mkpath(".");
_mmap_combined_image->save(dir.filePath(image_path));
_mmap_combined_image.reset();
}
}
void MinimapTool::saveSettings()
{
// Save minimap creator model filters
_minimapTool->saveFiltersToJSON();
}
}

View File

@@ -0,0 +1,60 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
class QProgressBar;
class QPushButton;
class World;
struct MinimapRenderSettings;
namespace Noggit
{
namespace Ui
{
class MinimapCreator;
}
class MinimapTool final : public Tool
{
public:
MinimapTool(MapView* mapView);
~MinimapTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onSelected() override;
void onTick(float deltaTime, TickParameters const& params) override;
bool preRender() override;
void onMouseMove(MouseMoveParameters const& params) override;
void saveSettings() override;
private:
Ui::MinimapCreator* _minimapTool = nullptr;
unsigned _mmap_async_index = 0;
unsigned _mmap_render_index = 0;
std::optional<QImage> _mmap_combined_image;
bool saving_minimap = false;
void finishSaving(QProgressBar* progress, QPushButton* cancel_btn, World* world, MinimapRenderSettings* settings);
};
}

View File

@@ -0,0 +1,968 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "ObjectTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/ObjectEditor.h>
#include <noggit/ui/tools/AssetBrowser/Ui/AssetBrowser.hpp>
#include <noggit/ui/ModelImport.h>
#include <noggit/ui/RotationEditor.h>
#include <noggit/ui/HelperModels.h>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <noggit/ui/object_palette.hpp>
#include <noggit/ui/windows/noggitWindow/NoggitWindow.hpp>
namespace Noggit
{
ObjectTool::ObjectTool(MapView* mapView)
: Tool{ mapView }
{
setupHotkeys();
}
ObjectTool::~ObjectTool()
{
delete _objectEditor;
}
unsigned int ObjectTool::actionModality() const
{
unsigned int actionModality = 0;
if (_moveObject)
actionModality |= Noggit::ActionModalityControllers::eMMB;
if (_keys)
actionModality |= Noggit::ActionModalityControllers::eSCALE;
if (_keyr)
actionModality |= Noggit::ActionModalityControllers::eROTATE;
return actionModality;
}
char const* ObjectTool::name() const
{
return "Object Editor";
}
editing_mode ObjectTool::editingMode() const
{
return editing_mode::object;
}
Ui::FontNoggit::Icons ObjectTool::icon() const
{
return Ui::FontNoggit::TOOL_OBJECT_EDITOR;
}
void ObjectTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
auto mv = mapView();
// initialize some saved defaults
_object_paste_params.rotate_on_terrain = mv->settings()->value("paste_params/rotate_on_terrain", true).toBool();
/* Tool */
_objectEditor = new Noggit::Ui::object_editor(mv
, mv->getWorld()
, &_move_model_to_cursor_position
, &_snap_multi_selection_to_ground
, &_use_median_pivot_point
, &_object_paste_params
, &_rotate_along_ground
, &_rotate_along_ground_smooth
, &_rotate_along_ground_random
, &_move_model_snap_to_objects
, mv
);
toolPanel->registerTool(name(), _objectEditor);
/* Additional tools */
/* Area selection */
_area_selection = new QRubberBand(QRubberBand::Rectangle, mv);
/* Object Palette */
_object_palette = new Noggit::Ui::ObjectPalette(mv, mv->project(), mv);
_object_palette->hide();
// Dock
_object_palette_dock = new QDockWidget("Object Palette", mv);
_object_palette_dock->setFeatures(QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetFloatable
| QDockWidget::DockWidgetClosable
);
_object_palette_dock->setWidget(_object_palette);
_object_palette_dock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
mv->mainWindow()->addDockWidget(Qt::BottomDockWidgetArea, _object_palette_dock);
_object_palette_dock->hide();
// End Dock
QObject::connect(_object_palette_dock, &QDockWidget::visibilityChanged,
[=](bool visible)
{
if (mv->isUiHidden())
return;
mv->settings()->setValue("map_view/object_palette", visible);
mv->settings()->sync();
});
QObject::connect(mapView(), &MapView::rotationChanged, [=] {
updateRotationEditor();
});
QObject::connect(_objectEditor, &Ui::object_editor::objectPaletteBtnPressed, [=] {
_object_palette_dock->setVisible(_object_palette_dock->isHidden());
});
QObject::connect(mapView(), &MapView::selectionUpdated, [=](auto) {
_objectEditor->update_selection_ui(mapView()->getWorld());
});
using AssetBrowser = Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget;
QObject::connect(mapView()->getAssetBrowserWidget(), &AssetBrowser::selectionChanged, [=](std::string const& path) {
if (_objectEditor->isVisible()) _objectEditor->copy(path);
});
QObject::connect(_object_palette, &Ui::ObjectPalette::selected, [=](std::string str) {
_objectEditor->copy(str);
});
}
ToolDrawParameters ObjectTool::drawParameters() const
{
return
{
.radius = _objectEditor->brushRadius(),
};
}
float ObjectTool::brushRadius() const
{
return _objectEditor->brushRadius();
}
bool ObjectTool::useMultiselectionPivot() const
{
return _use_median_pivot_point.get();
}
bool ObjectTool::useMedianPivotPoint() const
{
return _use_median_pivot_point.get();
}
void ObjectTool::registerMenuItems(QMenu* menu)
{
addMenuTitle(menu, name());
addMenuItem(menu, "Last M2 from WMV", QKeySequence{ "Shift+V" }, [this] { _objectEditor->import_last_model_from_wmv(eMODEL); });
addMenuItem(menu, "Last WMO from WMV", QKeySequence{ "Alt+V" }, [this] { _objectEditor->import_last_model_from_wmv(eWMO); });
addMenuItem(menu, "Helper models", [this] {_objectEditor->helper_models_widget->show(); });
}
void ObjectTool::registerContextMenuItems(QMenu* menu)
{
auto world = mapView()->getWorld();
addMenuTitle(menu, name());
bool has_selected_objects = world->get_selected_model_count();
bool has_copied_objects = _objectEditor->clipboardSize();
addMenuItem(menu, "Copy Object(s)", QKeySequence::Copy, has_selected_objects, [=] { _objectEditor->copy_current_selection(world); });
addMenuItem(menu, "Paste Object(s)", QKeySequence::Paste, has_copied_objects, [=] {
auto mv = mapView();
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_ADDED);
_objectEditor->pasteObject(mv->cursorPosition(), mv->getCamera()->position, world, &_object_paste_params);
NOGGIT_ACTION_MGR->endAction();
});
addMenuItem(menu, "Delete Object(s)", QKeySequence::Delete, has_selected_objects, [=] {
auto mv = mapView();
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_REMOVED);
mv->DeleteSelectedObjects();
NOGGIT_ACTION_MGR->endAction();
});
addMenuItem(menu, "Duplicate Object(s)", { "CTRL+B" }, has_copied_objects, [=] {
auto mv = mapView();
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_ADDED);
_objectEditor->copy_current_selection(world);
_objectEditor->pasteObject(mv->cursorPosition(), mv->getCamera()->position, world, &_object_paste_params);
NOGGIT_ACTION_MGR->endAction();
});
addMenuSeperator(menu);
addMenuItem(menu, "Select all Like Selected", "Warning : Doing actions on models overlapping unloaded tiles can cause crash",
world->get_selected_model_count() == 1, [=] {
auto world = mapView()->getWorld();
auto last_entry = world->get_last_selected_model();
if (last_entry)
{
if (!last_entry.value().index() == eEntry_Object)
return;
auto obj = std::get<selected_object_type>(last_entry.value());
auto model_name = obj->instance_model()->file_key().filepath();
// auto models = world->get_models_by_filename()[model_name];
// if changing this, make sure to check for duplicate instead // if (!world->is_selected(instance))
world->reset_selection();
if (obj->which() == eMODEL)
{
world->getModelInstanceStorage().for_each_m2_instance([&](ModelInstance& model_instance)
{
if (model_instance.instance_model()->file_key().filepath() == model_name)
{
world->add_to_selection(&model_instance);
}
});
}
else if (obj->which() == eWMO)
world->getModelInstanceStorage().for_each_wmo_instance([&](WMOInstance& wmo_instance)
{
if (wmo_instance.instance_model()->file_key().filepath() == model_name)
{
// objects_to_select.push_back(wmo_instance.uid);
world->add_to_selection(&wmo_instance);
}
});
// for (auto uid_it = objects_to_select.begin(); uid_it != objects_to_select.end(); uid_it++)
// {
// auto instance = world->getObjectInstance(*uid_it);
// // if (!world->is_selected(instance))
// world->add_to_selection(instance);
// }
}
});
addMenuItem(menu, "Hide Selected Objects", Qt::Key_H, has_selected_objects, [=] {
if (world->has_selection())
{
for (auto& obj : world->get_selected_objects())
{
if (obj->which() == eMODEL)
static_cast<ModelInstance*>(obj)->model->hide();
else if (obj->which() == eWMO)
static_cast<WMOInstance*>(obj)->wmo->hide();
}
}
});
addMenuItem(menu, "Hide Unselected Objects (NOT IMPLEMENTED)", [] {});
// QAction action_2("Show Hidden", this);
addMenuItem(menu, "Add Object To Palette", QKeySequence::UnknownKey, world->get_selected_model_count(),
[=] {
auto last_entry = world->get_last_selected_model();
if (last_entry)
{
if (!last_entry.value().index() == eEntry_Object)
return;
_object_palette_dock->setVisible(true);
auto obj = std::get<selected_object_type>(last_entry.value());
auto model_name = obj->instance_model()->file_key().filepath();
_object_palette->addObjectByFilename(model_name.c_str());
}
});
addMenuSeperator(menu);
// allow replacing all selected?
addMenuItem(menu, "Replace Models (By Clipboard)", "Replace the currently selected objects by the object in the clipboard (There must only be one!). M2s can only be replaced by m2s",
has_selected_objects && _objectEditor->clipboardSize() == 1, [=] {
auto mv = mapView();
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
if (mv->get_editing_mode() != editing_mode::object && NOGGIT_CUR_ACTION)
return;
if (!_objectEditor->clipboardSize())
return;
// verify this
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_ADDED | Noggit::ActionFlags::eOBJECTS_REMOVED);
// get the model to replace by
auto replace_select = _objectEditor->getClipboard().front();
auto replacement_obj = std::get<selected_object_type>(replace_select);
auto& replace_path = replacement_obj->instance_model()->file_key().filepath();
std::vector<SceneObject*> objects_to_delete;
// iterate selection (objects to replace)
std::vector<selected_object_type> selected_objects = world->get_selected_objects();
for (SceneObject* old_obj : selected_objects)
{
if (old_obj->instance_model()->file_key().filepath() == replace_path)
continue;
math::degrees::vec3 source_rot(math::degrees(0)._, math::degrees(0)._, math::degrees(0)._);
source_rot = old_obj->dir;
float source_scale = old_obj->scale;
glm::vec3 source_pos = old_obj->pos;
// world->deleteInstance(old_obj->uid);
objects_to_delete.emplace_back(old_obj);
if (replacement_obj->which() == eWMO)
{
// auto replace_wmo = static_cast<WMOInstance*>(replacement_obj);
// auto source_wmo = static_cast<WMOInstance*>(old_obj);
auto new_obj = world->addWMOAndGetInstance(replace_path, source_pos, source_rot, true);
new_obj->wmo->wait_until_loaded();
new_obj->wmo->waitForChildrenLoaded();
new_obj->recalcExtents();
}
else if (replacement_obj->which() == eMODEL)
{
// auto replace_m2 = static_cast<ModelInstance*>(replacement_obj);
// auto source_m2 = static_cast<ModelInstance*>(source_obj);
// Just swapping model
// Issue : doesn't work with actions
// world->updateTilesEntry(entry, model_update::remove);
// source_m2->model = scoped_model_reference(replace_path, _context);
// source_m2->recalcExtents();
// world->updateTilesEntry(entry, model_update::add);
auto new_obj = world->addM2AndGetInstance(replace_path
, source_pos
, source_scale
, source_rot
, &_object_paste_params
, true
, true
);
new_obj->model->wait_until_loaded();
new_obj->model->waitForChildrenLoaded();
new_obj->recalcExtents();
}
}
// this would also delete models that got skipped
// world->delete_selected_models();
world->deleteObjects(objects_to_delete, true);
world->reset_selection();
NOGGIT_ACTION_MGR->endAction();
});
addMenuItem(menu, "Snap Selected To Ground", Qt::Key_PageDown, has_selected_objects, [=] {
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eOBJECTS_TRANSFORMED);
mapView()->snap_selected_models_to_the_ground();
NOGGIT_ACTION_MGR->endAction();
});
addMenuItem(menu, "Save objects coords(to file)", QKeySequence::UnknownKey, has_selected_objects, [=] {
if (world->has_selection() && world->get_selected_model_count())
{
std::stringstream obj_data;
for (auto& obj : world->get_selected_objects())
{
obj_data << "\"Object : " << obj->instance_model()->file_key().filepath() << "(UID :" << obj->uid << ")\"," << std::endl;
obj_data << "\"Scale : " << obj->scale << "\"," << std::endl;
// coords string in ts-wow format
obj_data << "\"Coords(server): {map:" << world->getMapID() << ",x:" << (ZEROPOINT - obj->pos.z) << ",y:" << (ZEROPOINT - obj->pos.x)
<< ",z:" << obj->pos.y << ",o:";
float server_rot = 2 * glm::pi<float>() - glm::pi<float>() / 180.0 * (float(obj->dir.y) < 0 ? fabs(float(obj->dir.y)) + 180.0 : fabs(float(obj->dir.y) - 180.0));
// float server_rot = glm::radians(obj->dir.y) + glm::radians(180.f);
obj_data << server_rot << "}\"," << std::endl;
/// converting db gobject rotation to noggit. Keep commented for later usage
/*
glm::quat test_db_quat = glm::quat(1.0, 1.0, 1.0, 1.0);
test_db_quat.x = 0.607692, test_db_quat.y = -0.361538, test_db_quat.z = 0.607693, test_db_quat.w = 0.361539;
glm::vec3 rot_euler = glm::eulerAngles(test_db_quat);
glm::vec3 rot_degrees = glm::degrees(rot_euler);
rot_degrees = glm::vec3(rot_degrees.y, rot_degrees.z - 180.f, rot_degrees.x); // final noggit coords
*/
glm::quat rot_quat = glm::quat(glm::vec3(glm::radians(obj->dir.z), glm::radians(obj->dir.x), server_rot));
auto normalized_quat = glm::normalize(rot_quat);
obj_data << "\"Rotation (server quaternion): {x:" << normalized_quat.x << ",y:" << normalized_quat.y << ",z:" << normalized_quat.z
<< ",w:" << normalized_quat.w << "}\"," << std::endl << "\n";
}
std::ofstream f("saved_objects_data.txt", std::ios_base::app);
f << "\"Saved " << world->get_selected_model_count() << " objects at : " << QDateTime::currentDateTime().toString("dd MMMM yyyy hh:mm:ss").toStdString() << "\"" << std::endl;
f << obj_data.str();
f.close();
}});
addMenuSeperator(menu);
bool groupable = false;
if (world->has_multiple_model_selected())
{
// if there's no existing groups, that means it's always groupable
if (!world->_selection_groups.size())
groupable = true;
if (!groupable)
{
// check if there's any ungrouped object
for (auto obj : world->get_selected_objects())
{
bool obj_ungrouped = true;
for (auto& group : world->_selection_groups)
{
if (group.contains_object(obj))
obj_ungrouped = false;
}
if (obj_ungrouped)
{
groupable = true;
break;
}
}
}
}
// TODO
addMenuItem(menu, "Group Selected Objects", QKeySequence::UnknownKey, groupable, [=] {
// remove all groups the objects are already in and create a new one
// for (auto obj : _world->get_selected_objects())
// {
// for (auto& group : _world->_selection_groups)
// {
// if (group.contains_object(obj))
// {
// group.remove_group();
// }
// }
// }
for (auto& group : world->_selection_groups)
{
if (group.isSelected())
{
group.remove_group();
}
}
world->add_object_group_from_selection();
});
bool group_selected = false;
for (auto& group : world->_selection_groups)
{
if (group.isSelected())
{
group_selected = true;
break;
}
}
addMenuItem(menu, "Ungroup Selected Objects", QKeySequence::UnknownKey, group_selected, [=] {
world->clear_selection_groups();
});
}
void ObjectTool::onSelected()
{
_object_palette_dock->setVisible(!mapView()->isUiHidden() && mapView()->settings()->value("map_view/object_palette", false).toBool());
}
void ObjectTool::onDeselected()
{
_objectEditor->modelImport->hide();
_objectEditor->rotationEditor->hide();
_object_palette->hide();
_object_palette_dock->hide();
_moveObject = false;
}
void ObjectTool::onTick(float deltaTime, TickParameters const& params)
{
unsigned action_modality = 0;
float numpad_moveratio = 0.001f;
if (mapView()->getWorld()->has_selection())
{
auto mv = mapView();
auto world = mv->getWorld();
// reset numpad_moveratio when no numpad key is pressed
if (!(_keyx != 0 || _keyy != 0 || _keyz != 0 || _keyr != 0 || _keys != 0))
{
numpad_moveratio = 0.5f;
}
else // Set move scale and rotate for numpad keys
{
if (params.mod_ctrl_down && params.mod_shift_down)
{
numpad_moveratio += 0.5f;
}
else if (params.mod_shift_down)
{
numpad_moveratio += 0.05f;
}
else if (params.mod_ctrl_down)
{
numpad_moveratio += 0.005f;
}
}
if (_keys != 0.f)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eSCALE);
world->scale_selected_models(_keys * numpad_moveratio / 50.f, World::m2_scaling_type::add);
updateRotationEditor();
}
if (_keyr != 0.f)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eROTATE);
world->rotate_selected_models(math::degrees(0.f)
, math::degrees(_keyr * numpad_moveratio * 5.f)
, math::degrees(0.f)
, _use_median_pivot_point.get()
);
updateRotationEditor();
}
if (_moveObject)
{
if (params.mod_alt_down)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eALT
| Noggit::ActionModalityControllers::eMMB);
world->scale_selected_models(std::pow(2.f, _mv * 4.f), World::m2_scaling_type::mult);
}
else if (params.mod_shift_down)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eMMB);
world->move_selected_models(0.f, _mv * 80.f, 0.f);
}
else if (params.mod_ctrl_down)
{
// do nothing
}
else
{
bool snapped = false;
bool snapped_to_object = false;
if (world->has_multiple_model_selected())
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eMMB);
world->set_selected_models_pos(mv->cursorPosition(), false);
if (_snap_multi_selection_to_ground.get())
{
mv->snap_selected_models_to_the_ground();
snapped = true;
}
}
else
{
if (!_move_model_to_cursor_position.get())
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eMMB);
if ((_mh <= 0.01f && _mh >= -0.01f) && (_mv <= 0.01f && _mv >= -0.01f))
{
glm::vec3 _vec = (_mh * params.dirUp + _mv * params.dirRight);
world->move_selected_models(_vec * 500.f);
}
}
else
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eMMB);
if (_move_model_to_cursor_position.get() || _move_model_snap_to_objects.get())
{
selection_result results(mv->intersect_result(false));
if (!results.empty())
{
for (auto result = results.begin(); result != results.end(); result++)
{
auto const& hit(result->second);
bool is_selected_model = false;
// if a terrain is found first use that (terrain cursor pos position updated on move already)
if (hit.index() == eEntry_MapChunk && _move_model_to_cursor_position.get())
{
break;
}
if (hit.index() == eEntry_Object && _move_model_snap_to_objects.get())
{
auto obj_hit = std::get<selected_object_type>(hit);
auto obj_hit_type = obj_hit->which();
// don't snap to animated models
if (obj_hit_type == eMODEL)
{
auto m2_model_hit = static_cast<ModelInstance*>(obj_hit);
if (m2_model_hit->model->animated_mesh())
continue;
}
// find and ignore current object/selected models or it will keep snaping to itself
for (auto& entry : world->current_selection())
{
auto type = entry.index();
if (type == eEntry_Object)
{
auto& selection_obj = std::get<selected_object_type>(entry);
if (selection_obj->uid == obj_hit->uid)
{
is_selected_model = true;
break;
}
}
}
if (is_selected_model)
continue;
auto hit_pos = mv->intersect_ray().position(result->first);
mv->cursorPosition(hit_pos);
snapped_to_object = true;
// TODO : rotate objects to objects normal
// if (_rotate_doodads_along_doodads.get())
// world->rotate_selected_models_to_object_normal(_rotate_along_ground_smooth.get(), obj_hit, hit_pos, glm::transpose(model_view()), _rotate_doodads_along_wmos.get());
break;
}
}
}
world->set_selected_models_pos(mv->cursorPosition(), false);
snapped = true;
}
}
}
if (snapped && _rotate_along_ground.get())
{
if (!snapped_to_object)
world->rotate_selected_models_to_ground_normal(_rotate_along_ground_smooth.get());
if (_rotate_along_ground_random.get())
{
float minX = 0, maxX = 0, minY = 0, maxY = 0, minZ = 0, maxZ = 0;
if (mv->settings()->value("model/random_rotation", false).toBool())
{
minY = _object_paste_params.minRotation;
maxY = _object_paste_params.maxRotation;
}
if (mv->settings()->value("model/random_tilt", false).toBool())
{
minX = _object_paste_params.minTilt;
maxX = _object_paste_params.maxTilt;
minZ = minX;
maxZ = maxX;
}
world->rotate_selected_models_randomly(
minX,
maxX,
minY,
maxY,
minZ,
maxZ);
if (mv->settings()->value("model/random_size", false).toBool())
{
float min = _object_paste_params.minScale;
float max = _object_paste_params.maxScale;
world->scale_selected_models(misc::randfloat(min, max), World::m2_scaling_type::set);
}
}
}
}
updateRotationEditor();
}
/* TODO: Numpad for action system
if (_keyx != 0.f || _keyy != 0.f || _keyz != 0.f)
{
world->move_selected_models(_keyx * numpad_moveratio, _keyy * numpad_moveratio, _keyz * numpad_moveratio);
updateRotationEditor();
}
*/
if (mv->isRotatingCamera())
{
if (params.mod_ctrl_down) // X
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eCTRL
| Noggit::ActionModalityControllers::eRMB);
world->rotate_selected_models(math::degrees(_rh + _rv)
, math::degrees(0.f)
, math::degrees(0.f)
, _use_median_pivot_point.get()
);
}
if (params.mod_shift_down) // Y
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eRMB);
world->rotate_selected_models(math::degrees(0.f)
, math::degrees(_rh + _rv)
, math::degrees(0.f)
, _use_median_pivot_point.get()
);
}
if (params.mod_alt_down) // Z
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
Noggit::ActionModalityControllers::eALT
| Noggit::ActionModalityControllers::eRMB);
world->rotate_selected_models(math::degrees(0.f)
, math::degrees(0.f)
, math::degrees(_rh + _rv)
, _use_median_pivot_point.get()
);
}
updateRotationEditor();
}
}
_mh = 0;
_mv = 0;
_rh = 0;
_rv = 0;
}
void ObjectTool::onMousePress(MousePressParameters const& params)
{
if (params.button == Qt::MouseButton::LeftButton && !params.mod_ctrl_down)
{
_area_selection->setGeometry(QRect(_drag_start_pos, QSize()));
_area_selection->show();
_drag_start_pos = params.mouse_position;
mapView()->invalidate();
}
if (params.button == Qt::MouseButton::MiddleButton)
{
_moveObject = true;
}
}
void ObjectTool::onMouseRelease(MouseReleaseParameters const& params)
{
if (params.button == Qt::MouseButton::MiddleButton)
{
_moveObject = false;
return;
}
if (params.button != Qt::MouseButton::LeftButton || params.mod_ctrl_down)
{
return;
}
auto drag_end_pos = params.mouse_position;
if (_drag_start_pos != drag_end_pos && !ImGuizmo::IsUsing())
{
const std::array<glm::vec2, 2> selection_box
{
glm::vec2(std::min(_drag_start_pos.x(), drag_end_pos.x()), std::min(_drag_start_pos.y(), drag_end_pos.y())),
glm::vec2(std::max(_drag_start_pos.x(), drag_end_pos.x()), std::max(_drag_start_pos.y(), drag_end_pos.y()))
};
// _world->select_objects_in_area(selection_box, !_mod_shift_down, model_view(), projection(), width(), height(), objectEditor->drag_selection_depth(), _camera.position);
mapView()->selectObjects(selection_box, 3000.0f);
}
else // Do normal selection when we just clicked
{
mapView()->doSelection(false);
}
_area_selection->hide();
}
void ObjectTool::onMouseMove(MouseMoveParameters const& params)
{
auto mapView = this->mapView();
if (_moveObject)
{
_mh = -mapView->aspect_ratio() * params.relative_movement.dx() / static_cast<float>(mapView->width());
_mv = -params.relative_movement.dy() / static_cast<float>(mapView->height());
}
else
{
_mh = 0.0f;
_mv = 0.0f;
}
if (params.mod_shift_down || params.mod_ctrl_down || params.mod_alt_down || params.mod_space_down)
{
_rh = params.relative_movement.dx() / XSENS * 5.0f;
_rv = params.relative_movement.dy() / YSENS * 5.0f;
}
if (params.left_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_objectEditor->changeRadius(params.relative_movement.dx() / XSENS);
}
if (!params.mod_alt_down && params.displayMode == display_mode::in_3D && !ImGuizmo::IsUsing())
{
_area_selection->setGeometry(QRect(_drag_start_pos, params.mouse_position).normalized());
mapView->invalidate();
}
if (params.mod_shift_down || params.mod_ctrl_down)
{
mapView->doSelection(false, true);
}
}
}
void ObjectTool::hidePopups()
{
_objectEditor->modelImport->hide();
_objectEditor->rotationEditor->hide();
_objectEditor->helper_models_widget->hide();
_object_palette_dock->hide();
}
void ObjectTool::onFocusLost()
{
_keyx = 0;
_keyz = 0;
_keyy = 0;
_keyr = 0;
_keys = 0;
_moveObject = false;
}
void ObjectTool::setupHotkeys()
{
auto mapView = this->mapView();
addHotkey("copySelection"_hash, Hotkey{
.onPress = [=] { _objectEditor->copy_current_selection(mapView->getWorld()); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object && !NOGGIT_CUR_ACTION; },
});
addHotkey("paste"_hash, Hotkey{
.onPress = [=] {
NOGGIT_ACTION_MGR->beginAction(mapView, Noggit::ActionFlags::eOBJECTS_ADDED);
_objectEditor->pasteObject(mapView->cursorPosition(), mapView->getCamera()->position, mapView->getWorld(), &_object_paste_params);
NOGGIT_ACTION_MGR->endAction();
},
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object && !NOGGIT_CUR_ACTION; },
});
addHotkey("importM2FromWmv"_hash, Hotkey{
.onPress = [=] { _objectEditor->import_last_model_from_wmv(eMODEL); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object && !NOGGIT_CUR_ACTION; },
});
addHotkey("importWmoFromWmv"_hash, Hotkey{
.onPress = [=] { _objectEditor->import_last_model_from_wmv(eWMO); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object && !NOGGIT_CUR_ACTION; },
});
addHotkey("duplacteSelection"_hash, Hotkey{
.onPress = [=] {
NOGGIT_ACTION_MGR->beginAction(mapView, Noggit::ActionFlags::eOBJECTS_ADDED);
_objectEditor->copy_current_selection(mapView->getWorld());
_objectEditor->pasteObject(mapView->cursorPosition(), mapView->getCamera()->position, mapView->getWorld(), &_object_paste_params);
NOGGIT_ACTION_MGR->endAction();
},
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object && !NOGGIT_CUR_ACTION; },
});
addHotkey("togglePasteMode"_hash, Hotkey{
.onPress = [=] { _objectEditor->togglePasteMode(); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("moveSelectedDown"_hash, Hotkey{
.onPress = [=] { _keyx = 1; },
.onRelease = [=] { _keyx = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("moveSelectedUp"_hash, Hotkey{
.onPress = [=] { _keyx = -1; },
.onRelease = [=] { _keyx = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("moveSelectedLeft"_hash, Hotkey{
.onPress = [=] { _keyz = 1; },
.onRelease = [=] { _keyz = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("moveSelectedRight"_hash, Hotkey{
.onPress = [=] { _keyz = -1; },
.onRelease = [=] { _keyz = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("rotateSelectedPitchCcw"_hash, Hotkey{
.onPress = [=] { _keyy = 1; },
.onRelease = [=] { _keyy = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("rotateSelectedPitchCw"_hash, Hotkey{
.onPress = [=] { _keyy = -1; },
.onRelease = [=] { _keyy = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("rotateSelectedYawCcw"_hash, Hotkey{
.onPress = [=] { _keyr = 1; },
.onRelease = [=] {_keyr = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("rotateSelectedYawCw"_hash, Hotkey{
.onPress = [=] {_keyr = -1; },
.onRelease = [=] {_keyr = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("increaseSelectedScale"_hash, Hotkey{
.onPress = [=] { _keys = 1; },
.onRelease = [=] { _keys = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
addHotkey("decreaseSelectedScale"_hash, Hotkey{
.onPress = [=] { _keys = -1; },
.onRelease = [=] { _keys = 0; },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::object; },
});
}
void ObjectTool::updateRotationEditor()
{
_objectEditor->rotationEditor->updateValues(mapView()->getWorld());
}
}

View File

@@ -0,0 +1,93 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
#include <noggit/object_paste_params.hpp>
#include <noggit/BoolToggleProperty.hpp>
class QRubberBand;
class QDockWidget;
namespace Noggit
{
namespace Ui
{
class object_editor;
class ObjectPalette;
}
class ObjectTool final : public Tool
{
public:
ObjectTool(MapView* mapView);
~ObjectTool();
[[nodiscard]]
unsigned int actionModality() const override;
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
[[nodiscard]]
float brushRadius() const override;
[[nodiscard]]
bool useMultiselectionPivot() const override;
[[nodiscard]]
bool useMedianPivotPoint() const override;
void registerMenuItems(QMenu* menu) override;
void registerContextMenuItems(QMenu* menu) override;
void onSelected() override;
void onDeselected() override;
void onTick(float deltaTime, TickParameters const& params) override;
void onMousePress(MousePressParameters const& params) override;
void onMouseRelease(MouseReleaseParameters const& params) override;
void onMouseMove(MouseMoveParameters const& params) override;
void hidePopups() override;
void onFocusLost() override;
private:
Ui::object_editor* _objectEditor = nullptr;
QRubberBand* _area_selection = nullptr;
Ui::ObjectPalette* _object_palette = nullptr;
QDockWidget* _object_palette_dock = nullptr;
object_paste_params _object_paste_params;
BoolToggleProperty _move_model_to_cursor_position = { true };
BoolToggleProperty _snap_multi_selection_to_ground = { false };
BoolToggleProperty _use_median_pivot_point = { true };
BoolToggleProperty _rotate_along_ground = { true };
BoolToggleProperty _rotate_along_ground_smooth = { true };
BoolToggleProperty _rotate_along_ground_random = { false };
BoolToggleProperty _move_model_snap_to_objects = { true };
QPoint _drag_start_pos;
float _keyx = 0, _keyy = 0, _keyz = 0, _keyr = 0, _keys = 0;
float _mh = 0, _mv = 0, _rh = 0, _rv = 0; // mh = left click x, rv = right click y
bool _moveObject = false;
void setupHotkeys();
void updateRotationEditor();
};
}

View File

@@ -0,0 +1,254 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "RaiseLowerTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/Input.hpp>
#include <noggit/MapView.h>
#include <noggit/ui/TerrainTool.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <random>
namespace Noggit
{
RaiseLowerTool::RaiseLowerTool(MapView* mapView)
: Tool{ mapView }
{
addHotkey("nextType"_hash, Hotkey{
.onPress = [this] { _terrainTool->nextType(); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::ground && !NOGGIT_CUR_ACTION; },
});
addHotkey("flatten"_hash, Hotkey{
.onPress = [this] {
NOGGIT_ACTION_MGR->beginAction(this->mapView(), Noggit::ActionFlags::eCHUNKS_TERRAIN);
_terrainTool->flattenVertices(this->mapView()->getWorld());
NOGGIT_ACTION_MGR->endAction();
},
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::ground && !NOGGIT_CUR_ACTION; },
});
addHotkey("increaseRadius"_hash, Hotkey{
.onPress = [this] { _terrainTool->changeRadius(0.01f); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::ground && !NOGGIT_CUR_ACTION; },
});
addHotkey("decreaseRadius"_hash, Hotkey{
.onPress = [this] { _terrainTool->changeRadius(-0.01f); },
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::ground && !NOGGIT_CUR_ACTION; },
});
addHotkey("clearVertexSelection"_hash, Hotkey{
.onPress = [=] {
NOGGIT_ACTION_MGR->beginAction(mapView, Noggit::ActionFlags::eVERTEX_SELECTION);
mapView->getWorld()->clearVertexSelection();
NOGGIT_ACTION_MGR->endAction();
},
.condition = [mapView] { return mapView->get_editing_mode() == editing_mode::ground && !NOGGIT_CUR_ACTION; },
});
}
RaiseLowerTool::~RaiseLowerTool()
{
delete _terrainTool;
}
char const* RaiseLowerTool::name() const
{
return "Raise / Lower";
}
editing_mode RaiseLowerTool::editingMode() const
{
return editing_mode::ground;
}
Ui::FontNoggit::Icons RaiseLowerTool::icon() const
{
return Ui::FontNoggit::TOOL_RAISE_LOWER;
}
void RaiseLowerTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_terrainTool = new Noggit::Ui::TerrainTool{ mapView(), mapView() };
toolPanel->registerTool(name(), _terrainTool);
QObject::connect(_terrainTool
, &Noggit::Ui::TerrainTool::updateVertices
, [mapView = mapView()](int vertex_mode, math::degrees const& angle, math::degrees const& orientation)
{
mapView->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mapView->context());
mapView->getWorld()->orientVertices(vertex_mode == eVertexMode_Mouse
? mapView->cursorPosition()
: mapView->getWorld()->vertexCenter()
, angle
, orientation
);
}
);
}
ToolDrawParameters RaiseLowerTool::drawParameters() const
{
CursorType cursorType = CursorType::CIRCLE;
if ((_terrainTool->_edit_type != eTerrainType_Vertex && _terrainTool->_edit_type != eTerrainType_Script) && _terrainTool->getImageMaskSelector()->isEnabled())
cursorType = CursorType::STAMP;
return ToolDrawParameters
{
.radius = _terrainTool->brushRadius(),
.inner_radius = _terrainTool->innerRadius(),
.cursor_type = cursorType,
.terrain_type = _terrainTool->_edit_type,
};
}
void RaiseLowerTool::onSelected()
{
if (_terrainTool->_edit_type != eTerrainType_Vertex
|| (_terrainTool->_edit_type != eTerrainType_Script && _terrainTool->getImageMaskSelector()->isEnabled()))
{
_terrainTool->updateMaskImage();
}
}
void RaiseLowerTool::onTick(float deltaTime, TickParameters const& params)
{
if (!params.left_mouse)
{
return;
}
if (params.displayMode == display_mode::in_3D && !params.underMap)
{
auto mask_selector = _terrainTool->getImageMaskSelector();
auto mv = mapView();
if (params.mod_shift_down && (!mask_selector->isEnabled() || mask_selector->getBrushMode()))
{
auto action = NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
action->setPostCallback([this] { randomizeTerrainRotation(); });
_terrainTool->changeTerrain(mv->getWorld(), mv->cursorPosition(), 7.5f * deltaTime);
}
else if (params.mod_ctrl_down && (!mask_selector->isEnabled() || mask_selector->getBrushMode()))
{
auto action = NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eCTRL
| Noggit::ActionModalityControllers::eLMB);
action->setPostCallback([this] { randomizeTerrainRotation(); });
_terrainTool->changeTerrain(mv->getWorld(), mv->cursorPosition(), -7.5f * deltaTime);
}
}
}
void RaiseLowerTool::onMouseMove(MouseMoveParameters const& params)
{
if (params.right_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
if (_terrainTool->_edit_type == eTerrainType_Vertex)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eALT | Noggit::ActionModalityControllers::eRMB);
_terrainTool->changeOrientation(-params.relative_movement.dx() / XSENS * 4.5f);
}
else
{
_terrainTool->changeInnerRadius(params.relative_movement.dx() / 100.0f);
}
}
if (!params.mod_alt_down && params.mod_shift_down && !params.mod_ctrl_down)
{
if (_terrainTool->_edit_type == eTerrainType_Vertex)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eSHIFT | Noggit::ActionModalityControllers::eRMB);
_terrainTool->moveVertices(mapView()->getWorld(), -params.relative_movement.dy() / YSENS);
}
}
if (!params.mod_alt_down && !params.mod_shift_down && params.mod_ctrl_down)
{
if (_terrainTool->_edit_type == eTerrainType_Vertex)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eCTRL |
Noggit::ActionModalityControllers::eRMB);
_terrainTool->changeAngle(-params.relative_movement.dy() / YSENS * 4.f);
}
}
if (params.mod_space_down)
{
if (_terrainTool->_edit_type == eTerrainType_Vertex)
{
NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eRMB
| Noggit::ActionModalityControllers::eSPACE);
_terrainTool->setOrientRelativeTo(mapView()->getWorld(), mapView()->cursorPosition());
}
else if (_terrainTool->getImageMaskSelector()->isEnabled())
{
auto action = NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eDO_NOT_WRITE_HISTORY,
Noggit::ActionModalityControllers::eRMB
| Noggit::ActionModalityControllers::eSPACE);
_terrainTool->getImageMaskSelector()->setRotation(-params.relative_movement.dx() / XSENS * 10.f);
action->setBlockCursor(true);
}
}
}
if (params.left_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_terrainTool->changeRadius(params.relative_movement.dx() / XSENS);
}
if (params.mod_space_down)
{
_terrainTool->changeSpeed(params.relative_movement.dx() / 30.0f);
}
if (params.mod_shift_down && params.displayMode == display_mode::in_3D)
{
auto image_mask_selector = _terrainTool->getImageMaskSelector();
if (_terrainTool->_edit_type != eTerrainType_Vertex && _terrainTool->_edit_type != eTerrainType_Script &&
image_mask_selector->isEnabled() && !image_mask_selector->getBrushMode())
{
auto action = NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eCHUNKS_TERRAIN,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
action->setPostCallback([this] { randomizeTerrainRotation(); });
_terrainTool->changeTerrain(mapView()->getWorld(), mapView()->cursorPosition(), params.relative_movement.dx() / 30.0f);
}
}
}
}
void RaiseLowerTool::randomizeTerrainRotation()
{
auto image_mask_selector = _terrainTool->getImageMaskSelector();
if (!image_mask_selector->getRandomizeRotation())
return;
unsigned int ms = static_cast<unsigned>(QDateTime::currentMSecsSinceEpoch());
std::mt19937 gen(ms);
std::uniform_int_distribution<> uid(0, 360);
image_mask_selector->setRotation(uid(gen));
}
}

View File

@@ -0,0 +1,45 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Ui
{
class TerrainTool;
}
class RaiseLowerTool final : public Tool
{
public:
RaiseLowerTool(MapView* mapView);
~RaiseLowerTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onSelected() override;
void onTick(float deltaTime, TickParameters const& params) override;
void onMouseMove(MouseMoveParameters const& params) override;
private:
Ui::TerrainTool* _terrainTool = nullptr;
void randomizeTerrainRotation();
};
}

View File

@@ -0,0 +1,70 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "ScriptingTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_settings.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
namespace Noggit
{
ScriptingTool::ScriptingTool(MapView* mapView)
: Tool{ mapView }
{
}
ScriptingTool::~ScriptingTool()
{
delete _scriptingTool;
}
char const* ScriptingTool::name() const
{
return "Scripting";
}
editing_mode ScriptingTool::editingMode() const
{
return editing_mode::scripting;
}
Ui::FontNoggit::Icons ScriptingTool::icon() const
{
return Ui::FontNoggit::INFO;
}
void ScriptingTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_scriptingTool = new Noggit::Scripting::scripting_tool(mapView(), mapView(), mapView()->settings());
toolPanel->registerTool(name(), _scriptingTool);
}
ToolDrawParameters ScriptingTool::drawParameters() const
{
return
{
.radius = _scriptingTool->get_settings()->brushRadius(),
.inner_radius = _scriptingTool->get_settings()->innerRadius(),
};
}
void ScriptingTool::onTick(float deltaTime, TickParameters const& params)
{
auto world = mapView()->getWorld();
auto currentSelection = world->current_selection();
if (world->has_selection())
{
for (auto& selection : currentSelection)
{
if (selection.index() == eEntry_MapChunk)
{
_scriptingTool->sendBrushEvent(mapView()->cursorPosition(), 7.5f * deltaTime);
}
}
}
}
}

View File

@@ -0,0 +1,39 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Scripting
{
class scripting_tool;
}
class ScriptingTool final : public Tool
{
public:
ScriptingTool(MapView* mapView);
~ScriptingTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onTick(float deltaTime, TickParameters const& params) override;
private:
Scripting::scripting_tool* _scriptingTool = nullptr;
};
}

View File

@@ -0,0 +1,177 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "StampTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/tools/BrushStack/BrushStack.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <random>
namespace Noggit
{
StampTool::StampTool(MapView* mapView)
: Tool{ mapView }
{
}
StampTool::~StampTool()
{
delete _stampTool;
}
char const* StampTool::name() const
{
return "Stamp Mode";
}
editing_mode StampTool::editingMode() const
{
return editing_mode::stamp;
}
Ui::FontNoggit::Icons StampTool::icon() const
{
return Ui::FontNoggit::TOOL_STAMP;
}
void StampTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_stampTool = new Noggit::Ui::Tools::BrushStack(mapView(), mapView());
toolPanel->registerTool(name(), _stampTool);
QObject::connect(mapView(), &MapView::trySetBrushTexture, [=](QImage* brush, QWidget* sender) {
auto mv = mapView();
auto item = _stampTool->getActiveBrushItem();
if (mv->get_editing_mode() != editing_mode::stamp || (item && item->getTool() == sender))
{
mv->setBrushTexture(brush);
}
});
}
ToolDrawParameters StampTool::drawParameters() const
{
return
{
.radius = _stampTool->getRadius(),
.inner_radius = _stampTool->getInnerRadius(),
.cursor_type = (_stampTool->getActiveBrushItem() && _stampTool->getActiveBrushItem()->isMaskEnabled()) ? CursorType::STAMP : CursorType::CIRCLE,
};
}
void StampTool::onSelected()
{
if (_stampTool->getActiveBrushItem() && _stampTool->getActiveBrushItem()->isEnabled())
{
_stampTool->getActiveBrushItem()->updateMask();
}
}
void StampTool::onTick(float deltaTime, TickParameters const& params)
{
if (!mapView()->getWorld()->has_selection() || !params.left_mouse)
{
return;
}
auto mv = mapView();
auto world = mv->getWorld();
for (auto& selection : world->current_selection())
{
if (selection.index() != eEntry_MapChunk
|| params.displayMode != display_mode::in_3D
|| !(params.mod_shift_down || params.mod_ctrl_down || params.mod_alt_down)
|| !_stampTool->getBrushMode())
{
continue;
}
auto action = NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eNO_FLAG,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
if (!_stampTool->getBrushMode())
action->setBlockCursor(true);
_stampTool->execute(mv->cursorPosition(),
world, deltaTime,
params.mod_shift_down,
params.mod_alt_down,
params.mod_ctrl_down,
world->isUnderMap(mv->cursorPosition()));
}
}
void StampTool::onMouseMove(MouseMoveParameters const& params)
{
auto mv = mapView();
if (params.right_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_stampTool->changeInnerRadius(params.relative_movement.dx() / 300.0f);
}
if (params.mod_space_down)
{
auto action = NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eDO_NOT_WRITE_HISTORY,
Noggit::ActionModalityControllers::eRMB
| Noggit::ActionModalityControllers::eSPACE);
_stampTool->changeRotation(-params.relative_movement.dx() / XSENS * 10.f);
action->setBlockCursor(true);
}
}
if (params.left_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_stampTool->changeRadius(params.relative_movement.dx() / XSENS);
}
if (params.mod_space_down)
{
_stampTool->changeSpeed(params.relative_movement.dx() / XSENS);
}
if (params.mod_shift_down)
{
if(params.displayMode == display_mode::in_3D && !_stampTool->getBrushMode())
{
auto action = NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eNO_FLAG,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
action->setPostCallback([this] { randomizeStampRotation(); });
action->setBlockCursor(true);
_stampTool->execute(mv->cursorPosition()
, mv->getWorld()
, params.relative_movement.dx() / 30.0f
, params.mod_shift_down
, params.mod_alt_down
, params.mod_ctrl_down
, false);
}
}
}
}
void StampTool::randomizeStampRotation()
{
if (!_stampTool->getRandomizeRotation())
return;
unsigned int ms = static_cast<unsigned>(QDateTime::currentMSecsSinceEpoch());
std::mt19937 gen(ms);
std::uniform_int_distribution<> uid(0, 360);
_stampTool->changeRotation(uid(gen));
}
}

View File

@@ -0,0 +1,44 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Ui::Tools
{
class BrushStack;
}
class StampTool final : public Tool
{
public:
StampTool(MapView* mapView);
~StampTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onSelected() override;
void onTick(float deltaTime, TickParameters const& params) override;
void onMouseMove(MouseMoveParameters const& params) override;
private:
Ui::Tools::BrushStack* _stampTool = nullptr;
void randomizeStampRotation();
};
}

View File

@@ -0,0 +1,584 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "FlattenBlurTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/Input.hpp>
#include <noggit/MapView.h>
#include <noggit/Selection.h>
#include <noggit/ui/texturing_tool.hpp>
#include <noggit/ui/texture_swapper.hpp>
#include <noggit/ui/texture_swapper.hpp>
#include <noggit/ui/TexturePicker.h>
#include <noggit/ui/texture_palette_small.hpp>
#include <noggit/ui/CurrentTexture.h>
#include <noggit/ui/TexturingGUI.h>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <noggit/ui/tools/AssetBrowser/Ui/AssetBrowser.hpp>
#include <noggit/ui/windows/noggitWindow/NoggitWindow.hpp>
#include "TexturingTool.hpp"
#include <noggit/ui/tools/ViewToolbar/Ui/ViewToolbar.hpp>
#include <QDockWidget>
#include <QMenu>
#include <random>
namespace Noggit
{
TexturingTool::TexturingTool(MapView* mapView)
: Tool{ mapView }
{
addHotkey("toggleTool"_hash, Hotkey{
.onPress = [=] { _texturingTool->toggle_tool(); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("setBrushLevelMinMax"_hash, Hotkey{
.onPress = [=] { _texturingTool->toggle_brush_level_min_max(); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("increaseRadius"_hash, Hotkey{
.onPress = [=] { _texturingTool->change_radius(0.1f); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("decreaseRadius"_hash, Hotkey{
.onPress = [=] { _texturingTool->change_radius(-0.1f); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("setBrushLevel0Pct"_hash, Hotkey{
.onPress = [=] { _texturingTool->set_brush_level(0.0f); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("setBrushLevel25Pct"_hash, Hotkey{
.onPress = [=] { _texturingTool->set_brush_level(255.0f * 0.25f); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("setBrushLevel50Pct"_hash, Hotkey{
.onPress = [=] { _texturingTool->set_brush_level(255.0f * 0.5f); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("setBrushLevel75Pct"_hash, Hotkey{
.onPress = [=] { _texturingTool->set_brush_level(255.0f * 0.75f); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("setBrushLevel100Pct"_hash, Hotkey{
.onPress = [=] { _texturingTool->set_brush_level(255.0f); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
addHotkey("toggleTexturePalette"_hash, Hotkey{
.onPress = [=] { _show_texture_palette_small_window.toggle(); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::paint && !NOGGIT_CUR_ACTION; },
});
QObject::connect(mapView
, &MapView::selectionUpdated
, [=](std::vector<selection_type>& selection)
{
if (_texturePickerNeedUpdate)
{
_texturePickerDock->setVisible(true);
_texturePicker->setMainTexture(_texturingTool->_current_texture);
_texturePicker->getTextures(*selection.begin());
_texturePickerNeedUpdate = false;
}
}
);
}
TexturingTool::~TexturingTool()
{
delete _texturePickerDock;
delete _texturePaletteDock;
delete _textureBrowserDock;
delete _texturingTool;
}
char const* TexturingTool::name() const
{
return "Texture Painter";
}
editing_mode TexturingTool::editingMode() const
{
return editing_mode::paint;
}
Ui::FontNoggit::Icons TexturingTool::icon() const
{
return Ui::FontNoggit::TOOL_TEXTURE_PAINT;
}
void TexturingTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
auto mv = mapView();
/* Tool */
_texturingTool = new Ui::texturing_tool(&mv->getCamera()->position, mv, &_show_texture_palette_small_window, mv);
toolPanel->registerTool(name(), _texturingTool);
// Connects
QObject::connect(_texturingTool->texture_swap_tool()->texture_display()
, &Noggit::Ui::current_texture::texture_dropped
, [=](std::string const& filename)
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
_texturingTool->texture_swap_tool()->set_texture(filename);
}
);
QObject::connect(_texturingTool->_current_texture
, &Noggit::Ui::current_texture::texture_dropped
, [=](std::string const& filename)
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
Noggit::Ui::selected_texture::set({ filename, mv->getRenderContext() });
}
);
QObject::connect(_texturingTool->_current_texture, &Noggit::Ui::current_texture::clicked
, [=]
{
_textureBrowserDock->setVisible(!_textureBrowserDock->isVisible());
}
);
QObject::connect(_texturingTool, &Ui::texturing_tool::texturePaletteToggled,
[=]()
{
_show_texture_palette_small_window.set(!_show_texture_palette_small_window.get());
});
/* Additional tools */
/* Texture Browser */
// Dock
_textureBrowserDock = new QDockWidget("Texture Browser", mv);
_textureBrowserDock->setFeatures(QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetFloatable
| QDockWidget::DockWidgetClosable);
_textureBrowserDock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea);
mv->mainWindow()->addDockWidget(Qt::BottomDockWidgetArea, _textureBrowserDock);
_textureBrowserDock->hide();
QObject::connect(_textureBrowserDock, &QDockWidget::visibilityChanged,
[=](bool visible)
{
if (mv->isUiHidden())
return;
mv->settings()->setValue("map_view/texture_browser", visible);
mv->settings()->sync();
});
QObject::connect(mv, &QObject::destroyed, _textureBrowserDock, &QObject::deleteLater);
// End Dock
_texturePalette = new Noggit::Ui::tileset_chooser(mv);
_textureBrowserDock->setWidget(_texturePalette);
QObject::connect(mv, &QObject::destroyed, _texturePalette, &QObject::deleteLater);
QObject::connect(_texturePalette, &Noggit::Ui::tileset_chooser::selected
, [=](std::string const& filename)
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
Noggit::Ui::selected_texture::set({ filename, mv->getRenderContext() });
_texturingTool->_current_texture->set_texture(filename);
_texturePicker->setMainTexture(_texturingTool->_current_texture);
_texturePicker->updateSelection();
}
);
QObject::connect(_texturePalette, &Noggit::Ui::widget::visibilityChanged
, &_show_texture_palette_window, &Noggit::BoolToggleProperty::set
);
QObject::connect(&_show_texture_palette_window, &Noggit::BoolToggleProperty::changed
, [this, mv]
{
if ((mv->get_editing_mode() == editing_mode::paint || mv->get_editing_mode() == editing_mode::stamp)
&& !mv->isUiHidden())
{
_textureBrowserDock->setVisible(_show_texture_palette_window.get());
}
else
{
QSignalBlocker const _(_show_texture_palette_window);
_show_texture_palette_window.set(false);
}
}
);
/* Texture Palette Small */
_texturePaletteSmall = new Noggit::Ui::texture_palette_small(mv->project(), mv->getWorld()->getMapID(), mv);
// Dock
_texturePaletteDock = new QDockWidget("Texture Palette", mv);
_texturePaletteDock->setFeatures(QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetFloatable
| QDockWidget::DockWidgetClosable
);
_texturePaletteDock->setWidget(_texturePaletteSmall);
_texturePaletteDock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
_texturePaletteDock->hide();
QObject::connect(mv, &QObject::destroyed, _texturePaletteDock, &QObject::deleteLater);
mv->mainWindow()->addDockWidget(Qt::BottomDockWidgetArea, _texturePaletteDock);
// End Dock
QObject::connect(_texturePaletteDock, &QDockWidget::visibilityChanged,
[=](bool visible)
{
if (mv->isUiHidden())
return;
mv->settings()->setValue("map_view/texture_palette", visible);
mv->settings()->sync();
});
QObject::connect(_texturePaletteSmall, &Noggit::Ui::texture_palette_small::selected
, [=](std::string const& filename)
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
Noggit::Ui::selected_texture::set({ filename, mv->getRenderContext() });
_texturingTool->_current_texture->set_texture(filename);
}
);
QObject::connect(mv, &QObject::destroyed, _texturePaletteSmall, &QObject::deleteLater);
QObject::connect(&_show_texture_palette_small_window, &Noggit::BoolToggleProperty::changed
, _texturePaletteDock, [=]
{
QSignalBlocker const blocker(_show_texture_palette_small_window);
if (mv->get_editing_mode() == editing_mode::paint && !mv->isUiHidden())
{
_texturePaletteDock->setVisible(_show_texture_palette_small_window.get());
}
else
{
_show_texture_palette_small_window.set(false);
}
}
);
QObject::connect(_texturePaletteDock, &QDockWidget::visibilityChanged
, &_show_texture_palette_small_window, &Noggit::BoolToggleProperty::set
);
QObject::connect(_texturingTool->_current_texture, &Noggit::Ui::current_texture::texture_updated
, [=]()
{
mv->getWorld()->notifyTileRendererOnSelectedTextureChange();
_texturingTool->getGroundEffectsTool()->TextureChanged();
}
);
/* Texture Picker */
// Dock
_texturePickerDock = new QDockWidget("Texture picker", mv);
_texturePickerDock->setFeatures(QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetFloatable
| QDockWidget::DockWidgetClosable);
mv->mainWindow()->addDockWidget(Qt::BottomDockWidgetArea, _texturePickerDock);
_texturePickerDock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
_texturePickerDock->setFloating(true);
_texturePickerDock->hide();
QObject::connect(mv, &QObject::destroyed, _texturePickerDock, &QObject::deleteLater);
// End Dock
_texturePicker = new Noggit::Ui::texture_picker(_texturingTool->_current_texture, mv);
_texturePickerDock->setWidget(_texturePicker);
QObject::connect(mv, &QObject::destroyed, _texturePicker, &QObject::deleteLater);
QObject::connect(_texturePicker
, &Noggit::Ui::texture_picker::set_texture
, [=](scoped_blp_texture_reference texture)
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
Noggit::Ui::selected_texture::set(std::move(texture));
}
);
QObject::connect(_texturePicker, &Noggit::Ui::texture_picker::shift_left
, [=]
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
_texturePicker->shiftSelectedTextureLeft();
}
);
QObject::connect(_texturePicker, &Noggit::Ui::texture_picker::shift_right
, [=]
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
_texturePicker->shiftSelectedTextureRight();
}
);
}
void TexturingTool::registerMenuItems(QMenu* menu)
{
addMenuTitle(menu, "Texture Painter");
addMenuItem(menu, "Texture Browser", Qt::Key_X, _show_texture_palette_window);
addMenuItem(menu, "Texture palette", _show_texture_palette_small_window);
}
ToolDrawParameters TexturingTool::drawParameters() const
{
auto cursorType = CursorType::CIRCLE;
if (_texturingTool->getTexturingMode() == Noggit::Ui::texturing_mode::paint && _texturingTool->getImageMaskSelector()->isEnabled())
cursorType = CursorType::STAMP;
return
{
.radius = _texturingTool->brush_radius(),
.inner_radius = _texturingTool->hardness(),
.show_unpaintable_chunks = _texturingTool->show_unpaintable_chunks(),
.cursor_type = cursorType,
};
}
void TexturingTool::onSelected()
{
auto mv = mapView();
if (_texturingTool->getTexturingMode() == Noggit::Ui::texturing_mode::paint && _texturingTool->getImageMaskSelector()->isEnabled())
{
_texturingTool->updateMaskImage();
}
else if (_texturingTool->getTexturingMode() == Noggit::Ui::texturing_mode::ground_effect)
{
_texturingTool->getGroundEffectsTool()->updateTerrainUniformParams();
}
bool use_classic_ui = mv->settings()->value("classicUI", false).toBool();
if (use_classic_ui)
{
if (_texturingTool->show_unpaintable_chunks())
{
mv->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_paintability_overlay = true;
}
}
else
{
if (mv->getLeftSecondaryViewToolbar()->showUnpaintableChunk())
{
mv->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_paintability_overlay = true;
}
}
_textureBrowserDock->setVisible(!mv->isUiHidden() && mv->settings()->value("map_view/texture_browser", false).toBool());
_texturePaletteDock->setVisible(!mv->isUiHidden() && mv->settings()->value("map_view/texture_palette", false).toBool());
}
void TexturingTool::onDeselected()
{
_texturingTool->getGroundEffectsTool()->hide();
_textureBrowserDock->setVisible(false);
_texturePaletteDock->setVisible(false);
}
void TexturingTool::onTick(float deltaTime, TickParameters const& params)
{
if (!params.left_mouse)
{
return;
}
auto mv = mapView();
if (_texturingTool->getTexturingMode() == Noggit::Ui::texturing_mode::ground_effect)
{
if (params.mod_shift_down)
{
if (_texturingTool->getGroundEffectsTool()->brush_mode() == Noggit::Ui::ground_effect_brush_mode::exclusion)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNK_DOODADS_EXCLUSION,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
mv->getWorld()->paintGroundEffectExclusion(mv->cursorPosition(), _texturingTool->getGroundEffectsTool()->radius(), true);
// mv->getWorld()->setHole(mv->cursorPosition(), holeTool->brushRadius(), _mod_alt_down, false);
}
else if (_texturingTool->getGroundEffectsTool()->brush_mode() == Noggit::Ui::ground_effect_brush_mode::effect)
{
}
}
else if (params.mod_ctrl_down && !params.underMap)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNK_DOODADS_EXCLUSION,
Noggit::ActionModalityControllers::eCTRL
| Noggit::ActionModalityControllers::eLMB);
mv->getWorld()->paintGroundEffectExclusion(mv->cursorPosition(), _texturingTool->getGroundEffectsTool()->radius(), false);
}
}
else
{
if (params.mod_shift_down && params.mod_ctrl_down && params.mod_alt_down)
{
// clear chunk texture
if (!params.underMap)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_TEXTURE,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eCTRL
| Noggit::ActionModalityControllers::eALT
| Noggit::ActionModalityControllers::eLMB);
mv->getWorld()->eraseTextures(mv->cursorPosition());
}
}
else if (params.mod_ctrl_down && !mv->isUiHidden())
{
_texturePickerNeedUpdate = true;
// Pick texture
// _texturePickerDock->setVisible(true);
// _texturePicker->setMainTexture(_texturingTool->_current_texture);
// _texturePicker->getTextures(selection);
}
else if (params.mod_shift_down && !!Noggit::Ui::selected_texture::get())
{
if ((params.displayMode == display_mode::in_3D && !params.underMap) || params.displayMode == display_mode::in_2D)
{
auto image_mask_selector = _texturingTool->getImageMaskSelector();
if (NOGGIT_CUR_ACTION
&& _texturingTool->getTexturingMode() == Noggit::Ui::texturing_mode::paint
&& image_mask_selector->isEnabled()
&& !image_mask_selector->getBrushMode())
{
return;
}
auto action = NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_TEXTURE,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
action->setPostCallback([this] { randomizeTexturingRotation(); });
if (_texturingTool->getTexturingMode() == Noggit::Ui::texturing_mode::paint
&& image_mask_selector->isEnabled()
&& !image_mask_selector->getBrushMode())
action->setBlockCursor(true);
_texturingTool->paint(mv->getWorld(), mv->cursorPosition(), deltaTime, *Noggit::Ui::selected_texture::get());
}
}
}
}
void TexturingTool::onMousePress(MousePressParameters const& params)
{
if (params.button != Qt::MouseButton::LeftButton || !params.mod_ctrl_down)
{
return;
}
mapView()->doSelection(false, false);
}
void TexturingTool::onMouseMove(MouseMoveParameters const& params)
{
if (params.right_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_texturingTool->change_hardness(params.relative_movement.dx() / 300.0f);
}
if (params.mod_space_down)
{
if (_texturingTool->getImageMaskSelector()->isEnabled())
{
auto action = NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eDO_NOT_WRITE_HISTORY,
Noggit::ActionModalityControllers::eRMB
| Noggit::ActionModalityControllers::eSPACE);
_texturingTool->getImageMaskSelector()->setRotation(-params.relative_movement.dx() / XSENS * 10.f);
action->setBlockCursor(true);
}
}
}
if (params.left_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_texturingTool->change_radius(params.relative_movement.dx() / XSENS);
}
if (params.mod_space_down)
{
_texturingTool->change_pressure(params.relative_movement.dx() / 300.0f);
}
}
}
void TexturingTool::onMouseWheel(MouseWheelParameters const& params)
{
auto&& delta_for_range
([&](float range)
{
//! \note / 8.f for degrees, / 40.f for smoothness
return (params.mod_ctrl_down ? 0.01f : 0.1f)
* range
// alt = horizontal delta
* (params.mod_alt_down ? params.event.angleDelta().x() : params.event.angleDelta().y())
/ 320.f
;
}
);
if (params.mod_space_down)
{
_texturingTool->change_brush_level(delta_for_range(255.f));
}
else if (params.mod_alt_down)
{
_texturingTool->change_spray_size(delta_for_range(39.f));
}
else if (params.mod_shift_down)
{
_texturingTool->change_spray_pressure(delta_for_range(10.f));
}
}
void TexturingTool::hidePopups()
{
_texturePaletteSmall->hide();
_texturePickerDock->hide();
_textureBrowserDock->hide();
}
void TexturingTool::randomizeTexturingRotation()
{
auto image_mask_selector = _texturingTool->getImageMaskSelector();
if (!image_mask_selector->getRandomizeRotation())
return;
unsigned int ms = static_cast<unsigned>(QDateTime::currentMSecsSinceEpoch());
std::mt19937 gen(ms);
std::uniform_int_distribution<> uid(0, 360);
image_mask_selector->setRotation(uid(gen));
}
}

View File

@@ -0,0 +1,70 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
#include <noggit/BoolToggleProperty.hpp>
class QDockWidget;
namespace Noggit
{
namespace Ui
{
class texturing_tool;
struct tileset_chooser;
class texture_picker;
class texture_palette_small;
}
class TexturingTool final : public Tool
{
public:
TexturingTool(MapView* mapView);
~TexturingTool();
[[nodiscard]]
char const* name() const override;
[[nodiscard]]
editing_mode editingMode() const override;
[[nodiscard]]
Ui::FontNoggit::Icons icon() const override;
void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
void registerMenuItems(QMenu* menu) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onSelected() override;
void onDeselected() override;
void onTick(float deltaTime, TickParameters const& params) override;
void onMousePress(MousePressParameters const& params) override;
void onMouseMove(MouseMoveParameters const& params) override;
void onMouseWheel(MouseWheelParameters const& params) override;
void hidePopups() override;
private:
Ui::texturing_tool* _texturingTool = nullptr;
QDockWidget* _textureBrowserDock = nullptr;
Ui::tileset_chooser* _texturePalette = nullptr;
Ui::texture_picker* _texturePicker = nullptr;
Ui::texture_palette_small* _texturePaletteSmall = nullptr;
QDockWidget* _texturePaletteDock = nullptr;
QDockWidget* _texturePickerDock = nullptr;
bool _texturePickerNeedUpdate = false;
Noggit::BoolToggleProperty _show_texture_palette_window = { false };
Noggit::BoolToggleProperty _show_texture_palette_small_window = { false };
void randomizeTexturingRotation();
};
}

View File

@@ -0,0 +1,162 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "VertexPainterTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/ShaderTool.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <random>
namespace Noggit
{
VertexPainterTool::VertexPainterTool(MapView* mapView)
: Tool{ mapView }
{
addHotkey("addColor"_hash, Hotkey{
.onPress = [=] { _shaderTool->addColorToPalette(); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::mccv && !NOGGIT_CUR_ACTION; },
});
}
VertexPainterTool::~VertexPainterTool()
{
delete _shaderTool;
}
char const* VertexPainterTool::name() const
{
return "Vertex Painter";
}
editing_mode VertexPainterTool::editingMode() const
{
return editing_mode::mccv;
}
Ui::FontNoggit::Icons VertexPainterTool::icon() const
{
return Ui::FontNoggit::TOOL_VERTEX_PAINT;
}
void VertexPainterTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_shaderTool = new Noggit::Ui::ShaderTool(mapView(), mapView());
toolPanel->registerTool(name(), _shaderTool);
}
ToolDrawParameters VertexPainterTool::drawParameters() const
{
return
{
.radius = _shaderTool->brushRadius(),
.cursor_type = (_shaderTool->getImageMaskSelector()->isEnabled()) ? CursorType::STAMP : CursorType::CIRCLE,
.cursor_color = _shaderTool->shaderColor(),
};
}
void VertexPainterTool::onSelected()
{
if (_shaderTool->getImageMaskSelector()->isEnabled())
{
_shaderTool->updateMaskImage();
}
}
void VertexPainterTool::randomizeShaderRotation()
{
auto image_mask_selector = _shaderTool->getImageMaskSelector();
if (!image_mask_selector->getRandomizeRotation())
return;
unsigned int ms = static_cast<unsigned>(QDateTime::currentMSecsSinceEpoch());
std::mt19937 gen(ms);
std::uniform_int_distribution<> uid(0, 360);
image_mask_selector->setRotation(uid(gen));
}
void VertexPainterTool::onTick(float deltaTime, TickParameters const& params)
{
if (params.underMap || !params.left_mouse)
{
return;
}
for (auto& selection : mapView()->getWorld()->current_selection())
{
if (selection.index() != eEntry_MapChunk)
{
continue;
}
if ((params.mod_shift_down ^ params.mod_ctrl_down) == 0)
{
continue;
}
auto mv = mapView();
bool add = params.mod_shift_down && !params.mod_ctrl_down;
auto flags = add ? Noggit::ActionModalityControllers::eSHIFT : Noggit::ActionModalityControllers::eCTRL;
auto image_mask_selector = _shaderTool->getImageMaskSelector();
if (NOGGIT_CUR_ACTION
&& image_mask_selector->isEnabled()
&& !image_mask_selector->getBrushMode())
{
break;
}
auto action = NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_VERTEX_COLOR,
flags | Noggit::ActionModalityControllers::eLMB);
action->setPostCallback([this] { randomizeShaderRotation(); });
if (image_mask_selector->isEnabled() && !image_mask_selector->getBrushMode())
action->setBlockCursor(true);
_shaderTool->changeShader(mv->getWorld(), mv->cursorPosition(), deltaTime, add);
}
}
void VertexPainterTool::onMousePress(MousePressParameters const& params)
{
if (params.button != Qt::MouseButton::MiddleButton)
{
return;
}
_shaderTool->pickColor(mapView()->getWorld(), mapView()->cursorPosition());
}
void VertexPainterTool::onMouseMove(MouseMoveParameters const& params)
{
if (params.right_mouse)
{
if (params.mod_space_down && _shaderTool->getImageMaskSelector()->isEnabled())
{
auto action = NOGGIT_ACTION_MGR->beginAction(mapView(), Noggit::ActionFlags::eDO_NOT_WRITE_HISTORY,
Noggit::ActionModalityControllers::eRMB
| Noggit::ActionModalityControllers::eSPACE);
_shaderTool->getImageMaskSelector()->setRotation(-params.relative_movement.dx() / XSENS * 10.f);
action->setBlockCursor(true);
}
}
if (params.left_mouse)
{
if (params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_shaderTool->changeRadius(params.relative_movement.dx() / XSENS);
}
if (params.mod_space_down)
{
_shaderTool->changeSpeed(params.relative_movement.dx() / XSENS);
}
}
}
}

View File

@@ -0,0 +1,47 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
namespace Noggit
{
namespace Ui
{
class ShaderTool;
}
class VertexPainterTool final : public Tool
{
public:
VertexPainterTool(MapView* mapView);
~VertexPainterTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
virtual void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onSelected() override;
void onTick(float deltaTime, TickParameters const& params) override;
void onMousePress(MousePressParameters const& params) override;
void onMouseMove(MouseMoveParameters const& params) override;
private:
Noggit::Ui::ShaderTool* _shaderTool = nullptr;
void randomizeShaderRotation();
};
}

View File

@@ -0,0 +1,165 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "WaterTool.hpp"
#include <noggit/ActionManager.hpp>
#include <noggit/MapView.h>
#include <noggit/Input.hpp>
#include <noggit/ui/Water.h>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
namespace Noggit
{
WaterTool::WaterTool(MapView* mapView)
: Tool{ mapView }
{
addHotkey("toggleAngled"_hash, Hotkey{
.onPress = [=] { _guiWater->toggle_angled_mode(); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::water && !NOGGIT_CUR_ACTION; },
});
addHotkey("toggleLock"_hash, Hotkey{
.onPress = [=] { _guiWater->toggle_lock(); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::water && !NOGGIT_CUR_ACTION; },
});
addHotkey("lockCursor"_hash, Hotkey{
.onPress = [=] { _guiWater->lockPos(mapView->cursorPosition()); },
.condition = [=] { return mapView->get_editing_mode() == editing_mode::water && !NOGGIT_CUR_ACTION; },
});
}
WaterTool::~WaterTool()
{
delete _guiWater;
}
char const* WaterTool::name() const
{
return "Water Editor";
}
editing_mode WaterTool::editingMode() const
{
return editing_mode::water;
}
Ui::FontNoggit::Icons WaterTool::icon() const
{
return Ui::FontNoggit::TOOL_WATER_EDITOR;
}
void WaterTool::setupUi(Ui::Tools::ToolPanel* toolPanel)
{
_guiWater = new Noggit::Ui::water(&_displayedWaterLayer, &_displayAllWaterLayers, mapView());
toolPanel->registerTool(name(), _guiWater);
auto mv = mapView();
QObject::connect(_guiWater, &Noggit::Ui::water::regenerate_water_opacity
, [=](float factor)
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_WATER);
mv->getWorld()->autoGenWaterTrans(mv->getCamera()->position, factor);
NOGGIT_ACTION_MGR->endAction();
}
);
QObject::connect(_guiWater, &Noggit::Ui::water::crop_water
, [=]
{
mv->makeCurrent();
OpenGL::context::scoped_setter const _(::gl, mv->context());
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_WATER);
mv->getWorld()->CropWaterADT(mv->getCamera()->position);
NOGGIT_ACTION_MGR->endAction();
}
);
}
ToolDrawParameters WaterTool::drawParameters() const
{
return
{
.radius = _guiWater->brushRadius(),
.angle = _guiWater->angle(),
.orientation = _guiWater->orientation(),
.ref_pos = _guiWater->ref_pos(),
.angled_mode = _guiWater->angled_mode(),
.use_ref_pos = _guiWater->use_ref_pos(),
.displayed_water_layer = _displayAllWaterLayers.get() ? -1 : static_cast<int>(_displayedWaterLayer.get()),
};
}
void WaterTool::onTick(float deltaTime, TickParameters const& params)
{
if (params.underMap || !params.left_mouse)
{
return;
}
auto mv = mapView();
if (params.displayMode == display_mode::in_3D && !params.underMap)
{
if (params.mod_shift_down)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_WATER,
Noggit::ActionModalityControllers::eSHIFT
| Noggit::ActionModalityControllers::eLMB);
_guiWater->paintLiquid(mv->getWorld(), mv->cursorPosition(), true);
}
else if (params.mod_ctrl_down)
{
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eCHUNKS_WATER,
Noggit::ActionModalityControllers::eCTRL
| Noggit::ActionModalityControllers::eLMB);
_guiWater->paintLiquid(mv->getWorld(), mv->cursorPosition(), false);
}
}
// HINT: this was originally at the very end of MapView::Tick. Do we need a new postTick method?
// While testing I can't find any issues with the tools.
// Using the camera's position from last frame doesn't seem to matter but it's technically incorrect for one frame!
_guiWater->updatePos(mv->getCamera()->position);
}
void WaterTool::onMouseMove(MouseMoveParameters const& params)
{
if (params.left_mouse && params.mod_alt_down && !params.mod_shift_down && !params.mod_ctrl_down)
{
_guiWater->changeRadius(params.relative_movement.dx() / XSENS);
}
}
void WaterTool::onMouseWheel(MouseWheelParameters const& params)
{
auto&& delta_for_range
([&](float range)
{
//! \note / 8.f for degrees, / 40.f for smoothness
return (params.mod_ctrl_down ? 0.01f : 0.1f)
* range
// alt = horizontal delta
* (params.mod_alt_down ? params.event.angleDelta().x() : params.event.angleDelta().y())
/ 320.f
;
}
);
if (params.mod_alt_down)
{
_guiWater->changeOrientation(delta_for_range(360.f));
}
else if (params.mod_shift_down)
{
_guiWater->changeAngle(delta_for_range(89.f));
}
else if (params.mod_space_down)
{
//! \note not actual range
_guiWater->change_height(delta_for_range(40.f));
}
}
}

View File

@@ -0,0 +1,47 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/Tool.hpp>
#include <noggit/unsigned_int_property.hpp>
#include <noggit/BoolToggleProperty.hpp>
namespace Noggit
{
namespace Ui
{
class water;
}
class WaterTool final : public Tool
{
public:
WaterTool(MapView* mapView);
~WaterTool();
[[nodiscard]]
virtual char const* name() const override;
[[nodiscard]]
virtual editing_mode editingMode() const override;
[[nodiscard]]
virtual Ui::FontNoggit::Icons icon() const override;
virtual void setupUi(Ui::Tools::ToolPanel* toolPanel) override;
[[nodiscard]]
ToolDrawParameters drawParameters() const override;
void onTick(float deltaTime, TickParameters const& params) override;
void onMouseMove(MouseMoveParameters const& params) override;
void onMouseWheel(MouseWheelParameters const& params) override;
private:
Noggit::Ui::water* _guiWater = nullptr;
Noggit::unsigned_int_property _displayedWaterLayer = { 0 };
Noggit::BoolToggleProperty _displayAllWaterLayers = { true };
};
}

View File

@@ -2,6 +2,7 @@
#pragma once #pragma once
#include <QWidget>
#include <QtGui/QIcon> #include <QtGui/QIcon>
#include <QtGui/QIconEngine> #include <QtGui/QIconEngine>

View File

@@ -383,6 +383,10 @@ namespace Noggit
} }
); );
using AssetBrowser = Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget;
connect(map_view->getAssetBrowserWidget(), &AssetBrowser::selectionChanged, this, [=](std::string const& path) {
if (isVisible()) setDoodadSlotFromBrowser(path.c_str());
});
} }
void GroundEffectsTool::updateTerrainUniformParams() void GroundEffectsTool::updateTerrainUniformParams()

View File

@@ -14,7 +14,6 @@
#include <QtWidgets/QListWidget> #include <QtWidgets/QListWidget>
class World; class World;
class texturing_tool;
class MapView; class MapView;
class DBCFile::Record; class DBCFile::Record;
@@ -22,6 +21,8 @@ namespace Noggit
{ {
namespace Ui namespace Ui
{ {
class texturing_tool;
struct ground_effect_doodad struct ground_effect_doodad
{ {
unsigned int ID = 0; unsigned int ID = 0;

View File

@@ -1,354 +1,354 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3). // This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/ui/Help.h> #include <noggit/ui/Help.h>
#include <noggit/ui/FontNoggit.hpp> #include <noggit/ui/FontNoggit.hpp>
#include <QtWidgets/QFormLayout> #include <QtWidgets/QFormLayout>
#include <QtWidgets/QHBoxLayout> #include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel> #include <QtWidgets/QLabel>
#include <QtWidgets/QScrollArea> #include <QtWidgets/QScrollArea>
#include <QtWidgets/QTabWidget> #include <QtWidgets/QTabWidget>
#include <initializer_list> #include <initializer_list>
namespace Noggit namespace Noggit
{ {
namespace Ui namespace Ui
{ {
help::help(QWidget* parent) help::help(QWidget* parent)
: widget (parent, Qt::Window) : widget (parent, Qt::Window)
{ {
setWindowTitle ("Help"); setWindowTitle ("Help");
setWindowIcon (QIcon (":/icon")); setWindowIcon (QIcon (":/icon"));
setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint); setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint);
QString header_style = QString header_style =
"QLabel { \n " "QLabel { \n "
" font-weight: bold; \n " " font-weight: bold; \n "
" margin-top: 8px; \n " " margin-top: 8px; \n "
" margin-bottom: 4px; \n " " margin-bottom: 4px; \n "
" margin-left: 150px; \n " " margin-left: 150px; \n "
"} \n "; "} \n ";
auto layout (new QFormLayout (this)); auto layout (new QFormLayout (this));
layout->setSizeConstraint(QLayout::SetFixedSize); layout->setSizeConstraint(QLayout::SetFixedSize);
auto tabs (new QTabWidget (this)); auto tabs (new QTabWidget (this));
auto base_widget (new QWidget (this)); auto base_widget (new QWidget (this));
auto base_layout(new QGridLayout (base_widget)); auto base_layout(new QGridLayout (base_widget));
auto basic_controls_layout (new QFormLayout (this)); auto basic_controls_layout (new QFormLayout (this));
base_layout->addLayout(basic_controls_layout, 0, 0); base_layout->addLayout(basic_controls_layout, 0, 0);
base_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); base_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
auto label = new QLabel("Basic controls:"); auto label = new QLabel("Basic controls:");
label->setStyleSheet(header_style); label->setStyleSheet(header_style);
basic_controls_layout->addRow(label); basic_controls_layout->addRow(label);
generate_hotkey_row({FontNoggit::rmb_drag}, "\aRotate camera", basic_controls_layout); generate_hotkey_row({FontNoggit::rmb_drag}, "\aRotate camera", basic_controls_layout);
generate_hotkey_row({FontNoggit::lmb}, "\aSelect chunk or object", basic_controls_layout); generate_hotkey_row({FontNoggit::lmb}, "\aSelect chunk or object", basic_controls_layout);
generate_hotkey_row({FontNoggit::i}, "\aInvert mouse up and down", basic_controls_layout); generate_hotkey_row({FontNoggit::i}, "\aInvert mouse up and down", basic_controls_layout);
generate_hotkey_row({FontNoggit::q, FontNoggit::e}, "\a,\aMove up and down", basic_controls_layout); generate_hotkey_row({FontNoggit::q, FontNoggit::e}, "\a,\aMove up and down", basic_controls_layout);
generate_hotkey_row({FontNoggit::w, FontNoggit::a , FontNoggit::s , FontNoggit::d}, "\a\a\a\aMove left, right, forward, backwards", basic_controls_layout); generate_hotkey_row({FontNoggit::w, FontNoggit::a , FontNoggit::s , FontNoggit::d}, "\a\a\a\aMove left, right, forward, backwards", basic_controls_layout);
generate_hotkey_row({FontNoggit::home}, "\aMove position to the cursor", basic_controls_layout); generate_hotkey_row({FontNoggit::home}, "\aMove position to the cursor", basic_controls_layout);
generate_hotkey_row({FontNoggit::m}, "\aShow map", basic_controls_layout); generate_hotkey_row({FontNoggit::m}, "\aShow map", basic_controls_layout);
generate_hotkey_row({FontNoggit::u}, "\a2D texture editor", basic_controls_layout); generate_hotkey_row({FontNoggit::u}, "\a2D texture editor", basic_controls_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::f1}, "\a+\aThis help", basic_controls_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::f1}, "\a+\aThis help", basic_controls_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::j}, "\a+\aReload an adt under the camera", basic_controls_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::j}, "\a+\aReload an adt under the camera", basic_controls_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::r}, "\a+\aTurn camera 180 degrees", basic_controls_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::r}, "\a+\aTurn camera 180 degrees", basic_controls_layout);
generate_hotkey_row({FontNoggit::shift}, "\a+ 1, 2, 3 or 4 Set a predefined camera speed", basic_controls_layout); generate_hotkey_row({FontNoggit::shift}, "\a+ 1, 2, 3 or 4 Set a predefined camera speed", basic_controls_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::f4}, "\a+\aExit to main menu", basic_controls_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::f4}, "\a+\aExit to main menu", basic_controls_layout);
generate_hotkey_row({FontNoggit::l}, "\aToggle top view (hint: it's faster to use with graphic tablet stylus buttons)", basic_controls_layout); generate_hotkey_row({FontNoggit::l}, "\aToggle top view (hint: it's faster to use with graphic tablet stylus buttons)", basic_controls_layout);
generate_hotkey_row({}, "", basic_controls_layout); // padding generate_hotkey_row({}, "", basic_controls_layout); // padding
auto toggles_layout(new QFormLayout(this)); auto toggles_layout(new QFormLayout(this));
base_layout->addLayout(toggles_layout, 0, 1); base_layout->addLayout(toggles_layout, 0, 1);
auto label_toggle = new QLabel("Toggles:"); auto label_toggle = new QLabel("Toggles:");
label_toggle->setStyleSheet(header_style); label_toggle->setStyleSheet(header_style);
toggles_layout->addRow(label_toggle); toggles_layout->addRow(label_toggle);
generate_hotkey_row({FontNoggit::f1}, "\aToggle M2s", toggles_layout); generate_hotkey_row({FontNoggit::f1}, "\aToggle M2s", toggles_layout);
generate_hotkey_row({FontNoggit::f2}, "\aToggle WMO doodads set", toggles_layout); generate_hotkey_row({FontNoggit::f2}, "\aToggle WMO doodads set", toggles_layout);
generate_hotkey_row({FontNoggit::f3}, "\aToggle ground", toggles_layout); generate_hotkey_row({FontNoggit::f3}, "\aToggle ground", toggles_layout);
generate_hotkey_row({FontNoggit::f4}, "\aToggle water", toggles_layout); generate_hotkey_row({FontNoggit::f4}, "\aToggle water", toggles_layout);
generate_hotkey_row({FontNoggit::f6}, "\aToggle WMOs", toggles_layout); generate_hotkey_row({FontNoggit::f6}, "\aToggle WMOs", toggles_layout);
generate_hotkey_row({FontNoggit::f7}, "\aToggle chunk (red) and ADT (green) lines", toggles_layout); generate_hotkey_row({FontNoggit::f7}, "\aToggle chunk (red) and ADT (green) lines", toggles_layout);
generate_hotkey_row({FontNoggit::f8}, "\aToggle detailed window", toggles_layout); generate_hotkey_row({FontNoggit::f8}, "\aToggle detailed window", toggles_layout);
generate_hotkey_row({FontNoggit::f9}, "\aToggle map contour", toggles_layout); generate_hotkey_row({FontNoggit::f9}, "\aToggle map contour", toggles_layout);
generate_hotkey_row({FontNoggit::f10}, "\aToggle wireframe", toggles_layout); generate_hotkey_row({FontNoggit::f10}, "\aToggle wireframe", toggles_layout);
generate_hotkey_row({FontNoggit::f11}, "\aToggle model animations", toggles_layout); generate_hotkey_row({FontNoggit::f11}, "\aToggle model animations", toggles_layout);
generate_hotkey_row({FontNoggit::f12}, "\aToggle fog", toggles_layout); generate_hotkey_row({FontNoggit::f12}, "\aToggle fog", toggles_layout);
generate_hotkey_row({}, "1 - 9 Select the editing modes", toggles_layout); generate_hotkey_row({}, "1 - 9 Select the editing modes", toggles_layout);
auto files_layout(new QFormLayout(this)); auto files_layout(new QFormLayout(this));
base_layout->addLayout(files_layout, 1, 0); base_layout->addLayout(files_layout, 1, 0);
auto label_files = new QLabel("Files:"); auto label_files = new QLabel("Files:");
label_files->setStyleSheet(header_style); label_files->setStyleSheet(header_style);
files_layout->addRow(label_files); files_layout->addRow(label_files);
generate_hotkey_row({FontNoggit::f5}, "\aSave bookmark", files_layout); generate_hotkey_row({FontNoggit::f5}, "\aSave bookmark", files_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::s}, "\a+\a Save all changed ADT tiles", files_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::s}, "\a+\a Save all changed ADT tiles", files_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::shift, FontNoggit::s}, "\a+\a+\aSave ADT tile at camera position", files_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::shift, FontNoggit::s}, "\a+\a+\aSave ADT tile at camera position", files_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::shift, FontNoggit::a}, "\a+\a+\aSave all loaded ADT tiles", files_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::shift, FontNoggit::a}, "\a+\a+\aSave all loaded ADT tiles", files_layout);
generate_hotkey_row({FontNoggit::g}, "\aSave port commands to ports.txt", files_layout); generate_hotkey_row({FontNoggit::g}, "\aSave port commands to ports.txt", files_layout);
auto adjust_layout(new QFormLayout(this)); auto adjust_layout(new QFormLayout(this));
base_layout->addLayout(adjust_layout, 1, 1); base_layout->addLayout(adjust_layout, 1, 1);
auto label_adjust = new QLabel("Adjust:"); auto label_adjust = new QLabel("Adjust:");
label_adjust->setStyleSheet(header_style); label_adjust->setStyleSheet(header_style);
adjust_layout->addRow(label_adjust); adjust_layout->addRow(label_adjust);
generate_hotkey_row({FontNoggit::o, FontNoggit::p}, "\aor\aSlower / Faster movement", adjust_layout); generate_hotkey_row({FontNoggit::o, FontNoggit::p}, "\aor\aSlower / Faster movement", adjust_layout);
generate_hotkey_row({FontNoggit::b, FontNoggit::n}, "\aor\aSlower / Faster time", adjust_layout); generate_hotkey_row({FontNoggit::b, FontNoggit::n}, "\aor\aSlower / Faster time", adjust_layout);
generate_hotkey_row({FontNoggit::j}, "\aPause time", adjust_layout); generate_hotkey_row({FontNoggit::j}, "\aPause time", adjust_layout);
// NYI // NYI
// generate_hotkey_row({FontNoggit::shift, FontNoggit::plus, FontNoggit::minus}, "\a+\aor\aFog distance when no model is selected", adjust_layout); // generate_hotkey_row({FontNoggit::shift, FontNoggit::plus, FontNoggit::minus}, "\a+\aor\aFog distance when no model is selected", adjust_layout);
auto flag_widget (new QWidget (this)); auto flag_widget (new QWidget (this));
auto flag_layout (new QFormLayout (flag_widget)); auto flag_layout (new QFormLayout (flag_widget));
auto holes_label = new QLabel("Holes:"); auto holes_label = new QLabel("Holes:");
holes_label->setStyleSheet(header_style); holes_label->setStyleSheet(header_style);
flag_layout->addRow(holes_label); flag_layout->addRow(holes_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb}, "\a+\aClear hole", flag_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb}, "\a+\aClear hole", flag_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb}, "\a+\aAdd hole", flag_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb}, "\a+\aAdd hole", flag_layout);
generate_hotkey_row({FontNoggit::t}, "\aRemove all holes on ADT", flag_layout); generate_hotkey_row({FontNoggit::t}, "\aRemove all holes on ADT", flag_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::t}, "\a+\aRemove all ground on ADT", flag_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::t}, "\a+\aRemove all ground on ADT", flag_layout);
auto impass_flags_label = new QLabel("Impassible Flags:"); auto impass_flags_label = new QLabel("Impassible Flags:");
impass_flags_label->setStyleSheet(header_style); impass_flags_label->setStyleSheet(header_style);
flag_layout->addRow(impass_flags_label); flag_layout->addRow(impass_flags_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aPaint flag", flag_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aPaint flag", flag_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aClear flag", flag_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aClear flag", flag_layout);
auto areaid_label = new QLabel("AreaID Flags:"); auto areaid_label = new QLabel("AreaID Flags:");
areaid_label->setStyleSheet(header_style); areaid_label->setStyleSheet(header_style);
flag_layout->addRow(areaid_label); flag_layout->addRow(areaid_label);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aPick existing AreaID", flag_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aPick existing AreaID", flag_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aPaint selected AreaID", flag_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aPaint selected AreaID", flag_layout);
generate_hotkey_row({ FontNoggit::f }, "\a - Fill current ADT with selected AreaID", flag_layout); generate_hotkey_row({ FontNoggit::f }, "\a - Fill current ADT with selected AreaID", flag_layout);
auto ground_widget (new QWidget (this)); auto ground_widget (new QWidget (this));
auto ground_layout (new QGridLayout (ground_widget)); auto ground_layout (new QGridLayout (ground_widget));
auto ground_column1_layout(new QFormLayout(this)); auto ground_column1_layout(new QFormLayout(this));
ground_layout->addLayout(ground_column1_layout, 0, 0); ground_layout->addLayout(ground_column1_layout, 0, 0);
auto ground_label = new QLabel("Edit ground:"); auto ground_label = new QLabel("Edit ground:");
ground_label->setStyleSheet(header_style); ground_label->setStyleSheet(header_style);
ground_column1_layout->addRow(ground_label); ground_column1_layout->addRow(ground_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::f1 }, "\a+\aToggle ground edit mode", ground_column1_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::f1 }, "\a+\aToggle ground edit mode", ground_column1_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange brush size", ground_column1_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange brush size", ground_column1_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::lmb_drag }, "\a+\aChange speed", ground_column1_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::lmb_drag }, "\a+\aChange speed", ground_column1_layout);
auto raise_label = new QLabel("Raise / Lower tool:"); auto raise_label = new QLabel("Raise / Lower tool:");
raise_label->setStyleSheet(header_style); raise_label->setStyleSheet(header_style);
ground_column1_layout->addRow(raise_label); ground_column1_layout->addRow(raise_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aRaise terrain", ground_column1_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aRaise terrain", ground_column1_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aLower terrain", ground_column1_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aLower terrain", ground_column1_layout);
generate_hotkey_row({FontNoggit::y }, "\aSwitch to next type", ground_column1_layout); generate_hotkey_row({FontNoggit::y }, "\aSwitch to next type", ground_column1_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::rmb_drag }, "\a+\aChange inner radius", ground_column1_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::rmb_drag }, "\a+\aChange inner radius", ground_column1_layout);
auto raise_label_vm = new QLabel("Raise / Lower tool (vertex mode):"); auto raise_label_vm = new QLabel("Raise / Lower tool (vertex mode):");
raise_label_vm->setStyleSheet(header_style); raise_label_vm->setStyleSheet(header_style);
ground_column1_layout->addRow(raise_label_vm); ground_column1_layout->addRow(raise_label_vm);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aSelect vertices", ground_column1_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aSelect vertices", ground_column1_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aDeselect vertices", ground_column1_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aDeselect vertices", ground_column1_layout);
generate_hotkey_row({FontNoggit::c }, "\aClear selection", ground_column1_layout); generate_hotkey_row({FontNoggit::c }, "\aClear selection", ground_column1_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::f }, "\a+\aFlatten vertices", ground_column1_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::f }, "\a+\aFlatten vertices", ground_column1_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::rmb_drag }, "\a+\aOrient vertices toward the mouse cursor", ground_column1_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::rmb_drag }, "\a+\aOrient vertices toward the mouse cursor", ground_column1_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::rmb_drag }, "\a+\aChange vertices height", ground_column1_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::rmb_drag }, "\a+\aChange vertices height", ground_column1_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::mmb }, "\a+\aChange angle", ground_column1_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::mmb }, "\a+\aChange angle", ground_column1_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange orientation", ground_column1_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange orientation", ground_column1_layout);
auto ground_column2_layout(new QFormLayout(this)); auto ground_column2_layout(new QFormLayout(this));
ground_layout->addLayout(ground_column2_layout, 0, 1); ground_layout->addLayout(ground_column2_layout, 0, 1);
auto flatten_label = new QLabel("Flatten / Blur tool:"); auto flatten_label = new QLabel("Flatten / Blur tool:");
flatten_label->setStyleSheet(header_style); flatten_label->setStyleSheet(header_style);
ground_column2_layout->addRow(flatten_label); ground_column2_layout->addRow(flatten_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aFlatten terrain", ground_column2_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aFlatten terrain", ground_column2_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aBlur terrain", ground_column2_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aBlur terrain", ground_column2_layout);
generate_hotkey_row({FontNoggit::t }, "\aToggle flatten angle", ground_column2_layout); generate_hotkey_row({FontNoggit::t }, "\aToggle flatten angle", ground_column2_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::t }, "\a+\aToggle flatten type", ground_column2_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::t }, "\a+\aToggle flatten type", ground_column2_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::mmb }, "\a+\aChange angle", ground_column2_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::mmb }, "\a+\aChange angle", ground_column2_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange orientation", ground_column2_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange orientation", ground_column2_layout);
generate_hotkey_row({FontNoggit::y }, "\aSwitch to next type", ground_column2_layout); generate_hotkey_row({FontNoggit::y }, "\aSwitch to next type", ground_column2_layout);
generate_hotkey_row({FontNoggit::f }, "\aSet relative point", ground_column2_layout); generate_hotkey_row({FontNoggit::f }, "\aSet relative point", ground_column2_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::f }, "\a+\aToggle flatten relative mode", ground_column2_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::f }, "\a+\aToggle flatten relative mode", ground_column2_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::mmb }, "\a+\aChange height", ground_column2_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::mmb }, "\a+\aChange height", ground_column2_layout);
auto texture_widget (new QWidget (this)); auto texture_widget (new QWidget (this));
auto texture_layout (new QFormLayout (texture_widget)); auto texture_layout (new QFormLayout (texture_widget));
auto common_controls_label = new QLabel("Common controls:"); auto common_controls_label = new QLabel("Common controls:");
common_controls_label->setStyleSheet(header_style); common_controls_label->setStyleSheet(header_style);
texture_layout->addRow(common_controls_label); texture_layout->addRow(common_controls_label);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aOpen texture picker for the chunk", texture_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aOpen texture picker for the chunk", texture_layout);
auto paint_label = new QLabel("Paint:"); auto paint_label = new QLabel("Paint:");
paint_label->setStyleSheet(header_style); paint_label->setStyleSheet(header_style);
texture_layout->addRow(paint_label); texture_layout->addRow(paint_label);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::shift, FontNoggit::alt, FontNoggit::lmb }, "\a+\a+\a+\aErase textures", texture_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::shift, FontNoggit::alt, FontNoggit::lmb }, "\a+\a+\a+\aErase textures", texture_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aDraw texture or fills if chunk is empty", texture_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aDraw texture or fills if chunk is empty", texture_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange radius", texture_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange radius", texture_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::rmb_drag }, "\a+\aChange hardness (falloff)", texture_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::rmb_drag }, "\a+\aChange hardness (falloff)", texture_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::lmb_drag }, "\a+\aChange pressure (strength)", texture_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::lmb_drag }, "\a+\aChange pressure (strength)", texture_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::mmb }, "\a+\aChange opacity (gradient)", texture_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::mmb }, "\a+\aChange opacity (gradient)", texture_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::r }, "\a+\aToggle min and max oapcity (gradient)", texture_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::r }, "\a+\aToggle min and max oapcity (gradient)", texture_layout);
generate_hotkey_row({FontNoggit::t }, "\aToggle spray brush", texture_layout); generate_hotkey_row({FontNoggit::t }, "\aToggle spray brush", texture_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange spray radius", texture_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange spray radius", texture_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::mmb }, "\a+\aChange spray pressure", texture_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::mmb }, "\a+\aChange spray pressure", texture_layout);
auto swapper_label = new QLabel("Swap:"); auto swapper_label = new QLabel("Swap:");
swapper_label->setStyleSheet(header_style); swapper_label->setStyleSheet(header_style);
texture_layout->addRow(swapper_label); texture_layout->addRow(swapper_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aSwap texture", texture_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aSwap texture", texture_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange radius", texture_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange radius", texture_layout);
generate_hotkey_row({FontNoggit::t }, "\aToggle brush swapper", texture_layout); generate_hotkey_row({FontNoggit::t }, "\aToggle brush swapper", texture_layout);
auto anim_label = new QLabel("Anim:"); auto anim_label = new QLabel("Anim:");
anim_label->setStyleSheet(header_style); anim_label->setStyleSheet(header_style);
texture_layout->addRow(anim_label); texture_layout->addRow(anim_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aUpdate animation", texture_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aUpdate animation", texture_layout);
generate_hotkey_row({FontNoggit::t }, "\aSwitch between add/remove animation mode", texture_layout); generate_hotkey_row({FontNoggit::t }, "\aSwitch between add/remove animation mode", texture_layout);
auto water_widget (new QWidget (this)); auto water_widget (new QWidget (this));
auto water_layout (new QFormLayout (water_widget)); auto water_layout (new QFormLayout (water_widget));
auto water_label = new QLabel("Water:"); auto water_label = new QLabel("Water:");
water_label->setStyleSheet(header_style); water_label->setStyleSheet(header_style);
water_layout->addRow(water_label); water_layout->addRow(water_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aAdd liquid", water_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aAdd liquid", water_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aRemove liquid", water_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aRemove liquid", water_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange brush size", water_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange brush size", water_layout);
generate_hotkey_row({FontNoggit::t }, "\aToggle angled mode", water_layout); generate_hotkey_row({FontNoggit::t }, "\aToggle angled mode", water_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange orientation", water_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange orientation", water_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::mmb }, "\a+\aChange angle", water_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::mmb }, "\a+\aChange angle", water_layout);
generate_hotkey_row({FontNoggit::f }, "\aSet lock position to cursor position", water_layout); generate_hotkey_row({FontNoggit::f }, "\aSet lock position to cursor position", water_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::f }, "\a+\aToggle lock mode", water_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::f }, "\a+\aToggle lock mode", water_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::mmb }, "\a+\aChange height", water_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::mmb }, "\a+\aChange height", water_layout);
auto object_widget (new QWidget (this)); auto object_widget (new QWidget (this));
auto object_layout (new QFormLayout (object_widget)); auto object_layout (new QFormLayout (object_widget));
auto object_label = new QLabel("Edit objects if a model is selected with left click (in object editor):"); auto object_label = new QLabel("Edit objects if a model is selected with left click (in object editor):");
object_label->setStyleSheet(header_style); object_label->setStyleSheet(header_style);
object_layout->addRow(object_label); object_layout->addRow(object_label);
generate_hotkey_row({FontNoggit::mmb }, "\aMove object", object_layout); generate_hotkey_row({FontNoggit::mmb }, "\aMove object", object_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aScale M2", object_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aScale M2", object_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::ctrl, FontNoggit::alt, FontNoggit::lmb }, "\aor\aor\a+\aRotate object", object_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::ctrl, FontNoggit::alt, FontNoggit::lmb }, "\aor\aor\a+\aRotate object", object_layout);
generate_hotkey_row({FontNoggit::ctrl }, "\a+ 0 - 9 Change doodadset of selected WMO", object_layout); generate_hotkey_row({FontNoggit::ctrl }, "\a+ 0 - 9 Change doodadset of selected WMO", object_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::r }, "\a+\aReset rotation", object_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::r }, "\a+\aReset rotation", object_layout);
generate_hotkey_row({FontNoggit::h }, "\aToggle selected model/wmo visibility", object_layout); generate_hotkey_row({FontNoggit::h }, "\aToggle selected model/wmo visibility", object_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::h }, "\a+\a - Hide/Show hidden model/wmo", object_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::h }, "\a+\a - Hide/Show hidden model/wmo", object_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::h }, "\a+\a - Clear hidden model/wmo list", object_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::h }, "\a+\a - Clear hidden model/wmo list", object_layout);
generate_hotkey_row({FontNoggit::page_down }, "\aSet object to ground level", object_layout); generate_hotkey_row({FontNoggit::page_down }, "\aSet object to ground level", object_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::c }, "\a+\aCopy object to clipboard", object_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::c }, "\a+\aCopy object to clipboard", object_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::v }, "\a+\aPaste object on mouse position", object_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::v }, "\a+\aPaste object on mouse position", object_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::b }, "\a+\aDuplicate selected object to mouse position", object_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::b }, "\a+\aDuplicate selected object to mouse position", object_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::v }, "\a+\aImport last M2 from WMV", object_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::v }, "\a+\aImport last M2 from WMV", object_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::v }, "\a+\aImport last WMO from WMV", object_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::v }, "\a+\aImport last WMO from WMV", object_layout);
generate_hotkey_row({FontNoggit::t }, "\aSwitch between paste modes", object_layout); generate_hotkey_row({FontNoggit::t }, "\aSwitch between paste modes", object_layout);
generate_hotkey_row({FontNoggit::f }, "\aMove selection to cursor position", object_layout); generate_hotkey_row({FontNoggit::f }, "\aMove selection to cursor position", object_layout);
generate_hotkey_row({FontNoggit::minus, FontNoggit::plus }, "\aor\aScale M2", object_layout); generate_hotkey_row({FontNoggit::minus, FontNoggit::plus }, "\aor\aScale M2", object_layout);
generate_hotkey_row({FontNoggit::num }, "\a 7 or 9 Rotate object", object_layout); generate_hotkey_row({FontNoggit::num }, "\a 7 or 9 Rotate object", object_layout);
generate_hotkey_row({FontNoggit::num }, "\a 4 or 8 or 6 or 2 Vertical position", object_layout); generate_hotkey_row({FontNoggit::num }, "\a 4 or 8 or 6 or 2 Vertical position", object_layout);
generate_hotkey_row({FontNoggit::num }, "\a 1 or 3 Move up/down", object_layout); generate_hotkey_row({FontNoggit::num }, "\a 1 or 3 Move up/down", object_layout);
generate_hotkey_row({FontNoggit::shift }, "Holding \a 1 / 3 Double speed", object_layout); generate_hotkey_row({FontNoggit::shift }, "Holding \a 1 / 3 Double speed", object_layout);
generate_hotkey_row({FontNoggit::ctrl }, "Holding \a 1 / 3 Triple speed", object_layout); generate_hotkey_row({FontNoggit::ctrl }, "Holding \a 1 / 3 Triple speed", object_layout);
generate_hotkey_row({FontNoggit::shift, FontNoggit::ctrl }, "Holding \a and \a Half speed", object_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::ctrl }, "Holding \a and \a Half speed", object_layout);
auto shader_widget (new QWidget (this)); auto shader_widget (new QWidget (this));
auto shader_layout (new QFormLayout (shader_widget)); auto shader_layout (new QFormLayout (shader_widget));
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aAdd shader", shader_layout); generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aAdd shader", shader_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aRemove shader", shader_layout); generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aRemove shader", shader_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange brush size", shader_layout); generate_hotkey_row({FontNoggit::alt, FontNoggit::lmb_drag }, "\a+\aChange brush size", shader_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::lmb_drag }, "\a+\aChange speed", shader_layout); generate_hotkey_row({FontNoggit::space, FontNoggit::lmb_drag }, "\a+\aChange speed", shader_layout);
generate_hotkey_row({FontNoggit::mmb }, "\aPick shader color from the ground", shader_layout); generate_hotkey_row({FontNoggit::mmb }, "\aPick shader color from the ground", shader_layout);
generate_hotkey_row({FontNoggit::plus }, "\aAdd current color to palette", shader_layout); generate_hotkey_row({FontNoggit::plus }, "\aAdd current color to palette", shader_layout);
layout->addWidget(tabs); layout->addWidget(tabs);
tabs->addTab(base_widget, "Basic"); tabs->addTab(base_widget, "Basic");
tabs->addTab(ground_widget, "Terrain Editors"); tabs->addTab(ground_widget, "Terrain Editors");
tabs->addTab(texture_widget, "Texture Painter"); tabs->addTab(texture_widget, "Texture Painter");
tabs->addTab(water_widget, "Water Editor"); tabs->addTab(water_widget, "Water Editor");
tabs->addTab(object_widget, "Object Editor"); tabs->addTab(object_widget, "Object Editor");
tabs->addTab(shader_widget, "Vertex Painter"); tabs->addTab(shader_widget, "Vertex Painter");
tabs->addTab(flag_widget, "Impass Flag / Hole Cutter / Area ID"); tabs->addTab(flag_widget, "Impass Flag / Hole Cutter / Area ID");
} }
void help::generate_hotkey_row(std::initializer_list<FontNoggit::Icons>&& hotkeys, const char* description, QFormLayout* layout) void help::generate_hotkey_row(std::initializer_list<FontNoggit::Icons>&& hotkeys, const char* description, QFormLayout* layout)
{ {
auto row_layout = new QHBoxLayout(this); auto row_layout = new QHBoxLayout(this);
const char* from = nullptr; const char* from = nullptr;
auto icon = hotkeys.begin(); auto icon = hotkeys.begin();
while (*description) while (*description)
{ {
if (*description == '\a') if (*description == '\a')
{ {
if (from) if (from)
{ {
auto label = new QLabel(::std::string(from, description - from).c_str()); auto label = new QLabel(::std::string(from, description - from).c_str());
row_layout->addWidget(label); row_layout->addWidget(label);
} }
auto label = new QLabel(this); auto label = new QLabel(this);
QIcon hotkey_icon = FontNoggitIcon(*icon++); QIcon hotkey_icon = FontNoggitIcon(*icon++);
label->setPixmap(hotkey_icon.pixmap(22, 22)); label->setPixmap(hotkey_icon.pixmap(22, 22));
row_layout->addWidget(label); row_layout->addWidget(label);
from = ++description; from = ++description;
} }
else else
{ {
if (!from) if (!from)
{ {
from = description; from = description;
} }
++description; ++description;
} }
} }
if (from && *from) if (from && *from)
{ {
auto label = new QLabel(from); auto label = new QLabel(from);
row_layout->addWidget(label); row_layout->addWidget(label);
} }
row_layout->setAlignment(Qt::AlignLeft); row_layout->setAlignment(Qt::AlignLeft);
layout->addRow(row_layout); layout->addRow(row_layout);
} }
} }
} }

View File

@@ -827,17 +827,17 @@ namespace Noggit
// Buttons // Buttons
connect(cur_adt_btn, &QPushButton::clicked, [=]() { connect(cur_adt_btn, &QPushButton::clicked, [=]() {
_render_settings.export_mode = MinimapGenMode::CURRENT_ADT; _render_settings.export_mode = MinimapGenMode::CURRENT_ADT;
mapView->initMinimapSave(); emit onSave();
}); });
connect(sel_adts_btn, &QPushButton::clicked, [=]() { connect(sel_adts_btn, &QPushButton::clicked, [=]() {
_render_settings.export_mode = MinimapGenMode::SELECTED_ADTS; _render_settings.export_mode = MinimapGenMode::SELECTED_ADTS;
mapView->initMinimapSave(); emit onSave();
}); });
connect(all_adts_btn, &QPushButton::clicked, [=]() { connect(all_adts_btn, &QPushButton::clicked, [=]() {
_render_settings.export_mode = MinimapGenMode::MAP; _render_settings.export_mode = MinimapGenMode::MAP;
mapView->initMinimapSave(); emit onSave();
}); });
} }

View File

@@ -15,53 +15,13 @@
#include <array> #include <array>
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#include <noggit/MinimapRenderSettings.hpp>
#include <noggit/ui/minimap_widget.hpp> #include <noggit/ui/minimap_widget.hpp>
class MapView; class MapView;
class World; class World;
enum MinimapGenMode
{
CURRENT_ADT,
SELECTED_ADTS,
MAP
};
struct MinimapRenderSettings
{
MinimapGenMode export_mode;
std::string file_format = ".blp";
// Render settings
int resolution = 512;
bool draw_m2 = false;
bool draw_wmo = true;
bool draw_water = true;
bool draw_adt_grid = false;
bool draw_elevation = false;
bool draw_shadows = false;
bool use_filters = false;
bool combined_minimap = false;
// Selection
std::array<bool, 4096> selected_tiles = {false};
// Filtering
QListWidget* m2_model_filter_include;
QListWidget* m2_instance_filter_include;
QListWidget* wmo_model_filter_exclude;
QListWidget* wmo_instance_filter_exclude;
// Lighting. Based on default eastern kingdom global light settings (lightparams 12)
glm::vec3 diffuse_color = {1.0, 0.532352924, 0.0};
glm::vec3 ambient_color = {0.407770514, 0.508424163, 0.602650642};
glm::vec4 ocean_color_light = {0.0693173409, 0.294008732, 0.348329663, 0.75};
glm::vec4 ocean_color_dark = {0.000762581825, 0.113907099, 0.161220074, 1.0};
glm::vec4 river_color_light = {0.308351517, 0.363725543, 0.0798838138, 0.5};
glm::vec4 river_color_dark = {0.19945538, 0.320697188, 0.332425594, 1.0};
};
namespace Noggit namespace Noggit
@@ -72,6 +32,7 @@ namespace Noggit
class MinimapCreator : public QWidget class MinimapCreator : public QWidget
{ {
Q_OBJECT
public: public:
MinimapCreator(MapView* mapView, World* world, QWidget* parent = nullptr); MinimapCreator(MapView* mapView, World* world, QWidget* parent = nullptr);
@@ -79,7 +40,8 @@ namespace Noggit
float brushRadius() const { return _radius; } float brushRadius() const { return _radius; }
std::array<bool, 4096>* getSelectedTiles() { return &_render_settings.selected_tiles; }; //std::array<bool, 4096>* getSelectedTiles() { return &_render_settings.selected_tiles; };
std::vector<char>* getSelectedTiles() { return &_render_settings.selected_tiles; };
MinimapRenderSettings* getMinimapRenderSettings() { return &_render_settings; }; MinimapRenderSettings* getMinimapRenderSettings() { return &_render_settings; };
@@ -98,6 +60,9 @@ namespace Noggit
void loadFiltersFromJSON(); void loadFiltersFromJSON();
void saveFiltersToJSON(); void saveFiltersToJSON();
signals:
void onSave();
private: private:
float _radius = 0.01f; float _radius = 0.01f;
MinimapRenderSettings _render_settings; MinimapRenderSettings _render_settings;

View File

@@ -544,7 +544,9 @@ namespace Noggit
connect( object_palette_btn connect( object_palette_btn
, &QPushButton::clicked , &QPushButton::clicked
, [=]() { mapView->getObjectPalette()->setVisible(mapView->getObjectPalette()->isHidden()); } , [=]() {
emit objectPaletteBtnPressed();
}
); );
connect(_doodadSetSelector connect(_doodadSetSelector

View File

@@ -3,6 +3,7 @@
#pragma once #pragma once
#include <noggit/Selection.h> #include <noggit/Selection.h>
#include <noggit/BoolToggleProperty.hpp> #include <noggit/BoolToggleProperty.hpp>
#include <noggit/object_paste_params.hpp>
#include <QLabel> #include <QLabel>
#include <QWidget> #include <QWidget>
@@ -36,21 +37,11 @@ enum ModelPasteMode
namespace Noggit namespace Noggit
{ {
struct object_paste_params
{
float minRotation = -180.f;
float maxRotation = 180.f;
float minTilt = -5.f;
float maxTilt = 5.f;
float minScale = 0.9f;
float maxScale = 1.1f;
bool rotate_on_terrain = true;
};
namespace Ui namespace Ui
{ {
class object_editor : public QWidget class object_editor : public QWidget
{ {
Q_OBJECT
public: public:
object_editor ( MapView* object_editor ( MapView*
, World* , World*
@@ -94,6 +85,9 @@ namespace Noggit
void update_selection_ui(World* world); void update_selection_ui(World* world);
signals:
void objectPaletteBtnPressed();
private: private:
float _radius = 0.01f; float _radius = 0.01f;
float _drag_selection_depth = 100.0f; float _drag_selection_depth = 100.0f;

View File

@@ -273,9 +273,7 @@ namespace Noggit
matrix.rotateRadians(_image_mask_group->getRotation() / 360.0f * 2.0f * M_PI); matrix.rotateRadians(_image_mask_group->getRotation() / 360.0f * 2.0f * M_PI);
_mask_image = pixmap->toImage().transformed(matrix, Qt::SmoothTransformation); _mask_image = pixmap->toImage().transformed(matrix, Qt::SmoothTransformation);
if (_map_view->get_editing_mode() != editing_mode::stamp emit _map_view->trySetBrushTexture(&_mask_image, this);
|| (_map_view->getActiveStampModeItem() && _map_view->getActiveStampModeItem() == this))
_map_view->setBrushTexture(&_mask_image);
} }
QJsonObject ShaderTool::toJSON() QJsonObject ShaderTool::toJSON()

View File

@@ -241,9 +241,7 @@ namespace Noggit
matrix.rotateRadians(_image_mask_group->getRotation() / 360.0f * 2.0f * M_PI); matrix.rotateRadians(_image_mask_group->getRotation() / 360.0f * 2.0f * M_PI);
_mask_image = pixmap->toImage().transformed(matrix, Qt::SmoothTransformation); _mask_image = pixmap->toImage().transformed(matrix, Qt::SmoothTransformation);
if (_map_view->get_editing_mode() != editing_mode::stamp emit _map_view->trySetBrushTexture(&_mask_image, this);
|| (_map_view->getActiveStampModeItem() && _map_view->getActiveStampModeItem() == this))
_map_view->setBrushTexture(&_mask_image);
} }
void TerrainTool::changeTerrain void TerrainTool::changeTerrain

View File

@@ -1,12 +1,13 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3). // This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/Tool.hpp>
#include <noggit/ui/Toolbar.h> #include <noggit/ui/Toolbar.h>
namespace Noggit namespace Noggit
{ {
namespace Ui namespace Ui
{ {
toolbar::toolbar(std::function<void (editing_mode)> set_editing_mode) toolbar::toolbar(std::vector<std::unique_ptr<Noggit::Tool>> const& tools, std::function<void (editing_mode)> set_editing_mode)
: _set_editing_mode (set_editing_mode) : _set_editing_mode (set_editing_mode)
, _tool_group(this) , _tool_group(this)
{ {
@@ -14,20 +15,10 @@ namespace Noggit
setAllowedAreas(Qt::LeftToolBarArea); setAllowedAreas(Qt::LeftToolBarArea);
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
add_tool_icon(editing_mode::ground, tr("Raise / Lower"), FontNoggit::TOOL_RAISE_LOWER); for (auto&& tool : tools)
add_tool_icon(editing_mode::flatten_blur, tr("Flatten / Blur"), FontNoggit::TOOL_FLATTEN_BLUR); {
add_tool_icon(editing_mode::paint, tr("Texture Painter"), FontNoggit::TOOL_TEXTURE_PAINT); add_tool_icon(tool->editingMode(), tr(tool->name()), tool->icon());
add_tool_icon(editing_mode::holes, tr("Hole Cutter"), FontNoggit::TOOL_HOLE_CUTTER); }
add_tool_icon(editing_mode::areaid, tr("Area Designator"), FontNoggit::TOOL_AREA_DESIGNATOR);
add_tool_icon(editing_mode::impass, tr("Impass Designator"), FontNoggit::TOOL_IMPASS_DESIGNATOR);
add_tool_icon(editing_mode::water, tr("Water Editor"), FontNoggit::TOOL_WATER_EDITOR);
add_tool_icon(editing_mode::mccv, tr("Vertex Painter"), FontNoggit::TOOL_VERTEX_PAINT);
add_tool_icon(editing_mode::object, tr("Object Editor"), FontNoggit::TOOL_OBJECT_EDITOR);
add_tool_icon(editing_mode::minimap, tr("Minimap Editor"), FontNoggit::TOOL_MINIMAP_EDITOR);
add_tool_icon(editing_mode::stamp, tr("Stamp Mode"), FontNoggit::TOOL_STAMP);
add_tool_icon(editing_mode::light, tr("Light Editor"), FontNoggit::TOOL_LIGHT);
add_tool_icon(editing_mode::scripting, tr("Scripting"), FontNoggit::INFO);
add_tool_icon(editing_mode::chunk, tr("Chunk Manipulator"), FontNoggit::INFO);
} }
void toolbar::add_tool_icon(editing_mode mode, const QString& name, const FontNoggit::Icons& icon) void toolbar::add_tool_icon(editing_mode mode, const QString& name, const FontNoggit::Icons& icon)

View File

@@ -12,12 +12,14 @@
namespace Noggit namespace Noggit
{ {
class Tool;
namespace Ui namespace Ui
{ {
class toolbar: public QToolBar class toolbar: public QToolBar
{ {
public: public:
toolbar(std::function<void (editing_mode)> set_editing_mode); toolbar(std::vector<std::unique_ptr<Noggit::Tool>> const& tools, std::function<void (editing_mode)> set_editing_mode);
void check_tool(editing_mode); void check_tool(editing_mode);

View File

@@ -1,396 +1,396 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3). // This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/DBC.h> #include <noggit/DBC.h>
#include <noggit/Log.h> #include <noggit/Log.h>
#include <noggit/Misc.h> #include <noggit/Misc.h>
#include <noggit/World.h> #include <noggit/World.h>
#include <noggit/ui/pushbutton.hpp> #include <noggit/ui/pushbutton.hpp>
#include <noggit/ui/Water.h> #include <noggit/ui/Water.h>
#include <noggit/MapHeaders.h> #include <noggit/MapHeaders.h>
#include <util/qt/overload.hpp> #include <util/qt/overload.hpp>
#include <QtWidgets/QButtonGroup> #include <QtWidgets/QButtonGroup>
#include <QtWidgets/QCheckBox> #include <QtWidgets/QCheckBox>
#include <QtWidgets/QDoubleSpinBox> #include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QFormLayout> #include <QtWidgets/QFormLayout>
#include <QtWidgets/QGroupBox> #include <QtWidgets/QGroupBox>
#include <QtWidgets/QComboBox> #include <QtWidgets/QComboBox>
#include <QtWidgets/QLabel> #include <QtWidgets/QLabel>
#include <QtWidgets/QListWidget> #include <QtWidgets/QListWidget>
#include <QtWidgets/QRadioButton> #include <QtWidgets/QRadioButton>
namespace Noggit namespace Noggit
{ {
namespace Ui namespace Ui
{ {
water::water ( unsigned_int_property* current_layer water::water ( unsigned_int_property* current_layer
, BoolToggleProperty* display_all_layers , BoolToggleProperty* display_all_layers
, QWidget* parent , QWidget* parent
) )
: QWidget (parent) : QWidget (parent)
, _liquid_id(5) , _liquid_id(5)
, _liquid_type(liquid_basic_types_water) , _liquid_type(liquid_basic_types_water)
, _radius(10.0f) , _radius(10.0f)
, _angle(10.0f) , _angle(10.0f)
, _orientation(0.0f) , _orientation(0.0f)
, _locked(false) , _locked(false)
, _angled_mode(false) , _angled_mode(false)
, _override_liquid_id(true) , _override_liquid_id(true)
, _override_height(true) , _override_height(true)
, _opacity_mode(auto_opacity) , _opacity_mode(auto_opacity)
, _custom_opacity_factor(RIVER_OPACITY_VALUE) , _custom_opacity_factor(RIVER_OPACITY_VALUE)
, _lock_pos(glm::vec3(0.0f, 0.0f, 0.0f)) , _lock_pos(glm::vec3(0.0f, 0.0f, 0.0f))
, tile(0, 0) , tile(0, 0)
{ {
setMinimumWidth(250); setMinimumWidth(250);
setMaximumWidth(250); setMaximumWidth(250);
auto layout (new QFormLayout (this)); auto layout (new QFormLayout (this));
auto brush_group(new QGroupBox("Brush", this)); auto brush_group(new QGroupBox("Brush", this));
auto brush_layout (new QFormLayout (brush_group)); auto brush_layout (new QFormLayout (brush_group));
_radius_spin = new QDoubleSpinBox (this); _radius_spin = new QDoubleSpinBox (this);
_radius_spin->setRange (0.f, 1000.f); _radius_spin->setRange (0.f, 1000.f);
connect ( _radius_spin, qOverload<double> (&QDoubleSpinBox::valueChanged) connect ( _radius_spin, qOverload<double> (&QDoubleSpinBox::valueChanged)
, [&] (float f) { _radius = f; } , [&] (float f) { _radius = f; }
); );
_radius_spin->setValue(_radius); _radius_spin->setValue(_radius);
brush_layout->addRow ("Radius", _radius_spin); brush_layout->addRow ("Radius", _radius_spin);
waterType = new QComboBox(this); waterType = new QComboBox(this);
for (DBCFile::Iterator i = gLiquidTypeDB.begin(); i != gLiquidTypeDB.end(); ++i) for (DBCFile::Iterator i = gLiquidTypeDB.begin(); i != gLiquidTypeDB.end(); ++i)
{ {
int liquid_id = i->getInt(LiquidTypeDB::ID); int liquid_id = i->getInt(LiquidTypeDB::ID);
// filter WMO liquids // filter WMO liquids
if (liquid_id == LIQUID_WMO_Water || liquid_id == LIQUID_WMO_Ocean || liquid_id == LIQUID_WMO_Water_Interior if (liquid_id == LIQUID_WMO_Water || liquid_id == LIQUID_WMO_Ocean || liquid_id == LIQUID_WMO_Water_Interior
|| liquid_id == LIQUID_WMO_Magma || liquid_id == LIQUID_WMO_Slime) || liquid_id == LIQUID_WMO_Magma || liquid_id == LIQUID_WMO_Slime)
continue; continue;
std::stringstream ss; std::stringstream ss;
ss << liquid_id << "-" << LiquidTypeDB::getLiquidName(liquid_id); ss << liquid_id << "-" << LiquidTypeDB::getLiquidName(liquid_id);
waterType->addItem (QString::fromUtf8(ss.str().c_str()), QVariant (liquid_id)); waterType->addItem (QString::fromUtf8(ss.str().c_str()), QVariant (liquid_id));
} }
connect (waterType, qOverload<int> (&QComboBox::currentIndexChanged) connect (waterType, qOverload<int> (&QComboBox::currentIndexChanged)
, [&] , [&]
{ {
changeWaterType(waterType->currentData().toInt()); changeWaterType(waterType->currentData().toInt());
// change auto opacity based on liquid type // change auto opacity based on liquid type
if (_opacity_mode == custom_opacity || _opacity_mode == auto_opacity) if (_opacity_mode == custom_opacity || _opacity_mode == auto_opacity)
return; return;
// other liquid types shouldn't use opacity(depth) // other liquid types shouldn't use opacity(depth)
int liquid_type = LiquidTypeDB::getLiquidType(_liquid_id); int liquid_type = LiquidTypeDB::getLiquidType(_liquid_id);
if (liquid_type == liquid_basic_types_ocean) // ocean if (liquid_type == liquid_basic_types_ocean) // ocean
{ {
ocean_button->setChecked(true); ocean_button->setChecked(true);
_opacity_mode = ocean_opacity; _opacity_mode = ocean_opacity;
} }
else // water. opacity doesn't matter for lava/slim else // water. opacity doesn't matter for lava/slim
{ {
river_button->setChecked(true); river_button->setChecked(true);
_opacity_mode = river_opacity; _opacity_mode = river_opacity;
} }
} }
); );
brush_layout->addRow (waterType); brush_layout->addRow (waterType);
layout->addRow (brush_group); layout->addRow (brush_group);
auto angle_group (new QGroupBox ("Angled mode", this)); auto angle_group (new QGroupBox ("Angled mode", this));
angle_group->setCheckable (true); angle_group->setCheckable (true);
angle_group->setChecked (_angled_mode.get()); angle_group->setChecked (_angled_mode.get());
connect ( &_angled_mode, &BoolToggleProperty::changed connect ( &_angled_mode, &BoolToggleProperty::changed
, angle_group, &QGroupBox::setChecked , angle_group, &QGroupBox::setChecked
); );
connect ( angle_group, &QGroupBox::toggled connect ( angle_group, &QGroupBox::toggled
, &_angled_mode, &BoolToggleProperty::set , &_angled_mode, &BoolToggleProperty::set
); );
auto angle_layout (new QFormLayout (angle_group)); auto angle_layout (new QFormLayout (angle_group));
_angle_spin = new QDoubleSpinBox (this); _angle_spin = new QDoubleSpinBox (this);
_angle_spin->setRange (0.00001f, 89.f); _angle_spin->setRange (0.00001f, 89.f);
_angle_spin->setSingleStep (2.0f); _angle_spin->setSingleStep (2.0f);
connect ( _angle_spin, qOverload<double> (&QDoubleSpinBox::valueChanged) connect ( _angle_spin, qOverload<double> (&QDoubleSpinBox::valueChanged)
, [&] (float f) { _angle = f; } , [&] (float f) { _angle = f; }
); );
_angle_spin->setValue(_angle); _angle_spin->setValue(_angle);
angle_layout->addRow ("Angle", _angle_spin); angle_layout->addRow ("Angle", _angle_spin);
_orientation_spin = new QDoubleSpinBox (this); _orientation_spin = new QDoubleSpinBox (this);
_orientation_spin->setRange (0.f, 360.f); _orientation_spin->setRange (0.f, 360.f);
_orientation_spin->setWrapping (true); _orientation_spin->setWrapping (true);
_orientation_spin->setValue(_orientation); _orientation_spin->setValue(_orientation);
_orientation_spin->setSingleStep (5.0f); _orientation_spin->setSingleStep (5.0f);
connect ( _orientation_spin, qOverload<double> (&QDoubleSpinBox::valueChanged) connect ( _orientation_spin, qOverload<double> (&QDoubleSpinBox::valueChanged)
, [&] (float f) { _orientation = f; } , [&] (float f) { _orientation = f; }
); );
angle_layout->addRow ("Orienation", _orientation_spin); angle_layout->addRow ("Orienation", _orientation_spin);
layout->addRow (angle_group); layout->addRow (angle_group);
auto lock_group (new QGroupBox ("Lock", this)); auto lock_group (new QGroupBox ("Lock", this));
lock_group->setCheckable (true); lock_group->setCheckable (true);
lock_group->setChecked (_locked.get()); lock_group->setChecked (_locked.get());
auto lock_layout (new QFormLayout (lock_group)); auto lock_layout (new QFormLayout (lock_group));
lock_layout->addRow("X:", _x_spin = new QDoubleSpinBox (this)); lock_layout->addRow("X:", _x_spin = new QDoubleSpinBox (this));
lock_layout->addRow("Z:", _z_spin = new QDoubleSpinBox (this)); lock_layout->addRow("Z:", _z_spin = new QDoubleSpinBox (this));
lock_layout->addRow("H:", _h_spin = new QDoubleSpinBox (this)); lock_layout->addRow("H:", _h_spin = new QDoubleSpinBox (this));
_x_spin->setRange (std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max()); _x_spin->setRange (std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
_z_spin->setRange (std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max()); _z_spin->setRange (std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
_h_spin->setRange (std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max()); _h_spin->setRange (std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
_x_spin->setDecimals (2); _x_spin->setDecimals (2);
_z_spin->setDecimals (2); _z_spin->setDecimals (2);
_h_spin->setDecimals (2); _h_spin->setDecimals (2);
connect ( _x_spin, qOverload<double> (&QDoubleSpinBox::valueChanged) connect ( _x_spin, qOverload<double> (&QDoubleSpinBox::valueChanged)
, [&] (float f) { _lock_pos.x = f; } , [&] (float f) { _lock_pos.x = f; }
); );
connect ( _z_spin, qOverload<double> (&QDoubleSpinBox::valueChanged) connect ( _z_spin, qOverload<double> (&QDoubleSpinBox::valueChanged)
, [&] (float f) { _lock_pos.z = f; } , [&] (float f) { _lock_pos.z = f; }
); );
connect ( _h_spin, qOverload<double> (&QDoubleSpinBox::valueChanged) connect ( _h_spin, qOverload<double> (&QDoubleSpinBox::valueChanged)
, [&] (float f) { _lock_pos.y = f; } , [&] (float f) { _lock_pos.y = f; }
); );
connect ( &_locked, &BoolToggleProperty::changed connect ( &_locked, &BoolToggleProperty::changed
, lock_group, &QGroupBox::setChecked , lock_group, &QGroupBox::setChecked
); );
connect ( lock_group, &QGroupBox::toggled connect ( lock_group, &QGroupBox::toggled
, &_locked, &BoolToggleProperty::set , &_locked, &BoolToggleProperty::set
); );
layout->addRow(lock_group); layout->addRow(lock_group);
auto override_group (new QGroupBox ("Override", this)); auto override_group (new QGroupBox ("Override", this));
auto override_layout (new QFormLayout (override_group)); auto override_layout (new QFormLayout (override_group));
override_layout->addWidget (new CheckBox ("Liquid ID", &_override_liquid_id, this)); override_layout->addWidget (new CheckBox ("Liquid ID", &_override_liquid_id, this));
override_layout->addWidget (new CheckBox ("Height", &_override_height, this)); override_layout->addWidget (new CheckBox ("Height", &_override_height, this));
layout->addRow(override_group); layout->addRow(override_group);
auto opacity_group (new QGroupBox ("Auto opacity", this)); auto opacity_group (new QGroupBox ("Auto opacity", this));
auto opacity_layout (new QFormLayout (opacity_group)); auto opacity_layout (new QFormLayout (opacity_group));
auto auto_button(new QRadioButton("Auto", this)); auto auto_button(new QRadioButton("Auto", this));
auto_button->setToolTip("Automatically uses river or ocean opacity based on liquid type."); auto_button->setToolTip("Automatically uses river or ocean opacity based on liquid type.");
river_button = new QRadioButton ("River", this); river_button = new QRadioButton ("River", this);
river_button->setToolTip(std::to_string(RIVER_OPACITY_VALUE).c_str()); river_button->setToolTip(std::to_string(RIVER_OPACITY_VALUE).c_str());
ocean_button = new QRadioButton ("Ocean", this); ocean_button = new QRadioButton ("Ocean", this);
ocean_button->setToolTip(std::to_string(OCEAN_OPACITY_VALUE).c_str()); ocean_button->setToolTip(std::to_string(OCEAN_OPACITY_VALUE).c_str());
custom_button = new QRadioButton ("Custom factor:", this); custom_button = new QRadioButton ("Custom factor:", this);
transparency_toggle = new QButtonGroup (this); transparency_toggle = new QButtonGroup (this);
transparency_toggle->addButton(auto_button, auto_opacity); transparency_toggle->addButton(auto_button, auto_opacity);
transparency_toggle->addButton (river_button, river_opacity); transparency_toggle->addButton (river_button, river_opacity);
transparency_toggle->addButton (ocean_button, ocean_opacity); transparency_toggle->addButton (ocean_button, ocean_opacity);
transparency_toggle->addButton (custom_button, custom_opacity); transparency_toggle->addButton (custom_button, custom_opacity);
connect ( transparency_toggle, qOverload<int> (&QButtonGroup::idClicked) connect ( transparency_toggle, qOverload<int> (&QButtonGroup::idClicked)
, [&] (int id) { _opacity_mode = id; } , [&] (int id) { _opacity_mode = id; }
); );
opacity_layout->addRow(auto_button); opacity_layout->addRow(auto_button);
opacity_layout->addRow (river_button); opacity_layout->addRow (river_button);
opacity_layout->addRow (ocean_button); opacity_layout->addRow (ocean_button);
opacity_layout->addRow (custom_button); opacity_layout->addRow (custom_button);
transparency_toggle->button (_opacity_mode)->setChecked (true); transparency_toggle->button (_opacity_mode)->setChecked (true);
QDoubleSpinBox *opacity_spin = new QDoubleSpinBox (this); QDoubleSpinBox *opacity_spin = new QDoubleSpinBox (this);
opacity_spin->setRange (0.f, 1.f); opacity_spin->setRange (0.f, 1.f);
opacity_spin->setDecimals (4); opacity_spin->setDecimals (4);
opacity_spin->setSingleStep (0.02f); opacity_spin->setSingleStep (0.02f);
opacity_spin->setValue(_custom_opacity_factor); opacity_spin->setValue(_custom_opacity_factor);
connect ( opacity_spin, qOverload<double> (&QDoubleSpinBox::valueChanged) connect ( opacity_spin, qOverload<double> (&QDoubleSpinBox::valueChanged)
, [&] (float f) { _custom_opacity_factor = f; } , [&] (float f) { _custom_opacity_factor = f; }
); );
opacity_layout->addRow (opacity_spin); opacity_layout->addRow (opacity_spin);
layout->addRow (opacity_group); layout->addRow (opacity_group);
layout->addRow ( new pushbutton layout->addRow ( new pushbutton
( "Regen ADT opacity" ( "Regen ADT opacity"
, [this] , [this]
{ {
emit regenerate_water_opacity emit regenerate_water_opacity
(get_opacity_factor()); (get_opacity_factor());
} }
) )
); );
layout->addRow ( new pushbutton layout->addRow ( new pushbutton
( "Crop water" ( "Crop water"
, [this] , [this]
{ {
emit crop_water(); emit crop_water();
} }
) )
); );
auto layer_group (new QGroupBox ("Layers", this)); auto layer_group (new QGroupBox ("Layers", this));
auto layer_layout (new QFormLayout (layer_group)); auto layer_layout (new QFormLayout (layer_group));
layer_layout->addRow (new CheckBox("Show all layers", display_all_layers)); layer_layout->addRow (new CheckBox("Show all layers", display_all_layers));
layer_layout->addRow (new QLabel("Current layer:", this)); layer_layout->addRow (new QLabel("Current layer:", this));
waterLayer = new QSpinBox (this); waterLayer = new QSpinBox (this);
waterLayer->setValue (current_layer->get()); waterLayer->setValue (current_layer->get());
waterLayer->setRange (0, 100); waterLayer->setRange (0, 100);
layer_layout->addRow (waterLayer); layer_layout->addRow (waterLayer);
layout->addRow (layer_group); layout->addRow (layer_group);
connect ( waterLayer, qOverload<int> (&QSpinBox::valueChanged) connect ( waterLayer, qOverload<int> (&QSpinBox::valueChanged)
, current_layer, &unsigned_int_property::set , current_layer, &unsigned_int_property::set
); );
connect ( current_layer, &unsigned_int_property::changed connect ( current_layer, &unsigned_int_property::changed
, waterLayer, &QSpinBox::setValue , waterLayer, &QSpinBox::setValue
); );
updateData(); updateData();
} }
void water::updatePos(TileIndex const& newTile) void water::updatePos(TileIndex const& newTile)
{ {
if (newTile == tile) return; if (newTile == tile) return;
tile = newTile; tile = newTile;
updateData(); updateData();
} }
void water::updateData() void water::updateData()
{ {
std::stringstream mt; std::stringstream mt;
mt << _liquid_id << " - " << LiquidTypeDB::getLiquidName(_liquid_id); mt << _liquid_id << " - " << LiquidTypeDB::getLiquidName(_liquid_id);
waterType->setCurrentText (QString::fromStdString (mt.str())); waterType->setCurrentText (QString::fromStdString (mt.str()));
_liquid_type = static_cast<liquid_basic_types>(LiquidTypeDB::getLiquidType(_liquid_id)); _liquid_type = static_cast<liquid_basic_types>(LiquidTypeDB::getLiquidType(_liquid_id));
} }
void water::changeWaterType(int waterint) void water::changeWaterType(int waterint)
{ {
_liquid_id = waterint; _liquid_id = waterint;
updateData(); updateData();
} }
void water::changeRadius(float change) void water::changeRadius(float change)
{ {
_radius_spin->setValue(_radius + change); _radius_spin->setValue(_radius + change);
} }
void water::setRadius(float radius) void water::setRadius(float radius)
{ {
_radius_spin->setValue(radius); _radius_spin->setValue(radius);
} }
void water::changeOrientation(float change) void water::changeOrientation(float change)
{ {
_orientation += change; _orientation += change;
while (_orientation >= 360.0f) while (_orientation >= 360.0f)
{ {
_orientation -= 360.0f; _orientation -= 360.0f;
} }
while (_orientation < 0.0f) while (_orientation < 0.0f)
{ {
_orientation += 360.0f; _orientation += 360.0f;
} }
_orientation_spin->setValue(_orientation); _orientation_spin->setValue(_orientation);
} }
void water::changeAngle(float change) void water::changeAngle(float change)
{ {
_angle_spin->setValue(_angle + change); _angle_spin->setValue(_angle + change);
} }
void water::change_height(float change) void water::change_height(float change)
{ {
_h_spin->setValue(_lock_pos.y + change); _h_spin->setValue(_lock_pos.y + change);
} }
void water::paintLiquid (World* world, glm::vec3 const& pos, bool add) void water::paintLiquid (World* world, glm::vec3 const& pos, bool add)
{ {
world->paintLiquid ( pos world->paintLiquid ( pos
, _radius , _radius
, _liquid_id , _liquid_id
, add , add
, math::degrees (_angled_mode.get() ? _angle : 0.0f) , math::degrees (_angled_mode.get() ? _angle : 0.0f)
, math::degrees (_angled_mode.get() ? _orientation : 0.0f) , math::degrees (_angled_mode.get() ? _orientation : 0.0f)
, _locked.get() , _locked.get()
, _lock_pos , _lock_pos
, _override_height.get() , _override_height.get()
, _override_liquid_id.get() , _override_liquid_id.get()
, get_opacity_factor() , get_opacity_factor()
); );
} }
void water::lockPos(glm::vec3 const& cursor_pos) void water::lockPos(glm::vec3 const& cursor_pos)
{ {
QSignalBlocker const blocker_x(_x_spin); QSignalBlocker const blocker_x(_x_spin);
QSignalBlocker const blocker_z(_z_spin); QSignalBlocker const blocker_z(_z_spin);
QSignalBlocker const blocker_h(_h_spin); QSignalBlocker const blocker_h(_h_spin);
_lock_pos = cursor_pos; _lock_pos = cursor_pos;
_x_spin->setValue(_lock_pos.x); _x_spin->setValue(_lock_pos.x);
_z_spin->setValue(_lock_pos.z); _z_spin->setValue(_lock_pos.z);
_h_spin->setValue(_lock_pos.y); _h_spin->setValue(_lock_pos.y);
if (!_locked.get()) if (!_locked.get())
{ {
toggle_lock(); toggle_lock();
} }
} }
void water::toggle_lock() void water::toggle_lock()
{ {
_locked.toggle(); _locked.toggle();
} }
void water::toggle_angled_mode() void water::toggle_angled_mode()
{ {
_angled_mode.toggle(); _angled_mode.toggle();
} }
float water::get_opacity_factor() const float water::get_opacity_factor() const
{ {
switch (_opacity_mode) switch (_opacity_mode)
{ {
default: // values found by experimenting default: // values found by experimenting
case river_opacity: return RIVER_OPACITY_VALUE; case river_opacity: return RIVER_OPACITY_VALUE;
case ocean_opacity: return OCEAN_OPACITY_VALUE; case ocean_opacity: return OCEAN_OPACITY_VALUE;
case custom_opacity: return _custom_opacity_factor; case custom_opacity: return _custom_opacity_factor;
case auto_opacity: case auto_opacity:
{ {
switch (_liquid_type) switch (_liquid_type)
{ {
case 0: return RIVER_OPACITY_VALUE; case 0: return RIVER_OPACITY_VALUE;
case 1: return OCEAN_OPACITY_VALUE; case 1: return OCEAN_OPACITY_VALUE;
default: return RIVER_OPACITY_VALUE; // lava and slime, opacity isn't used default: return RIVER_OPACITY_VALUE; // lava and slime, opacity isn't used
} }
} }
break; break;
} }
} }
QSize water::sizeHint() const QSize water::sizeHint() const
{ {
return QSize(250, height()); return QSize(250, height());
} }
} }
} }

View File

@@ -76,7 +76,7 @@ namespace Noggit
if (!_selected_tiles) if (!_selected_tiles)
return; return;
_selected_tiles->fill(false); std::memset(_selected_tiles->data(), false, _selected_tiles->size());
} }
); );
} }

View File

@@ -41,9 +41,9 @@ namespace Noggit
{ _draw_boundaries = draw_boundaries_; update(); return _draw_boundaries; } { _draw_boundaries = draw_boundaries_; update(); return _draw_boundaries; }
inline const bool& draw_boundaries() const { return _draw_boundaries; } inline const bool& draw_boundaries() const { return _draw_boundaries; }
inline const std::array<bool, 4096>* use_selection (std::array<bool, 4096>* selection_) inline const std::vector<char>* use_selection (std::vector<char>* selection_)
{ _use_selection = selection_; _selected_tiles = selection_; update(); return _selected_tiles; } { _use_selection = selection_; _selected_tiles = selection_; update(); return _selected_tiles; }
inline const std::array<bool, 4096>* selection() const { return _selected_tiles; } inline const std::vector<char>* selection() const { return _selected_tiles; }
inline void camera (Noggit::Camera* camera) { _camera = camera; } inline void camera (Noggit::Camera* camera) { _camera = camera; }
void set_resizeable(bool state) { _resizeable = state; }; void set_resizeable(bool state) { _resizeable = state; };
@@ -66,7 +66,7 @@ namespace Noggit
private: private:
World* _world; World* _world;
Noggit::Camera* _camera; Noggit::Camera* _camera;
std::array<bool, 4096>* _selected_tiles; std::vector<char>* _selected_tiles;
bool _draw_skies; bool _draw_skies;
bool _draw_camera; bool _draw_camera;

View File

@@ -102,7 +102,7 @@ namespace Noggit
connect(_object_list, &QListWidget::itemClicked, this, [=](QListWidgetItem* item) connect(_object_list, &QListWidget::itemClicked, this, [=](QListWidgetItem* item)
{ {
_map_view->getObjectEditor()->copy(item->toolTip().toStdString()); emit selected(item->toolTip().toStdString());
} }
); );

View File

@@ -347,7 +347,7 @@ namespace Noggit
connect ( quick_palette_btn, &QPushButton::clicked connect ( quick_palette_btn, &QPushButton::clicked
, [=] () , [=] ()
{ {
_map_view->getTexturePalette()->setVisible(_map_view->getTexturePalette()->isHidden()); emit texturePaletteToggled();
} }
); );
@@ -402,9 +402,7 @@ namespace Noggit
matrix.rotateRadians(_image_mask_group->getRotation() * M_PI / 180.f); matrix.rotateRadians(_image_mask_group->getRotation() * M_PI / 180.f);
_mask_image = pixmap->toImage().transformed(matrix, Qt::SmoothTransformation); _mask_image = pixmap->toImage().transformed(matrix, Qt::SmoothTransformation);
if (_map_view->get_editing_mode() != editing_mode::stamp emit _map_view->trySetBrushTexture(&_mask_image, this);
|| (_map_view->getActiveStampModeItem() && _map_view->getActiveStampModeItem() == this))
_map_view->setBrushTexture(&_mask_image);
} }
void texturing_tool::update_brush_hardness() void texturing_tool::update_brush_hardness()

View File

@@ -21,6 +21,7 @@
#include <QtWidgets/QWidget> #include <QtWidgets/QWidget>
#include <QtWidgets/QListWidget> #include <QtWidgets/QListWidget>
#include <QJsonObject> #include <QJsonObject>
#include <QPainter>
class World; class World;
class MapView; class MapView;
@@ -127,6 +128,7 @@ namespace Noggit
class texturing_tool : public QWidget class texturing_tool : public QWidget
{ {
Q_OBJECT
public: public:
texturing_tool ( const glm::vec3* camera_pos texturing_tool ( const glm::vec3* camera_pos
, MapView* map_view , MapView* map_view
@@ -197,6 +199,9 @@ namespace Noggit
QJsonObject toJSON(); QJsonObject toJSON();
void fromJSON(QJsonObject const& json); void fromJSON(QJsonObject const& json);
signals:
void texturePaletteToggled();
private: private:
void change_tex_flag(World* world, glm::vec3 const& pos, bool add, scoped_blp_texture_reference texture); void change_tex_flag(World* world, glm::vec3 const& pos, bool add, scoped_blp_texture_reference texture);

View File

@@ -135,14 +135,7 @@ AssetBrowserWidget::AssetBrowserWidget(MapView* map_view, QWidget *parent)
ui->viewport->setModel(str_path); ui->viewport->setModel(str_path);
_selected_path = str_path; _selected_path = str_path;
if (_browse_mode == asset_browse_mode::detail_doodads && _map_view->get_editing_mode() == editing_mode::paint) emit selectionChanged(str_path);
{
_map_view->getGroundEffectsTool()->setDoodadSlotFromBrowser(str_path.c_str());
}
else
{
_map_view->getObjectEditor()->copy(str_path);
}
} }
} }

View File

@@ -91,6 +91,7 @@ namespace Noggit
asset_browse_mode _browse_mode = asset_browse_mode::world; asset_browse_mode _browse_mode = asset_browse_mode::world;
signals: signals:
void gl_data_unloaded(); void gl_data_unloaded();
void selectionChanged(std::string const& path);
private: private:
::Ui::AssetBrowser* ui; ::Ui::AssetBrowser* ui;

View File

@@ -1,5 +1,7 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3). // This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/MapView.h>
#include <noggit/BoolToggleProperty.hpp>
#include <noggit/ui/tools/ViewToolbar/Ui/ViewToolbar.hpp> #include <noggit/ui/tools/ViewToolbar/Ui/ViewToolbar.hpp>
#include <noggit/ui/tools/ActionHistoryNavigator/ActionHistoryNavigator.hpp> #include <noggit/ui/tools/ActionHistoryNavigator/ActionHistoryNavigator.hpp>
#include <noggit/ui/FontAwesome.hpp> #include <noggit/ui/FontAwesome.hpp>
@@ -213,15 +215,15 @@ ViewToolbar::ViewToolbar(MapView* mapView, editing_mode mode)
IconAction* _icon = new IconAction(FontNoggitIcon{ FontNoggit::TOOL_FLATTEN_BLUR }); IconAction* _icon = new IconAction(FontNoggitIcon{ FontNoggit::TOOL_FLATTEN_BLUR });
CheckBoxAction* _raise = new CheckBoxAction(tr("Raise"), true); CheckBoxAction* _raise = new CheckBoxAction(tr("Raise"), true);
connect(_raise->checkbox(), &QCheckBox::stateChanged, [mapView](int state) connect(_raise->checkbox(), &QCheckBox::stateChanged, [this, mapView](int state)
{ {
mapView->getFlattenTool()->_flatten_mode.raise = state; emit updateStateRaise(state != 0);
}); });
CheckBoxAction* _lower = new CheckBoxAction(tr("Lower"), true); CheckBoxAction* _lower = new CheckBoxAction(tr("Lower"), true);
connect(_lower->checkbox(), &QCheckBox::stateChanged, [mapView](int state) connect(_lower->checkbox(), &QCheckBox::stateChanged, [this, mapView](int state)
{ {
mapView->getFlattenTool()->_flatten_mode.lower = state; emit updateStateLower(state != 0);
}); });
@@ -434,10 +436,8 @@ bool ViewToolbar::showUnpaintableChunk()
return static_cast<SubToolBarAction*>(_texture_secondary_tool[0])->GET<CheckBoxAction*>(unpaintable_chunk_index)->checkbox()->isChecked() && current_mode == editing_mode::paint; return static_cast<SubToolBarAction*>(_texture_secondary_tool[0])->GET<CheckBoxAction*>(unpaintable_chunk_index)->checkbox()->isChecked() && current_mode == editing_mode::paint;
} }
void ViewToolbar::nextFlattenMode(MapView* mapView) void ViewToolbar::nextFlattenMode()
{ {
mapView->getFlattenTool()->_flatten_mode.next();
CheckBoxAction* _raise_option = static_cast<SubToolBarAction*>(_flatten_secondary_tool[0])->GET<CheckBoxAction*>(raise_index); CheckBoxAction* _raise_option = static_cast<SubToolBarAction*>(_flatten_secondary_tool[0])->GET<CheckBoxAction*>(raise_index);
CheckBoxAction* _lower_option = static_cast<SubToolBarAction*>(_flatten_secondary_tool[0])->GET<CheckBoxAction*>(lower_index); CheckBoxAction* _lower_option = static_cast<SubToolBarAction*>(_flatten_secondary_tool[0])->GET<CheckBoxAction*>(lower_index);

View File

@@ -8,17 +8,20 @@
#include <QtWidgets/QActionGroup> #include <QtWidgets/QActionGroup>
#include <QtWidgets/QToolBar> #include <QtWidgets/QToolBar>
#include <noggit/MapView.h>
#include <noggit/ui/FontNoggit.hpp> #include <noggit/ui/FontNoggit.hpp>
#include <noggit/BoolToggleProperty.hpp>
#include <noggit/ui/FlattenTool.hpp> class MapView;
namespace Noggit namespace Noggit
{ {
struct BoolToggleProperty;
namespace Ui::Tools::ViewToolbar::Ui namespace Ui::Tools::ViewToolbar::Ui
{ {
class ViewToolbar: public QToolBar class ViewToolbar: public QToolBar
{ {
Q_OBJECT
public: public:
ViewToolbar(MapView* mapView); ViewToolbar(MapView* mapView);
ViewToolbar(MapView* mapView, ViewToolbar* tb); ViewToolbar(MapView* mapView, ViewToolbar* tb);
@@ -34,7 +37,7 @@ namespace Noggit
/*secondary left tool*/ /*secondary left tool*/
QVector<QWidgetAction*> _flatten_secondary_tool; QVector<QWidgetAction*> _flatten_secondary_tool;
void nextFlattenMode(MapView* mapView); void nextFlattenMode();
QVector<QWidgetAction*> _texture_secondary_tool; QVector<QWidgetAction*> _texture_secondary_tool;
bool showUnpaintableChunk(); bool showUnpaintableChunk();
@@ -46,6 +49,10 @@ namespace Noggit
bool drawWireframeSphereLight(); bool drawWireframeSphereLight();
float getAlphaSphereLight(); float getAlphaSphereLight();
signals:
void updateStateRaise(bool newState);
void updateStateLower(bool newState);
private: private:
QActionGroup _tool_group; QActionGroup _tool_group;
editing_mode current_mode; editing_mode current_mode;

View File

@@ -289,7 +289,7 @@ void ViewportGizmo::handleTransformGizmo(MapView* map_view
if (map_view) if (map_view)
{ {
map_view->updateRotationEditor(); emit map_view->rotationChanged();
} }
if (_world) if (_world)

View File

@@ -1,4 +1,5 @@
#include "LightViewWidget.h" #include "LightViewWidget.h"
#include <QPainter>
LightViewWidget::LightViewWidget(QWidget* parent) LightViewWidget::LightViewWidget(QWidget* parent)
: QWidget(parent) : QWidget(parent)

View File

@@ -37,6 +37,7 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QDir> #include <QDir>
#include <QIcon> #include <QIcon>
#include <QScrollArea>
#include <sstream> #include <sstream>
#include <chrono> #include <chrono>