feat(player): alteration engine — knob vector to RenderPlan (design §4/§5)
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
"""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)),
|
||||
)
|
||||
Reference in New Issue
Block a user