c26aec916e
Reusable gradient definitions with built-in presets (rainbow, sunset, ocean, etc.) and user-created gradients. Includes model, JSON store, Pydantic schemas, REST routes (list/create/update/clone/delete), and backup/restore integration.
84 lines
2.5 KiB
Python
84 lines
2.5 KiB
Python
"""Gradient data model.
|
|
|
|
A Gradient defines a reusable color gradient as a list of color stops.
|
|
Gradients are referenced by ID from effect, gradient, and audio color
|
|
strip sources. Eight built-in gradients are seeded on first run.
|
|
"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
from typing import List, Optional
|
|
|
|
|
|
@dataclass
|
|
class Gradient:
|
|
"""Persistent gradient definition with color stops."""
|
|
|
|
id: str
|
|
name: str
|
|
stops: list # [{"position": float, "color": [R, G, B]}, ...]
|
|
is_builtin: bool
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
description: Optional[str] = None
|
|
tags: List[str] = field(default_factory=list)
|
|
|
|
def to_dict(self) -> dict:
|
|
return {
|
|
"id": self.id,
|
|
"name": self.name,
|
|
"stops": self.stops,
|
|
"is_builtin": self.is_builtin,
|
|
"description": self.description,
|
|
"tags": self.tags,
|
|
"created_at": self.created_at.isoformat(),
|
|
"updated_at": self.updated_at.isoformat(),
|
|
}
|
|
|
|
@staticmethod
|
|
def from_dict(data: dict) -> "Gradient":
|
|
return Gradient(
|
|
id=data["id"],
|
|
name=data["name"],
|
|
stops=data.get("stops", []),
|
|
is_builtin=data.get("is_builtin", False),
|
|
description=data.get("description"),
|
|
tags=data.get("tags", []),
|
|
created_at=datetime.fromisoformat(data["created_at"]),
|
|
updated_at=datetime.fromisoformat(data["updated_at"]),
|
|
)
|
|
|
|
@classmethod
|
|
def create_from_kwargs(
|
|
cls,
|
|
*,
|
|
id: str,
|
|
name: str,
|
|
stops: list,
|
|
is_builtin: bool = False,
|
|
created_at: datetime,
|
|
updated_at: datetime,
|
|
description: Optional[str] = None,
|
|
tags: Optional[List[str]] = None,
|
|
) -> "Gradient":
|
|
return cls(
|
|
id=id,
|
|
name=name,
|
|
stops=stops,
|
|
is_builtin=is_builtin,
|
|
created_at=created_at,
|
|
updated_at=updated_at,
|
|
description=description,
|
|
tags=tags or [],
|
|
)
|
|
|
|
def apply_update(self, **kwargs) -> None:
|
|
if kwargs.get("name") is not None:
|
|
self.name = kwargs["name"]
|
|
if kwargs.get("stops") is not None:
|
|
self.stops = kwargs["stops"]
|
|
if kwargs.get("description") is not None:
|
|
self.description = kwargs["description"]
|
|
if kwargs.get("tags") is not None:
|
|
self.tags = kwargs["tags"]
|