Compare commits

..

1 Commits

Author SHA1 Message Date
540d6444a6 Merge branch 'main' of https://git.bibko.uk/Pasha/Pacore 2026-01-24 20:00:19 +00:00
48 changed files with 261 additions and 549 deletions

View File

@@ -1,40 +0,0 @@
name: Create Unity package from repo
on:
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g. 1.0.0)'
required: true
jobs:
build-package:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Unity package folder
run: |
mkdir -p package
rsync -av --exclude='*.meta' Assets/Pacore/ package/
- name: Create tarball
run: |
VERSION=${{ github.event.inputs.version }}
PACKAGE_NAME="com.pashabibko.pacore-${VERSION}.tgz"
tar -czf "$PACKAGE_NAME" package
ls -1h "$PACKAGE_NAME"
- name: Create Github Release
uses: ncipollo/release-action@v1
with:
tag: ${{ github.event.inputs.version }}
name: Release ${{ github.event.inputs.version }}
body: "Automated release of Pacore package"
artifacts: "com.pashabibko.pacore-${{ github.event.inputs.version }}.tgz"
draft: false
prerelease: false
token: ${{ secrets.GITHUB_TOKEN }}

3
.gitignore vendored
View File

@@ -22,9 +22,8 @@
# Uncomment this line if you wish to ignore the asset store tools plugin # Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools* # /[Aa]ssets/AssetStoreTools*
# Rider files # Autogenerated Jetbrains Rider plugin
/[Aa]ssets/Plugins/Editor/JetBrains* /[Aa]ssets/Plugins/Editor/JetBrains*
/.idea/
# Visual Studio cache directory # Visual Studio cache directory
.vs/ .vs/

15
.idea/.idea.Pacore/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,15 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/contentModel.xml
/.idea.Pacore.iml
/modules.xml
/projectSettingsUpdater.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

4
.idea/.idea.Pacore/.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

6
.idea/.idea.Pacore/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -1,3 +0,0 @@
# Files are generated/modified at runtime and do not need backing up #
Resources.meta
Resources

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 9eace838af5041fd9d8cb05c8fbf9ef4
timeCreated: 1769349074

View File

@@ -1,58 +0,0 @@
using PashaBibko.Pacore.Attributes;
using System.Collections.Generic;
using System.Reflection;
using System;
namespace PashaBibko.Pacore.Editor.Caches
{
public static class InspectorCallableCache
{
public struct AttributeInfo
{
public InspectorCallableAttribute Attribute;
public MethodInfo AttachedMethod;
}
private const BindingFlags BINDING_FLAGS =
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance;
private static Dictionary<Type, AttributeInfo[]> Cache { get; } = new();
public static AttributeInfo[] GetAllAttributesOfType(Type type)
{
/* Checks the cache for the type */
if (Cache.TryGetValue(type, out AttributeInfo[] attributes))
{
return attributes;
}
/* Finds all the functions with the attribute */
MethodInfo[] methods = type.GetMethods(BINDING_FLAGS);
List<AttributeInfo> buttons = new();
foreach (MethodInfo method in methods)
{
InspectorCallableAttribute attribute
= method.GetCustomAttribute<InspectorCallableAttribute>();
if (attribute != null)
{
AttributeInfo info = new()
{
Attribute = attribute,
AttachedMethod = method,
};
buttons.Add(info);
}
}
/* Adds it to the cache before returning */
AttributeInfo[] array = buttons.ToArray();
Cache.Add(type, array);
return array;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 2574e8cf9f6b45dbb4aa22f0e62b23df
timeCreated: 1769349096

View File

@@ -1,34 +0,0 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System;
namespace PashaBibko.Pacore.Editor.Caches
{
public static class MonoScriptCache
{
private static Dictionary<string, MonoScript> Cache { get; } = new();
static MonoScriptCache()
{
/* Finds all MonoScripts and adds them to the dictionary by name */
MonoScript[] scripts = Resources.FindObjectsOfTypeAll<MonoScript>();
foreach (MonoScript script in scripts)
{
Type scriptType = script.GetClass();
if (scriptType is not null)
{
string name = scriptType.FullName;
Cache.TryAdd(name, script);
}
}
}
public static MonoScript Get(string name)
{
/* Fetches the value (if there is one) without creating a default val */
Cache.TryGetValue(name, out MonoScript script);
return script;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 96c81b83f299432fbf183bc40b69c061
timeCreated: 1769349335

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9a1f5463ef6a4249af45548d72f211c6
timeCreated: 1769189971

View File

@@ -0,0 +1,11 @@
using UnityEngine;
using System;
namespace PashaBibko.Pacore.Editor.Drawers
{
public sealed class DisabledGUIBlock : IDisposable
{
public DisabledGUIBlock() => GUI.enabled = false;
public void Dispose() => GUI.enabled = true;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3d8664e5ad044a248710d9b31044d2fc
timeCreated: 1769189984

View File

@@ -11,12 +11,11 @@ namespace PashaBibko.Pacore.Editor.Drawers
{ {
if (attribute is InspectorReadOnlyAttribute readOnlyAttribute) if (attribute is InspectorReadOnlyAttribute readOnlyAttribute)
{ {
GUI.enabled = false; using (new DisabledGUIBlock())
{
label.text = readOnlyAttribute.Name ?? label.text; // Uses custom name if it exists label.text = readOnlyAttribute.Name ?? label.text; // Uses custom name if it exists
EditorGUI.PropertyField(position, property, label); EditorGUI.PropertyField(position, property, label);
}
GUI.enabled = true;
} }
} }
} }

View File

@@ -1,11 +1,62 @@
using PashaBibko.Pacore.Editor.Caches; using System;
using System.Collections.Generic;
using System.Reflection;
using PashaBibko.Pacore.Attributes;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using System;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace PashaBibko.Pacore.Editor.Drawers namespace PashaBibko.Pacore.Editor.Drawers
{ {
public static class InspectorCallableAttributeCache
{
public struct AttributeInfo
{
public InspectorCallableAttribute Attribute;
public MethodInfo AttachedMethod;
}
private const BindingFlags BINDING_FLAGS =
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance;
private static Dictionary<Type, AttributeInfo[]> Cache { get; } = new();
public static AttributeInfo[] GetAllAttributes(Type type)
{
/* Checks the cache for the type */
if (Cache.TryGetValue(type, out AttributeInfo[] attributes))
{
return attributes;
}
/* Finds all the functions with the attribute */
MethodInfo[] methods = type.GetMethods(BINDING_FLAGS);
List<AttributeInfo> buttons = new();
foreach (MethodInfo method in methods)
{
InspectorCallableAttribute attribute = method.GetCustomAttribute<InspectorCallableAttribute>();
if (attribute != null)
{
AttributeInfo info = new()
{
Attribute = attribute,
AttachedMethod = method,
};
buttons.Add(info);
}
}
/* Adds it to the cache before returning */
AttributeInfo[] array = buttons.ToArray();
Cache.Add(type, array);
return array;
}
}
[CustomEditor(typeof(MonoBehaviour), editorForChildClasses: true)] [CustomEditor(typeof(MonoBehaviour), editorForChildClasses: true)]
public class MonoBehaviourDrawer : UnityEditor.Editor public class MonoBehaviourDrawer : UnityEditor.Editor
{ {
@@ -18,8 +69,8 @@ namespace PashaBibko.Pacore.Editor.Drawers
public static void DrawFunctionButtons(Object target) public static void DrawFunctionButtons(Object target)
{ {
Type type = target.GetType(); Type type = target.GetType();
InspectorCallableCache.AttributeInfo[] buttons InspectorCallableAttributeCache.AttributeInfo[] buttons
= InspectorCallableCache.GetAllAttributesOfType(type); = InspectorCallableAttributeCache.GetAllAttributes(type);
if (buttons.Length == 0) if (buttons.Length == 0)
{ {
@@ -29,7 +80,7 @@ namespace PashaBibko.Pacore.Editor.Drawers
EditorGUILayout.Space(); EditorGUILayout.Space();
EditorGUILayout.LabelField("Functions", EditorStyles.boldLabel); EditorGUILayout.LabelField("Functions", EditorStyles.boldLabel);
foreach (InspectorCallableCache.AttributeInfo button in buttons) foreach (InspectorCallableAttributeCache.AttributeInfo button in buttons)
{ {
string name = button.Attribute.ButtonName; string name = button.Attribute.ButtonName;
if (GUILayout.Button(name)) if (GUILayout.Button(name))

View File

@@ -1,11 +1,38 @@
using PashaBibko.Pacore.Editor.Caches; using PashaBibko.Pacore.Attributes;
using PashaBibko.Pacore.Attributes; using System.Collections.Generic;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using System; using System;
namespace PashaBibko.Pacore.Editor.Drawers namespace PashaBibko.Pacore.Editor.Drawers
{ {
public static class MonoScriptCache
{
private static Dictionary<string, MonoScript> Cache { get; } = new();
static MonoScriptCache()
{
/* Finds all MonoScripts and adds them to the dictionary by name */
MonoScript[] scripts = Resources.FindObjectsOfTypeAll<MonoScript>();
foreach (MonoScript script in scripts)
{
Type scriptType = script.GetClass();
if (scriptType is not null)
{
string name = scriptType.FullName;
Cache.TryAdd(name, script);
}
}
}
public static MonoScript Get(string name)
{
/* Fetches the value (if there is one) without creating a default val */
Cache.TryGetValue(name, out MonoScript script);
return script;
}
}
[CustomPropertyDrawer(typeof(MonoScriptAttribute))] [CustomPropertyDrawer(typeof(MonoScriptAttribute))]
public class MonoScriptDrawer : PropertyDrawer public class MonoScriptDrawer : PropertyDrawer
{ {

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: d9b025c89af342a3b3cfc696a32fdb2e
timeCreated: 1769285442

View File

@@ -1,97 +0,0 @@
using System.Collections.Generic;
using PashaBibko.Pacore.DevTools;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Pacore.Editor.EditorWindows
{
public class ProfilerWindow : EditorWindow
{
private double LastRepaint = double.MinValue;
private Vector2 ScrollPosition;
[MenuItem("Pacore/Profiler")]
public static void OpenWindow() => GetWindow<ProfilerWindow>();
/* Makes sure the window is repainted often to show latest info */
private void OnDisable() => EditorApplication.update -= CheckForRepaint;
private void OnEnable() => EditorApplication.update += CheckForRepaint;
private void CheckForRepaint()
{
/* Triggers a repaint when it has been over 1 second since last repaint */
double now = EditorApplication.timeSinceStartup;
if (now - LastRepaint > 1f)
{
LastRepaint = now;
Repaint();
}
}
private static void DrawEmptyProfiler()
{
GUILayout.BeginVertical(style: "box");
GUILayout.Label(text: "No profiler snippets found", EditorStyles.boldLabel);
GUILayout.Label(text: "Try running the game to collect profile samples");
GUILayout.EndVertical();
}
private static void DrawProfilerSnippet(string name, List<long> times)
{
GUILayout.BeginVertical(style: "box");
GUILayout.BeginHorizontal();
GUILayout.Label(text: name, EditorStyles.boldLabel);
GUILayout.EndHorizontal();
float averageMs = times.Sum() / (float)times.Count;
GUILayout.Label("Average time: " + averageMs);
IGrouping<long, long>[] ordered = times // List<long>
.GroupBy(time => time) // IEnumerable<IGrouping<long, long>>
.OrderByDescending(time => time.Key) // IOrdererEnumerable<IGrouping<long, long>>
.ToArray();
foreach (IGrouping<long, long> group in ordered)
{
string text = group.Count() > 1
? $"- {group.Key}ms {group.Count()}x"
: $"- {group.Key}ms";
GUILayout.Label(text, EditorStyles.label);
}
GUILayout.EndVertical();
}
/* Draws the different snippets to the screen */
private void OnGUI()
{
GUILayout.Space(5); // Stops the window rendering right at the top
IReadOnlyDictionary<string, List<long>> snippets = CodeProfiler.GetProfilerSnippets();
/* If there are no snippets, draws an inspector with instructions */
if (snippets.Count == 0)
{
DrawEmptyProfiler();
return;
}
/* Draws a quick overview of all snippets found */
GUILayout.BeginVertical(style: "box");
GUILayout.Label(text: $"[{snippets.Count}] different profiler snippets found");
GUILayout.EndVertical();
/* Draws each profiler snippet */
ScrollPosition = EditorGUILayout.BeginScrollView(ScrollPosition);
foreach (KeyValuePair<string, List<long>> snippet in snippets)
{
DrawProfilerSnippet(snippet.Key, snippet.Value);
}
EditorGUILayout.EndScrollView();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 5bd8cdd7db4d4436978e97bda9cdc0cb
timeCreated: 1769285452

View File

@@ -1,14 +1,15 @@
using UnityEngine; using JetBrains.Annotations;
using UnityEngine;
using System; using System;
namespace PashaBibko.Pacore.Attributes namespace PashaBibko.Pacore.Attributes
{ {
[AttributeUsage(validOn: AttributeTargets.Field)] [MeansImplicitUse, AttributeUsage(validOn: AttributeTargets.Field)]
public sealed class DetectInspectorChangesAttribute : PropertyAttribute public sealed class DetectInspectorChangesAttribute : PropertyAttribute
{ {
public string ActionName { get; } public string ActionName { get; }
public DetectInspectorChangesAttribute(string function) public DetectInspectorChangesAttribute([NotNull] string function)
{ {
ActionName = function; ActionName = function;
} }

View File

@@ -1,8 +1,9 @@
using System; using JetBrains.Annotations;
using System;
namespace PashaBibko.Pacore.Attributes namespace PashaBibko.Pacore.Attributes
{ {
[AttributeUsage(AttributeTargets.Method)] [MeansImplicitUse, AttributeUsage(AttributeTargets.Method)]
public class InspectorCallableAttribute : Attribute public class InspectorCallableAttribute : Attribute
{ {
public string ButtonName { get; } public string ButtonName { get; }

View File

@@ -1,9 +1,11 @@
using JetBrains.Annotations;
using UnityEngine; using UnityEngine;
using System; using System;
namespace PashaBibko.Pacore.Attributes namespace PashaBibko.Pacore.Attributes
{ {
[AttributeUsage(validOn: AttributeTargets.Field)] #if UNITY_EDITOR
[MeansImplicitUse, AttributeUsage(validOn: AttributeTargets.Field)]
public sealed class InspectorReadOnlyAttribute : PropertyAttribute public sealed class InspectorReadOnlyAttribute : PropertyAttribute
{ {
public string Name { get; } public string Name { get; }
@@ -13,4 +15,11 @@ namespace PashaBibko.Pacore.Attributes
Name = name; Name = name;
} }
} }
#else // #if UNITY_EDITOR
[MeansImplicitUse, AttributeUsage(validOn: AttributeTargets.Field)]
public sealed class InspectorReadOnlyAttribute : Attribute
{
public InspectorReadOnlyAttribute(string _name = null) { }
}
#endif // UNITY_EDITOR
} }

View File

@@ -1,7 +0,0 @@
using System;
namespace PashaBibko.Pacore.Attributes
{
[AttributeUsage(validOn: AttributeTargets.Field)]
public class StaticInspectorFieldAttribute : Attribute { }
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: f4bdb9ab5a544b57a8e8ec1dae246433
timeCreated: 1769349847

View File

@@ -1,5 +1,6 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Linq; using System.Linq;
using System; using System;
using UnityEngine; using UnityEngine;
@@ -12,9 +13,9 @@ namespace PashaBibko.Pacore
public static ReadOnlyCollection<Type> GetAttributesOf<T>() public static ReadOnlyCollection<Type> GetAttributesOf<T>()
{ {
return AttributeCache.TryGetValue(typeof(T), out List<Type> classes) return AttributeCache.TryGetValue(typeof(T), out List<Type> classes) ?
? classes.AsReadOnly() classes.AsReadOnly() :
: throw new ArgumentException($"Attribute [{nameof(T)}] is not used by any classes"); throw new ArgumentException($"Attribute [{nameof(T)}] is not used by any classes");
} }
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)] [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
@@ -22,7 +23,18 @@ namespace PashaBibko.Pacore
{ {
/* Fetches all the class types in all loaded assemblies */ /* Fetches all the class types in all loaded assemblies */
Type[] classes = AppDomain.CurrentDomain.GetAssemblies() // Assembly[] Type[] classes = AppDomain.CurrentDomain.GetAssemblies() // Assembly[]
.SelectMany(assembly => assembly.GetTypes()) // IEnumerable<Type> .SelectMany(assembly =>
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException err)
{
return err.Types.Where(t => t != null);
}
}) // IEnumerable<Type>
.Where(type => type.IsClass && !type.IsAbstract) // IEnumerable<Type> .Where(type => type.IsClass && !type.IsAbstract) // IEnumerable<Type>
.ToArray(); .ToArray();
@@ -36,20 +48,18 @@ namespace PashaBibko.Pacore
); // Dictionary<Type, List<Type>> ); // Dictionary<Type, List<Type>>
/* Finds which attributes are attached to what classes */ /* Finds which attributes are attached to what classes */
HashSet<Type> seen = new();
foreach (Type current in classes) foreach (Type current in classes)
{ {
/* Tracks the seen attributes */ /* Finds all the attributes of the current class */
seen.Clear(); Type[] attached = current // Type
foreach (object attr in current.GetCustomAttributes(inherit: true)) .GetCustomAttributes(inherit: true) // object[]
{ .Select(attribute => attribute.GetType()) // IEnumerable<Type>
seen.Add(attr.GetType()); .Distinct().ToArray();
}
/* Adds the class type to each attribute in the dictionary */ /* Adds the class type to each attribute in the dictionary */
foreach (Type type in seen) foreach (Type attribute in attached)
{ {
AttributeCache[type].Add(current); AttributeCache[attribute].Add(current);
} }
} }
} }

View File

@@ -1,7 +1,9 @@
{ {
"name": "Pacore", "name": "Pacore",
"rootNamespace": "", "rootNamespace": "",
"references": [], "references": [
"GUID:73bc4dcce6d82e44c8fe9738b987d694"
],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],
"allowUnsafeCode": false, "allowUnsafeCode": false,

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: d359635ad84f4f6eaf0635d203692066
timeCreated: 1769295079

View File

@@ -1,118 +0,0 @@
using System.Collections.Concurrent;
using PashaBibko.Pacore.Attributes;
using UnityEngine;
using System;
using System.Collections;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Debug = UnityEngine.Debug;
namespace PashaBibko.Pacore.Threading
{
[CreateInstanceOnStart] public class ThreadDispatcher : MonoBehaviour
{
private static ConcurrentQueue<IEnumerator> MainThreadMultistepQueue { get; } = new();
private static ConcurrentQueue<Action> MainThreadImmediateQueue { get; } = new();
private static ConcurrentQueue<Action> BackgroundQueue { get; } = new();
private static SemaphoreSlim Semaphore { get; } = new(initialCount: 4);
private static int IsBackgroundProcessing; // Pseudo boolean
private static IEnumerator ActiveMultistepRoutine { get; set; }
private static ThreadDispatcher Instance;
private const long MAIN_THREAD_MS_MAX = 5;
private void Awake()
{
/* Makes sure there is only one instance */
if (Instance is not null)
{
Debug.LogError($"Cannot have multiple instances of [{nameof(ThreadDispatcher)}]");
return;
}
Instance = this;
}
private void OnDestroy()
{
Instance = null; // Allows the Dispatcher to be destroyed
}
public static void QueueMultistep(IEnumerator routine) => MainThreadMultistepQueue.Enqueue(routine);
public static void QueueImmediate(Action action) => MainThreadImmediateQueue.Enqueue(action);
public static void QueueBackground(Action action)
{
/* Adds to the queue and runs if there are no active threads */
BackgroundQueue.Enqueue(action);
TriggerBackgroundProcessing();
}
private static void TriggerBackgroundProcessing()
{
/* Makes sure there are not too many threads queued */
if (Interlocked.Exchange(ref IsBackgroundProcessing, 1) != 1)
{
Task.Run(ProcessBackgroundQueue);
}
}
private static async Task ProcessBackgroundQueue()
{
/* Empties the queue of all tasks */
while (BackgroundQueue.TryDequeue(out Action task))
{
await Semaphore.WaitAsync();
_ = Task.Run(() =>
{
ThreadSafe.Try
(
action: task,
final: () => Semaphore.Release()
);
});
}
/* Cleans up to allow for future procession */
Interlocked.Exchange(ref IsBackgroundProcessing, 0);
if (!BackgroundQueue.IsEmpty) // Items may be queued during cleanup
{
TriggerBackgroundProcessing();
}
}
private void Update()
{
/* Runs the Actions in the immediate queue */
Stopwatch sw = Stopwatch.StartNew(); // Used to make sure not too much processing is done in one go
while (MainThreadImmediateQueue.TryDequeue(out Action current) && sw.ElapsedMilliseconds < MAIN_THREAD_MS_MAX)
{
current.Invoke();
}
/* Runs the multistep actions (if there is still time) */
while (sw.ElapsedMilliseconds < MAIN_THREAD_MS_MAX)
{
/* Gets a new routine if there is none active */
if (ActiveMultistepRoutine == null)
{
if (!MainThreadMultistepQueue.TryDequeue(out IEnumerator next))
{
return; // There is none left so we can return early
}
ActiveMultistepRoutine = next;
}
/* Runs the next step in the routine */
if (!ActiveMultistepRoutine.MoveNext())
{
ActiveMultistepRoutine = null; // [MoveNext() -> false] means the routine has ended
}
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 1ef64778d77647d9991a3b56a831dc5e
timeCreated: 1769293819

View File

@@ -1,44 +0,0 @@
using System.Runtime.CompilerServices;
using System.Threading;
using UnityEngine;
using System;
namespace PashaBibko.Pacore.Threading
{
public static partial class ThreadSafe
{
private static SynchronizationContext MainThreadContext { get; set; }
public class IncorrectThreadException : Exception
{
public IncorrectThreadException(string message)
: base(message)
{
}
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
private static void CaptureMainThreadContext()
{
MainThreadContext = SynchronizationContext.Current;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void EnforceMainThread()
{
if (SynchronizationContext.Current != MainThreadContext)
{
throw new IncorrectThreadException("Main thread function was called on a background thread");
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void EnforceBackgroundThread()
{
if (SynchronizationContext.Current == MainThreadContext)
{
throw new IncorrectThreadException("Background thread function was called on the main thread");
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: a4aad0735c2147beb2b087872fe4c364
timeCreated: 1769347995

View File

@@ -1,24 +0,0 @@
using System.Runtime.CompilerServices;
using UnityEngine;
using System;
namespace PashaBibko.Pacore.Threading
{
public static partial class ThreadSafe
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Try(Action action, Action final = null)
{
try { action(); }
/* Makes sure any exceptions are caught and logged properly */
catch (Exception ex)
{
ThreadDispatcher.QueueImmediate(() => Debug.Log($"Exception: [{ex.Message}]"));
throw;
}
finally { final?.Invoke(); }
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 0ffd3b00465e46ae99836711cf00f884
timeCreated: 1769295315

View File

@@ -1,7 +1,7 @@
{ {
"name": "com.pashabibko.pacore", "name": "com.pashabibko.pacore",
"displayName": "Pacore", "displayName": "Pacore",
"version": "1.1.1-alpha", "version": "1.0.0",
"unity": "2022.3", "unity": "2022.3",
"description" : "Small Unity Util library", "description" : "Small Unity Util library",
"keywords": [ "tool", "script", "runtime" ], "keywords": [ "tool", "script", "runtime" ],

View File

@@ -133,6 +133,7 @@ GameObject:
- component: {fileID: 330585546} - component: {fileID: 330585546}
- component: {fileID: 330585545} - component: {fileID: 330585545}
- component: {fileID: 330585544} - component: {fileID: 330585544}
- component: {fileID: 330585548}
- component: {fileID: 330585547} - component: {fileID: 330585547}
m_Layer: 0 m_Layer: 0
m_Name: Main Camera m_Name: Main Camera
@@ -259,6 +260,21 @@ MonoBehaviour:
m_MipBias: 0 m_MipBias: 0
m_VarianceClampScale: 0.9 m_VarianceClampScale: 0.9
m_ContrastAdaptiveSharpening: 0 m_ContrastAdaptiveSharpening: 0
--- !u!114 &330585548
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 330585543}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a411a69d284bfd04bafc210a81b43e88, type: 3}
m_Name:
m_EditorClassIdentifier:
go: {fileID: 0}
Spawnable: PashaBibko.Pacore.Editor.Drawers.DetectInspectorChangesDrawer
Test: 0
--- !u!1 &410087039 --- !u!1 &410087039
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@@ -0,0 +1,30 @@
using PashaBibko.Pacore.Attributes;
using UnityEngine;
[CreateInstanceOnStart] public class TestMonoBehaviour : MonoBehaviour
{
[InspectorReadOnly, SerializeField] private GameObject go;
[MonoScript(inherited: typeof(MonoBehaviour))] public string Spawnable;
[DetectInspectorChanges("OnTestChange")]
public int Test;
private void OnTestChange() => LogTestValue();
[InspectorCallable(nameof(LogSpawnableType))]
public void LogSpawnableType()
{
Debug.Log(Spawnable);
}
[InspectorCallable("Test button")] public void LogTestValue()
{
Debug.Log($"Test value [{Test}]");
}
[InspectorCallable("Other Test button")] public void DontLogTestValue()
{
Debug.Log("Test");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a411a69d284bfd04bafc210a81b43e88
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

View File

@@ -1,7 +1,7 @@
{ {
"dependencies": { "dependencies": {
"com.unity.collab-proxy": "2.11.3", "com.unity.collab-proxy": "2.11.3",
"com.unity.ide.rider": "3.0.39", "com.unity.ide.rider": "3.0.36",
"com.unity.ide.visualstudio": "2.0.22", "com.unity.ide.visualstudio": "2.0.22",
"com.unity.ide.vscode": "1.2.5", "com.unity.ide.vscode": "1.2.5",
"com.unity.render-pipelines.universal": "14.0.12", "com.unity.render-pipelines.universal": "14.0.12",

View File

@@ -25,7 +25,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.ide.rider": { "com.unity.ide.rider": {
"version": "3.0.39", "version": "3.0.36",
"depth": 0, "depth": 0,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {

View File

@@ -3,45 +3,33 @@
--- !u!159 &1 --- !u!159 &1
EditorSettings: EditorSettings:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
serializedVersion: 12 serializedVersion: 9
m_ExternalVersionControlSupport: Visible Meta Files
m_SerializationMode: 2 m_SerializationMode: 2
m_LineEndingsForNewScripts: 2 m_LineEndingsForNewScripts: 2
m_DefaultBehaviorMode: 0 m_DefaultBehaviorMode: 0
m_PrefabRegularEnvironment: {fileID: 0} m_PrefabRegularEnvironment: {fileID: 0}
m_PrefabUIEnvironment: {fileID: 0} m_PrefabUIEnvironment: {fileID: 0}
m_SpritePackerMode: 0 m_SpritePackerMode: 0
m_SpritePackerCacheSize: 10
m_SpritePackerPaddingPower: 1 m_SpritePackerPaddingPower: 1
m_Bc7TextureCompressor: 0
m_EtcTextureCompressorBehavior: 1 m_EtcTextureCompressorBehavior: 1
m_EtcTextureFastCompressor: 1 m_EtcTextureFastCompressor: 1
m_EtcTextureNormalCompressor: 2 m_EtcTextureNormalCompressor: 2
m_EtcTextureBestCompressor: 4 m_EtcTextureBestCompressor: 4
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp
m_ProjectGenerationRootNamespace: m_ProjectGenerationRootNamespace:
m_CollabEditorSettings:
inProgressEnabled: 1
m_EnableTextureStreamingInEditMode: 1 m_EnableTextureStreamingInEditMode: 1
m_EnableTextureStreamingInPlayMode: 1 m_EnableTextureStreamingInPlayMode: 1
m_EnableEditorAsyncCPUTextureLoading: 0
m_AsyncShaderCompilation: 1 m_AsyncShaderCompilation: 1
m_PrefabModeAllowAutoSave: 1 m_EnterPlayModeOptionsEnabled: 0
m_EnterPlayModeOptionsEnabled: 1
m_EnterPlayModeOptions: 3 m_EnterPlayModeOptions: 3
m_GameObjectNamingDigits: 1 m_ShowLightmapResolutionOverlay: 1
m_GameObjectNamingScheme: 0
m_AssetNamingUsesSpace: 1
m_InspectorUseIMGUIDefaultInspector: 0
m_UseLegacyProbeSampleCount: 0 m_UseLegacyProbeSampleCount: 0
m_SerializeInlineMappingsOnOneLine: 0
m_DisableCookiesInLightmapper: 1
m_AssetPipelineMode: 1 m_AssetPipelineMode: 1
m_RefreshImportMode: 0
m_CacheServerMode: 0 m_CacheServerMode: 0
m_CacheServerEndpoint: m_CacheServerEndpoint:
m_CacheServerNamespacePrefix: default m_CacheServerNamespacePrefix: default
m_CacheServerEnableDownload: 1 m_CacheServerEnableDownload: 1
m_CacheServerEnableUpload: 1 m_CacheServerEnableUpload: 1
m_CacheServerEnableAuth: 0
m_CacheServerEnableTls: 0
m_CacheServerValidationMode: 2
m_CacheServerDownloadBatchSize: 128
m_EnableEnlightenBakedGI: 0

View File

@@ -1,19 +0,0 @@
# Pacore
Pacore is a small unity coding QoL library mainly focused on improving accesability within the editor.
You can view a list of the features with their documentation [here](Features.md)
and all planned features [here](Todo.md).
> NOTE: You may be viewing this repository on the github mirror,
> the repository is hosted on [git.bibko.uk](https://git.bibko.uk/Pasha/Pacore)
### Add to project
#### Requirements
- Unity 2022.3 or later (earlier versions may still work)
- No other dependencies or software is required
#### Instillation guide
WIP

View File

@@ -1,8 +0,0 @@
### Planned features
##### Static variable inspector tooling
- Ability to view static fields
- Change static values within the inspector
##### Instillation guide
- Instructions to download and include the library within Unity projects