99 lines
3.0 KiB
Python
99 lines
3.0 KiB
Python
"""The alteration engine: a knob vector -> a layered RenderPlan (design §4, §5).
|
|
|
|
Replaces the 2026-06-04 nearest-match *selection* with a *transformation* of a
|
|
neutral base clip. Given the four experience knobs, it produces three layers
|
|
that compose per §4.2:
|
|
|
|
- Substrate transforms (alter pixels, blend with each other):
|
|
* Restyle -- the Right axis: a pre-baked generative v2v dreamlike restyle.
|
|
* ColorGrade -- the mood axis (Dark/Light): a deterministic color grade.
|
|
- Overlay (composited on top of the substrate):
|
|
* AnalyticalOverlay -- the Left axis: HUD/labels/measurement.
|
|
|
|
Left and Right are NOT opposites; they live on different layers and stack
|
|
(§4.2). Dark and Light are the two poles of one mood grade whose center is the
|
|
identity (§5).
|
|
|
|
Calibration note: the knob->strength curves below are the single source of
|
|
truth for how a 0..4 position maps to a transform strength. See the session
|
|
0006 transcript Deferred decisions for the §3-vs-§4.2/§5 reconciliation.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from hef.selection import Coordinate
|
|
|
|
KNOB_MAX = 4 # knob full-scale (0..4)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ColorGrade:
|
|
"""Mood-axis grade (§5). `tone` is signed: >0 warm yellow->white (light),
|
|
<0 cool blue->black (dark), 0 = identity (raw, ungraded)."""
|
|
|
|
tone: float
|
|
|
|
@property
|
|
def is_identity(self) -> bool:
|
|
return self.tone == 0.0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AnalyticalOverlay:
|
|
"""Left axis (§4.1): analytical HUD/annotation/labels, composited on top.
|
|
`intensity` 0..1 (0 = no overlay)."""
|
|
|
|
intensity: float
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Restyle:
|
|
"""Right axis (§4.1): pre-baked generative v2v dreamlike substrate.
|
|
`blend` 0..1 (0 = raw substrate, no restyle)."""
|
|
|
|
blend: float
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class RenderPlan:
|
|
"""The full layered alteration for one knob vector (§4.2)."""
|
|
|
|
grade: ColorGrade
|
|
overlay: AnalyticalOverlay
|
|
restyle: Restyle
|
|
|
|
@property
|
|
def is_identity(self) -> bool:
|
|
"""True when the plan leaves the neutral base un-altered."""
|
|
return (
|
|
self.grade.is_identity
|
|
and self.overlay.intensity == 0.0
|
|
and self.restyle.blend == 0.0
|
|
)
|
|
|
|
|
|
def _overlay_intensity(left: int) -> float:
|
|
"""Left knob -> analytical-overlay intensity (0..1)."""
|
|
return left / KNOB_MAX
|
|
|
|
|
|
def _restyle_blend(right: int) -> float:
|
|
"""Right knob -> v2v restyle blend (0..1)."""
|
|
return right / KNOB_MAX
|
|
|
|
|
|
def _mood_tone(dark: int, light: int) -> float:
|
|
"""(dark, light) -> signed mood grade in [-1, 1]; equal -> 0 identity (§5)."""
|
|
return (light - dark) / KNOB_MAX
|
|
|
|
|
|
def plan_alteration(coord: Coordinate) -> RenderPlan:
|
|
"""Map a knob vector to its layered RenderPlan (design §4)."""
|
|
return RenderPlan(
|
|
grade=ColorGrade(tone=_mood_tone(coord.dark, coord.light)),
|
|
overlay=AnalyticalOverlay(intensity=_overlay_intensity(coord.left)),
|
|
restyle=Restyle(blend=_restyle_blend(coord.right)),
|
|
)
|