瀏覽代碼

samples: RotateTool: add camera plane rotation

Daniele Bartolini 5 年之前
父節點
當前提交
941a0cd747
共有 1 個文件被更改,包括 55 次插入17 次删除
  1. 55 17
      samples/core/editors/level_editor/level_editor.lua

+ 55 - 17
samples/core/editors/level_editor/level_editor.lua

@@ -1102,6 +1102,7 @@ function RotateTool:axis_selected()
 	return self._selected == "x"
 		or self._selected == "y"
 		or self._selected == "z"
+		or self._selected == "xyz"
 end
 
 function RotateTool:drag_start()
@@ -1112,16 +1113,18 @@ function RotateTool:rotate_normal()
 	if self._selected == "x" then return Quaternion.right(self:rotation()) end
 	if self._selected == "y" then return Quaternion.up(self:rotation()) end
 	if self._selected == "z" then return Quaternion.forward(self:rotation()) end
+	if self._selected == "xyz" then return -Matrix4x4.z(LevelEditor:camera():local_pose()) end
 	return nil
 end
 
 function RotateTool:update(dt, x, y)
 	local selected = LevelEditor._selection:last_selected_object()
+	if not selected then
+		return
+	end
 
 	-- Update gizmo pose
-	if selected then
-		self:set_pose(LevelEditor._reference_system == "world" and Matrix4x4.from_translation(selected:local_position()) or selected:world_pose())
-	end
+	self:set_pose(LevelEditor._reference_system == "world" and Matrix4x4.from_translation(selected:local_position()) or selected:world_pose())
 
 	local tm = self:pose()
 	local p  = self:position()
@@ -1129,18 +1132,19 @@ function RotateTool:update(dt, x, y)
 	local cam_z = Matrix4x4.z(LevelEditor:camera():local_pose())
 
 	-- Select axis
-	if self:is_idle() and selected then
+	if self:is_idle() then
 		local pos, dir = LevelEditor:camera():camera_ray(x, y)
 
 		local axis = {
 			Math.ray_disc_intersection(pos, dir, p, l, Matrix4x4.x(tm)),
 			Math.ray_disc_intersection(pos, dir, p, l, Matrix4x4.y(tm)),
-			Math.ray_disc_intersection(pos, dir, p, l, Matrix4x4.z(tm))
+			Math.ray_disc_intersection(pos, dir, p, l, Matrix4x4.z(tm)),
+			Math.ray_disc_intersection(pos, dir, p, l*1.25, -cam_z)
 		}
 
 		local nearest = nil
 		local dist = math.huge
-		local axis_names = { "x", "y", "z" }
+		local axis_names = { "x", "y", "z", "xyz" }
 		for ii, name in ipairs(axis_names) do
 			if axis[ii] ~= -1.0 and axis[ii] < dist then
 				nearest = ii
@@ -1150,12 +1154,52 @@ function RotateTool:update(dt, x, y)
 		self._selected = nearest and axis_names[nearest] or nil
 	end
 
+	function DebugLine.add_arc(lines, center, radius, normal, color, segments)
+		if not segments then
+			segments = 36
+		end
+
+		-- Pick a right axis.
+		local right = Vector3(normal.z, normal.z , -normal.x-normal.y)
+		if normal.z ~= 0 and -normal.x ~= normal.y then
+			 right = Vector3(-normal.y-normal.z, normal.x, normal.x)
+		end
+		Vector3.normalize(right)
+
+		local x = right * radius
+		local y = Vector3.cross(right, normal) * radius
+		local step = (2*math.pi) / (segments > 3 and segments or 3)
+		local from = center - y
+
+		local cam_to_center = Vector3.normalize(center-Matrix4x4.translation(LevelEditor:camera():local_pose()))
+
+		for i=0,segments+1 do
+			local t = step * i - (math.pi/2)
+			local to = center + x*math.cos(t) + y*math.sin(t)
+
+			local center_to_vertex = Vector3.normalize(to - center)
+			local ctc_dot_ctv = Vector3.dot(center_to_vertex, cam_to_center)
+			if ctc_dot_ctv <= 0 then
+				DebugLine.add_line(lines, from, to, color)
+			end
+			from = to
+		end
+	end
+
 	-- Drawing
-	if selected then
-		local lines = LevelEditor._lines_no_depth
-		DebugLine.add_circle(lines, p, l, Matrix4x4.x(tm), self._selected == "x" and Colors.axis_selected() or plane_color(Matrix4x4.x(tm), cam_z, Colors.axis_x()))
-		DebugLine.add_circle(lines, p, l, Matrix4x4.y(tm), self._selected == "y" and Colors.axis_selected() or plane_color(Matrix4x4.y(tm), cam_z, Colors.axis_y()))
-		DebugLine.add_circle(lines, p, l, Matrix4x4.z(tm), self._selected == "z" and Colors.axis_selected() or plane_color(Matrix4x4.z(tm), cam_z, Colors.axis_z()))
+	local lines = LevelEditor._lines_no_depth
+	-- Draw major planes handles.
+	DebugLine.add_arc(lines, p, l, Matrix4x4.x(tm), self._selected == "x" and Colors.axis_selected() or Colors.axis_x())
+	DebugLine.add_arc(lines, p, l, Matrix4x4.y(tm), self._selected == "y" and Colors.axis_selected() or Colors.axis_y())
+	DebugLine.add_arc(lines, p, l, Matrix4x4.z(tm), self._selected == "z" and Colors.axis_selected() or Colors.axis_z())
+	-- Draw camera plane handle.
+	DebugLine.add_circle(lines, p, l*1.25, cam_z, self._selected == "xyz" and Colors.axis_selected() or Colors.grid())
+
+
+	if self:is_rotating() then
+		local radius = self._selected == "xyz" and l*1.25 or l
+		DebugLine.add_line(lines, self:position(), self:position() - radius*Vector3.normalize(self:position() - self:drag_start()), Colors.axis_selected())
+		DebugLine.add_line(lines, self:position(), self:position() - radius*Vector3.normalize(self:position() - self:drag_offset(x, y)), Colors.axis_selected())
 	end
 end
 
@@ -1243,12 +1287,6 @@ function RotateTool:mouse_move(x, y)
 			v:set_local_position(Matrix4x4.translation(new_pose))
 			v:set_local_rotation(Matrix4x4.rotation(new_pose))
 		end
-
-		-- Drawing
-		local lines = LevelEditor._lines_no_depth
-		DebugLine.add_sphere(lines, point_on_plane, 0.1, Color4.green())
-		DebugLine.add_line(lines, self:position(), self:position() + Vector3.normalize(drag_start - self:position()), Color4.yellow())
-		DebugLine.add_line(lines, self:position(), self:position() + Vector3.normalize(point_on_plane - self:position()), Color4.yellow())
 	end
 end