internal static void SetBehaviourVersion(UdonBehaviour behaviour, UdonSharpBehaviourVersion version) { UdonSharpBehaviourVersion lastVer = GetBehaviourVersion(behaviour); if (lastVer == version && lastVer != UdonSharpBehaviourVersion.V0) { return; } bool setVer = behaviour.publicVariables.TrySetVariableValue <int>(UDONSHARP_BEHAVIOUR_VERSION_KEY, (int)version); if (!setVer) { behaviour.publicVariables.RemoveVariable(UDONSHARP_BEHAVIOUR_VERSION_KEY); IUdonVariable newVar = new UdonVariable <int>(UDONSHARP_BEHAVIOUR_VERSION_KEY, (int)version); setVer = behaviour.publicVariables.TryAddVariable(newVar); } if (setVer) { UdonSharpUtils.SetDirty(behaviour); return; } UdonSharpUtils.LogError("Could not set version variable"); }
internal static void SetSceneBehaviourUpgraded(UdonBehaviour behaviour) { if (!PrefabUtility.IsPartOfPrefabInstance(behaviour) && !PrefabUtility.IsPartOfPrefabAsset(behaviour)) { return; } if (!behaviour.publicVariables.TrySetVariableValue <bool>(UDONSHARP_SCENE_BEHAVIOUR_UPGRADE_MARKER, true)) { behaviour.publicVariables.RemoveVariable(UDONSHARP_SCENE_BEHAVIOUR_UPGRADE_MARKER); IUdonVariable newVar = new UdonVariable <bool>(UDONSHARP_SCENE_BEHAVIOUR_UPGRADE_MARKER, true); behaviour.publicVariables.TryAddVariable(newVar); } UdonSharpUtils.SetDirty(behaviour); }
private static void RunBehaviourSetup(UdonSharpBehaviour behaviour, bool withUndo) { UdonBehaviour backingBehaviour = GetBackingUdonBehaviour(behaviour); // Handle components pasted across different behaviours if (backingBehaviour && backingBehaviour.gameObject != behaviour.gameObject) { backingBehaviour = null; } // Handle pasting components on the same behaviour, assumes pasted components are always the last in the list. if (backingBehaviour) { int refCount = 0; UdonSharpBehaviour[] behaviours = backingBehaviour.GetComponents <UdonSharpBehaviour>(); foreach (UdonSharpBehaviour udonSharpBehaviour in behaviours) { if (GetBackingUdonBehaviour(udonSharpBehaviour) == backingBehaviour) { refCount++; } } if (refCount > 1 && behaviour == behaviours.Last()) { backingBehaviour = null; } } bool isPartOfPrefabInstance = PrefabUtility.IsPartOfPrefabInstance(behaviour) && PrefabUtility.GetCorrespondingObjectFromSource(behaviour) != behaviour; if (backingBehaviour == null) { if (isPartOfPrefabInstance) { UdonSharpUtils.LogWarning("Cannot setup behaviour on prefab instance, original prefab asset needs setup"); return; } SetIgnoreEvents(true); try { backingBehaviour = withUndo ? Undo.AddComponent <UdonBehaviour>(behaviour.gameObject) : behaviour.gameObject.AddComponent <UdonBehaviour>(); #pragma warning disable CS0618 // Type or member is obsolete backingBehaviour.SynchronizePosition = false; backingBehaviour.AllowCollisionOwnershipTransfer = false; #pragma warning restore CS0618 // Type or member is obsolete MoveComponentRelativeToComponent(backingBehaviour, behaviour, false); SetBackingUdonBehaviour(behaviour, backingBehaviour); SetBehaviourVersion(backingBehaviour, UdonSharpBehaviourVersion.CurrentVersion); SetSceneBehaviourUpgraded(backingBehaviour); // UdonSharpUtils.Log($"Created behaviour {backingBehaviour}", behaviour); } finally { SetIgnoreEvents(false); } _proxyBehaviourLookup.Add(backingBehaviour, behaviour); UdonSharpUtils.SetDirty(behaviour); UdonSharpUtils.SetDirty(backingBehaviour); } // Handle U# behaviours that have been added to a prefab via Added Component > Apply To Prefab, but have not had their backing behaviour added // if (isPartOfPrefabInstance && // backingBehaviour != null && // !PrefabUtility.IsPartOfPrefabInstance(backingBehaviour)) // { // PropertyModification[] modifications = PrefabUtility.GetPropertyModifications(behaviour); // // if (modifications != null) // { // // } // } UdonSharpProgramAsset programAsset = GetUdonSharpProgramAsset(behaviour); if (backingBehaviour.programSource == null) { backingBehaviour.programSource = programAsset; if (backingBehaviour.programSource == null) { UdonSharpUtils.LogError($"Unable to find valid U# program asset associated with script '{behaviour}'", behaviour); } UdonSharpUtils.SetDirty(backingBehaviour); } if (_serializedProgramAssetField.GetValue(backingBehaviour) == null) { SerializedObject componentAsset = new SerializedObject(backingBehaviour); SerializedProperty serializedProgramAssetProperty = componentAsset.FindProperty("serializedProgramAsset"); serializedProgramAssetProperty.objectReferenceValue = programAsset.SerializedProgramAsset; if (withUndo) { componentAsset.ApplyModifiedProperties(); } else { componentAsset.ApplyModifiedPropertiesWithoutUndo(); } } if (backingBehaviour.enabled != behaviour.enabled) { if (withUndo) { Undo.RecordObject(backingBehaviour, "Enabled change"); } backingBehaviour.enabled = behaviour.enabled; if (!withUndo) { UdonSharpUtils.SetDirty(backingBehaviour); } } #if UDONSHARP_DEBUG backingBehaviour.hideFlags &= ~HideFlags.HideInInspector; #else backingBehaviour.hideFlags |= HideFlags.HideInInspector; #endif ((UdonSharpProgramAsset)backingBehaviour.programSource)?.UpdateProgram(); }
internal static void UpgradeSceneBehaviours(IEnumerable <UdonBehaviour> behaviours) { if (EditorApplication.isPlaying) { return; } // Create proxies if they do not exist foreach (UdonBehaviour udonBehaviour in behaviours) { if (!IsUdonSharpBehaviour(udonBehaviour)) { continue; } if (PrefabUtility.IsPartOfPrefabInstance(udonBehaviour) && PrefabUtility.IsAddedComponentOverride(udonBehaviour)) { continue; } if (GetProxyBehaviour(udonBehaviour) == null) { if (PrefabUtility.IsPartOfPrefabInstance(udonBehaviour) && PrefabUtility.GetCorrespondingObjectFromSource(udonBehaviour) != udonBehaviour) { UdonSharpUtils.LogError($"Cannot upgrade scene behaviour '{udonBehaviour}' since its prefab must be upgraded.", udonBehaviour); continue; } Type udonSharpBehaviourType = GetUdonSharpBehaviourType(udonBehaviour); if (!udonSharpBehaviourType.IsSubclassOf(typeof(UdonSharpBehaviour))) { UdonSharpUtils.LogError($"Class script referenced by program asset '{udonBehaviour.programSource}' is not an UdonSharpBehaviour", udonBehaviour.programSource); continue; } UdonSharpBehaviour newProxy = (UdonSharpBehaviour)udonBehaviour.gameObject.AddComponent(udonSharpBehaviourType); newProxy.enabled = udonBehaviour.enabled; SetBackingUdonBehaviour(newProxy, udonBehaviour); if (!PrefabUtility.IsAddedComponentOverride(udonBehaviour)) { MoveComponentRelativeToComponent(newProxy, udonBehaviour, true); } else { UdonSharpUtils.LogWarning($"Cannot reorder internal UdonBehaviour for '{udonBehaviour}' during upgrade because it is on a prefab instance.", udonBehaviour.gameObject); } UdonSharpUtils.SetDirty(newProxy); } if (GetBehaviourVersion(udonBehaviour) == UdonSharpBehaviourVersion.V0) { SetBehaviourVersion(udonBehaviour, UdonSharpBehaviourVersion.V0DataUpgradeNeeded); } } // Copy data over from UdonBehaviour to UdonSharpBehaviour foreach (UdonBehaviour udonBehaviour in behaviours) { if (!IsUdonSharpBehaviour(udonBehaviour)) { continue; } bool needsPrefabInstanceUpgrade = false; // Checks if the version is below V1 or if it needs the prefab instance upgrade UdonSharpBehaviourVersion behaviourVersion = GetBehaviourVersion(udonBehaviour); if (behaviourVersion >= UdonSharpBehaviourVersion.V1) { // Check if the prefab instance has a prefab that was upgraded causing the string data to be copied, but has a delta'd UnityEngine.Object storage array if (PrefabUtility.IsPartOfPrefabInstance(udonBehaviour) && !HasSceneBehaviourUpgradeFlag(udonBehaviour)) { UdonBehaviour prefabSource = PrefabUtility.GetCorrespondingObjectFromSource(udonBehaviour); if (prefabSource && BehaviourRequiresBackwardsCompatibilityPersistence(prefabSource)) { PropertyModification[] modifications = PrefabUtility.GetPropertyModifications(udonBehaviour); if (modifications != null && modifications.Any(e => e.propertyPath.StartsWith("publicVariablesUnityEngineObjects", StringComparison.Ordinal))) { needsPrefabInstanceUpgrade = true; } } } if (!needsPrefabInstanceUpgrade) { continue; } } UdonSharpBehaviour proxy = GetProxyBehaviour(udonBehaviour); if (proxy == null) { UdonSharpUtils.LogWarning($"UdonSharpBehaviour '{udonBehaviour}' could not be upgraded since it is missing a proxy", udonBehaviour); continue; } CopyUdonToProxy(proxy, ProxySerializationPolicy.RootOnly); // Nuke out old data now because we want only the C# side to own the data from this point on ClearBehaviourVariables(udonBehaviour, true); SetBehaviourVersion(udonBehaviour, UdonSharpBehaviourVersion.V1); SetSceneBehaviourUpgraded(udonBehaviour); if (needsPrefabInstanceUpgrade) { UdonSharpUtils.Log($"Scene behaviour '{udonBehaviour.name}' needed UnityEngine.Object upgrade pass", udonBehaviour); } UdonSharpUtils.SetDirty(proxy); UdonSharpUtils.Log($"Upgraded scene behaviour '{udonBehaviour.name}'", udonBehaviour); } }