feat: integrate Draco compression for 3D models in backoffice

- Added support for uploading and compressing GLB models using Draco in the backoffice.
- Implemented commands for importing and re-compressing 3D models.
- Updated model resource to handle 3D model uploads and validations.
- Introduced a new script for compressing GLB files with Draco.
- Modified Vite configuration to remove GLB files from the build output.
- Updated package dependencies to include GLTF-transform libraries for handling 3D models.
- Added tests to ensure proper functionality of 3D model handling and compression.
This commit is contained in:
2026-11-01 10:35:50 +01:00
parent 24f9e59654
commit 1208187a17
32 changed files with 895 additions and 52 deletions
@@ -0,0 +1,60 @@
<?php
namespace App\Filament\Resources\ModelloResource\Pages\Concerns;
use App\Models\Modello;
use App\Support\Configuratore\Modelli3d;
use App\Support\Configuratore\Modello3dNonValido;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
/**
* Il campo "Modello 3D" non è una colonna: il file caricato passa da Modelli3d, che salva
* l'originale e la copia compressa con Draco. Se la compressione fallisce, il salvataggio
* viene annullato (transazione) e l'errore compare sul campo.
*/
trait CaricaModello3d
{
protected function handleRecordCreation(array $data): Model
{
$file = Arr::pull($data, 'modello_3d_upload');
return DB::transaction(function () use ($data, $file) {
$record = parent::handleRecordCreation($data);
$this->caricaModello3d($record, $file);
return $record;
});
}
protected function handleRecordUpdate(Model $record, array $data): Model
{
$file = Arr::pull($data, 'modello_3d_upload');
return DB::transaction(function () use ($record, $data, $file) {
$record = parent::handleRecordUpdate($record, $data);
$this->caricaModello3d($record, $file);
return $record;
});
}
private function caricaModello3d(Model $record, mixed $file): void
{
$file = is_array($file) ? Arr::first($file) : $file;
if (! $file instanceof TemporaryUploadedFile || ! $record instanceof Modello) {
return;
}
try {
app(Modelli3d::class)->carica($record, $file->getRealPath(), $file->getClientOriginalName());
} catch (Modello3dNonValido $e) {
throw ValidationException::withMessages(['data.modello_3d_upload' => $e->getMessage()]);
}
$file->delete();
}
}