Skip to content

Commit

Permalink
[KK] Updated icon APIs to allow removing
Browse files Browse the repository at this point in the history
  • Loading branch information
ManlyMarco committed Apr 6, 2021
1 parent 6c20119 commit 33297a7
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 17 deletions.
4 changes: 2 additions & 2 deletions doc/KKAPI.MainGame.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ Static Methods

| Type | Name | Summary |
| --- | --- | --- |
| `void` | AddActionIcon(`Int32` mapNo, `Vector3` position, `Sprite` iconOn, `Sprite` iconOff, `Action` onOpen, `Action<TriggerEnterExitEvent>` onCreated = null) | Register a new action icon in roaming mode (like the icons for training/studying, club report screen, peeping). Icon templates can be found here https://github.com/IllusionMods/IllusionModdingAPI/tree/master/src/KKAPI/MainGame/ActionIcons |
| `void` | AddTouchIcon(`Sprite` icon, `Action<Button>` onCreated, `Int32` row = 1, `Int32` order = 0) | Register a new touch icon in talk scenes in roaming mode (like the touch and look buttons on top right when talking to a character). Icon templates can be found here https://github.com/IllusionMods/IllusionModdingAPI/tree/master/src/KKAPI/MainGame/TouchIcons By default this functions as a simple button. If you want to turn this into a toggle you have to manually switch button.image.sprite as needed. |
| `IDisposable` | AddActionIcon(`Int32` mapNo, `Vector3` position, `Sprite` iconOn, `Sprite` iconOff, `Action` onOpen, `Action<TriggerEnterExitEvent>` onCreated = null, `Boolean` delayed = True, `Boolean` immediate = False) | Register a new action icon in roaming mode (like the icons for training/studying, club report screen, peeping). Dispose the return value to remove the icon. Icon templates can be found here https://github.com/IllusionMods/IllusionModdingAPI/tree/master/src/KKAPI/MainGame/ActionIcons |
| `IDisposable` | AddTouchIcon(`Sprite` icon, `Action<Button>` onCreated, `Int32` row = 1, `Int32` order = 0) | Register a new touch icon in talk scenes in roaming mode (like the touch and look buttons on top right when talking to a character). Dispose the return value to remove the icon. Icon templates can be found here https://github.com/IllusionMods/IllusionModdingAPI/tree/master/src/KKAPI/MainGame/TouchIcons By default this functions as a simple button. If you want to turn this into a toggle you have to manually switch button.image.sprite as needed. |
| `IEnumerable<GameCustomFunctionController>` | GetBehaviours() | Get all registered behaviours for the game. |
| `GameCustomFunctionController` | GetRegisteredBehaviour(`String` extendedDataId) | Get the first controller that was registered with the specified extendedDataId. |
| `GameCustomFunctionController` | GetRegisteredBehaviour(`Type` controllerType) | Get the first controller that was registered with the specified extendedDataId. |
Expand Down
35 changes: 29 additions & 6 deletions src/KKAPI/MainGame/ActionIcons/CustomActionIcon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ private sealed class ActionIconEntry
public readonly Action OnOpen;
public readonly Action<TriggerEnterExitEvent> OnCreated;

public Object Instance;

public ActionIconEntry(int mapNo, Vector3 position, Sprite iconOn, Sprite iconOff, Action onOpen, Action<TriggerEnterExitEvent> onCreated)
{
IconOff = iconOff;
Expand All @@ -31,11 +33,16 @@ public ActionIconEntry(int mapNo, Vector3 position, Sprite iconOn, Sprite iconOf
MapNo = mapNo;
Position = position;
}

public void Dispose()
{
Object.Destroy(Instance);
}
}

private static readonly List<ActionIconEntry> _entries = new List<ActionIconEntry>();

public static void AddActionIcon(int mapNo, Vector3 position, Sprite iconOn, Sprite iconOff, Action onOpen, Action<TriggerEnterExitEvent> onCreated = null)
public static IDisposable AddActionIcon(int mapNo, Vector3 position, Sprite iconOn, Sprite iconOff, Action onOpen, Action<TriggerEnterExitEvent> onCreated = null, bool delayed = true, bool immediate = false)
{
if (iconOn == null) throw new ArgumentNullException(nameof(iconOn));
if (iconOff == null) throw new ArgumentNullException(nameof(iconOff));
Expand All @@ -45,7 +52,18 @@ public static void AddActionIcon(int mapNo, Vector3 position, Sprite iconOn, Spr
Object.DontDestroyOnLoad(iconOff);

var entry = new ActionIconEntry(mapNo, position, iconOn, iconOff, onOpen, onCreated);
_entries.Add(entry);

if (delayed)
_entries.Add(entry);

if (immediate && Game.IsInstance() && Game.Instance.actScene != null && mapNo == Game.Instance.actScene.Player?.mapNo)
SpawnActionPoint(entry, 100);

return Disposable.Create(() =>
{
_entries.Remove(entry);
entry.Dispose();
});
}

[HarmonyPostfix]
Expand All @@ -62,7 +80,7 @@ private static void OnMapChangedHook(ActionMap __instance)
{
try
{
SpawnActionPoint(iconEntry);
SpawnActionPoint(iconEntry, created);
created++;
}
catch (Exception e)
Expand All @@ -76,9 +94,10 @@ private static void OnMapChangedHook(ActionMap __instance)
KoikatuAPI.Logger.LogDebug($"Created {created} custom action points on map no {__instance.no}");
}

private static void SpawnActionPoint(ActionIconEntry iconEntry)
private static void SpawnActionPoint(ActionIconEntry iconEntry, int created)
{
var inst = CommonLib.LoadAsset<GameObject>("map/playeractionpoint/00.unity3d", "PlayerActionPoint_05", true);
inst.gameObject.name = "CustomActionPoint_" + created;
var parent = GameObject.Find("Map/ActionPoints");
inst.transform.SetParent(parent.transform, true);

Expand All @@ -93,6 +112,7 @@ private static void SpawnActionPoint(ActionIconEntry iconEntry)
var animator = iconRootObject.GetComponentInChildren<Animator>();
var rendererIcon = iconRootObject.GetComponentInChildren<SpriteRenderer>();
rendererIcon.sprite = iconEntry.IconOff;
rendererIcon.flipX = true; // Needed to fix images being flipped
var playerInRange = false;
evt.onTriggerEnter += c =>
{
Expand All @@ -111,12 +131,13 @@ private static void SpawnActionPoint(ActionIconEntry iconEntry)
c.GetComponent<Player>().actionPointList.Remove(evt);
};

var player = Singleton<Game>.Instance.actScene.Player;
var game = Singleton<Game>.Instance;
var player = game.actScene.Player;
evt.UpdateAsObservable()
.Subscribe(_ =>
{
// Hide in H scenes and other places
var isVisible = Singleton<Game>.IsInstance() && !Singleton<Game>.Instance.IsRegulate(true);
var isVisible = !game.IsRegulate(true) && !game.actScene.isEventNow;
if (rendererIcon.enabled != isVisible)
rendererIcon.enabled = isVisible;
Expand All @@ -126,6 +147,8 @@ private static void SpawnActionPoint(ActionIconEntry iconEntry)
})
.AddTo(evt);

iconEntry.Instance = inst;

iconEntry.OnCreated?.Invoke(evt);
}
}
Expand Down
24 changes: 18 additions & 6 deletions src/KKAPI/MainGame/GameApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using HarmonyLib;
using Illusion.Component;
using KKAPI.Studio;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.SceneManagement;
Expand Down Expand Up @@ -117,6 +118,7 @@ public static void RegisterExtraBehaviour<T>(string extendedDataId) where T : Ga

/// <summary>
/// Register a new action icon in roaming mode (like the icons for training/studying, club report screen, peeping).
/// Dispose the return value to remove the icon.
/// Icon templates can be found here https://github.com/IllusionMods/IllusionModdingAPI/tree/master/src/KKAPI/MainGame/ActionIcons
/// </summary>
/// <param name="mapNo">Identification number of the map the icon should be spawned on</param>
Expand All @@ -128,14 +130,24 @@ public static void RegisterExtraBehaviour<T>(string extendedDataId) where T : Ga
/// to enable mouse cursor and hide the action icon to prevent it from being clicked again.).</param>
/// <param name="onCreated">Optional action to run after the icon is created.
/// Use to attach extra code to the icon, e.g. by using <see cref="ObservableTriggerExtensions.UpdateAsObservable(Component)"/> and similar methods.</param>
public static void AddActionIcon(int mapNo, Vector3 position, Sprite iconOn, Sprite iconOff, Action onOpen, Action<TriggerEnterExitEvent> onCreated = null)
/// <param name="delayed">Should the icon be spawned every time the map is entered</param>
/// <param name="immediate">Should the icon be spawned immediately if the player is on the correct map</param>
public static IDisposable AddActionIcon(int mapNo, Vector3 position, Sprite iconOn, Sprite iconOff, Action onOpen, Action<TriggerEnterExitEvent> onCreated = null, bool delayed = true, bool immediate = false)
{
if (StudioAPI.InsideStudio) return;
CustomActionIcon.AddActionIcon(mapNo, position, iconOn, iconOff, onOpen, onCreated);
if (StudioAPI.InsideStudio) return Disposable.Empty;
return CustomActionIcon.AddActionIcon(mapNo, position, iconOn, iconOff, onOpen, onCreated, delayed, immediate);
}

/// <inheritdoc cref="AddActionIcon(int,Vector3,Sprite,Sprite,Action,Action{TriggerEnterExitEvent},bool,bool)"/>
[Obsolete]
public static void AddActionIcon(int mapNo, Vector3 position, Sprite iconOn, Sprite iconOff, Action onOpen, Action<TriggerEnterExitEvent> onCreated)
{
AddActionIcon(mapNo, position, iconOn, iconOff, onOpen, onCreated, true, false);
}

/// <summary>
/// Register a new touch icon in talk scenes in roaming mode (like the touch and look buttons on top right when talking to a character).
/// Dispose the return value to remove the icon.
/// Icon templates can be found here https://github.com/IllusionMods/IllusionModdingAPI/tree/master/src/KKAPI/MainGame/TouchIcons
/// By default this functions as a simple button. If you want to turn this into a toggle you have to manually switch button.image.sprite as needed.
/// </summary>
Expand All @@ -144,10 +156,10 @@ public static void AddActionIcon(int mapNo, Vector3 position, Sprite iconOn, Spr
/// Use to subscribe to the onClick event and/or attach extra code to the button, e.g. by using <see cref="ObservableTriggerExtensions.UpdateAsObservable(Component)"/> and similar methods.</param>
/// <param name="row">Row of the button, counted from top at 0. Buttons are added from right to left. Row has to be between 0 and 5, but 0 to 2 are recommended.</param>
/// <param name="order">Order of the buttons in a row. Lower value is placed more to the right. By default order of adding the icons is used.</param>
public static void AddTouchIcon(Sprite icon, Action<Button> onCreated, int row = 1, int order = 0)
public static IDisposable AddTouchIcon(Sprite icon, Action<Button> onCreated, int row = 1, int order = 0)
{
if (StudioAPI.InsideStudio) return;
CustomTalkSceneTouchIcon.AddTouchIcon(icon, onCreated, row, order);
if (StudioAPI.InsideStudio) return Disposable.Empty;
return CustomTalkSceneTouchIcon.AddTouchIcon(icon, onCreated, row, order);
}

internal static void Init(bool insideStudio)
Expand Down
20 changes: 17 additions & 3 deletions src/KKAPI/MainGame/TouchIcons/CustomTalkSceneTouchIcon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using HarmonyLib;
using KKAPI.Utilities;
using UniRx;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
Expand All @@ -17,6 +18,7 @@ private sealed class TouchIconEntry
public readonly int Row;
public readonly int Order;
public readonly Action<Button> OnCreated;
internal Object Instance;

public TouchIconEntry(Sprite icon, Action<Button> onCreated, int row, int order)
{
Expand All @@ -25,19 +27,31 @@ public TouchIconEntry(Sprite icon, Action<Button> onCreated, int row, int order)
Row = row;
Order = order;
}

public void Dispose()
{
Object.Destroy(Instance);
}
}

private static readonly List<TouchIconEntry> _buttons = new List<TouchIconEntry>();

public static void AddTouchIcon(Sprite icon, Action<Button> onCreated, int row = 1, int order = 0)
public static IDisposable AddTouchIcon(Sprite icon, Action<Button> onCreated, int row = 1, int order = 0)
{
if (icon == null) throw new ArgumentNullException(nameof(icon));
if (onCreated == null) throw new ArgumentNullException(nameof(onCreated));
if (row < 0 || row > 5) throw new ArgumentOutOfRangeException(nameof(row), "row should be either 0, 1 or 2. It can't be below 0 or higher than 5");

Object.DontDestroyOnLoad(icon);

_buttons.Add(new TouchIconEntry(icon, onCreated, row, order));
var entry = new TouchIconEntry(icon, onCreated, row, order);
_buttons.Add(entry);

return Disposable.Create(() =>
{
_buttons.Remove(entry);
entry.Dispose();
});
}

[HarmonyPostfix]
Expand All @@ -60,7 +74,6 @@ private static void AwakePost(Button[] ___buttonTouch)
foreach (var entry in entryRow.OrderBy(x => x.Order).ThenBy(x => _buttons.IndexOf(x)))
{
var copy = Object.Instantiate(sourceTransform.gameObject, sourceTransform.parent, false);

copy.transform.localPosition = lastPosition + new Vector3(change, 0, 0);
lastPosition = copy.transform.localPosition;

Expand All @@ -69,6 +82,7 @@ private static void AwakePost(Button[] ___buttonTouch)

btn.image.sprite = entry.Icon;

entry.Instance = copy;
entry.OnCreated(btn);
}
}
Expand Down

0 comments on commit 33297a7

Please sign in to comment.