srctools.choreo
Text format is the .vcd format saved by Faceposer, and includes a number of additional attributes to save the editor configuration.
Binary format is contained in the scenes.image file, only storing the data required to actually play the scene.
Note that scenes from scenes.image are not named - they are looked up by a hash/checksum of the VCD filename, so the filenames must already be known to identify an entry.
Basic usage
An example for reading and writing VCDs and scenes.image:
from srctools.choreo import *
from srctools.tokenizer import Tokenizer
with open('some_scene.vcd') as file:
scene = Scene.parse_text(Tokenizer(file))
with open('some_scene_copy.vcd', 'w') as file:
scene.export_text(file)
with open('scenes.image', 'rb') as file:
image = parse_scenes_image(file)
with open('new_scenes.image', 'wb') as file:
save_scenes_image_sync(file, image)
Scenes.image
Entry instances represent the additional metadata contained in an image file.
- class srctools.choreo.Entry(
- filename: str,
- checksum: CRC,
- duration_ms: int,
- last_speak_ms: int,
- sounds: list[str],
- data: Scene | tuple[bytes, list[str]],
An entry in
scenes.image, containing useful metadata about a scene.The data attribute may be accessed to parse the scene.
- filename: str
The filename of the choreo scene. If parsed from scenes.image, only a CRC is available. When set, this automatically recalculates the checksum.
- checksum: CRC
- type srctools.choreo.CRC = int
This
typing.NewTyperepresents computed CRC checksums.
- srctools.choreo.parse_scenes_image( ) dict[CRC, Entry]
Parse the
scenes.imagefile, extracting all the choreo data.
- srctools.choreo.save_scenes_image_sync(
- file: FileWBinarySeek,
- scenes: dict[CRC, Entry] | Iterable[Entry],
- *,
- version: Literal[2, 3] = 3,
- encoding: str = 'latin1',
Write a new
scenes.imagefile.Binary scenes use a common string pool, meaning that all unparsed scenes must share their pool to be copied over directly.
Scene Tree
Scenes consist of many Events, organised into Channels which themselves are directed at specific Actor NPCs.
- class srctools.choreo.Scene(
- *,
- events: list[Event] = ...,
- actors: list[Actor] = ...,
- ramp: Curve = ...,
- ignore_phonemes: bool = False,
- text_crc: int = 0,
- map_name: str = '',
- fps: int = 60,
- time_zoom_lookup: dict[int, int] = ...,
- use_frame_snap: bool = False,
- scale_settings: dict[str, str] = ...,
A choreo scene.
- classmethod parse_text(tokenizer: BaseTokenizer) Self
Parse a scene from a text VCD file.
This does not calculate the CRC value.
- iter_events( ) Iterator[Event]
Iterate over all events, including those in actors.
If a filter is provided, only events of that type are produced.
- class srctools.choreo.Actor( )
An actor in a choreo scene.
- classmethod parse_text(tokenizer: BaseTokenizer) Self
Parse text data. The ‘actor’ string should have already been parsed.
- class srctools.choreo.Channel(name: str, active: bool = True, events: list[Event] = ...)
A channel defines a set of events that an actor performs.
- classmethod parse_text(tokenizer: BaseTokenizer) Self
Parse text data. The ‘channnel’ string should have already been parsed.
Events
There are many types of events. Most share common configuration and use the base Event class, but some have additional options and require a specific subclass.
- class srctools.choreo.EventType
Bases:
EnumKinds of events.
- Unspecified = 0
- Section = 1
- Expression = 2
- LookAt = 3
- MoveTo = 4
- Speak = 5
- Gesture = 6
- Sequence = 7
- Face = 8
- FireTrigger = 9
- FlexAnimation = 10
- SubScene = 11
- Loop = 12
- Interrupt = 13
- StopPoint = 14
- PermitResponses = 15
- Generic = 16
- Camera = 17
- Script = 18
- class srctools.choreo.EventFlags
Bases:
FlagFlags for an event.
- NoFlags = 0x0
- ResumeCondition = 0x1
- LockBodyFacing = 0x2
- FixedLength = 0x4
- Active = 0x8
- ForceShortMovement = 0x10
- PlayOverScript = 0x20
- class srctools.choreo.Event(*, name: str, type: ~typing.Literal[EventType.Unspecified, EventType.Section, EventType.Expression, EventType.LookAt, EventType.MoveTo, EventType.Sequence, EventType.Face, EventType.FireTrigger, EventType.FlexAnimation, EventType.SubScene, EventType.Interrupt, EventType.StopPoint, EventType.PermitResponses, EventType.Generic, EventType.Camera, EventType.Script], flags: ~srctools.choreo.EventFlags = <EventFlags.NoFlags: 0>, parameters: tuple[str, str, str], start_time: float, end_time: float = -1.0, ramp: ~srctools.choreo.Curve, tag_name: str | None = None, tag_wav_name: str | None = None, dist_to_targ: float = 0, relative_tags: list[~srctools.choreo.Tag] =..., timing_tags: list[~srctools.choreo.TimingTag] =..., absolute_playback_tags: list[~srctools.choreo.AbsoluteTag] =..., absolute_shifted_tags: list[~srctools.choreo.AbsoluteTag] =..., flex_anim_tracks: list[~srctools.choreo.FlexAnimTrack] =..., default_curve_type: ~srctools.choreo.CurveType = CurveType(first=<Interpolation.DEFAULT: 0>, second=<Interpolation.DEFAULT: 0>), pitch: int = 0, yaw: int = 0)
An event is an action that occurs in a choreo scene’s timeline.
- flags: EventFlags
- absolute_playback_tags: list[AbsoluteTag]
- absolute_shifted_tags: list[AbsoluteTag]
- flex_anim_tracks: list[FlexAnimTrack]
- export_binary(
- file: FileWBinary,
- add_to_pool: Callable[[str], int],
Write this to a binary BVCD block.
- classmethod parse_text(tokenizer: BaseTokenizer) Event
Parse text data. The ‘event’ string should have already been parsed.
- class srctools.choreo.GestureEvent(*, name: str, flags: ~srctools.choreo.EventFlags = <EventFlags.NoFlags: 0>, parameters: tuple[str, str, str], start_time: float, end_time: float = -1.0, ramp: ~srctools.choreo.Curve, tag_name: str | None = None, tag_wav_name: str | None = None, dist_to_targ: float = 0, relative_tags: list[~srctools.choreo.Tag] =..., timing_tags: list[~srctools.choreo.TimingTag] =..., absolute_playback_tags: list[~srctools.choreo.AbsoluteTag] =..., absolute_shifted_tags: list[~srctools.choreo.AbsoluteTag] =..., flex_anim_tracks: list[~srctools.choreo.FlexAnimTrack] =..., default_curve_type: ~srctools.choreo.CurveType = CurveType(first=<Interpolation.DEFAULT: 0>, second=<Interpolation.DEFAULT: 0>), pitch: int = 0, yaw: int = 0, gesture_sequence_duration: float)
Additional parameters for Gesture events.
- class srctools.choreo.LoopEvent(*, name: str, flags: ~srctools.choreo.EventFlags = <EventFlags.NoFlags: 0>, parameters: tuple[str, str, str], start_time: float, end_time: float = -1.0, ramp: ~srctools.choreo.Curve, tag_name: str | None = None, tag_wav_name: str | None = None, dist_to_targ: float = 0, relative_tags: list[~srctools.choreo.Tag] =..., timing_tags: list[~srctools.choreo.TimingTag] =..., absolute_playback_tags: list[~srctools.choreo.AbsoluteTag] =..., absolute_shifted_tags: list[~srctools.choreo.AbsoluteTag] =..., flex_anim_tracks: list[~srctools.choreo.FlexAnimTrack] =..., default_curve_type: ~srctools.choreo.CurveType = CurveType(first=<Interpolation.DEFAULT: 0>, second=<Interpolation.DEFAULT: 0>), pitch: int = 0, yaw: int = 0, loop_count: int = 0)
Additional parameters for Loop events.
- class srctools.choreo.SpeakEvent(*, name: str, flags: ~srctools.choreo.EventFlags = <EventFlags.NoFlags: 0>, parameters: tuple[str, str, str], start_time: float, end_time: float = -1.0, ramp: ~srctools.choreo.Curve, tag_name: str | None = None, tag_wav_name: str | None = None, dist_to_targ: float = 0, relative_tags: list[~srctools.choreo.Tag] =..., timing_tags: list[~srctools.choreo.TimingTag] =..., absolute_playback_tags: list[~srctools.choreo.AbsoluteTag] =..., absolute_shifted_tags: list[~srctools.choreo.AbsoluteTag] =..., flex_anim_tracks: list[~srctools.choreo.FlexAnimTrack] =..., default_curve_type: ~srctools.choreo.CurveType = CurveType(first=<Interpolation.DEFAULT: 0>, second=<Interpolation.DEFAULT: 0>), pitch: int = 0, yaw: int = 0, caption_type: ~srctools.choreo.CaptionType = CaptionType.Master, cc_token: str = '', suppress_caption_attenuation: bool = False, use_combined_file: bool = False, use_gender_token: bool = False)
Additional parameters for Speak events.
- caption_type: CaptionType
Miscellaneous Classes
- class srctools.choreo.Interpolation(*values)
Kinds of interpolation.
- DEFAULT = 0
- CATMULL_ROM_NORMALIZE_X = 1
- EASE_IN = 2
- EASE_OUT = 3
- EASE_IN_OUT = 4
- BSP_LINE = 5
- LINEAR = 6
- KOCHANEK_BARTELS = 7
- KOCHANEK_BARTELS_EARLY = 8
- KOCHANEK_BARTELS_LATE = 9
- SIMPLE_CUBIC = 10
- CATMULL_ROM = 11
- CATMULL_ROM_NORMALIZE = 12
- CATMULL_ROM_TANGENT = 13
- EXPONENTIAL_DECAY = 14
- HOLD = 15
- class srctools.choreo.CurveType(first: Interpolation, second: Interpolation)
A pair of interpolation types.
- first: Interpolation
- second: Interpolation
- class srctools.choreo.CaptionType
Bases:
EnumKind of closed captions.
- Master = 0
- Slave = 1
- Disabled = 2
- class srctools.choreo.ExpressionSample(
- time: float,
- value: float,
- curve_type: ~srctools.choreo.CurveType = CurveType(first=<Interpolation.DEFAULT: 0>,
- second=<Interpolation.DEFAULT: 0>),
Keyframes for animations.
- class srctools.choreo.Tag(name: str, value: float)
A tag labels a particular location in an event.
- value: float
Value for the tag. Ranges from 0-1, but is encoded into binary with 8 bits of precision.
- classmethod parse_binary( ) list[Self]
Parse a list of tags from the file. If double is set, the value is 16-bit not 8-bit.
- classmethod for ... in parse_text(
- tokenizer: BaseTokenizer,
Parse a list of tags from a text file.
- class srctools.choreo.TimingTag(name: str, value: float, locked: bool = False)
Flex animation timing tags additionally can be locked.
- class srctools.choreo.AbsoluteTag(name: str, value: float)
Absolute tags have an increased range and precision.
- class srctools.choreo.CurveEdge(
- active: bool,
- zero_pos: float = 0.0,
- curve_type: ~srctools.choreo.CurveType = CurveType(first=<Interpolation.DEFAULT: 0>,
- second=<Interpolation.DEFAULT: 0>),
Curve data, only saved in the text file.
- classmethod parse_text(tokenizer: BaseTokenizer) Self
Parse text data. The leftedge/rightedge string should have already been parsed.
- class srctools.choreo.Curve(
- ramp: list[~srctools.choreo.ExpressionSample] =...,
- left: ~srctools.choreo.CurveEdge = CurveEdge(active=False,
- zero_pos=0.0,
- curve_type=CurveType(first=<Interpolation.DEFAULT: 0>,
- second=<Interpolation.DEFAULT: 0>)),
- right: ~srctools.choreo.CurveEdge = CurveEdge(active=False,
- zero_pos=0.0,
- curve_type=CurveType(first=<Interpolation.DEFAULT: 0>,
- second=<Interpolation.DEFAULT: 0>)),
Scene or event ramp data.
- ramp: list[ExpressionSample]
- export_binary(file: FileWBinary) None
Write this to a binary BVCD block.
- classmethod parse_text(tokenizer: BaseTokenizer) Self
Parse text data. The ‘ramp’ string should have already been parsed.
- class srctools.choreo.FlexAnimTrack(
- name: str,
- active: bool = True,
- min: float = 0.0,
- max: float = 1.0,
- mag_track: list[~srctools.choreo.ExpressionSample] =...,
- dir_track: list[~srctools.choreo.ExpressionSample] | None = None,
- left: ~srctools.choreo.CurveEdge = CurveEdge(active=False,
- zero_pos=0.0,
- curve_type=CurveType(first=<Interpolation.DEFAULT: 0>,
- second=<Interpolation.DEFAULT: 0>)),
- right: ~srctools.choreo.CurveEdge = CurveEdge(active=False,
- zero_pos=0.0,
- curve_type=CurveType(first=<Interpolation.DEFAULT: 0>,
- second=<Interpolation.DEFAULT: 0>)),
Flex controller animation data.
- mag_track: list[ExpressionSample]
- dir_track: list[ExpressionSample] | None
- classmethod parse_binary( ) FlexAnimTrack
Parse the BVCD form of this data.