feat: add avatar sandbox oufits feature!
This commit is contained in:
parent
4a3ad2eb5f
commit
792375158d
2 changed files with 340 additions and 60 deletions
|
|
@ -70,6 +70,7 @@ let Order = "desc"
|
|||
let ShowOffsale = true
|
||||
let TabSelected = "hat"
|
||||
let RetroItems = null
|
||||
let Outfits = null
|
||||
|
||||
/* Customization */
|
||||
let SelectedBodyPart
|
||||
|
|
@ -78,8 +79,9 @@ let SelectedBodyPart
|
|||
Utilities = await import(chrome.runtime.getURL('resources/utils.js'));
|
||||
Utilities = Utilities.default;
|
||||
|
||||
chrome.storage.sync.get(['PolyPlus_Settings'], function(result){
|
||||
chrome.storage.sync.get(['PolyPlus_Settings', 'PolyPlus_AvatarSandboxOutfits'], function(result){
|
||||
Settings = result.PolyPlus_Settings || Utilities.DefaultSettings;
|
||||
Outfits = result.PolyPlus_AvatarSandboxOutfits || [];
|
||||
|
||||
if (Settings.AvatarSandboxOn || 1 === 1) {
|
||||
if (new URLSearchParams(window.location.search).has('sandbox')) {
|
||||
|
|
@ -284,6 +286,44 @@ async function PageLoad() {
|
|||
}
|
||||
})
|
||||
|
||||
const SaveButton = document.getElementById('saveOutfit')
|
||||
const OutfitCreateModal = document.getElementById('p+outfit_create')
|
||||
const OutfitCreateButton = document.getElementById('p+save_outfit_confirm')
|
||||
const OutfitCreateError = document.getElementById('p+outfit_create_error')
|
||||
SaveButton.addEventListener('click', function(){
|
||||
console.log(Outfits)
|
||||
OutfitCreateModal.showModal()
|
||||
})
|
||||
|
||||
OutfitCreateButton.addEventListener('click', function(){
|
||||
let OutfitName = OutfitCreateButton.previousElementSibling.value.trim()
|
||||
OutfitCreateButton.previousElementSibling.value = ''
|
||||
if (OutfitName === '') {
|
||||
OutfitCreateError.classList = 'text-danger';
|
||||
OutfitCreateError.innerHTML = '<i class="fa-duotone fa-circle-exclamation mr-1"></i> You cannot name an outfit nothing.';
|
||||
return
|
||||
} else if (OutfitName.length > 25) {
|
||||
OutfitName = OutfitName.substring(0, 25)
|
||||
} else if (Outfits.findIndex((x) => x.name.trim() === OutfitName) !== -1) {
|
||||
OutfitCreateError.classList = 'text-danger';
|
||||
OutfitCreateError.innerHTML = '<i class="fa-duotone fa-circle-exclamation mr-1"></i> You already have an outfit with the name "' + OutfitName + '".';
|
||||
return
|
||||
}
|
||||
OutfitCreateModal.close()
|
||||
Outfits.push({
|
||||
name: OutfitName,
|
||||
createdAt: new Date().getTime(),
|
||||
data: Avatar
|
||||
})
|
||||
if (TabSelected === 'outfit') {
|
||||
LoadItems()
|
||||
}
|
||||
|
||||
chrome.storage.sync.set({'PolyPlus_AvatarSandboxOutfits': Outfits}, function(){
|
||||
console.log('Saved outfits!')
|
||||
})
|
||||
})
|
||||
|
||||
document.getElementById('view-cache').addEventListener('click', function(){
|
||||
console.log('Cache: ', ItemCache)
|
||||
})
|
||||
|
|
@ -486,9 +526,21 @@ async function LoadItems() {
|
|||
document.getElementById('inventory').innerHTML = ''
|
||||
|
||||
let Items;
|
||||
if (TabSelected !== 'retro') {
|
||||
if (['retro', 'outfit'].indexOf(TabSelected) === -1) {
|
||||
Items = (await (await fetch('https://api.polytoria.com/v1/store?limit=12&order=' + Order + '&sort=' + Sort + '&showOffsale=' + ShowOffsale + '&types[]='+ TabSelected +'&search=' + Search + '&page=' + Page)).json())
|
||||
} else {
|
||||
} else if (TabSelected === 'outfit') {
|
||||
const OutfitsClone = structuredClone(Outfits)
|
||||
let Groups = []
|
||||
while (OutfitsClone.length > 0) {
|
||||
Groups.push(OutfitsClone.splice(0, 12));
|
||||
}
|
||||
|
||||
console.log(Groups, OutfitsClone)
|
||||
Items = {
|
||||
assets: Groups[Page - 1],
|
||||
pages: Groups.length
|
||||
}
|
||||
} else if (TabSelected === 'retro') {
|
||||
if (RetroItems === null) {
|
||||
Items = (await (await fetch('https://poly-upd-archival.pages.dev/data.json')).json())
|
||||
Object.values(Items).forEach((item, index) => {
|
||||
|
|
@ -538,6 +590,11 @@ async function LoadItems() {
|
|||
document.getElementById('pagination-first').classList.add('disabled');
|
||||
}
|
||||
document.getElementById('pagination-current').innerText = Page
|
||||
|
||||
if (Items.assets === undefined) { Items.assets = [] }
|
||||
if (Items.assets.length > 0) {
|
||||
document.getElementById('inventory').classList.add('itemgrid')
|
||||
if (TabSelected !== 'outfit') {
|
||||
Items.assets.forEach(item => {
|
||||
const ItemColumn = document.createElement('div')
|
||||
ItemColumn.classList = 'col-auto'
|
||||
|
|
@ -597,6 +654,175 @@ async function LoadItems() {
|
|||
WearAsset(item, item.id)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
Items.assets.forEach((outfit, index) => {
|
||||
const ItemColumn = document.createElement('div')
|
||||
ItemColumn.classList = 'col-auto'
|
||||
ItemColumn.innerHTML = `
|
||||
<div style="max-width: 150px;">
|
||||
<div class="card mb-2">
|
||||
<div class="p-2 text-center">
|
||||
<div class="mb-1">
|
||||
<button style="border: 0; border-radius: 5px; cursor: default; background-color: ${outfit.data.headColor}; padding: 15px;"></button>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<button style="border: 0; border-radius: 5px; cursor: default; background-color: ${outfit.data.leftArmColor}; padding: 10px; padding-top: 20px; padding-bottom: 20px;"></button>
|
||||
<button style="border: 0; border-radius: 5px; cursor: default; background-color: ${outfit.data.torsoColor}; padding: 20px;"></button>
|
||||
<button style="border: 0; border-radius: 5px; cursor: default; background-color: ${outfit.data.rightArmColor}; padding: 20px; padding: 10px; padding-top: 20px; padding-bottom: 20px;"></button>
|
||||
</div>
|
||||
<button style="border: 0; border-radius: 5px; cursor: default; background-color: ${outfit.data.leftLegColor}; padding: 10px; padding-top: 20px; padding-bottom: 20px;"></button>
|
||||
<button style="border: 0; border-radius: 5px; cursor: default; background-color: ${outfit.data.rightLegColor}; padding: 10px; padding-top: 20px; padding-bottom: 20px;"></button>
|
||||
</div>
|
||||
</div>
|
||||
<h6 class="text-truncate mb-0 text-reset text-center mb-2">${outfit.name}</h6>
|
||||
<div class="btn-group w-100">
|
||||
<button class="btn btn-primary btn-sm p+outfit_wear_button">Wear</button>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-warning dropdown-toggle btn-sm" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa-duotone fa-wrench"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a class="dropdown-item text-primary p+outfit_rename_button" href="#">
|
||||
<i class="fa-solid fa-signature"></i>
|
||||
Rename
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<span class="p+outfit_overwrite_button dropdown-item text-warning">
|
||||
<i class="fa-solid fa-wand-magic-sparkles"></i>
|
||||
<span>Overwrite</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<hr class="dropdown-divider">
|
||||
</li>
|
||||
<li>
|
||||
<span class="p+outfit_delete_button dropdown-item text-danger">
|
||||
<i class="fa-duotone fa-trash"></i>
|
||||
<span>Delete</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
document.getElementById('inventory').appendChild(ItemColumn)
|
||||
Utilities.InjectResource("registerTooltips")
|
||||
|
||||
ItemColumn.getElementsByClassName('p+outfit_wear_button')[0].addEventListener('click', function(){
|
||||
if (Avatar === outfit.data) {
|
||||
return
|
||||
}
|
||||
console.log('Equipped Outfit: ', outfit)
|
||||
Avatar = outfit.data
|
||||
UpdateAvatar()
|
||||
})
|
||||
|
||||
const OutfitRenameModal = document.getElementById('p+outfit_rename')
|
||||
const OutfitRenameButton = document.getElementById('p+rename_outfit_confirm')
|
||||
const OutfitRenameError = document.getElementById('p+outfit_rename_error')
|
||||
ItemColumn.getElementsByClassName('p+outfit_rename_button')[0].addEventListener('click', function(){
|
||||
OutfitRenameModal.showModal()
|
||||
document.getElementById('p+outfit_rename_name').innerText = outfit.name
|
||||
})
|
||||
|
||||
OutfitRenameButton.addEventListener('click', function(){
|
||||
let OutfitName = OutfitRenameButton.previousElementSibling.value.trim()
|
||||
OutfitRenameButton.previousElementSibling.value = ''
|
||||
if (OutfitName === '') {
|
||||
OutfitRenameError.classList = 'text-danger';
|
||||
OutfitRenameError.innerHTML = '<i class="fa-duotone fa-circle-exclamation mr-1"></i> You cannot name an outfit nothing.';
|
||||
return
|
||||
} else if (OutfitName.length > 25) {
|
||||
OutfitName = OutfitName.substring(0, 25)
|
||||
} else if (Outfits.findIndex((x) => x.name.trim() === OutfitName) !== -1) {
|
||||
OutfitRenameError.classList = 'text-danger';
|
||||
OutfitRenameError.innerHTML = '<i class="fa-duotone fa-circle-exclamation mr-1"></i> You already have an outfit with the name "' + OutfitName + '".';
|
||||
return
|
||||
}
|
||||
OutfitRenameModal.close()
|
||||
Outfits[index].name = OutfitName
|
||||
if (TabSelected === 'outfit') {
|
||||
LoadItems()
|
||||
}
|
||||
|
||||
chrome.storage.sync.set({'PolyPlus_AvatarSandboxOutfits': Outfits}, function(){
|
||||
console.log('Saved outfits!')
|
||||
})
|
||||
})
|
||||
|
||||
let OverwritePending = false
|
||||
const OutfitOverwriteButton = ItemColumn.getElementsByClassName('p+outfit_overwrite_button')[0]
|
||||
OutfitOverwriteButton.addEventListener('click', function(e){
|
||||
e.stopPropagation()
|
||||
if (OverwritePending === false) {
|
||||
OverwritePending = true
|
||||
OutfitOverwriteButton.children[1].innerText = 'Are you sure?'
|
||||
setTimeout(function (){
|
||||
if (OverwritePending === true) {
|
||||
OutfitOverwriteButton.children[1].innerText = 'Overwrite'
|
||||
OverwritePending = false
|
||||
}
|
||||
}, 3000)
|
||||
} else {
|
||||
OverwritePending = false
|
||||
console.log('Overwrite Outfit (outfit, avatar): ', outfit, Avatar)
|
||||
|
||||
Outfits[index].data = Avatar
|
||||
if (TabSelected === 'outfit') {
|
||||
LoadItems()
|
||||
}
|
||||
|
||||
chrome.storage.sync.set({'PolyPlus_AvatarSandboxOutfits': Outfits}, function(){
|
||||
console.log('Saved outfits!')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let DeletePending = false
|
||||
const OutfitDeleteButton = ItemColumn.getElementsByClassName('p+outfit_delete_button')[0]
|
||||
OutfitDeleteButton.addEventListener('click', function(e){
|
||||
e.stopPropagation()
|
||||
if (DeletePending === false) {
|
||||
DeletePending = true
|
||||
OutfitDeleteButton.children[1].innerText = 'Are you sure?'
|
||||
setTimeout(function (){
|
||||
if (DeletePending === true) {
|
||||
OutfitDeleteButton.children[1].innerText = 'Delete'
|
||||
DeletePending = false
|
||||
}
|
||||
}, 3000)
|
||||
} else {
|
||||
DeletePending = false
|
||||
console.log('Deleted Outfit: ', outfit)
|
||||
|
||||
Outfits.splice(index, 1)
|
||||
if (TabSelected === 'outfit') {
|
||||
LoadItems()
|
||||
}
|
||||
|
||||
chrome.storage.sync.set({'PolyPlus_AvatarSandboxOutfits': Outfits}, function(){
|
||||
console.log('Saved outfits!')
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
document.getElementById('inventory').classList.remove('itemgrid')
|
||||
document.getElementById('inventory').innerHTML = `
|
||||
<div class="text-muted" style="padding: 37px 30px;">
|
||||
<h1 class="display-3">
|
||||
<i class="fas fa-box-open"></i>
|
||||
</h1>
|
||||
<h6 class="mb-0">
|
||||
You do not have any items matching this type or search query. Find new items in the <a href="/store">store</a>!
|
||||
</h6>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
function LoadWearing() {
|
||||
|
|
@ -710,5 +936,13 @@ function FormatPrice(price) {
|
|||
} else {
|
||||
return 'text-muted">???</small>'
|
||||
}
|
||||
return "what"
|
||||
return '">how did this happen</small>'
|
||||
}
|
||||
|
||||
chrome.storage.onChanged.addListener(function (changes, namespace) {
|
||||
if ('PolyPlus_AvatarSandboxOutfits' in changes) {
|
||||
chrome.storage.sync.get(['PolyPlus_AvatarSandboxOutfits'], function (result) {
|
||||
Outfits = result.PolyPlus_AvatarSandboxOutfits || [];
|
||||
});
|
||||
}
|
||||
})
|
||||
|
|
@ -34,6 +34,10 @@
|
|||
#options *:not(input):not(:nth-child(2)) {
|
||||
margin-bottom: 3.5px;
|
||||
}
|
||||
|
||||
[class^="p+outfit_overwrite_button"]:hover, [class^="p+outfit_delete_button"]:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<dialog id="p+body_colors" class="polyplus-modal" style="width: 375px; border: 1px solid #484848; background-color: #181818; border-radius: 20px; overflow: hidden;">
|
||||
<div class="row text-muted mb-4" style="font-size: 0.8rem;">
|
||||
|
|
@ -112,6 +116,42 @@
|
|||
<div class="colorpicker-color" style="background-color: #e8bac8"></div>
|
||||
</div>
|
||||
</dialog>
|
||||
<dialog id="p+outfit_create" class="polyplus-modal" style="width: 375px; border: 1px solid #484848; background-color: #181818; border-radius: 20px; overflow: hidden;">
|
||||
<div class="row text-muted mb-4" style="font-size: 0.8rem;">
|
||||
<div class="col">
|
||||
<h5 class="mb-0" style="color: #fff;">Create Outfit</h5>
|
||||
Save this avatar for later!
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-info w-100 mx-auto" onclick="this.parentElement.parentElement.parentElement.close();">X</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group mb-2">
|
||||
<input type="text" class="form-control" placeholder="Outfit Name...">
|
||||
<button id="p+save_outfit_confirm" class="btn btn-success">Save</button>
|
||||
</div>
|
||||
<b id="p+outfit_create_error" class="text-muted" style="font-size: 0.85rem;"><i class="fa-duotone fa-square-question mr-1"></i> ...</b>
|
||||
</div>
|
||||
</dialog>
|
||||
<dialog id="p+outfit_rename" class="polyplus-modal" style="width: 375px; border: 1px solid #484848; background-color: #181818; border-radius: 20px; overflow: hidden;">
|
||||
<div class="row text-muted mb-4" style="font-size: 0.8rem;">
|
||||
<div class="col">
|
||||
<h5 class="mb-0" style="color: #fff;">Rename Outfit</h5>
|
||||
Renaming Outfit "<i id="p+outfit_rename_name">none</i>"
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-info w-100 mx-auto" onclick="this.parentElement.parentElement.parentElement.close();">X</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group mb-2">
|
||||
<input type="text" class="form-control" placeholder="New Outfit Name...">
|
||||
<button id="p+rename_outfit_confirm" class="btn btn-success">Save</button>
|
||||
</div>
|
||||
<b id="p+outfit_rename_error" class="text-muted" style="font-size: 0.85rem;"><i class="fa-duotone fa-square-question mr-1"></i> ...</b>
|
||||
</div>
|
||||
</dialog>
|
||||
<span class="badge bg-warning mb-2" id="view-cache">Poly+</span>
|
||||
<h4 class="d-none d-lg-block">
|
||||
Avatar Sandbox
|
||||
|
|
@ -260,6 +300,12 @@
|
|||
<span class="pilltitle">Retro</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item col-6 col-md-4 col-xl-3" style="flex: unset">
|
||||
<a class="nav-link" data-tab="outfit">
|
||||
<i class="fa-solid fa-tv-retro"></i>
|
||||
<span class="pilltitle">Outfits</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="card px-2 pt-2 pb-2 mb-2" style="background: transparent; border-color: transparent; border-top-left-radius: 20px; border-top-right-radius: 20px;">
|
||||
<div class="row mb-1">
|
||||
|
|
|
|||
Reference in a new issue