mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
568
lua/pac3/editor/client/mctrl.lua
Normal file
568
lua/pac3/editor/client/mctrl.lua
Normal file
@@ -0,0 +1,568 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
pace.mctrl = {}
|
||||
local mctrl = pace.mctrl
|
||||
mctrl.grab_dist = 15
|
||||
mctrl.angle_pos = 0.5
|
||||
local cvar_pos_grid = CreateClientConVar("pac_grid_pos_size", "4")
|
||||
local cvar_ang_grid = CreateClientConVar("pac_grid_ang_size", "45")
|
||||
|
||||
--[[
|
||||
Give this function the coordinates of a pixel on your screen, and it will return a unit vector pointing
|
||||
in the direction that the camera would project that pixel in.
|
||||
|
||||
Useful for converting mouse positions to aim vectors for traces.
|
||||
|
||||
iScreenX is the x position of your cursor on the screen, in pixels.
|
||||
iScreenY is the y position of your cursor on the screen, in pixels.
|
||||
iScreenW is the width of the screen, in pixels.
|
||||
iScreenH is the height of the screen, in pixels.
|
||||
angCamRot is the angle your camera is at
|
||||
fFoV is the Field of View (FOV) of your camera in ___radians___
|
||||
Note: This must be nonzero or you will get a divide by zero error.
|
||||
]]
|
||||
local function LPCameraScreenToVector(iScreenX, iScreenY, iScreenW, iScreenH, angCamRot, fFoV)
|
||||
--This code works by basically treating the camera like a frustrum of a pyramid.
|
||||
--We slice this frustrum at a distance "d" from the camera, where the slice will be a rectangle whose width equals the "4:3" width corresponding to the given screen height.
|
||||
local d = 4 * iScreenH / (6 * math.tan(0.5 * fFoV))
|
||||
--Forward, right, and up vectors (need these to convert from local to world coordinates
|
||||
local vForward = angCamRot:Forward()
|
||||
local vRight = angCamRot:Right()
|
||||
local vUp = angCamRot:Up()
|
||||
--Then convert vec to proper world coordinates and return it
|
||||
|
||||
return (d * vForward + (iScreenX - 0.5 * iScreenW) * vRight + (0.5 * iScreenH - iScreenY) * vUp):GetNormalized()
|
||||
end
|
||||
|
||||
--[[
|
||||
Give this function a vector, pointing from the camera to a position in the world,
|
||||
and it will return the coordinates of a pixel on your screen - this is where the world position would be projected onto your screen.
|
||||
|
||||
Useful for finding where things in the world are on your screen (if they are at all).
|
||||
|
||||
vDir is a direction vector pointing from the camera to a position in the world
|
||||
iScreenW is the width of the screen, in pixels.
|
||||
iScreenH is the height of the screen, in pixels.
|
||||
angCamRot is the angle your camera is at
|
||||
fFoV is the Field of View (FOV) of your camera in ___radians___
|
||||
Note: This must be nonzero or you will get a divide by zero error.
|
||||
|
||||
Returns x, y, iVisibility.
|
||||
x and y are screen coordinates.
|
||||
iVisibility will be:
|
||||
1 if the point is visible
|
||||
0 if the point is in front of the camera, but is not visible
|
||||
-1 if the point is behind the camera
|
||||
]]
|
||||
local function VectorToLPCameraScreen(vDir, iScreenW, iScreenH, angCamRot, fFoV)
|
||||
--Same as we did above, we found distance the camera to a rectangular slice of the camera's frustrum, whose width equals the "4:3" width corresponding to the given screen height.
|
||||
local d = 4 * iScreenH / (6 * math.tan(0.5 * fFoV))
|
||||
local fdp = angCamRot:Forward():Dot(vDir)
|
||||
--fdp must be nonzero ( in other words, vDir must not be perpendicular to angCamRot:Forward() )
|
||||
--or we will get a divide by zero error when calculating vProj below.
|
||||
if fdp == 0 then return 0, 0, -1 end
|
||||
--Using linear projection, project this vector onto the plane of the slice
|
||||
local vProj = (d / fdp) * vDir
|
||||
--Dotting the projected vector onto the right and up vectors gives us screen positions relative to the center of the screen.
|
||||
--We add half-widths / half-heights to these coordinates to give us screen positions relative to the upper-left corner of the screen.
|
||||
--We have to subtract from the "up" instead of adding, since screen coordinates decrease as they go upwards.
|
||||
local x = 0.5 * iScreenW + angCamRot:Right():Dot(vProj)
|
||||
local y = 0.5 * iScreenH - angCamRot:Up():Dot(vProj)
|
||||
--Lastly we have to ensure these screen positions are actually on the screen.
|
||||
local iVisibility
|
||||
|
||||
--Simple check to see if the object is in front of the camera
|
||||
if fdp < 0 then
|
||||
iVisibility = -1
|
||||
elseif x < 0 or x > iScreenW or y < 0 or y > iScreenH then
|
||||
--We've already determined the object is in front of us, but it may be lurking just outside our field of vision.
|
||||
iVisibility = 0
|
||||
else
|
||||
iVisibility = 1
|
||||
end
|
||||
|
||||
return x, y, iVisibility
|
||||
end
|
||||
|
||||
local function LocalToWorldAngle(lang, wang)
|
||||
local lm = Matrix()
|
||||
lm:SetAngles(lang)
|
||||
local wm = Matrix()
|
||||
wm:SetAngles(wang)
|
||||
|
||||
return (wm * lm):GetAngles()
|
||||
end
|
||||
|
||||
local function WorldToLocalAngle(lang, wang)
|
||||
local lm = Matrix()
|
||||
lm:SetAngles(lang)
|
||||
local wm = Matrix()
|
||||
wm:SetAngles(wang)
|
||||
|
||||
return (wm:GetInverse() * lm):GetAngles()
|
||||
end
|
||||
|
||||
local function cursor_pos()
|
||||
local x, y = input.GetCursorPos()
|
||||
|
||||
if mctrl.grab and mctrl.grab.mouse_offset then
|
||||
x = x + mctrl.grab.mouse_offset.x
|
||||
y = y + mctrl.grab.mouse_offset.y
|
||||
end
|
||||
|
||||
return x, y
|
||||
end
|
||||
|
||||
-- pace
|
||||
do
|
||||
mctrl.target = NULL
|
||||
|
||||
function mctrl.SetTarget(part)
|
||||
part = part or NULL
|
||||
|
||||
if not part:IsValid() then
|
||||
mctrl.target = NULL
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if not part.GetDrawPosition then
|
||||
mctrl.target = NULL
|
||||
else
|
||||
mctrl.target = part
|
||||
end
|
||||
end
|
||||
|
||||
function mctrl.GetTarget()
|
||||
return mctrl.target:IsValid() and not mctrl.target:IsHidden() and mctrl.target or NULL
|
||||
end
|
||||
|
||||
function mctrl.GetAxes(ang)
|
||||
return ang:Forward(), ang:Right() * -1, ang:Up()
|
||||
end
|
||||
|
||||
function mctrl.GetWorldPosition()
|
||||
local part = mctrl.GetTarget()
|
||||
if not part:IsValid() then return end
|
||||
local m = part:GetWorldMatrixWithoutOffsets()
|
||||
|
||||
return m:GetTranslation(), m:GetAngles()
|
||||
end
|
||||
|
||||
function mctrl.GetWorldMatrix()
|
||||
local part = mctrl.GetTarget()
|
||||
if not part:IsValid() then return end
|
||||
|
||||
return part:GetWorldMatrixWithoutOffsets()
|
||||
end
|
||||
|
||||
function mctrl.WorldToLocalPosition(pos, ang)
|
||||
local part = mctrl.GetTarget()
|
||||
if not part:IsValid() then return end
|
||||
local wpos, wang = part:GetBonePosition()
|
||||
if wpos and wang then return WorldToLocal(pos, ang, wpos, wang) end
|
||||
end
|
||||
|
||||
function mctrl.GetCameraFOV()
|
||||
if pace.editing_viewmodel or pace.editing_hands then return pac.LocalPlayer:GetActiveWeapon().ViewModelFOV or 55 end
|
||||
|
||||
return pace.GetViewFOV()
|
||||
end
|
||||
|
||||
function mctrl.VecToScreen(vec)
|
||||
local x, y, vis = VectorToLPCameraScreen((vec - EyePos()):GetNormalized(), ScrW(), ScrH(), EyeAngles(), math.rad(mctrl.GetCameraFOV()))
|
||||
|
||||
return {
|
||||
x = x - 1,
|
||||
y = y - 1,
|
||||
visible = vis == 1
|
||||
}
|
||||
end
|
||||
|
||||
function mctrl.ScreenToVec(x, y)
|
||||
local vec = LPCameraScreenToVector(x, y, ScrW(), ScrH(), EyeAngles(), math.rad(mctrl.GetCameraFOV()))
|
||||
|
||||
return vec
|
||||
end
|
||||
|
||||
function mctrl.GetGizmoSize()
|
||||
local part = pace.current_part
|
||||
if pace.editing_viewmodel or pace.editing_hands then return 5 end
|
||||
|
||||
if part.ClassName == "clip" or part.ClassName == "clip2" then
|
||||
part = part.Parent
|
||||
end
|
||||
|
||||
if part.ClassName == "camera" then return 30 end
|
||||
if part.ClassName == "group" then return 45 end
|
||||
if not part:IsValid() or not part.GetWorldPosition then return 3 end
|
||||
local dist = (part:GetWorldMatrixWithoutOffsets():GetTranslation():Distance(pace.GetViewPos()) / 50)
|
||||
|
||||
if dist > 1 then
|
||||
dist = 1 / dist
|
||||
end
|
||||
|
||||
return 5 * math.rad(pace.GetViewFOV()) / dist
|
||||
end
|
||||
end
|
||||
|
||||
function mctrl.LinePlaneIntersection(pos, normal, x, y)
|
||||
local n = normal
|
||||
local lp = pace.GetViewPos() - pos
|
||||
local ln = mctrl.ScreenToVec(x, y)
|
||||
|
||||
return lp + ln * (-lp:Dot(n) / ln:Dot(n))
|
||||
end
|
||||
|
||||
local function dot2D(x1, y1, x2, y2)
|
||||
return x1 * x2 + y1 * y2
|
||||
end
|
||||
|
||||
function mctrl.PointToAxis(pos, axis)
|
||||
local x, y = cursor_pos()
|
||||
local origin = mctrl.VecToScreen(pos)
|
||||
local point = mctrl.VecToScreen(pos + axis * 10)
|
||||
local a = math.atan2(point.y - origin.y, point.x - origin.x)
|
||||
local d = dot2D(math.cos(a), math.sin(a), point.x - x, point.y - y)
|
||||
|
||||
return point.x + math.cos(a) * -d, point.y + math.sin(a) * -d
|
||||
end
|
||||
|
||||
function mctrl.CalculateMovement()
|
||||
local part = mctrl.GetTarget()
|
||||
if not part:IsValid() then return end
|
||||
local axis = mctrl.grab.axis
|
||||
local offset = mctrl.GetGizmoSize()
|
||||
local m = mctrl.grab.matrix --part:GetWorldMatrixWithoutOffsets()
|
||||
local pos = m:GetTranslation()
|
||||
local forward, right, up = m:GetForward(), -m:GetRight(), m:GetUp()
|
||||
local world_dir
|
||||
|
||||
if axis == "x" then
|
||||
local localpos = mctrl.LinePlaneIntersection(pos, right, mctrl.PointToAxis(pos, forward))
|
||||
world_dir = (localpos:Dot(forward) - offset) * forward
|
||||
elseif axis == "y" then
|
||||
local localpos = mctrl.LinePlaneIntersection(pos, forward, mctrl.PointToAxis(pos, right))
|
||||
world_dir = (localpos:Dot(right) - offset) * right
|
||||
elseif axis == "z" then
|
||||
local localpos = mctrl.LinePlaneIntersection(pos, forward, mctrl.PointToAxis(pos, up))
|
||||
world_dir = (localpos:Dot(up) - offset) * up
|
||||
elseif axis == "view" then
|
||||
world_dir = mctrl.LinePlaneIntersection(pos, pace.GetViewAngles():Forward(), cursor_pos())
|
||||
end
|
||||
|
||||
if world_dir then
|
||||
local m2 = Matrix()
|
||||
m2:SetTranslation(m:GetTranslation() + world_dir)
|
||||
local wm = mctrl.grab.bone_matrix:GetInverse() * m2
|
||||
local pos = wm:GetTranslation()
|
||||
|
||||
if input.IsKeyDown(KEY_LCONTROL) then
|
||||
local num = cvar_pos_grid:GetInt("pac_grid_pos_size")
|
||||
pos.x = math.Round(pos.x / num) * num
|
||||
pos.y = math.Round(pos.y / num) * num
|
||||
pos.z = math.Round(pos.z / num) * num
|
||||
end
|
||||
|
||||
pace.Call("VariableChanged", part, "Position", pos, 0.25)
|
||||
|
||||
timer.Create("pace_refresh_properties", 0.1, 1, function()
|
||||
pace.PopulateProperties(part)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function mctrl.CalculateRotation()
|
||||
local part = mctrl.GetTarget()
|
||||
if not part:IsValid() then return end
|
||||
local axis = mctrl.grab.axis
|
||||
local ang = mctrl.grab.matrix:GetAngles() --part:GetWorldMatrixWithoutOffsets():GetAngles()
|
||||
local world_angle
|
||||
|
||||
if axis == "x" then
|
||||
local plane_pos = util.IntersectRayWithPlane(EyePos(), mctrl.ScreenToVec(cursor_pos()), mctrl.grab.matrix:GetTranslation(), mctrl.grab.matrix:GetRight())
|
||||
if not plane_pos then return end
|
||||
local diff_angle = (plane_pos - mctrl.grab.matrix:GetTranslation()):Angle()
|
||||
local local_angle = WorldToLocalAngle(diff_angle, ang)
|
||||
local p = local_angle.p
|
||||
|
||||
if math.abs(local_angle.y) > 90 then
|
||||
p = -p + 180
|
||||
end
|
||||
|
||||
p = math.NormalizeAngle(p)
|
||||
world_angle = LocalToWorldAngle(Angle(p, 0, 0), ang)
|
||||
elseif axis == "y" then
|
||||
local plane_pos = util.IntersectRayWithPlane(EyePos(), mctrl.ScreenToVec(cursor_pos()), mctrl.grab.matrix:GetTranslation(), mctrl.grab.matrix:GetUp())
|
||||
if not plane_pos then return end
|
||||
local diff_angle = (plane_pos - mctrl.grab.matrix:GetTranslation()):Angle()
|
||||
local local_angle = WorldToLocalAngle(diff_angle, ang)
|
||||
world_angle = LocalToWorldAngle(Angle(0, local_angle.y - 90, 0), ang)
|
||||
elseif axis == "z" then
|
||||
local plane_pos = util.IntersectRayWithPlane(EyePos(), mctrl.ScreenToVec(cursor_pos()), mctrl.grab.matrix:GetTranslation(), mctrl.grab.matrix:GetForward())
|
||||
if not plane_pos then return end
|
||||
local diff_angle = (plane_pos - mctrl.grab.matrix:GetTranslation()):Angle()
|
||||
diff_angle:RotateAroundAxis(mctrl.grab.matrix:GetForward(), 90)
|
||||
local local_angle = WorldToLocalAngle(diff_angle, ang)
|
||||
local p = local_angle.p
|
||||
|
||||
if local_angle.y > 0 then
|
||||
p = -p + 180
|
||||
end
|
||||
|
||||
p = math.NormalizeAngle(p)
|
||||
world_angle = LocalToWorldAngle(Angle(0, 0, p), ang)
|
||||
end
|
||||
|
||||
if world_angle then
|
||||
local ang = WorldToLocalAngle(world_angle, mctrl.grab.bone_matrix:GetAngles())
|
||||
|
||||
if input.IsKeyDown(KEY_LCONTROL) then
|
||||
local num = cvar_ang_grid:GetInt("pac_grid_ang_size")
|
||||
ang.p = math.Round(ang.p / num) * num
|
||||
ang.y = math.Round(ang.y / num) * num
|
||||
ang.r = math.Round(ang.r / num) * num
|
||||
end
|
||||
|
||||
pace.Call("VariableChanged", part, "Angles", ang, 0.25)
|
||||
|
||||
timer.Create("pace_refresh_properties", 0.1, 1, function()
|
||||
pace.PopulateProperties(part)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
mctrl.grab = {
|
||||
mode = nil,
|
||||
axis = nil
|
||||
}
|
||||
|
||||
local GRAB_AND_CLONE = CreateClientConVar("pac_grab_clone", "1", true, false, "Holding shift when moving or rotating a part creates its clone")
|
||||
|
||||
function mctrl.GUIMousePressed(mc)
|
||||
if mc ~= MOUSE_LEFT then return end
|
||||
local target = mctrl.GetTarget()
|
||||
if not target:IsValid() then return end
|
||||
local x, y = input.GetCursorPos()
|
||||
local pos, ang = mctrl.GetWorldPosition()
|
||||
if not pos or not ang then return end
|
||||
local forward, right, up = mctrl.GetAxes(ang)
|
||||
local r = mctrl.GetGizmoSize()
|
||||
|
||||
-- Movement
|
||||
do
|
||||
local axis
|
||||
|
||||
for i, v in pairs({
|
||||
x = mctrl.VecToScreen(pos + forward * r),
|
||||
y = mctrl.VecToScreen(pos + right * r),
|
||||
z = mctrl.VecToScreen(pos + up * r),
|
||||
view = mctrl.VecToScreen(pos)
|
||||
}) do
|
||||
local d = math.sqrt((v.x - x) ^ 2 + (v.y - y) ^ 2)
|
||||
|
||||
if d <= mctrl.grab_dist then
|
||||
axis = {
|
||||
axis = i,
|
||||
pos = v
|
||||
}
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if axis then
|
||||
mctrl.grab = {}
|
||||
mctrl.grab.mode = "move"
|
||||
mctrl.grab.axis = axis.axis
|
||||
local x, y = input.GetCursorPos()
|
||||
|
||||
mctrl.grab.mouse_offset = {
|
||||
x = math.ceil(axis.pos.x - x),
|
||||
y = math.ceil(axis.pos.y - y),
|
||||
}
|
||||
|
||||
mctrl.grab.matrix = target:GetWorldMatrixWithoutOffsets() * Matrix()
|
||||
mctrl.grab.bone_matrix = target:GetBoneMatrix() * Matrix()
|
||||
|
||||
if GRAB_AND_CLONE:GetBool() and input.IsShiftDown() then
|
||||
local copy = target:Clone()
|
||||
copy:SetParent(copy:GetParent())
|
||||
end
|
||||
|
||||
pace.RecordUndoHistory()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- Rotation
|
||||
do
|
||||
local axis
|
||||
|
||||
for i, v in pairs({
|
||||
x = mctrl.VecToScreen(pos + forward * r * mctrl.angle_pos),
|
||||
y = mctrl.VecToScreen(pos + right * r * mctrl.angle_pos),
|
||||
z = mctrl.VecToScreen(pos + up * r * mctrl.angle_pos)
|
||||
}) do
|
||||
local d = math.sqrt((v.x - x) ^ 2 + (v.y - y) ^ 2)
|
||||
|
||||
if d <= mctrl.grab_dist then
|
||||
axis = {
|
||||
axis = i,
|
||||
pos = v
|
||||
}
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if axis then
|
||||
mctrl.grab = {}
|
||||
mctrl.grab.mode = "rotate"
|
||||
mctrl.grab.axis = axis.axis
|
||||
local x, y = input.GetCursorPos()
|
||||
|
||||
mctrl.grab.mouse_offset = {
|
||||
x = math.ceil(axis.pos.x - x) + 0.5,
|
||||
y = math.ceil(axis.pos.y - y) + 0.5,
|
||||
}
|
||||
|
||||
mctrl.grab.matrix = target:GetWorldMatrixWithoutOffsets() * Matrix()
|
||||
mctrl.grab.bone_matrix = target:GetBoneMatrix() * Matrix()
|
||||
mctrl.grab.dist = dist
|
||||
|
||||
if GRAB_AND_CLONE:GetBool() and input.IsShiftDown() then
|
||||
local copy = target:Clone()
|
||||
copy:SetParent(copy:GetParent())
|
||||
end
|
||||
|
||||
pace.RecordUndoHistory()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function mctrl.GUIMouseReleased(mc)
|
||||
if mc == MOUSE_LEFT then
|
||||
mctrl.grab = nil
|
||||
end
|
||||
|
||||
pace.RecordUndoHistory()
|
||||
end
|
||||
|
||||
local white = surface.GetTextureID("gui/center_gradient.vtf")
|
||||
|
||||
local function DrawLineEx(x1, y1, x2, y2, w, skip_tex)
|
||||
w = w or 1
|
||||
|
||||
if not skip_tex then
|
||||
surface.SetTexture(white)
|
||||
end
|
||||
|
||||
local dx, dy = x1 - x2, y1 - y2
|
||||
local ang = math.atan2(dx, dy)
|
||||
local dst = math.sqrt((dx * dx) + (dy * dy))
|
||||
x1 = x1 - dx * 0.5
|
||||
y1 = y1 - dy * 0.5
|
||||
surface.DrawTexturedRectRotated(x1, y1, w, dst, math.deg(ang))
|
||||
end
|
||||
|
||||
local function DrawLine(x, y, a, b)
|
||||
DrawLineEx(x, y, a, b, 3)
|
||||
end
|
||||
|
||||
local function DrawCircleEx(x, y, rad, res, ...)
|
||||
res = res or 16
|
||||
local spacing = (res / rad) - 0.1
|
||||
|
||||
for i = 0, res do
|
||||
local i1 = ((i + 0) / res) * math.pi * 2
|
||||
local i2 = ((i + 1 + spacing) / res) * math.pi * 2
|
||||
DrawLineEx(x + math.sin(i1) * rad, y + math.cos(i1) * rad, x + math.sin(i2) * rad, y + math.cos(i2) * rad, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function mctrl.LineToBox(origin, point, siz)
|
||||
siz = siz or 7
|
||||
DrawLine(origin.x, origin.y, point.x, point.y)
|
||||
DrawCircleEx(point.x, point.y, siz, 32, 2)
|
||||
end
|
||||
|
||||
function mctrl.RotationLines(pos, dir, dir2, r)
|
||||
local pr = mctrl.VecToScreen(pos + dir * r * mctrl.angle_pos)
|
||||
local pra = mctrl.VecToScreen(pos + dir * r * (mctrl.angle_pos * 0.9) + dir2 * r * 0.08)
|
||||
local prb = mctrl.VecToScreen(pos + dir * r * (mctrl.angle_pos * 0.9) + dir2 * r * -0.08)
|
||||
DrawLine(pr.x, pr.y, pra.x, pra.y)
|
||||
DrawLine(pr.x, pr.y, prb.x, prb.y)
|
||||
end
|
||||
|
||||
function mctrl.HUDPaint()
|
||||
mctrl.LastThinkCall = FrameNumber()
|
||||
if pace.IsSelecting then return end
|
||||
local target = mctrl.GetTarget()
|
||||
if not target then return end
|
||||
local pos, ang = mctrl.GetWorldPosition()
|
||||
if not pos or not ang then return end
|
||||
local forward, right, up = mctrl.GetAxes(ang)
|
||||
local radius = mctrl.GetGizmoSize()
|
||||
local origin = mctrl.VecToScreen(pos)
|
||||
local forward_point = mctrl.VecToScreen(pos + forward * radius)
|
||||
local right_point = mctrl.VecToScreen(pos + right * radius)
|
||||
local up_point = mctrl.VecToScreen(pos + up * radius)
|
||||
|
||||
if origin.visible or forward_point.visible or right_point.visible or up_point.visible then
|
||||
if mctrl.grab and (mctrl.grab.axis == "x" or mctrl.grab.axis == "view") then
|
||||
surface.SetDrawColor(255, 200, 0, 255)
|
||||
else
|
||||
surface.SetDrawColor(255, 80, 80, 255)
|
||||
end
|
||||
|
||||
mctrl.LineToBox(origin, forward_point)
|
||||
mctrl.RotationLines(pos, forward, up, radius)
|
||||
|
||||
if mctrl.grab and (mctrl.grab.axis == "y" or mctrl.grab.axis == "view") then
|
||||
surface.SetDrawColor(255, 200, 0, 255)
|
||||
else
|
||||
surface.SetDrawColor(80, 255, 80, 255)
|
||||
end
|
||||
|
||||
mctrl.LineToBox(origin, right_point)
|
||||
mctrl.RotationLines(pos, right, forward, radius)
|
||||
|
||||
if mctrl.grab and (mctrl.grab.axis == "z" or mctrl.grab.axis == "view") then
|
||||
surface.SetDrawColor(255, 200, 0, 255)
|
||||
else
|
||||
surface.SetDrawColor(80, 80, 255, 255)
|
||||
end
|
||||
|
||||
mctrl.LineToBox(origin, up_point)
|
||||
mctrl.RotationLines(pos, up, right, radius)
|
||||
surface.SetDrawColor(255, 200, 0, 255)
|
||||
DrawCircleEx(origin.x, origin.y, 4, 32, 2)
|
||||
end
|
||||
end
|
||||
|
||||
function mctrl.Think()
|
||||
if pace.IsSelecting then return end
|
||||
if not mctrl.target:IsValid() then return end
|
||||
if not mctrl.grab then return end
|
||||
|
||||
if mctrl.grab.axis and mctrl.grab.mode == "move" then
|
||||
mctrl.CalculateMovement()
|
||||
elseif mctrl.grab.axis and mctrl.grab.mode == "rotate" then
|
||||
mctrl.CalculateRotation()
|
||||
end
|
||||
end
|
||||
|
||||
pac.AddHook("Think", "pace_mctrl_Think", mctrl.Think)
|
||||
pace.mctrl = mctrl
|
||||
Reference in New Issue
Block a user