mirror of
https://github.com/shinyflvre/Mate-Engine.git
synced 2026-07-17 04:58:29 +00:00
**Changelog 1.4.0 – THE LOCAL AI Update** **Disclaimer:** The AI runs *entirely locally* and is designed to be environmentally and ethically responsible. - It does **not** harm nature or exploit any artists. - It has only **1.5 billion parameters**, making it a **very small model** by modern standards. - It consumes as much GPU energy as watching a **1440p 60fps YouTube video**. - It was **not trained on artist data**; it uses personal input and public Wikipedia datasets. - It has its own personality, and I ensured it adheres to **ethical standards**. --- ### New Features - Added **Qwen 2.5 1.5B LLM** to MateEngine! - Press **Middle Mouse Button** while hovering over the pet to open the chat window. - Runs fully locally on your GPU — no internet connection required. - Only uses GPU while processing prompts. - Note: This is a **lightweight model** and won’t handle complex tasks or coding. It’s just a small, fun feature! - Added **Resize Button** – Quickly adjust app size for 1080p, 1440p, and 4K monitors. - Added **VRM Information Panel** – Displays polygon count, VRM version, and bone status: - **Perfect** – Properly exported model. - **Failure** – Model has export issues; animations may break. - Added **Options Submenu**. - Added **Volume Sliders** – Independently control pet, effects, and menu volume. - Added **Graphics Settings**. - Added **Dance Trails** – Glowing effects on the pet’s hands during dance. Toggle on/off as desired. - Improved **Music Source Selector** – You can now whitelist or add custom audio sources for dancing. - Added **MateEngine Version Info** – View the current app version from the menu. - Menu can now be opened with **M** key or **Right-Click**. - Added full support for **VRM 1.x** and **VRM 0.x** models. - Introduced **VRM Validator Tool** in Unity Editor – Great for content creators. --- ### Improvements & Fixes - Major **Performance Optimizations**. - Fixed a **GC Error** that could appear after 6–12 hours of continuous use. - Improved **Hand Tracking** – Reduced stuttering in some animations. - Added **Discord Rich Presence** integration. - Added **Glowing Halo** for Steam users as exclusive DLC!
244 lines
10 KiB
C#
244 lines
10 KiB
C#
using System;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using System.Reflection;
|
|
using System.Collections.Generic;
|
|
|
|
namespace LLMUnity
|
|
{
|
|
public class PropertyEditor : Editor
|
|
{
|
|
public static int buttonWidth = 150;
|
|
|
|
public virtual void AddScript(SerializedObject llmScriptSO)
|
|
{
|
|
var scriptProp = llmScriptSO.FindProperty("m_Script");
|
|
EditorGUILayout.PropertyField(scriptProp);
|
|
}
|
|
|
|
public virtual bool ToggleButton(string text, bool activated)
|
|
{
|
|
GUIStyle style = new GUIStyle("Button");
|
|
if (activated) style.normal = new GUIStyleState() { background = Texture2D.grayTexture };
|
|
return GUILayout.Button(text, style, GUILayout.Width(buttonWidth));
|
|
}
|
|
|
|
public virtual void AddSetupSettings(SerializedObject llmScriptSO)
|
|
{
|
|
List<Type> attributeClasses = new List<Type>(){typeof(LocalRemoteAttribute)};
|
|
SerializedProperty remoteProperty = llmScriptSO.FindProperty("remote");
|
|
if (remoteProperty != null) attributeClasses.Add(remoteProperty.boolValue ? typeof(RemoteAttribute) : typeof(LocalAttribute));
|
|
attributeClasses.Add(typeof(LLMAttribute));
|
|
if (llmScriptSO.FindProperty("advancedOptions").boolValue)
|
|
{
|
|
attributeClasses.Add(typeof(LLMAdvancedAttribute));
|
|
}
|
|
ShowPropertiesOfClass("Setup Settings", llmScriptSO, attributeClasses, true);
|
|
}
|
|
|
|
public virtual void AddModelSettings(SerializedObject llmScriptSO)
|
|
{
|
|
List<Type> attributeClasses = new List<Type>(){typeof(ModelAttribute)};
|
|
if (llmScriptSO.FindProperty("advancedOptions").boolValue)
|
|
{
|
|
attributeClasses.Add(typeof(ModelAdvancedAttribute));
|
|
}
|
|
ShowPropertiesOfClass("Model Settings", llmScriptSO, attributeClasses, true);
|
|
}
|
|
|
|
public virtual void AddChatSettings(SerializedObject llmScriptSO)
|
|
{
|
|
List<Type> attributeClasses = new List<Type>(){typeof(ChatAttribute)};
|
|
if (llmScriptSO.FindProperty("advancedOptions").boolValue)
|
|
{
|
|
attributeClasses.Add(typeof(ChatAdvancedAttribute));
|
|
}
|
|
ShowPropertiesOfClass("Chat Settings", llmScriptSO, attributeClasses, true);
|
|
}
|
|
|
|
public void AddDebugModeToggle()
|
|
{
|
|
LLMUnitySetup.SetDebugMode((LLMUnitySetup.DebugModeType)EditorGUILayout.EnumPopup("Log Level", LLMUnitySetup.DebugMode));
|
|
}
|
|
|
|
public void AddAdvancedOptionsToggle(SerializedObject llmScriptSO)
|
|
{
|
|
List<SerializedProperty> properties = GetPropertiesOfClass(llmScriptSO, new List<Type>(){typeof(AdvancedAttribute)});
|
|
if (properties.Count == 0) return;
|
|
|
|
SerializedProperty advancedOptionsProp = llmScriptSO.FindProperty("advancedOptions");
|
|
string toggleText = (advancedOptionsProp.boolValue ? "Hide" : "Show") + " Advanced Options";
|
|
if (ToggleButton(toggleText, advancedOptionsProp.boolValue)) advancedOptionsProp.boolValue = !advancedOptionsProp.boolValue;
|
|
}
|
|
|
|
public virtual void AddOptionsToggles(SerializedObject llmScriptSO)
|
|
{
|
|
AddAdvancedOptionsToggle(llmScriptSO);
|
|
Space();
|
|
}
|
|
|
|
public virtual void Space()
|
|
{
|
|
EditorGUILayout.Space((int)EditorGUIUtility.singleLineHeight / 2);
|
|
}
|
|
|
|
protected virtual Type[] GetPropertyTypes()
|
|
{
|
|
List<Type> types = new List<Type>();
|
|
Type currentType = target.GetType();
|
|
while (currentType != null)
|
|
{
|
|
types.Add(currentType);
|
|
currentType = currentType.BaseType;
|
|
if (currentType == typeof(MonoBehaviour)) break;
|
|
}
|
|
types.Reverse();
|
|
return types.ToArray();
|
|
}
|
|
|
|
public List<SerializedProperty> GetPropertiesOfClass(SerializedObject so, List<Type> attributeClasses)
|
|
{
|
|
// display a property if it belongs to a certain class and/or has a specific attribute class
|
|
List<SerializedProperty> properties = new List<SerializedProperty>();
|
|
foreach (Type attrClass in attributeClasses)
|
|
{
|
|
if (attrClass == null) continue;
|
|
foreach (Type targetClass in GetPropertyTypes())
|
|
{
|
|
SerializedProperty prop = so.GetIterator();
|
|
if (prop.NextVisible(true))
|
|
{
|
|
do
|
|
{
|
|
if (PropertyInClass(prop, targetClass, attrClass))
|
|
properties.Add(so.FindProperty(prop.propertyPath));
|
|
}
|
|
while (prop.NextVisible(false));
|
|
}
|
|
}
|
|
}
|
|
return properties;
|
|
}
|
|
|
|
public bool ShowPropertiesOfClass(string title, SerializedObject so, List<Type> attributeClasses, bool addSpace = true, List<Type> excludeAttributeClasses = null)
|
|
{
|
|
// display a property if it belongs to a certain class and/or has a specific attribute class
|
|
List<SerializedProperty> properties = GetPropertiesOfClass(so, attributeClasses);
|
|
if (excludeAttributeClasses != null)
|
|
{
|
|
List<SerializedProperty> excludeProperties = GetPropertiesOfClass(so, excludeAttributeClasses);
|
|
List<SerializedProperty> removeProperties = new List<SerializedProperty>();
|
|
foreach (SerializedProperty excprop in excludeProperties)
|
|
{
|
|
foreach (SerializedProperty prop in properties)
|
|
{
|
|
if (prop.displayName == excprop.displayName) removeProperties.Add(prop);
|
|
}
|
|
}
|
|
foreach (SerializedProperty prop in removeProperties) properties.Remove(prop);
|
|
}
|
|
if (properties.Count == 0) return false;
|
|
if (title != "") EditorGUILayout.LabelField(title, EditorStyles.boldLabel);
|
|
foreach (SerializedProperty prop in properties)
|
|
{
|
|
Attribute floatAttr = GetPropertyAttribute(prop, typeof(FloatAttribute));
|
|
Attribute intAttr = GetPropertyAttribute(prop, typeof(IntAttribute));
|
|
Attribute dynamicRangeAttr = GetPropertyAttribute(prop, typeof(DynamicRangeAttribute));
|
|
if (floatAttr != null)
|
|
{
|
|
FloatAttribute attr = (FloatAttribute)floatAttr;
|
|
EditorGUILayout.Slider(prop, attr.Min, attr.Max, new GUIContent(prop.displayName));
|
|
}
|
|
else if (intAttr != null)
|
|
{
|
|
IntAttribute attr = (IntAttribute)intAttr;
|
|
EditorGUILayout.IntSlider(prop, attr.Min, attr.Max, new GUIContent(prop.displayName));
|
|
}
|
|
else if (dynamicRangeAttr != null)
|
|
{
|
|
DynamicRangeAttribute attr = (DynamicRangeAttribute)dynamicRangeAttr;
|
|
if (attr.intOrFloat)
|
|
{
|
|
float minValue = so.FindProperty(attr.minVariable).floatValue;
|
|
float maxValue = so.FindProperty(attr.maxVariable).floatValue;
|
|
EditorGUILayout.Slider(prop, minValue, maxValue, new GUIContent(prop.displayName));
|
|
}
|
|
else
|
|
{
|
|
int minValue = so.FindProperty(attr.minVariable).intValue;
|
|
int maxValue = so.FindProperty(attr.maxVariable).intValue;
|
|
EditorGUILayout.IntSlider(prop, minValue, maxValue, new GUIContent(prop.displayName));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EditorGUILayout.PropertyField(prop);
|
|
}
|
|
}
|
|
if (addSpace) Space();
|
|
return true;
|
|
}
|
|
|
|
public bool PropertyInClass(SerializedProperty prop, Type targetClass, Type attributeClass = null)
|
|
{
|
|
// check if a property belongs to a certain class and/or has a specific attribute class
|
|
FieldInfo field = prop.serializedObject.targetObject.GetType().GetField(prop.name,
|
|
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
return field != null && field.DeclaringType == targetClass && (attributeClass == null || GetPropertyAttribute(prop, attributeClass) != null);
|
|
}
|
|
|
|
public Attribute GetPropertyAttribute(SerializedProperty prop, Type attributeClass)
|
|
{
|
|
// check if a property has a specific attribute class
|
|
foreach (var pathSegment in prop.propertyPath.Split('.'))
|
|
{
|
|
var targetType = prop.serializedObject.targetObject.GetType();
|
|
while (targetType != null)
|
|
{
|
|
var fieldInfo = targetType.GetField(pathSegment, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
if (fieldInfo != null)
|
|
{
|
|
foreach (Attribute attr in fieldInfo.GetCustomAttributes(attributeClass, true))
|
|
{
|
|
if (attributeClass.IsAssignableFrom(attr.GetType()))
|
|
return attr;
|
|
}
|
|
}
|
|
targetType = targetType.BaseType;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public virtual void OnInspectorGUIStart(SerializedObject scriptSO)
|
|
{
|
|
scriptSO.Update();
|
|
GUI.enabled = false;
|
|
AddScript(scriptSO);
|
|
GUI.enabled = true;
|
|
EditorGUI.BeginChangeCheck();
|
|
}
|
|
|
|
public virtual void OnInspectorGUIEnd(SerializedObject scriptSO)
|
|
{
|
|
if (EditorGUI.EndChangeCheck())
|
|
Repaint();
|
|
|
|
scriptSO.ApplyModifiedProperties();
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
SerializedObject llmScriptSO = new SerializedObject(target);
|
|
|
|
OnInspectorGUIStart(llmScriptSO);
|
|
AddOptionsToggles(llmScriptSO);
|
|
|
|
AddSetupSettings(llmScriptSO);
|
|
AddChatSettings(llmScriptSO);
|
|
AddModelSettings(llmScriptSO);
|
|
|
|
OnInspectorGUIEnd(llmScriptSO);
|
|
}
|
|
}
|
|
}
|