Skip to content

Instantly share code, notes, and snippets.

@BigHandInSky
Created February 7, 2021 12:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BigHandInSky/e8ee87e179b1a48adf791272f62922de to your computer and use it in GitHub Desktop.
Save BigHandInSky/e8ee87e179b1a48adf791272f62922de to your computer and use it in GitHub Desktop.
An editor field to quickly pick Ink knots from inside a given sub-folder in Assets
using System;
namespace _project.utilities
{
/// <summary>
/// Struct that is used for an editor GUI to simplify picking an ink knot from the Assets folder
/// </summary>
[Serializable]
public struct StoryKnot
{
public string name;
public StoryKnot( string n ) => name = n;
public bool IsValid => !string.IsNullOrEmpty( name );
}
}
using System.Collections.Generic;
using System.IO;
using _project.utilities;
using UnityEditor;
using UnityEngine;
namespace _project
{
[CustomPropertyDrawer( typeof(StoryKnot) )]
public class StoryKnotDrawer : PropertyDrawer
{
private static Dictionary<string, List<string>> _fileToKnotsLookup = new Dictionary<string, List<string>>();
private string _selectedName = "";
public override void OnGUI(
Rect position,
SerializedProperty property,
GUIContent label )
{
label = EditorGUI.BeginProperty( position, label, property );
Rect contentPosition = EditorGUI.PrefixLabel(position, label);
EditorGUI.BeginChangeCheck();
var nameProperty = property.FindPropertyRelative( "name" );
var buttonLabel = string.IsNullOrEmpty( nameProperty.stringValue )
? "Pick knot name"
: nameProperty.stringValue;
if ( EditorGUI.DropdownButton( contentPosition, new GUIContent( buttonLabel ),
FocusType.Passive ) )
{
if ( _fileToKnotsLookup.Count == 0 )
{
FetchKnots();
}
ConstructThenShowMenu();
}
if ( !string.IsNullOrEmpty( _selectedName ) )
{
nameProperty.stringValue = _selectedName;
_selectedName = "";
}
EditorGUI.EndChangeCheck();
EditorGUI.EndProperty();
}
public override float GetPropertyHeight( SerializedProperty property, GUIContent label )
{
return EditorGUIUtility.singleLineHeight;
}
#region Menu
private void FetchKnots()
{
_fileToKnotsLookup.Clear();
var folderPath = "Assets/_content/writing";
var guids = AssetDatabase.FindAssets( "", new []{ folderPath } );
foreach ( var guid in guids )
{
var path = AssetDatabase.GUIDToAssetPath( guid );
if ( path.EndsWith( ".ink" ) )
{
var splits = path.Split( '/' );
var knots = LoadInkThenParse( path );
var reduced = path.Remove( 0, folderPath.Length + 1 );
//Debug.Log( $"path? {path}" );
//Debug.Log( $" reduced: {reduced}, split: {splits[splits.Length - 1]}" );
//Debug.Log( $"knots: [{string.Join( ",", knots )}]" );
_fileToKnotsLookup.Add( reduced, knots );
}
// ignore .jsons
}
}
private List<string> LoadInkThenParse( string path )
{
List<string> value = new List<string>();
using ( var reader = File.OpenText( path ) )
{
var line = "";
while ( !reader.EndOfStream )
{
line = reader.ReadLine();
if ( line.StartsWith( "==" ) )
{
line = line.Replace( "==", "" );
line = line.Trim();
value.Add( line );
}
}
}
return value;
}
private void ConstructThenShowMenu()
{
GenericMenu menu = new GenericMenu();
foreach ( var pair in _fileToKnotsLookup )
{
string root = pair.Key;
foreach ( var s in pair.Value )
{
AddMenuItemForKnot( menu, $"{root}/{s}", s );
}
}
menu.ShowAsContext();
}
void AddMenuItemForKnot(GenericMenu menu, string menuPath, string knot)
{
menu.AddItem(new GUIContent(menuPath), _selectedName.Equals(knot), OnStringSelected, knot);
}
void OnStringSelected(object knot)
{
_selectedName = (string)knot;
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment