using UnityEngine; using Yarn.Unity; namespace Ichni.Story.YarnFunctions { /// /// 立绘控制相关的 Yarn 自定义命令静态注册器。 /// /// 全局静态命令,不依赖于 GameObject 的挂载。所有方法都使用强类型的参数, /// 以更明确、简洁的指令名称区分不同应用场景,从而抛弃复杂的内部字符串解析判断。 /// /// public static class PortraitCommands { // ── Yarn Commands ──────────────────────────────────────────────────────── /// /// 最基础、最全面的立绘指令:设置指定角色的坐标和表情。 /// 若角色不在台上,会自动以指定的表情和位置实例化。 /// 格式: <<set_portrait characterId x y [emotion]>> /// /// 角色标识 ID。 /// 归一化 X 坐标 [-100, 100] /// 归一化 Y 坐标 [-100, 100] /// 表情名称。如果不填,默认保持不变或初始化为 "normal" [YarnCommand("set_portrait")] public static void SetPortrait(string characterId, float x, float y, string emotion = null) { if (!EnsureStage()) return; // 传入归一化坐标,由 VNPortraitStage 内部自动应用 positionOffset 并转换为像素坐标 Vector2 normalizedPos = new Vector2(x, y); Dialogue.VNPortraitStage.Instance.SetPortraitPosition(characterId, normalizedPos, emotion); } /// /// 设置当前说话角色的坐标和表情。 /// 格式: <<set_portrait_current x y [emotion]>> /// [YarnCommand("set_portrait_current")] public static void SetPortraitCurrent(float x, float y, string emotion = null) { if (!EnsureStage()) return; string characterId = Dialogue.VNPortraitStage.Instance.CurrentSpeakerId; if (string.IsNullOrEmpty(characterId)) { Debug.LogWarning("[PortraitCommands] set_portrait_current: 当前没有活动的说话者,无法执行此命令!"); return; } SetPortrait(characterId, x, y, emotion); } /// /// 仅设置或移动指定角色的坐标(不改变当前表情)。 /// 格式: <<set_portrait_position characterId x y>> /// [YarnCommand("set_portrait_position")] public static void SetPortraitPosition(string characterId, float x, float y) { // 通过传入 emotion = null,VNPortraitStage 在更新时将保持角色原有表情 SetPortrait(characterId, x, y, null); } /// /// 仅改变指定角色的表情(角色必须已经上台)。 /// 格式: <<set_portrait_emotion characterId emotion>> /// [YarnCommand("set_portrait_emotion")] public static void SetPortraitEmotion(string characterId, string emotion) { if (!EnsureStage()) return; Dialogue.VNPortraitStage.Instance.SetPortraitEmotion(characterId, emotion); } /// /// 隐藏指定角色的立绘。 /// 格式: <<hide_portrait characterId>> /// [YarnCommand("hide_portrait")] public static void HidePortrait(string characterId) { if (!EnsureStage()) return; Dialogue.VNPortraitStage.Instance.HidePortrait(characterId); } /// /// 隐藏当前所有在台上的立绘。 /// 格式: <<hide_all_portraits>> /// [YarnCommand("hide_all_portraits")] public static void HideAllPortraits() { if (!EnsureStage()) return; Dialogue.VNPortraitStage.Instance.HideAll(); } // ── 内部辅助 ───────────────────────────────────────────────────────────── private static bool EnsureStage() { if (Dialogue.VNPortraitStage.Instance != null) return true; Debug.LogError("[PortraitCommands] 未找到 VNPortraitStage 实例!请确保在当前场景中存在挂载了 VNPortraitStage 的游戏物体。"); return false; } } }