Complete Asset Audit JAN 12 2026 - 3477 images cataloged, new asset gallery with all images, DNEVNIK and GAME_BIBLE updated

This commit is contained in:
2026-01-12 23:53:00 +01:00
parent 1b17e806ec
commit dad515a8a2
25 changed files with 24738 additions and 217 deletions

View File

@@ -0,0 +1,454 @@
#!/usr/bin/env python3
"""
Generate complete asset gallery HTML with all images
"""
import os
from pathlib import Path
from datetime import datetime
def main():
assets_dir = Path("assets")
# Find all images
extensions = ['.png', '.jpg', '.jpeg', '.webp', '.gif']
all_images = []
for ext in extensions:
all_images.extend(assets_dir.rglob(f"*{ext}"))
all_images.extend(assets_dir.rglob(f"*{ext.upper()}"))
# Remove duplicates and sort
all_images = sorted(set(str(p) for p in all_images))
print(f"Found {len(all_images)} images")
# Categorize images
categories = {}
def get_category(path):
path_lower = path.lower()
if 'phase_packs/0_demo' in path_lower:
if 'crops' in path_lower:
return '🎮 DEMO - Crops'
elif 'tools' in path_lower:
return '🎮 DEMO - Tools'
elif 'animals' in path_lower:
return '🎮 DEMO - Animals'
return '🎮 DEMO - Other'
elif 'phase_packs/1_faza_1' in path_lower:
if 'crops' in path_lower:
return '🌾 FAZA 1 - Crops'
elif 'animals' in path_lower:
return '🌾 FAZA 1 - Animals'
elif 'tools' in path_lower:
return '🌾 FAZA 1 - Tools'
elif 'infrastructure' in path_lower:
return '🌾 FAZA 1 - Infrastructure'
return '🌾 FAZA 1 - Other'
elif 'phase_packs/2_faza_2' in path_lower:
if 'buildings' in path_lower:
return '🏘️ FAZA 2 - Buildings'
elif 'npcs' in path_lower:
return '🏘️ FAZA 2 - NPCs'
elif 'infrastructure' in path_lower:
return '🏘️ FAZA 2 - Infrastructure'
return '🏘️ FAZA 2 - Other'
elif 'references/kai' in path_lower:
return '👤 References - Kai'
elif 'references/ana' in path_lower:
return '👤 References - Ana'
elif 'references/gronk' in path_lower:
return '👤 References - Gronk'
elif 'references/susi' in path_lower:
return '👤 References - Susi'
elif 'references/npcs' in path_lower:
return '👥 References - NPCs'
elif 'references/creatures' in path_lower:
return '🐉 References - Creatures'
elif 'references/buildings' in path_lower:
return '🏠 References - Buildings'
elif 'references/trees' in path_lower:
return '🌳 References - Trees'
elif 'references/ui' in path_lower:
return '🎨 References - UI'
elif 'references/' in path_lower:
return '📸 References - Other'
elif 'sprites' in path_lower:
return '🖼️ Sprites'
elif 'crops' in path_lower:
return '🌱 Crops'
elif 'buildings' in path_lower:
return '🏠 Buildings'
elif 'characters' in path_lower:
return '👤 Characters'
elif 'grounds' in path_lower:
return '🌍 Ground Tiles'
elif 'terrain' in path_lower:
return '⛰️ Terrain'
elif 'ui' in path_lower:
return '🎨 UI'
elif 'vfx' in path_lower:
return '✨ VFX'
elif 'props' in path_lower:
return '🪑 Props'
elif 'slike' in path_lower:
return '🖼️ Slike'
return '📦 Other'
for img_path in all_images:
cat = get_category(img_path)
if cat not in categories:
categories[cat] = []
categories[cat].append(img_path)
# Generate HTML
html = f'''<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>🎮 NovaFarma - Vse Slike ({len(all_images)})</title>
<style>
* {{ box-sizing: border-box; }}
body {{
background: linear-gradient(135deg, #0a0a0a, #1a1a2e, #16213e);
color: #fff;
font-family: 'Segoe UI', Arial, sans-serif;
padding: 20px;
margin: 0;
min-height: 100vh;
}}
h1 {{
text-align: center;
color: #ff4444;
font-size: 2.5em;
text-shadow: 2px 2px 4px #000, 0 0 20px rgba(255, 68, 68, 0.5);
margin-bottom: 10px;
}}
.stats {{
text-align: center;
color: #aaa;
margin-bottom: 20px;
font-size: 1.1em;
}}
.stats span {{
color: #ff6666;
font-weight: bold;
}}
.controls {{
display: flex;
justify-content: center;
gap: 15px;
margin-bottom: 30px;
flex-wrap: wrap;
position: sticky;
top: 0;
background: rgba(10, 10, 10, 0.95);
padding: 15px;
z-index: 100;
border-radius: 10px;
}}
.controls input {{
padding: 12px 20px;
border: 2px solid #444;
border-radius: 25px;
background: rgba(0, 0, 0, 0.5);
color: #fff;
font-size: 1em;
width: 400px;
max-width: 90vw;
transition: border-color 0.3s;
}}
.controls input:focus {{
outline: none;
border-color: #ff4444;
box-shadow: 0 0 10px rgba(255, 68, 68, 0.3);
}}
.controls select {{
padding: 12px 20px;
border: 2px solid #444;
border-radius: 25px;
background: rgba(0, 0, 0, 0.5);
color: #fff;
font-size: 1em;
cursor: pointer;
}}
.section {{
margin: 30px 0;
background: rgba(0, 0, 0, 0.3);
padding: 20px;
border-radius: 15px;
border: 1px solid #333;
}}
.section h2 {{
color: #ff6666;
border-bottom: 2px solid #444;
padding-bottom: 10px;
margin-top: 0;
cursor: pointer;
}}
.section h2:hover {{
color: #ff8888;
}}
.section h2 .count {{
background: #ff4444;
color: #fff;
padding: 3px 12px;
border-radius: 15px;
font-size: 0.7em;
margin-left: 10px;
}}
.grid {{
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
gap: 12px;
margin-top: 15px;
}}
.card {{
background: rgba(255, 255, 255, 0.05);
border: 1px solid #333;
border-radius: 10px;
padding: 10px;
text-align: center;
transition: all 0.3s ease;
cursor: pointer;
}}
.card:hover {{
transform: translateY(-3px) scale(1.02);
border-color: #ff4444;
box-shadow: 0 8px 25px rgba(255, 68, 68, 0.3);
background: rgba(255, 68, 68, 0.1);
}}
.card img {{
width: 120px;
height: 120px;
object-fit: contain;
background: linear-gradient(45deg, #111 25%, #222 25%, #222 50%, #111 50%, #111 75%, #222 75%);
background-size: 16px 16px;
border-radius: 6px;
}}
.card .name {{
margin: 8px 0 3px;
font-size: 0.7em;
color: #aaa;
font-family: 'Consolas', monospace;
word-break: break-all;
max-height: 2.2em;
overflow: hidden;
}}
.card button {{
background: linear-gradient(135deg, #ff4444, #cc3333);
color: #fff;
border: none;
padding: 5px 12px;
border-radius: 12px;
cursor: pointer;
font-size: 0.75em;
margin-top: 6px;
transition: all 0.2s;
}}
.card button:hover {{
background: linear-gradient(135deg, #ff6666, #ff4444);
}}
.copied {{
background: linear-gradient(135deg, #44ff44, #33cc33) !important;
}}
.modal {{
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
z-index: 1000;
justify-content: center;
align-items: center;
flex-direction: column;
}}
.modal.active {{
display: flex;
}}
.modal img {{
max-width: 90%;
max-height: 80%;
border-radius: 10px;
box-shadow: 0 0 50px rgba(255, 68, 68, 0.5);
}}
.modal .info {{
color: #aaa;
margin-top: 15px;
font-family: monospace;
text-align: center;
}}
.modal .close {{
position: absolute;
top: 20px;
right: 30px;
font-size: 3em;
color: #fff;
cursor: pointer;
transition: color 0.3s;
}}
.modal .close:hover {{
color: #ff4444;
}}
.hidden {{ display: none !important; }}
.toc {{
background: rgba(0, 0, 0, 0.4);
padding: 20px;
border-radius: 10px;
margin-bottom: 30px;
}}
.toc h3 {{ color: #ff6666; margin-top: 0; }}
.toc ul {{ list-style: none; padding: 0; column-count: 3; }}
.toc li {{ margin: 5px 0; }}
.toc a {{ color: #aaa; text-decoration: none; }}
.toc a:hover {{ color: #ff4444; }}
@media (max-width: 768px) {{
.toc ul {{ column-count: 1; }}
}}
</style>
</head>
<body>
<h1>🎮 NOVAFARMA - VSE SLIKE 💀</h1>
<div class="stats">
<span>{len(all_images)}</span> slik v <span>{len(categories)}</span> kategorijah |
Generirano: {datetime.now().strftime("%d.%m.%Y %H:%M")}
</div>
<div class="controls">
<input type="text" id="search" placeholder="🔍 Išči slike... (npr. 'kai', 'zombie', 'crop')" />
<select id="categoryFilter">
<option value="">📁 Vse kategorije ({len(all_images)})</option>
'''
# Add category options
for cat in sorted(categories.keys()):
html += f' <option value="{cat}">{cat} ({len(categories[cat])})</option>\n'
html += ''' </select>
</div>
<div class="toc">
<h3>📋 Kazalo kategorij</h3>
<ul>
'''
# Add TOC
for cat in sorted(categories.keys()):
safe_id = cat.replace(' ', '_').replace('-', '_')
html += f' <li><a href="#{safe_id}">{cat} ({len(categories[cat])})</a></li>\n'
html += ''' </ul>
</div>
<div id="content">
'''
# Add sections
for cat in sorted(categories.keys()):
safe_id = cat.replace(' ', '_').replace('-', '_')
html += f'''
<div class="section" data-category="{cat}" id="{safe_id}">
<h2 onclick="toggleSection(this)">{cat} <span class="count">{len(categories[cat])}</span></h2>
<div class="grid">
'''
for img_path in sorted(categories[cat]):
name = os.path.basename(img_path)
html += f''' <div class="card" data-path="{img_path}" data-name="{name.lower()}" onclick="openModal('{img_path}', '{name}')">
<img src="{img_path}" alt="{name}" loading="lazy" onerror="this.style.opacity='0.3'">
<div class="name">{name}</div>
<button onclick="event.stopPropagation(); copy('{img_path}', this)">📋</button>
</div>
'''
html += ''' </div>
</div>
'''
html += ''' </div>
<div class="modal" id="modal" onclick="closeModal()">
<span class="close">&times;</span>
<img id="modalImg" src="" alt="Preview">
<div class="info" id="modalInfo"></div>
</div>
<script>
function copy(text, btn) {
navigator.clipboard.writeText(text).then(() => {
btn.textContent = '';
btn.classList.add('copied');
setTimeout(() => {
btn.textContent = '📋';
btn.classList.remove('copied');
}, 1500);
});
}
function openModal(src, name) {
document.getElementById('modalImg').src = src;
document.getElementById('modalInfo').textContent = src;
document.getElementById('modal').classList.add('active');
}
function closeModal() {
document.getElementById('modal').classList.remove('active');
}
function toggleSection(el) {
const grid = el.nextElementSibling;
grid.classList.toggle('hidden');
}
document.getElementById('search').addEventListener('input', filterImages);
document.getElementById('categoryFilter').addEventListener('change', filterImages);
function filterImages() {
const search = document.getElementById('search').value.toLowerCase();
const category = document.getElementById('categoryFilter').value;
document.querySelectorAll('.card').forEach(card => {
const name = card.dataset.name;
const path = card.dataset.path.toLowerCase();
const cardCategory = card.closest('.section').dataset.category;
const matchesSearch = !search || name.includes(search) || path.includes(search);
const matchesCategory = !category || cardCategory === category;
card.classList.toggle('hidden', !(matchesSearch && matchesCategory));
});
document.querySelectorAll('.section').forEach(section => {
const visible = section.querySelectorAll('.card:not(.hidden)').length;
section.classList.toggle('hidden', visible === 0);
});
}
document.addEventListener('keydown', e => {
if (e.key === 'Escape') closeModal();
if (e.key === '/' && e.target.tagName !== 'INPUT') {
e.preventDefault();
document.getElementById('search').focus();
}
});
</script>
</body>
</html>
'''
# Write HTML file
with open('tiled_assets_mini.html', 'w', encoding='utf-8') as f:
f.write(html)
print(f"Generated tiled_assets_mini.html with {len(all_images)} images in {len(categories)} categories")
if __name__ == '__main__':
main()