private void PresentNewFrame(Frame f) { //special handling for blank frames if (f is BlankFrame) { CurrentFrameObject = f; OnChoiceButtonClick(0); return; } //present music if (!string.IsNullOrEmpty(f.Music)) { if (!(AudioPlayer.Instance.IsMusicSetToPlay(MusicSlot.Cinematic) && AudioPlayer.Instance.GetMusicName(MusicSlot.Cinematic) == f.Music)) { AudioPlayer.Instance.SetMusic(f.Music, MusicSlot.Cinematic, 1.0f, true, false); AudioPlayer.Instance.StartMusic(MusicSlot.Cinematic); } } else { AudioPlayer.Instance.ClearMusic(MusicSlot.Cinematic); } //present audio if (VoiceAudioSource.isPlaying) { VoiceAudioSource.Stop(); } var voiceClip = CCBase.GetModule <AudioModule>().GetSound($"{CurrentSceneName}/{CurrentFrameName}", SoundType.Voice); //GetModule<T> is now preferred if (voiceClip != null) { VoiceAudioSource.clip = voiceClip; VoiceAudioSource.Play(); } //present background BackgroundImage.sprite = null; BackgroundImage.gameObject.SetActive(false); if (!string.IsNullOrEmpty(f.Background)) { var sprite = CoreUtils.LoadResource <Sprite>("Dialogue/bg/" + f.Background); if (sprite != null) { BackgroundImage.sprite = sprite; BackgroundImage.gameObject.SetActive(true); } else { CDebug.LogEx($"Couldn't find face sprite Dialogue/bg/{f.Background}", LogLevel.Verbose, this); } } //present image FaceImage.sprite = null; FaceImage.gameObject.SetActive(false); if (!string.IsNullOrEmpty(f.Image)) { //attempt to present image var sprite = CoreUtils.LoadResource <Sprite>("Dialogue/char/" + f.Image); if (sprite != null) { //Debug.Log(sprite.name); float spriteX = sprite.texture.width * (100f / sprite.pixelsPerUnit); float spriteY = sprite.texture.height * (100f / sprite.pixelsPerUnit); switch (f.ImagePosition) { case FrameImagePosition.Fill: FaceImage.rectTransform.localPosition = Vector3.zero; FaceImage.rectTransform.sizeDelta = FaceImage.canvas.pixelRect.size; break; case FrameImagePosition.Character: FaceImage.rectTransform.localPosition = new Vector3(0, 100, 0); FaceImage.rectTransform.sizeDelta = new Vector2(spriteX, spriteY); break; default: //center, no scale FaceImage.rectTransform.localPosition = Vector3.zero; FaceImage.rectTransform.sizeDelta = new Vector2(spriteX, spriteY); break; } FaceImage.sprite = sprite; FaceImage.gameObject.SetActive(true); } else { CDebug.LogEx($"Couldn't find face sprite Dialogue/char/{f.Image}", LogLevel.Verbose, this); } } //present camera try { if (!string.IsNullOrEmpty(f.CameraDirection) && !f.CameraDirection.StartsWith("Default", StringComparison.OrdinalIgnoreCase)) { if (CameraController == null) { var cameraGo = Instantiate(CameraPrefab, CoreUtils.GetWorldRoot()); CameraController = cameraGo.GetComponent <DialogueCameraController>(); } CameraController.Activate(f.CameraDirection); } else { CameraController.Ref()?.Deactivate(); } } catch (Exception e) { Debug.LogError($"Failed to point camera ({f.CameraDirection})"); Debug.LogException(e); } //present text TextTitle.text = Sub.Macro(f.NameText); TextMain.text = Sub.Macro(f.Text); //clear buttons foreach (Transform t in ScrollChoiceContent) { Destroy(t.gameObject); } ScrollChoiceContent.DetachChildren(); //present buttons if (f is ChoiceFrame) { ScrollChoice.gameObject.SetActive(true); ButtonContinue.gameObject.SetActive(false); ChoiceFrame cf = (ChoiceFrame)f; for (int i = 0; i < cf.Choices.Length; i++) { ChoiceNode cn = cf.Choices[i]; string prependText = string.Empty; bool showChoice = true; bool lockChoice = false; if (cn.ShowCondition != null) { showChoice = cn.ShowCondition.Evaluate(); } if (cn.HideCondition != null && showChoice) { showChoice = !cn.HideCondition.Evaluate(); } //skill checks if (cn.SkillCheck != null) { bool isPossible = cn.SkillCheck.CheckIfPossible(); if (!GameParams.ShowImpossibleSkillChecks && !isPossible) { showChoice = false; } if (!GameParams.AttemptImpossibleSkillChecks && !isPossible) { lockChoice = true; } string passValue = cn.SkillCheck.CheckType == SkillCheckType.Soft ? $"{(int)(cn.SkillCheck.GetApproximatePassChance() * 100)}%" : cn.SkillCheck.Value.ToString(); prependText = $"[{Sub.Replace(cn.SkillCheck.Target, "IGUI_AV")} {passValue}] "; } if (showChoice) { GameObject choiceGO = Instantiate <GameObject>(ButtonPrefab, ScrollChoiceContent); Button b = choiceGO.GetComponent <Button>(); b.interactable = !lockChoice; b.gameObject.SetActive(true); b.transform.Find("Text").GetComponent <Text>().text = prependText + Sub.Macro(cn.Text); int idx = i; b.onClick.AddListener(delegate { OnChoiceButtonClick(idx); }); } } } else // if(f is TextFrame) { ScrollChoice.gameObject.SetActive(false); string nextText = string.IsNullOrEmpty(f.NextText) ? Sub.Replace("DefaultNextText", "IGUI_DIALOGUE", false) : f.NextText; Button b = ButtonContinue; b.gameObject.SetActive(true); b.transform.Find("Text").GetComponent <Text>().text = nextText; } CurrentFrameObject = f; }
private void PresentNewFrame(Frame f) { TryCallScript(f?.Scripts?.BeforePresent, f); //special handling for blank frames if (f is BlankFrame) { CurrentFrameObject = f; ScriptingModule.CallNamedHooked("DialogueOnPresent", this, CurrentFrameObject); TryCallScript(f?.Scripts?.OnPresent, f); OnChoiceButtonClick(0); return; } //create trace node var traceNode = new DialogueTraceNode(); traceNode.Path = $"{CurrentSceneName}.{CurrentFrameName}"; //present music if (!string.IsNullOrEmpty(f.Music)) { if (!(AudioPlayer.Instance.IsMusicSetToPlay(MusicSlot.Cinematic) && AudioPlayer.Instance.GetMusicName(MusicSlot.Cinematic) == f.Music)) { AudioPlayer.Instance.SetMusic(f.Music, MusicSlot.Cinematic, 1.0f, true, false); AudioPlayer.Instance.StartMusic(MusicSlot.Cinematic); } } else if (f.Music != null) //null = no change, empty = no music { AudioPlayer.Instance.ClearMusic(MusicSlot.Cinematic); } //present audio string voiceClipName = $"{CurrentSceneName}/{CurrentFrameName}"; string voiceClipNameOverride = f.Options.VoiceOverride; if (!string.IsNullOrEmpty(voiceClipNameOverride)) { if (voiceClipNameOverride.StartsWith("/")) { voiceClipName = voiceClipNameOverride.TrimStart('/'); } else { voiceClipName = $"{CurrentSceneName}/{voiceClipNameOverride}"; } } if (VoiceAudioSource.isPlaying) { VoiceAudioSource.Stop(); } var voiceClip = CCBase.GetModule <AudioModule>().GetSound(voiceClipName, SoundType.Voice, !GameParams.DialogueVerboseLogging); //GetModule<T> is now preferred if (voiceClip != null) { VoiceAudioSource.clip = voiceClip; VoiceAudioSource.volume = f.Options.VoiceVolume ?? 1f; VoiceAudioSource.Play(); } //present background BackgroundImage.sprite = null; BackgroundImage.gameObject.SetActive(false); if (!string.IsNullOrEmpty(f.Background)) { var sprite = CoreUtils.LoadResource <Sprite>("Dialogue/bg/" + f.Background); if (sprite != null) { BackgroundImage.sprite = sprite; BackgroundImage.gameObject.SetActive(true); } else { if (GameParams.DialogueVerboseLogging) { CDebug.LogEx($"Couldn't find face sprite Dialogue/bg/{f.Background}", LogLevel.Verbose, this); } } } //size panel float faceYOffset = 0; var framePanelHeight = f.Options.PanelHeight; var panelHeight = framePanelHeight == ChoicePanelHeight.Default ? GameParams.DialoguePanelHeight : framePanelHeight; switch (panelHeight) { case ChoicePanelHeight.Half: if (!Mathf.Approximately(ChoicePanel.rect.height, DefaultPanelHeight / 2f)) { ChoicePanel.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, DefaultPanelHeight / 2f); } faceYOffset = -(DefaultPanelHeight / 2f); break; case ChoicePanelHeight.Variable: CDebug.LogEx($"{nameof(ChoicePanelHeight)} {ChoicePanelHeight.Variable} is not supported!", LogLevel.Warning, this); break; case ChoicePanelHeight.Fixed: ChoicePanel.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, f.Options.PanelHeightPixels); faceYOffset = -(DefaultPanelHeight - f.Options.PanelHeightPixels); break; default: if (!Mathf.Approximately(ChoicePanel.rect.height, DefaultPanelHeight)) { ChoicePanel.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, DefaultPanelHeight); //correct? } break; } //show/hide name text if (f.Options.HideNameText) { NameTextPanel.gameObject.SetActive(false); } else { NameTextPanel.gameObject.SetActive(true); } //present image FaceImage.sprite = null; FaceImage.gameObject.SetActive(false); if (!string.IsNullOrEmpty(f.Image)) { //attempt to present image var sprite = CoreUtils.LoadResource <Sprite>("Dialogue/char/" + f.Image); if (sprite != null) { //Debug.Log(sprite.name); Vector2 canvasSize = ((RectTransform)FaceImage.canvas.transform).rect.size; float spriteX = sprite.texture.width * (100f / sprite.pixelsPerUnit); float spriteY = sprite.texture.height * (100f / sprite.pixelsPerUnit); switch (f.ImagePosition) { case FrameImagePosition.Fill: //works FaceImage.rectTransform.localPosition = Vector3.zero; FaceImage.rectTransform.sizeDelta = canvasSize; break; case FrameImagePosition.Contain: //works { FaceImage.rectTransform.localPosition = Vector3.zero; float imageRatio = (float)sprite.texture.width / (float)sprite.texture.height; //force float division! float rectRatio = canvasSize.x / canvasSize.y; if (imageRatio > rectRatio) //image is wider than rect { FaceImage.rectTransform.sizeDelta = new Vector2(canvasSize.x, canvasSize.x / imageRatio); } else //image is narrower than rect { FaceImage.rectTransform.sizeDelta = new Vector2(canvasSize.y * imageRatio, canvasSize.y); } } break; case FrameImagePosition.Cover: //works { FaceImage.rectTransform.localPosition = Vector3.zero; float imageRatio = (float)sprite.texture.width / (float)sprite.texture.height; float rectRatio = canvasSize.x / canvasSize.y; if (imageRatio > rectRatio) //image is wider than rect { FaceImage.rectTransform.sizeDelta = new Vector2(canvasSize.y * imageRatio, canvasSize.y); } else //image is narrower than rect { FaceImage.rectTransform.sizeDelta = new Vector2(canvasSize.x, canvasSize.x / imageRatio); } } break; case FrameImagePosition.Character: //works FaceImage.rectTransform.localPosition = new Vector3(0, faceYOffset + (GameParams.DialogueDrawPortraitHigh ? 140 : 100), 0); FaceImage.rectTransform.sizeDelta = new Vector2(spriteX, spriteY); break; case FrameImagePosition.CharacterBottom: //works { float yPos = (-(canvasSize.y / 2f)) + (spriteY / 2f); //I think we want SpriteY and not pixels directly FaceImage.rectTransform.localPosition = new Vector3(0, yPos, 0); FaceImage.rectTransform.sizeDelta = new Vector2(spriteX, spriteY); } break; case FrameImagePosition.Battler: //deliberately broken CDebug.LogEx($"FrameImagePosition {f.ImagePosition} is not supported!", LogLevel.Warning, this); FaceImage.rectTransform.localPosition = Vector3.zero; FaceImage.rectTransform.sizeDelta = new Vector2(spriteX, spriteY); break; default: //works FaceImage.rectTransform.localPosition = Vector3.zero; FaceImage.rectTransform.sizeDelta = new Vector2(spriteX, spriteY);; break; } FaceImage.sprite = sprite; FaceImage.gameObject.SetActive(true); } else { if (GameParams.DialogueVerboseLogging) { CDebug.LogEx($"Couldn't find face sprite Dialogue/char/{f.Image}", LogLevel.Verbose, this); } } } //present camera try { if (!string.IsNullOrEmpty(f.CameraDirection) && !f.CameraDirection.StartsWith("Default", StringComparison.OrdinalIgnoreCase)) { if (CameraController == null) { var cameraGo = Instantiate(CameraPrefab, CoreUtils.GetWorldRoot()); CameraController = cameraGo.GetComponent <DialogueCameraController>(); } CameraController.Activate(f.CameraDirection); } else { CameraController.Ref()?.Deactivate(); } } catch (Exception e) { Debug.LogError($"Failed to point camera ({f.CameraDirection})"); Debug.LogException(e); } //present hidden objects var objectsToHide = f.Options.HideObjects; if (objectsToHide != null) { var hiddenObjectsToShow = HiddenObjects.Except(objectsToHide); UnhideObjects(hiddenObjectsToShow); var newObjectsToHide = objectsToHide.Except(HiddenObjects); HideObjects(newObjectsToHide); HiddenObjects.Clear(); HiddenObjects.UnionWith(objectsToHide); } else { UnhideAllObjects(); } //present text string nameText = Sub.Macro(f.NameText); TextTitle.text = nameText; string mainText = Sub.Macro(f.Text); TextMain.text = mainText; //save text to trace (note use of null instead of null-or-empty) traceNode.Speaker = (f.Options.TraceSpeaker == null) ? (string.IsNullOrEmpty(nameText) ? GetDefaultTraceSpeaker(f) : nameText) : Sub.Macro(f.Options.TraceSpeaker); traceNode.Text = (f.Options.TraceText == null) ? mainText : Sub.Macro(f.Options.TraceText); //clear buttons Navigator.ClearButtons(); foreach (Transform t in ScrollChoiceContent) { Destroy(t.gameObject); } ScrollChoiceContent.DetachChildren(); ButtonAlternateContinue.gameObject.SetActive(false); //present buttons and frame if (f is ChoiceFrame choiceFrame) { ChoicePanel.gameObject.SetActive(true); ScrollChoice.gameObject.SetActive(true); ButtonContinue.gameObject.SetActive(false); //ChoiceFrame cf = (ChoiceFrame)f; var buttons = new List <Button>(); for (int i = 0; i < choiceFrame.Choices.Length; i++) { ChoiceNode cn = choiceFrame.Choices[i]; string prependText = string.Empty; bool showChoice = true; bool lockChoice = false; if (cn.ShowCondition != null) { showChoice = cn.ShowCondition.Evaluate(); } if (cn.HideCondition != null && showChoice) { showChoice = !cn.HideCondition.Evaluate(); } //skill checks if (cn.SkillCheck != null) { bool isPossible = cn.SkillCheck.CheckIfPossible(); if (!GameParams.ShowImpossibleSkillChecks && !isPossible) { showChoice = false; } if (!GameParams.AttemptImpossibleSkillChecks && !isPossible) { lockChoice = true; } string passValue = cn.SkillCheck.CheckType == SkillCheckType.Soft ? $"{(int)(cn.SkillCheck.GetApproximatePassChance() * 100)}%" : cn.SkillCheck.Value.ToString(); prependText = $"[{Sub.Replace(cn.SkillCheck.Target, "RPG_AV")} {passValue}] "; } if (showChoice) { GameObject choiceGO = Instantiate <GameObject>(ButtonPrefab, ScrollChoiceContent); Button b = choiceGO.GetComponent <Button>(); b.interactable = !lockChoice; b.gameObject.SetActive(true); b.transform.Find("Text").GetComponent <Text>().text = prependText + Sub.Macro(cn.Text); int idx = i; b.onClick.AddListener(delegate { OnChoiceButtonClick(idx); }); buttons.Add(b); } } Navigator.AttachButtons(buttons); } else if (f is ImageFrame imageFrame) { string nextText = string.IsNullOrEmpty(f.NextText) ? Sub.Replace("DefaultNextText", "IGUI_DIALOGUE", false) : f.NextText; if (imageFrame.AllowSkip) { ChoicePanel.gameObject.SetActive(false); ScrollChoice.gameObject.SetActive(false); Button b = ButtonAlternateContinue; b.gameObject.SetActive(true); b.transform.Find("Text").GetComponent <Text>().text = nextText; Navigator.AttachButtons(new Button[] { b }); } else { ChoicePanel.gameObject.SetActive(false); ButtonAlternateContinue.gameObject.SetActive(false); } if (imageFrame.HideSkip) { CDebug.LogEx("Image frame HideSkip is deprecated and not implemented (use AllowSkip=false instead)", LogLevel.Warning, this); } if (imageFrame.UseTimer) { StartWaitAndAdvance(imageFrame.TimeToShow); } } else if (f is TextFrame textFrame) { ChoicePanel.gameObject.SetActive(true); ScrollChoice.gameObject.SetActive(false); string nextText = string.IsNullOrEmpty(f.NextText) ? Sub.Replace("DefaultNextText", "IGUI_DIALOGUE", false) : f.NextText; Button b = ButtonContinue; b.gameObject.SetActive(textFrame.AllowSkip); b.transform.Find("Text").GetComponent <Text>().text = nextText; Navigator.AttachButtons(new Button[] { b }); if (textFrame.UseTimer) { StartWaitAndAdvance(textFrame.TimeToShow); } } else { throw new NotImplementedException($"Frame type {f.GetType().Name} is not supported"); } //apply theme ApplyThemeToPanel(); CurrentFrameObject = f; ScriptingModule.CallNamedHooked("DialogueOnPresent", this, CurrentFrameObject); TryCallScript(f?.Scripts?.OnPresent, f); if (f.Options.TraceIgnore) { traceNode.Ignored = true; } Trace.Nodes.Add(traceNode); }