summaryrefslogtreecommitdiff
path: root/editor/plugins
diff options
context:
space:
mode:
authorPrzemysław Gołąb (n-pigeon) <golab.przemyslaw@gmail.com>2017-09-21 23:11:56 +0200
committerPrzemysław Gołąb (n-pigeon) <golab.przemyslaw@gmail.com>2017-09-26 20:39:41 +0200
commitaad234d5ac53c03e8c615ebbae64100aa57a0817 (patch)
tree0195070cb787bea79646aaa079764ef41b2b0927 /editor/plugins
parent59c3f61d57e745db2eb5ee2eab9c4cac17105f7b (diff)
Scale editing Gizmo for Spatial Editor
Added support for axis locked scaling with handles, supports both world and local space. Local space recommended for most editing tasks. Also fixed some small bugs, polished Gizmo looks and cleaned up some dead code. Happy scaling! :)
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp238
-rw-r--r--editor/plugins/spatial_editor_plugin.h6
2 files changed, 190 insertions, 54 deletions
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 5ddd1c5b62..7b2361242f 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -49,13 +49,15 @@
#define DISTANCE_DEFAULT 4
-#define GIZMO_ARROW_SIZE 0.3
+#define GIZMO_ARROW_SIZE 0.35
#define GIZMO_RING_HALF_WIDTH 0.1
//#define GIZMO_SCALE_DEFAULT 0.28
#define GIZMO_SCALE_DEFAULT 0.15
#define GIZMO_PLANE_SIZE 0.2
#define GIZMO_PLANE_DST 0.3
-#define GIZMO_CIRCLE_SIZE 0.9
+#define GIZMO_CIRCLE_SIZE 1.1
+#define GIZMO_SCALE_OFFSET (GIZMO_CIRCLE_SIZE + 0.3)
+#define GIZMO_ARROW_OFFSET (GIZMO_CIRCLE_SIZE + 0.3)
#define ZOOM_MIN_DISTANCE 0.001
#define ZOOM_MULTIPLIER 1.08
@@ -538,8 +540,6 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- //Vector3 center;
- //int nc=0;
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Spatial *sp = Object::cast_to<Spatial>(E->get());
@@ -551,14 +551,8 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) {
continue;
se->original = se->sp->get_global_transform();
- //center+=se->original.origin;
- //nc++;
+ se->original_local = se->sp->get_transform();
}
-
- /*
- if (nc)
- _edit.center=center/float(nc);
- */
}
static int _get_key_modifier_setting(const String &p_property) {
@@ -609,7 +603,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig
for (int i = 0; i < 3; i++) {
- Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs;
+ Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs * (GIZMO_ARROW_OFFSET + (GIZMO_ARROW_SIZE * 0.5));
float grabber_radius = gs * GIZMO_ARROW_SIZE;
Vector3 r;
@@ -624,7 +618,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig
}
bool is_plane_translate = false;
- // second try
+ // plane select
if (col_axis == -1) {
col_d = 1e20;
@@ -710,6 +704,43 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig
}
}
+ if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE) {
+
+ int col_axis = -1;
+ float col_d = 1e20;
+
+ for (int i = 0; i < 3; i++) {
+
+ Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs * GIZMO_SCALE_OFFSET;
+ float grabber_radius = gs * GIZMO_ARROW_SIZE;
+
+ Vector3 r;
+
+ if (Geometry::segment_intersects_sphere(ray_pos, ray_pos + ray * 10000.0, grabber_pos, grabber_radius, &r)) {
+ float d = r.distance_to(ray_pos);
+ if (d < col_d) {
+ col_d = d;
+ col_axis = i;
+ }
+ }
+ }
+
+ if (col_axis != -1) {
+
+ if (p_highlight_only) {
+
+ spatial_editor->select_gizmo_highlight_axis(col_axis + 9);
+
+ } else {
+ //handle scale
+ _edit.mode = TRANSFORM_SCALE;
+ _compute_edit(Point2(p_screenpos.x, p_screenpos.y));
+ _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis);
+ }
+ return true;
+ }
+ }
+
if (p_highlight_only)
spatial_editor->select_gizmo_highlight_axis(-1);
@@ -1182,7 +1213,28 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
case TRANSFORM_SCALE: {
- Plane plane = Plane(_edit.center, _get_camera_normal());
+ Vector3 motion_mask;
+ Plane plane;
+ bool plane_mv;
+
+ switch (_edit.plane) {
+ case TRANSFORM_VIEW:
+ motion_mask = Vector3(0, 0, 0);
+ plane = Plane(_edit.center, _get_camera_normal());
+ break;
+ case TRANSFORM_X_AXIS:
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(0);
+ plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
+ break;
+ case TRANSFORM_Y_AXIS:
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(1);
+ plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
+ break;
+ case TRANSFORM_Z_AXIS:
+ motion_mask = spatial_editor->get_gizmo_transform().basis.get_axis(2);
+ plane = Plane(_edit.center, motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
+ break;
+ }
Vector3 intersection;
if (!plane.intersects_ray(ray_pos, ray, &intersection))
@@ -1192,42 +1244,78 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (!plane.intersects_ray(_edit.click_ray_pos, _edit.click_ray, &click))
break;
- float center_click_dist = click.distance_to(_edit.center);
- float center_inters_dist = intersection.distance_to(_edit.center);
- if (center_click_dist == 0)
- break;
+ Vector3 motion = intersection - click;
+ print_line(String(intersection) + " --- " + String(click));
+ if (motion_mask != Vector3()) {
- float scale = (center_inters_dist / center_click_dist) * 100.0;
+ motion = motion_mask.dot(motion) * motion_mask;
+ } else {
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ float center_click_dist = click.distance_to(_edit.center);
+ float center_inters_dist = intersection.distance_to(_edit.center);
+ if (center_click_dist == 0)
+ break;
- scale = Math::stepify(scale, spatial_editor->get_scale_snap());
+ float scale = center_inters_dist - center_click_dist;
+ motion = Vector3(scale, scale, scale);
}
- set_message(vformat(TTR("Scaling to %s%%."), String::num(scale, 1)));
- scale /= 100.0;
+ List<Node *> &selection = editor_selection->get_selected_node_list();
- Transform r;
- r.basis.scale(Vector3(scale, scale, scale));
+ bool local_coords = (spatial_editor->are_local_coords_enabled() && motion_mask != Vector3()); // Disable local transformation for TRANSFORM_VIEW
- List<Node *> &selection = editor_selection->get_selected_node_list();
+ float snap = 0;
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+
+ snap = spatial_editor->get_scale_snap() / 100;
+ }
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Spatial *sp = Object::cast_to<Spatial>(E->get());
- if (!sp)
+ if (!sp) {
continue;
+ }
SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
+ if (!se) {
continue;
+ }
Transform original = se->original;
-
+ Transform original_local = se->original_local;
Transform base = Transform(Basis(), _edit.center);
- Transform t = base * (r * (base.inverse() * original));
+ Transform t;
+ Vector3 local_scale;
- sp->set_global_transform(t);
+ if (local_coords) {
+
+ Basis g = original.basis.orthonormalized();
+ Vector3 local_motion = g.inverse().xform(motion);
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ local_motion.snap(Vector3(snap, snap, snap));
+ }
+
+ local_scale = original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1));
+
+ } else {
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ motion.snap(Vector3(snap, snap, snap));
+ }
+
+ Transform r;
+ r.basis.scale(motion + Vector3(1, 1, 1));
+ t = base * (r * (base.inverse() * original));
+ }
+
+ // Apply scale
+ if (local_coords) {
+ sp->set_scale(local_scale);
+ } else {
+ sp->set_global_transform(t);
+ }
}
surface->update();
@@ -2271,6 +2359,14 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
//VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
VS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i], layer);
+
+ scale_gizmo_instance[i] = VS::get_singleton()->instance_create();
+ VS::get_singleton()->instance_set_base(scale_gizmo_instance[i], spatial_editor->get_scale_gizmo(i)->get_rid());
+ VS::get_singleton()->instance_set_scenario(scale_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
+ VS::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false);
+ //VS::get_singleton()->instance_geometry_set_flag(scale_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
+ VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
+ VS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer);
}
}
@@ -2280,6 +2376,7 @@ void SpatialEditorViewport::_finish_gizmo_instances() {
VS::get_singleton()->free(move_gizmo_instance[i]);
VS::get_singleton()->free(move_plane_gizmo_instance[i]);
VS::get_singleton()->free(rotate_gizmo_instance[i]);
+ VS::get_singleton()->free(scale_gizmo_instance[i]);
}
}
void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {
@@ -2374,6 +2471,8 @@ void SpatialEditorViewport::update_transform_gizmo_view() {
VisualServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE));
VisualServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform);
VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE));
+ VisualServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform);
+ VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE));
}
}
@@ -3259,6 +3358,7 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) {
move_gizmo[i]->surface_set_material(0, i == p_axis ? gizmo_hl : gizmo_color[i]);
move_plane_gizmo[i]->surface_set_material(0, (i + 6) == p_axis ? gizmo_hl : plane_gizmo_color[i]);
rotate_gizmo[i]->surface_set_material(0, (i + 3) == p_axis ? gizmo_hl : gizmo_color[i]);
+ scale_gizmo[i]->surface_set_material(0, (i + 9) == p_axis ? gizmo_hl : gizmo_color[i]);
}
}
@@ -3269,7 +3369,7 @@ void SpatialEditor::update_transform_gizmo() {
bool first = true;
Basis gizmo_basis;
- bool local_gizmo_coords = transform_menu->get_popup()->is_item_checked(transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS));
+ bool local_gizmo_coords = are_local_coords_enabled();
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -3720,10 +3820,6 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
void SpatialEditor::_init_indicators() {
- //RID mat = VisualServer::get_singleton()->fixed_material_create();
- ///VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA,true);
- //VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true);
-
{
indicator_mat.instance();
@@ -3835,6 +3931,7 @@ void SpatialEditor::_init_indicators() {
move_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
move_plane_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
rotate_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
+ scale_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
Ref<SpatialMaterial> mat = memnew(SpatialMaterial);
mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
@@ -3857,25 +3954,25 @@ void SpatialEditor::_init_indicators() {
Vector3 ivec3;
ivec3[(i + 2) % 3] = 1;
+ //translate
{
Ref<SurfaceTool> surftool = memnew(SurfaceTool);
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
- //translate
-
+ // Arrow profile
const int arrow_points = 5;
Vector3 arrow[5] = {
nivec * 0.0 + ivec * 0.0,
nivec * 0.01 + ivec * 0.0,
- nivec * 0.01 + ivec * 1.0,
- nivec * 0.1 + ivec * 1.0,
- nivec * 0.0 + ivec * (1 + GIZMO_ARROW_SIZE),
+ nivec * 0.01 + ivec * GIZMO_ARROW_OFFSET,
+ nivec * 0.065 + ivec * GIZMO_ARROW_OFFSET,
+ nivec * 0.0 + ivec * (GIZMO_ARROW_OFFSET + GIZMO_ARROW_SIZE),
};
int arrow_sides = 6;
- for (int k = 0; k < 7; k++) {
+ for (int k = 0; k < 6; k++) {
Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides);
Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides);
@@ -3902,7 +3999,7 @@ void SpatialEditor::_init_indicators() {
surftool->commit(move_gizmo[i]);
}
- // plane translation
+ // Plane Translation
{
Ref<SurfaceTool> surftool = memnew(SurfaceTool);
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
@@ -3945,6 +4042,7 @@ void SpatialEditor::_init_indicators() {
surftool->commit(move_plane_gizmo[i]);
}
+ // Rotate
{
Ref<SurfaceTool> surftool = memnew(SurfaceTool);
@@ -3958,7 +4056,7 @@ void SpatialEditor::_init_indicators() {
ivec * 0.02 + ivec2 * 0.02 + ivec2 * GIZMO_CIRCLE_SIZE,
};
- for (int k = 0; k < 33; k++) {
+ for (int k = 0; k < 32; k++) {
Basis ma(ivec, Math_PI * 2 * float(k) / 32);
Basis mb(ivec, Math_PI * 2 * float(k + 1) / 32);
@@ -3984,19 +4082,55 @@ void SpatialEditor::_init_indicators() {
surftool->set_material(mat);
surftool->commit(rotate_gizmo[i]);
}
- }
- }
- /*for(int i=0;i<4;i++) {
+ // Scale
+ {
+ Ref<SurfaceTool> surftool = memnew(SurfaceTool);
+ surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
- viewports[i]->init_gizmo_instance(i);
- }*/
+ // Cube arrow profile
+ const int arrow_points = 6;
+ Vector3 arrow[6] = {
+ nivec * 0.0 + ivec * 0.0,
+ nivec * 0.01 + ivec * 0.0,
+ nivec * 0.01 + ivec * 1.0 * GIZMO_SCALE_OFFSET,
+ nivec * 0.07 + ivec * 1.0 * GIZMO_SCALE_OFFSET,
+ nivec * 0.07 + ivec * 1.11 * GIZMO_SCALE_OFFSET,
+ nivec * 0.0 + ivec * 1.11 * GIZMO_SCALE_OFFSET,
+ };
- _generate_selection_box();
+ int arrow_sides = 4;
+
+ for (int k = 0; k < 4; k++) {
- //Object::cast_to<EditorNode>(get_scene()->get_root_node())->get_scene_root()->add_child(camera);
+ Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides);
+ Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides);
- //current_camera=camera;
+ for (int j = 0; j < arrow_points - 1; j++) {
+
+ Vector3 points[4] = {
+ ma.xform(arrow[j]),
+ mb.xform(arrow[j]),
+ mb.xform(arrow[j + 1]),
+ ma.xform(arrow[j + 1]),
+ };
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[1]);
+ surftool->add_vertex(points[2]);
+
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[2]);
+ surftool->add_vertex(points[3]);
+ }
+ }
+
+ surftool->set_material(mat);
+ surftool->commit(scale_gizmo[i]);
+ }
+ }
+ }
+
+ _generate_selection_box();
}
void SpatialEditor::_finish_indicators() {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index e0ded6e646..4f4c540048 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -245,7 +245,7 @@ private:
real_t zoom_indicator_delay;
- RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3];
+ RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3], scale_gizmo_instance[3];
String last_message;
String message;
@@ -319,6 +319,7 @@ class SpatialEditorSelectedItem : public Object {
public:
Rect3 aabb;
Transform original; // original location when moving
+ Transform original_local;
Transform last_xform; // last transform
Spatial *sp;
RID sbox_instance;
@@ -407,7 +408,7 @@ private:
bool grid_enable[3]; //should be always visible if true
bool grid_enabled;
- Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[3];
+ Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[3], scale_gizmo[3];
Ref<SpatialMaterial> gizmo_color[3];
Ref<SpatialMaterial> plane_gizmo_color[3];
Ref<SpatialMaterial> gizmo_hl;
@@ -557,6 +558,7 @@ public:
Ref<ArrayMesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }
Ref<ArrayMesh> get_move_plane_gizmo(int idx) const { return move_plane_gizmo[idx]; }
Ref<ArrayMesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; }
+ Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; }
void update_transform_gizmo();