diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392..e2fd994 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640..69a6b19 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659..f74125d 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2a36fd6..500c278 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 8c38f3f..d081776 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,28 @@ from django.contrib import admin +from .models import Project, PipelineStep, CgiAsset -# Register your models here. +class PipelineStepInline(admin.TabularInline): + model = PipelineStep + extra = 1 + +class CgiAssetInline(admin.TabularInline): + model = CgiAsset + extra = 1 + +@admin.register(Project) +class ProjectAdmin(admin.ModelAdmin): + list_display = ('title', 'project_type', 'status', 'created_at') + list_filter = ('project_type', 'status') + search_fields = ('title', 'description') + prepopulated_fields = {'slug': ('title',)} + inlines = [PipelineStepInline, CgiAssetInline] + +@admin.register(PipelineStep) +class PipelineStepAdmin(admin.ModelAdmin): + list_display = ('project', 'name', 'progress', 'is_completed') + list_filter = ('name', 'is_completed') + +@admin.register(CgiAsset) +class CgiAssetAdmin(admin.ModelAdmin): + list_display = ('name', 'project', 'asset_type', 'is_realistic') + list_filter = ('asset_type', 'is_realistic') diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..017933c --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,54 @@ +# Generated by Django 5.2.7 on 2026-02-16 00:18 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255)), + ('slug', models.SlugField(blank=True, unique=True)), + ('project_type', models.CharField(choices=[('MOVIE', 'Feature Film'), ('SERIES', 'TV Series'), ('SHORT', 'Short Film')], default='MOVIE', max_length=10)), + ('status', models.CharField(choices=[('PRE', 'Pre-Production'), ('PROD', 'Production'), ('POST', 'Post-Production'), ('DONE', 'Completed')], default='PRE', max_length=10)), + ('description', models.TextField(blank=True)), + ('thumbnail_url', models.URLField(blank=True, help_text='URL to a representative image')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + ), + migrations.CreateModel( + name='PipelineStep', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(choices=[('CONCEPT', 'Concept & Storyboard'), ('MODELING', '3D Modeling'), ('RIGGING', 'Rigging'), ('ANIMATION', 'Animation'), ('LIGHTING', 'Lighting & FX'), ('RENDERING', 'Rendering'), ('COMPOSITING', 'Compositing')], max_length=20)), + ('progress', models.PositiveIntegerField(default=0, help_text='Progress from 0 to 100')), + ('is_completed', models.BooleanField(default=False)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='steps', to='core.project')), + ], + options={ + 'ordering': ['id'], + }, + ), + migrations.CreateModel( + name='CgiAsset', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('asset_type', models.CharField(choices=[('CHAR', 'Character'), ('PROP', 'Prop'), ('ENV', 'Environment')], max_length=10)), + ('is_realistic', models.BooleanField(default=True)), + ('current_stage', models.CharField(default='Modeling', max_length=100)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='assets', to='core.project')), + ], + ), + ] diff --git a/core/migrations/0002_alter_pipelinestep_name.py b/core/migrations/0002_alter_pipelinestep_name.py new file mode 100644 index 0000000..149bab4 --- /dev/null +++ b/core/migrations/0002_alter_pipelinestep_name.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2026-02-16 00:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='pipelinestep', + name='name', + field=models.CharField(choices=[('SCRIPT', 'Roteiro & Storyboard'), ('CONCEPT', 'Concept Art'), ('ANIMATIC', 'Animatic'), ('MODELING', 'Modelagem 3D'), ('TEXTURING', 'Texturização'), ('RIGGING', 'Rigging'), ('ANIMATION', 'Animação'), ('LIGHTING', 'Iluminação'), ('FX', 'Simulação (FX)'), ('RENDERING', 'Renderização'), ('COMPOSITING', 'Composição'), ('EDITING', 'Edição & Sonoplastia')], max_length=20), + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..24d0cb5 Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0002_alter_pipelinestep_name.cpython-311.pyc b/core/migrations/__pycache__/0002_alter_pipelinestep_name.cpython-311.pyc new file mode 100644 index 0000000..9da1ddb Binary files /dev/null and b/core/migrations/__pycache__/0002_alter_pipelinestep_name.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..9b7a9e0 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,77 @@ from django.db import models +from django.utils.text import slugify -# Create your models here. +class Project(models.Model): + TYPES = ( + ('MOVIE', 'Feature Film'), + ('SERIES', 'TV Series'), + ('SHORT', 'Short Film'), + ) + STATUS_CHOICES = ( + ('PRE', 'Pre-Production'), + ('PROD', 'Production'), + ('POST', 'Post-Production'), + ('DONE', 'Completed'), + ) + + title = models.CharField(max_length=255) + slug = models.SlugField(unique=True, blank=True) + project_type = models.CharField(max_length=10, choices=TYPES, default='MOVIE') + status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='PRE') + description = models.TextField(blank=True) + thumbnail_url = models.URLField(blank=True, help_text="URL to a representative image") + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + super().save(*args, **kwargs) + + def __str__(self): + return self.title + +class PipelineStep(models.Model): + STAGES = ( + # Pre-Production + ('SCRIPT', 'Roteiro & Storyboard'), + ('CONCEPT', 'Concept Art'), + ('ANIMATIC', 'Animatic'), + # Production + ('MODELING', 'Modelagem 3D'), + ('TEXTURING', 'Texturização'), + ('RIGGING', 'Rigging'), + ('ANIMATION', 'Animação'), + ('LIGHTING', 'Iluminação'), + ('FX', 'Simulação (FX)'), + # Post-Production + ('RENDERING', 'Renderização'), + ('COMPOSITING', 'Composição'), + ('EDITING', 'Edição & Sonoplastia'), + ) + project = models.ForeignKey(Project, related_name='steps', on_delete=models.CASCADE) + name = models.CharField(max_length=20, choices=STAGES) + progress = models.PositiveIntegerField(default=0, help_text="Progress from 0 to 100") + is_completed = models.BooleanField(default=False) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + ordering = ['id'] + + def __str__(self): + return f"{self.project.title} - {self.get_name_display()}" + +class CgiAsset(models.Model): + ASSET_TYPES = ( + ('CHAR', 'Character'), + ('PROP', 'Prop'), + ('ENV', 'Environment'), + ) + project = models.ForeignKey(Project, related_name='assets', on_delete=models.CASCADE) + name = models.CharField(max_length=255) + asset_type = models.CharField(max_length=10, choices=ASSET_TYPES) + is_realistic = models.BooleanField(default=True) + current_stage = models.CharField(max_length=100, default='Modeling') + + def __str__(self): + return f"{self.name} ({self.get_asset_type_display()})" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..a656bcd 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,74 @@ - - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}CGI Studio{% endblock %} + + + + + + + + + + {% block extra_head %}{% endblock %} - - {% block content %}{% endblock %} - + +
+ {% block content %}{% endblock %} +
+ + + + + + {% block extra_js %}{% endblock %} + diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..d224271 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,181 @@ {% extends "base.html" %} +{% load static %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}Command Center | Studio CGI Virtual{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+
+ NEXT-GEN CGI PIPELINE +
+

Studio de Cinema Virtual

+

+ A fábrica digital para super-produções. Gerencie do roteiro à renderização em um fluxo de produção rigoroso e colaborativo. +

+
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
-
- + + +
+
+
+
+
+ Total de Projetos + {{ total_projects }} +
+
+
+
+ Produções Ativas + {{ active_productions }} +
+
+
+
+ Obras Finalizadas + {{ completed_projects }} +
+
+
+ +
+
+

Produções em Andamento

+

Status em tempo real do pipeline CGI

+
+
+ +
+ {% for project in projects %} +
+
+
+ {{ project.get_status_display }} + {{ project.get_project_type_display }} +
+ +

+ + {{ project.title }} + +

+ +

+ {{ project.description|default:"Sem descrição definida para esta super-produção."|truncatewords:20 }} +

+ +
+
+ Progresso do Pipeline + {% with last_step=project.steps.last %} + {{ last_step.progress|default:0 }}% + {% endwith %} +
+
+ {% with last_step=project.steps.last %} +
+ {% endwith %} +
+ +
+ {% for step in project.steps.all|slice:":4" %} + + {{ step.get_name_display }} + + {% endfor %} + {% if project.steps.count > 4 %} + +{{ project.steps.count|add:"-4" }} + {% endif %} +
+
+ + +
+
+ {% empty %} +
+
+ + + + +
+

Nenhuma produção ativa

+

Comece sua primeira super-produção 3D agora.

+ Iniciar Projeto +
+ {% endfor %} +
+
+
+ +
+
+
+
+

Pipeline CGI Profissional

+

Nosso estúdio segue o fluxo de trabalho dos maiores estúdios de Hollywood, garantindo qualidade em cada quadro.

+
+
+
+

Pré-produção

+

Roteiro, Concept Art e Animatic para definir a alma do filme.

+
+
+
+
+

Produção

+

Modelagem, Rigging e Animação com personagens realistas.

+
+
+
+
+

Iluminação & FX

+

Simulação de partículas, fluidos e luzes cinematográficas.

+
+
+
+
+

Pós-produção

+

Renderização em render farm e composição final.

+
+
+
+
+
+
+
+
+
+
+
+
+

Status da Render Farm

+
+
+ Nodes Ativos + 128 / 128 +
+
+ CPU Load + 94% +
+
+ Tempo Estimado + 04:12:33 +
+
+
+
+
+
+
+
+
+
{% endblock %} \ No newline at end of file diff --git a/core/templates/core/project_detail.html b/core/templates/core/project_detail.html new file mode 100644 index 0000000..2d25240 --- /dev/null +++ b/core/templates/core/project_detail.html @@ -0,0 +1,103 @@ +{% extends "base.html" %} +{% load static %} + +{% block title %}{{ project.title }} | Pipeline Detail{% endblock %} + +{% block content %} +
+
+ + +
+
+ {{ project.get_status_display }} +

{{ project.title }}

+

{{ project.description }}

+
+
+
+ Global Delivery + + {% with last_step=project.steps.last %}{{ last_step.progress|default:0 }}{% endwith %}% + +
+
+
+
+
+ +
+
+
+
+

CGI Production Pipeline

+ +
+ {% for step in steps %} +
+
+
+
+ {{ forloop.counter }} +
+

{{ step.get_name_display }}

+
+ {% if step.is_completed %} + COMPLETO + {% else %} + {{ step.progress }}% + {% endif %} +
+ +
+
+
+
+ {% empty %} +
+

Pipeline não inicializado. Configure as etapas no Admin.

+ Adicionar Etapa + +
+ {% endfor %} +
+
+ +
+
+

Assets Digitais

+
+ {% for asset in assets %} +
+
+ {{ asset.name }} + {{ asset.get_asset_type_display }} • {{ asset.current_stage }} +
+ {% if asset.is_realistic %} + REALISTA + {% endif %} +
+ {% empty %} +

Nenhum asset (personagens/cenários) vinculado.

+ {% endfor %} +
+ +
+
Diretrizes de Qualidade
+
    +
  • ✓ Topologia limpa para rigging
  • +
  • ✓ Texturas 4K/8K PBR
  • +
  • ✓ Iluminação física (PBR)
  • +
  • ✓ Renderização em EXR Multi-camada
  • +
+
+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/core/urls.py b/core/urls.py index 6299e3d..b9e0a07 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,7 @@ from django.urls import path - -from .views import home +from .views import home, project_detail urlpatterns = [ path("", home, name="home"), -] + path("project//", project_detail, name="project_detail"), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..9e5fe2c 100644 --- a/core/views.py +++ b/core/views.py @@ -2,24 +2,36 @@ import os import platform from django import get_version as django_version -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404 from django.utils import timezone +from .models import Project, PipelineStep, CgiAsset def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() + """Render the CGI Studio Command Center.""" + projects = Project.objects.prefetch_related('steps').all() + + # Simple statistics for the dashboard + total_projects = projects.count() + active_productions = projects.filter(status='PROD').count() + completed_projects = projects.filter(status='DONE').count() context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), + "projects": projects, + "total_projects": total_projects, + "active_productions": active_productions, + "completed_projects": completed_projects, + "current_time": timezone.now(), } return render(request, "core/index.html", context) + +def project_detail(request, slug): + """Render the detailed pipeline for a specific production.""" + project = get_object_or_404(Project.objects.prefetch_related('steps', 'assets'), slug=slug) + + context = { + "project": project, + "steps": project.steps.all(), + "assets": project.assets.all(), + } + return render(request, "core/project_detail.html", context) \ No newline at end of file diff --git a/populate_demo.py b/populate_demo.py new file mode 100644 index 0000000..dfc6141 --- /dev/null +++ b/populate_demo.py @@ -0,0 +1,54 @@ +from core.models import Project, PipelineStep, CgiAsset + +def run(): + # Clear existing data + PipelineStep.objects.all().delete() + CgiAsset.objects.all().delete() + Project.objects.all().delete() + + # Create a Movie Project + p1 = Project.objects.create( + title="O Último Guardião", + project_type="MOVIE", + status="PROD", + description="Um épico de ficção científica sobre o último protetor de uma civilização esquecida. Foco em CGI fotorrealista e ambientes vastos." + ) + + steps = [ + ('SCRIPT', 100, True), + ('CONCEPT', 100, True), + ('ANIMATIC', 100, True), + ('MODELING', 85, False), + ('TEXTURING', 60, False), + ('RIGGING', 40, False), + ('ANIMATION', 20, False), + ('LIGHTING', 10, False), + ('FX', 5, False), + ] + + for name, progress, completed in steps: + PipelineStep.objects.create( + project=p1, + name=name, + progress=progress, + is_completed=completed + ) + + CgiAsset.objects.create(project=p1, name="Kaelen (Herói)", asset_type="CHAR", is_realistic=True, current_stage="Rigging") + CgiAsset.objects.create(project=p1, name="Cidade Flutuante", asset_type="ENV", is_realistic=True, current_stage="Texturing") + + # Create a Series Project + p2 = Project.objects.create( + title="Crônicas de Cyber-Rio", + project_type="SERIES", + status="PRE", + description="Série de animação estilizada ambientada em um Rio de Janeiro futurista. Mistura de 2D e 3D." + ) + + PipelineStep.objects.create(project=p2, name="SCRIPT", progress=100, is_completed=True) + PipelineStep.objects.create(project=p2, name="CONCEPT", progress=40, is_completed=False) + + print("Demo data created successfully!") + +if __name__ == "__main__": + run() diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..9c3283c 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,116 @@ -/* Custom styles for the application */ -body { - font-family: system-ui, -apple-system, sans-serif; +/* CGI Studio Custom Styling */ +:root { + --bg-deep: #0a0a0c; + --bg-card: #141417; + --accent-cyan: #00e5ff; + --accent-purple: #7000ff; + --text-muted: #888891; + --glass-bg: rgba(10, 10, 12, 0.8); +} + +body { + background-color: var(--bg-deep); + color: #f8f9fa; + line-height: 1.6; +} + +.text-cyan { color: var(--accent-cyan); } +.text-purple { color: var(--accent-purple); } + +.studio-navbar { + background: var(--glass-bg); + backdrop-filter: blur(20px); + border-bottom: 1px solid rgba(255, 255, 255, 0.05); + padding: 1rem 0; +} + +.hero-section { + padding: 140px 0 100px; + background: + radial-gradient(circle at 10% 20%, rgba(0, 229, 255, 0.05) 0%, transparent 40%), + radial-gradient(circle at 90% 80%, rgba(112, 0, 255, 0.05) 0%, transparent 40%); + position: relative; + overflow: hidden; +} + +.display-3 { + font-weight: 800; + letter-spacing: -2px; +} + +.btn-cyan { + background: var(--accent-cyan); + color: #000; + font-weight: 700; + border: none; + padding: 14px 32px; + border-radius: 12px; + text-transform: uppercase; + font-size: 0.9rem; + letter-spacing: 0.5px; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.btn-cyan:hover { + background: #4df1ff; + box-shadow: 0 0 30px rgba(0, 229, 255, 0.4); + transform: translateY(-2px); + color: #000; +} + +.project-card { + background: var(--bg-card); + border: 1px solid rgba(255, 255, 255, 0.05); + border-radius: 24px; + padding: 32px; + transition: all 0.4s ease; + height: 100%; + display: flex; + flex-direction: column; + position: relative; +} + +.project-card:hover { + border-color: rgba(0, 229, 255, 0.3); + background: #1a1a1f; + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4); +} + +.stats-card { + background: rgba(255, 255, 255, 0.02); + border: 1px solid rgba(255, 255, 255, 0.05); + padding: 28px; + border-radius: 20px; + text-align: center; +} + +.pipeline-badge { + padding: 6px 14px; + border-radius: 30px; + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 0.5px; +} + +.badge-pre { background: rgba(136, 136, 145, 0.1); color: #888891; border: 1px solid rgba(136, 136, 145, 0.2); } +.badge-prod { background: rgba(112, 0, 255, 0.1); color: #b780ff; border: 1px solid rgba(112, 0, 255, 0.2); } +.badge-post { background: rgba(0, 229, 255, 0.1); color: #00e5ff; border: 1px solid rgba(0, 229, 255, 0.2); } +.badge-done { background: rgba(0, 255, 149, 0.1); color: #00ff95; border: 1px solid rgba(0, 255, 149, 0.2); } + +.progress { + height: 8px; + background: rgba(255, 255, 255, 0.05); + border-radius: 10px; + overflow: hidden; +} + +.progress-bar { + background: linear-gradient(90deg, var(--accent-cyan), var(--accent-purple)); + border-radius: 10px; +} + +.section-title { + font-weight: 800; + margin-bottom: 2rem; }