File size: 4,435 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 |
-- ExtrasGen based editor tools place fences, decals, etc. alongside these line guide helper objects
--
-- The line guide is aligned to the object's X axis, and the line normal direction - to the Z axis.
-- The line guide length is determined by the object's Scale; it is StandardLength long at normal scale.
DefineClass.EditorLineGuide = {
__parents = { "Mesh", "CollideLuaObject", "EditorVisibleObject", "EditorCallbackObject" },
StandardLength = 10 * guim, -- length at 100% scale
NormalColor = RGB(240, 240, 240),
HighlightColor = RGB(240, 230, 150),
SelectedColor = RGB(240, 230, 40),
collide_mesh = false,
color = RGB(240, 240, 240),
}
-- rotates the object so that axis1 before the rotation matches axis2 after the rotation
local function rotate_to_match(obj, axis1, axis2)
axis1, axis2 = SetLen(axis1, 4096), SetLen(axis2, 4096)
local axis = Cross(axis1, axis2)
if axis ~= point30 then
obj:Rotate(axis, GetAngle(axis1, axis2))
end
end
function EditorLineGuide:Set(pos1, pos2, normal)
local pos = (pos1 + pos2) / 2
self:SetPos(pos)
self:SetOrientation(normal, 0)
self:SetScale(MulDivRound((pos1 - pos2):Len(), 100, self.StandardLength))
local axis1 = self:GetRelativePoint(axis_y) - self:GetPos()
local axis2 = pos1 - self:GetPos()
rotate_to_match(self, axis1, axis2)
self:SetGameFlags(const.gofPermanent)
self:UpdateVisuals()
end
function EditorLineGuide:GetLength()
return MulDivRound(self.StandardLength, self:GetScale(), 100)
end
function EditorLineGuide:SetLength(length)
self:SetScale(MulDivRound(length, 100, self.StandardLength))
self:UpdateVisuals()
end
function EditorLineGuide:GetPos1()
return self:GetRelativePoint(SetLen(axis_y, self.StandardLength / 2))
end
function EditorLineGuide:GetPos2()
return self:GetRelativePoint(-SetLen(axis_y, self.StandardLength / 2))
end
function EditorLineGuide:GetNormal()
return self:GetRelativePoint(axis_z) - self:GetVisualPos()
end
function EditorLineGuide:IsHorizontal()
local tangent = self:GetRelativePoint(axis_y) - self:GetPos()
local angle = GetAngle(tangent, axis_z) / 60
return abs(angle) > 85
end
function EditorLineGuide:IsVertical()
local tangent = self:GetRelativePoint(axis_y) - self:GetPos()
local angle = GetAngle(tangent, axis_z) / 60
return angle < 5 or angle > 175
end
function EditorLineGuide:UpdateVisuals()
if self:GetScale() == 0 then
self:SetMesh(pstr(""))
return
end
local offset = SetLen(axis_y, self.StandardLength / 2)
local arrowlen = MulDivRound(guim / 2, 100, self:GetScale())
local normal = SetLen(axis_z, arrowlen)
local along = SetLen(offset, arrowlen / 2)
local str = pstr("")
str:AppendVertex(offset, self.color)
str:AppendVertex(-offset)
str:AppendVertex(-along)
str:AppendVertex(normal)
str:AppendVertex(normal)
str:AppendVertex(along)
self:SetShader(ProceduralMeshShaders.mesh_linelist)
self:SetMesh(str)
if IsEditorActive() then
self:SetEnumFlags(const.efVisible)
end
end
EditorLineGuide.EditorCallbackPlaceCursor = EditorLineGuide.UpdateVisuals
EditorLineGuide.EditorCallbackPlace = EditorLineGuide.UpdateVisuals
EditorLineGuide.EditorCallbackScale = EditorLineGuide.UpdateVisuals
EditorLineGuide.EditorEnter = EditorLineGuide.UpdateVisuals
function EditorLineGuide:GetBBox()
local grow = guim / 4
local length = self:GetLength()
return GrowBox(box(0, -length / 2, 0, 0, length / 2, 0), grow, grow, grow)
end
function EditorLineGuide:TestRay(pos, dir)
-- TODO: Refactor C++ code to expect intersection point to be returned
return true
end
----- Selection and highlighting on hover
if FirstLoad then
SelectedLineGuides = {}
end
function EditorLineGuide:SetHighlighted(highlight)
local selected = table.find(SelectedLineGuides, self)
self.color = selected and self.SelectedColor or
highlight and self.HighlightColor or self.NormalColor
self:UpdateVisuals()
end
function OnMsg.EditorSelectionChanged(objects)
local lines = table.ifilter(objects, function(idx, obj) return IsKindOf(obj, "EditorLineGuide") end )
if #lines > 0 then
for _, line in ipairs(table.subtraction(lines, SelectedLineGuides)) do
line.color = line.SelectedColor
line:UpdateVisuals()
end
end
if #SelectedLineGuides > 0 then
for _, line in ipairs(table.subtraction(SelectedLineGuides, lines)) do
if IsValid(line) then
line.color = nil
line:UpdateVisuals()
end
end
end
SelectedLineGuides = lines
end
|