Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Sqlite example #49

Merged
merged 3 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Samples/PausingTypewriter/PauseSample.tscn
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[gd_scene load_steps=7 format=3 uid="uid://ckp616grs7xrs"]

[ext_resource type="PackedScene" uid="uid://bv42g323prh5f" path="res://addons/YarnSpinner-Godot/Scenes/DefaultDialogueSystem.tscn" id="1_m0dlq"]
[ext_resource type="Resource" uid="uid://btil08na83k0p" path="res://Samples/PausingTypewriter/PauseProj.yarnproject" id="2_j3415"]
[ext_resource type="Resource" uid="uid://21gon4fidoq8" path="res://Samples/PausingTypewriter/PauseProj.yarnproject" id="2_j3415"]
[ext_resource type="Texture2D" uid="uid://crtrls05kcbu5" path="res://Samples/PausingTypewriter/sprites/talking.png" id="2_njmvd"]
[ext_resource type="Script" path="res://Samples/PausingTypewriter/PauseResponder.cs" id="3_uqanb"]
[ext_resource type="Texture2D" uid="uid://dk84dy4vqquds" path="res://Samples/PausingTypewriter/sprites/thinking.png" id="4_1i87u"]
Expand Down
36 changes: 36 additions & 0 deletions Samples/SQLiteVariableStorage/SQLSample.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=3 uid="uid://dt33g06nhtxn2"]

[ext_resource type="PackedScene" uid="uid://dqe5yshlcmnpg" path="res://addons/YarnSpinner-Godot/Scenes/RoundedDialogueSystem.tscn" id="1_8wwci"]
[ext_resource type="Resource" uid="uid://tsj53mnkwps3" path="res://Samples/SQLiteVariableStorage/SQLSample.yarnproject" id="2_73843"]
[ext_resource type="Script" path="res://Samples/SQLiteVariableStorage/SQLVariableStorage.cs" id="3_71oeg"]
[ext_resource type="Script" path="res://Samples/ReturnOnComplete.cs" id="4_lgfx4"]

[node name="SqlSample" type="Node2D"]

[node name="RoundedYarnSpinnerCanvasLayer" parent="." instance=ExtResource("1_8wwci")]

[node name="DialogueRunner" parent="RoundedYarnSpinnerCanvasLayer" index="0" node_paths=PackedStringArray("variableStorage")]
yarnProject = ExtResource("2_73843")
variableStorage = NodePath("../SQLVariableStorage")
startNode = "SqlSample"
startAutomatically = true

[node name="ColorRect" type="ColorRect" parent="RoundedYarnSpinnerCanvasLayer"]
z_index = -6
z_as_relative = false
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
color = Color(0.187867, 0.096, 0.2, 1)

[node name="SQLVariableStorage" type="Node2D" parent="RoundedYarnSpinnerCanvasLayer"]
script = ExtResource("3_71oeg")

[node name="ReturnOnComplete" type="Node2D" parent="." node_paths=PackedStringArray("dialogueRunner")]
script = ExtResource("4_lgfx4")
dialogueRunner = NodePath("../RoundedYarnSpinnerCanvasLayer/DialogueRunner")

[editable path="RoundedYarnSpinnerCanvasLayer"]
10 changes: 10 additions & 0 deletions Samples/SQLiteVariableStorage/SQLSample.yarnproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"projectFileVersion": 2,
"sourceFiles": [
"**/*.yarn"
],
"excludeFiles": [],
"localisation": {},
"baseLanguage": "en",
"compilerOptions": {}
}
14 changes: 14 additions & 0 deletions Samples/SQLiteVariableStorage/SQLSample.yarnproject.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[remap]

importer="yarnproject"
type="Resource"
uid="uid://tsj53mnkwps3"
path="res://.godot/imported/SQLSample.yarnproject-492bf8c35d4a0f0a8978692c27ea366f.tres"

[deps]

source_file="res://Samples/SQLiteVariableStorage/SQLSample.yarnproject"
dest_files=["res://.godot/imported/SQLSample.yarnproject-492bf8c35d4a0f0a8978692c27ea366f.tres"]

[params]

256 changes: 256 additions & 0 deletions Samples/SQLiteVariableStorage/SQLVariableStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
#nullable disable

using System;
using System.Collections.Generic;
using System.Linq;
using Godot;
using SQLite;
using YarnSpinnerGodot;

/// <summary>
/// SQLite based custom variable storage example.
/// </summary>
public partial class SQLVariableStorage : VariableStorageBehaviour
{
private SQLiteConnection db; // the database connector

public override void _EnterTree()
{
// pick a place on disk for the database to save to
string path = ProjectSettings.GlobalizePath("user://db.sqlite");
// create a new database connection to speak to it
db = new SQLiteConnection(path);
// create the tables we need
db.CreateTable<YarnString>();
db.CreateTable<YarnFloat>();
db.CreateTable<YarnBool>();
GD.Print($"Initialized database at {path}");
}

public override bool TryGetValue<T>(string variableName, out T result)
{
string query = "";
List<object> results = new();
if (typeof(T) == typeof(IConvertible))
{
// we don't know the expected type
if (TryGetValue<string>(variableName, out string stringResult))
{
result = (T) (object) stringResult;
return true;
}

if (TryGetValue<float>(variableName, out float floatResult))
{
result = (T) (object) floatResult;
return true;
}

if (TryGetValue<bool>(variableName, out bool boolResult))
{
result = (T) (object) boolResult;
return true;
}

result = default(T);
return false;
}

if (typeof(T) == typeof(string))
{
query = "SELECT * FROM YarnString WHERE key = ?";
results.AddRange(db.Query<YarnString>(query, variableName));
}
else if (typeof(T) == typeof(bool))
{
query = "SELECT * FROM YarnBool WHERE key = ?";
results.AddRange(db.Query<YarnBool>(query, variableName));
}
else if (typeof(T) == typeof(float))
{
query = "SELECT * FROM YarnFloat WHERE key = ?";
results.AddRange(db.Query<YarnFloat>(query, variableName));
}

// if a result was found, convert it to type T and assign it
if (results?.Count > 0)
{
if (results[0] is YarnFloat f)
{
result = (T) (object) f.value;
}
else if (results[0] is YarnBool b)
{
result = (T) (object) b.value;
}
else if (results[0] is YarnString s)
{
result = (T) (object) s.value;
}
else
{
throw new ArgumentException($"Unknown variable type {typeof(T)}");
}

return true;
}

// otherwise TryGetValue has failed
result = default(T);
return false;
}

public override void SetValue(string variableName, string stringValue)
{
// check it doesn't exist already in other table
if (Exists(variableName, typeof(bool)))
{
throw new ArgumentException($"{variableName} is a bool.");
}

if (Exists(variableName, typeof(float)))
{
throw new ArgumentException($"{variableName} is a float.");
}

// if not, insert or update row in this table to the given value
string query = "INSERT OR REPLACE INTO YarnString (key, value)";
query += "VALUES (?, ?)";
db.Execute(query, variableName, stringValue);
}

public override void SetValue(string variableName, float floatValue)
{
// check it doesn't exist already in other table
if (Exists(variableName, typeof(string)))
{
throw new ArgumentException($"{variableName} is a string.");
}

if (Exists(variableName, typeof(bool)))
{
throw new ArgumentException($"{variableName} is a bool.");
}

// if not, insert or update row in this table to the given value
string query = "INSERT OR REPLACE INTO YarnFloat (key, value)";
query += "VALUES (?, ?)";
db.Execute(query, variableName, floatValue);
}

public override void SetValue(string variableName, bool boolValue)
{
// check it doesn't exist already in other table
if (Exists(variableName, typeof(string)))
{
throw new ArgumentException($"{variableName} is a string.");
}

if (Exists(variableName, typeof(float)))
{
throw new ArgumentException($"{variableName} is a float.");
}

// if not, insert or update row in this table to the given value
string query = "INSERT OR REPLACE INTO YarnBool (key, value)";
query += "VALUES (?, ?)";
db.Execute(query, variableName, boolValue);
}

public override void Clear()
{
db.Execute("DELETE * FROM YarnString;");
db.Execute("DELETE * FROM YarnBool;");
db.Execute("DELETE * FROM YarnFloat;");
}

public override bool Contains(string variableName)
{
return Exists(variableName, typeof(string)) ||
Exists(variableName, typeof(bool)) ||
Exists(variableName, typeof(float));
}

public override void SetAllVariables(Dictionary<string, float> floats, Dictionary<string, string> strings,
Dictionary<string, bool> bools, bool clear = true)
{
foreach (var entry in floats)
{
SetValue(entry.Key, entry.Value);
}

foreach (var entry in bools)
{
SetValue(entry.Key, entry.Value);
}

foreach (var entry in strings)
{
SetValue(entry.Key, entry.Value);
}
}

public override (Dictionary<string, float>, Dictionary<string, string>, Dictionary<string, bool>) GetAllVariables()
{
var floatQuery = "SELECT value FROM YarnFloat";
var floats = db.Query<YarnFloat>(floatQuery)
.AsEnumerable()
.ToDictionary(f => f.key, f => f.value);
var stringQuery = "SELECT value FROM YarnString";
var strings = db.Query<YarnString>(stringQuery)
.AsEnumerable()
.ToDictionary(f => f.key, f => f.value);
var boolQuery = "SELECT value FROM YarnBool";
var booleans = db.Query<YarnBool>(boolQuery)
.AsEnumerable()
.ToDictionary(f => f.key, f => f.value);

return (floats, strings, booleans);
}

private bool Exists(string variableName, Type type)
{
if (type == typeof(string))
{
string stringResult;
if (TryGetValue(variableName, out stringResult))
{
return (stringResult != null);
}
}
else if (type == typeof(bool))
{
if (TryGetValue(variableName, out bool _))
{
return true;
}
}
else if (type == typeof(float))
{
if (TryGetValue(variableName, out float _))
{
return true;
}
}

return false;
}
}

public class YarnString
{
[PrimaryKey] public string key { get; set; }
public string value { get; set; }
}

public class YarnFloat
{
[PrimaryKey] public string key { get; set; }
public float value { get; set; }
}

public class YarnBool
{
[PrimaryKey] public string key { get; set; }
public bool value { get; set; }
}
41 changes: 41 additions & 0 deletions Samples/SQLiteVariableStorage/SqlSample.yarn
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
title: SqlSample
tags:
---
<<declare $characterName = "" as string>>
<<declare $numVariables = 0>>
<<declare $impressed = false as bool>>
Guide: Alright, I've been waiting for my last applicant of the day.
Guide: Hmm, how do you say your name!? It says "S-Q-L".
-> Eskew-well
<<set $characterName to "Eskew-well">>
-> Seekwill
<<set $characterName to "Seekwill">>
{$characterName}: My name is {$characterName}.
{$characterName}: I have trained for one thousand years to store the most variables of all time.
Guide: Wow. Impressive! Just how many variables do you think you could store??
-> There's no limit.
<<set $numVariables to -1>>
Guide: Wh- what? Unlimited??
Guide: Gahhh!!!
The guide ran away.
<<stop>>
-> Sixty two thousand.
<<set $numVariables to 62000>>
Guide: Formidable... imagine the heights you could reach under our guidance.
<<set $impressed to true>>
-> One thousand.
<<set $numVariables to 1000>>
Guide: Hmm. That's not bad.
<<set $impressed to true>>
-> Three.
<<set $numVariables to 3>>
Guide: I ...see.
<<set $impressed to false>>

Guide: Alright then, {$characterName}. You can store {$numVariables} variables...
<<if $impressed>>
Guide: Welcome to Variable Academy.
<<else>>
Guide: I'm afraid you're not cut out for Variable Academy.
<<endif>>
===
14 changes: 14 additions & 0 deletions Samples/SQLiteVariableStorage/SqlSample.yarn.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[remap]

importer="yarnscript"
type="Resource"
uid="uid://mno2y7y3atrn"
path="res://.godot/imported/SqlSample.yarn-1a034971b5ef626e0730aa486cf1cdf1.tres"

[deps]

source_file="res://Samples/SQLiteVariableStorage/SqlSample.yarn"
dest_files=["res://.godot/imported/SqlSample.yarn-1a034971b5ef626e0730aa486cf1cdf1.tres"]

[params]

Loading
Loading