Implement Vector4, Vector4i, Projection

Implement built-in classes Vector4, Vector4i and Projection.

* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.

These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.

**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
This commit is contained in:
reduz
2022-07-20 01:11:13 +02:00
committed by Juan Linietsky
parent fe929d4787
commit 455c06ecd4
123 changed files with 4139 additions and 594 deletions
+306
View File
@@ -2623,6 +2623,186 @@ EditorPropertyQuaternion::EditorPropertyQuaternion() {
set_label_reference(spin[0]); //show text and buttons around this
}
}
///////////////////// VECTOR4 /////////////////////////
void EditorPropertyVector4::_set_read_only(bool p_read_only) {
for (int i = 0; i < 4; i++) {
spin[i]->set_read_only(p_read_only);
}
};
void EditorPropertyVector4::_value_changed(double val, const String &p_name) {
if (setting) {
return;
}
Vector4 p;
p.x = spin[0]->get_value();
p.y = spin[1]->get_value();
p.z = spin[2]->get_value();
p.w = spin[3]->get_value();
emit_changed(get_edited_property(), p, p_name);
}
void EditorPropertyVector4::update_property() {
Vector4 val = get_edited_object()->get(get_edited_property());
setting = true;
spin[0]->set_value(val.x);
spin[1]->set_value(val.y);
spin[2]->set_value(val.z);
spin[3]->set_value(val.w);
setting = false;
}
void EditorPropertyVector4::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
const Color *colors = _get_property_colors();
for (int i = 0; i < 4; i++) {
spin[i]->add_theme_color_override("label_color", colors[i]);
}
} break;
}
}
void EditorPropertyVector4::_bind_methods() {
}
void EditorPropertyVector4::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 4; 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);
// Vector4 is inherently unitless, however someone may want to use it as
// a generic way to store 4 values, so we'll still respect the suffix.
spin[i]->set_suffix(p_suffix);
}
}
EditorPropertyVector4::EditorPropertyVector4() {
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
BoxContainer *bc;
if (horizontal) {
bc = memnew(HBoxContainer);
add_child(bc);
set_bottom_editor(bc);
} else {
bc = memnew(VBoxContainer);
add_child(bc);
}
static const char *desc[4] = { "x", "y", "z", "w" };
for (int i = 0; i < 4; i++) {
spin[i] = memnew(EditorSpinSlider);
spin[i]->set_flat(true);
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector4::_value_changed), varray(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
}
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
}
///////////////////// VECTOR4I /////////////////////////
void EditorPropertyVector4i::_set_read_only(bool p_read_only) {
for (int i = 0; i < 4; i++) {
spin[i]->set_read_only(p_read_only);
}
};
void EditorPropertyVector4i::_value_changed(double val, const String &p_name) {
if (setting) {
return;
}
Vector4i p;
p.x = spin[0]->get_value();
p.y = spin[1]->get_value();
p.z = spin[2]->get_value();
p.w = spin[3]->get_value();
emit_changed(get_edited_property(), p, p_name);
}
void EditorPropertyVector4i::update_property() {
Vector4i val = get_edited_object()->get(get_edited_property());
setting = true;
spin[0]->set_value(val.x);
spin[1]->set_value(val.y);
spin[2]->set_value(val.z);
spin[3]->set_value(val.w);
setting = false;
}
void EditorPropertyVector4i::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
const Color *colors = _get_property_colors();
for (int i = 0; i < 4; i++) {
spin[i]->add_theme_color_override("label_color", colors[i]);
}
} break;
}
}
void EditorPropertyVector4i::_bind_methods() {
}
void EditorPropertyVector4i::setup(double p_min, double p_max, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 4; i++) {
spin[i]->set_min(p_min);
spin[i]->set_max(p_max);
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);
}
}
EditorPropertyVector4i::EditorPropertyVector4i() {
bool horizontal = EDITOR_GET("interface/inspector/horizontal_vector_types_editing");
BoxContainer *bc;
if (horizontal) {
bc = memnew(HBoxContainer);
add_child(bc);
set_bottom_editor(bc);
} else {
bc = memnew(VBoxContainer);
add_child(bc);
}
static const char *desc[4] = { "x", "y", "z", "w" };
for (int i = 0; i < 4; i++) {
spin[i] = memnew(EditorSpinSlider);
spin[i]->set_flat(true);
spin[i]->set_label(desc[i]);
bc->add_child(spin[i]);
add_focusable(spin[i]);
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyVector4i::_value_changed), varray(desc[i]));
if (horizontal) {
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
}
}
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
}
///////////////////// AABB /////////////////////////
@@ -2986,6 +3166,111 @@ EditorPropertyTransform3D::EditorPropertyTransform3D() {
set_bottom_editor(g);
}
///////////////////// PROJECTION /////////////////////////
void EditorPropertyProjection::_set_read_only(bool p_read_only) {
for (int i = 0; i < 12; i++) {
spin[i]->set_read_only(p_read_only);
}
};
void EditorPropertyProjection::_value_changed(double val, const String &p_name) {
if (setting) {
return;
}
Projection p;
p.matrix[0][0] = spin[0]->get_value();
p.matrix[0][1] = spin[1]->get_value();
p.matrix[0][2] = spin[2]->get_value();
p.matrix[0][3] = spin[3]->get_value();
p.matrix[1][0] = spin[4]->get_value();
p.matrix[1][1] = spin[5]->get_value();
p.matrix[1][2] = spin[6]->get_value();
p.matrix[1][3] = spin[7]->get_value();
p.matrix[2][0] = spin[8]->get_value();
p.matrix[2][1] = spin[9]->get_value();
p.matrix[2][2] = spin[10]->get_value();
p.matrix[2][3] = spin[11]->get_value();
p.matrix[3][0] = spin[12]->get_value();
p.matrix[3][1] = spin[13]->get_value();
p.matrix[3][2] = spin[14]->get_value();
p.matrix[3][3] = spin[15]->get_value();
emit_changed(get_edited_property(), p, p_name);
}
void EditorPropertyProjection::update_property() {
update_using_transform(get_edited_object()->get(get_edited_property()));
}
void EditorPropertyProjection::update_using_transform(Projection p_transform) {
setting = true;
spin[0]->set_value(p_transform.matrix[0][0]);
spin[1]->set_value(p_transform.matrix[0][1]);
spin[2]->set_value(p_transform.matrix[0][2]);
spin[3]->set_value(p_transform.matrix[0][3]);
spin[4]->set_value(p_transform.matrix[1][0]);
spin[5]->set_value(p_transform.matrix[1][1]);
spin[6]->set_value(p_transform.matrix[1][2]);
spin[7]->set_value(p_transform.matrix[1][3]);
spin[8]->set_value(p_transform.matrix[2][0]);
spin[9]->set_value(p_transform.matrix[2][1]);
spin[10]->set_value(p_transform.matrix[2][2]);
spin[11]->set_value(p_transform.matrix[2][3]);
spin[12]->set_value(p_transform.matrix[3][0]);
spin[13]->set_value(p_transform.matrix[3][1]);
spin[14]->set_value(p_transform.matrix[3][2]);
spin[15]->set_value(p_transform.matrix[3][3]);
setting = false;
}
void EditorPropertyProjection::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
const Color *colors = _get_property_colors();
for (int i = 0; i < 16; i++) {
spin[i]->add_theme_color_override("label_color", colors[i % 4]);
}
} break;
}
}
void EditorPropertyProjection::_bind_methods() {
}
void EditorPropertyProjection::setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix) {
for (int i = 0; i < 16; 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);
if (i % 4 == 3) {
spin[i]->set_suffix(p_suffix);
}
}
}
EditorPropertyProjection::EditorPropertyProjection() {
GridContainer *g = memnew(GridContainer);
g->set_columns(4);
add_child(g);
static const char *desc[16] = { "xx", "xy", "xz", "xw", "yx", "yy", "yz", "yw", "zx", "zy", "zz", "zw", "wx", "wy", "wz", "ww" };
for (int i = 0; i < 16; i++) {
spin[i] = memnew(EditorSpinSlider);
spin[i]->set_label(desc[i]);
spin[i]->set_flat(true);
g->add_child(spin[i]);
spin[i]->set_h_size_flags(SIZE_EXPAND_FILL);
add_focusable(spin[i]);
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyProjection::_value_changed), varray(desc[i]));
}
set_bottom_editor(g);
}
////////////// COLOR PICKER //////////////////////
void EditorPropertyColor::_set_read_only(bool p_read_only) {
@@ -3950,6 +4235,20 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
editor->setup(hint.min, hint.max, hint.hide_slider, p_hint == PROPERTY_HINT_LINK, hint.suffix);
return editor;
} break;
case Variant::VECTOR4: {
EditorPropertyVector4 *editor = memnew(EditorPropertyVector4);
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
return editor;
} break;
case Variant::VECTOR4I: {
EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
editor->setup(hint.min, hint.max, hint.hide_slider, hint.suffix);
return editor;
} break;
case Variant::TRANSFORM2D: {
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
@@ -3987,6 +4286,13 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
return editor;
} break;
case Variant::PROJECTION: {
EditorPropertyProjection *editor = memnew(EditorPropertyProjection);
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.suffix);
return editor;
} break;
// misc types
+52
View File
@@ -636,6 +636,40 @@ public:
EditorPropertyQuaternion();
};
class EditorPropertyVector4 : public EditorProperty {
GDCLASS(EditorPropertyVector4, EditorProperty);
EditorSpinSlider *spin[4];
bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
virtual void _set_read_only(bool p_read_only) override;
void _notification(int p_what);
static void _bind_methods();
public:
virtual void update_property() override;
void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyVector4();
};
class EditorPropertyVector4i : public EditorProperty {
GDCLASS(EditorPropertyVector4i, EditorProperty);
EditorSpinSlider *spin[4];
bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
virtual void _set_read_only(bool p_read_only) override;
void _notification(int p_what);
static void _bind_methods();
public:
virtual void update_property() override;
void setup(double p_min, double p_max, bool p_no_slider, const String &p_suffix = String());
EditorPropertyVector4i();
};
class EditorPropertyAABB : public EditorProperty {
GDCLASS(EditorPropertyAABB, EditorProperty);
EditorSpinSlider *spin[6];
@@ -705,6 +739,24 @@ public:
EditorPropertyTransform3D();
};
class EditorPropertyProjection : public EditorProperty {
GDCLASS(EditorPropertyProjection, EditorProperty);
EditorSpinSlider *spin[16];
bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
virtual void _set_read_only(bool p_read_only) override;
void _notification(int p_what);
static void _bind_methods();
public:
virtual void update_property() override;
virtual void update_using_transform(Projection p_transform);
void setup(double p_min, double p_max, double p_step, bool p_no_slider, const String &p_suffix = String());
EditorPropertyProjection();
};
class EditorPropertyColor : public EditorProperty {
GDCLASS(EditorPropertyColor, EditorProperty);
ColorPickerButton *picker = nullptr;
+18
View File
@@ -948,6 +948,18 @@ void EditorPropertyDictionary::update_property() {
editor->setup(-100000, 100000, true);
prop = editor;
} break;
case Variant::VECTOR4: {
EditorPropertyVector4 *editor = memnew(EditorPropertyVector4);
editor->setup(-100000, 100000, default_float_step, true);
prop = editor;
} break;
case Variant::VECTOR4I: {
EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
editor->setup(-100000, 100000, true);
prop = editor;
} break;
case Variant::TRANSFORM2D: {
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
@@ -984,6 +996,12 @@ void EditorPropertyDictionary::update_property() {
editor->setup(-100000, 100000, default_float_step, true);
prop = editor;
} break;
case Variant::PROJECTION: {
EditorPropertyProjection *editor = memnew(EditorPropertyProjection);
editor->setup(-100000, 100000, default_float_step, true);
prop = editor;
} break;
// Miscellaneous types.
+3 -3
View File
@@ -33,8 +33,8 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/input/input_map.h"
#include "core/math/camera_matrix.h"
#include "core/math/math_funcs.h"
#include "core/math/projection.h"
#include "core/os/keyboard.h"
#include "core/templates/sort_array.h"
#include "editor/debugger/editor_debugger_node.h"
@@ -642,7 +642,7 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayRe
}
Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
CameraMatrix cm;
Projection cm;
if (orthogonal) {
cm.set_orthogonal(camera->get_size(), get_size().aspect(), get_znear() + p_vector3.z, get_zfar());
} else {
@@ -6639,7 +6639,7 @@ void Node3DEditor::_finish_grid() {
}
void Node3DEditor::update_grid() {
const Camera3D::Projection current_projection = viewports[0]->camera->get_projection();
const Camera3D::ProjectionType current_projection = viewports[0]->camera->get_projection();
if (current_projection != grid_camera_last_update_perspective) {
grid_init_draw = false; // redraw
+1 -1
View File
@@ -560,7 +560,7 @@ private:
bool grid_enable[3]; //should be always visible if true
bool grid_enabled = false;
bool grid_init_draw = false;
Camera3D::Projection grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
Camera3D::ProjectionType grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
Vector3 grid_camera_last_update_position = Vector3();
Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3], axis_gizmo[3];
+4 -4
View File
@@ -156,7 +156,7 @@ protected:
pinfo.type = Variant::VECTOR3I;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC4: {
pinfo.type = Variant::PACKED_INT32_ARRAY;
pinfo.type = Variant::VECTOR4I;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2I: {
pinfo.type = Variant::RECT2I;
@@ -171,7 +171,7 @@ protected:
pinfo.type = Variant::VECTOR3I;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC4: {
pinfo.type = Variant::PACKED_INT32_ARRAY;
pinfo.type = Variant::VECTOR4I;
} break;
case RS::GLOBAL_VAR_TYPE_FLOAT: {
pinfo.type = Variant::FLOAT;
@@ -183,7 +183,7 @@ protected:
pinfo.type = Variant::VECTOR3;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
pinfo.type = Variant::QUATERNION;
pinfo.type = Variant::VECTOR4;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
pinfo.type = Variant::RECT2;
@@ -204,7 +204,7 @@ protected:
pinfo.type = Variant::TRANSFORM3D;
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
pinfo.type = Variant::PACKED_INT32_ARRAY;
pinfo.type = Variant::PROJECTION;
} break;
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
pinfo.type = Variant::OBJECT;