mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
Make again gets a Made by picker, /api/ugc/options lists the processor choices and default, the settings page has the toolbox_* settings, and /reprocessproperty takes native or toolbox-blender. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
235 lines
18 KiB
Django/Jinja
235 lines
18 KiB
Django/Jinja
{% extends "base.jinja2" %}
|
|
|
|
{% block title %}UGC Server - DarkflameServer{% endblock %}
|
|
|
|
{% block content %}
|
|
<div id="ugcPage">
|
|
<div class="mb-3">
|
|
<h2 class="mb-1">UGC Server</h2>
|
|
<p class="text-body-secondary mb-0">The UGC server makes a mesh and an icon for every model players build, and icons for their cars and rockets,
|
|
and serves them to the game client. New and changed models are picked up by themselves; a model that fails is tried a few times, then left
|
|
as failed until it's made again from here. The search finds creations by owner, account, property, the name players gave them, LOT or id,
|
|
and the List view says where each one is. See <code>docs/UgcServer.md</code>.</p>
|
|
</div>
|
|
|
|
<div class="row g-2 mb-3" id="counts"></div>
|
|
|
|
<div class="card mb-3">
|
|
<div class="card-body py-2 small"><div id="serverStatus">Asking the UGC server…</div>
|
|
<div data-ugc-settings="UGC processing" data-title="Processing settings"></div>
|
|
<div data-ugc-settings="UGC models" data-title="How models are made"></div>
|
|
<div data-ugc-settings="UGC serving" data-title="Serving settings"></div></div>
|
|
</div>
|
|
|
|
<details class="card mb-3" id="presetsCard">
|
|
<summary class="card-header py-2 small fw-semibold">Icon presets per type</summary>
|
|
<div class="card-body py-2 small">
|
|
<p class="text-body-secondary mb-2">Each car or rocket build type in the client's data has a preset over the default settings. Open one to set
|
|
its camera, the model's turn, the light and the border on an example. Player models have no preset: each one is a different size and
|
|
shape, so its icon is fitted to it from the defaults; open a model to change just its icon.</p>
|
|
<div class="d-flex flex-wrap gap-2" id="presetsList">Loading…</div>
|
|
<div data-ugc-settings="UGC icons" data-title="Icon defaults (under every preset)"></div>
|
|
</div>
|
|
</details>
|
|
|
|
<details class="card mb-3" id="optionsCard">
|
|
<summary class="card-header py-2 small fw-semibold">Processing options compared</summary>
|
|
<div class="card-body py-2 small">
|
|
<p class="text-body-secondary mb-2">The ways of making models to compare: the ray tracer of the occlusion (Embree on the CPU, HIPRT on AMD or
|
|
NVIDIA GPUs, Embree on Intel GPUs), denoising of icons, and what makes the models (the UGC server itself, or LU Toolbox in Blender:
|
|
<code>toolbox-blender</code>, where its hidden faces are Process Model's and its occlusion Bake Lighting's). The settings pick the defaults; <b>Make again</b> can use others for a make (the options next
|
|
to it, or <code>/reprocessproperty embree oidn</code> in game).
|
|
Every make is counted under what made it: the averages per make below, each model's in the List view's Options column.</p>
|
|
<div class="table-responsive"><table class="table table-sm align-middle mb-0" id="optionsTable">
|
|
<thead><tr><th>Options</th><th>Makes</th><th>Models</th><th>Took</th><th>CPU</th><th>Hidden faces</th><th>Occlusion</th><th>Icon</th><th>Bricks</th><th>Triangles removed</th></tr></thead>
|
|
<tbody><tr><td colspan="10" class="text-body-secondary">Loading…</td></tr></tbody></table></div>
|
|
</div>
|
|
</details>
|
|
|
|
<details class="card mb-3 d-none" id="cacheCard">
|
|
<summary class="card-header py-2 small fw-semibold">Stored files: delete and purge</summary>
|
|
<div class="card-body py-2 small">
|
|
<p class="text-body-secondary mb-2">Deletes files the UGC server made, of the kind picked below. Afterwards they are made again when a game client
|
|
asks for them, queued to be made now, or left deleted. A car or rocket's icon is shared by every build of the same modules.</p>
|
|
<div class="d-flex flex-wrap gap-2 align-items-end">
|
|
<label>State<select class="form-select form-select-sm" id="purgeState"><option value="">Any</option><option value="done">Made</option><option value="failed">Failed</option><option value="pending">Waiting</option></select></label>
|
|
<label>Owner<input class="form-control form-control-sm" id="purgeOwner" placeholder="Name (part of it)"></label>
|
|
<label>Made more than<div class="input-group input-group-sm"><input type="number" min="0" class="form-control" id="purgeOlder" value="0" style="width:5rem"><span class="input-group-text">days ago</span></div></label>
|
|
<label>Not asked for in<div class="input-group input-group-sm"><input type="number" min="0" class="form-control" id="purgeUnused" value="0" style="width:5rem"><span class="input-group-text">days</span></div></label>
|
|
<label>Then<select class="form-select form-select-sm" id="purgeAfter"><option value="on_demand">Make again when asked for</option><option value="now">Make again now</option><option value="gone">Leave deleted</option></select></label>
|
|
<button type="button" class="btn btn-sm btn-outline-warning" id="purgeButton">Purge matching</button>
|
|
<button type="button" class="btn btn-sm btn-outline-danger" id="purgeAllButton">Purge all…</button>
|
|
</div>
|
|
<div class="mt-2" id="purgeResult"></div>
|
|
<div data-ugc-settings="UGC storage" data-title="Storage settings"></div>
|
|
</div>
|
|
</details>
|
|
|
|
<div class="d-flex flex-wrap gap-2 align-items-center mb-2">
|
|
<div class="btn-group btn-group-sm" role="group" id="kindButtons">
|
|
<button type="button" class="btn btn-outline-primary active" data-kind="model">Models</button>
|
|
<button type="button" class="btn btn-outline-primary" data-kind="modular">Cars and rockets</button>
|
|
</div>
|
|
<input type="search" class="form-control form-control-sm" style="max-width: 22rem" id="search" placeholder="Search: text, owner:, account:, property:, name:, lot:, id:, state:, kind:"
|
|
aria-label="Search" title="Plain text matches names, owners and ids. Prefixes search one field: owner:, account:, property:, name:, lot: or module:, id:, state: (pending, done, failed, empty), kind: (a car or rocket type)">
|
|
<select class="form-select form-select-sm w-auto" id="stateFilter" aria-label="State">
|
|
<option value="">Every state</option><option value="pending">Waiting</option><option value="done">Made</option><option value="failed">Failed</option><option value="empty">Empty (no bricks)</option>
|
|
</select>
|
|
<select class="form-select form-select-sm w-auto d-none" id="typeFilter" aria-label="Type"><option value="">Every type</option></select>
|
|
<select class="form-select form-select-sm w-auto" id="sortSelect" aria-label="Sort"></select>
|
|
<div class="btn-group btn-group-sm" role="group" id="viewButtons">
|
|
<button type="button" class="btn btn-outline-secondary active" data-view="gallery">Icons</button>
|
|
<button type="button" class="btn btn-outline-secondary" data-view="list">List</button>
|
|
</div>
|
|
<div class="ms-auto d-none d-flex flex-wrap gap-1 align-items-center" id="manageButtons">
|
|
<span class="d-flex gap-1" id="remakeOptions" title="How Make again makes models (the settings' way unless picked here)">
|
|
<select class="form-select form-select-sm w-auto" id="optRays" aria-label="Ray tracer for Make again"><option value="">Ray tracer: settings</option></select>
|
|
<select class="form-select form-select-sm w-auto" id="optDenoise" aria-label="Denoise for Make again"><option value="">Denoise: settings</option></select>
|
|
<select class="form-select form-select-sm w-auto" id="optProcessor" aria-label="What makes the models for Make again"><option value="">Made by: settings</option></select>
|
|
</span>
|
|
<button type="button" class="btn btn-sm btn-outline-warning" id="retryFailed">Try the failed ones again</button>
|
|
<button type="button" class="btn btn-sm btn-outline-danger" id="remakeAll">Make everything again</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="gallery" class="ugc-gallery mb-2"></div>
|
|
<div class="card d-none" id="listCard"><div class="card-body p-2">
|
|
<div id="modelTableBox"><table class="table table-sm align-middle mb-0 w-100 table-stack" id="ugcModelTable">
|
|
<thead><tr><th>Icon</th><th>ID</th><th>Owner</th><th>State</th><th>Made</th><th>Took</th><th>CPU</th><th>RAM (est.)</th><th>Options</th><th>Saved</th><th>Size</th><th>File</th><th>Where</th><th></th></tr></thead></table></div>
|
|
<div id="assemblyTableBox" class="d-none"><table class="table table-sm align-middle mb-0 w-100 table-stack" id="ugcAssemblyTable">
|
|
<thead><tr><th>Icon</th><th>ID</th><th>Owner</th><th>State</th><th>Made</th><th>Took</th><th>CPU</th><th>RAM (est.)</th><th>Size</th><th>File</th><th>Where</th><th></th></tr></thead></table></div>
|
|
</div></div>
|
|
<div class="d-flex flex-wrap gap-2 align-items-center mt-2" id="pagerBar">
|
|
<nav aria-label="Pages"><ul class="pagination pagination-sm mb-0" id="pager"></ul></nav>
|
|
<label class="d-flex align-items-center gap-1 small">Page <input type="number" min="1" class="form-control form-control-sm" style="width:5rem" id="jumpPage" aria-label="Go to page"></label>
|
|
<label class="d-flex align-items-center gap-1 small">Show <select class="form-select form-select-sm w-auto" id="pageSize" aria-label="Per page">
|
|
<option>24</option><option>48</option><option>96</option><option>200</option></select> per page</label>
|
|
<span class="small text-body-secondary ms-auto" id="totalText"></span>
|
|
</div>
|
|
|
|
<div class="modal fade" id="previewModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-xl modal-fullscreen-lg-down"><div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="previewTitle">Model</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="d-flex flex-wrap gap-2 align-items-center mb-2 small" id="meshControls">
|
|
<label class="d-flex align-items-center gap-1">Detail
|
|
<select class="form-select form-select-sm w-auto" id="lodSelect"></select></label>
|
|
<label class="d-flex align-items-center gap-1">Version
|
|
<select class="form-select form-select-sm w-auto" id="versionSelect">
|
|
<option value="current">Now</option><option value="previous">Before it was made again</option>
|
|
</select></label>
|
|
<div class="form-check form-switch mb-0"><input class="form-check-input" type="checkbox" id="wireframeSwitch"><label class="form-check-label" for="wireframeSwitch">Wireframe</label></div>
|
|
<div class="form-check form-switch mb-0"><input class="form-check-input" type="checkbox" id="colorsSwitch" checked><label class="form-check-label" for="colorsSwitch">Vertex colors</label></div>
|
|
<div class="form-check form-switch mb-0"><input class="form-check-input" type="checkbox" id="aoSwitch" checked><label class="form-check-label" for="aoSwitch">Baked lighting</label></div>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="reframeButton">Reset view</button>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-lg-5" id="nifColumn">
|
|
<div class="small fw-semibold mb-1">Generated mesh (.nif)</div>
|
|
<div id="nifViewer" class="rounded border" style="height: 420px"></div>
|
|
<div class="small text-body-secondary mt-1" id="nifStats"></div>
|
|
</div>
|
|
<div class="col-lg-4" id="lxfmlColumn">
|
|
<div class="small fw-semibold mb-1">As built (LXFML)</div>
|
|
<div id="lxfmlViewer" class="rounded border" style="height: 420px"></div>
|
|
<div class="small text-body-secondary mt-1">Every brick, before hidden faces are removed.</div>
|
|
</div>
|
|
<div class="col-lg-3">
|
|
<div class="small fw-semibold mb-1">Icon</div>
|
|
<div class="d-flex gap-2 flex-wrap">
|
|
<figure class="text-center mb-0"><img id="previewIcon" alt="Icon" class="border rounded bg-body-tertiary ugc-checker" width="128" height="128">
|
|
<figcaption class="small text-body-secondary">Now</figcaption></figure>
|
|
<figure class="text-center mb-0 d-none" id="previousIconBox"><img id="previousIcon" alt="Icon before" class="border rounded bg-body-tertiary ugc-checker" width="128" height="128">
|
|
<figcaption class="small text-body-secondary">Before</figcaption></figure>
|
|
</div>
|
|
<div class="small mt-2" id="previewLinks"></div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3" id="statsBox"></div>
|
|
<div class="card mt-3 d-none" id="framingCard">
|
|
<div class="card-header py-2 small fw-semibold d-flex flex-wrap align-items-center gap-2">Icon editor
|
|
<span class="text-body-secondary fw-normal" id="framingKind"></span>
|
|
<span class="ms-auto text-body-secondary fw-normal" id="framingState">Preview drawn by the UGC server, not stored.</span></div>
|
|
<div class="card-body py-2 small">
|
|
<div class="row g-3">
|
|
<div class="col-lg-8">
|
|
<div class="d-flex flex-wrap gap-2 align-items-center mb-1">
|
|
<div class="btn-group btn-group-sm" role="group" aria-label="What dragging changes" id="poseModes">
|
|
<button type="button" class="btn btn-outline-secondary active" data-mode="camera" title="Drag: the camera around the model">Camera</button>
|
|
<button type="button" class="btn btn-outline-secondary" data-mode="model" title="Drag: turn the model (Ctrl+drag in any mode; Alt+wheel rolls it)">Turn model</button>
|
|
<button type="button" class="btn btn-outline-secondary" data-mode="sun" title="Drag: the sun's direction (Alt+drag in any mode)">Sun</button>
|
|
<button type="button" class="btn btn-outline-secondary" data-mode="shift" title="Drag: move the model in the icon (Shift+drag or right drag in any mode)">Shift</button>
|
|
</div>
|
|
<div class="form-check form-switch mb-0"><input class="form-check-input" type="checkbox" id="sunArrowSwitch" checked><label class="form-check-label" for="sunArrowSwitch">Sun arrow</label></div>
|
|
<span class="text-body-secondary">Wheel: border. The dashed square is the icon.</span>
|
|
</div>
|
|
<div id="poseView" class="rounded border" style="height: 420px"></div>
|
|
<div class="text-body-secondary mt-1" id="poseStats"></div>
|
|
</div>
|
|
<div class="col-lg-4 text-center">
|
|
<div class="d-flex justify-content-center gap-2 flex-wrap">
|
|
<figure class="mb-0"><img id="framingPreview" alt="Icon preview" class="border rounded ugc-checker" width="256" height="256" style="image-rendering: pixelated">
|
|
<figcaption class="text-body-secondary">Preview</figcaption></figure>
|
|
</div>
|
|
<div class="d-flex flex-column gap-1 mt-2">
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="framingPreviewButton">Draw the preview again</button>
|
|
<button type="button" class="btn btn-sm btn-outline-primary ugc-manage" id="framingSaveType">Save as the preset for this type</button>
|
|
<button type="button" class="btn btn-sm btn-outline-primary ugc-manage" id="framingSaveCombo">Save for this item</button>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="framingResetType">Back to the type's preset</button>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="framingResetDefaults">Back to the default settings</button>
|
|
<button type="button" class="btn btn-sm btn-outline-danger ugc-manage" id="framingReset">Remove this item's own values</button>
|
|
<button type="button" class="btn btn-sm btn-outline-warning ugc-manage" id="framingRegenerate">Draw all icons of this type again</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row g-2 mt-1" id="framingControls"></div>
|
|
</div>
|
|
</div>
|
|
<div class="card mt-3 d-none" id="referencesCard">
|
|
<div class="card-header py-2 small fw-semibold d-flex flex-wrap align-items-center gap-2">References <span class="text-body-secondary fw-normal">the builds that use these modules</span>
|
|
<input type="search" class="form-control form-control-sm ms-auto" style="max-width: 16rem" id="refSearch" placeholder="Owner, account, property or id" aria-label="Search the builds"></div>
|
|
<div class="card-body p-2"><table class="table table-sm small align-middle mb-0 w-100" id="refTable">
|
|
<thead><tr><th>Build (blueprint id)</th><th>Owner</th><th>Account</th><th>State</th><th>Made</th><th>Where it is</th></tr></thead></table></div>
|
|
</div>
|
|
</div>
|
|
</div></div>
|
|
</div>
|
|
</div>
|
|
<style>
|
|
.ugc-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: .5rem; }
|
|
.ugc-tile { cursor: pointer; text-align: center; }
|
|
.ugc-tile:hover, .ugc-tile:focus-visible { border-color: var(--bs-primary); }
|
|
.ugc-tile img, .ugc-tile .ugc-noicon { width: 128px; height: 128px; }
|
|
.ugc-noicon { display: inline-flex; align-items: center; justify-content: center; }
|
|
.ugc-checker { background-image: linear-gradient(45deg, rgba(128,128,128,.15) 25%, transparent 25%, transparent 75%, rgba(128,128,128,.15) 75%),
|
|
linear-gradient(45deg, rgba(128,128,128,.15) 25%, transparent 25%, transparent 75%, rgba(128,128,128,.15) 75%);
|
|
background-size: 16px 16px; background-position: 0 0, 8px 8px; }
|
|
.ugc-meter { height: .4rem; }
|
|
.ugc-modules img { width: 32px; height: 32px; }
|
|
tr.ugc-highlight > td { background-color: var(--bs-warning-bg-subtle); }
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.min.js",
|
|
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
|
|
},
|
|
"integrity": {
|
|
"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.min.js": "sha384-IDC7sAMAIMB/TZ6dgKKPPAKZ2bXXXP8+FBMBC8cU319eBhKITx+PaalhfDkDNH28",
|
|
"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/controls/OrbitControls.js": "sha384-aJoe4qqS/DgF2jh9njAuvA6QIveJYoCuYOfYjdFY8P3eawzmc9bEQ40jq2TvOyuP",
|
|
"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/environments/RoomEnvironment.js": "sha384-9ItPPH2vgKbkvgrqTKq7ptGYe+WuAnqlZtlqleJW4/CJjnM5R7C+efD6iS7ADPJ9"
|
|
}
|
|
}
|
|
</script>
|
|
<script src="/api/bricks/materials.js"></script>
|
|
<script src="/js/ugc-settings.js"></script>
|
|
<script src="/js/ugc-icon-editor.js"></script>
|
|
<script src="/js/ugc.js"></script>
|
|
{% endblock %}
|