Tools rewrite

This commit is contained in:
DennisWG
2024-09-06 20:16:57 +00:00
committed by T1ti
parent ab4e581c7c
commit 53b50aaff3
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(lodepng REQUIRED)
set(FASTNOISE2_NOISETOOL OFF CACHE BOOL "")
FIND_PACKAGE(FastNoise2 REQUIRED)
FetchContent_Declare(
FastNoise2
GIT_REPOSITORY https://github.com/Auburn/FastNoise2.git
GIT_TAG v0.10.0-alpha
)
FetchContent_MakeAvailable(FastNoise2)
FIND_PACKAGE(Sol2 REQUIRED)
FIND_PACKAGE(Qt5 COMPONENTS Widgets OpenGLExtensions Gui Network Xml Multimedia REQUIRED)

View File

@@ -544,7 +544,7 @@ void Noggit::Action::finish()
}
if (_post)
(_map_view->*_post)();
_post();
}
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 <ClientData.hpp>
#include <functional>
class MapView;
class MapChunk;
@@ -115,7 +117,7 @@ namespace Noggit
float getDelta() const;
void setBlockCursor(bool state);
bool getBlockCursor() const;
void setPostCallback(auto(MapView::*method)()->void);
void setPostCallback(std::function<void()> function);
bool getTag() { return _tag; };
void setTag(bool tag) { _tag = tag; };
@@ -184,7 +186,7 @@ namespace Noggit
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 <noggit/Misc.h>
#include <noggit/Selection.h>
#include <noggit/BoolToggleProperty.hpp>
#include <noggit/Camera.hpp>
#include <noggit/tool_enums.hpp>
#include <noggit/ui/ObjectEditor.h>
#include <noggit/ui/MinimapCreator.hpp>
#include <noggit/ui/UidFixWindow.hpp>
#include <noggit/unsigned_int_property.hpp>
#include <noggit/ui/tools/AssetBrowser/Ui/AssetBrowser.hpp>
#include <noggit/ui/tools/ViewportGizmo/ViewportGizmo.hpp>
#include <noggit/ui/tools/ViewportManager/ViewportManager.hpp>
#include <noggit/ui/tools/ToolPanel/ToolPanel.hpp>
#include <noggit/TabletManager.hpp>
#include <external/qtimgui/QtImGui.h>
#include <opengl/texture.hpp>
#include <opengl/scoped.hpp>
#include <optional>
#include <noggit/Tool.hpp>
#include <QtCore/QElapsedTimer>
#include <QtCore/QSettings>
@@ -51,6 +46,7 @@ namespace Noggit::Ui::Windows
namespace Noggit
{
class Tool;
namespace Ui::Tools::ViewToolbar::Ui
{
@@ -59,18 +55,7 @@ namespace Noggit
namespace Ui::Tools
{
class BrushStack;
class LightEditor;
namespace ChunkManipulator
{
class ChunkManipulatorPanel;
}
}
namespace Scripting
{
class scripting_tool;
class ToolPanel;
}
class Camera;
@@ -79,21 +64,9 @@ namespace Noggit
namespace Ui
{
class detail_infos;
class flatten_blur_tool;
class help;
class minimap_widget;
class ShaderTool;
class TerrainTool;
class texture_picker;
class texturing_tool;
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 };
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();
display_mode _display_mode;
@@ -196,26 +163,13 @@ private:
float mTimespeed;
void ResetSelectedObjectRotation();
void snap_selected_models_to_the_ground();
void DeleteSelectedObjects();
void changeZoneIDValue (int set);
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;
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
// view settings when the ground editing mode is switched on to
// restore them if switch back again
@@ -243,8 +197,6 @@ private:
uid_fix_mode _uid_fix;
bool _from_bookmark;
bool saving_minimap = false;
Noggit::Ui::toolbar* _toolbar;
Noggit::Ui::Tools::ViewToolbar::Ui::ViewToolbar* _view_toolbar;
Noggit::Ui::Tools::ViewToolbar::Ui::ViewToolbar* _secondary_toolbar;
@@ -261,7 +213,10 @@ signals:
void resized();
void saved();
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:
void on_exit_prompt();
void ShowContextMenu(QPoint pos);
@@ -284,16 +239,9 @@ public:
void tick (float dt);
void change_selected_wmo_nameset(int set);
void change_selected_wmo_doodadset(int set);
void saveMinimap(MinimapRenderSettings* settings);
void initMinimapSave() { saving_minimap = true; };
auto setBrushTexture(QImage const* img) -> void;
Noggit::Camera* getCamera() { return &_camera; };
void randomizeTerrainRotation();
void randomizeTexturingRotation();
void randomizeShaderRotation();
void randomizeStampRotation();
void onSettingsSave();
void updateRotationEditor() { _rotation_editor_need_update = true; };
void setCameraDirty() { _camera_moved_since_last_draw = true; };
[[nodiscard]]
@@ -308,15 +256,6 @@ public:
[[nodiscard]]
QWidget *getLeftSecondaryToolbar();
[[nodiscard]]
QWidget* getActiveStampModeItem();
[[nodiscard]]
Noggit::Ui::flatten_blur_tool* getFlattenTool() { return flattenTool; };
[[nodiscard]]
Noggit::Ui::GroundEffectsTool* getGroundEffectsTool();
[[nodiscard]]
Noggit::NoggitRenderContext getRenderContext() { return _context; };
@@ -329,14 +268,8 @@ public:
[[nodiscard]]
Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget* getAssetBrowserWidget() { return _asset_browser; };
[[nodiscard]]
Noggit::Ui::object_editor* getObjectEditor() { return objectEditor; };
[[nodiscard]]
QDockWidget* getObjectPalette() { return _object_palette_dock; };
[[nodiscard]]
QDockWidget* getTexturePalette() { return _texture_palette_dock; };
glm::vec3 cursorPosition() const;
void cursorPosition(glm::vec3 position);
private:
enum Modifier
@@ -353,15 +286,17 @@ private:
{
Qt::Key key;
size_t modifiers;
std::function<void()> function;
std::function<void()> onPress;
std::function<void()> onRelease;
std::function<bool()> condition;
HotKey (Qt::Key k, size_t m, std::function<void()> f, std::function<bool()> c)
: key (k), modifiers (m), function (f), condition (c) {}
HotKey (Qt::Key k, size_t m, std::function<void()> f, std::function<bool()> c, std::function<void()> r = []{})
: key (k), modifiers (m), onPress(f), onRelease{r}, condition (c) {}
};
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, StringHash hotkeyName);
QElapsedTimer _startup_time;
qreal _last_update = 0.f;
@@ -389,7 +324,6 @@ private:
Noggit::Ui::Windows::NoggitWindow* _main_window;
glm::vec4 normalized_device_coords (int x, int y) const;
float aspect_ratio() const;
Noggit::TabletManager* _tablet_manager;
@@ -402,31 +336,17 @@ private:
QLabel* _status_database;
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_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_minimap_borders = {true};
Noggit::BoolToggleProperty _show_minimap_skies = {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::Ui::minimap_widget* _minimap;
QDockWidget* _minimap_dock;
QDockWidget* _texture_palette_dock;
QDockWidget* _object_palette_dock;
void move_camera_with_auto_height (glm::vec3 const&);
@@ -435,33 +355,14 @@ private:
void unloadOpenglData() override;
Noggit::Ui::help* _keybindings;
Noggit::Ui::tileset_chooser* TexturePalette;
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;
Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget* _asset_browser;
Noggit::Ui::Tools::AssetBrowser::Ui::AssetBrowserWidget* _asset_browser = nullptr;
QDockWidget* _asset_browser_dock;
QDockWidget* _node_editor_dock;
QDockWidget* _texture_browser_dock;
QDockWidget* _texture_picker_dock;
QDockWidget* _detail_infos_dock;
Noggit::Ui::Tools::ToolPanel* _tool_panel_dock;
@@ -479,33 +380,14 @@ private:
bool _needs_redraw = false;
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;
QRubberBand* _area_selection;
public:
private:
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 setupAssetBrowser();
void setupDetailInfos();
@@ -517,10 +399,60 @@ private:
void setupEditMenu();
void setupAssistMenu();
void setupViewMenu();
void setupToolsMenu();
void setupHelpMenu();
void setupHotkeys();
void setupClientMenu();
void setupMainToolbar();
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
#include <QWidget>
#include <QtGui/QIcon>
#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()

View File

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

View File

@@ -1,354 +1,354 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/ui/Help.h>
#include <noggit/ui/FontNoggit.hpp>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QScrollArea>
#include <QtWidgets/QTabWidget>
#include <initializer_list>
namespace Noggit
{
namespace Ui
{
help::help(QWidget* parent)
: widget (parent, Qt::Window)
{
setWindowTitle ("Help");
setWindowIcon (QIcon (":/icon"));
setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint);
QString header_style =
"QLabel { \n "
" font-weight: bold; \n "
" margin-top: 8px; \n "
" margin-bottom: 4px; \n "
" margin-left: 150px; \n "
"} \n ";
auto layout (new QFormLayout (this));
layout->setSizeConstraint(QLayout::SetFixedSize);
auto tabs (new QTabWidget (this));
auto base_widget (new QWidget (this));
auto base_layout(new QGridLayout (base_widget));
auto basic_controls_layout (new QFormLayout (this));
base_layout->addLayout(basic_controls_layout, 0, 0);
base_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
auto label = new QLabel("Basic controls:");
label->setStyleSheet(header_style);
basic_controls_layout->addRow(label);
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::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::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::m}, "\aShow map", 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::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}, "\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::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
auto toggles_layout(new QFormLayout(this));
base_layout->addLayout(toggles_layout, 0, 1);
auto label_toggle = new QLabel("Toggles:");
label_toggle->setStyleSheet(header_style);
toggles_layout->addRow(label_toggle);
generate_hotkey_row({FontNoggit::f1}, "\aToggle M2s", 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::f4}, "\aToggle water", 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::f8}, "\aToggle detailed window", 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::f11}, "\aToggle model animations", toggles_layout);
generate_hotkey_row({FontNoggit::f12}, "\aToggle fog", toggles_layout);
generate_hotkey_row({}, "1 - 9 Select the editing modes", toggles_layout);
auto files_layout(new QFormLayout(this));
base_layout->addLayout(files_layout, 1, 0);
auto label_files = new QLabel("Files:");
label_files->setStyleSheet(header_style);
files_layout->addRow(label_files);
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::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::g}, "\aSave port commands to ports.txt", files_layout);
auto adjust_layout(new QFormLayout(this));
base_layout->addLayout(adjust_layout, 1, 1);
auto label_adjust = new QLabel("Adjust:");
label_adjust->setStyleSheet(header_style);
adjust_layout->addRow(label_adjust);
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::j}, "\aPause time", adjust_layout);
// NYI
// 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_layout (new QFormLayout (flag_widget));
auto holes_label = new QLabel("Holes:");
holes_label->setStyleSheet(header_style);
flag_layout->addRow(holes_label);
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::t}, "\aRemove all holes 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:");
impass_flags_label->setStyleSheet(header_style);
flag_layout->addRow(impass_flags_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aPaint flag", flag_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aClear flag", flag_layout);
auto areaid_label = new QLabel("AreaID Flags:");
areaid_label->setStyleSheet(header_style);
flag_layout->addRow(areaid_label);
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::f }, "\a - Fill current ADT with selected AreaID", flag_layout);
auto ground_widget (new QWidget (this));
auto ground_layout (new QGridLayout (ground_widget));
auto ground_column1_layout(new QFormLayout(this));
ground_layout->addLayout(ground_column1_layout, 0, 0);
auto ground_label = new QLabel("Edit ground:");
ground_label->setStyleSheet(header_style);
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::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);
auto raise_label = new QLabel("Raise / Lower tool:");
raise_label->setStyleSheet(header_style);
ground_column1_layout->addRow(raise_label);
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::y }, "\aSwitch to next type", 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):");
raise_label_vm->setStyleSheet(header_style);
ground_column1_layout->addRow(raise_label_vm);
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::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::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::mmb }, "\a+\aChange angle", ground_column1_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange orientation", ground_column1_layout);
auto ground_column2_layout(new QFormLayout(this));
ground_layout->addLayout(ground_column2_layout, 0, 1);
auto flatten_label = new QLabel("Flatten / Blur tool:");
flatten_label->setStyleSheet(header_style);
ground_column2_layout->addRow(flatten_label);
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::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::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::y }, "\aSwitch to next type", 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::mmb }, "\a+\aChange height", ground_column2_layout);
auto texture_widget (new QWidget (this));
auto texture_layout (new QFormLayout (texture_widget));
auto common_controls_label = new QLabel("Common controls:");
common_controls_label->setStyleSheet(header_style);
texture_layout->addRow(common_controls_label);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aOpen texture picker for the chunk", texture_layout);
auto paint_label = new QLabel("Paint:");
paint_label->setStyleSheet(header_style);
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::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::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::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::t }, "\aToggle spray brush", 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);
auto swapper_label = new QLabel("Swap:");
swapper_label->setStyleSheet(header_style);
texture_layout->addRow(swapper_label);
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::t }, "\aToggle brush swapper", texture_layout);
auto anim_label = new QLabel("Anim:");
anim_label->setStyleSheet(header_style);
texture_layout->addRow(anim_label);
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);
auto water_widget (new QWidget (this));
auto water_layout (new QFormLayout (water_widget));
auto water_label = new QLabel("Water:");
water_label->setStyleSheet(header_style);
water_layout->addRow(water_label);
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::alt, FontNoggit::lmb_drag }, "\a+\aChange brush size", 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::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::space, FontNoggit::f }, "\a+\aToggle lock mode", water_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::mmb }, "\a+\aChange height", water_layout);
auto object_widget (new QWidget (this));
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):");
object_label->setStyleSheet(header_style);
object_layout->addRow(object_label);
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::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, FontNoggit::r }, "\a+\aReset rotation", 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::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::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::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::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::f }, "\aMove selection to cursor position", 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 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::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::shift, FontNoggit::ctrl }, "Holding \a and \a Half speed", object_layout);
auto shader_widget (new QWidget (this));
auto shader_layout (new QFormLayout (shader_widget));
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::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::mmb }, "\aPick shader color from the ground", shader_layout);
generate_hotkey_row({FontNoggit::plus }, "\aAdd current color to palette", shader_layout);
layout->addWidget(tabs);
tabs->addTab(base_widget, "Basic");
tabs->addTab(ground_widget, "Terrain Editors");
tabs->addTab(texture_widget, "Texture Painter");
tabs->addTab(water_widget, "Water Editor");
tabs->addTab(object_widget, "Object Editor");
tabs->addTab(shader_widget, "Vertex Painter");
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)
{
auto row_layout = new QHBoxLayout(this);
const char* from = nullptr;
auto icon = hotkeys.begin();
while (*description)
{
if (*description == '\a')
{
if (from)
{
auto label = new QLabel(::std::string(from, description - from).c_str());
row_layout->addWidget(label);
}
auto label = new QLabel(this);
QIcon hotkey_icon = FontNoggitIcon(*icon++);
label->setPixmap(hotkey_icon.pixmap(22, 22));
row_layout->addWidget(label);
from = ++description;
}
else
{
if (!from)
{
from = description;
}
++description;
}
}
if (from && *from)
{
auto label = new QLabel(from);
row_layout->addWidget(label);
}
row_layout->setAlignment(Qt::AlignLeft);
layout->addRow(row_layout);
}
}
}
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/ui/Help.h>
#include <noggit/ui/FontNoggit.hpp>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QScrollArea>
#include <QtWidgets/QTabWidget>
#include <initializer_list>
namespace Noggit
{
namespace Ui
{
help::help(QWidget* parent)
: widget (parent, Qt::Window)
{
setWindowTitle ("Help");
setWindowIcon (QIcon (":/icon"));
setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint);
QString header_style =
"QLabel { \n "
" font-weight: bold; \n "
" margin-top: 8px; \n "
" margin-bottom: 4px; \n "
" margin-left: 150px; \n "
"} \n ";
auto layout (new QFormLayout (this));
layout->setSizeConstraint(QLayout::SetFixedSize);
auto tabs (new QTabWidget (this));
auto base_widget (new QWidget (this));
auto base_layout(new QGridLayout (base_widget));
auto basic_controls_layout (new QFormLayout (this));
base_layout->addLayout(basic_controls_layout, 0, 0);
base_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
auto label = new QLabel("Basic controls:");
label->setStyleSheet(header_style);
basic_controls_layout->addRow(label);
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::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::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::m}, "\aShow map", 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::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}, "\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::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
auto toggles_layout(new QFormLayout(this));
base_layout->addLayout(toggles_layout, 0, 1);
auto label_toggle = new QLabel("Toggles:");
label_toggle->setStyleSheet(header_style);
toggles_layout->addRow(label_toggle);
generate_hotkey_row({FontNoggit::f1}, "\aToggle M2s", 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::f4}, "\aToggle water", 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::f8}, "\aToggle detailed window", 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::f11}, "\aToggle model animations", toggles_layout);
generate_hotkey_row({FontNoggit::f12}, "\aToggle fog", toggles_layout);
generate_hotkey_row({}, "1 - 9 Select the editing modes", toggles_layout);
auto files_layout(new QFormLayout(this));
base_layout->addLayout(files_layout, 1, 0);
auto label_files = new QLabel("Files:");
label_files->setStyleSheet(header_style);
files_layout->addRow(label_files);
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::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::g}, "\aSave port commands to ports.txt", files_layout);
auto adjust_layout(new QFormLayout(this));
base_layout->addLayout(adjust_layout, 1, 1);
auto label_adjust = new QLabel("Adjust:");
label_adjust->setStyleSheet(header_style);
adjust_layout->addRow(label_adjust);
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::j}, "\aPause time", adjust_layout);
// NYI
// 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_layout (new QFormLayout (flag_widget));
auto holes_label = new QLabel("Holes:");
holes_label->setStyleSheet(header_style);
flag_layout->addRow(holes_label);
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::t}, "\aRemove all holes 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:");
impass_flags_label->setStyleSheet(header_style);
flag_layout->addRow(impass_flags_label);
generate_hotkey_row({FontNoggit::shift, FontNoggit::lmb }, "\a+\aPaint flag", flag_layout);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aClear flag", flag_layout);
auto areaid_label = new QLabel("AreaID Flags:");
areaid_label->setStyleSheet(header_style);
flag_layout->addRow(areaid_label);
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::f }, "\a - Fill current ADT with selected AreaID", flag_layout);
auto ground_widget (new QWidget (this));
auto ground_layout (new QGridLayout (ground_widget));
auto ground_column1_layout(new QFormLayout(this));
ground_layout->addLayout(ground_column1_layout, 0, 0);
auto ground_label = new QLabel("Edit ground:");
ground_label->setStyleSheet(header_style);
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::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);
auto raise_label = new QLabel("Raise / Lower tool:");
raise_label->setStyleSheet(header_style);
ground_column1_layout->addRow(raise_label);
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::y }, "\aSwitch to next type", 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):");
raise_label_vm->setStyleSheet(header_style);
ground_column1_layout->addRow(raise_label_vm);
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::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::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::mmb }, "\a+\aChange angle", ground_column1_layout);
generate_hotkey_row({FontNoggit::alt, FontNoggit::mmb }, "\a+\aChange orientation", ground_column1_layout);
auto ground_column2_layout(new QFormLayout(this));
ground_layout->addLayout(ground_column2_layout, 0, 1);
auto flatten_label = new QLabel("Flatten / Blur tool:");
flatten_label->setStyleSheet(header_style);
ground_column2_layout->addRow(flatten_label);
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::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::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::y }, "\aSwitch to next type", 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::mmb }, "\a+\aChange height", ground_column2_layout);
auto texture_widget (new QWidget (this));
auto texture_layout (new QFormLayout (texture_widget));
auto common_controls_label = new QLabel("Common controls:");
common_controls_label->setStyleSheet(header_style);
texture_layout->addRow(common_controls_label);
generate_hotkey_row({FontNoggit::ctrl, FontNoggit::lmb }, "\a+\aOpen texture picker for the chunk", texture_layout);
auto paint_label = new QLabel("Paint:");
paint_label->setStyleSheet(header_style);
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::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::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::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::t }, "\aToggle spray brush", 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);
auto swapper_label = new QLabel("Swap:");
swapper_label->setStyleSheet(header_style);
texture_layout->addRow(swapper_label);
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::t }, "\aToggle brush swapper", texture_layout);
auto anim_label = new QLabel("Anim:");
anim_label->setStyleSheet(header_style);
texture_layout->addRow(anim_label);
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);
auto water_widget (new QWidget (this));
auto water_layout (new QFormLayout (water_widget));
auto water_label = new QLabel("Water:");
water_label->setStyleSheet(header_style);
water_layout->addRow(water_label);
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::alt, FontNoggit::lmb_drag }, "\a+\aChange brush size", 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::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::space, FontNoggit::f }, "\a+\aToggle lock mode", water_layout);
generate_hotkey_row({FontNoggit::space, FontNoggit::mmb }, "\a+\aChange height", water_layout);
auto object_widget (new QWidget (this));
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):");
object_label->setStyleSheet(header_style);
object_layout->addRow(object_label);
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::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, FontNoggit::r }, "\a+\aReset rotation", 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::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::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::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::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::f }, "\aMove selection to cursor position", 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 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::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::shift, FontNoggit::ctrl }, "Holding \a and \a Half speed", object_layout);
auto shader_widget (new QWidget (this));
auto shader_layout (new QFormLayout (shader_widget));
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::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::mmb }, "\aPick shader color from the ground", shader_layout);
generate_hotkey_row({FontNoggit::plus }, "\aAdd current color to palette", shader_layout);
layout->addWidget(tabs);
tabs->addTab(base_widget, "Basic");
tabs->addTab(ground_widget, "Terrain Editors");
tabs->addTab(texture_widget, "Texture Painter");
tabs->addTab(water_widget, "Water Editor");
tabs->addTab(object_widget, "Object Editor");
tabs->addTab(shader_widget, "Vertex Painter");
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)
{
auto row_layout = new QHBoxLayout(this);
const char* from = nullptr;
auto icon = hotkeys.begin();
while (*description)
{
if (*description == '\a')
{
if (from)
{
auto label = new QLabel(::std::string(from, description - from).c_str());
row_layout->addWidget(label);
}
auto label = new QLabel(this);
QIcon hotkey_icon = FontNoggitIcon(*icon++);
label->setPixmap(hotkey_icon.pixmap(22, 22));
row_layout->addWidget(label);
from = ++description;
}
else
{
if (!from)
{
from = description;
}
++description;
}
}
if (from && *from)
{
auto label = new QLabel(from);
row_layout->addWidget(label);
}
row_layout->setAlignment(Qt::AlignLeft);
layout->addRow(row_layout);
}
}
}

View File

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

View File

@@ -15,53 +15,13 @@
#include <array>
#include <glm/vec4.hpp>
#include <noggit/MinimapRenderSettings.hpp>
#include <noggit/ui/minimap_widget.hpp>
class MapView;
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
@@ -72,6 +32,7 @@ namespace Noggit
class MinimapCreator : public QWidget
{
Q_OBJECT
public:
MinimapCreator(MapView* mapView, World* world, QWidget* parent = nullptr);
@@ -79,7 +40,8 @@ namespace Noggit
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; };
@@ -98,6 +60,9 @@ namespace Noggit
void loadFiltersFromJSON();
void saveFiltersToJSON();
signals:
void onSave();
private:
float _radius = 0.01f;
MinimapRenderSettings _render_settings;

View File

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

View File

@@ -3,6 +3,7 @@
#pragma once
#include <noggit/Selection.h>
#include <noggit/BoolToggleProperty.hpp>
#include <noggit/object_paste_params.hpp>
#include <QLabel>
#include <QWidget>
@@ -36,21 +37,11 @@ enum ModelPasteMode
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
{
class object_editor : public QWidget
{
Q_OBJECT
public:
object_editor ( MapView*
, World*
@@ -94,6 +85,9 @@ namespace Noggit
void update_selection_ui(World* world);
signals:
void objectPaletteBtnPressed();
private:
float _radius = 0.01f;
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);
_mask_image = pixmap->toImage().transformed(matrix, Qt::SmoothTransformation);
if (_map_view->get_editing_mode() != editing_mode::stamp
|| (_map_view->getActiveStampModeItem() && _map_view->getActiveStampModeItem() == this))
_map_view->setBrushTexture(&_mask_image);
emit _map_view->trySetBrushTexture(&_mask_image, this);
}
QJsonObject ShaderTool::toJSON()

View File

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

View File

@@ -1,12 +1,13 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/Tool.hpp>
#include <noggit/ui/Toolbar.h>
namespace Noggit
{
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)
, _tool_group(this)
{
@@ -14,20 +15,10 @@ namespace Noggit
setAllowedAreas(Qt::LeftToolBarArea);
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
add_tool_icon(editing_mode::ground, tr("Raise / Lower"), FontNoggit::TOOL_RAISE_LOWER);
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(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);
for (auto&& tool : tools)
{
add_tool_icon(tool->editingMode(), tr(tool->name()), tool->icon());
}
}
void toolbar::add_tool_icon(editing_mode mode, const QString& name, const FontNoggit::Icons& icon)

View File

@@ -12,12 +12,14 @@
namespace Noggit
{
class Tool;
namespace Ui
{
class toolbar: public QToolBar
{
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);

View File

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

View File

@@ -76,7 +76,7 @@ namespace Noggit
if (!_selected_tiles)
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; }
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; }
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; }
void set_resizeable(bool state) { _resizeable = state; };
@@ -66,7 +66,7 @@ namespace Noggit
private:
World* _world;
Noggit::Camera* _camera;
std::array<bool, 4096>* _selected_tiles;
std::vector<char>* _selected_tiles;
bool _draw_skies;
bool _draw_camera;

View File

@@ -102,7 +102,7 @@ namespace Noggit
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
, [=] ()
{
_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);
_mask_image = pixmap->toImage().transformed(matrix, Qt::SmoothTransformation);
if (_map_view->get_editing_mode() != editing_mode::stamp
|| (_map_view->getActiveStampModeItem() && _map_view->getActiveStampModeItem() == this))
_map_view->setBrushTexture(&_mask_image);
emit _map_view->trySetBrushTexture(&_mask_image, this);
}
void texturing_tool::update_brush_hardness()

View File

@@ -21,6 +21,7 @@
#include <QtWidgets/QWidget>
#include <QtWidgets/QListWidget>
#include <QJsonObject>
#include <QPainter>
class World;
class MapView;
@@ -127,6 +128,7 @@ namespace Noggit
class texturing_tool : public QWidget
{
Q_OBJECT
public:
texturing_tool ( const glm::vec3* camera_pos
, MapView* map_view
@@ -197,6 +199,9 @@ namespace Noggit
QJsonObject toJSON();
void fromJSON(QJsonObject const& json);
signals:
void texturePaletteToggled();
private:
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);
_selected_path = str_path;
if (_browse_mode == asset_browse_mode::detail_doodads && _map_view->get_editing_mode() == editing_mode::paint)
{
_map_view->getGroundEffectsTool()->setDoodadSlotFromBrowser(str_path.c_str());
}
else
{
_map_view->getObjectEditor()->copy(str_path);
}
emit selectionChanged(str_path);
}
}

View File

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

View File

@@ -1,5 +1,7 @@
// 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/ActionHistoryNavigator/ActionHistoryNavigator.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 });
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);
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;
}
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* _lower_option = static_cast<SubToolBarAction*>(_flatten_secondary_tool[0])->GET<CheckBoxAction*>(lower_index);

View File

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

View File

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

View File

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

View File

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