예제 #1
0
        public void AssembleCsProgram(uint heapSize)
        {
            // The heap size is determined by the symbol count + the unique extern string count
            UdonSharp.HeapFactory heapFactory        = new UdonSharp.HeapFactory(heapSize);
            UdonEditorInterface   assemblerInterface = new UdonEditorInterface(null, heapFactory, null, null, null, null, null, null, null);

            assemblerInterface.AddTypeResolver(new UdonBehaviourTypeResolver());

            FieldInfo assemblyError = typeof(UdonAssemblyProgramAsset).GetField("assemblyError", BindingFlags.NonPublic | BindingFlags.Instance);

            try
            {
                program = assemblerInterface.Assemble(udonAssembly);
                assemblyError.SetValue(this, null);

                hasInteractEvent = false;

                foreach (string entryPoint in program.EntryPoints.GetExportedSymbols())
                {
                    if (entryPoint == "_interact")
                    {
                        hasInteractEvent = true;
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                program = null;
                assemblyError.SetValue(this, e.Message);
                Debug.LogException(e);
            }
        }
        private UdonEditorManager()
        {
            _udonEditorInterface = new UdonEditorInterface();
            _udonEditorInterface.AddTypeResolver(new UdonBehaviourTypeResolver());

            EditorSceneManager.sceneOpened         += OnSceneOpened;
            EditorSceneManager.sceneSaving         += OnSceneSaving;
            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
        }
예제 #3
0
        /// <summary>
        /// В typesForResolver надо передавать как минимум {"VRCUdonUdonBehaviour", typeof(UdonBehaviour)}
        /// </summary>
        public static DoshikNodeDefinition[] GetAllNodeDefinitions(IDictionary <string, Type> typesForResolver)
        {
            var udonEditorInterface = new UdonEditorInterface();

            udonEditorInterface.AddTypeResolver(new AnyTypeResolver(typesForResolver));

            var rootRegistries = udonEditorInterface.GetNodeRegistries();

            return(GetNodeDefinitions(rootRegistries.Values, new INodeRegistry[0]).ToArray());
        }
        private UdonEditorManager()
        {
            _udonEditorInterface = new Lazy <UdonEditorInterface>(() =>
            {
                var editorInterface = new UdonEditorInterface();
                editorInterface.AddTypeResolver(new UdonBehaviourTypeResolver());

                return(editorInterface);
            });

            // Async init the editor interface to avoid 1+ second delay added to assembly reload.
            Task.Run(() =>
            {
                var _ = _udonEditorInterface.Value;
            });

            EditorSceneManager.sceneOpened         += OnSceneOpened;
            EditorSceneManager.sceneSaving         += OnSceneSaving;
            EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
        }
예제 #5
0
        internal bool AssembleCsProgram(uint heapSize)
        {
            if (editorInterfaceInstance == null || heapFactoryInstance == null)
            {
                // The heap size is determined by the symbol count + the unique extern string count
                heapFactoryInstance     = new UdonSharp.HeapFactory();
                editorInterfaceInstance = new UdonEditorInterface(null, heapFactoryInstance, null, null, null, null, null, null, null);
                editorInterfaceInstance.AddTypeResolver(new UdonBehaviourTypeResolver()); // todo: can be removed with SDK's >= VRCSDK-UDON-2020.06.15.14.08_Public
            }

            heapFactoryInstance.FactoryHeapSize = heapSize;

            FieldInfo assemblyError = typeof(UdonAssemblyProgramAsset).GetField("assemblyError", BindingFlags.NonPublic | BindingFlags.Instance);

            try
            {
                program = editorInterfaceInstance.Assemble(udonAssembly);
                assemblyError.SetValue(this, null);

                hasInteractEvent = false;

                foreach (string entryPoint in program.EntryPoints.GetExportedSymbols())
                {
                    if (entryPoint == "_interact")
                    {
                        hasInteractEvent = true;
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                program = null;
                assemblyError.SetValue(this, e.Message);
                Debug.LogException(e);

                return(false);
            }

            return(true);
        }
        public void AssembleCsProgram(uint heapSize)
        {
            // The heap size is determined by the symbol count + the unique extern string count
            UdonSharp.HeapFactory heapFactory        = new UdonSharp.HeapFactory(heapSize);
            UdonEditorInterface   assemblerInterface = new UdonEditorInterface(null, heapFactory, null, null, null, null, null, null, null);

            assemblerInterface.AddTypeResolver(new UdonBehaviourTypeResolver());

            FieldInfo assemblyError = typeof(UdonAssemblyProgramAsset).GetField("assemblyError", BindingFlags.NonPublic | BindingFlags.Instance);

            try
            {
                program = assemblerInterface.Assemble(udonAssembly);
                assemblyError.SetValue(this, null);
            }
            catch (Exception e)
            {
                program = null;
                assemblyError.SetValue(this, e.Message);
                Debug.LogException(e);
            }
        }
        public static UdonAssemblyProgramAsset UdonSharpProgramToAssemblyProgram(UdonSharpProgramAsset udonSharpProgramAsset, string savePath)
        {
            if (EditorApplication.isPlaying)
            {
                throw new System.NotSupportedException("USharpEditorUtility.UdonSharpProgramToAssemblyProgram() cannot be called in play mode");
            }

            UdonAssemblyProgramAsset newProgramAsset = ScriptableObject.CreateInstance <UdonAssemblyProgramAsset>();

            AssetDatabase.CreateAsset(newProgramAsset, savePath);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);

            newProgramAsset = AssetDatabase.LoadAssetAtPath <UdonAssemblyProgramAsset>(savePath);

            udonSharpProgramAsset.CompileCsProgram();

            string programAssembly = UdonSharpEditorCache.Instance.GetUASMStr(udonSharpProgramAsset);

            // Strip comments/inline code
            StringBuilder asmBuilder = new StringBuilder();

            using (StringReader reader = new StringReader(programAssembly))
            {
                string line = reader.ReadLine();

                while (line != null)
                {
                    if (!string.IsNullOrWhiteSpace(line) &&
                        !line.TrimStart().StartsWith("#", System.StringComparison.Ordinal))
                    {
                        asmBuilder.AppendFormat("{0}\n", line);
                    }

                    line = reader.ReadLine();
                }
            }

            programAssembly = asmBuilder.ToString();

            FieldInfo assemblyField = typeof(UdonAssemblyProgramAsset).GetField("udonAssembly", BindingFlags.NonPublic | BindingFlags.Instance);

            assemblyField.SetValue(newProgramAsset, programAssembly);

            IUdonProgram program = null;

            try
            {
                UdonSharp.HeapFactory heapFactory = new UdonSharp.HeapFactory();

                UdonEditorInterface editorInterface = new UdonEditorInterface(null, heapFactory, null, null, null, null, null, null, null);
                heapFactory.FactoryHeapSize = udonSharpProgramAsset.GetSerializedUdonProgramAsset().RetrieveProgram().Heap.GetHeapCapacity();

                program = editorInterface.Assemble(programAssembly);
            }
            catch (System.Exception e)
            {
                Debug.LogError(e);

                return(null);
            }

            FieldInfo assemblyProgramField = typeof(UdonProgramAsset).GetField("program", BindingFlags.NonPublic | BindingFlags.Instance);

            assemblyProgramField.SetValue(newProgramAsset, program);

            IUdonProgram uSharpProgram   = udonSharpProgramAsset.GetRealProgram();
            IUdonProgram assemblyProgram = (IUdonProgram)assemblyProgramField.GetValue(newProgramAsset);

            if (uSharpProgram == null || assemblyProgram == null)
            {
                return(null);
            }

            ImmutableArray <string> symbols = uSharpProgram.SymbolTable.GetSymbols();

            foreach (string symbol in symbols)
            {
                uint        symbolAddress = uSharpProgram.SymbolTable.GetAddressFromSymbol(symbol);
                System.Type symbolType    = uSharpProgram.Heap.GetHeapVariableType(symbolAddress);
                object      symbolValue   = uSharpProgram.Heap.GetHeapVariable(symbolAddress);

                assemblyProgram.Heap.SetHeapVariable(assemblyProgram.SymbolTable.GetAddressFromSymbol(symbol), symbolValue, symbolType);
            }

            EditorUtility.SetDirty(newProgramAsset);

            newProgramAsset.SerializedProgramAsset.StoreProgram(assemblyProgram);
            EditorUtility.SetDirty(newProgramAsset.SerializedProgramAsset);

            AssetDatabase.SaveAssets();

            // This doesn't work unfortunately due to how Udon tries to locate the serialized asset when importing an assembly
            //string serializedAssetPath = $"{Path.GetDirectoryName(savePath)}/{Path.GetFileNameWithoutExtension(savePath)}_serialized.asset";

            //AssetDatabase.MoveAsset(AssetDatabase.GetAssetPath(newProgramAsset.SerializedProgramAsset), serializedAssetPath);
            //AssetDatabase.SaveAssets();

            return(newProgramAsset);
        }