Просмотр исходного кода

Add support for filtering by species and tag

Only Fen has a tag, and most characters lack species,
so it'll be a while until this covers everyone.
master
Fen Dweller 5 лет назад
Родитель
Сommit
a5e74a533d
2 измененных файлов: 103 добавлений и 104 удалений
  1. +99
    -103
      macrovision.js
  2. +4
    -1
      presets/characters.js

+ 99
- 103
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) {


+ 4
- 1
presets/characters.js Просмотреть файл

@@ -49,7 +49,10 @@ characterMakers.push(() => makeCharacter(
description: {
title: "Bio",
text: "Very furry. Sheds on everything."
}
},
tags: [
"anthro"
]
},
{
back: {


Загрузка…
Отмена
Сохранить