|
local cardinal_dirs = {"east", "west", "north", "south"} |
|
local dir_angle = { ["east"] = 90 * 60, ["west"] = 270 * 60, ["south"] = 180 * 60, ["north"] = 0 } |
|
|
|
local function GetPlaneDir(plane) |
|
for _, dir in ipairs(cardinal_dirs) do |
|
if string.match(plane:lower(), dir) then |
|
return dir |
|
end |
|
end |
|
end |
|
|
|
MapVar("s_BorderBuildingAutoAttachesRequired", 0) |
|
MapVar("s_BorderBuildingAutoAttachesCreated", 0) |
|
|
|
DefineClass.BorderBuilding = { |
|
__parents = {"AutoAttachObject", "EditorCallbackObject", "EditorSelectedObject"}, |
|
|
|
properties = { |
|
{category = "Windows Auto Attaches", id = "east", name = "East", editor = "bool", default = true, help = "Uncheck to remove window auto attaches from this side"}, |
|
{category = "Windows Auto Attaches", id = "west", name = "West", editor = "bool", default = true, help = "Uncheck to remove window auto attaches from this side"}, |
|
{category = "Windows Auto Attaches", id = "north", name = "North", editor = "bool", default = true, help = "Uncheck to remove window auto attaches from this side"}, |
|
{category = "Windows Auto Attaches", id = "south", name = "South", editor = "bool", default = true, help = "Uncheck to remove window auto attaches from this side"}, |
|
{category = "Windows Auto Attaches", id = "Recalc", editor = "buttons", default = false, |
|
buttons = { |
|
{ name = "Recalc Visible Sides", func = function(self) |
|
self:CalcVisibleSides() |
|
end}, |
|
{ name = "Turn All Sides ON", func = function(self) |
|
self:TurnAllSides(true) |
|
end}, |
|
{ name = "Turn All Sides OFF", func = function(self) |
|
self:TurnAllSides(false) |
|
end}, |
|
}, |
|
}, |
|
}, |
|
|
|
texts = false, |
|
} |
|
|
|
function BorderBuilding:ShouldAttach(attach) |
|
s_BorderBuildingAutoAttachesRequired = s_BorderBuildingAutoAttachesRequired + 1 |
|
|
|
local spot_ann = self:GetSpotAnnotation(attach.spot_idx) |
|
if not spot_ann then return true end |
|
|
|
local dir = GetPlaneDir(spot_ann) |
|
if not dir then return true end |
|
|
|
return self[dir] |
|
end |
|
|
|
function BorderBuilding:OnAttachCreated(attach, spot) |
|
s_BorderBuildingAutoAttachesCreated = s_BorderBuildingAutoAttachesCreated + 1 |
|
|
|
if IsKindOfClasses(attach, "WindowTunnelObject", "Door") then |
|
attach.AttachLight = false |
|
end |
|
end |
|
|
|
function BorderBuilding:UpdateAutoAttaches() |
|
self:SetAutoAttachMode(self:GetAutoAttachMode()) |
|
end |
|
|
|
function BorderBuilding:GatherWallWindows() |
|
local spots_used = {} |
|
local spots = table.imap(AutoAttachPresets[self.class], function(attach) |
|
spots_used[attach.name] = true |
|
end) |
|
local spots = table.keys(spots_used) |
|
|
|
local planes = {} |
|
local sides = {} |
|
for _, spot_name in ipairs(spots) do |
|
local first, last = self:GetSpotRange(spot_name) |
|
for spot_idx = first, last do |
|
local spot_pos = self:GetSpotPos(spot_idx) |
|
local spot_ann = self:GetSpotAnnotation(spot_idx) |
|
if spot_ann then |
|
local dir = GetPlaneDir(spot_ann) |
|
if dir then |
|
local spot = {pos = spot_pos, name = spot_name, idx = spot_idx} |
|
planes[spot_ann] = planes[spot_ann] or {dir = dir} |
|
table.insert(planes[spot_ann], spot) |
|
sides[dir] = sides[dir] or {} |
|
table.insert(sides[dir], spot) |
|
end |
|
end |
|
end |
|
end |
|
|
|
return planes, sides |
|
end |
|
|
|
function BorderBuilding:CalcVisibleSides() |
|
local center = GetMapBox():Center() |
|
local planes, sides = self:GatherWallWindows() |
|
local side_count = {} |
|
for plane_name, plane in pairs(planes) do |
|
local dir = GetPlaneDir(plane_name) |
|
local angle = self:GetAngle() + dir_angle[dir] |
|
local plane_norm = Rotate(point(4096, 0), angle) |
|
local plane_data = side_count[dir] or {total = 0, visible = 0} |
|
side_count[dir] = plane_data |
|
plane_data.total = plane_data.total + #plane |
|
if Dot(center - plane[1].pos, plane_norm) > 0 then |
|
plane_data.visible = plane_data.visible + #plane |
|
end |
|
end |
|
|
|
for dir, side in pairs(side_count) do |
|
self:SetProperty(dir, side.visible > side.total / 2) |
|
end |
|
ObjModified(self) |
|
|
|
self:UpdateAutoAttaches() |
|
end |
|
|
|
function BorderBuilding:TurnAllSides(state) |
|
for _, dir in pairs(cardinal_dirs) do |
|
self:SetProperty(dir, state) |
|
end |
|
ObjModified(self) |
|
self:UpdateAutoAttaches() |
|
end |
|
|
|
function BorderBuilding:OnEditorSetProperty(prop_id) |
|
if table.find(cardinal_dirs, prop_id) then |
|
self:UpdateAutoAttaches() |
|
end |
|
end |
|
|
|
function BorderBuilding:DelayedRecalcAutoAttaches() |
|
DelayedCall(500, function(self) |
|
self:CalcVisibleSides() |
|
self:UpdateAutoAttaches() |
|
end, self) |
|
end |
|
|
|
BorderBuilding.EditorCallbackMove = BorderBuilding.DelayedRecalcAutoAttaches |
|
BorderBuilding.EditorCallbackRotate = BorderBuilding.DelayedRecalcAutoAttaches |
|
BorderBuilding.EditorCallbackPlace = BorderBuilding.DelayedRecalcAutoAttaches |
|
|
|
function BorderBuilding:EditorSelect(selected) |
|
if selected then |
|
local center = self:GetPos() |
|
local high_z = self:GetObjectBBox():sizez() + guim |
|
local _, sides = self:GatherWallWindows() |
|
for dir, spots in pairs(sides) do |
|
local pos = point30 |
|
for _, spot in pairs(spots) do |
|
pos = pos + spot.pos - center |
|
end |
|
pos = (pos / #spots):SetZ(high_z) |
|
local text = PlaceText(dir:upper(), pos, const.clrGreen) |
|
self:Attach(text) |
|
text:SetAttachOffset(pos) |
|
self.texts = self.texts or {} |
|
table.insert(self.texts, text) |
|
end |
|
elseif self.texts then |
|
for _, text in ipairs(self.texts) do |
|
if IsValid(text) then |
|
text:Detach() |
|
DoneObject(text) |
|
end |
|
end |
|
self.texts = false |
|
end |
|
end |
|
|
|
function BorderBuildingsRecalcVisibleSides() |
|
s_BorderBuildingAutoAttachesRequired = 0 |
|
s_BorderBuildingAutoAttachesCreated = 0 |
|
|
|
local buildings = 0 |
|
MapForEach("map", "BorderBuilding", function(bld) |
|
buildings = buildings + 1 |
|
bld:CalcVisibleSides() |
|
bld:UpdateAutoAttaches() |
|
end) |
|
|
|
printf("BorderBuilding(s): %d, Auto Attaches Created/Required: %d/%d(%d%%)", buildings, |
|
s_BorderBuildingAutoAttachesCreated, s_BorderBuildingAutoAttachesRequired, |
|
100 * s_BorderBuildingAutoAttachesCreated / s_BorderBuildingAutoAttachesRequired) |
|
end |
|
|
|
function SelectionBorderBuildingToggleWall(dir) |
|
for _, obj in ipairs(editor.GetSel() or empty_table) do |
|
if IsKindOf(obj, "BorderBuilding") then |
|
obj:SetProperty(dir, not obj:GetProperty(dir)) |
|
obj:UpdateAutoAttaches() |
|
end |
|
end |
|
end |
|
|