diff --git a/macrovision.js b/macrovision.js index 7884e5a9..87c8a501 100644 --- a/macrovision.js +++ b/macrovision.js @@ -33,7 +33,9 @@ let sizeHandle = null; let worldSizeDirty = false; - +const tagDefs = { + "anthro": "Anthro" +} math.createUnit("humans", { definition: "5.75 feet" @@ -307,7 +309,6 @@ function drawScale(ifDirty = false) { return; function drawTicks(/** @type {CanvasRenderingContext2D} */ ctx, pixelsPer, heightPer) { let total = heightPer.clone(); - console.log(total) total.value = 0; for (let y = ctx.canvas.clientHeight - 50; y >= 50; y -= pixelsPer) { drawTick(ctx, 50, y, total); @@ -407,6 +408,8 @@ function createEntityMaker(info, views, sizes) { const maker = {}; maker.name = info.name; + maker.info = info; + maker.constructor = () => makeEntity(info, views, sizes); maker.authors = []; maker.owners = []; @@ -2293,6 +2296,40 @@ function makeCustomEntity(url, x=0.5, y=0.5) { entity.ephemeral = true; displayEntity(entity, "custom", x, y, true, true); } + +const filterDefs = { + none: { + id: "none", + name: "None", + extract: maker => [], + render: name => name + }, + author: { + id: "author", + name: "Authors", + extract: maker => maker.authors ? maker.authors : [], + render: author => attributionData.people[author].name + }, + owner: { + id: "owner", + name: "Owners", + extract: maker => maker.owners ? maker.owners : [], + render: owner => attributionData.people[owner].name + }, + species: { + id: "species", + name: "Species", + extract: maker => maker.info && maker.info.species ? [maker.info.species] : [], + render: species => species + }, + tags: { + id: "tags", + name: "Tags", + extract: maker => maker.info && maker.info.tags ? maker.info.tags : [], + render: tag => tagDefs[tag] + } +} + function prepareEntities() { availableEntities["buildings"] = makeBuildings(); availableEntities["characters"] = makeCharacters(); @@ -2321,8 +2358,11 @@ function prepareEntities() { holder.appendChild(categorySelect); filterHolder.appendChild(filterSelect); - const authorSet = new Set(); - const ownerSet = new Set(); + const filterSets = {}; + + Object.values(filterDefs).forEach(filter => { + filterSets[filter.id] = new Set(); + }) Object.entries(availableEntities).forEach(([category, entityList]) => { const select = document.createElement("select"); @@ -2339,18 +2379,11 @@ function prepareEntities() { option.classList.add("nsfw"); } - if (entity.authors) { - entity.authors.forEach(a => { - authorSet.add(a); - }) - } - - if (entity.owners) { - entity.owners.forEach(o => { - ownerSet.add(o); - }) - } - + Object.values(filterDefs).forEach(filter => { + filter.extract(entity).forEach(result => { + filterSets[filter.id].add(result); + }); + }); availableEntitiesByName[entity.name] = entity; }; @@ -2389,50 +2422,27 @@ function prepareEntities() { holder.appendChild(button); }); - const noFilter = document.createElement("option"); - noFilter.innerText = "No Filter"; - noFilter.value = "none"; - const authorFilter = document.createElement("option"); - authorFilter.innerText = "Author"; - authorFilter.value = "author"; - const ownerFilter = document.createElement("option"); - ownerFilter.innerText = "Owner"; - ownerFilter.value = "owner"; - - filterSelect.appendChild(noFilter); - filterSelect.appendChild(authorFilter); - filterSelect.appendChild(ownerFilter); - - const authorFilterSelect = document.createElement("select"); - authorFilterSelect.classList.add("filter-select"); - authorFilterSelect.id = "filter-author"; - filterHolder.appendChild(authorFilterSelect); - - Array.from(authorSet).map(author => [author, attributionData.people[author].name]).sort((e1, e2) => e1[1].toLowerCase().localeCompare(e2[1].toLowerCase())).forEach(author => { + Object.values(filterDefs).forEach(filter => { const option = document.createElement("option"); - option.innerText = author[1]; - option.value = author[0]; - authorFilterSelect.appendChild(option); - }); + option.innerText = filter.name; + option.value = filter.id; + filterSelect.appendChild(option); - authorFilterSelect.addEventListener("change", e => { - updateFilter(); - }); + const filterNameSelect = document.createElement("select"); + filterNameSelect.classList.add("filter-select"); + filterNameSelect.id = "filter-" + filter.id; + filterHolder.appendChild(filterNameSelect); - const ownerFilterSelect = document.createElement("select"); - ownerFilterSelect.classList.add("filter-select"); - ownerFilterSelect.id = "filter-owner"; - filterHolder.appendChild(ownerFilterSelect); - - Array.from(ownerSet).map(owner => [owner, attributionData.people[owner].name]).sort((e1, e2) => e1[1].toLowerCase().localeCompare(e2[1].toLowerCase())).forEach(owner => { - const option = document.createElement("option"); - option.innerText = owner[1]; - option.value = owner[0]; - ownerFilterSelect.appendChild(option); - }); - - ownerFilterSelect.addEventListener("change", e => { - updateFilter(); + Array.from(filterSets[filter.id]).map(name => [name, filter.render(name)]).sort((e1, e2) => e1[1].toLowerCase().localeCompare(e2[1].toLowerCase())).forEach(name => { + const option = document.createElement("option"); + option.innerText = name[1]; + option.value = name[0]; + filterNameSelect.appendChild(option); + }); + + filterNameSelect.addEventListener("change", e => { + updateFilter(); + }); }); console.log("Loaded " + Object.keys(availableEntitiesByName).length + " entities"); @@ -2471,50 +2481,44 @@ function prepareEntities() { // somewhere in the current entity list function recomputeFilters() { const category = document.querySelector("#category-picker").value; - const authorSet = new Set(); - const ownerSet = new Set(); + + const filterSets = {}; + + Object.values(filterDefs).forEach(filter => { + filterSets[filter.id] = new Set(); + }); + document.querySelectorAll(".entity-select.category-visible > option").forEach(element => { const entity = availableEntities[category][element.value]; - if (entity.authors) - entity.authors.forEach(author => authorSet.add(author)); - if (entity.owners) - entity.owners.forEach(owner => ownerSet.add(owner)); + + Object.values(filterDefs).forEach(filter => { + filter.extract(entity).forEach(result => { + filterSets[filter.id].add(result); + }); + }); }); - let authorFound = false; + Object.values(filterDefs).forEach(filter => { + // always show the "none" option + let found = filter.id == "none"; - document.querySelectorAll("#filter-author > option").forEach(element => { - if (authorSet.has(element.value)) { - element.classList.remove("filtered"); - authorFound = true; - } else { - element.classList.add("filtered"); - } - }) + document.querySelectorAll("#filter-" + filter.id + " > option").forEach(element => { + if (filterSets[filter.id].has(element.value) || filter.id == "none") { + element.classList.remove("filtered"); + found = true; + } else { + element.classList.add("filtered"); + } + }); - let ownerFound = false; - document.querySelectorAll("#filter-owner > option").forEach(element => { - if (ownerSet.has(element.value)) { - element.classList.remove("filtered"); - ownerFound = true; + const filterOption = document.querySelector("#filter-picker > option[value='" + filter.id + "']"); + if (found) { + filterOption.classList.remove("filtered"); } else { - element.classList.add("filtered"); + filterOption.classList.add("filtered"); } - }) - - if (authorFound) { - document.querySelector("#filter-picker > option[value='author']").classList.remove("filtered"); - } else { - document.querySelector("#filter-picker > option[value='author']").classList.add("filtered"); - } - - if (ownerFound) { - document.querySelector("#filter-picker > option[value='owner']").classList.remove("filtered"); - } else { - document.querySelector("#filter-picker > option[value='owner']").classList.add("filtered"); - } - + }); document.querySelector("#filter-picker").value = "none"; document.querySelector("#filter-picker").dispatchEvent(new Event("input")); @@ -2538,17 +2542,9 @@ function updateFilter() { let first = null; document.querySelectorAll(".entity-select.category-visible > option").forEach(element => { let keep = false; - if (type == "author") { - const authorList = availableEntities[category][element.value].authors; - if (authorList && authorList.indexOf(key) >= 0) { - keep = true; - } - } - if (type == "owner") { - const ownerList = availableEntities[category][element.value].owners; - if (ownerList && ownerList.indexOf(key) >= 0) { - keep = true; - } + + if (filterDefs[type].extract(availableEntities[category][element.value]).indexOf(key) >= 0) { + keep = true; } if (!keep) { diff --git a/presets/characters.js b/presets/characters.js index 75366208..3c8910a7 100644 --- a/presets/characters.js +++ b/presets/characters.js @@ -49,7 +49,10 @@ characterMakers.push(() => makeCharacter( description: { title: "Bio", text: "Very furry. Sheds on everything." - } + }, + tags: [ + "anthro" + ] }, { back: {