File size: 2,392 Bytes
b6a38d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
DefineClass.XEditorRotateLogic = {
	__parents = { "PropertyObject" },
	init_rotate_center = false,
	init_rotate_data = false,
	init_angle = false,
	last_angle = false,
}

-- with Slabs in the selection, rotate around a half-grid aligned point
-- to ensure Slab positions are aligned after the rotation
function XEditorRotateLogic:GetRotateCenter(center, has_slabs)
	local snap = has_slabs and const.SlabSizeX or 1
	return point(center:x() / snap * snap, center:y() / snap * snap, center:z())
end

function XEditorRotateLogic:GetRotateAngle()
	assert(false, "Please implement GetRotateAngle in the subclass.")
end

function XEditorRotateLogic:InitRotation(objs, center, initial_angle)
	assert(not self.init_rotate_data)
	local has_slabs = HasAlignedObjs(objs)
	self.init_rotate_center = self:GetRotateCenter(center or CenterOfMasses(objs), has_slabs)
	self.init_angle = initial_angle or self:GetRotateAngle()
	self.last_angle = 0
	self.init_rotate_data = {}
	for i, obj in ipairs(objs) do
		if obj:IsValidPos() then
			self.init_rotate_data[i] = {
				axis = obj:GetVisualAxis(),
				angle = obj:GetVisualAngle(),
				offset = obj:GetVisualPos() - self.init_rotate_center,
				valid_z = obj:IsValidZ(),
				last_angle = 0,
			}
		end
	end
end

function XEditorRotateLogic:Rotate(objs, group_rotation, center, axis, angle)
	if not self.init_rotate_data then
		self:InitRotation(objs, center)
	end
	
	axis = axis or axis_z
	angle = angle or self:GetRotateAngle()
	
	local has_slabs = HasAlignedObjs(objs)
	local center = self.init_rotate_center
	local angle = XEditorSettings:AngleSnap(angle - self.init_angle, has_slabs)
	for i, obj in ipairs(objs) do
		if obj:HasMember("EditorRotate") then
			obj:EditorRotate(group_rotation and center or obj:GetPos(), axis, angle, self.last_angle)
		elseif obj:IsValidPos() then
			local data = self.init_rotate_data[i]
			local newPos = obj:GetPos()
			if group_rotation then
				newPos = center + RotateAxis(data.offset, axis, angle)
				if not data.valid_z then
					newPos = newPos:SetInvalidZ()
				end
			end
			XEditorSetPosAxisAngle(obj, newPos, ComposeRotation(data.axis, data.angle, axis, angle))
		end
	end
	Msg("EditorCallback", "EditorCallbackRotate", objs)
	self.last_angle = angle
end

function XEditorRotateLogic:CleanupRotation()
	self.init_rotate_data = nil
	self.init_rotate_center = nil
	self.init_angle = nil
	self.last_angle = nil
end