You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
6.8 KiB

// ----------------------------------------------------------------------------
// <copyright file="PhotonViewHandler.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// This is a Editor script to initialize PhotonView components.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
namespace Photon.Pun
{
using System.Collections.Generic;
using Realtime;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;
[InitializeOnLoad]
public class PhotonViewHandler : EditorWindow
{
static PhotonViewHandler()
{
// called once per change (per key-press in inspectors) and once after play-mode ends.
#if (UNITY_2018 || UNITY_2018_1_OR_NEWER)
EditorApplication.hierarchyChanged += OnHierarchyChanged;
#else
EditorApplication.hierarchyWindowChanged += OnHierarchyChanged;
#endif
}
internal static void OnHierarchyChanged()
{
// set prefabs to viewID 0 if needed
// organize resource PVs in a list per viewID
// process the lists: if more than one photonView is in a list, we have to resolve the clash
// check if only one view had the viewId earlier
// apply a new viewID to the others
// update the cached list of instances and their viewID
//Debug.LogWarning("OnHierarchyChanged(). isPlaying: " + Application.isPlaying);
if (Application.isPlaying)
{
return;
}
PhotonView[] photonViewResources = Resources.FindObjectsOfTypeAll<PhotonView>();
List<PhotonView> photonViewInstances = new List<PhotonView>();
Dictionary<int, List<PhotonView>> viewInstancesPerViewId = new Dictionary<int, List<PhotonView>>();
List<PhotonView> photonViewsToReassign = new List<PhotonView>();
foreach (PhotonView view in photonViewResources)
{
if (PhotonEditorUtils.IsPrefab(view.gameObject))
{
// prefabs should use 0 as ViewID and sceneViewId
if (view.ViewID != 0 || view.sceneViewId != 0)
{
view.ViewID = 0;
view.sceneViewId = 0;
EditorUtility.SetDirty(view);
}
continue; // skip prefabs in further processing
}
photonViewInstances.Add(view);
// assign a new viewID if the viewId is lower than the minimum for this scene
if (!IsViewIdOkForScene(view))
{
photonViewsToReassign.Add(view);
continue; // this view definitely gets cleaned up, so it does not count versus duplicates, checked below
}
// organize the viewInstances into lists per viewID, so we know duplicate usage
if (!viewInstancesPerViewId.ContainsKey(view.sceneViewId))
{
viewInstancesPerViewId[view.sceneViewId] = new List<PhotonView>();
}
viewInstancesPerViewId[view.sceneViewId].Add(view);
}
//Debug.Log("PreviousAssignments: "+PunSceneViews.Instance.Views.Count);
foreach (List<PhotonView> list in viewInstancesPerViewId.Values)
{
if (list.Count <= 1)
{
continue; // skip lists with just one entry (the viewID is unique)
}
PhotonView previousAssignment = null;
bool wasAssigned = PunSceneViews.Instance.Views.TryGetValue(list[0].sceneViewId, out previousAssignment);
foreach (PhotonView view in list)
{
if (wasAssigned && view.Equals(previousAssignment))
{
// previously, we cached the used viewID as assigned to the current view. we don't change this.
continue;
}
//Debug.LogWarning("View to reassign due to viewID: "+view, view.gameObject);
photonViewsToReassign.Add(view);
}
}
int i;
foreach (PhotonView view in photonViewsToReassign)
{
i = MinSceneViewId(view);
while (viewInstancesPerViewId.ContainsKey(i))
{
i++;
}
view.sceneViewId = i;
viewInstancesPerViewId.Add(i, null); // we don't need the lists anymore but we care about getting the viewIDs listed
EditorUtility.SetDirty(view);
}
// update the "semi persistent" list of viewIDs and their PhotonViews
PunSceneViews.Instance.Views.Clear();
foreach (PhotonView view in photonViewInstances)
{
if (PunSceneViews.Instance.Views.ContainsKey(view.sceneViewId))
{
Debug.LogError("ViewIDs should no longer have duplicates! "+view.sceneViewId, view);
continue;
}
PunSceneViews.Instance.Views[view.sceneViewId] = view;
}
//Debug.Log("photonViewsToReassign.Count: "+photonViewsToReassign.Count + " count of viewIDs in use: "+viewInstancesPerViewId.Values.Count);
//Debug.Log("PreviousAssignments now counts: "+PunSceneViews.Instance.Views.Count);
}
private static int MinSceneViewId(PhotonView view)
{
int result = PunSceneSettings.MinViewIdForScene(view.gameObject.scene.name);
return result;
}
private static bool IsViewIdOkForScene(PhotonView view)
{
return view.sceneViewId >= MinSceneViewId(view);
}
}
/// <summary>
/// Stores a PhotonView instances per viewId (key). Instance is used as cache storage in-Editor.
/// </summary>
public class PunSceneViews : ScriptableObject
{
[SerializeField]
public Dictionary<int, PhotonView> Views = new Dictionary<int, PhotonView>();
private static PunSceneViews instanceField;
public static PunSceneViews Instance
{
get
{
if (instanceField != null)
{
return instanceField;
}
instanceField = GameObject.FindObjectOfType<PunSceneViews>();
if (instanceField == null)
{
instanceField = ScriptableObject.CreateInstance<PunSceneViews>();
}
return instanceField;
}
}
}
}