Download CommonLua/MapGen/PlacePrefabMarker.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 9.06 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/MapGen/PlacePrefabMarker.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/MapGen/PlacePrefabMarker.lua
-
curl -L -o PlacePrefabMarker.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/MapGen/PlacePrefabMarker.lua
9.06 kB
| local function GetPrefabItems(self) | |
| local items = {} | |
| local PrefabMarkers = PrefabMarkers | |
| for _, prefab in ipairs(self:FilterPrefabs()) do | |
| items[#items + 1] = PrefabMarkers[prefab] | |
| end | |
| table.sort(items) | |
| table.insert(items, 1, "") | |
| return items | |
| end | |
| DefineClass.PlacePrefabLogic = { | |
| __parents = { "PropertyObject" }, | |
| properties = { | |
| { category = "Prefab", id = "FixedPrefab", name = "Fixed Prefabs", editor = "string_list", default = false, items = GetPrefabItems, no_validate = true, buttons = {{name = "Test", func = "TestPlacePrefab"}}}, | |
| { category = "Prefab", id = "PrefabPOIType", name = "Prefab POI Type", editor = "preset_id", default = "", preset_class = "PrefabPOI" }, | |
| { category = "Prefab", id = "PrefabType", name = "Prefab Type", editor = "preset_id", default = "", preset_class = "PrefabType" }, | |
| { category = "Prefab", id = "PrefabTagsAny", name = "Prefab Tags Any", editor = "set", default = empty_table, items = function() return PrefabTagsCombo() end, three_state = true }, | |
| { category = "Prefab", id = "PrefabTagsAll", name = "Prefab Tags All", editor = "set", default = empty_table, items = function() return PrefabTagsCombo() end, three_state = true }, | |
| { category = "Prefab", id = "MaxPrefabRadius", name = "Max Allowed Radius", editor = "number", default = 0, scale = "m" }, | |
| { category = "Prefab", id = "FixAtCenter", name = "Fix At Center", editor = "bool", default = true, help = "Allow the prefab to be spawned anywhere inside the max radius" }, | |
| { category = "Prefab", id = "RandAngle", name = "Rand Angle", editor = "number", default = 0, scale = "deg" }, | |
| { category = "Prefab", id = "PlacedName", name = "Placed Name", editor = "text", default = "", read_only = true, dont_save = true, buttons = {{name = "Goto", func = "GotoPrefabAction"}} }, | |
| { category = "Prefab", id = "PlaceError", name = "Place Error", editor = "text", default = "", read_only = true, dont_save = true }, | |
| { category = "Prefab", id = "PrefabCount", name = "Prefab Count", editor = "number", default = 0, read_only = true, dont_save = true }, | |
| }, | |
| reserved_locations = false, | |
| } | |
| function PlacePrefabLogic:SetFixedPrefab(prefab) | |
| if type(prefab) == "string" then | |
| prefab = { prefab } | |
| end | |
| self.FixedPrefab = prefab | |
| end | |
| function PlacePrefabLogic:FilterPrefabs(params, all_prefabs) | |
| all_prefabs = all_prefabs or PrefabMarkers | |
| local prefabs = {} | |
| local poi_type = params and params.poi_type or self.PrefabPOIType or "" | |
| local ptype = params and params.prefab_type or self.PrefabType or "" | |
| local max_radius = params and params.max_radius or self.MaxPrefabRadius or 0 | |
| local tags_any = params and params.tags_any or self.PrefabTagsAny | |
| local tags_all = params and params.tags_all or self.PrefabTagsAll | |
| local type_tile = const.TypeTileSize | |
| for _, prefab in ipairs(all_prefabs) do | |
| if (poi_type == "" or prefab.poi_type == poi_type) | |
| and (ptype == "" or prefab.type == "" or prefab.type == ptype) | |
| and (max_radius == 0 or prefab.max_radius * type_tile <= max_radius) | |
| and MatchThreeStateSet(prefab.tags, tags_any, tags_all) | |
| then | |
| prefabs[#prefabs + 1] = prefab | |
| end | |
| end | |
| return prefabs | |
| end | |
| function PlacePrefabLogic:GetPrefabs(params) | |
| local fixed_prefabs = params and params.name or self.FixedPrefab | |
| if fixed_prefabs then | |
| local prefabs = {} | |
| if type(fixed_prefabs) == "string" then | |
| fixed_prefabs = { fixed_prefabs } | |
| end | |
| for _, name in ipairs(fixed_prefabs) do | |
| local prefab = PrefabMarkers[name] | |
| if not prefab then | |
| StoreErrorSource(self, "No such prefab:", name) | |
| else | |
| prefabs[#prefabs + 1] = prefab | |
| end | |
| end | |
| if params and params.filter_fixed then | |
| local tags_any = params and params.tags_any or self.PrefabTagsAny | |
| local tags_all = params and params.tags_all or self.PrefabTagsAll | |
| for i = #prefabs,1,-1 do | |
| if not MatchThreeStateSet(prefabs[i].tags, tags_any, tags_all) then | |
| table.remove_rotate(prefabs, i) | |
| end | |
| end | |
| end | |
| if #prefabs > 0 then | |
| return prefabs | |
| end | |
| end | |
| return self:FilterPrefabs(params) | |
| end | |
| function PlacePrefabLogic:GetError() | |
| if mapdata.IsPrefabMap and self:GetPrefabCount() == 0 then | |
| return "No matching prefabs found!" | |
| end | |
| end | |
| function PlacePrefabLogic:GetPrefabCount(params) | |
| return #self:GetPrefabs(params) | |
| end | |
| function PlacePrefabLogic:ReserveLocation(pos, radius) | |
| self.reserved_locations = table.create_add(self.reserved_locations, {pos, radius}) | |
| end | |
| function PlacePrefabLogic:GetReservedRatio() | |
| local max_radius = self.MaxPrefabRadius | |
| if max_radius <= 0 then | |
| return 100 | |
| end | |
| local radius_sum2 = 0 | |
| for _, info in ipairs(self.reserved_locations) do | |
| local radius = info[2] | |
| radius_sum2 = radius * radius | |
| end | |
| return 100 * sqrt(radius_sum2) / max_radius | |
| end | |
| function PlacePrefabLogic:CheckReservedLocations(pos, radius) | |
| --DbgClear(true) DbgAddCircle(self, self.MaxPrefabRadius, yellow) DbgAddCircle(pos, radius, blue) | |
| for _, info in ipairs(self.reserved_locations) do | |
| if IsCloser2D(pos, info[1], radius + info[2]) then | |
| --DbgAddCircle(info[1], info[2], red) | |
| return | |
| end | |
| end | |
| --DbgAddVector(pos) | |
| return true | |
| end | |
| function PlacePrefabLogic:GetPrefabLoc(seed, params) | |
| seed = seed or InteractionRand(nil, "PlacePrefab") | |
| local name, pos, angle, prefab, idx | |
| local prefabs = self:GetPrefabs(params) | |
| local retry | |
| while true do | |
| local idx | |
| if #prefabs > 1 then | |
| prefab, idx, seed = table.weighted_rand(prefabs, "weight", seed) | |
| else | |
| prefab = prefabs[1] | |
| end | |
| assert(prefab) | |
| if not prefab then | |
| return | |
| end | |
| pos = params and params.pos | |
| if not pos then | |
| pos = self:GetVisualPos() | |
| if not self.FixAtCenter then | |
| local reserved_radius | |
| if params and params.avoid_reserved_locations and self.reserved_locations then | |
| reserved_radius = (prefab.min_radius + prefab.max_radius) * const.TypeTileSize / 2 | |
| end | |
| local radius = prefab.max_radius * const.TypeTileSize | |
| local free_dist = self.MaxPrefabRadius - radius | |
| if free_dist > 0 then | |
| local center = pos | |
| pos = false | |
| local retries = params and params.avoid_reserved_retries or 16 | |
| for i=1,retries do | |
| local ra, rr | |
| ra, seed = BraidRandom(seed, 360*60) | |
| rr, seed = BraidRandom(seed, free_dist) | |
| local pos_i = RotateRadius(rr, ra, center) | |
| if not reserved_radius or self:CheckReservedLocations(pos_i, reserved_radius) then | |
| pos = pos_i | |
| break | |
| end | |
| end | |
| elseif reserved_radius and not self:CheckReservedLocations(pos, reserved_radius) then | |
| pos = false | |
| end | |
| end | |
| end | |
| if pos then | |
| name = PrefabMarkers[prefab] | |
| angle = params and params.angle | |
| if not angle then | |
| angle = self:GetAngle() | |
| local rand_angle = self.RandAngle | |
| if rand_angle > 0 then | |
| local desired_angle = params and params.desired_angle | |
| if desired_angle then | |
| local angle_diff = AngleDiff(desired_angle, angle) | |
| if abs(angle_diff) <= rand_angle then | |
| angle = desired_angle | |
| else | |
| local min_angle, max_angle = angle - rand_angle, angle + rand_angle | |
| if abs(AngleDiff(desired_angle, min_angle)) < abs(AngleDiff(desired_angle, max_angle)) then | |
| angle = min_angle | |
| else | |
| angle = max_angle | |
| end | |
| end | |
| else | |
| local da | |
| da, seed = BraidRandom(seed, -rand_angle, rand_angle) | |
| angle = angle + da | |
| end | |
| end | |
| end | |
| return name, pos, angle, prefab, seed | |
| end | |
| if #prefabs == 1 then | |
| return | |
| end | |
| table.remove_rotate(prefabs, idx) | |
| end | |
| end | |
| function PlacePrefabLogic:PlacePrefab(seed, params) | |
| local success, err, objs, inv_bbox | |
| local name, pos, angle, prefab, seed = self:GetPrefabLoc(seed, params) | |
| if not name then | |
| err = "No matching prefabs found!" | |
| else | |
| success, err, objs, inv_bbox = procall(PlacePrefab, name, pos, angle, seed, params) | |
| end | |
| self.PlaceError = err | |
| self.PlacedName = name | |
| ObjModified(self) | |
| return err, objs, pos, prefab, name, inv_bbox | |
| end | |
| function PlacePrefabLogic:EditorCallbackGenerate(generator, object_source, placed_objects, prefab_list) | |
| local mark = placed_objects[self] | |
| local info = mark and prefab_list[mark] | |
| local ptype = info and info[4] | |
| if ptype then | |
| self.PrefabType = ptype | |
| end | |
| end | |
| ---- | |
| DefineClass.PlacePrefabMarker = { | |
| __parents = { "RadiusMarker", "PlacePrefabLogic", "PrefabSourceInfo" }, | |
| editor_text_color = RGB(50, 50, 100), | |
| editor_color = RGB(150, 150, 0), | |
| } | |
| function PlacePrefabMarker:GetMeshRadius() | |
| local max_radius = self.MaxPrefabRadius | |
| for _, prefab in ipairs(self:GetPrefabs()) do | |
| max_radius = Max(max_radius, prefab.max_radius) | |
| end | |
| return max_radius | |
| end | |
| function PlacePrefabMarker:OnEditorSetProperty(prop_id, old_value, ged) | |
| local meta = self:GetPropertyMetadata(prop_id) | |
| if meta and meta.category == "Prefab" then | |
| self:UpdateMeshRadius() | |
| end | |
| end | |
| function PlacePrefabMarker:TestPlacePrefab() | |
| local err, objs = self:PlacePrefab(AsyncRand(), { | |
| create_undo = true, | |
| }) | |
| if err then | |
| print(err) | |
| end | |
| end | |