myspace / CommonLua /Libs /Volumes /Editor /XStickToWallsFloorsHelper.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
DefineClass.XStickToObjsBase = {
__parents = { "XObjectPlacementHelper" },
InXPlaceObjectTool = true,
InXSelectObjectsTool = true,
AllowRotationAfterPlacement = true,
HasSnapSetting = true,
pivot_obj_id = false,
intersection_class = "WallSlab",
set_angle = true,
}
function XStickToObjsBase:StartMoveObjects(mouse_pos, objects)
local cur_pos = GetTerrainCursor()
local bestIp = false
local bestId = -1
local eye = camera.GetEye()
local cursor = ScreenToGame(mouse_pos)
local sp = eye
local ep = (cursor - eye) * 1000 + cursor
self.init_move_positions = {}
self.init_orientations = {}
for i, o in ipairs(objects) do
local hisPos = o:GetPos()
if not hisPos:IsValid() then
o:SetPos(cur_pos)
hisPos = cur_pos
end
self.init_move_positions[i] = hisPos
self.init_orientations[i] = { o:GetOrientation() }
local ip1, ip2 = ClipSegmentWithBox3D(sp, ep, o)
if ip1 and (bestId == -1 or IsCloser(sp, ip1, bestIp)) then
bestIp = ip1
bestId = i
end
end
if bestId == -1 then
bestId = 1 --that sux, no obj crossed the ray from camera
end
self.pivot_obj_id = bestId
self.init_drag_position = objects[bestId]:GetPos():SetTerrainZ()
end
function XStickToObjsBase:MoveObjects(mouse_pos, objects)
local vMove = (GetTerrainCursor() - self.init_drag_position):SetZ(0)
for i, obj in ipairs(objects) do
local offset = self.init_move_positions[i] - self.init_move_positions[self.pivot_obj_id]
if not offset:z() then
offset = offset:SetZ(0)
end
local eye = camera.GetEye()
local cursor = ScreenToGame(mouse_pos)
local sp = eye + offset
local ep = (cursor - eye) * 1000 + cursor + offset
local objs = IntersectObjectsOnSegment(sp, ep, 0, self.intersection_class, function(o)
if not o.isVisible then
return rawget(o, "wall_obj") == obj
end
return true
end)
--[[DbgClear()
print(eye)
DbgAddVector(eye, cursor - eye, RGB(255, 0, 0))
DbgAddVector(sp, ep - sp)
if objs and objs[1] then
DbgAddBox(objs[1]:GetObjectBBox())
end]]
if objs and #objs > 0 then
local closest = objs[1]
local p1, p2 = ClipSegmentWithBox3D(sp, ep, closest)
local ip = closest:GetPos()
if p1 then
ip = p1 == sp and p2 or p1
end
local angle = closest:GetAngle()
local x, y, z
if XEditorSettings:GetSnapEnabled() then
x, y, z, angle = WallWorldToVoxel(ip:x(), ip:y(), ip:z(), angle)
x, y, z = WallVoxelToWorld(x, y, z, angle)
else
x, y, z = ip:xyz()
end
if IsKindOf(obj, "AlignedObj") then
obj:AlignObj(point(x, y, z), self.set_angle and angle or nil)
else
if self.set_angle then
obj:SetPosAngle(x, y, z, angle)
else
obj:SetPos(x, y, z)
end
end
else
local pos = (self.init_move_positions[i] + vMove):SetTerrainZ()
if IsKindOf(obj, "AlignedObj") then
obj:AlignObj(pos)
else
obj:SetPos(pos)
end
end
end
Msg("EditorCallback", "EditorCallbackMove", objects)
end
DefineClass.XStickToWallsHelper = {
__parents = { "XStickToObjsBase" },
Title = "Stick to walls (Y)",
Description = false,
ActionSortKey = "6",
ActionIcon = "CommonAssets/UI/Editor/Tools/StickToWall.tga",
ActionShortcut = "Y",
UndoOpName = "Stuck %d object(s) to wall",
intersection_class = "WallSlab",
set_angle = true,
}
DefineClass.XStickToFloorsHelper = {
__parents = { "XStickToObjsBase" },
Title = "Stick to floors (U)",
Description = false,
ActionSortKey = "7",
ActionIcon = "CommonAssets/UI/Editor/Tools/StickToFloor.tga",
ActionShortcut = "U",
UndoOpName = "Stuck %d object(s) to floor",
intersection_class = "FloorSlab",
set_angle = false,
}