Download CommonLua/Editor/XEditor/XPlaceMultipleObjectsToolBase.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 6.93 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/Editor/XEditor/XPlaceMultipleObjectsToolBase.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/Editor/XEditor/XPlaceMultipleObjectsToolBase.lua
-
curl -L -o XPlaceMultipleObjectsToolBase.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/Editor/XEditor/XPlaceMultipleObjectsToolBase.lua
6.93 kB
| DefineClass.XPlaceMultipleObjectsToolBase = { | |
| __parents = { "XEditorBrushTool" }, | |
| properties = { | |
| { id = "Distance", editor = "number", default = 5 * guim, scale = "m", min = guim , max = 100 * guim, step = guim / 10, | |
| slider = true, persisted_setting = true, auto_select_all = true, sort_order = -1, }, | |
| { id = "MinDistance", name = "Min distance", editor = "number", default = 0, scale = "m", min = 0, max = function(self) return self:GetDistance() end, step = guim / 10, | |
| slider = true, persisted_setting = true, auto_select_all = true, sort_order = -1, }, | |
| }, | |
| deleted_objects = false, | |
| new_objects = false, | |
| new_positions = false, | |
| box_changed = false, | |
| init_terrain_type = false, | |
| terrain_normal = false, | |
| distance_visualization = false, | |
| } | |
| function XPlaceMultipleObjectsToolBase:Init() | |
| self.distance_visualization = Mesh:new() | |
| self.distance_visualization:SetMeshFlags(const.mfWorldSpace) | |
| self.distance_visualization:SetShader(ProceduralMeshShaders.mesh_linelist) | |
| self.distance_visualization:SetPos(point(0, 0)) | |
| end | |
| function XPlaceMultipleObjectsToolBase:Done() | |
| self.distance_visualization:delete() | |
| end | |
| function XPlaceMultipleObjectsToolBase:OnEditorSetProperty(prop_id, old_value, ged) | |
| if prop_id == "Distance" then | |
| self:SetMinDistance(Min(self:GetMinDistance(), self:GetDistance())) | |
| end | |
| end | |
| function XPlaceMultipleObjectsToolBase:UpdateCursor() | |
| local v_pstr = self:CreateCircleCursor() | |
| local strength = self:GetCursorHeight() | |
| if strength then | |
| v_pstr:AppendVertex(point(0, 0, 0)) | |
| v_pstr:AppendVertex(point(0, 0, strength)) | |
| end | |
| self.cursor_mesh:SetMeshFlags(self.cursor_default_flags + self:GetCursorExtraFlags()) | |
| local pt = self:GetWorldMousePos() | |
| local radius = self:GetCursorRadius() | |
| self.box_changed = box(pt:x() - radius, pt:y() - radius, pt:x() + radius, pt:y() + radius) | |
| self.box_changed = terrain.ClampBox(self.box_changed) | |
| local distance = self:GetDistance() | |
| local bxDistanceGrid = self.box_changed / distance | |
| local vpstr = pstr("") | |
| for i = bxDistanceGrid:miny(), bxDistanceGrid:maxy() do | |
| for j = bxDistanceGrid:minx(), bxDistanceGrid:maxx() do | |
| local ptDistance = point(j, i) | |
| local ptReal = ptDistance * distance | |
| local color = self:GetCursorColor() | |
| if ptReal:Dist(pt) <= self:GetCursorRadius() then | |
| ptReal = ptReal:SetZ(terrain.GetHeight(ptReal)) | |
| vpstr:AppendVertex(ptReal + point(-200, -200, 0), color) | |
| vpstr:AppendVertex(ptReal + point(200, 200, 0)) | |
| vpstr:AppendVertex(ptReal + point(-200, 200, 0), color) | |
| vpstr:AppendVertex(ptReal + point(200, -200, 0)) | |
| end | |
| end | |
| end | |
| self.distance_visualization:SetMesh(vpstr) | |
| self.cursor_mesh:SetMesh(v_pstr) | |
| self.cursor_mesh:SetPos(GetTerrainCursor()) | |
| end | |
| function XPlaceMultipleObjectsToolBase:GetCursorRadius() | |
| local radius = self:GetSize() / 2 | |
| return radius, radius | |
| end | |
| function XPlaceMultipleObjectsToolBase:MarkObjectsForDelete() | |
| local radius = self:GetCursorRadius() | |
| MapForEach(GetTerrainCursor(), radius, function(o) | |
| local classes = self:GetClassesForDelete() or {} | |
| if not self.deleted_objects[o] and not self.new_objects[o] and XEditorFilters:IsVisible(o) and IsKindOfClasses(o, classes) | |
| and (not self.init_terrain_type or self.init_terrain_type[terrain.GetTerrainType(o:GetPos())])then | |
| self.deleted_objects[o] = true | |
| o:ClearEnumFlags(const.efVisible) | |
| end | |
| end) | |
| end | |
| function XPlaceMultipleObjectsToolBase:PlaceObjects(pt) | |
| local newobjs = {} | |
| local distance = self:GetDistance() | |
| local min_distance = self:GetMinDistance() | |
| local bxDistanceGrid = self.box_changed / distance | |
| for i = bxDistanceGrid:miny(), bxDistanceGrid:maxy() do | |
| for j = bxDistanceGrid:minx(), bxDistanceGrid:maxx() do | |
| local ptDistance = point(j, i) | |
| local ptReal = ptDistance * distance | |
| local offset = (distance - min_distance) / 2 | |
| local randX = -offset + AsyncRand(2 * offset) | |
| local randY = -offset + AsyncRand(2 * offset) | |
| ptReal = ptReal + point(randX, randY) | |
| local classes = self:GetClassesForPlace(ptReal) | |
| local class = classes and classes[AsyncRand(#classes) + 1] | |
| local terrainNormal, scale, scaleDeviation, angle, colorMin, colorMax = self:GetParams(ptReal) | |
| if ptReal:InBox2D(GetMapBox()) and ptReal:Dist(pt) <= self:GetCursorRadius() and (not self.new_positions[j] or not self.new_positions[j][i]) and class and scale | |
| and (not self.init_terrain_type or self.init_terrain_type[terrain.GetTerrainType(ptReal)]) then | |
| local axis = terrainNormal and terrain.GetTerrainNormal(ptReal) or axis_z | |
| local obj = XEditorPlaceObject(class) | |
| scaleDeviation = scaleDeviation == 0 and 0 or -scaleDeviation + AsyncRand(2 * scaleDeviation) | |
| scale = Clamp(MulDivRound(scale, 100 + scaleDeviation, 100), 10, 250) | |
| angle = angle * 60 | |
| angle = AsyncRand(-angle, angle) | |
| local minR, minG, minB = GetRGB(colorMin) | |
| local maxR, maxG, maxB = GetRGB(colorMax) | |
| minR, maxR = MinMax(minR, maxR) | |
| minG, maxG = MinMax(minG, maxG) | |
| minB, maxB = MinMax(minB, maxB) | |
| local color = RGB(AsyncRand(minR, maxR), AsyncRand(minG, maxG), AsyncRand(minB, maxB)) | |
| obj:SetPos(ptReal) | |
| obj:SetInvalidZ() | |
| obj:SetScale(scale) | |
| obj:SetOrientation(axis, angle) | |
| obj:SetColorModifier(color) | |
| obj:RestoreHierarchyEnumFlags() -- will rebuild surfaces if required | |
| obj:SetHierarchyEnumFlags(const.efVisible) | |
| obj:SetGameFlags(const.gofPermanent) | |
| obj:SetCollection(Collections[editor.GetLockedCollectionIdx()]) | |
| self.new_positions[j] = self.new_positions[j] or {} | |
| self.new_positions[j][i] = true | |
| self.new_objects[obj] = true | |
| newobjs[#newobjs + 1] = obj | |
| end | |
| end | |
| end | |
| Msg("EditorCallback", "EditorCallbackPlace", newobjs) | |
| end | |
| function XPlaceMultipleObjectsToolBase:StartDraw(pt) | |
| SuspendPassEdits("XEditorPlaceMultipleObjects") | |
| self.deleted_objects = {} | |
| self.new_objects = {} | |
| self.new_positions = {} | |
| if terminal.IsKeyPressed(const.vkControl) then self.init_terrain_type = {[terrain.GetTerrainType(pt)] = true} end | |
| if terminal.IsKeyPressed(const.vkAlt) then self.terrain_normal = true end | |
| end | |
| function XPlaceMultipleObjectsToolBase:Draw(pt1, pt2) | |
| self:MarkObjectsForDelete() | |
| self:PlaceObjects(pt2) | |
| end | |
| function XPlaceMultipleObjectsToolBase:EndDraw(pt) | |
| local objs = table.validate(table.keys(self.deleted_objects)) | |
| for _, obj in ipairs(objs) do obj:SetEnumFlags(const.efVisible) end | |
| XEditorUndo:BeginOp({ objects = objs, name = "Placed multiple objects" }) | |
| Msg("EditorCallback", "EditorCallbackDelete", objs) | |
| for _, obj in ipairs(objs) do obj:delete() end | |
| XEditorUndo:EndOp(table.keys(self.new_objects)) | |
| ResumePassEdits("XEditorPlaceMultipleObjects", true) | |
| self.deleted_objects = false | |
| self.new_objects = false | |
| self.new_positions = false | |
| self.init_terrain_type = false | |
| self.terrain_normal = false | |
| end | |
| function XPlaceMultipleObjectsToolBase:GetParams() | |
| end | |
| function XPlaceMultipleObjectsToolBase:GetClassesForDelete() | |
| end | |
| function XPlaceMultipleObjectsToolBase:GetClassesForPlace(pt) | |
| end |