Aller au contenu

Camera Rules

Lorsque Libretto génère une séquence de dialogue, il filme la conversation pour vous : chaque plan (une coupe de caméra) est assigné à l'une des caméras du stage. Le choix n'est pas codé en dur — il est piloté par un petit système de scoring. Chaque règle de caméra note chaque caméra candidate pour le plan courant, les notes sont additionnées, et la caméra au score le plus élevé remporte la coupe.

Cette page explique où vivent ces règles, comment le générateur choisit quel ensemble appliquer, comment fonctionne le scoring, comment lire le journal de génération, quelles règles sont livrées avec le plugin, et comment créer les vôtres.

Presets de règles : un DataTable FLBRCameraRulesPreset

Les règles sont regroupées en presets. Un preset est une ligne d'un DataTable dont la structure de ligne est FLBRCameraRulesPreset (module LBRSequenceGenerator). La structure ne comporte qu'un seul champ, Project Camera Rules — un tableau de classes de règles de caméra (chacune un ULBRDialogueCameraRule).

Le plugin livre un tel table, DT_CameraRulesPresets sous /Libretto/CameraRules/, avec une ligne nommée BasePreset. D'emblée, BasePreset liste huit règles :

  • BP_CameraRule_30Degree
  • BP_CameraRule_Choice
  • BP_CameraRule_CloseMC
  • BP_CameraRule_CloseThought
  • BP_CameraRule_DisplayEmotion
  • BP_CameraRule_FocusedCharacter
  • BP_CameraRule_MediumShot
  • BP_CameraRule_ReuseMedium

The BasePreset row in DT_CameraRulesPresets

BP_CameraRule_FocusedCharacter est la règle qui fait le gros du travail : elle privilégie une caméra montrant le personnage qui parle au début de la plage temporelle du plan, de sorte que les plans pointent vers celui qui parle plutôt que de choisir une caméra au hasard.

Tip

Pour utiliser votre propre ensemble de règles, créez un nouveau DataTable (Row Structure FLBRCameraRulesPreset), ajoutez une ligne, et remplissez son tableau Project Camera Rules. Pointez ensuite l'un des trois niveaux de résolution ci-dessous vers ce table + cette ligne.

Comment le générateur choisit un preset

Pour chaque sous-dialogue, le générateur détermine quel preset utiliser selon cet ordre de priorité — le premier non vide l'emporte :

  1. La Dialogue Instance — sa propriété CameraRulesPreset (catégorie Staging), si le sous-dialogue est joué au travers d'une instance placée qui en définit une.
  2. Le Stage — le CameraRulesStageOverride de la classe de stage (son Camera Rules Stage Override dans les Class Defaults).
  3. Project Settings — ProjectCameraRules sous Project Settings ▸ Libretto - Sequence Generator ▸ Cameras, utilisé comme repli.

Dans le code, le repli est chargé en premier, puis écrasé par la valeur du stage si elle est définie, puis par celle de l'instance si elle est définie (LBRCameraTrackGenerator::InitSubDialogue).

Câblé par défaut

ProjectCameraRules est défini d'emblée dans le DefaultLibretto.ini du plugin sur DT_CameraRulesPresets / BasePreset, de sorte que les plans générés visent immédiatement le locuteur. Vous pouvez le surcharger par stage ou par instance.

Project Settings ▸ Libretto - Sequence Generator ▸ Cameras

Caméras de stage et types de plan

Les caméras d'un stage sont des composants ULBRStageCameraComponent — des cine cameras qu'une règle peut inspecter. Deux propriétés comptent le plus pour la création de règles :

  • Shot Type — un ELBRShotType décrivant le cadrage (voir ci-dessous).
  • Blend Type — un ELBRBlendCameraType (None, BlendIn, BlendOut, BlendInOut).

L'énumération ELBRShotType possède neuf valeurs :

Valeur
FullShot MediumShot
AmericanShot MediumCloseUpShot
CloseUpShot ExtremeCloseUpShot
OTS_MediumCloseUpShot OTS_CloseUpShot
LongShot

Un stage expose généralement plusieurs caméras par participant — par exemple un gros plan et un plan moyen sur chaque slot, plus des variantes par-dessus / sous l'épaule et une caméra choix dédiée. Les règles lisent ces types de plan pour raisonner sur le cadrage.

A stage camera's Shot Type and Blend Type

Follow focus : garder la tête dans le cadre

Une caméra de stage est bakée avec une transform statique — elle ne bouge pas pendant un plan. Quand le personnage cadré s'anime (balancement d'idle, gestes), sa tête dérive et peut sortir de la composition. Les propriétés Follow Focus sur ULBRStageCameraComponent permettent à la caméra active de réajuster son aim à chaque frame pour garder la tête cadrée, avec une latence volontairement douce, à la manière d'un cadreur.

La correction est additive : elle préserve votre cadrage d'auteur (par-dessus l'épaule, règle des tiers…) et ne compense que la dérive angulaire de la tête depuis le début du plan. Elle ne recentre jamais la tête et n'écrase pas la composition — elle infléchit seulement l'aim pour suivre le mouvement.

Propriété Défaut Rôle
Use Follow Focus true Interrupteur principal. Désactivé, la caméra garde sa transform bakée.
Follow Start Delay 0.35 s Délai de réaction après chaque coupe : la caméra tient son cadrage baké ce temps, puis le suivi s'enclenche en douceur. Émule un cadreur qui réagit un temps après le début du plan.
Follow Dead Zone 2.0° La tête peut dériver de ce nombre de degrés avant que la caméra ne réagisse. La zone morte est soustraite de la correction (pas de saut au franchissement du seuil), si bien que les micro-mouvements d'idle ne font jamais trembler le cadrage.
Follow Interp Speed 3.0 Raideur du rattrapage une fois le suivi actif — plus bas = plus mou/laggé, plus haut = plus collé. 0 = suivi instantané.

Les trois propriétés de timing composent le ressenti « cadreur » : la caméra réagit un temps après (Start Delay), ignore les petits tremblements (Dead Zone), puis rattrape en douceur (Interp Speed).

Seuls les plans à un seul focus suivent

Le suivi ne s'enclenche que si la caméra ne cadre qu'un seul personnage. Un plan large / de groupe (aucun focus) ou un plan par-dessus l'épaule / à deux (plusieurs personnages focalisés) garde son aim baké, si bien que la composition des plans multi-personnages n'est jamais perturbée.

Réglez ces propriétés par caméra dans la catégorie Camera du composant, dans le panneau Details. L'état du suivi est remis à zéro à chaque coupe, si bien que chaque nouveau plan recapture la position de repos de la tête avant d'appliquer le délai, la zone morte et le lissage.

Durée de plan et placement des coupes

Deux Project Settings bornent la durée d'un plan unique :

  • Min Shot Length — par défaut 2.0 s.
  • Max Shot Length — par défaut 9.0 s.

Les limites des coupes sont dérivées de manière déterministe des durées de réplique : une réplique qui tient dans la fenêtre min/max devient un plan ; une réplique plus longue que le max est répartie sur plusieurs plans ; une réplique trop courte est fusionnée avec le plan précédent (ou emprunte une tranche du suivant). C'est pourquoi un seul plan peut contenir plusieurs répliques courtes, ou qu'une coupe peut tomber au milieu d'une réplique.

Les coupes générées vivent sur la track Camera Cuts de chaque level sequence, les caméras étant regroupées dans un dossier GEN_Cameras.

Camera Cuts track and GEN_Cameras folder

Scoring : EvaluateScore

Chaque règle note une caméra candidate au travers d'EvaluateScore, un événement implémentable en Blueprint sur ULBRDialogueCameraRule :

int32 EvaluateScore(ULBRStageCameraComponent* CameraToTest, FCameraRuleData InputData)
  • Camera To Test — la caméra candidate en cours de notation.
  • Input Data — une struct de contexte FCameraRuleData. Décomposez-la (Break) pour obtenir :
    • Dialogue — le dialogue en cours de génération.
    • Line ID — l'ID de la réplique au début du plan.
    • Is Choice — indique si ce plan contient un choix.
    • Previous Cameras — un tableau des caméras susceptibles de précéder le plan.
  • Return Value — un score int32. Renvoyer 0 signifie que la règle n'a pas d'avis sur cette caméra. Toute autre valeur oriente le choix vers le haut ou vers le bas ; l'échelle exacte est entièrement laissée à vous et à vos concepteurs cinématiques pour la modéliser et l'équilibrer.

Pour chaque plan, le sélecteur exécute chaque règle sur chaque caméra. Les scores entiers par règle sont additionnés en un poids par caméra (un float), et la caméra au poids le plus élevé est sélectionnée.

Previous Cameras peut contenir plus d'une entrée

Sur le premier plan d'une séquence atteignable depuis plusieurs branches du dialogue, le tableau peut contenir plusieurs prédécesseurs. Sur une séquence linéaire simple, il en contient zéro (tout premier plan) ou un (le plan précédent de la même séquence).

Le journal de génération

Chaque génération écrit un journal pour que vous puissiez vérifier comment les règles ont été appliquées et itérer sur l'équilibrage. Il est écrit dans :

<Project>/Saved/GenerationLog/Cameras/<DialogueName>.txt

Le fichier est intégralement réécrit à chaque génération. Par séquence, il contient :

  1. Sentence data — un récapitulatif de chaque réplique (son ID, locuteur, auditeur, durée et tout cas particulier tel que Contains Choice).
  2. Camera Splits — chaque plan avec sa durée et les ID des répliques qu'il couvre.
  3. Scores par règle — pour chaque plan, une ligne par règle × caméra, par ex. :

    Rule  Default__BP_CameraRule_FocusedCharacter_C : Camera Slot1Medium_0 got 10 point.
    
  4. Récapitulatif des poids et sélection :

    ---------- Shot Camera Weights ----------
    Slot1Medium_0 : 10.0
    Slot1Closeup_3 : 10.0
    Choice1_5 : 10.0
    Camera selected : Slot1Closeup_3
    

    La caméra sélectionnée sur un plan de choix est en outre annotée -- Choice Cam ; une caméra qui cadre un personnage est annotée -- Focusing <Character>.

Lecture d'un journal réel : avec seulement FocusedCharacter actif, les caméras qui cadrent le locuteur courant reçoivent ses points et l'une d'elles est sélectionnée. Ajoutez une seconde règle et ses scores sont ajoutés aux mêmes poids — une caméra qui à la fois cadre le locuteur (+10) et satisfait la seconde règle (+20) finit à 30 et l'emporte.

The camera generation log

Règles livrées avec le plugin

Toutes les règles livrées vivent sous /Libretto/CameraRules/ :

Règle Intention
BP_CameraRule_FocusedCharacter Privilégier une caméra qui cadre celui qui parle au début du plan.
BP_CameraRule_Choice Privilégier la caméra de choix dédiée sur les plans contenant un choix.
BP_CameraRule_30Degree Pénaliser les coupes qui enfreignent la règle des 30 degrés entre caméras consécutives.
BP_CameraRule_MediumShot Favoriser les cadrages moyens.
BP_CameraRule_CloseMC Favoriser les cadrages en plan moyen serré.
BP_CameraRule_CloseThought Adapter le cadrage pour les répliques internes / de pensée.
BP_CameraRule_DisplayEmotion Adapter le cadrage pour accentuer les temps forts émotionnels.
BP_CameraRule_ReuseMedium Encourager la réutilisation d'une caméra en plan moyen pour la continuité.

Info

Ces assets de règles sont des Blueprints ; leur scoring exact est défini dans le graphe EvaluateScore de chaque Blueprint plutôt qu'en C++, et les résumés ci-dessus décrivent l'intention d'après leurs noms. /Libretto/CameraRules/ contient également BP_CameraRule_RandomListener, qui existe en tant qu'asset mais ne fait pas partie du BasePreset livré — ajoutez-le vous-même à un preset si vous le souhaitez.

Créer une règle personnalisée

Ce qui suit détaille une règle qui alterne le cadrage : après un gros plan, récompenser les cadrages moyen/large ; après un moyen/large, récompenser un gros plan.

  1. Créez le Blueprint. Clic droit dans le Content Browser ▸ Blueprint Class, et dans Pick Parent Class recherchez « camera rule » et choisissez ULBRDialogueCameraRule. Nommez-le, par convention, BP_CameraRule_<Something>.

    Pick Parent Class filtered to camera rule

  2. Surchargez EvaluateScore (catégorie Evaluation dans My Blueprint ▸ Functions). Le graphe par défaut se contente de renvoyer le résultat du parent.

    The EvaluateScore override graph

  3. Décomposez le contexte. Ajoutez un nœud Break CameraRuleData sur Input Data pour exposer Dialogue, Line ID, Is Choice et Previous Cameras.

    Break CameraRuleData

  4. Traitez le cas vide. Si Previous Cameras Is Empty, il n'y a rien contre quoi alterner — Return 0.

  5. Lisez le cadrage précédent. Sinon, faites Get de l'index 0 de Previous Cameras, lisez son Shot Type, et Switch on ELBRShotType.

  6. Comparez avec la candidate. Pour les branches pertinentes, lisez le Shot Type de Camera To Test et faites de nouveau un switch :

    • le précédent était large/moyen et la candidate est un gros plan → Return 20 (récompenser le changement) ;
    • le précédent était large/moyen et la candidate est large/moyen → Return -20 (pénaliser la répétition) ;
    • symétriquement pour un gros plan précédent.
  7. Compilez.

  8. Câblez-la. Ouvrez votre DataTable de preset, et dans le tableau Project Camera Rules de la ligne cliquez sur + pour ajouter votre nouvelle règle. Régénérez le dialogue.

Dans le journal régénéré, votre règle contribue désormais +20 / -20 aux côtés du +10 de FocusedCharacter, et les caméras sélectionnées alternent le cadrage tout en continuant de pointer vers le bon locuteur — le poids final est simplement la somme du score de chaque règle.

Tip

Renvoyez 0 sans hésiter. Une règle qui ne se manifeste que dans les situations qui l'intéressent se compose proprement avec les autres ; une règle qui renvoie toujours une valeur non nulle peut étouffer FocusedCharacter et envoyer les plans hors du locuteur.

Comportement à l'exécution

Les règles s'exécutent au moment de la génération pour placer les coupes. À la lecture, Libretto se prémunit en plus contre le fait qu'une caméra choisie soit bloquée dans la scène réelle.

Repli sur occlusion

Lorsqu'une coupe de caméra de stage se joue, le dialogue manager vérifie si la caméra de coupe est occultée (ULBRDialogueManager::HandleStageCameraCut effectue un balayage d'occlusion via ALBRDialogueStageActor::CalculateCamerasCompValidation). Si la caméra sélectionnée est bloquée, il bascule vers une caméra sœur ayant le même focus dont la ligne de vue est dégagée, afin que le locuteur reste à l'écran.

Répliques du joueur et découpage caméra

La sélection de caméra construit ses données de plan à partir des seules répliques Text et Choice — les répliques Reply du joueur ne sont pas filmées comme des plans parlés, par conception. Pour donner au joueur ses propres plans à l'écran, sonorisez-le avec de vraies répliques Text (un motif de création courant) plutôt que de vous appuyer sur du texte de Reply.