private Dictionary <int, RealtimeView> CreateChildViewMap() { Dictionary <int, RealtimeView> childViewMap = new Dictionary <int, RealtimeView>(); // Loop through all child views, ignore invalid ones. foreach (RealtimeViewChildIDViewPair pair in _childViews) { int viewID = pair.viewID; RealtimeView view = pair.view; // Check for valid view ID (greater than zero) // TODO: We need to verify the upper bound limit on viewIDs too if (viewID <= 0) { Debug.LogError("RealtimeView child views must have an ID of 1 or greater. Skipping view: (" + viewID + ":" + view + ")", view); continue; } // Check for duplicate if (childViewMap.Remove(viewID)) { Debug.LogError("Found duplicate child view ID (" + viewID + "). Skipping both views to avoid data corruption.", view); continue; } childViewMap.Add(viewID, view); } return(childViewMap); }
private void CreateComponentsModelAndChildViewsModelIfNeeded(string prefabName) { // Load the prefab GameObject prefab = Resources.Load <GameObject>(prefabName); if (prefab == null) { Debug.LogError("Attempting to instantiate prefab from datastore. Failed to find prefab \"" + prefabName + "\". Make sure it's in a Resources folder. Bailing."); return; } // Get the RealtimeView script at the root RealtimeView prefabRealtimeView = prefab.GetComponent <RealtimeView>(); if (prefabRealtimeView == null) { Debug.LogError("Attempting to instantiate prefab from datastore. Failed to find RealtimeView component on prefab \"" + prefabName + "\". Make sure the prefab has a RealtimeView script at the root level. Bailing."); return; } if (_componentsModel == null) { _componentsModel = prefabRealtimeView._CreateComponentsModel(); } if (_childViewsModel == null) { _childViewsModel = prefabRealtimeView._CreateChildViewsModel(); } }
private RealtimeViewComponentsModel CreateChildViewsModel(Dictionary <int, RealtimeView> childViewMap) { // Create models for all views Dictionary <int, IModel> childViewModelMap = new Dictionary <int, IModel>(); foreach (KeyValuePair <int, RealtimeView> pair in childViewMap) { int viewID = pair.Key; RealtimeView view = pair.Value; if (view == null) { // Note: Deprecated view IDs will have a null view property. This is normal and they can be safely ignored. continue; } // Create model RealtimeViewModel viewModel = view._CreateChildViewModel(); if (viewModel == null) { Debug.LogError("Model supplied by child RealtimeView is null. Skipping view: (" + viewID + ":" + view + ")", view); continue; } // Set model childViewModelMap[viewID] = viewModel; } // Create RealtimeViewComponentsModel RealtimeViewComponentsModel childViewsModel = new RealtimeViewComponentsModel(childViewModelMap); return(childViewsModel); }
private static void RemoveChildViewFromParentViewList(RealtimeView parentView, RealtimeView childView) { // Remove from parent view's childViews list. SerializedObject parentViewSerializedObject = new SerializedObject(parentView); parentViewSerializedObject.Update(); SerializedProperty childViewsProperty = parentViewSerializedObject.FindProperty("_childViews"); int numberOfChildViews = childViewsProperty.arraySize; // Check for child view in the list for (int i = 0; i < numberOfChildViews; i++) { SerializedProperty childViewProperty = childViewsProperty.GetArrayElementAtIndex(i); SerializedProperty childViewViewProperty = childViewProperty.FindPropertyRelative("view"); SerializedProperty childViewViewToUseIfMovedBackProperty = childViewProperty.FindPropertyRelative("viewToUseIfMovedBack"); RealtimeView view = childViewViewProperty.objectReferenceValue as RealtimeView; // If the view exists, clear it out. if (view == childView) { // Clear view property childViewViewProperty.objectReferenceValue = null; // Store a reference so if the view is moved back, it gets assigned to the same View ID childViewViewToUseIfMovedBackProperty.objectReferenceValue = childView; } } parentViewSerializedObject.ApplyModifiedPropertiesWithoutUndo(); }
public static void _ConfigureRealtimeView(RealtimeView realtimeView) { GameObject[] sceneRootGameObjects = SceneManager.GetActiveScene().GetRootGameObjects(); Realtime[] realtimeInstances = sceneRootGameObjects.SelectMany(i => i.GetComponentsInChildren <Realtime>()).ToArray(); bool didWarnAboutRealtimeInstancesBeingTooFewOrTooMany = false; ConfigureRealtimeView(realtimeView, realtimeInstances, ref didWarnAboutRealtimeInstancesBeingTooFewOrTooMany); }
void Start() { _rt = GetComponentInParent <Normal.Realtime.RealtimeTransform>(); _rv = GetComponentInParent <Normal.Realtime.RealtimeView>(); //_rv.RequestOwnership(); //Debug.Log("realtime.clientID is " + _rt.ownerID); objMats = this.gameObject.GetComponent <Renderer>().materials; if (_rt != null) { //set the player number to the matching material number if (_rt.ownerID < avatarMats.Length && _rt.ownerID >= -1) { //Debug.Log(_rt.ownerID + 1); objMats[matSlot] = avatarMats[_rt.ownerID + 1]; } //but if we have more players than materials, than cycle back around else { objMats[matSlot] = avatarMats[_rt.ownerID % avatarMats.Length]; } //don't forget to tell this object to now use our new materials this.gameObject.GetComponent <Renderer>().materials = objMats; //Debug.Log("clientID is " + _rv.realtime.clientID); } if (_rt == null && _rv != null) { //set the player number to the matching material number if (_rv.ownerID < avatarMats.Length && _rv.ownerID >= -1) { //Debug.Log(_rt.ownerID + 1); objMats[matSlot] = avatarMats[_rv.ownerID + 1]; } //but if we have more players than materials, than cycle back around else { objMats[matSlot] = avatarMats[_rv.ownerID % avatarMats.Length]; } //don't forget to tell this object to now use our new materials this.gameObject.GetComponent <Renderer>().materials = objMats; //Debug.Log("clientID is " + _rv.realtime.clientID); } /* * if (_rt == null && _rv == null) * { * * } */ }
static RealtimeView AddRealtimeViewComponentIfNeeded(GameObject gameObject) { RealtimeView realtimeView = gameObject.GetComponent <RealtimeView>(); if (realtimeView == null) { realtimeView = gameObject.AddComponent <RealtimeView>(); // Collapse inspector SetComponentInspectorExpanded(realtimeView, false); } return(realtimeView); }
private static RealtimeView FindParentRealtimeViewForTransform(Transform realtimeViewTransform) { Transform parent = realtimeViewTransform.parent; if (parent == null) { return(null); } RealtimeView realtimeView = parent.GetComponent <RealtimeView>(); if (realtimeView != null) { return(realtimeView); } return(FindParentRealtimeViewForTransform(parent)); }
private static void AddComponentToViewListIfNeeded(RealtimeView view, RealtimeComponent componentToAdd) { // Add to view's components list. SerializedObject viewSerializedObject = new SerializedObject(view); viewSerializedObject.Update(); SerializedProperty componentsProperty = viewSerializedObject.FindProperty("_components"); int numberOfComponents = componentsProperty.arraySize; // Check for component in the list int largestComponentID = 0; for (int i = 0; i < numberOfComponents; i++) { SerializedProperty componentProperty = componentsProperty.GetArrayElementAtIndex(i); SerializedProperty componentComponentIDProperty = componentProperty.FindPropertyRelative("componentID"); SerializedProperty componentComponentProperty = componentProperty.FindPropertyRelative("component"); MonoBehaviour component = componentComponentProperty.objectReferenceValue as MonoBehaviour; // If the component exists, we're done. if (component == componentToAdd) { return; } int componentID = componentComponentIDProperty.intValue; if (componentID > largestComponentID) { largestComponentID = componentID; } } // Not found. Add to list. int componentIndex = numberOfComponents; int nextAvailableComponentID = largestComponentID + 1; componentsProperty.InsertArrayElementAtIndex(componentIndex); SerializedProperty newComponentProperty = componentsProperty.GetArrayElementAtIndex(componentIndex); newComponentProperty.FindPropertyRelative("componentID").intValue = nextAvailableComponentID; newComponentProperty.FindPropertyRelative("component").objectReferenceValue = componentToAdd; newComponentProperty.FindPropertyRelative("componentIDHasBeenUsed").boolValue = true; viewSerializedObject.ApplyModifiedPropertiesWithoutUndo(); }
static void AddComponentToRealtimeViewIfNeeded(RealtimeView realtimeView, Component component) { SerializedObject realtimeViewSerializedObject = new SerializedObject(realtimeView); realtimeViewSerializedObject.Update(); SerializedProperty realtimeViewComponentsProperty = realtimeViewSerializedObject.FindProperty("_components"); // Check if the component already exists on the RealtimeView int numberOfProperties = realtimeViewComponentsProperty.arraySize; int largestPropertyIDSeen = 0; for (int i = 0; i < numberOfProperties; i++) { SerializedProperty realtimeViewComponentProperty = realtimeViewComponentsProperty.GetArrayElementAtIndex(i); SerializedProperty realtimeViewComponentComponentIDProperty = realtimeViewComponentProperty.FindPropertyRelative("componentID"); SerializedProperty realtimeViewComponentComponentProperty = realtimeViewComponentProperty.FindPropertyRelative("component"); // Record the property ID largestPropertyIDSeen = realtimeViewComponentComponentIDProperty.intValue; // We found the component. We're done. if (realtimeViewComponentComponentProperty.objectReferenceValue == component) { return; } } // Component not found, add it. int newPropertyIndex = realtimeViewComponentsProperty.arraySize; realtimeViewComponentsProperty.InsertArrayElementAtIndex(newPropertyIndex); SerializedProperty realtimeViewNewComponentProperty = realtimeViewComponentsProperty.GetArrayElementAtIndex(newPropertyIndex); SerializedProperty realtimeViewNewComponentComponentIDProperty = realtimeViewNewComponentProperty.FindPropertyRelative("componentID"); SerializedProperty realtimeViewNewComponentComponentProperty = realtimeViewNewComponentProperty.FindPropertyRelative("component"); realtimeViewNewComponentComponentIDProperty.intValue = largestPropertyIDSeen + 1; realtimeViewNewComponentComponentProperty.objectReferenceValue = component; realtimeViewSerializedObject.ApplyModifiedProperties(); }
void CreateAvatarPrefab() { GameObject gameObject = realtimeAvatar.gameObject; //// Root // RealtimeView RealtimeView rootRealtimeView = AddRealtimeViewComponentIfNeeded(gameObject); // RealtimeAvatar AddComponentToRealtimeViewIfNeeded(rootRealtimeView, realtimeAvatar); // RealtimeTransform RealtimeTransform rootRealtimeTransform = AddRealtimeTransformComponentIfNeeded(gameObject, true); AddComponentToRealtimeViewIfNeeded(rootRealtimeView, rootRealtimeTransform); //// Head Transform head = CreateGameObjectForPropertyIfNeeded(headProperty, gameObject.transform, "Head", new Type[] { typeof(Examples.VoiceScale) }); // RealtimeView RealtimeView headRealtimeView = AddRealtimeViewComponentIfNeeded(head.gameObject); // RealtimeTransform RealtimeTransform headRealtimeTransform = AddRealtimeTransformComponentIfNeeded(head.gameObject, false); AddComponentToRealtimeViewIfNeeded(headRealtimeView, headRealtimeTransform); // RealtimeAvatarVoice RealtimeAvatarVoice headRealtimeAvatarVoice = head.gameObject.GetComponent <RealtimeAvatarVoice>(); if (headRealtimeAvatarVoice == null) { headRealtimeAvatarVoice = head.gameObject.AddComponent <RealtimeAvatarVoice>(); // Collapse inspector SetComponentInspectorExpanded(headRealtimeAvatarVoice, false); } AddComponentToRealtimeViewIfNeeded(headRealtimeView, headRealtimeAvatarVoice); //// Left Hand Transform leftHand = CreateGameObjectForPropertyIfNeeded(leftHandProperty, gameObject.transform, "Left Hand"); // RealtimeView RealtimeView leftHandRealtimeView = AddRealtimeViewComponentIfNeeded(leftHand.gameObject); // RealtimeTransform RealtimeTransform leftHandRealtimeTransform = AddRealtimeTransformComponentIfNeeded(leftHand.gameObject, false); AddComponentToRealtimeViewIfNeeded(leftHandRealtimeView, leftHandRealtimeTransform); //// Right Hand Transform rightHand = CreateGameObjectForPropertyIfNeeded(rightHandProperty, gameObject.transform, "Right Hand"); // RealtimeView RealtimeView rightHandRealtimeView = AddRealtimeViewComponentIfNeeded(rightHand.gameObject); // RealtimeTransform RealtimeTransform rightHandRealtimeTransform = AddRealtimeTransformComponentIfNeeded(rightHand.gameObject, false); AddComponentToRealtimeViewIfNeeded(rightHandRealtimeView, rightHandRealtimeTransform); }
private void SetModel(RealtimeViewModel model) { if (model == _model) { return; } if (_model != null) { _model._SetRealtimeView(null); } _model = model; if (_model != null) { _model._SetRealtimeView(this); Dictionary <int, Tuple <Component, MethodInfo, PropertyInfo, PropertyInfo> > componentMap = CreateComponentMap(); // Create components model if needed (can happen if RealtimeViewModel existed in the datastore but hasn't been linked to a RealtimeView yet) RealtimeViewComponentsModel componentsModel = _model.componentsModel; if (_model.componentsModel == null) { componentsModel = CreateComponentsModel(componentMap); _model.SetComponentsModelAndDeserializeCachedModelsIfNeeded(componentsModel); } // Loop through components and assign models foreach (KeyValuePair <int, Tuple <Component, MethodInfo, PropertyInfo, PropertyInfo> > pair in componentMap) { int componentID = pair.Key; Component component = pair.Value.First; MethodInfo createModelMethod = pair.Value.Second; PropertyInfo modelProperty = pair.Value.Third; PropertyInfo realtimeViewProperty = pair.Value.Fourth; IModel componentModel = componentsModel[componentID]; if (componentModel == null) { Debug.LogError("RealtimeView is attempting to connect a component to its model, but cannot find model for component: (" + componentID + ":" + component + "). This is a bug!", component); continue; } // Set realtime view reference on object if it supports it if (realtimeViewProperty != null) { realtimeViewProperty.SetValue(component, this, null); } // Set model on component modelProperty.SetValue(component, componentModel, null); } Dictionary <int, RealtimeView> childViewMap = CreateChildViewMap(); // Create child views model if needed (can happen if RealtimeViewModel existed in the datastore but hasn't been linked to a RealtimeView yet) RealtimeViewComponentsModel childViewsModel = _model.childViewsModel; if (childViewsModel == null) { childViewsModel = CreateChildViewsModel(childViewMap); _model.SetChildViewsModelAndDeserializeCachedModelsIfNeeded(childViewsModel); } // Loop through child views and assign models foreach (KeyValuePair <int, RealtimeView> pair in childViewMap) { int viewID = pair.Key; RealtimeView view = pair.Value; RealtimeViewModel viewModel = childViewsModel[viewID] as RealtimeViewModel; if (viewModel == null) { Debug.LogError("RealtimeView attempting to connect child view to its models, but cannot find model for view: (" + viewID + ":" + view + "). This is a bug!", view); continue; } // Set realtime instance and model view._SetRealtime(_realtime); view.model = viewModel; } } }
public void _SetRealtimeView(RealtimeView realtimeView) { _realtimeView = realtimeView; }
private static bool AddChildViewToParentViewIfNeeded(RealtimeView childView, SerializedObject childViewSerializedObject) { if (childView == null) { Debug.LogError("Attempting to add null child view to parent view. This is a bug! Bailing..."); return(false); } // Recursively trace up to the parent RealtimeView parentView = FindParentRealtimeViewForTransform(childView.transform); // Remove from previous parentView and update _parentView property. SerializedProperty parentViewSerializedProperty = childViewSerializedObject.FindProperty("_parentView"); RealtimeView oldParentView = parentViewSerializedProperty.objectReferenceValue as RealtimeView; if (parentView != oldParentView) { // We're going to change the parent below. Remove the child view from the old parent view's child view list. if (oldParentView != null) { RemoveChildViewFromParentViewList(oldParentView, childView); } // Set parent property on child view parentViewSerializedProperty.objectReferenceValue = parentView; } // No parent found, this is a root view. if (parentView == null) { return(true); } // Add to parent view's childViews list. SerializedObject parentViewSerializedObject = new SerializedObject(parentView); parentViewSerializedObject.Update(); SerializedProperty childViewsProperty = parentViewSerializedObject.FindProperty("_childViews"); int numberOfChildViews = childViewsProperty.arraySize; // Check for child view in the list int largestViewID = 0; for (int i = 0; i < numberOfChildViews; i++) { SerializedProperty childViewProperty = childViewsProperty.GetArrayElementAtIndex(i); SerializedProperty childViewViewIDProperty = childViewProperty.FindPropertyRelative("viewID"); SerializedProperty childViewViewProperty = childViewProperty.FindPropertyRelative("view"); SerializedProperty childViewViewToUseIfMovedBackProperty = childViewProperty.FindPropertyRelative("viewToUseIfMovedBack"); RealtimeView view = childViewViewProperty.objectReferenceValue as RealtimeView; RealtimeView viewToUseIfMovedBack = childViewViewToUseIfMovedBackProperty.objectReferenceValue as RealtimeView; // If the view exists, we're done. if (view == childView) { return(false); } // If the view has been assigned to this property before, re-assign it and we're done. if (viewToUseIfMovedBack == childView) { childViewViewProperty.objectReferenceValue = childView; parentViewSerializedProperty.objectReferenceValue = parentView; parentViewSerializedObject.ApplyModifiedPropertiesWithoutUndo(); return(false); } int viewID = childViewViewIDProperty.intValue; if (viewID > largestViewID) { largestViewID = viewID; } } // Not found. Add to list. int viewIndex = numberOfChildViews; int nextAvailableViewID = largestViewID + 1; childViewsProperty.InsertArrayElementAtIndex(viewIndex); SerializedProperty newChildViewProperty = childViewsProperty.GetArrayElementAtIndex(viewIndex); newChildViewProperty.FindPropertyRelative("viewID").intValue = nextAvailableViewID; newChildViewProperty.FindPropertyRelative("view").objectReferenceValue = childView; newChildViewProperty.FindPropertyRelative("viewToUseIfMovedBack").objectReferenceValue = childView; newChildViewProperty.FindPropertyRelative("viewIDHasBeenUsed").boolValue = true; parentViewSerializedObject.ApplyModifiedPropertiesWithoutUndo(); return(false); }
public static void _UpdateRealtimeViewSceneViewUUID(RealtimeView realtimeView, byte[] sceneViewUUID) { _rootSceneViewUUIDMap[realtimeView] = sceneViewUUID; }
private static void ConfigureRealtimeView(RealtimeView realtimeView, Realtime[] realtimeInstances, ref bool didWarnAboutRealtimeInstancesBeingTooFewOrTooMany) { SerializedObject realtimeViewSerializedObject = new SerializedObject(realtimeView); realtimeViewSerializedObject.Update(); SerializedProperty realtimeProperty = realtimeViewSerializedObject.FindProperty("_realtime"); SerializedProperty sceneViewUUIDProperty = realtimeViewSerializedObject.FindProperty("_sceneViewUUID"); SerializedProperty isRootPrefabViewProperty = realtimeViewSerializedObject.FindProperty("_isRootPrefabView"); // Realtime Instance Realtime realtime = realtimeProperty.objectReferenceValue as Realtime; bool prefab = EditorUtility.IsPersistent(realtimeView.gameObject); if (prefab) { if (realtime != null) { realtimeProperty.objectReferenceValue = null; } } else { if (realtime == null) { if (realtimeInstances.Length == 1) { realtimeProperty.objectReferenceValue = realtimeInstances[0]; } else if (!didWarnAboutRealtimeInstancesBeingTooFewOrTooMany) { if (realtimeInstances.Length == 0) { Debug.LogWarning("RealtimeView: No instances of Realtime exist in the scene. Make sure to create an instance of Realtime otherwise this scene view will not work!"); } else if (realtimeInstances.Length > 1) { Debug.LogWarning("RealtimeView: There are multiple instances of Realtime in the scene. If you plan to use this as a scene view, wire up a reference to Realtime manually under the Advanced Settings panel on the RealtimeView."); } didWarnAboutRealtimeInstancesBeingTooFewOrTooMany = true; } } } // Add realtime components RealtimeComponent[] components = realtimeView.GetComponents <RealtimeComponent>(); foreach (RealtimeComponent component in components) { AddComponentToViewListIfNeeded(realtimeView, component); } // Add to parent RealtimeView if this is a child view bool isRoot = AddChildViewToParentViewIfNeeded(realtimeView, realtimeViewSerializedObject); byte[] sceneViewUUID = GetSceneViewUUIDAsByteArray(sceneViewUUIDProperty); if (isRoot && !prefab) { // Root scene view // Make sure this root scene view exists in our map. If it does, verify the UUID is set properly. byte[] previouslyAssignedUUID; if (_rootSceneViewUUIDMap.TryGetValue(realtimeView, out previouslyAssignedUUID)) { // If previously assigned UUID doesn't match, reset it. This can happen when clicking Apply on a prefab. // This is because the UUID gets stored on the prefab and cleared on the scene view because it inherits the value from the prefab. // Then this script comes in and clears the UUID on the prefab, which then means the scene view will have no UUID because it's inheriting // from the prefab. We'll detect that here and set it back on the scene view. if (!previouslyAssignedUUID.SequenceEqual(sceneViewUUID)) { // Reset scene view UUID sceneViewUUID = SetSceneViewUUIDUsingByteArray(sceneViewUUIDProperty, previouslyAssignedUUID); } } else { // Set scene UUID if needed if (sceneViewUUID == null || sceneViewUUID.Length == 0) { sceneViewUUID = SetSceneViewUUIDUsingByteArray(sceneViewUUIDProperty, Guid.NewGuid().ToByteArray()); } else { // If this view doesn't exist in the UUID map, but it has a scene view UUID, it's possible it's been copy & pasted. Check the map to see if another scene view has the same UUID. If it does, reset it and log a warning. foreach (KeyValuePair <RealtimeView, byte[]> viewUUIDPair in _rootSceneViewUUIDMap) { RealtimeView view = viewUUIDPair.Key; byte[] viewUUID = viewUUIDPair.Value; if (sceneViewUUID.SequenceEqual(viewUUID) && realtimeView != view && realtimeView.gameObject.scene == view.gameObject.scene) { // If we enter this block, it means there's already a realtime view with this UUID loaded, /and/ it exists in the same scene. // As far as I know, the only way for that to happen is to copy & paste a root scene realtime view. In that case, I think it's ok to reset // the UUID on the copy. And since the original is going to be the one that already exists in the map, that means this one is the copy. // For root scene views that have the same UUID as a view in another scene, we'll log an error below. That can happen when a scene is saved // as a copy, and the copy is additively loaded. In that case, we don't know which view the developer will want to keep so we log the error. Debug.LogWarning("Realtime: Found a RealtimeView in scene with a duplicate UUID. Resetting the UUID on the copy."); sceneViewUUID = SetSceneViewUUIDUsingByteArray(sceneViewUUIDProperty, Guid.NewGuid().ToByteArray()); break; } } } // Add to the map _rootSceneViewUUIDMap[realtimeView] = sceneViewUUID; } } else { // Not root scene view // Clear scene UUID if (sceneViewUUID == null || sceneViewUUID.Length != 0) { // Clear the UUID sceneViewUUID = SetSceneViewUUIDUsingByteArray(sceneViewUUIDProperty, new byte[0]); // Remove from map _rootSceneViewUUIDMap.Remove(realtimeView); } } if (isRoot && prefab) { // Root prefab view // Set isRootPrefabView property if (!isRootPrefabViewProperty.boolValue) { isRootPrefabViewProperty.boolValue = true; } } else { // Not root prefab view // Clear isRootPrefabView property if (isRootPrefabViewProperty.boolValue) { isRootPrefabViewProperty.boolValue = false; } } realtimeViewSerializedObject.ApplyModifiedPropertiesWithoutUndo(); }