Skip to content

Commit

Permalink
Use MonoPInvokeCallback attributes for callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
bgk- committed May 28, 2024
1 parent 37f3b53 commit 176f5ad
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 42 deletions.
1 change: 0 additions & 1 deletion Editor/ByteDataEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ private void OnEnable()
public override VisualElement CreateInspectorGUI()
{
var elem = new VisualElement();

var externsField = new PropertyField(_externsProperty);
externsField.SetEnabled(false);
elem.Add(externsField);
Expand Down
20 changes: 13 additions & 7 deletions Editor/TopiScriptedImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,24 @@ public override void OnImportAsset(AssetImportContext ctx)
return;
}
var log = Logger(ctx);
Library.OnDebugLogMessage += log;
try
{
var absPath = Application.dataPath + ctx.assetPath[6..];
var compiled = Dialogue.Compile(absPath);
var compiled = Dialogue.Compile(absPath, log);

using var memStream = new MemoryStream(compiled);
using var reader = new BinaryReader(memStream);
var boughs = ByteCode.GetBoughs(reader);
if (boughs.Length == 0) return;


// var boughs = ByteCode
var identifier = $"{fileName}b";
var compiledAsset = ScriptableObject.CreateInstance<ByteData>();
compiledAsset.name = identifier;
compiledAsset.bytes = compiled;

using var memStream = new MemoryStream(compiled);
using var reader = new BinaryReader(memStream);
reader.BaseStream.Position = 0;
compiledAsset.ExternsSet = ByteCode.GetExterns(reader);
ctx.AddObjectToAsset(identifier, compiledAsset, byteIcon);

Expand Down Expand Up @@ -70,12 +76,12 @@ public override void OnImportAsset(AssetImportContext ctx)
ctx.SetMainObject(asset);
}

Library.OnDebugLogMessage -= log;
}

private static Action<string, Library.Severity> Logger(AssetImportContext ctx) =>
(msg, severity) =>
private static Delegates.OutputLogDelegate Logger(AssetImportContext ctx) =>
(intPtr, severity) =>
{
var msg = Library.PtrToUtf8String(intPtr);
switch (severity)
{
case Library.Severity.Debug:
Expand Down
58 changes: 33 additions & 25 deletions Runtime/Conversation.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using AOT;
using PeartreeGames.Evt.Variables;
using UnityEngine;
using UnityEngine.AddressableAssets;
Expand All @@ -22,11 +23,13 @@ public class Conversation : MonoBehaviour

private TopiSpeaker _previousSpeaker;
private List<EvtTopiReference> _evtReferences;
public static event Action<Dialogue, Conversation> OnCreated;
public static event Action<Dialogue, Conversation> OnStart;
public static event Action<Dialogue, Conversation> OnEnd;
public static event Action<Dialogue, Line, TopiSpeaker> OnLine;
public static event Action<Dialogue, Choice[]> OnChoices;
public static Dictionary<string, TopiSpeaker> Speakers { get; } = new();
public static readonly Dictionary<string, TopiSpeaker> Speakers = new();
public static readonly Dictionary<IntPtr, Conversation> Conversations = new();
public static void AddSpeaker(TopiSpeaker speaker) => Speakers[speaker.name] = speaker;
public static void RemoveSpeaker(TopiSpeaker speaker) => Speakers.Remove(speaker.name);

Expand All @@ -50,32 +53,33 @@ private IEnumerator Start()
var ao = Addressables.LoadAssetAsync<ByteData>(file);
yield return ao;
_data = ao.Result;
Library.OnDebugLogMessage += Log;
Dialogue = new Dialogue(_data.bytes, OnLineCallback, OnChoicesCallback, logs);
if (!Dialogue.IsValid) Log("[Topiary.Unity] Could not create Dialogue ", Library.Severity.Error);
else Dialogue.BindFunctions(AppDomain.CurrentDomain.GetAssemblies());
Library.OnDebugLogMessage -= Log;
}
Dialogue = new Dialogue(_data.bytes, OnLineCallback, OnChoicesCallback, LogCallback, logs);
if (!Dialogue.IsValid)
{
Log("[Topiary.Unity] Could not create Dialogue ", Library.Severity.Error);
yield break;
}

[RuntimeInitializeOnLoadMethod]
private static void Init()
{
Library.IsUnityRuntime = true;
OnCreated?.Invoke(Dialogue, this);
Conversations.Add(Dialogue.VmPtr, this);
}

public void Log(string msg, Library.Severity severity)
[MonoPInvokeCallback(typeof(Delegates.OutputLogDelegate))]
public static void LogCallback(IntPtr intPtr, Library.Severity severity) => Log(Library.PtrToUtf8String(intPtr), severity);

public static void Log(string msg, Library.Severity severity)
{
switch (severity)
{
case Library.Severity.Debug:
case Library.Severity.Info:
Debug.Log($"{name}: {msg}", gameObject);
Debug.Log(msg);
break;
case Library.Severity.Warn:
Debug.LogWarning($"{name}: {msg}", gameObject);
Debug.LogWarning(msg);
break;
case Library.Severity.Error:
Debug.LogError($"{name}: {msg}", gameObject);
Debug.LogError(msg);
break;
default:
throw new ArgumentOutOfRangeException(nameof(severity), severity, null);
Expand All @@ -84,22 +88,28 @@ public void Log(string msg, Library.Severity severity)

private void OnDestroy()
{
Library.OnDebugLogMessage -= Log;
UnloadAddressableTopiValues();
Dialogue?.Dispose();
if (Dialogue != null)
{
Conversations?.Remove(Dialogue.VmPtr);
Dialogue?.Dispose();
}
if (file.IsValid()) file.ReleaseAsset();
}

private void OnLineCallback(Dialogue dialogue, Line line)
[MonoPInvokeCallback(typeof(Delegates.OnLineDelegate))]
private static void OnLineCallback(IntPtr vmPtr, Line line)
{
if (_previousSpeaker != null) _previousSpeaker.StopSpeaking();
var convo = Conversations[vmPtr];
if (convo._previousSpeaker != null) convo._previousSpeaker.StopSpeaking();
if (Speakers.TryGetValue(line.Speaker, out var speaker)) speaker.StartSpeaking();
_previousSpeaker = speaker;
OnLine?.Invoke(dialogue, line, speaker);
convo._previousSpeaker = speaker;
OnLine?.Invoke(Dialogue.Dialogues[vmPtr], line, speaker);
}

private void OnChoicesCallback(Dialogue dialogue, Choice[] choices) =>
OnChoices?.Invoke(dialogue, choices);
[MonoPInvokeCallback(typeof(Delegates.OnChoicesDelegate))]
private static void OnChoicesCallback(IntPtr vmPtr, IntPtr choicesPtr, byte count) =>
OnChoices?.Invoke(Dialogue.Dialogues[vmPtr], Choice.MarshalPtr(choicesPtr, count));

public void PlayDialogue()
{
Expand All @@ -114,7 +124,6 @@ public IEnumerator Play()
yield break;
}
Dialogue.Library.SetDebugSeverity(logs);
Library.OnDebugLogMessage += Log;
yield return StartCoroutine(LoadAddressableTopiValues());
State.Inject(Dialogue);
OnStart?.Invoke(Dialogue, this);
Expand Down Expand Up @@ -144,7 +153,6 @@ public IEnumerator Play()
_previousSpeaker = null;
OnEnd?.Invoke(Dialogue, this);
UnloadAddressableTopiValues();
Library.OnDebugLogMessage -= Log;
}


Expand Down
12 changes: 6 additions & 6 deletions Runtime/Evt/EvtTopiReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ public EvtTopiReference(Conversation conversation, EvtTopiVariable<T> evtVariabl
{
_evtVariable = evtVariable;
_evtVariable.OnEvt += OnValueChanged;
_conversation.Dialogue.Subscribe(_evtVariable.Name, OnTopiValueChanged);
_conversation.Dialogue.Subscribe(_evtVariable.Name);
}

public override void Dispose()
{
_evtVariable.OnEvt -= OnValueChanged;
_conversation.Dialogue.Unsubscribe(_evtVariable.Name, OnTopiValueChanged);
_conversation.Dialogue.Unsubscribe(_evtVariable.Name);
}

protected abstract void OnValueChanged(T value);
Expand Down Expand Up @@ -96,13 +96,13 @@ protected override void OnValueChanged(bool value)
{
var name = _evtVariable.Name;
var current = _conversation.Dialogue.GetValue(name);
if (current.tag != TopiValue.Tag.Number) return;
if (current.tag != TopiValue.Tag.Bool) return;
_conversation.Dialogue.Set(name, value);
}

protected override void OnTopiValueChanged(ref TopiValue topiValue)
{
if (topiValue.tag != TopiValue.Tag.Number) return;
if (topiValue.tag != TopiValue.Tag.Bool) return;
_evtVariable.Value = topiValue.Bool;
}
}
Expand All @@ -120,13 +120,13 @@ protected override void OnValueChanged(string value)
{
var name = _evtVariable.Name;
var current = _conversation.Dialogue.GetValue(name);
if (current.tag != TopiValue.Tag.Number) return;
if (current.tag != TopiValue.Tag.String) return;
_conversation.Dialogue.Set(name, value);
}

protected override void OnTopiValueChanged(ref TopiValue topiValue)
{
if (topiValue.tag != TopiValue.Tag.Number) return;
if (topiValue.tag != TopiValue.Tag.String) return;
_evtVariable.Value = topiValue.String;
}
}
Expand Down
3 changes: 0 additions & 3 deletions Runtime/State.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using Newtonsoft.Json.Linq;
using Sirenix.OdinInspector;
using UnityEngine;

namespace PeartreeGames.Topiary.Unity
{
public class State
{
private JObject _rootState;
[ShowInInspector, TextArea]
public string Value
{
get => _rootState?.ToString();
Expand Down
Binary file modified Topiary.CSharp.dll
Binary file not shown.
Binary file modified Topiary.CSharp.pdb
Binary file not shown.

0 comments on commit 176f5ad

Please sign in to comment.