Created
January 29, 2023 22:10
-
-
Save valkyrienyanko/b1355f108a05791b3acca5b1fd71e871 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.VisualBasic; | |
namespace CatCafe; | |
public class Dialogue | |
{ | |
public string Name { get; set; } | |
public string Text { get; set; } | |
public List<Choice> Choices { get; set; } | |
} | |
public class Choice | |
{ | |
public string Text { get; set; } | |
public List<Dialogue> Dialogues { get; set; } | |
} | |
public partial class UIDialogue : Control | |
{ | |
private Dictionary<string, List<Dialogue>> Conversations { get; set; } = new() | |
{ | |
{ "fairy_encounter_1", new List<Dialogue> | |
{ | |
new Dialogue | |
{ | |
Name = "Minnie", | |
Text = "Who are you?" | |
}, | |
new Dialogue | |
{ | |
Name = "Fairy", | |
Text = "A fairy of course! Would you like to see something cool?", | |
Choices = new List<Choice> | |
{ | |
{ | |
new Choice | |
{ | |
Text = "Yes", | |
Dialogues = new List<Dialogue> | |
{ | |
new Dialogue | |
{ | |
Name = "Fairy", | |
Text = "*fairy does a back flip*" | |
}, | |
new Dialogue | |
{ | |
Name = "Fairy", | |
Text = "*fairy laughs*" | |
} | |
} | |
} }, | |
{ | |
new Choice | |
{ | |
Text = "No", | |
Dialogues = new List<Dialogue> | |
{ | |
new Dialogue | |
{ | |
Name = "Fairy", | |
Text = "Aw okay.." | |
} | |
} | |
} | |
} | |
} | |
}, | |
{ | |
new Dialogue | |
{ | |
Name = "Fairy", | |
Text = "Okay well good bye!" | |
} | |
} | |
} } | |
}; | |
private string CurConversation { get; set; } = "fairy_encounter_1"; | |
private int CurDialogIndex { get; set; } | |
private int CurDialogWithChoicesIndex { get; set; } | |
private List<Dialogue> CurDialogues { get; set; } | |
// Anything lower than 2 is way too slow even for crazy plot dialogues | |
[Export(PropertyHint.Range, "2, 100")] public double TextSpeed { get; set; } = 40.0; | |
[Export] public NodePath NodePathActorName { get; set; } | |
[Export] public NodePath NodePathActorDialogue { get; set; } | |
[Export] public NodePath NodePathPanelName { get; set; } | |
[Export] public NodePath NodePathPanelBack { get; set; } | |
[Export] public NodePath NodePathPanelDialogue { get; set; } | |
[Export] public NodePath NodePathSectionChoices { get; set; } | |
private Sprite2D ActorPortrait { get; set; } | |
private Label ActorName { get; set; } | |
private Label ActorDialogue { get; set; } | |
private Control PanelName { get; set; } | |
private Control PanelBack { get; set; } | |
private Control PanelDialogue { get; set; } | |
private Control SectionChoices { get; set; } | |
private GridContainer[] ChoiceRows { get; set; } = new GridContainer[2]; | |
private Button[] BtnChoices { get; set; } = new Button[4]; | |
private Vector2 PanelDialogueSize { get; set; } | |
private Vector2 PanelBackPosition { get; set; } | |
private Vector2 ActorPortraitStartingPos { get; set; } | |
private Tween TweenPanel { get; set; } | |
private Tween TweenText { get; set; } | |
public override void _Ready() | |
{ | |
ActorPortrait = GetNode<Sprite2D>("Portrait"); | |
ActorName = GetNode<Label> (NodePathActorName); | |
ActorDialogue = GetNode<Label> (NodePathActorDialogue); | |
PanelName = GetNode<Control> (NodePathPanelName); | |
PanelBack = GetNode<Control> (NodePathPanelBack); | |
PanelDialogue = GetNode<Control> (NodePathPanelDialogue); | |
SectionChoices = GetNode<Control> (NodePathSectionChoices); | |
ChoiceRows[0] = SectionChoices.GetNode<GridContainer>("Row1"); | |
ChoiceRows[1] = SectionChoices.GetNode<GridContainer>("Row2"); | |
BtnChoices[0] = ChoiceRows[0].GetNode<Button>("Choice1"); | |
BtnChoices[1] = ChoiceRows[0].GetNode<Button>("Choice2"); | |
BtnChoices[2] = ChoiceRows[1].GetNode<Button>("Choice3"); | |
BtnChoices[3] = ChoiceRows[1].GetNode<Button>("Choice4"); | |
// Dialogue text should not make the panel grow above, only downwards | |
PanelDialogue.GrowVertical = GrowDirection.End; | |
// Get panel dialogue size and panel back position before setting the scale of panel dialogue to zero | |
PanelDialogueSize = PanelDialogue.GetRect().Size; | |
PanelBackPosition = PanelBack.GlobalPosition; | |
PanelDialogue.Scale = Vector2.Zero; | |
ActorPortraitStartingPos = ActorPortrait.GlobalPosition; | |
// Initially hide the dialogue panel | |
Destroy(); | |
} | |
public override void _PhysicsProcess(double delta) | |
{ | |
var portraitPos = ActorPortrait.GlobalPosition; | |
portraitPos.Y = PanelBack.GlobalPosition.Y - ActorPortrait.GetRect().Size.Y; | |
ActorPortrait.GlobalPosition = ActorPortrait.GlobalPosition.Lerp(portraitPos, 0.05f); | |
} | |
public override void _Input(InputEvent @event) | |
{ | |
if (Input.IsActionJustPressed("player_skip_dialogue")) | |
{ | |
var firstDialogue = false; | |
if (!Visible) | |
{ | |
firstDialogue = true; | |
Reveal(); | |
// Prepare dialogue for first time | |
CurDialogues = new List<Dialogue>(); | |
foreach (var diag in Conversations[CurConversation]) | |
CurDialogues.Add(new Dialogue | |
{ | |
Name = diag.Name, | |
Text = diag.Text | |
}); | |
GD.Print(CurDialogues.PrintFull()); | |
} | |
NextDialogue(firstDialogue); | |
} | |
} | |
public void NextDialogue(bool firstDialogue) | |
{ | |
// Hide the choices before each new dialogue is shown | |
HideChoices(); | |
// Get the current conversation | |
var conversation = Conversations[CurConversation]; | |
// Are we at the end of the conversation? | |
if (CurDialogIndex >= conversation.Count) | |
{ | |
// Close all the dialogue UIs | |
CurDialogIndex = 0; | |
CurDialogWithChoicesIndex = 0; | |
Destroy(); | |
return; | |
} | |
// Get the current dialog in the conversation | |
var dialog = CurDialogues[CurDialogIndex++]; | |
// Display the dialogue | |
Text(dialog.Name, dialog.Text, firstDialogue ? 0.5 : 0); | |
var dialogWithMaybeChoices = conversation[CurDialogWithChoicesIndex++]; | |
// Are there choices to this dialogue? | |
if (dialogWithMaybeChoices.Choices == null) | |
return; | |
// There are choices, lets show them | |
SectionChoices.Show(); | |
// Showing all choices that were defined | |
for (int i = 0; i < BtnChoices.Length; i++) | |
if (dialogWithMaybeChoices.Choices.ElementAtOrDefault(i) != default(Choice)) | |
{ | |
var btn = BtnChoices[i]; | |
var choice = dialogWithMaybeChoices.Choices[i]; | |
btn.Show(); | |
btn.Text = choice.Text; // Show the text for each choice | |
// Lets do something when we click on a choice | |
void onPressed() | |
{ | |
// Unsubscribe as soon as we click on a choice to prepare it for later | |
btn.Pressed -= onPressed; | |
var dialogues = choice.Dialogues; | |
// Does this choice lead to additional dialogues? | |
if (dialogues != null) | |
{ | |
} | |
} | |
btn.Pressed += onPressed; | |
} | |
} | |
private void HideChoices() | |
{ | |
SectionChoices.Hide(); | |
for (int i = 0; i < BtnChoices.Length; i++) | |
BtnChoices[i].Hide(); | |
} | |
private void Reveal() | |
{ | |
SetPhysicsProcess(true); | |
Show(); | |
// ensure no other tween for panel is running | |
TweenPanel?.Kill(); | |
AnimatePanel(); | |
} | |
private void Text(string name, string dialogue, double delay = 0) | |
{ | |
// ensure no other tween for text is running | |
TweenText?.Kill(); | |
ActorName.Text = name; | |
ActorDialogue.Text = dialogue; | |
ActorDialogue.VisibleRatio = 0; | |
AnimateText(delay); | |
} | |
public void Destroy() | |
{ | |
// exit animation for dialogue panel | |
TweenPanel = GetTree().CreateTween(); | |
TweenPanel.TweenProperty(PanelDialogue, "scale", Vector2.Zero, 0.4); | |
// stop setting the NPC portrait position | |
SetPhysicsProcess(false); | |
// exit animation for NPC portrait | |
var tween = GetTree().CreateTween(); | |
tween.TweenProperty(ActorPortrait, "position:y", ActorPortraitStartingPos.Y, 0.4); | |
tween.TweenCallback(Callable.From(() => Hide())); | |
} | |
private void AnimatePanel() | |
{ | |
PanelDialogue.PivotOffset = PanelDialogueSize / 2; | |
TweenPanel = GetTree().CreateTween(); | |
TweenPanel.TweenProperty(PanelDialogue, "scale", Vector2.One, 0.5) | |
.From(Vector2.Zero) | |
.SetTrans(Tween.TransitionType.Quad) | |
.SetEase(Tween.EaseType.InOut); | |
} | |
private void AnimateText(double delay) | |
{ | |
// allow 1 second for every 'TextSpeed' characters of text | |
var duration = ActorDialogue.Text.Length / TextSpeed; | |
TweenText = GetTree().CreateTween(); | |
TweenText.TweenProperty(ActorDialogue, "visible_ratio", 1, duration) | |
.SetDelay(delay) | |
.From(0.0); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment