// /////////////////////////////////////////////////////////////////////////// / // Copyright © 2019-2022 Frédéric Maquin // Licensed under the MIT License. // See LICENSE in the project root for license information. // /////////////////////////////////////////////////////////////////////////// / using Godot; using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; public partial class InkBridger : Node { #region Imports private readonly GDScript InkPath = (GDScript) ResourceLoader.Load("res://addons/inkgd/runtime/ink_path.gd"); private readonly GDScript InkList = (GDScript) ResourceLoader.Load("res://addons/inkgd/runtime/lists/ink_list.gd"); private readonly GDScript InkListDefinition = (GDScript) ResourceLoader.Load("res://addons/inkgd/runtime/lists/list_definition.gd"); private readonly GDScript InkListItem = (GDScript) ResourceLoader.Load("res://addons/inkgd/runtime/lists/structs/ink_list_item.gd"); private readonly GDScript InkFunctionResult = (GDScript) ResourceLoader.Load("res://addons/inkgd/runtime/extra/function_result.gd"); #endregion #region Methods | Helpers public bool IsInkObjectOfType(Godot.Object inkObject, string name) { return inkObject.HasMethod("is_ink_class") && (bool)inkObject.Call("is_ink_class", new object[] { name }); } public Godot.Object MakeFunctionResult(string textOutput, object returnValue) { var parameters = new object[] { textOutput ?? "", returnValue }; return (Godot.Object) InkFunctionResult.New(parameters); } #endregion #region Methods | Conversion -> (GDScript -> C#) public Godot.Object MakeGDInkPath(Ink.Runtime.Path3D path) { var inkPath = (Godot.Object) InkPath.New(); inkPath.Call("_init_with_components_string", path.componentsString); return inkPath; } public Godot.Object MakeGDInkList(Ink.Runtime.InkList list) { var inkListBase = new Godot.Collections.Dictionary(); foreach(KeyValuePair kv in list) { inkListBase.Add(MakeGDInkListItem(kv.Key).Call("serialized") as string, kv.Value); } object[] inkListParams = new object[] { inkListBase, list.originNames.ToArray(), MakeGDInkListOrigins(list.origins) }; var inkList = (Godot.Object) InkList.New(); inkList.Call("_init_from_csharp", inkListParams); return inkList; } public Ink.Runtime.Path3D MakeSharpInkPath(Godot.Object path) { if (!IsInkObjectOfType(path, "InkPath")) { throw new ArgumentException("Expected a 'Godot.Object' of class 'InkPath'"); } return new Ink.Runtime.Path3D((string)path.Get("components_string")); } #endregion #region Methods | Conversion (GDScript -> C#) public Ink.Runtime.InkList MakeSharpInkList(Godot.Object list, Ink.Runtime.Story story) { if (!IsInkObjectOfType(list, "InkList")) { throw new ArgumentException("Expected a 'Godot.Object' of class 'InkList'"); } var underlyingDictionary = new Godot.Collections.Dictionary( (Godot.Collections.Dictionary)list.Get("_dictionary")); var originNames = new Godot.Collections.Array( (Godot.Collections.Array)list.Get("origin_names")); var inkList = new Ink.Runtime.InkList(); inkList.origins = new List(); inkList.SetInitialOriginNames(originNames.ToList()); foreach(string originName in originNames) { if (story.listDefinitions.TryListGetDefinition (originName, out Ink.Runtime.ListDefinition definition)) { if (!inkList.origins.Contains(definition)) { inkList.origins.Add(definition); } } else { throw new Exception ( $"InkList origin could not be found in story when reconstructing list: {originName}" ); } } foreach(KeyValuePair kv in underlyingDictionary) { inkList[MakeSharpInkListItem(kv.Key)] = kv.Value; } return inkList; } #endregion #region Private Methods | Conversion (C# -> GDScript) private Godot.Collections.Array MakeGDInkListOrigins( List listDefinitions) { var inkListDefinitions = new Godot.Collections.Array(); foreach(Ink.Runtime.ListDefinition listDefinition in listDefinitions) { var inkListDefinition = MakeGDListDefinition(listDefinition); inkListDefinitions.Add(inkListDefinition); } return inkListDefinitions; } private Godot.Object MakeGDListDefinition(Ink.Runtime.ListDefinition listDefinition) { var items = new Godot.Collections.Dictionary(); foreach(KeyValuePair kv in listDefinition.items) { var inkListItem = MakeGDInkListItem(kv.Key); items.Add(inkListItem, kv.Value); } var definitionParams = new object[] { listDefinition.name, items }; var inkListDefinition = (Godot.Object) InkListDefinition.New(definitionParams); return inkListDefinition; } private Godot.Object MakeGDInkListItem(Ink.Runtime.InkListItem listItem) { object[] itemParams = new object[] { listItem.fullName }; var inkListItem = (Godot.Object) InkListItem.New(); inkListItem.Call("_init_with_full_name", itemParams); return inkListItem; } #endregion #region Private Methods | Conversion (GDScript -> C#) private Ink.Runtime.InkListItem MakeSharpInkListItem(string listItemKey) { var listItem = (Godot.Object) InkListItem.Call("from_serialized_key", new object[] { listItemKey }); if (!IsInkObjectOfType(listItem, "InkListItem")) { throw new ArgumentException("Expected a 'Godot.Object' of class 'InkListItem'"); } return new Ink.Runtime.InkListItem( listItem.Get("origin_name") as string, listItem.Get("item_name") as string ); } #endregion }