Commit f6ed3c6f authored by cann-alberto's avatar cann-alberto
Browse files

first project commit

parent 4487b14f
using UnityEngine;
using UnityEditor;
namespace Mirror
{
[CustomPropertyDrawer(typeof(ReadOnlyAttribute))]
public class ReadOnlyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// Cache the current GUI enabled state
bool prevGuiEnabledState = GUI.enabled;
GUI.enabled = false;
EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = prevGuiEnabledState;
}
}
}
fileFormatVersion: 2
guid: 22f17bdd21f104c41bc175937fefbdec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEditor;
using UnityEngine;
namespace Mirror
{
[CustomPropertyDrawer(typeof(SceneAttribute))]
public class SceneDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType == SerializedPropertyType.String)
{
SceneAsset sceneObject = AssetDatabase.LoadAssetAtPath<SceneAsset>(property.stringValue);
if (sceneObject == null && !string.IsNullOrWhiteSpace(property.stringValue))
{
// try to load it from the build settings for legacy compatibility
sceneObject = GetBuildSettingsSceneObject(property.stringValue);
}
if (sceneObject == null && !string.IsNullOrWhiteSpace(property.stringValue))
{
Debug.LogError($"Could not find scene {property.stringValue} in {property.propertyPath}, assign the proper scenes in your NetworkManager");
}
SceneAsset scene = (SceneAsset)EditorGUI.ObjectField(position, label, sceneObject, typeof(SceneAsset), true);
property.stringValue = AssetDatabase.GetAssetPath(scene);
}
else
{
EditorGUI.LabelField(position, label.text, "Use [Scene] with strings.");
}
}
protected SceneAsset GetBuildSettingsSceneObject(string sceneName)
{
foreach (EditorBuildSettingsScene buildScene in EditorBuildSettings.scenes)
{
SceneAsset sceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(buildScene.path);
if (sceneAsset!= null && sceneAsset.name == sceneName)
{
return sceneAsset;
}
}
return null;
}
}
}
fileFormatVersion: 2
guid: b24704a46211b4ea294aba8f58715cea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// helper class for NetworkBehaviourInspector to draw all enumerable SyncObjects
// (SyncList/Set/Dictionary)
// 'SyncObjectCollectionsDrawer' is a nicer name than 'IEnumerableSyncObjectsDrawer'
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
namespace Mirror
{
class SyncObjectCollectionField
{
public bool visible;
public readonly FieldInfo field;
public readonly string label;
public SyncObjectCollectionField(FieldInfo field)
{
this.field = field;
visible = false;
// field.FieldType.Name has a backtick and number at the end, e.g. SyncList`1
// so we split it and only take the first part so it looks nicer.
// e.g. SyncList`1 -> SyncList
// Better to do it one time here than in hot path in OnInspectorGUI
label = $"{field.Name} [{Regex.Replace(field.FieldType.Name, @"`\d+", "")}]";
}
}
public class SyncObjectCollectionsDrawer
{
readonly UnityEngine.Object targetObject;
readonly List<SyncObjectCollectionField> syncObjectCollectionFields;
public SyncObjectCollectionsDrawer(UnityEngine.Object targetObject)
{
this.targetObject = targetObject;
syncObjectCollectionFields = new List<SyncObjectCollectionField>();
foreach (FieldInfo field in InspectorHelper.GetAllFields(targetObject.GetType(), typeof(NetworkBehaviour)))
{
// only draw SyncObjects that are IEnumerable (SyncList/Set/Dictionary)
if (field.IsVisibleSyncObject() &&
field.ImplementsInterface<SyncObject>() &&
field.ImplementsInterface<IEnumerable>())
{
syncObjectCollectionFields.Add(new SyncObjectCollectionField(field));
}
}
}
public void Draw()
{
if (syncObjectCollectionFields.Count == 0) { return; }
EditorGUILayout.Space();
EditorGUILayout.LabelField("Sync Collections", EditorStyles.boldLabel);
for (int i = 0; i < syncObjectCollectionFields.Count; i++)
{
DrawSyncObjectCollection(syncObjectCollectionFields[i]);
}
}
void DrawSyncObjectCollection(SyncObjectCollectionField syncObjectCollectionField)
{
syncObjectCollectionField.visible = EditorGUILayout.Foldout(syncObjectCollectionField.visible, syncObjectCollectionField.label);
if (syncObjectCollectionField.visible)
{
using (new EditorGUI.IndentLevelScope())
{
object fieldValue = syncObjectCollectionField.field.GetValue(targetObject);
if (fieldValue is IEnumerable syncObject)
{
int index = 0;
foreach (object item in syncObject)
{
string itemValue = item != null ? item.ToString() : "NULL";
string itemLabel = $"Element {index}";
EditorGUILayout.LabelField(itemLabel, itemValue);
index++;
}
}
}
}
}
}
}
fileFormatVersion: 2
guid: 6f90afab12e04f0e945d83e9d38308a3
timeCreated: 1632556645
\ No newline at end of file
using UnityEditor;
using UnityEngine;
namespace Mirror
{
[CustomPropertyDrawer(typeof(SyncVarAttribute))]
public class SyncVarAttributeDrawer : PropertyDrawer
{
static readonly GUIContent syncVarIndicatorContent = new GUIContent("SyncVar", "This variable has been marked with the [SyncVar] attribute.");
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Vector2 syncVarIndicatorRect = EditorStyles.miniLabel.CalcSize(syncVarIndicatorContent);
float valueWidth = position.width - syncVarIndicatorRect.x;
Rect valueRect = new Rect(position.x, position.y, valueWidth, position.height);
Rect labelRect = new Rect(position.x + valueWidth, position.y, syncVarIndicatorRect.x, position.height);
EditorGUI.PropertyField(valueRect, property, label, true);
GUI.Label(labelRect, syncVarIndicatorContent, EditorStyles.miniLabel);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property);
}
}
}
fileFormatVersion: 2
guid: 27821afc81c4d064d8348fbeb00c0ce8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: d9f8e6274119b4ce29e498cfb8aca8a4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Mirror.Tests")]
fileFormatVersion: 2
guid: 929924d95663264478d4238d4910d22e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 251338e67afb4cefa38da924f8c50a6e
timeCreated: 1628851818
\ No newline at end of file
// for Unity 2020+ we use ILPostProcessor.
// only automatically invoke it for older versions.
#if !UNITY_2020_3_OR_NEWER
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Mono.CecilX;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
using UnityAssembly = UnityEditor.Compilation.Assembly;
namespace Mirror.Weaver
{
public static class CompilationFinishedHook
{
// needs to be the same as Weaver.MirrorAssemblyName!
const string MirrorRuntimeAssemblyName = "Mirror";
const string MirrorWeaverAssemblyName = "Mirror.Weaver";
// global weaver define so that tests can use it
internal static Weaver weaver;
// delegate for subscription to Weaver warning messages
public static Action<string> OnWeaverWarning;
// delete for subscription to Weaver error messages
public static Action<string> OnWeaverError;
// controls whether Weaver errors are reported direct to the Unity console (tests enable this)
public static bool UnityLogEnabled = true;
[InitializeOnLoadMethod]
public static void OnInitializeOnLoad()
{
CompilationPipeline.assemblyCompilationFinished += OnCompilationFinished;
// We only need to run this once per session
// after that, all assemblies will be weaved by the event
if (!SessionState.GetBool("MIRROR_WEAVED", false))
{
// reset session flag
SessionState.SetBool("MIRROR_WEAVED", true);
SessionState.SetBool("MIRROR_WEAVE_SUCCESS", true);
WeaveExistingAssemblies();
}
}
public static void WeaveExistingAssemblies()
{
foreach (UnityAssembly assembly in CompilationPipeline.GetAssemblies())
{
if (File.Exists(assembly.outputPath))
{
OnCompilationFinished(assembly.outputPath, new CompilerMessage[0]);
}
}
EditorUtility.RequestScriptReload();
}
static Assembly FindCompilationPipelineAssembly(string assemblyName) =>
CompilationPipeline.GetAssemblies().First(assembly => assembly.name == assemblyName);
static bool CompilerMessagesContainError(CompilerMessage[] messages) =>
messages.Any(msg => msg.type == CompilerMessageType.Error);
public static void OnCompilationFinished(string assemblyPath, CompilerMessage[] messages)
{
// Do nothing if there were compile errors on the target
if (CompilerMessagesContainError(messages))
{
Debug.Log("Weaver: stop because compile errors on target");
return;
}
// Should not run on the editor only assemblies (test ones still need to be weaved)
if (assemblyPath.Contains("-Editor") ||
(assemblyPath.Contains(".Editor") && !assemblyPath.Contains(".Tests")))
{
return;
}
// skip Mirror.dll because CompilationFinishedHook can't weave itself.
// this would cause a sharing violation.
// skip Mirror.Weaver.dll too.
string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
if (assemblyName == MirrorRuntimeAssemblyName || assemblyName == MirrorWeaverAssemblyName)
{
return;
}
// find Mirror.dll
Assembly mirrorAssembly = FindCompilationPipelineAssembly(MirrorRuntimeAssemblyName);
if (mirrorAssembly == null)
{
Debug.LogError("Failed to find Mirror runtime assembly");
return;
}
string mirrorRuntimeDll = mirrorAssembly.outputPath;
if (!File.Exists(mirrorRuntimeDll))
{
// this is normal, it happens with any assembly that is built before mirror
// such as unity packages or your own assemblies
// those don't need to be weaved
// if any assembly depends on mirror, then it will be built after
return;
}
// find UnityEngine.CoreModule.dll
string unityEngineCoreModuleDLL = UnityEditorInternal.InternalEditorUtility.GetEngineCoreModuleAssemblyPath();
if (string.IsNullOrEmpty(unityEngineCoreModuleDLL))
{
Debug.LogError("Failed to find UnityEngine assembly");
return;
}
HashSet<string> dependencyPaths = GetDependencyPaths(assemblyPath);
dependencyPaths.Add(Path.GetDirectoryName(mirrorRuntimeDll));
dependencyPaths.Add(Path.GetDirectoryName(unityEngineCoreModuleDLL));
if (!WeaveFromFile(assemblyPath, dependencyPaths.ToArray()))
{
// Set false...will be checked in \Editor\EnterPlayModeSettingsCheck.CheckSuccessfulWeave()
SessionState.SetBool("MIRROR_WEAVE_SUCCESS", false);
if (UnityLogEnabled) Debug.LogError($"Weaving failed for {assemblyPath}");
}
}
static HashSet<string> GetDependencyPaths(string assemblyPath)
{
// build directory list for later asm/symbol resolving using CompilationPipeline refs
HashSet<string> dependencyPaths = new HashSet<string>
{
Path.GetDirectoryName(assemblyPath)
};
foreach (Assembly assembly in CompilationPipeline.GetAssemblies())
{
if (assembly.outputPath == assemblyPath)
{
foreach (string reference in assembly.compiledAssemblyReferences)
{
dependencyPaths.Add(Path.GetDirectoryName(reference));
}
}
}
return dependencyPaths;
}
// helper function to invoke Weaver with an AssemblyDefinition from a
// file path, with dependencies added.
static bool WeaveFromFile(string assemblyPath, string[] dependencies)
{
// resolve assembly from stream
using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters{ ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver }))
{
// add this assembly's path and unity's assembly path
asmResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath));
asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName());
// add dependencies
if (dependencies != null)
{
foreach (string path in dependencies)
{
asmResolver.AddSearchDirectory(path);
}
}
// create weaver with logger
weaver = new Weaver(new CompilationFinishedLogger());
if (weaver.Weave(assembly, asmResolver, out bool modified))
{
// write changes to file if modified
if (modified)
assembly.Write(new WriterParameters{WriteSymbols = true});
return true;
}
return false;
}
}
}
}
#endif
fileFormatVersion: 2
guid: de2aeb2e8068f421a9a1febe408f7051
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
// logger for compilation finished hook.
// where we need a callback and Debug.Log.
// for Unity 2020+ we use ILPostProcessor.
#if !UNITY_2020_3_OR_NEWER
using Mono.CecilX;
using UnityEngine;
namespace Mirror.Weaver
{
public class CompilationFinishedLogger : Logger
{
public void Warning(string message) => Warning(message, null);
public void Warning(string message, MemberReference mr)
{
if (mr != null) message = $"{message} (at {mr})";
if (CompilationFinishedHook.UnityLogEnabled) Debug.LogWarning(message);
CompilationFinishedHook.OnWeaverWarning?.Invoke(message);
}
public void Error(string message) => Error(message, null);
public void Error(string message, MemberReference mr)
{
if (mr != null) message = $"{message} (at {mr})";
if (CompilationFinishedHook.UnityLogEnabled) Debug.LogError(message);
CompilationFinishedHook.OnWeaverError?.Invoke(message);
}
}
}
#endif
fileFormatVersion: 2
guid: 47026732f0fa475c94bd1dd41f1de559
timeCreated: 1629379868
\ No newline at end of file
#if !UNITY_2020_3_OR_NEWER
// make sure we weaved successfully when entering play mode.
using UnityEditor;
using UnityEngine;
namespace Mirror
{
public class EnterPlayModeSettingsCheck : MonoBehaviour
{
[InitializeOnLoadMethod]
static void OnInitializeOnLoad()
{
// Hook this event to see if we have a good weave every time
// user attempts to enter play mode or tries to do a build
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
static void OnPlayModeStateChanged(PlayModeStateChange state)
{
// Per Unity docs, this fires "when exiting edit mode before the Editor is in play mode".
// This doesn't fire when closing the editor.
if (state == PlayModeStateChange.ExitingEditMode)
{
// Check if last weave result was successful
if (!SessionState.GetBool("MIRROR_WEAVE_SUCCESS", false))
{
// Last weave result was a failure...try to weave again
// Faults will show in the console that may have been cleared by "Clear on Play"
SessionState.SetBool("MIRROR_WEAVE_SUCCESS", true);
Weaver.CompilationFinishedHook.WeaveExistingAssemblies();
// Did that clear things up for us?
if (!SessionState.GetBool("MIRROR_WEAVE_SUCCESS", false))
{
// Nope, still failed, and console has the issues logged
Debug.LogError("Can't enter play mode until weaver issues are resolved.");
EditorApplication.isPlaying = false;
}
}
}
}
}
}
#endif
fileFormatVersion: 2
guid: b73d0f106ba84aa983baa5142b08a0a9
timeCreated: 1628851346
\ No newline at end of file
fileFormatVersion: 2
guid: 09082db63d1d48d9ab91320165c1b684
timeCreated: 1628859005
\ No newline at end of file
// tests use WeaveAssembler, which uses AssemblyBuilder to Build().
// afterwards ILPostProcessor weaves the build.
// this works on windows, but build() does not run ILPP on mac atm.
// we need to manually invoke ILPP with an assembly from file.
//
// this is in Weaver folder becuase CompilationPipeline can only be accessed
// from assemblies with the name "Unity.*.CodeGen"
using System.IO;
using Unity.CompilationPipeline.Common.ILPostProcessing;
namespace Mirror.Weaver
{
public class CompiledAssemblyFromFile : ICompiledAssembly
{
readonly string assemblyPath;
public string Name => Path.GetFileNameWithoutExtension(assemblyPath);
public string[] References { get; set; }
public string[] Defines { get; set; }
public InMemoryAssembly InMemoryAssembly { get; }
public CompiledAssemblyFromFile(string assemblyPath)
{
this.assemblyPath = assemblyPath;
byte[] peData = File.ReadAllBytes(assemblyPath);
string pdbFileName = Path.GetFileNameWithoutExtension(assemblyPath) + ".pdb";
byte[] pdbData = File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(assemblyPath), pdbFileName));
InMemoryAssembly = new InMemoryAssembly(peData, pdbData);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment