public override void OnInspectorGUI()
    {
        this.m_Target = (PhotonView)target;
        bool isProjectPrefab = EditorUtility.IsPersistent(this.m_Target.gameObject);

        if (this.m_Target.ObservedComponents == null)
        {
            this.m_Target.ObservedComponents = new System.Collections.Generic.List <Component>();
        }

        if (this.m_Target.ObservedComponents.Count == 0)
        {
            this.m_Target.ObservedComponents.Add(null);
        }

        EditorGUILayout.BeginHorizontal();
        // Owner
        if (isProjectPrefab)
        {
            EditorGUILayout.LabelField("Owner:", "Set at runtime");
        }
        else if (!this.m_Target.isOwnerActive)
        {
            EditorGUILayout.LabelField("Owner", "Scene");
        }
        else
        {
            PhotonPlayer owner     = this.m_Target.owner;
            string       ownerInfo = (owner != null) ? owner.NickName : "<no PhotonPlayer found>";

            if (string.IsNullOrEmpty(ownerInfo))
            {
                ownerInfo = "<no playername set>";
            }

            EditorGUILayout.LabelField("Owner", "[" + this.m_Target.ownerId + "] " + ownerInfo);
        }

        // ownership requests
        EditorGUI.BeginDisabledGroup(Application.isPlaying);
        OwnershipOption own = (OwnershipOption)EditorGUILayout.EnumPopup(this.m_Target.ownershipTransfer, GUILayout.Width(100));

        if (own != this.m_Target.ownershipTransfer)
        {
            // jf: fixed 5 and up prefab not accepting changes if you quit Unity straight after change.
            // not touching the define nor the rest of the code to avoid bringing more problem than solving.
            EditorUtility.SetDirty(this.m_Target);

            Undo.RecordObject(this.m_Target, "Change PhotonView Ownership Transfer");
            this.m_Target.ownershipTransfer = own;
        }
        EditorGUI.EndDisabledGroup();

        EditorGUILayout.EndHorizontal();


        // View ID
        if (isProjectPrefab)
        {
            EditorGUILayout.LabelField("View ID", "Set at runtime");
        }
        else if (EditorApplication.isPlaying)
        {
            EditorGUILayout.LabelField("View ID", this.m_Target.viewID.ToString());
        }
        else
        {
            int idValue = EditorGUILayout.IntField("View ID [1.." + (PhotonNetworkManager.MAX_VIEW_IDS - 1) + "]", this.m_Target.viewID);
            if (this.m_Target.viewID != idValue)
            {
                Undo.RecordObject(this.m_Target, "Change PhotonView viewID");
                this.m_Target.viewID = idValue;
            }
        }

        // Locally Controlled
        if (EditorApplication.isPlaying)
        {
            string masterClientHint = PhotonNetworkManager.isMasterClient ? "(master)" : "";
            EditorGUILayout.Toggle("Controlled locally: " + masterClientHint, this.m_Target.isMine);
        }

        // ViewSynchronization (reliability)
        if (this.m_Target.synchronization == ViewSynchronization.Off)
        {
            GUI.color = Color.grey;
        }

        EditorGUILayout.PropertyField(serializedObject.FindProperty("synchronization"), new GUIContent("Observe option:"));

        if (this.m_Target.synchronization != ViewSynchronization.Off && this.m_Target.ObservedComponents.FindAll(item => item != null).Count == 0)
        {
            GUILayout.BeginVertical(GUI.skin.box);
            GUILayout.Label("Warning", EditorStyles.boldLabel);
            GUILayout.Label("Setting the synchronization option only makes sense if you observe something.");
            GUILayout.EndVertical();
        }

        DrawSpecificTypeSerializationOptions();

        GUI.color = Color.white;
        DrawObservedComponentsList();

        // Cleanup: save and fix look
        if (GUI.changed)
        {
            #if !UNITY_MIN_5_3
            EditorUtility.SetDirty(this.m_Target);
            #endif
            PhotonViewHandler.HierarchyChange(); // TODO: check if needed
        }

        GUI.color = Color.white;
        #if !UNITY_MIN_5_3
        EditorGUIUtility.LookLikeControls();
        #endif
    }
    public static void RunConversion()
    {
        //Ask if user has made a backup.
        int option = EditorUtility.DisplayDialogComplex("Conversion", "Attempt automatic conversion from Unity Networking to Photon Unity Networking \"PUN\"?", "Yes", "No!", "Pick Script Folder");

        switch (option)
        {
        case 0:
            break;

        case 1:
            return;

        case 2:
            PickFolderAndConvertScripts();
            return;

        default:
            return;
        }

        //REAAAALY?
        bool result = EditorUtility.DisplayDialog("Conversion", "Disclaimer: The code conversion feature is quite crude, but should do it's job well (see the sourcecode). A backup is therefore strongly recommended!", "Yes, I've made a backup: GO", "Abort");

        if (!result)
        {
            return;
        }
        Output(EditorApplication.timeSinceStartup + " Started conversion of Unity networking -> Photon");

        //Ask to save current scene (optional)
        EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();

        EditorUtility.DisplayProgressBar("Converting..", "Starting.", 0);

        //Convert NetworkViews to PhotonViews in Project prefabs
        //Ask the user if we can move all prefabs to a resources folder
        bool movePrefabs = EditorUtility.DisplayDialog("Conversion", "Can all prefabs that use a PhotonView be moved to a Resources/ folder? You need this if you use Network.Instantiate.", "Yes", "No");


        string[] prefabs = Directory.GetFiles("Assets/", "*.prefab", SearchOption.AllDirectories);
        foreach (string prefab in prefabs)
        {
            EditorUtility.DisplayProgressBar("Converting..", "Object:" + prefab, 0.6f);

            Object[] objs      = (Object[])AssetDatabase.LoadAllAssetsAtPath(prefab);
            int      converted = 0;
            foreach (Object obj in objs)
            {
                if (obj != null && obj.GetType() == typeof(GameObject))
                {
                    converted += ConvertNetworkView(((GameObject)obj).GetComponents <NetworkView>(), false);
                }
            }
            if (movePrefabs && converted > 0)
            {
                //This prefab needs to be under the root of a Resources folder!
                string path           = prefab.Replace("\\", "/");
                int    lastSlash      = path.LastIndexOf("/");
                int    resourcesIndex = path.LastIndexOf("/Resources/");
                if (resourcesIndex != lastSlash - 10)
                {
                    if (path.Contains("/Resources/"))
                    {
                        Debug.LogWarning("Warning, prefab [" + prefab + "] was already in a resources folder. But has been placed in the root of another one!");
                    }
                    //This prefab NEEDS to be placed under a resources folder
                    string resourcesFolder = path.Substring(0, lastSlash) + "/Resources/";
                    EnsureFolder(resourcesFolder);
                    string newPath = resourcesFolder + path.Substring(lastSlash + 1);
                    string error   = AssetDatabase.MoveAsset(prefab, newPath);
                    if (error != "")
                    {
                        Debug.LogError(error);
                    }
                    Output("Fixed prefab [" + prefab + "] by moving it into a resources folder.");
                }
            }
        }

        //Convert NetworkViews to PhotonViews in scenes
        string[] sceneFiles = Directory.GetFiles("Assets/", "*.unity", SearchOption.AllDirectories);
        foreach (string sceneName in sceneFiles)
        {
            EditorSceneManager.OpenScene(sceneName);
            EditorUtility.DisplayProgressBar("Converting..", "Scene:" + sceneName, 0.2f);

            int converted2 = ConvertNetworkView((NetworkView[])GameObject.FindObjectsOfType(typeof(NetworkView)), true);
            if (converted2 > 0)
            {
                //This will correct all prefabs: The prefabs have gotten new components, but the correct ID's were lost in this case
                PhotonViewHandler.HierarchyChange();

                Output("Replaced " + converted2 + " NetworkViews with PhotonViews in scene: " + sceneName);
                EditorSceneManager.SaveOpenScenes();
            }
        }

        //Convert C#/JS scripts (API stuff)
        List <string> scripts = GetScriptsInFolder("Assets");

        EditorUtility.DisplayProgressBar("Converting..", "Scripts..", 0.9f);
        ConvertScripts(scripts);

        Output(EditorApplication.timeSinceStartup + " Completed conversion!");
        EditorUtility.ClearProgressBar();

        EditorUtility.DisplayDialog("Completed the conversion", "Don't forget to add \"PhotonNetwork.ConnectWithDefaultSettings();\" to connect to the Photon server before using any multiplayer functionality.", "OK");
    }
Exemplo n.º 3
0
    public override void OnInspectorGUI()
    {
        EditorGUIUtility.LookLikeInspector();
        EditorGUI.indentLevel = 1;

        PhotonView mp = (PhotonView)this.target;
        bool       isProjectPrefab = EditorUtility.IsPersistent(mp.gameObject);



        // Owner
        if (isProjectPrefab)
        {
            EditorGUILayout.LabelField("Owner:", "Set at runtime");
        }
        else if (mp.isSceneView)
        {
            EditorGUILayout.LabelField("Owner:", "Scene");
        }
        else
        {
            PhotonPlayer owner     = mp.owner;
            string       ownerInfo = (owner != null) ? owner.name : "<no PhotonPlayer found>";

            if (string.IsNullOrEmpty(ownerInfo))
            {
                ownerInfo = "<no playername set>";
            }

            EditorGUILayout.LabelField("Owner:", "[" + mp.ownerId + "] " + ownerInfo);
        }



        // View ID
        if (isProjectPrefab)
        {
            EditorGUILayout.LabelField("View ID", "Set at runtime");
        }
        else if (EditorApplication.isPlaying)
        {
            EditorGUILayout.LabelField("View ID", mp.viewID.ToString());
        }
        else
        {
            int idValue = EditorGUILayout.IntField("View ID [0.." + (PhotonNetwork.MAX_VIEW_IDS - 1) + "]", mp.viewID);
            mp.viewID = idValue;
        }



        // Locally Controlled
        if (EditorApplication.isPlaying)
        {
            string masterClientHint = PhotonNetwork.isMasterClient ? "(master)" : "";
            EditorGUILayout.Toggle("Controlled locally: " + masterClientHint, mp.isMine);
        }



        // Observed Item
        EditorGUILayout.BeginHorizontal();

        // Using a lower version then 3.4? Remove the TRUE in the next line to fix an compile error
        string typeOfObserved = string.Empty;

        if (mp.observed != null)
        {
            int firstBracketPos = mp.observed.ToString().LastIndexOf('(');
            if (firstBracketPos > 0)
            {
                typeOfObserved = mp.observed.ToString().Substring(firstBracketPos);
            }
        }


        Component componenValue = (Component)EditorGUILayout.ObjectField("Observe: " + typeOfObserved, mp.observed, typeof(Component), true);

        if (mp.observed != componenValue)
        {
            if (mp.observed == null)
            {
                mp.synchronization = ViewSynchronization.Unreliable;    // if we didn't observe anything before, we could observe unreliably now
            }
            if (componenValue == null)
            {
                mp.synchronization = ViewSynchronization.Off;
            }

            mp.observed = componenValue;
        }

        EditorGUILayout.EndHorizontal();



        // ViewSynchronization (reliability)
        if (mp.synchronization == ViewSynchronization.Off)
        {
            GUI.color = Color.grey;
        }

        ViewSynchronization vsValue = (ViewSynchronization)EditorGUILayout.EnumPopup("Observe option:", mp.synchronization);

        if (vsValue != mp.synchronization)
        {
            mp.synchronization = vsValue;
            if (mp.synchronization != ViewSynchronization.Off && mp.observed == null)
            {
                EditorUtility.DisplayDialog("Warning", "Setting the synchronization option only makes sense if you observe something.", "OK, I will fix it.");
            }
        }



        // Serialization
        // show serialization options only if something is observed
        if (mp.observed != null)
        {
            Type type = mp.observed.GetType();
            if (type == typeof(Transform))
            {
                mp.onSerializeTransformOption = (OnSerializeTransform)EditorGUILayout.EnumPopup("Serialization:", mp.onSerializeTransformOption);
            }
            else if (type == typeof(Rigidbody))
            {
                mp.onSerializeRigidBodyOption = (OnSerializeRigidBody)EditorGUILayout.EnumPopup("Serialization:", mp.onSerializeRigidBodyOption);
            }
        }



        // Cleanup: save and fix look
        if (GUI.changed)
        {
            EditorUtility.SetDirty(mp);
            PhotonViewHandler.HierarchyChange();  // TODO: check if needed
        }

        GUI.color = Color.white;
        EditorGUIUtility.LookLikeControls();
    }
Exemplo n.º 4
0
    // this method corrects the IDs for photonviews in the scene and in prefabs
    // make sure prefabs always use viewID 0
    // make sure instances never use a owner
    // this is a editor class that should only run if not playing
    internal static void HierarchyChange()
    {
        if (Application.isPlaying)
        {
            //Debug.Log("HierarchyChange ignored, while running.");
            CheckSceneForStuckHandlers = true;  // done once AFTER play mode.
            return;
        }

        if (CheckSceneForStuckHandlers)
        {
            CheckSceneForStuckHandlers = false;
            PhotonNetwork.InternalCleanPhotonMonoFromSceneIfStuck();
        }

        HashSet <PhotonView> pvInstances             = new HashSet <PhotonView>();
        HashSet <int>        usedInstanceViewNumbers = new HashSet <int>();
        bool fixedSomeId = false;

        //// the following code would be an option if we only checked scene objects (but we can check all PVs)
        //PhotonView[] pvObjects = GameObject.FindSceneObjectsOfType(typeof(PhotonView)) as PhotonView[];
        //Debug.Log("HierarchyChange. PV Count: " + pvObjects.Length);

        string levelName = SceneManagerHelper.ActiveSceneName;

        #if UNITY_EDITOR
        levelName = SceneManagerHelper.EditorActiveSceneName;
        #endif
        int minViewIdInThisScene = PunSceneSettings.MinViewIdForScene(levelName);
        //Debug.Log("Level '" + Application.loadedLevelName + "' has a minimum ViewId of: " + minViewIdInThisScene);

        PhotonView[] pvObjects = Resources.FindObjectsOfTypeAll(typeof(PhotonView)) as PhotonView[];

        foreach (PhotonView view in pvObjects)
        {
            // first pass: fix prefabs to viewID 0 if they got a view number assigned (cause they should not have one!)
            if (EditorUtility.IsPersistent(view.gameObject))
            {
                if (view.viewID != 0 || view.prefixBackup != -1 || view.instantiationId != -1)
                {
                    Debug.LogWarning("PhotonView on persistent object being fixed (id and prefix must be 0). Was: " + view);
                    view.viewID          = 0;
                    view.prefixBackup    = -1;
                    view.instantiationId = -1;
                    EditorUtility.SetDirty(view);   // even in Unity 5.3+ it's OK to SetDirty() for non-scene objects.
                    fixedSomeId = true;
                }
            }
            else
            {
                // keep all scene-instanced PVs for later re-check
                pvInstances.Add(view);
            }
        }

        Dictionary <GameObject, int> idPerObject = new Dictionary <GameObject, int>();

        // second pass: check all used-in-scene viewIDs for duplicate viewIDs (only checking anything non-prefab)
        // scene-PVs must have user == 0 (scene/room) and a subId != 0
        foreach (PhotonView view in pvInstances)
        {
            if (view.ownerId > 0)
            {
                Debug.Log("Re-Setting Owner ID of: " + view);
            }
            view.ownerId = 0;   // simply make sure no owner is set (cause room always uses 0)
            view.prefix  = -1;  // TODO: prefix could be settable via inspector per scene?!

            if (view.viewID != 0)
            {
                if (view.viewID < minViewIdInThisScene || usedInstanceViewNumbers.Contains(view.viewID))
                {
                    view.viewID = 0; // avoid duplicates and negative values by assigning 0 as (temporary) number to be fixed in next pass
                }
                else
                {
                    usedInstanceViewNumbers.Add(view.viewID); // builds a list of currently used viewIDs

                    int instId = 0;
                    if (idPerObject.TryGetValue(view.gameObject, out instId))
                    {
                        view.instantiationId = instId;
                    }
                    else
                    {
                        view.instantiationId         = view.viewID;
                        idPerObject[view.gameObject] = view.instantiationId;
                    }
                }
            }
        }

        // third pass: anything that's now 0 must get a new (not yet used) ID (starting at 0)
        int lastUsedId = (minViewIdInThisScene > 0) ? minViewIdInThisScene - 1 : 0;

        foreach (PhotonView view in pvInstances)
        {
            if (view.viewID == 0)
            {
                Undo.RecordObject(view, "Automatic viewID change for: " + view.gameObject.name);

                // Debug.LogWarning("setting scene ID: " + view.gameObject.name + " ID: " + view.subId.ID + " scene ID: " + view.GetSceneID() + " IsPersistent: " + EditorUtility.IsPersistent(view.gameObject) + " IsSceneViewIDFree: " + IsSceneViewIDFree(view.subId.ID, view));
                int nextViewId = PhotonViewHandler.GetID(lastUsedId, usedInstanceViewNumbers);

                view.viewID = nextViewId;

                int instId = 0;
                if (idPerObject.TryGetValue(view.gameObject, out instId))
                {
                    view.instantiationId = instId;
                }
                else
                {
                    view.instantiationId         = view.viewID;
                    idPerObject[view.gameObject] = nextViewId;
                }

                lastUsedId  = nextViewId;
                fixedSomeId = true;

                #if !UNITY_MIN_5_3
                EditorUtility.SetDirty(view);
                #endif
            }
        }


        if (fixedSomeId)
        {
            //Debug.LogWarning("Some subId was adjusted."); // this log is only interesting for Exit Games
        }
    }
    public override void OnInspectorGUI()
    {
        m_Target = (PhotonView)this.target;
        bool isProjectPrefab = EditorUtility.IsPersistent(m_Target.gameObject);

        if (m_Target.ObservedComponents == null)
        {
            m_Target.ObservedComponents = new System.Collections.Generic.List <Component>();
        }

        if (m_Target.ObservedComponents.Count == 0)
        {
            m_Target.ObservedComponents.Add(null);
        }

        EditorGUILayout.BeginHorizontal();
        // Owner
        if (isProjectPrefab)
        {
            EditorGUILayout.LabelField("Owner:", "Set at runtime");
        }
        else if (m_Target.isSceneView)
        {
            EditorGUILayout.LabelField("Owner", "Scene");
        }
        else
        {
            PhotonPlayer owner     = m_Target.owner;
            string       ownerInfo = (owner != null) ? owner.name : "<no PhotonPlayer found>";

            if (string.IsNullOrEmpty(ownerInfo))
            {
                ownerInfo = "<no playername set>";
            }

            EditorGUILayout.LabelField("Owner", "[" + m_Target.ownerId + "] " + ownerInfo);
        }

        // ownership requests
        EditorGUI.BeginDisabledGroup(Application.isPlaying);
        m_Target.ownershipTransfer = (OwnershipOption)EditorGUILayout.EnumPopup(m_Target.ownershipTransfer, GUILayout.Width(100));
        EditorGUI.EndDisabledGroup();

        EditorGUILayout.EndHorizontal();


        // View ID
        if (isProjectPrefab)
        {
            EditorGUILayout.LabelField("View ID", "Set at runtime");
        }
        else if (EditorApplication.isPlaying)
        {
            EditorGUILayout.LabelField("View ID", m_Target.viewID.ToString());
        }
        else
        {
            int idValue = EditorGUILayout.IntField("View ID [1.." + (PhotonNetwork.MAX_VIEW_IDS - 1) + "]", m_Target.viewID);
            m_Target.viewID = idValue;
        }


        // Locally Controlled
        if (EditorApplication.isPlaying)
        {
            string masterClientHint = PhotonNetwork.isMasterClient ? "(master)" : "";
            EditorGUILayout.Toggle("Controlled locally: " + masterClientHint, m_Target.isMine);
        }


        //DrawOldObservedItem();
        this.ConvertOldObservedItemToObservedList();


        // ViewSynchronization (reliability)
        if (m_Target.synchronization == ViewSynchronization.Off)
        {
            GUI.color = Color.grey;
        }

        EditorGUILayout.PropertyField(serializedObject.FindProperty("synchronization"), new GUIContent("Observe option:"));

        if (m_Target.synchronization != ViewSynchronization.Off &&
            m_Target.ObservedComponents.FindAll(item => item != null).Count == 0)
        {
            GUILayout.BeginVertical(GUI.skin.box);
            GUILayout.Label("Warning", EditorStyles.boldLabel);
            GUILayout.Label("Setting the synchronization option only makes sense if you observe something.");
            GUILayout.EndVertical();
        }

        /*ViewSynchronization vsValue = (ViewSynchronization)EditorGUILayout.EnumPopup("Observe option:", m_Target.synchronization);
         * if (vsValue != m_Target.synchronization)
         * {
         *  m_Target.synchronization = vsValue;
         *  if (m_Target.synchronization != ViewSynchronization.Off && m_Target.observed == null)
         *  {
         *      EditorUtility.DisplayDialog("Warning", "Setting the synchronization option only makes sense if you observe something.", "OK, I will fix it.");
         *  }
         * }*/

        DrawSpecificTypeSerializationOptions();

        GUI.color = Color.white;
        DrawObservedComponentsList();

        // Cleanup: save and fix look
        if (GUI.changed)
        {
            EditorUtility.SetDirty(m_Target);
            PhotonViewHandler.HierarchyChange(); // TODO: check if needed
        }

        GUI.color = Color.white;
        #if !UNITY_MIN_5_3
        EditorGUIUtility.LookLikeControls();
        #endif
    }