Модуль:Entity Sprite/all: различия между версиями
Pok (обсуждение | вклад) мНет описания правки |
Pok (обсуждение | вклад) Нет описания правки |
||
| (не показана 51 промежуточная версия этого же участника) | |||
| Строка 1: | Строка 1: | ||
local p = {} | local p = {} | ||
local JsonPaths = require('Module:JsonPaths') | |||
local function | local function normalizeSpritePath(path) | ||
if path == nil then | |||
return nil | |||
end | |||
path = mw.text.trim(tostring(path)) | |||
path = path:gsub("^/Textures/?", "") | |||
return path | |||
end | |||
local function normalizeData(data) | |||
if type(data) ~= "table" then | |||
return nil | |||
end | |||
if type(data.id) == "table" then | |||
return data.id | |||
end | |||
return data | |||
end | end | ||
local function | local function buildEntryKey(entry) | ||
local parts = {} | |||
local function addField(name, value) | |||
if value ~= nil then | |||
table.insert(parts, name .. "=" .. tostring(value)) | |||
end | |||
end | |||
addField("sprite", normalizeSpritePath(entry.sprite)) | |||
addField("state", entry.state) | |||
addField("scale", entry.scale) | |||
addField("enableOverrideDir", entry.enableOverrideDir) | |||
addField("overrideDir", entry.overrideDir) | |||
if entry.layers and type(entry.layers) == "table" then | |||
local layers = {} | |||
for _, layer in ipairs(entry.layers) do | |||
local layerParts = {} | |||
for k, v in pairs(layer) do | |||
if type(v) ~= "table" then | |||
layerParts[#layerParts + 1] = k .. "=" .. tostring(v) | |||
end | |||
end | |||
table.sort(layerParts) | |||
table.insert(layers, table.concat(layerParts, ",")) | |||
end | |||
table.sort(layers) | |||
table.insert(parts, "layers=" .. table.concat(layers, "|")) | |||
end | |||
table.sort(parts) | |||
return table.concat(parts, ";") | |||
end | |||
local function getSpriteStates(entry) | |||
local result = {} | |||
if entry.layers and type(entry.layers) == "table" then | |||
for _, layer in ipairs(entry.layers) do | |||
if layer.visible ~= false and layer.state then | |||
table.insert(result, { | |||
state = tostring(layer.state), | |||
sprite = normalizeSpritePath(layer.sprite or entry.sprite) | |||
}) | |||
end | |||
end | |||
elseif entry.state and entry.sprite then | |||
table.insert(result, { | |||
state = tostring(entry.state), | |||
sprite = normalizeSpritePath(entry.sprite) | |||
}) | |||
end | |||
return (#result > 0) and result or nil | |||
end | end | ||
local function getSpritePath(entry) | local function getSpritePath(entry) | ||
if entry.sprite then | |||
return normalizeSpritePath(entry.sprite) | |||
end | |||
if entry.layers and type(entry.layers) == "table" then | |||
for _, layer in ipairs(entry.layers) do | |||
if layer.sprite then | |||
return normalizeSpritePath(layer.sprite) | |||
end | |||
end | |||
end | |||
return nil | |||
end | |||
local function splitCsv(value) | |||
local result = {} | |||
if value == nil then | |||
return nil | |||
end | |||
value = mw.text.trim(tostring(value)) | |||
if value == "" then | |||
return nil | |||
end | |||
for part in mw.text.gsplit(value, ",", true) do | |||
local item = mw.text.trim(part) | |||
if item ~= "" then | |||
table.insert(result, item) | |||
end | |||
end | |||
return (#result > 0) and result or nil | |||
end | |||
local function buildSet(value) | |||
local list = splitCsv(value) | |||
if not list then | |||
return nil | |||
end | |||
local set = {} | |||
for _, item in ipairs(list) do | |||
set[item] = true | |||
end | |||
return set | |||
end | |||
local function getParents(parentData, id) | |||
if not parentData or type(parentData) ~= "table" or not id then | |||
return nil | |||
end | |||
local parents = parentData[id] | |||
if type(parents) ~= "table" then | |||
return nil | |||
end | |||
return parents | |||
end | |||
local function hasAnyParent(parents, set) | |||
if not parents or not set then | |||
return false | |||
end | |||
for _, parent in ipairs(parents) do | |||
if set[parent] then | |||
return true | |||
end | |||
end | |||
return false | |||
end | end | ||
local function | local function shouldIncludeEntry(id, whitelistSet, blacklistSet, parentData) | ||
local parents = getParents(parentData, id) | |||
if whitelistSet and not hasAnyParent(parents, whitelistSet) then | |||
return false | |||
end | |||
if blacklistSet and hasAnyParent(parents, blacklistSet) then | |||
return false | |||
end | |||
return true | |||
end | end | ||
local function | local function filterSpriteData(spriteData, parentData, whitelistSet, blacklistSet, project) | ||
local result = {} | |||
for id, entry in pairs(spriteData) do | |||
if shouldIncludeEntry(id, whitelistSet, blacklistSet, parentData) then | |||
if project == "" or JsonPaths.has(id, project) then | |||
result[id] = entry | |||
end | |||
end | |||
end | |||
return result | |||
end | |||
local function buildFileLink(id, project) | |||
return "[[:Файл:" .. JsonPaths.prefixFile(id) .. ".png]]" | |||
end | |||
local function buildSpriteUrl(baseUrl, spritePath) | |||
return baseUrl .. spritePath | |||
end | |||
local function buildSpritePathLink(baseUrl, spritePath) | |||
local url = buildSpriteUrl(baseUrl, spritePath) | |||
return "[" .. url .. " " .. spritePath .. "]" | |||
end | |||
local function buildStateLink(baseUrl, spritePath, state) | |||
local url = buildSpriteUrl(baseUrl, spritePath) .. "/" .. state .. ".png" | |||
return "[" .. url .. " " .. state .. "]" | |||
end | |||
local function buildSpriteStateLinks(baseUrl, states) | |||
if not states or #states == 0 then | |||
return "" | |||
end | |||
local links = {} | |||
for _, item in ipairs(states) do | |||
if item.sprite and item.state then | |||
table.insert(links, buildStateLink(baseUrl, item.sprite, item.state)) | |||
end | |||
end | |||
return table.concat(links, ", ") | |||
end | |||
local function buildRepeatSpriteValue(baseUrl, entry) | |||
local spritePath = getSpritePath(entry) | |||
if not spritePath then | |||
return "" | |||
end | |||
local pathLink = buildSpritePathLink(baseUrl, spritePath) | |||
local states = getSpriteStates(entry) | |||
if states and #states > 0 and states[1].state and states[1].state ~= "" then | |||
return pathLink .. " (" .. buildStateLink(baseUrl, spritePath, states[1].state) .. ")" | |||
end | |||
return pathLink | |||
end | end | ||
local function generateRepeatTemplate(data) | local function generateRepeatTemplate(data, project, baseUrl) | ||
local spriteGroups = {} | |||
for id, entry in pairs(data) do | |||
local key = buildEntryKey(entry) | |||
spriteGroups[key] = spriteGroups[key] or {} | |||
table.insert(spriteGroups[key], { id = id, entry = entry }) | |||
end | |||
local result = {} | |||
for _, group in pairs(spriteGroups) do | |||
if #group > 1 then | |||
local idLinks = {} | |||
for _, obj in ipairs(group) do | |||
table.insert(idLinks, buildFileLink(obj.id, project)) | |||
end | |||
local firstId = group[1].id | |||
local firstEntry = group[1].entry | |||
local spriteValue = buildRepeatSpriteValue(baseUrl, firstEntry) | |||
table.insert(result, mw.getCurrentFrame():preprocess( | |||
"{{Entity Sprite/Repeat|файлы=" .. table.concat(idLinks, " ") .. | |||
"|перенаправление=" .. JsonPaths.prefixFile(firstId) .. | |||
"|id=" .. firstId .. | |||
"|спрайт=" .. spriteValue .. | |||
"}}" | |||
)) | |||
end | |||
end | |||
return table.concat(result, "\n") | |||
end | end | ||
local function generateTemplate(entry, | local function generateTemplate(id, entry, baseUrl, project) | ||
local spritePath = getSpritePath(entry) | |||
if not id or not spritePath then | |||
return nil | |||
end | |||
local states = getSpriteStates(entry) | |||
local stateStr = buildSpriteStateLinks(baseUrl, states) | |||
return mw.getCurrentFrame():preprocess( | |||
"{{Entity Sprite/Image|файл=" .. JsonPaths.prefixFile(id) .. | |||
"|id=" .. id .. | |||
"|путь=" .. buildSpriteUrl(baseUrl, spritePath) .. | |||
"|state=" .. stateStr .. | |||
"}}" | |||
) | |||
end | end | ||
function p.main(frame) | function p.main(frame) | ||
local action = frame.args[1] | |||
local json = frame.args.json or "component/Sprite.json" | |||
local project = JsonPaths.project() | |||
local baseUrl = JsonPaths.git() .. "/Resources/Textures/" | |||
local dataPage = JsonPaths.get(json) | |||
local parentPage = JsonPaths.get("entity parent.json") | |||
local spriteDataRaw = mw.loadData(dataPage) | |||
local parentDataRaw = mw.loadData(parentPage) | |||
local spriteData = normalizeData(spriteDataRaw) | |||
local parentData = normalizeData(parentDataRaw) | |||
if not spriteData or type(spriteData) ~= "table" then | |||
return "Ошибка загрузки JSON: " .. dataPage | |||
end | |||
if not parentData or type(parentData) ~= "table" then | |||
return "Ошибка загрузки JSON: " .. parentPage | |||
end | |||
local whitelistSet = buildSet(frame.args.whitelistParent) | |||
local blacklistSet = buildSet(frame.args.blacklistParent) | |||
local filteredData = filterSpriteData(spriteData, parentData, whitelistSet, blacklistSet, project) | |||
if action == "repeat" then | |||
return generateRepeatTemplate(filteredData, project, baseUrl) | |||
elseif action == "image" then | |||
local result = {} | |||
for id, entry in pairs(filteredData) do | |||
local t = generateTemplate(id, entry, baseUrl, project) | |||
if t then | |||
table.insert(result, t) | |||
end | |||
end | |||
return table.concat(result, "\n") | |||
end | |||
return nil | |||
end | end | ||
return p | return p | ||