Skip to content

Commit

Permalink
Add editor shortcut to re-generate terrain
Browse files Browse the repository at this point in the history
  • Loading branch information
Zylann committed Jun 4, 2023
1 parent 486fc13 commit 3d4585f
Show file tree
Hide file tree
Showing 12 changed files with 197 additions and 4 deletions.
2 changes: 2 additions & 0 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def get_sources(env, is_editor_build):

"util/godot/classes/concave_polygon_shape_3d.cpp",
"util/godot/classes/geometry_2d.cpp",
"util/godot/classes/input_event_key.cpp",
"util/godot/classes/mesh.cpp",
"util/godot/classes/multimesh.cpp",
"util/godot/classes/node.cpp",
Expand Down Expand Up @@ -109,6 +110,7 @@ def get_sources(env, is_editor_build):
"util/godot/classes/editor_import_plugin.cpp",
"util/godot/classes/editor_inspector_plugin.cpp",
"util/godot/classes/editor_property.cpp",
"util/godot/classes/editor_settings.cpp",
"util/godot/classes/graph_edit.cpp", # Not editor-only, but only used in editor for now
]

Expand Down
2 changes: 2 additions & 0 deletions doc/source/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Semver is not yet in place, so each version can have breaking changes, although

- General
- Added shadow casting setting to both terrain types
- Added editor shortcut to re-generate the selected terrain
- Updated FastNoise2 to 0.10.0-alpha
- `VoxelGeneratorGraph`:
- Added `Spots2D` and `Spots3D` nodes, optimized for generating "ore patches"
- `VoxelTerrain`:
Expand Down
7 changes: 6 additions & 1 deletion editor/terrain/voxel_terrain_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
#include "../../terrain/variable_lod/voxel_lod_terrain.h"
#include "../../util/godot/classes/camera_3d.h"
#include "../../util/godot/classes/editor_interface.h"
#include "../../util/godot/classes/editor_settings.h"
#include "../../util/godot/classes/menu_button.h"
#include "../../util/godot/classes/node.h"
#include "../../util/godot/classes/popup_menu.h"
#include "../../util/godot/core/callable.h"
#include "../../util/godot/core/keyboard.h"
#include "../../util/godot/funcs.h"
#include "../about_window.h"
#include "../graph/voxel_graph_node_inspector_wrapper.h"
Expand Down Expand Up @@ -40,7 +42,10 @@ void VoxelTerrainEditorPlugin::generate_menu_items(MenuButton *menu_button, bool
PopupMenu *popup = menu_button->get_popup();
popup->clear();

popup->add_item(ZN_TTR("Re-generate"), MENU_RESTART_STREAM);
popup->add_shortcut(get_or_create_editor_shortcut("voxel/regenerate_terrain", ZN_TTR("Re-generate"),
godot::KEY_MASK_CMD_OR_CTRL | godot::KEY_R),
MENU_RESTART_STREAM);

popup->add_item(ZN_TTR("Re-mesh"), MENU_REMESH);
popup->add_separator();
{
Expand Down
45 changes: 45 additions & 0 deletions util/godot/classes/editor_settings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "editor_settings.h"
#include "input_event_key.h"

namespace zylann {

Ref<Shortcut> get_or_create_editor_shortcut(const String &p_path, const String &p_name, Key p_keycode) {
#if defined(ZN_GODOT)
return ED_SHORTCUT(p_path, p_name, p_keycode);

#elif defined(ZN_GODOT_EXTENSION)
// TODO GDX: `ED_SHORTCUT` and other `EditorSettings` shortcut APIs are not exposed
// See https://github.com/godotengine/godot/pull/58585

// Ported from core `ED_SHORTCUT_ARRAY`.
// Returning a shortcut from the provided key without any registration to `EditorSettings`.
// That means the shortcut cannot be configured by the user.

Array events;

Key keycode = p_keycode;

// TODO GDX: No built-in macros to test the target platform
#ifdef MACOS_ENABLED
// Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
if (keycode == Key::KEY_DELETE) {
keycode = KeyModifierMask::META | Key::BACKSPACE;
}
#endif

Ref<InputEventKey> ie;
if (keycode != godot::KEY_NONE) {
ie = create_input_event_from_key(keycode, false);
events.push_back(ie);
}

Ref<Shortcut> sc;
sc.instantiate();
sc->set_name(p_name);
sc->set_events(events);
sc->set_meta("original", events.duplicate(true));
return sc;
#endif
}

} // namespace zylann
19 changes: 19 additions & 0 deletions util/godot/classes/editor_settings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef ZN_GODOT_EDITOR_SETTINGS_H
#define ZN_GODOT_EDITOR_SETTINGS_H

#if defined(ZN_GODOT)
#include <editor/editor_settings.h>
#elif defined(ZN_GODOT_EXTENSION)
#include <godot_cpp/classes/editor_settings.hpp>
using namespace godot;
#endif

#include "shortcut.h"

namespace zylann {

Ref<Shortcut> get_or_create_editor_shortcut(const String &p_path, const String &p_name, Key p_keycode);

} // namespace zylann

#endif // ZN_GODOT_EDITOR_SETTINGS_H
2 changes: 1 addition & 1 deletion util/godot/classes/input_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define ZN_GODOT_INPUT_EVENT_H

#if defined(ZN_GODOT)
#include <core/input/input.h>
#include <core/input/input_event.h>
#elif defined(ZN_GODOT_EXTENSION)
#include <godot_cpp/classes/input_event.hpp>
using namespace godot;
Expand Down
51 changes: 51 additions & 0 deletions util/godot/classes/input_event_key.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "input_event_key.h"
#include "../core/keyboard.h"

namespace zylann {

Ref<InputEventKey> create_input_event_from_key(Key p_keycode_with_modifier_masks, bool p_physical) {
#if defined(ZN_GODOT)
return InputEventKey::create_reference(p_keycode_with_modifier_masks, p_physical);

#elif defined(ZN_GODOT_EXTENSION)
Key p_keycode = p_keycode_with_modifier_masks;

// Ported from core `InputEventKey::create_reference`

Ref<InputEventKey> ie;
ie.instantiate();
if (p_physical) {
ie->set_physical_keycode(p_keycode & godot::KEY_CODE_MASK);
} else {
ie->set_keycode(p_keycode & godot::KEY_CODE_MASK);
}

ie->set_unicode(char32_t(p_keycode & godot::KEY_CODE_MASK));

if ((p_keycode & godot::KEY_MASK_SHIFT) != godot::KEY_NONE) {
ie->set_shift_pressed(true);
}
if ((p_keycode & godot::KEY_MASK_ALT) != godot::KEY_NONE) {
ie->set_alt_pressed(true);
}
if ((p_keycode & godot::KEY_MASK_CMD_OR_CTRL) != godot::KEY_NONE) {
ie->set_command_or_control_autoremap(true);
if ((p_keycode & godot::KEY_MASK_CTRL) != godot::KEY_NONE ||
(p_keycode & godot::KEY_MASK_META) != godot::KEY_NONE) {
WARN_PRINT("Invalid Key Modifiers: Command or Control autoremapping is enabled, Meta and Control values "
"are ignored!");
}
} else {
if ((p_keycode & godot::KEY_MASK_CTRL) != godot::KEY_NONE) {
ie->set_ctrl_pressed(true);
}
if ((p_keycode & godot::KEY_MASK_META) != godot::KEY_NONE) {
ie->set_meta_pressed(true);
}
}

return ie;
#endif
}

} // namespace zylann
18 changes: 18 additions & 0 deletions util/godot/classes/input_event_key.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef ZN_GODOT_INPUT_EVENT_KEY_H
#define ZN_GODOT_INPUT_EVENT_KEY_H

#if defined(ZN_GODOT)
#include <core/input/input_event.h>
#elif defined(ZN_GODOT_EXTENSION)
#include <godot_cpp/classes/input_event_key.hpp>
using namespace godot;
#endif

namespace zylann {

// TODO GDX: InputEventKey::create_reference is not exposed
Ref<InputEventKey> create_input_event_from_key(Key p_keycode_with_modifier_masks, bool p_physical = false);

} // namespace zylann

#endif // ZN_GODOT_INPUT_EVENT_KEY_H
2 changes: 1 addition & 1 deletion util/godot/classes/input_event_mouse_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define ZN_GODOT_INPUT_EVENT_MOUSE_BUTTON_H

#if defined(ZN_GODOT)
#include <core/input/input.h>
#include <core/input/input_event.h>
#elif defined(ZN_GODOT_EXTENSION)
#include <godot_cpp/classes/input_event_mouse_button.hpp>
using namespace godot;
Expand Down
2 changes: 1 addition & 1 deletion util/godot/classes/input_event_mouse_motion.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define ZN_GODOT_INPUT_EVENT_MOUSE_MOTION_H

#if defined(ZN_GODOT)
#include <core/input/input.h>
#include <core/input/input_event.h>
#elif defined(ZN_GODOT_EXTENSION)
#include <godot_cpp/classes/input_event_mouse_motion.hpp>
using namespace godot;
Expand Down
11 changes: 11 additions & 0 deletions util/godot/classes/shortcut.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef ZN_GODOT_SHORTCUT_H
#define ZN_GODOT_SHORTCUT_H

#if defined(ZN_GODOT)
#include <core/input/shortcut.h>
#elif defined(ZN_GODOT_EXTENSION)
#include <godot_cpp/classes/shortcut.hpp>
using namespace godot;
#endif

#endif // ZN_GODOT_SHORTCUT_H
40 changes: 40 additions & 0 deletions util/godot/core/keyboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef ZN_GODOT_KEYBOARD_H
#define ZN_GODOT_KEYBOARD_H

// Key enums are not defined the same way between Godot and GDExtension.
// This defines aliases so using them is the same in both module and extension builds.

#if defined(ZN_GODOT)
#include <core/os/keyboard.h>

namespace godot {
static const KeyModifierMask KEY_CODE_MASK = KeyModifierMask::CODE_MASK;
static const KeyModifierMask KEY_MODIFIER_MASK = KeyModifierMask::MODIFIER_MASK;
static const KeyModifierMask KEY_MASK_CMD_OR_CTRL = KeyModifierMask::CMD_OR_CTRL;
static const KeyModifierMask KEY_MASK_SHIFT = KeyModifierMask::SHIFT;
static const KeyModifierMask KEY_MASK_ALT = KeyModifierMask::ALT;
static const KeyModifierMask KEY_MASK_META = KeyModifierMask::META;
static const KeyModifierMask KEY_MASK_CTRL = KeyModifierMask::CTRL;
static const KeyModifierMask KEY_MASK_KPAD = KeyModifierMask::KPAD;
static const KeyModifierMask KEY_MASK_GROUP_SWITCH = KeyModifierMask::GROUP_SWITCH;

static const Key KEY_NONE = Key::NONE;
static const Key KEY_R = Key::R;
}; // namespace godot

#elif defined(ZN_GODOT_EXTENSION)
#include <godot_cpp/classes/global_constants.hpp>

// TODO GDX: The operator `Key & KeyModifierMask` is defined in core, but not in GDExtension...
constexpr godot::Key operator&(godot::Key a, godot::KeyModifierMask b) {
return (godot::Key)((int)a & (int)b);
}

// TODO GDX: The operator `Key | KeyModifierMask` is defined in core, but not in GDExtension...
constexpr godot::KeyModifierMask operator|(godot::KeyModifierMask a, godot::KeyModifierMask b) {
return (godot::KeyModifierMask)((int)a | (int)b);
}

#endif

#endif // ZN_GODOT_KEYBOARD_H

0 comments on commit 3d4585f

Please sign in to comment.