File size: 4,414 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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
local voxelSizeX = const.SlabSizeX or 0
local voxelSizeY = const.SlabSizeY or 0
local voxelSizeZ = const.SlabSizeZ or 0
local halfVoxelSizeX = voxelSizeX / 2
local halfVoxelSizeY = voxelSizeY / 2
local halfVoxelSizeZ = voxelSizeZ / 2
local InvalidZ = const.InvalidZ

DefineClass.RoomSizeGizmo = {
	__parents = { "XEditorGizmo", "MoveGizmoTool" },
	
	HasLocalCSSetting = false,
	HasSnapSetting = false,
	
	Title = "Room size gizmo (Ctrl+\\)",
	Description = false,
	ActionSortKey = "9",
	ActionIcon = "CommonAssets/UI/Editor/Tools/RoomResize.tga",
	ActionShortcut = "Ctrl-\\",
	UndoOpName = "Resized room(s)",
	
	r_color = RGB(255, 200, 0),
	g_color = RGB(0, 255, 200),
	b_color = RGB(200, 0, 255),
	
	room = false,
	sw = false,
}

local saveMapBlock = false
function OnMsg.PreSaveMap()
	saveMapBlock = true
end

function OnMsg.PostSaveMap()
	saveMapBlock = false
end

function RoomSizeGizmo:CheckStartOperation(pt)
	return GetSelectedRoom() and self:IntersectRay(camera.GetEye(), ScreenToGame(pt))
end

function RoomSizeGizmo:PosFromSide(r, side)
	local b = r.box
	if side == "South" then
		return b:max()
	elseif side == "North" then
		return b:min():SetZ(b:max():z())
	elseif side == "West" then
		return b:max() - point(b:sizex(), 0, 0)
	else --east
		return b:max() - point(0, b:sizey(), 0)
	end
end

function RoomSizeGizmo:Render()
	if saveMapBlock then return end
	
	local obj = not XEditorIsContextMenuOpen() and GetSelectedRoom()
	if obj then		
		self.v_axis_x = axis_x
		self.v_axis_y = axis_y
		self.v_axis_z = axis_z
		self:SetOrientation(axis_z, 0)
		
		if not self.operation_started then
			local sw = obj.selected_wall or "South"
			self:SetPos(self:PosFromSide(obj, sw))
		end
		
		self:ChangeScale()
		self:SetMesh(self:RenderGizmo())
	else 
		self:SetMesh(pstr("")) 
	end
end

function RoomSizeGizmo:StartOperation(pt)
	if saveMapBlock then return end
	
	self.initial_positions = {}
	self.initial_pos = self:CursorIntersection(pt)
	self.initial_gizmo_pos = self:GetVisualPos()
	self.room = GetSelectedRoom()
	self.sw = self.room.selected_wall or "South"
	self.operation_started = true
end

function RoomSizeGizmo:PerformOperation(pt)
	local intersection = self:CursorIntersection(pt)
	if intersection then
		local vMove = intersection - self.initial_pos
		local newPos = self.initial_gizmo_pos + vMove
		local room = self.room
		local sw = self.sw
		self:SetPos(newPos)
		local boxEdge = self:PosFromSide(room, sw)
		local delta = newPos - boxEdge
		local x, y, z = delta:xyz()
		--this resizes when gizmo hits voxel cell mid
		--delta = point((x + halfVoxelSizeX) / voxelSizeX, (y + halfVoxelSizeY) / voxelSizeY, (z + halfVoxelSizeZ) / voxelSizeZ)
		--this resizes when gizmo hits voxel cell edge
		delta = point(sign(x) * (abs(x) / voxelSizeX), sign(y) * (abs(y) / voxelSizeY), sign(z) * (abs(z) / voxelSizeZ))
		if delta ~= point30 then
			x, y, z = delta:xyz()
			local move
			if sw == "East" then
				move = point(0, y * voxelSizeY, 0)
				delta = point(x, y * -1, z)
			elseif sw == "West" then
				move = point(x * voxelSizeX, 0, 0)
				delta = point(x * -1, y, z)
			elseif sw == "North" then
				move = point(x * voxelSizeX, y * voxelSizeY, 0)
				delta = point(x * -1, y * -1, z)
			else --south
				move = point30
			end
			local oldSize = room.size
			local newSize = oldSize + delta

			if newSize:x() > 0 and newSize:y() > 0 and newSize:z() >= 0 then --else unhandled behaviour
				if VolumeCollisonEnabled and room.enable_collision then
					local b = room.box
					local mix, miy, miz = b:min():xyz()
					local max, may, maz = b:max():xyz()
					local mvx, mvy, mvz = move:xyz()
					local dx, dy, dz = delta:xyz()
					
					local testBox = box(mix + mvx, miy + mvy, miz, max + dx * voxelSizeX + mvx, may + dy * voxelSizeY + mvy, maz + dz * voxelSizeZ)
					if room:CheckCollision(nil, testBox) then
						print("Failed to resize room due to collision with other room!")
						return
					end
				end
				
				local c = room.enable_collision
				room.enable_collision = false --skip col checks, we already did them
				if move ~= point30 then
					moveHelperHelper(room, move)
				end
				room.size = oldSize + delta
				SizeSetterHelper(room, oldSize)
				room.enable_collision = c
			else
				print("Room can't shrink below x:1, y:1, z:0 size!")
			end
		end
	end
end

function RoomSizeGizmo:EndOperation()
	MoveGizmo.EndOperation(self)
	self.room = false
	self.sw = false
end