Show voxel bounds as min/max instead of pos/size
This commit is contained in:
parent
d6d592bb20
commit
97e4101234
@ -20,8 +20,8 @@ static const unsigned int MAX_BLOCK_COUNT_PER_REQUEST = 4 * 4 * 4;
|
||||
// Using a higher maximum can cause int32 overflows when calculating dimensions. There is no use case for it.
|
||||
static const unsigned int MAX_LOD = 24;
|
||||
|
||||
static const unsigned int MAX_VOLUME_EXTENT = 0x1fffffff;
|
||||
static const unsigned int MAX_VOLUME_SIZE = 2 * MAX_VOLUME_EXTENT; // 1,073,741,822 voxels
|
||||
static const int MAX_VOLUME_EXTENT = 0x1fffffff;
|
||||
static const int MAX_VOLUME_SIZE = 2 * MAX_VOLUME_EXTENT; // 1,073,741,822 voxels
|
||||
|
||||
static const float INV_0x7f = 1.f / 0x7f;
|
||||
static const float INV_0x7fff = 1.f / 0x7fff;
|
||||
|
@ -21,6 +21,7 @@ Godot 4 is required from this version.
|
||||
- Added `ZN_ThreadedTask` to allow running custom tasks using the thread pool system
|
||||
- Added `VoxelMeshSDF` to bake SDF from meshes, which can be used in voxel sculpting.
|
||||
- Mesh resources are now fully built on threads with the Godot Vulkan renderer
|
||||
- Editor: terrain bounds are now shown in the inspector as min/max instead of position/size
|
||||
- `VoxelGeneratorGraph`: added support for outputting to the TYPE channel, allowing use with `VoxelMesherBlocky`
|
||||
- `VoxelGeneratorGraph`: editor: unconnected inputs show their default value directly on the node
|
||||
- `VoxelGeneratorGraph`: editor: allow to change the axes on preview nodes 3D slices
|
||||
|
108
editor/terrain/editor_property_aabb_min_max.cpp
Normal file
108
editor/terrain/editor_property_aabb_min_max.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
#include "editor_property_aabb_min_max.h"
|
||||
#include <scene/gui/grid_container.h>
|
||||
|
||||
namespace zylann {
|
||||
|
||||
EditorPropertyAABBMinMax::EditorPropertyAABBMinMax() {
|
||||
GridContainer *grid = memnew(GridContainer);
|
||||
grid->set_columns(4);
|
||||
add_child(grid);
|
||||
|
||||
for (int i = 0; i < _spin.size(); i++) {
|
||||
if (i == 0) {
|
||||
Label *label = memnew(Label);
|
||||
label->set_text("Min");
|
||||
grid->add_child(label);
|
||||
|
||||
} else if (i == 3) {
|
||||
Label *label = memnew(Label);
|
||||
label->set_text("Max");
|
||||
grid->add_child(label);
|
||||
}
|
||||
|
||||
EditorSpinSlider *sb = memnew(EditorSpinSlider);
|
||||
sb->set_flat(true);
|
||||
sb->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
sb->connect("value_changed", callable_mp(this, &EditorPropertyAABBMinMax::_value_changed), varray(i));
|
||||
_spin[i] = sb;
|
||||
|
||||
add_focusable(sb);
|
||||
|
||||
grid->add_child(sb);
|
||||
}
|
||||
|
||||
_spin[0]->set_label("X");
|
||||
_spin[1]->set_label("Y");
|
||||
_spin[2]->set_label("Z");
|
||||
_spin[3]->set_label("X");
|
||||
_spin[4]->set_label("Y");
|
||||
_spin[5]->set_label("Z");
|
||||
|
||||
set_bottom_editor(grid);
|
||||
}
|
||||
|
||||
void EditorPropertyAABBMinMax::_set_read_only(bool p_read_only) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_spin[i]->set_read_only(p_read_only);
|
||||
}
|
||||
};
|
||||
|
||||
void EditorPropertyAABBMinMax::_value_changed(double val, int spinbox_index) {
|
||||
if (_setting) {
|
||||
return;
|
||||
}
|
||||
|
||||
AABB p;
|
||||
p.position.x = _spin[0]->get_value();
|
||||
p.position.y = _spin[1]->get_value();
|
||||
p.position.z = _spin[2]->get_value();
|
||||
p.size.x = _spin[3]->get_value() - p.position.x;
|
||||
p.size.y = _spin[4]->get_value() - p.position.y;
|
||||
p.size.z = _spin[5]->get_value() - p.position.z;
|
||||
|
||||
emit_changed(get_edited_property(), p, "");
|
||||
}
|
||||
|
||||
void EditorPropertyAABBMinMax::update_property() {
|
||||
const AABB val = get_edited_object()->get(get_edited_property());
|
||||
|
||||
_setting = true;
|
||||
|
||||
_spin[0]->set_value(val.position.x);
|
||||
_spin[1]->set_value(val.position.y);
|
||||
_spin[2]->set_value(val.position.z);
|
||||
_spin[3]->set_value(val.position.x + val.size.x);
|
||||
_spin[4]->set_value(val.position.y + val.size.y);
|
||||
_spin[5]->set_value(val.position.z + val.size.z);
|
||||
|
||||
_setting = false;
|
||||
}
|
||||
|
||||
void EditorPropertyAABBMinMax::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
const Color *colors = _get_property_colors();
|
||||
for (unsigned int i = 0; i < _spin.size(); i++) {
|
||||
_spin[i]->add_theme_color_override("label_color", colors[i % 3]);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorPropertyAABBMinMax::setup(
|
||||
double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
|
||||
for (int i = 0; i < _spin.size(); i++) {
|
||||
_spin[i]->set_min(p_min);
|
||||
_spin[i]->set_max(p_max);
|
||||
_spin[i]->set_step(p_step);
|
||||
_spin[i]->set_hide_slider(p_no_slider);
|
||||
_spin[i]->set_allow_greater(true);
|
||||
_spin[i]->set_allow_lesser(true);
|
||||
_spin[i]->set_suffix(p_suffix);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorPropertyAABBMinMax::_bind_methods() {}
|
||||
|
||||
} // namespace zylann
|
37
editor/terrain/editor_property_aabb_min_max.h
Normal file
37
editor/terrain/editor_property_aabb_min_max.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef ZYLANN_EDITOR_PROPERTY_AABB_H
|
||||
#define ZYLANN_EDITOR_PROPERTY_AABB_H
|
||||
|
||||
#include <editor/editor_inspector.h>
|
||||
#include <editor/editor_spin_slider.h>
|
||||
|
||||
#include "../../util/fixed_array.h"
|
||||
|
||||
namespace zylann {
|
||||
|
||||
// Alternative to the default AABB editor which presents it as a minimum and maximum point
|
||||
class EditorPropertyAABBMinMax : public EditorProperty {
|
||||
GDCLASS(EditorPropertyAABBMinMax, EditorProperty);
|
||||
|
||||
public:
|
||||
EditorPropertyAABBMinMax();
|
||||
|
||||
void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
|
||||
|
||||
virtual void update_property() override;
|
||||
|
||||
protected:
|
||||
virtual void _set_read_only(bool p_read_only) override;
|
||||
|
||||
private:
|
||||
void _value_changed(double p_val, int spinbox_index);
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
FixedArray<EditorSpinSlider *, 6> _spin;
|
||||
bool _setting = false;
|
||||
};
|
||||
|
||||
} // namespace zylann
|
||||
|
||||
#endif // ZYLANN_EDITOR_PROPERTY_AABB_H
|
37
editor/terrain/voxel_terrain_editor_inspector_plugin.cpp
Normal file
37
editor/terrain/voxel_terrain_editor_inspector_plugin.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "voxel_terrain_editor_inspector_plugin.h"
|
||||
#include "../../terrain/fixed_lod/voxel_terrain.h"
|
||||
#include "../../terrain/variable_lod/voxel_lod_terrain.h"
|
||||
#include "editor_property_aabb_min_max.h"
|
||||
|
||||
namespace zylann::voxel {
|
||||
|
||||
bool VoxelTerrainEditorInspectorPlugin::can_handle(Object *p_object) {
|
||||
const VoxelTerrain *vt = Object::cast_to<VoxelTerrain>(p_object);
|
||||
if (vt != nullptr) {
|
||||
return true;
|
||||
}
|
||||
const VoxelLodTerrain *vlt = Object::cast_to<VoxelLodTerrain>(p_object);
|
||||
if (vlt != nullptr) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VoxelTerrainEditorInspectorPlugin::parse_property(Object *p_object, const Variant::Type p_type,
|
||||
const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage,
|
||||
const bool p_wide) {
|
||||
if (p_type != Variant::AABB) {
|
||||
return false;
|
||||
}
|
||||
// TODO Give the same name to these properties
|
||||
if (p_path != "voxel_bounds" && p_path != "bounds") {
|
||||
return false;
|
||||
}
|
||||
// Replace default AABB editor with this one
|
||||
EditorPropertyAABBMinMax *ed = memnew(EditorPropertyAABBMinMax);
|
||||
ed->setup(-constants::MAX_VOLUME_EXTENT, constants::MAX_VOLUME_EXTENT, 1, true);
|
||||
add_property_editor(p_path, ed);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace zylann::voxel
|
18
editor/terrain/voxel_terrain_editor_inspector_plugin.h
Normal file
18
editor/terrain/voxel_terrain_editor_inspector_plugin.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef VOXEL_TERRAIN_EDITOR_INSPECTOR_PLUGIN_H
|
||||
#define VOXEL_TERRAIN_EDITOR_INSPECTOR_PLUGIN_H
|
||||
|
||||
#include <editor/editor_inspector.h>
|
||||
|
||||
namespace zylann::voxel {
|
||||
|
||||
class VoxelTerrainEditorInspectorPlugin : public EditorInspectorPlugin {
|
||||
GDCLASS(VoxelTerrainEditorInspectorPlugin, EditorInspectorPlugin)
|
||||
public:
|
||||
bool can_handle(Object *p_object) override;
|
||||
bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint,
|
||||
const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
|
||||
};
|
||||
|
||||
} // namespace zylann::voxel
|
||||
|
||||
#endif // VOXEL_TERRAIN_EDITOR_INSPECTOR_PLUGIN_H
|
@ -78,10 +78,14 @@ void VoxelTerrainEditorPlugin::_notification(int p_what) {
|
||||
VoxelServer::get_singleton().set_viewer_distance(_editor_viewer_id, 512);
|
||||
// No collision needed in editor, also it updates faster without
|
||||
VoxelServer::get_singleton().set_viewer_requires_collisions(_editor_viewer_id, false);
|
||||
|
||||
_inspector_plugin.instantiate();
|
||||
add_inspector_plugin(_inspector_plugin);
|
||||
break;
|
||||
|
||||
case NOTIFICATION_EXIT_TREE:
|
||||
VoxelServer::get_singleton().remove_viewer(_editor_viewer_id);
|
||||
remove_inspector_plugin(_inspector_plugin);
|
||||
break;
|
||||
|
||||
case NOTIFICATION_PROCESS:
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef VOXEL_TERRAIN_EDITOR_PLUGIN_H
|
||||
#define VOXEL_TERRAIN_EDITOR_PLUGIN_H
|
||||
|
||||
#include "voxel_terrain_editor_inspector_plugin.h"
|
||||
#include <editor/editor_plugin.h>
|
||||
|
||||
class MenuButton;
|
||||
@ -56,6 +57,7 @@ private:
|
||||
MenuButton *_menu_button = nullptr;
|
||||
VoxelAboutWindow *_about_window = nullptr;
|
||||
VoxelTerrainEditorTaskIndicator *_task_indicator = nullptr;
|
||||
Ref<VoxelTerrainEditorInspectorPlugin> _inspector_plugin;
|
||||
};
|
||||
|
||||
} // namespace zylann::voxel
|
||||
|
Loading…
x
Reference in New Issue
Block a user