mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
Add OccluderShapePolygon
Add OccluderShapePolygon, glue to Occluder and gizmos etc.
This commit is contained in:
parent
b5eef640e1
commit
8ea20f5fdd
32 changed files with 2065 additions and 84 deletions
|
@ -62,6 +62,7 @@
|
|||
#include "scene/resources/cylinder_shape.h"
|
||||
#include "scene/resources/height_map_shape.h"
|
||||
#include "scene/resources/occluder_shape.h"
|
||||
#include "scene/resources/occluder_shape_polygon.h"
|
||||
#include "scene/resources/plane_shape.h"
|
||||
#include "scene/resources/primitive_meshes.h"
|
||||
#include "scene/resources/ray_shape.h"
|
||||
|
@ -5000,6 +5001,8 @@ OccluderGizmoPlugin::OccluderGizmoPlugin() {
|
|||
Color color_occluder = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/occluder", Color(1.0, 0.0, 1.0));
|
||||
create_material("occluder", color_occluder, false, true, false);
|
||||
|
||||
create_material("occluder_poly", Color(1, 1, 1, 1), false, false, true);
|
||||
|
||||
create_handle_material("occluder_handle");
|
||||
create_handle_material("extra_handle", false, SpatialEditor::get_singleton()->get_icon("EditorInternalHandle", "EditorIcons"));
|
||||
}
|
||||
|
@ -5046,6 +5049,15 @@ String OccluderSpatialGizmo::get_handle_name(int p_idx) const {
|
|||
}
|
||||
}
|
||||
|
||||
const OccluderShapePolygon *occ_poly = get_occluder_shape_poly();
|
||||
if (occ_poly) {
|
||||
if (p_idx < occ_poly->_poly_pts_local_raw.size()) {
|
||||
return "Poly Point " + itos(p_idx);
|
||||
} else {
|
||||
return "Hole Point " + itos(p_idx - occ_poly->_poly_pts_local_raw.size());
|
||||
}
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
|
@ -5063,6 +5075,19 @@ Variant OccluderSpatialGizmo::get_handle_value(int p_idx) {
|
|||
}
|
||||
}
|
||||
|
||||
const OccluderShapePolygon *occ_poly = get_occluder_shape_poly();
|
||||
if (occ_poly) {
|
||||
if (p_idx < occ_poly->_poly_pts_local_raw.size()) {
|
||||
return occ_poly->_poly_pts_local_raw[p_idx];
|
||||
} else {
|
||||
p_idx -= occ_poly->_poly_pts_local_raw.size();
|
||||
if (p_idx < occ_poly->_hole_pts_local_raw.size()) {
|
||||
return occ_poly->_hole_pts_local_raw[p_idx];
|
||||
}
|
||||
return Vector2(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5145,16 +5170,63 @@ void OccluderSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
OccluderShapePolygon *occ_poly = get_occluder_shape_poly();
|
||||
if (occ_poly) {
|
||||
Vector3 pt_local;
|
||||
|
||||
bool hole = p_idx >= occ_poly->_poly_pts_local_raw.size();
|
||||
if (hole) {
|
||||
p_idx -= occ_poly->_poly_pts_local_raw.size();
|
||||
if (p_idx >= occ_poly->_hole_pts_local_raw.size()) {
|
||||
return;
|
||||
}
|
||||
pt_local = OccluderShapePolygon::_vec2to3(occ_poly->_hole_pts_local_raw[p_idx]);
|
||||
} else {
|
||||
pt_local = OccluderShapePolygon::_vec2to3(occ_poly->_poly_pts_local_raw[p_idx]);
|
||||
}
|
||||
|
||||
Vector3 pt_world = tr.xform(pt_local);
|
||||
|
||||
// get a normal from the global transform
|
||||
Plane plane(Vector3(0, 0, 0), Vector3(0, 0, 1));
|
||||
plane = tr.xform(plane);
|
||||
|
||||
// construct the plane that the 2d portal is defined in
|
||||
plane = Plane(pt_world, plane.normal);
|
||||
|
||||
Vector3 inters;
|
||||
|
||||
if (plane.intersects_ray(ray_from, ray_dir, &inters)) {
|
||||
// back calculate from the 3d intersection to the 2d portal plane
|
||||
inters = tr_inv.xform(inters);
|
||||
|
||||
// snapping will be in 2d for portals, and the scale may make less sense,
|
||||
// but better to offer at least some functionality
|
||||
if (SpatialEditor::get_singleton()->is_snap_enabled()) {
|
||||
float snap = SpatialEditor::get_singleton()->get_translate_snap();
|
||||
inters.snap(Vector3(snap, snap, snap));
|
||||
}
|
||||
|
||||
if (hole) {
|
||||
occ_poly->set_hole_point(p_idx, Vector2(inters.x, inters.y));
|
||||
} else {
|
||||
occ_poly->set_polygon_point(p_idx, Vector2(inters.x, inters.y));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OccluderSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
|
||||
UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
|
||||
|
||||
OccluderShapeSphere *occ_sphere = get_occluder_shape_sphere();
|
||||
if (occ_sphere) {
|
||||
Vector<Plane> spheres = occ_sphere->get_spheres();
|
||||
int num_spheres = spheres.size();
|
||||
|
||||
UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
|
||||
|
||||
if (p_idx >= num_spheres) {
|
||||
p_idx -= num_spheres;
|
||||
|
||||
|
@ -5170,24 +5242,49 @@ void OccluderSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bo
|
|||
ur->commit_action();
|
||||
_occluder->property_list_changed_notify();
|
||||
}
|
||||
|
||||
OccluderShapePolygon *occ_poly = get_occluder_shape_poly();
|
||||
if (occ_poly) {
|
||||
if (p_idx < occ_poly->_poly_pts_local_raw.size()) {
|
||||
ur->create_action(TTR("Set Occluder Polygon Point Position"));
|
||||
ur->add_do_method(occ_poly, "set_polygon_point", p_idx, occ_poly->_poly_pts_local_raw[p_idx]);
|
||||
ur->add_undo_method(occ_poly, "set_polygon_point", p_idx, p_restore);
|
||||
ur->commit_action();
|
||||
_occluder->property_list_changed_notify();
|
||||
} else {
|
||||
p_idx -= occ_poly->_poly_pts_local_raw.size();
|
||||
if (p_idx < occ_poly->_hole_pts_local_raw.size()) {
|
||||
ur->create_action(TTR("Set Occluder Hole Point Position"));
|
||||
ur->add_do_method(occ_poly, "set_hole_point", p_idx, occ_poly->_hole_pts_local_raw[p_idx]);
|
||||
ur->add_undo_method(occ_poly, "set_hole_point", p_idx, p_restore);
|
||||
ur->commit_action();
|
||||
_occluder->property_list_changed_notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OccluderShapeSphere *OccluderSpatialGizmo::get_occluder_shape_sphere() {
|
||||
if (!_occluder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Ref<OccluderShape> rshape = _occluder->get_shape();
|
||||
if (rshape.is_null() || !rshape.is_valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OccluderShape *shape = rshape.ptr();
|
||||
OccluderShapeSphere *occ_sphere = Object::cast_to<OccluderShapeSphere>(shape);
|
||||
OccluderShapeSphere *occ_sphere = Object::cast_to<OccluderShapeSphere>(get_occluder_shape());
|
||||
return occ_sphere;
|
||||
}
|
||||
|
||||
const OccluderShapePolygon *OccluderSpatialGizmo::get_occluder_shape_poly() const {
|
||||
const OccluderShapePolygon *occ_poly = Object::cast_to<OccluderShapePolygon>(get_occluder_shape());
|
||||
return occ_poly;
|
||||
}
|
||||
|
||||
OccluderShapePolygon *OccluderSpatialGizmo::get_occluder_shape_poly() {
|
||||
OccluderShapePolygon *occ_poly = Object::cast_to<OccluderShapePolygon>(get_occluder_shape());
|
||||
return occ_poly;
|
||||
}
|
||||
|
||||
const OccluderShapeSphere *OccluderSpatialGizmo::get_occluder_shape_sphere() const {
|
||||
const OccluderShapeSphere *occ_sphere = Object::cast_to<OccluderShapeSphere>(get_occluder_shape());
|
||||
return occ_sphere;
|
||||
}
|
||||
|
||||
const OccluderShape *OccluderSpatialGizmo::get_occluder_shape() const {
|
||||
if (!_occluder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -5197,9 +5294,20 @@ const OccluderShapeSphere *OccluderSpatialGizmo::get_occluder_shape_sphere() con
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const OccluderShape *shape = rshape.ptr();
|
||||
const OccluderShapeSphere *occ_sphere = Object::cast_to<OccluderShapeSphere>(shape);
|
||||
return occ_sphere;
|
||||
return rshape.ptr();
|
||||
}
|
||||
|
||||
OccluderShape *OccluderSpatialGizmo::get_occluder_shape() {
|
||||
if (!_occluder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Ref<OccluderShape> rshape = _occluder->get_shape();
|
||||
if (rshape.is_null() || !rshape.is_valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return rshape.ptr();
|
||||
}
|
||||
|
||||
void OccluderSpatialGizmo::redraw() {
|
||||
|
@ -5258,9 +5366,90 @@ void OccluderSpatialGizmo::redraw() {
|
|||
add_handles(handles, material_handle);
|
||||
add_handles(radius_handles, material_extra_handle, false, true);
|
||||
}
|
||||
|
||||
const OccluderShapePolygon *occ_poly = get_occluder_shape_poly();
|
||||
if (occ_poly) {
|
||||
// main poly
|
||||
_redraw_poly(false, occ_poly->_poly_pts_local, occ_poly->_poly_pts_local_raw);
|
||||
|
||||
// hole
|
||||
_redraw_poly(true, occ_poly->_hole_pts_local, occ_poly->_hole_pts_local_raw);
|
||||
}
|
||||
}
|
||||
|
||||
void OccluderSpatialGizmo::_redraw_poly(bool p_hole, const Vector<Vector2> &p_pts, const PoolVector<Vector2> &p_pts_raw) {
|
||||
PoolVector<Vector3> pts_edge;
|
||||
PoolVector<Color> cols;
|
||||
|
||||
Color col_front = _color_poly_front;
|
||||
Color col_back = _color_poly_back;
|
||||
|
||||
if (p_hole) {
|
||||
col_front = _color_hole;
|
||||
col_back = _color_hole;
|
||||
}
|
||||
|
||||
if (p_pts.size() > 2) {
|
||||
Vector3 pt_first = OccluderShapePolygon::_vec2to3(p_pts[0]);
|
||||
Vector3 pt_prev = OccluderShapePolygon::_vec2to3(p_pts[p_pts.size() - 1]);
|
||||
for (int n = 0; n < p_pts.size(); n++) {
|
||||
Vector3 pt_curr = OccluderShapePolygon::_vec2to3(p_pts[n]);
|
||||
pts_edge.push_back(pt_first);
|
||||
pts_edge.push_back(pt_prev);
|
||||
pts_edge.push_back(pt_curr);
|
||||
cols.push_back(col_front);
|
||||
cols.push_back(col_front);
|
||||
cols.push_back(col_front);
|
||||
|
||||
pts_edge.push_back(pt_first);
|
||||
pts_edge.push_back(pt_curr);
|
||||
pts_edge.push_back(pt_prev);
|
||||
cols.push_back(col_back);
|
||||
cols.push_back(col_back);
|
||||
cols.push_back(col_back);
|
||||
|
||||
pt_prev = pt_curr;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the handles separately because these must correspond to the raw points
|
||||
// for editing
|
||||
Vector<Vector3> handles;
|
||||
for (int n = 0; n < p_pts_raw.size(); n++) {
|
||||
Vector3 pt = OccluderShapePolygon::_vec2to3(p_pts_raw[n]);
|
||||
handles.push_back(pt);
|
||||
}
|
||||
|
||||
// poly itself
|
||||
{
|
||||
if (pts_edge.size() > 2) {
|
||||
Ref<ArrayMesh> mesh = memnew(ArrayMesh);
|
||||
Array array;
|
||||
array.resize(Mesh::ARRAY_MAX);
|
||||
array[Mesh::ARRAY_VERTEX] = pts_edge;
|
||||
array[Mesh::ARRAY_COLOR] = cols;
|
||||
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array);
|
||||
|
||||
Ref<Material> material_poly = gizmo_plugin->get_material("occluder_poly", this);
|
||||
add_mesh(mesh, false, Ref<SkinReference>(), material_poly);
|
||||
}
|
||||
|
||||
// handles
|
||||
if (!p_hole) {
|
||||
Ref<Material> material_handle = gizmo_plugin->get_material("occluder_handle", this);
|
||||
add_handles(handles, material_handle);
|
||||
} else {
|
||||
Ref<Material> material_extra_handle = gizmo_plugin->get_material("extra_handle", this);
|
||||
add_handles(handles, material_extra_handle, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OccluderSpatialGizmo::OccluderSpatialGizmo(Occluder *p_occluder) {
|
||||
_occluder = p_occluder;
|
||||
set_spatial_node(p_occluder);
|
||||
|
||||
_color_poly_front = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/occluder_polygon_front", Color(1.0, 0.25, 0.8, 0.3));
|
||||
_color_poly_back = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/occluder_polygon_back", Color(0.85, 0.1, 1.0, 0.3));
|
||||
_color_hole = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/occluder_hole", Color(0.0, 1.0, 1.0, 0.3));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue