first commit

This commit is contained in:
2022-07-08 09:14:55 +08:00
commit 4d6bd72555
1123 changed files with 456307 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

View File

@ -0,0 +1,116 @@
fileFormatVersion: 2
guid: d1228d93299ce47a8a5ac1a33513aeaf
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: iPhone
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,116 @@
fileFormatVersion: 2
guid: 81b8e0c5ffa3345b7aa3af3a2c0257ce
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: iPhone
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Android
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: WebGL
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,855 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonEditor.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// MenuItems and in-Editor scripts for PhotonNetwork.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.Compilation;
using UnityEngine;
namespace Photon.Pun
{
using Realtime;
public class PunWizardText
{
public string WindowTitle = "PUN Wizard";
public string SetupWizardWarningTitle = "Warning";
public string SetupWizardWarningMessage = "You have not yet run the Photon setup wizard! Your game won't be able to connect. See Windows -> Photon Unity Networking.";
public string MainMenuButton = "Main Menu";
public string SetupWizardTitle = "PUN Setup";
public string SetupWizardInfo = "Thanks for importing Photon Unity Networking.\nThis window should set you up.\n\n<b>-</b> To use an existing Photon Cloud App, enter your AppId.\n<b>-</b> To register an account or access an existing one, enter the account's mail address.\n<b>-</b> To use Photon OnPremise, skip this step.";
public string EmailOrAppIdLabel = "AppId or Email";
public string AlreadyRegisteredInfo = "The email is registered so we can't fetch your AppId (without password).\n\nPlease login online to get your AppId and paste it above.";
public string SkipRegistrationInfo = "Skipping? No problem:\nEdit your server settings in the PhotonServerSettings file.";
public string RegisteredNewAccountInfo = "We created a (free) account and fetched you an AppId.\nWelcome. Your PUN project is setup.";
public string AppliedToSettingsInfo = "Your AppId is now applied to this project.";
public string SetupCompleteInfo = "<b>Done!</b>\nAll connection settings can be edited in the <b>PhotonServerSettings</b> now.\nHave a look.";
public string CloseWindowButton = "Close";
public string SkipButton = "Skip";
public string SetupButton = "Setup Project";
public string CancelButton = "Cancel";
public string PUNWizardLabel = "PUN Wizard";
public string SettingsButton = "Settings:";
public string SetupServerCloudLabel = "Setup wizard for setting up your own server or the cloud.";
public string WarningPhotonDisconnect = "Disconnecting PUN due to recompile. Exit PlayMode.";
public string StartButton = "Start";
public string LocateSettingsButton = "Locate PhotonServerSettings";
public string SettingsHighlightLabel = "Highlights the used photon settings file in the project.";
public string DocumentationLabel = "Documentation:";
public string OpenPDFText = "Reference PDF";
public string OpenPDFTooltip = "Opens the local documentation pdf.";
public string OpenDevNetText = "Doc Pages / Manual";
public string OpenDevNetTooltip = "Online documentation for Photon.";
public string OpenCloudDashboardText = "Cloud Dashboard Login";
public string OpenCloudDashboardTooltip = "Review Cloud App information and statistics.";
public string OpenForumText = "Open Forum";
public string OpenForumTooltip = "Online support for Photon.";
public string OkButton = "Ok";
public string OwnHostCloudCompareLabel = "How 'my own host' compares to 'cloud'.";
public string ComparisonPageButton = "Cloud versus OnPremise";
public string ConnectionTitle = "Connecting";
public string ConnectionInfo = "Connecting to the account service...";
public string ErrorTextTitle = "Error";
public string IncorrectRPCListTitle = "Warning: RPC-list becoming incompatible!";
public string IncorrectRPCListLabel = "Your project's RPC-list is full, so we can't add some RPCs just compiled.\n\nBy removing outdated RPCs, the list will be long enough but incompatible with older client builds!\n\nMake sure you change the game version where you use PhotonNetwork.ConnectUsingSettings().";
public string RemoveOutdatedRPCsLabel = "Remove outdated RPCs";
public string FullRPCListTitle = "Warning: RPC-list is full!";
public string FullRPCListLabel = "Your project's RPC-list is too long for PUN.\n\nYou can change PUN's source to use short-typed RPC index. Look for comments 'LIMITS RPC COUNT'\n\nAlternatively, remove some RPC methods (use more parameters per RPC maybe).\n\nAfter a RPC-list refresh, make sure you change the game version where you use PhotonNetwork.ConnectUsingSettings().";
public string SkipRPCListUpdateLabel = "Skip RPC-list update";
public string PUNNameReplaceTitle = "Warning: RPC-list Compatibility";
public string PUNNameReplaceLabel = "PUN replaces RPC names with numbers by using the RPC-list. All clients must use the same list for that.\n\nClearing it most likely makes your client incompatible with previous versions! Change your game version or make sure the RPC-list matches other clients.";
public string RPCListCleared = "Clear RPC-list";
public string ServerSettingsCleanedWarning = "Cleared the PhotonServerSettings.RpcList, which breaks compatibility with older builds. You should update the \"App Version\" in the PhotonServerSettings to avoid issues.";
public string WizardMainWindowInfo = "This window should help you find important settings for PUN, as well as documentation.";
}
public class PhotonEditor : EditorWindow
{
protected static Type WindowType = typeof(PhotonEditor);
protected Vector2 scrollPos = Vector2.zero;
private readonly Vector2 preferredSize = new Vector2(350, 400);
private static Texture2D BackgroundImage;
public static PunWizardText CurrentLang = new PunWizardText();
/// <summary>
/// third parties custom token
/// </summary>
public static string CustomToken = null;
/// <summary>
/// third parties custom context
/// </summary>
public static string CustomContext = null;
protected static string DocumentationLocation = "Assets/Photon/PhotonNetworking-Documentation.pdf";
protected static string UrlFreeLicense = "https://dashboard.photonengine.com/en-US/SelfHosted";
public const string UrlDevNet = "https://doc.photonengine.com/en-us/pun/v2";
protected static string UrlForum = "https://forum.photonengine.com";
protected static string UrlCompare = "https://doc.photonengine.com/en-us/realtime/current/getting-started/onpremise-or-saas";
protected static string UrlHowToSetup = "https://doc.photonengine.com/en-us/onpremise/current/getting-started/photon-server-in-5min";
protected static string UrlAppIDExplained = "https://doc.photonengine.com/en-us/realtime/current/getting-started/obtain-your-app-id";
public const string UrlCloudDashboard = "https://dashboard.photonengine.com/en-US/account/signin?email=";
public const string UrlPunSettings = "https://doc.photonengine.com/en-us/pun/v2/getting-started/initial-setup"; // the SeverSettings class has this url directly in it's HelpURL attribute.
private enum PhotonSetupStates
{
MainUi,
RegisterForPhotonCloud,
EmailAlreadyRegistered,
GoEditPhotonServerSettings,
EmailRegistrationPending
}
private bool isSetupWizard = false;
private PhotonSetupStates photonSetupState = PhotonSetupStates.RegisterForPhotonCloud;
private bool minimumInput = false;
private bool useMail = false;
private bool useAppId = false;
private bool useSkip = false;
private bool highlightedSettings = false;
private bool close = false;
private string mailOrAppId = string.Empty;
private static double lastWarning = 0;
private static bool postInspectorUpdate;
[MenuItem("Window/Photon Unity Networking/PUN Wizard &p", false, 0)]
protected static void MenuItemOpenWizard()
{
PhotonEditor win = GetWindow<PhotonEditor>(false, CurrentLang.WindowTitle, true);
if (win == null)
{
return;
}
win.photonSetupState = PhotonSetupStates.MainUi;
win.isSetupWizard = false;
}
[MenuItem("Window/Photon Unity Networking/Highlight Server Settings %#&p", false, 1)]
protected static void MenuItemHighlightSettings()
{
HighlightSettings();
}
[UnityEditor.InitializeOnLoadMethod]
public static void InitializeOnLoadMethod()
{
//Debug.Log("InitializeOnLoadMethod()");
EditorApplication.delayCall += OnDelayCall;
}
// used to register for various events (post-load)
private static void OnDelayCall()
{
//Debug.Log("OnDelayCall()");
postInspectorUpdate = true;
EditorApplication.playModeStateChanged -= PlayModeStateChanged;
EditorApplication.playModeStateChanged += PlayModeStateChanged;
#if UNITY_2021_1_OR_NEWER
CompilationPipeline.compilationStarted -= OnCompileStarted21;
CompilationPipeline.compilationStarted += OnCompileStarted21;
#else
CompilationPipeline.assemblyCompilationStarted -= OnCompileStarted;
CompilationPipeline.assemblyCompilationStarted += OnCompileStarted;
#endif
#if (UNITY_2018 || UNITY_2018_1_OR_NEWER)
EditorApplication.projectChanged -= OnProjectChanged;
EditorApplication.projectChanged += OnProjectChanged;
#else
EditorApplication.projectWindowChanged -= OnProjectChanged;
EditorApplication.projectWindowChanged += OnProjectChanged;
#endif
if (!EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode)
{
OnProjectChanged(); // call this initially from here, as the project change events happened earlier (on start of the Editor)
PhotonEditor.UpdateRpcList();
}
}
// called in editor, opens wizard for initial setup, keeps scene PhotonViews up to date and closes connections when compiling (to avoid issues)
private static void OnProjectChanged()
{
PhotonEditorUtils.ProjectChangedWasCalled = true;
// Prevent issues with Unity Cloud Builds where ServerSettings are not found.
// Also, within the context of a Unity Cloud Build, ServerSettings is already present anyway.
#if UNITY_CLOUD_BUILD
return;
#endif
if (PhotonNetwork.PhotonServerSettings == null || PhotonNetwork.PhotonServerSettings.AppSettings == null || string.IsNullOrEmpty(PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime))
{
PhotonNetwork.LoadOrCreateSettings(true);
}
if (PhotonNetwork.PhotonServerSettings == null)
{
// the PhotonServerSettings are loaded or created. If both fails, the Editor should probably not run (anymore).
return;
}
PunSceneSettings.SanitizeSceneSettings();
// serverSetting is null when the file gets deleted. otherwise, the wizard should only run once and only if hosting option is not (yet) set
if (!PhotonNetwork.PhotonServerSettings.DisableAutoOpenWizard)
{
ShowRegistrationWizard();
PhotonNetwork.PhotonServerSettings.DisableAutoOpenWizard = true;
PhotonEditor.SaveSettings();
}
}
#if UNITY_2021_1_OR_NEWER
private static void OnCompileStarted21(object obj)
{
OnCompileStarted(obj as string);
}
#endif
private static void OnCompileStarted(string obj)
{
if (PhotonNetwork.IsConnected)
{
// log warning, unless there was one recently
if (EditorApplication.timeSinceStartup - lastWarning > 3)
{
Debug.LogWarning(CurrentLang.WarningPhotonDisconnect);
lastWarning = EditorApplication.timeSinceStartup;
}
PhotonNetwork.Disconnect();
PhotonNetwork.NetworkingClient.LoadBalancingPeer.DispatchIncomingCommands();
#if UNITY_2019_4_OR_NEWER && UNITY_EDITOR
EditorApplication.ExitPlaymode();
#endif
}
}
[DidReloadScripts]
private static void OnDidReloadScripts()
{
//Debug.Log("OnDidReloadScripts() postInspectorUpdate: "+postInspectorUpdate + " isPlayingOrWillChangePlaymode: "+EditorApplication.isPlayingOrWillChangePlaymode);
if (postInspectorUpdate && !EditorApplication.isPlayingOrWillChangePlaymode)
{
PhotonEditor.UpdateRpcList(); // could be called when compilation finished (instead of when reload / compile starts)
}
}
private static void PlayModeStateChanged(PlayModeStateChange state)
{
//Debug.Log("PlayModeStateChanged");
if (EditorApplication.isPlaying || !EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
if (string.IsNullOrEmpty(PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime) && !PhotonNetwork.PhotonServerSettings.AppSettings.IsMasterServerAddress)
{
EditorUtility.DisplayDialog(CurrentLang.SetupWizardWarningTitle, CurrentLang.SetupWizardWarningMessage, CurrentLang.OkButton);
}
}
#region GUI and Wizard
// setup per window
public PhotonEditor()
{
this.minSize = this.preferredSize;
}
protected void Awake()
{
// check if some appid is set. if so, we can avoid registration calls.
if (PhotonNetwork.PhotonServerSettings != null && PhotonNetwork.PhotonServerSettings.AppSettings != null && !string.IsNullOrEmpty(PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime))
{
this.mailOrAppId = PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime;
}
}
/// <summary>Creates an Editor window, showing the cloud-registration wizard for Photon (entry point to setup PUN).</summary>
protected static void ShowRegistrationWizard()
{
PhotonEditor win = GetWindow(WindowType, false, CurrentLang.WindowTitle, true) as PhotonEditor;
if (win == null)
{
return;
}
win.photonSetupState = PhotonSetupStates.RegisterForPhotonCloud;
win.isSetupWizard = true;
}
// Window Update() callback. On-demand, when Window is open
protected void Update()
{
if (this.close)
{
this.Close();
}
}
protected virtual void OnGUI()
{
if (BackgroundImage == null)
{
string[] paths = AssetDatabase.FindAssets("PunGradient t:Texture2D");
if (paths != null && paths.Length > 0)
{
BackgroundImage = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(paths[0]));
}
}
PhotonSetupStates oldGuiState = this.photonSetupState; // used to fix an annoying Editor input field issue: wont refresh until focus is changed.
GUI.SetNextControlName(string.Empty);
this.scrollPos = GUILayout.BeginScrollView(this.scrollPos);
if (this.photonSetupState == PhotonSetupStates.MainUi)
{
this.UiMainWizard();
}
else
{
EditorGUI.BeginDisabledGroup(this.photonSetupState == PhotonSetupStates.EmailRegistrationPending);
this.UiSetupApp();
EditorGUI.EndDisabledGroup();
}
GUILayout.EndScrollView();
if (oldGuiState != this.photonSetupState)
{
GUI.FocusControl(string.Empty);
}
}
private string emailSentToAccount;
private bool emailSentToAccountIsRegistered;
protected virtual void UiSetupApp()
{
GUI.skin.label.wordWrap = true;
if (!this.isSetupWizard)
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(CurrentLang.MainMenuButton, GUILayout.ExpandWidth(false)))
{
this.photonSetupState = PhotonSetupStates.MainUi;
}
GUILayout.EndHorizontal();
}
// setup header
this.UiTitleBox(CurrentLang.SetupWizardTitle, BackgroundImage);
// setup info text
GUI.skin.label.richText = true;
GUILayout.Label(CurrentLang.SetupWizardInfo);
// input of appid or mail
EditorGUILayout.Separator();
GUILayout.Label(CurrentLang.EmailOrAppIdLabel);
this.minimumInput = false;
this.useMail = false;
this.useAppId = false;
this.mailOrAppId = EditorGUILayout.TextField(this.mailOrAppId);
if (!string.IsNullOrEmpty(this.mailOrAppId))
{
this.mailOrAppId = this.mailOrAppId.Trim(); // note: we trim all input
if (AccountService.IsValidEmail(this.mailOrAppId))
{
// input should be a mail address
this.useMail = true;
// check if the current input equals earlier input, which is known to be registered already
this.minimumInput = !this.mailOrAppId.Equals(this.emailSentToAccount) || !this.emailSentToAccountIsRegistered;
}
else if (ServerSettings.IsAppId(this.mailOrAppId))
{
// this should be an appId
this.minimumInput = true;
this.useAppId = true;
}
}
// button to skip setup
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(CurrentLang.SkipButton, GUILayout.Width(100)))
{
this.photonSetupState = PhotonSetupStates.GoEditPhotonServerSettings;
this.useSkip = true;
this.useMail = false;
this.useAppId = false;
}
// SETUP button
EditorGUI.BeginDisabledGroup(!this.minimumInput);
if (GUILayout.Button(CurrentLang.SetupButton, GUILayout.Width(100)))
{
this.useSkip = false;
GUIUtility.keyboardControl = 0;
if (this.useMail)
{
this.RegisterWithEmail(this.mailOrAppId); // sets state
}
else if (this.useAppId)
{
this.photonSetupState = PhotonSetupStates.GoEditPhotonServerSettings;
Undo.RecordObject(PhotonNetwork.PhotonServerSettings, "Update PhotonServerSettings for PUN");
PhotonNetwork.PhotonServerSettings.UseCloud(this.mailOrAppId);
PhotonEditor.SaveSettings();
}
}
EditorGUI.EndDisabledGroup();
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
// existing account needs to fetch AppId online
if (this.photonSetupState == PhotonSetupStates.EmailAlreadyRegistered)
{
// button to open dashboard and get the AppId
GUILayout.Space(15);
GUILayout.Label(CurrentLang.AlreadyRegisteredInfo);
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(new GUIContent(CurrentLang.OpenCloudDashboardText, CurrentLang.OpenCloudDashboardTooltip), GUILayout.Width(205)))
{
Application.OpenURL(string.Concat(UrlCloudDashboard, Uri.EscapeUriString(this.mailOrAppId)));
this.mailOrAppId = string.Empty;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
else if (this.photonSetupState == PhotonSetupStates.GoEditPhotonServerSettings)
{
if (!this.highlightedSettings)
{
this.highlightedSettings = true;
HighlightSettings();
}
GUILayout.Space(15);
if (this.useSkip)
{
GUILayout.Label(CurrentLang.SkipRegistrationInfo);
}
else if (this.useMail)
{
GUILayout.Label(CurrentLang.RegisteredNewAccountInfo);
}
else if (this.useAppId)
{
GUILayout.Label(CurrentLang.AppliedToSettingsInfo);
}
// setup-complete info
GUILayout.Space(15);
GUILayout.Label(CurrentLang.SetupCompleteInfo);
// close window (done)
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(CurrentLang.CloseWindowButton, GUILayout.Width(205)))
{
this.close = true;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
GUI.skin.label.richText = false;
}
private void UiTitleBox(string title, Texture2D bgIcon)
{
GUIStyle bgStyle = EditorGUIUtility.isProSkin ? new GUIStyle(GUI.skin.GetStyle("Label")) : new GUIStyle(GUI.skin.GetStyle("WhiteLabel"));
bgStyle.padding = new RectOffset(10, 10, 10, 10);
bgStyle.fontSize = 22;
bgStyle.fontStyle = FontStyle.Bold;
if (bgIcon != null)
{
bgStyle.normal.background = bgIcon;
}
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
Rect scale = GUILayoutUtility.GetLastRect();
scale.height = 44;
GUI.Label(scale, title, bgStyle);
GUILayout.Space(scale.height + 5);
}
protected virtual void UiMainWizard()
{
GUILayout.Space(15);
// title
this.UiTitleBox(CurrentLang.PUNWizardLabel, BackgroundImage);
EditorGUILayout.BeginVertical(new GUIStyle() { padding = new RectOffset(10, 10, 10, 10) });
// wizard info text
GUILayout.Label(CurrentLang.WizardMainWindowInfo, new GUIStyle("Label") { wordWrap = true });
GUILayout.Space(15);
// settings button
GUILayout.Label(CurrentLang.SettingsButton, EditorStyles.boldLabel);
if (GUILayout.Button(new GUIContent(CurrentLang.LocateSettingsButton, CurrentLang.SettingsHighlightLabel)))
{
HighlightSettings();
}
if (GUILayout.Button(new GUIContent(CurrentLang.OpenCloudDashboardText, CurrentLang.OpenCloudDashboardTooltip)))
{
Application.OpenURL(UrlCloudDashboard + Uri.EscapeUriString(this.mailOrAppId));
}
if (GUILayout.Button(new GUIContent(CurrentLang.SetupButton, CurrentLang.SetupServerCloudLabel)))
{
this.photonSetupState = PhotonSetupStates.RegisterForPhotonCloud;
}
GUILayout.Space(15);
// documentation
GUILayout.Label(CurrentLang.DocumentationLabel, EditorStyles.boldLabel);
if (GUILayout.Button(new GUIContent(CurrentLang.OpenPDFText, CurrentLang.OpenPDFTooltip)))
{
EditorUtility.OpenWithDefaultApp(DocumentationLocation);
}
if (GUILayout.Button(new GUIContent(CurrentLang.OpenDevNetText, CurrentLang.OpenDevNetTooltip)))
{
Application.OpenURL(UrlDevNet);
}
GUI.skin.label.wordWrap = true;
GUILayout.Label(CurrentLang.OwnHostCloudCompareLabel);
if (GUILayout.Button(CurrentLang.ComparisonPageButton))
{
Application.OpenURL(UrlCompare);
}
if (GUILayout.Button(new GUIContent(CurrentLang.OpenForumText, CurrentLang.OpenForumTooltip)))
{
Application.OpenURL(UrlForum);
}
GUILayout.EndVertical();
}
#endregion
private AccountService serviceClient;
protected virtual void RegisterWithEmail(string email)
{
List<ServiceTypes> types = new List<ServiceTypes>();
types.Add(ServiceTypes.Pun);
if (PhotonEditorUtils.HasChat)
{
types.Add(ServiceTypes.Chat);
}
if (PhotonEditorUtils.HasVoice)
{
types.Add(ServiceTypes.Voice);
}
if (this.serviceClient == null)
{
this.serviceClient = new AccountService();
this.serviceClient.CustomToken = CustomToken;
this.serviceClient.CustomContext = CustomContext;
}
else
{
// while RegisterByEmail will check RequestPendingResult below, it would also display an error message. no needed in this case
if (this.serviceClient.RequestPendingResult)
{
Debug.LogWarning("Registration request is pending a response. Please wait.");
return;
}
}
this.emailSentToAccount = email;
this.emailSentToAccountIsRegistered = false;
if (this.serviceClient.RegisterByEmail(email, types, RegisterWithEmailSuccessCallback, RegisterWithEmailErrorCallback, "PUN"+PhotonNetwork.PunVersion))
{
this.photonSetupState = PhotonSetupStates.EmailRegistrationPending;
EditorUtility.DisplayProgressBar(CurrentLang.ConnectionTitle, CurrentLang.ConnectionInfo, 0.5f);
}
else
{
this.DisplayErrorMessage("Email registration request could not be sent. Retry again or check error logs and contact support.");
}
}
private void RegisterWithEmailSuccessCallback(AccountServiceResponse res)
{
EditorUtility.ClearProgressBar();
this.emailSentToAccountIsRegistered = true; // email is either registered now, or was already
if (res.ReturnCode == AccountServiceReturnCodes.Success)
{
string key = ((int) ServiceTypes.Pun).ToString();
string appId;
if (res.ApplicationIds.TryGetValue(key, out appId))
{
this.mailOrAppId = appId;
PhotonNetwork.PhotonServerSettings.UseCloud(this.mailOrAppId, null);
key = ((int) ServiceTypes.Chat).ToString();
if (res.ApplicationIds.TryGetValue(key, out appId))
{
PhotonNetwork.PhotonServerSettings.AppSettings.AppIdChat = appId;
}
else if (PhotonEditorUtils.HasChat)
{
Debug.LogWarning("Registration successful but no Chat AppId returned");
}
key = ((int) ServiceTypes.Voice).ToString();
if (res.ApplicationIds.TryGetValue(key, out appId))
{
PhotonNetwork.PhotonServerSettings.AppSettings.AppIdVoice = appId;
}
else if (PhotonEditorUtils.HasVoice)
{
Debug.LogWarning("Registration successful but no Voice AppId returned");
}
PhotonEditor.SaveSettings();
this.photonSetupState = PhotonSetupStates.GoEditPhotonServerSettings;
}
else
{
DisplayErrorMessage("Registration successful but no PUN AppId returned");
}
}
else
{
PhotonEditor.SaveSettings();
if (res.ReturnCode == AccountServiceReturnCodes.EmailAlreadyRegistered)
{
this.photonSetupState = PhotonSetupStates.EmailAlreadyRegistered;
}
else
{
DisplayErrorMessage(res.Message);
}
}
}
private void RegisterWithEmailErrorCallback(string error)
{
EditorUtility.ClearProgressBar();
DisplayErrorMessage(error);
}
private void DisplayErrorMessage(string error)
{
EditorUtility.DisplayDialog(CurrentLang.ErrorTextTitle, error, CurrentLang.OkButton);
this.photonSetupState = PhotonSetupStates.RegisterForPhotonCloud;
}
// Pings PhotonServerSettings and makes it selected (show in Inspector)
private static void HighlightSettings()
{
ServerSettings serverSettings = (ServerSettings)Resources.Load(PhotonNetwork.ServerSettingsFileName, typeof(ServerSettings));
Selection.objects = new UnityEngine.Object[] { serverSettings };
EditorGUIUtility.PingObject(serverSettings);
}
// Marks settings object as dirty, so it gets saved.
// unity 5.3 changes the usecase for SetDirty(). but here we don't modify a scene object! so it's ok to use
private static void SaveSettings()
{
EditorUtility.SetDirty(PhotonNetwork.PhotonServerSettings);
}
#region RPC List Handling
public static void UpdateRpcList()
{
//Debug.Log("UpdateRpcList()");
if (PhotonNetwork.PhotonServerSettings == null)
{
Debug.LogWarning("UpdateRpcList() wasn not able to access the PhotonServerSettings. Not updating the RPCs.");
return;
}
// check all "script assemblies" for methods with PunRPC attribute
List<string> additionalRpcs = new List<string>(); // not yet listed rpc-method names go here
List<string> allRpcs = new List<string>();
#if UNITY_2019_2_OR_NEWER
// we can make use of the new TypeCache to find methods with PunRPC attribute
var extractedMethods = TypeCache.GetMethodsWithAttribute<PunRPC>();
foreach (var methodInfo in extractedMethods)
{
allRpcs.Add(methodInfo.Name);
if (!PhotonNetwork.PhotonServerSettings.RpcList.Contains(methodInfo.Name) && !additionalRpcs.Contains(methodInfo.Name))
{
additionalRpcs.Add(methodInfo.Name);
}
}
#else
System.Reflection.Assembly[] assemblies = System.AppDomain.CurrentDomain.GetAssemblies().Where(a => !(a.ManifestModule is System.Reflection.Emit.ModuleBuilder)).ToArray();
foreach (var assembly in assemblies)
{
if (!assembly.Location.Contains("ScriptAssemblies") || assembly.FullName.StartsWith("Assembly-CSharp-Editor"))
{
continue;
}
var types = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(MonoBehaviour)));
var methodInfos = types.SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
var methodNames = methodInfos.Where(m => m.IsDefined(typeof(PunRPC), false)).Select(mi => mi.Name).ToArray();
var additional = methodNames.Where(n => !PhotonNetwork.PhotonServerSettings.RpcList.Contains(n) && !additionalRpcs.Contains(n));
allRpcs.AddRange(methodNames);
additionalRpcs.AddRange(additional);
}
#endif
if (additionalRpcs.Count <= 0)
{
//Debug.Log("UpdateRPCs did not found new.");
return;
}
if (additionalRpcs.Count + PhotonNetwork.PhotonServerSettings.RpcList.Count >= byte.MaxValue)
{
if (allRpcs.Count <= byte.MaxValue)
{
bool clearList = EditorUtility.DisplayDialog(CurrentLang.IncorrectRPCListTitle, CurrentLang.IncorrectRPCListLabel, CurrentLang.RemoveOutdatedRPCsLabel, CurrentLang.CancelButton);
if (clearList)
{
PhotonNetwork.PhotonServerSettings.RpcList.Clear();
additionalRpcs = allRpcs.Distinct().ToList(); // we add all unique names
}
else
{
return;
}
}
else
{
EditorUtility.DisplayDialog(CurrentLang.FullRPCListTitle, CurrentLang.FullRPCListLabel, CurrentLang.SkipRPCListUpdateLabel);
return;
}
}
additionalRpcs.Sort();
Undo.RecordObject(PhotonNetwork.PhotonServerSettings, "RPC-list update of PUN.");
PhotonNetwork.PhotonServerSettings.RpcList.AddRange(additionalRpcs);
EditorUtility.SetDirty(PhotonNetwork.PhotonServerSettings);
//Debug.Log("Updated RPCs. Added: "+additionalRpcs.Count);
}
public static void ClearRpcList()
{
bool clearList = EditorUtility.DisplayDialog(CurrentLang.PUNNameReplaceTitle, CurrentLang.PUNNameReplaceLabel, CurrentLang.RPCListCleared, CurrentLang.CancelButton);
if (clearList)
{
ServerSettings serverSettings = PhotonNetwork.PhotonServerSettings;
Undo.RecordObject(serverSettings, "RPC-list cleared for PUN.");
serverSettings.RpcList.Clear();
EditorUtility.SetDirty(serverSettings);
Debug.LogWarning(CurrentLang.ServerSettingsCleanedWarning);
}
}
#endregion
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: dabbbed2a74eac44dac281f20d706ba8
labels:
- ExitGames
- PUN
- Photon
- Networking
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}

View File

@ -0,0 +1,363 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonGUI.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// GUI scripts for the Editor.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
using UnityEngine;
using UnityEditor;
namespace Photon.Pun
{
public class PhotonGUI
{
#region Styles
static GUIStyle m_DefaultTitleStyle;
public static GUIStyle DefaultTitleStyle
{
get
{
if (m_DefaultTitleStyle == null)
{
m_DefaultTitleStyle = new GUIStyle();
m_DefaultTitleStyle.border = new RectOffset(2, 2, 2, 1);
m_DefaultTitleStyle.margin = new RectOffset(5, 5, 5, 0);
m_DefaultTitleStyle.padding = new RectOffset(5, 5, 0, 0);
m_DefaultTitleStyle.alignment = TextAnchor.MiddleLeft;
m_DefaultTitleStyle.normal.background = ReorderableListResources.texTitleBackground;
m_DefaultTitleStyle.normal.textColor = EditorGUIUtility.isProSkin
? new Color(0.8f, 0.8f, 0.8f)
: new Color(0.2f, 0.2f, 0.2f);
}
return m_DefaultTitleStyle;
}
}
static GUIStyle m_DefaultContainerStyle;
public static GUIStyle DefaultContainerStyle
{
get
{
if (m_DefaultContainerStyle == null)
{
m_DefaultContainerStyle = new GUIStyle();
m_DefaultContainerStyle.border = new RectOffset(2, 2, 1, 2);
m_DefaultContainerStyle.margin = new RectOffset(5, 5, 5, 5);
m_DefaultContainerStyle.padding = new RectOffset(1, 1, 2, 2);
m_DefaultContainerStyle.normal.background = ReorderableListResources.texContainerBackground;
}
return m_DefaultContainerStyle;
}
}
static GUIStyle m_DefaultAddButtonStyle;
public static GUIStyle DefaultAddButtonStyle
{
get
{
if (m_DefaultAddButtonStyle == null)
{
m_DefaultAddButtonStyle = new GUIStyle();
m_DefaultAddButtonStyle.fixedWidth = 30;
m_DefaultAddButtonStyle.fixedHeight = 16;
m_DefaultAddButtonStyle.normal.background = ReorderableListResources.texAddButton;
m_DefaultAddButtonStyle.active.background = ReorderableListResources.texAddButtonActive;
}
return m_DefaultAddButtonStyle;
}
}
static GUIStyle m_DefaultRemoveButtonStyle;
public static GUIStyle DefaultRemoveButtonStyle
{
get
{
if (m_DefaultRemoveButtonStyle == null)
{
m_DefaultRemoveButtonStyle = new GUIStyle();
m_DefaultRemoveButtonStyle.fixedWidth = 30;
m_DefaultRemoveButtonStyle.fixedHeight = 20;
m_DefaultRemoveButtonStyle.active.background = ReorderableListResources.CreatePixelTexture("Dark Pixel (List GUI)", new Color32(18, 18, 18, 255));
m_DefaultRemoveButtonStyle.imagePosition = ImagePosition.ImageOnly;
m_DefaultRemoveButtonStyle.alignment = TextAnchor.MiddleCenter;
}
return m_DefaultRemoveButtonStyle;
}
}
static GUIStyle m_DefaultContainerRowStyle;
public static GUIStyle DefaultContainerRowStyle
{
get
{
if (m_DefaultContainerRowStyle == null)
{
m_DefaultContainerRowStyle = new GUIStyle();
m_DefaultContainerRowStyle.border = new RectOffset(2, 2, 2, 2);
m_DefaultContainerRowStyle.margin = new RectOffset(5, 5, 5, 5);
m_DefaultContainerRowStyle.padding = new RectOffset(1, 1, 2, 2);
m_DefaultContainerRowStyle.normal.background = ReorderableListResources.texContainerBackground;
}
return m_DefaultContainerRowStyle;
}
}
static GUIStyle m_FoldoutBold;
public static GUIStyle FoldoutBold
{
get
{
if (m_FoldoutBold == null)
{
m_FoldoutBold = new GUIStyle(EditorStyles.foldout);
m_FoldoutBold.fontStyle = FontStyle.Bold;
}
return m_FoldoutBold;
}
}
static GUIStyle m_RichLabel;
public static GUIStyle RichLabel
{
get
{
if (m_RichLabel == null)
{
m_RichLabel = new GUIStyle(GUI.skin.label);
m_RichLabel.richText = true;
m_RichLabel.wordWrap = true;
}
return m_RichLabel;
}
}
#endregion
internal static string GetIconPath(string iconFileName)
{
string _thisIconPath = PhotonNetwork.FindAssetPath ("PhotonGUI");
if (string.IsNullOrEmpty(_thisIconPath))
{
_thisIconPath = "Assets/Photon/PhotonUnityNetworking/Code/Editor/"+iconFileName;
}
else
{
_thisIconPath = _thisIconPath.Replace("PhotonGUI.cs", iconFileName);
}
return _thisIconPath;
}
static Texture2D m_HelpIcon;
public static Texture2D HelpIcon
{
get
{
if (m_HelpIcon == null)
{
m_HelpIcon = AssetDatabase.LoadAssetAtPath(GetIconPath("help.png"), typeof(Texture2D)) as Texture2D;
}
return m_HelpIcon;
}
}
static Texture2D m_CopyIcon;
static Texture2D m_CopyIconPro;
public static Texture2D CopyIcon
{
get
{
if (EditorGUIUtility.isProSkin)
{
if (m_CopyIconPro == null)
{
m_CopyIconPro = AssetDatabase.LoadAssetAtPath(GetIconPath("CopyIconPro.png"), typeof(Texture2D)) as Texture2D;
}
return m_CopyIconPro;
}
if (m_CopyIcon == null)
{
m_CopyIcon = AssetDatabase.LoadAssetAtPath(GetIconPath("CopyIcon.png"), typeof(Texture2D)) as Texture2D;
}
return m_CopyIcon;
}
}
#region Interface
public static void ContainerHeader(string headline)
{
DoContainerHeader(headline, 27, 0);
}
public static bool ContainerHeaderToggle(string headline, bool toggle)
{
return DoContainerHeaderToggle(headline, toggle);
}
public static bool ContainerHeaderFoldout(string headline, bool foldout, System.Action buttonAction = null, string buttonName = null)
{
return DoContainerHeaderFoldout(headline, foldout, buttonAction, buttonName);
}
public static Rect ContainerBody(float height)
{
return DoContainerBody(height);
}
public static bool AddButton()
{
Rect controlRect = EditorGUILayout.GetControlRect(false, DefaultAddButtonStyle.fixedHeight - 5);
controlRect.yMin -= 5;
controlRect.yMax -= 5;
Rect addButtonRect = new Rect(controlRect.xMax - DefaultAddButtonStyle.fixedWidth,
controlRect.yMin,
DefaultAddButtonStyle.fixedWidth,
DefaultAddButtonStyle.fixedHeight);
return GUI.Button(addButtonRect, "", DefaultAddButtonStyle);
}
public static void DrawSplitter(Rect position)
{
ReorderableListResources.DrawTexture(position, ReorderableListResources.texItemSplitter);
}
public static void DrawGizmoOptions(
Rect position,
string label,
SerializedProperty gizmoEnabledProperty,
SerializedProperty gizmoColorProperty,
SerializedProperty gizmoTypeProperty,
SerializedProperty gizmoSizeProperty)
{
float height = EditorGUIUtility.singleLineHeight;
float flexibleWidth = Mathf.Max(40, position.width - EditorGUIUtility.labelWidth - 20 - 75 - 5 - 40 - 5);
Rect labelRect = new Rect(position.xMin, position.yMin, EditorGUIUtility.labelWidth, height);
GUI.Label(labelRect, label);
Rect enabledRect = new Rect(labelRect.xMax, labelRect.yMin, 20, height);
EditorGUI.PropertyField(enabledRect, gizmoEnabledProperty, GUIContent.none);
bool oldGUIEnabled = GUI.enabled;
GUI.enabled = gizmoEnabledProperty.boolValue;
Rect colorRect = new Rect(enabledRect.xMax + 5, labelRect.yMin, 70, height);
EditorGUI.PropertyField(colorRect, gizmoColorProperty, GUIContent.none);
Rect typeRect = new Rect(colorRect.xMax + 5, labelRect.yMin, flexibleWidth * 0.7f, height);
EditorGUI.PropertyField(typeRect, gizmoTypeProperty, GUIContent.none);
Rect sizeLabelRect = new Rect(typeRect.xMax + 10, labelRect.yMin, 30, height);
GUI.Label(sizeLabelRect, "Size");
Rect sizeRect = new Rect(sizeLabelRect.xMax + 5, labelRect.yMin, flexibleWidth * 0.3f, height);
EditorGUI.PropertyField(sizeRect, gizmoSizeProperty, GUIContent.none);
GUI.enabled = oldGUIEnabled;
}
#endregion
#region Implementation
static Rect DoContainerBody(float height)
{
Rect controlRect = EditorGUILayout.GetControlRect(false, height);
controlRect.yMin -= 3;
controlRect.yMax -= 2;
int controlID = GUIUtility.GetControlID(FocusType.Passive, controlRect);
if (Event.current.type == EventType.Repaint)
{
PhotonGUI.DefaultContainerStyle.Draw(controlRect, GUIContent.none, controlID);
}
return controlRect;
}
static bool DoContainerHeaderToggle(string headline, bool toggle)
{
Rect rect = DoContainerHeader(headline, 27, 15);
Rect toggleRect = new Rect(rect.xMin + 5, rect.yMin + 5, EditorGUIUtility.labelWidth, rect.height);
return EditorGUI.Toggle(toggleRect, toggle);
}
static bool DoContainerHeaderFoldout(string headline, bool foldout, System.Action buttonAction = null, string buttonLabel = null, float buttonWidth = 48)
{
bool showButton = buttonAction != null;
Rect rect = DoContainerHeader("", 27, 0f);
// Shorten foldout label if button is present, so it doesn't interfere with clicking.
float foldoutWidth = rect.width - (showButton ? 15 + buttonWidth: 15);
Rect foldoutRect = new Rect(rect.xMin + 15, rect.yMin + 5, foldoutWidth, 16);
bool expanded = EditorGUI.Foldout(foldoutRect, foldout, headline, FoldoutBold);
// If a button is defined show it, and invoke action on click.
if (showButton && GUI.Button(new Rect(foldoutRect) { x = foldoutRect.xMax, height = 17, width = buttonWidth - 4 }, buttonLabel == null ? "" : buttonLabel))
{
buttonAction.Invoke();
}
return expanded;
}
static Rect DoContainerHeader(string headline, float height, float contentOffset)
{
GUILayout.Space(5);
Rect controlRect = EditorGUILayout.GetControlRect(false, height);
int controlID = GUIUtility.GetControlID(FocusType.Passive, controlRect);
if (Event.current.type == EventType.Repaint)
{
PhotonGUI.DefaultTitleStyle.Draw(controlRect, GUIContent.none, controlID);
Rect labelRect = new Rect(controlRect.xMin + 5 + contentOffset, controlRect.yMin + 5, controlRect.width, controlRect.height);
GUI.Label(labelRect, headline, EditorStyles.boldLabel);
}
return controlRect;
}
#endregion
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3d2cadb1ccf05074e8ce96b1393846cf
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,13 @@
{
"name": "PhotonUnityNetworking.Editor",
"references": [
"PhotonRealtime",
"PhotonUnityNetworking"
],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4025d00f1ce60da4ea2d0830acf5ebfb
timeCreated: 1537863428
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,191 @@
// ----------------------------------------------------------------------------
// <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;
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 57b538e62a0ca6248bfd354def935e57
labels:
- ExitGames
- PUN
- Photon
- Networking
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}

View File

@ -0,0 +1,394 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonViewInspector.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// Custom inspector for the PhotonView component.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
using System;
using UnityEditor;
using UnityEngine;
using Photon.Realtime;
namespace Photon.Pun
{
[CustomEditor(typeof(PhotonView))]
[CanEditMultipleObjects]
internal class PhotonViewInspector : Editor
{
private PhotonView m_Target;
private static GUIContent ownerTransferGuiContent = new GUIContent("Ownership Transfer", "Determines how ownership changes may be initiated.");
private static GUIContent syncronizationGuiContent = new GUIContent("Synchronization", "Determines how sync updates are culled and sent.");
private static GUIContent observableSearchGuiContent = new GUIContent("Observable Search", "When set to Auto, On Awake, Observables on this GameObject (and child GameObjects) will be found and populate the Observables List." +
"\n\nNested PhotonViews (children with a PhotonView) and their children will not be included in the search.");
public void OnEnable()
{
this.m_Target = (PhotonView)this.target;
if (!Application.isPlaying)
m_Target.FindObservables();
}
public override void OnInspectorGUI()
{
this.m_Target = (PhotonView)this.target;
bool isProjectPrefab = PhotonEditorUtils.IsPrefab(this.m_Target.gameObject);
bool multiSelected = Selection.gameObjects.Length > 1;
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);
}
GUILayout.Space(5);
EditorGUILayout.BeginVertical((GUIStyle)"HelpBox");
// View ID - Hide if we are multi-selected
if (!multiSelected)
{
if (isProjectPrefab)
{
EditorGUILayout.LabelField("View ID", "<i>Set at runtime</i>", new GUIStyle("Label") { richText = true });
}
else if (EditorApplication.isPlaying)
{
EditorGUILayout.LabelField("View ID", this.m_Target.ViewID.ToString());
}
else
{
// this is an object in a scene, modified at edit-time. we can store this as sceneViewId
int idValue = EditorGUILayout.IntField("View ID [1.." + (PhotonNetwork.MAX_VIEW_IDS - 1) + "]", this.m_Target.sceneViewId);
if (this.m_Target.sceneViewId != idValue)
{
Undo.RecordObject(this.m_Target, "Change PhotonView viewID");
this.m_Target.sceneViewId = idValue;
}
}
}
// Locally Controlled
if (EditorApplication.isPlaying)
{
string masterClientHint = PhotonNetwork.IsMasterClient ? " (master)" : "";
EditorGUILayout.LabelField("IsMine:", this.m_Target.IsMine.ToString() + masterClientHint);
Room room = PhotonNetwork.CurrentRoom;
int cretrId = this.m_Target.CreatorActorNr;
Player cretr = (room != null) ? room.GetPlayer(cretrId) : null;
Player owner = this.m_Target.Owner;
Player ctrlr = this.m_Target.Controller;
EditorGUILayout.LabelField("Controller:", (ctrlr != null ? ("[" + ctrlr.ActorNumber + "] '" + ctrlr.NickName + "' " + (ctrlr.IsMasterClient ? " (master)" : "")) : "[0] <null>"));
EditorGUILayout.LabelField("Owner:", (owner != null ? ("[" + owner.ActorNumber + "] '" + owner.NickName + "' " + (owner.IsMasterClient ? " (master)" : "")) : "[0] <null>"));
EditorGUILayout.LabelField("Creator:", (cretr != null ? ("[" +cretrId + "] '" + cretr.NickName + "' " + (cretr.IsMasterClient ? " (master)" : "")) : "[0] <null>"));
}
EditorGUILayout.EndVertical();
EditorGUI.BeginDisabledGroup(Application.isPlaying);
GUILayout.Space(5);
// Ownership section
EditorGUILayout.LabelField("Ownership", (GUIStyle)"BoldLabel");
OwnershipOption own = (OwnershipOption)EditorGUILayout.EnumPopup(ownerTransferGuiContent, this.m_Target.OwnershipTransfer/*, GUILayout.MaxWidth(68), GUILayout.MinWidth(68)*/);
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;
}
GUILayout.Space(5);
// Observables section
EditorGUILayout.LabelField("Observables", (GUIStyle)"BoldLabel");
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("Synchronization"), syncronizationGuiContent);
if (this.m_Target.Synchronization == ViewSynchronization.Off)
{
// Show warning if there are any observables. The null check is because the list allows nulls.
var observed = m_Target.ObservedComponents;
if (observed.Count > 0)
{
for (int i = 0, cnt = observed.Count; i < cnt; ++i)
if (observed[i] != null)
{
EditorGUILayout.HelpBox("Synchronization is set to Off. Select a Synchronization setting in order to sync the listed Observables.", MessageType.Warning);
break;
}
}
}
PhotonView.ObservableSearch autoFindObservables = (PhotonView.ObservableSearch)EditorGUILayout.EnumPopup(observableSearchGuiContent, m_Target.observableSearch);
if (m_Target.observableSearch != autoFindObservables)
{
Undo.RecordObject(this.m_Target, "Change Auto Find Observables Toggle");
m_Target.observableSearch = autoFindObservables;
}
m_Target.FindObservables();
if (!multiSelected)
{
bool disableList = Application.isPlaying || autoFindObservables != PhotonView.ObservableSearch.Manual;
if (disableList)
EditorGUI.BeginDisabledGroup(true);
this.DrawObservedComponentsList(disableList);
if (disableList)
EditorGUI.EndDisabledGroup();
}
// Cleanup: save and fix look
if (GUI.changed)
{
PhotonViewHandler.OnHierarchyChanged(); // TODO: check if needed
}
EditorGUI.EndDisabledGroup();
}
private int GetObservedComponentsCount()
{
int count = 0;
for (int i = 0; i < this.m_Target.ObservedComponents.Count; ++i)
{
if (this.m_Target.ObservedComponents[i] != null)
{
count++;
}
}
return count;
}
/// <summary>
/// Find Observables, and then baking them into the serialized object.
/// </summary>
private void EditorFindObservables()
{
Undo.RecordObject(serializedObject.targetObject, "Find Observables");
var property = serializedObject.FindProperty("ObservedComponents");
// Just doing a Find updates the Observables list, but Unity fails to save that change.
// Instead we do the find, and then iterate the found objects into the serialize property, then apply that.
property.ClearArray();
m_Target.FindObservables(true);
for(int i = 0; i < m_Target.ObservedComponents.Count; ++i)
{
property.InsertArrayElementAtIndex(i);
property.GetArrayElementAtIndex(i).objectReferenceValue = m_Target.ObservedComponents[i];
}
serializedObject.ApplyModifiedProperties();
}
private void DrawObservedComponentsList(bool disabled = false)
{
SerializedProperty listProperty = this.serializedObject.FindProperty("ObservedComponents");
if (listProperty == null)
{
return;
}
float containerElementHeight = 22;
float containerHeight = listProperty.arraySize * containerElementHeight;
string foldoutLabel = "Observed Components (" + this.GetObservedComponentsCount() + ")";
bool isOpen = PhotonGUI.ContainerHeaderFoldout(foldoutLabel, this.serializedObject.FindProperty("ObservedComponentsFoldoutOpen").boolValue, () => EditorFindObservables(), "Find");
this.serializedObject.FindProperty("ObservedComponentsFoldoutOpen").boolValue = isOpen;
if (isOpen == false)
{
containerHeight = 0;
}
//Texture2D statsIcon = AssetDatabase.LoadAssetAtPath( "Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewStats.png", typeof( Texture2D ) ) as Texture2D;
Rect containerRect = PhotonGUI.ContainerBody(containerHeight);
bool wasObservedComponentsEmpty = this.m_Target.ObservedComponents.FindAll(item => item != null).Count == 0;
if (isOpen == true)
{
for (int i = 0; i < listProperty.arraySize; ++i)
{
Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + containerElementHeight * i, containerRect.width, containerElementHeight);
{
Rect texturePosition = new Rect(elementRect.xMin + 6, elementRect.yMin + elementRect.height / 2f - 1, 9, 5);
ReorderableListResources.DrawTexture(texturePosition, ReorderableListResources.texGrabHandle);
Rect propertyPosition = new Rect(elementRect.xMin + 20, elementRect.yMin + 3, elementRect.width - 45, 16);
// keep track of old type to catch when a new type is observed
Type _oldType = listProperty.GetArrayElementAtIndex(i).objectReferenceValue != null ? listProperty.GetArrayElementAtIndex(i).objectReferenceValue.GetType() : null;
EditorGUI.PropertyField(propertyPosition, listProperty.GetArrayElementAtIndex(i), new GUIContent());
// new type, could be different from old type
Type _newType = listProperty.GetArrayElementAtIndex(i).objectReferenceValue != null ? listProperty.GetArrayElementAtIndex(i).objectReferenceValue.GetType() : null;
// the user dropped a Transform, we must change it by adding a PhotonTransformView and observe that instead
if (_oldType != _newType)
{
if (_newType == typeof(PhotonView))
{
listProperty.GetArrayElementAtIndex(i).objectReferenceValue = null;
Debug.LogError("PhotonView Detected you dropped a PhotonView, this is not allowed. \n It's been removed from observed field.");
}
else if (_newType == typeof(Transform))
{
// try to get an existing PhotonTransformView ( we don't want any duplicates...)
PhotonTransformView _ptv = this.m_Target.gameObject.GetComponent<PhotonTransformView>();
if (_ptv == null)
{
// no ptv yet, we create one and enable position and rotation, no scaling, as it's too rarely needed to take bandwidth for nothing
_ptv = Undo.AddComponent<PhotonTransformView>(this.m_Target.gameObject);
}
// switch observe from transform to _ptv
listProperty.GetArrayElementAtIndex(i).objectReferenceValue = _ptv;
Debug.Log("PhotonView has detected you dropped a Transform. Instead it's better to observe a PhotonTransformView for better control and performances");
}
else if (_newType == typeof(Rigidbody))
{
Rigidbody _rb = listProperty.GetArrayElementAtIndex(i).objectReferenceValue as Rigidbody;
// try to get an existing PhotonRigidbodyView ( we don't want any duplicates...)
PhotonRigidbodyView _prbv = _rb.gameObject.GetComponent<PhotonRigidbodyView>();
if (_prbv == null)
{
// no _prbv yet, we create one
_prbv = Undo.AddComponent<PhotonRigidbodyView>(_rb.gameObject);
}
// switch observe from transform to _prbv
listProperty.GetArrayElementAtIndex(i).objectReferenceValue = _prbv;
Debug.Log("PhotonView has detected you dropped a RigidBody. Instead it's better to observe a PhotonRigidbodyView for better control and performances");
}
else if (_newType == typeof(Rigidbody2D))
{
// try to get an existing PhotonRigidbody2DView ( we don't want any duplicates...)
PhotonRigidbody2DView _prb2dv = this.m_Target.gameObject.GetComponent<PhotonRigidbody2DView>();
if (_prb2dv == null)
{
// no _prb2dv yet, we create one
_prb2dv = Undo.AddComponent<PhotonRigidbody2DView>(this.m_Target.gameObject);
}
// switch observe from transform to _prb2dv
listProperty.GetArrayElementAtIndex(i).objectReferenceValue = _prb2dv;
Debug.Log("PhotonView has detected you dropped a Rigidbody2D. Instead it's better to observe a PhotonRigidbody2DView for better control and performances");
}
else if (_newType == typeof(Animator))
{
// try to get an existing PhotonAnimatorView ( we don't want any duplicates...)
PhotonAnimatorView _pav = this.m_Target.gameObject.GetComponent<PhotonAnimatorView>();
if (_pav == null)
{
// no _pav yet, we create one
_pav = Undo.AddComponent<PhotonAnimatorView>(this.m_Target.gameObject);
}
// switch observe from transform to _prb2dv
listProperty.GetArrayElementAtIndex(i).objectReferenceValue = _pav;
Debug.Log("PhotonView has detected you dropped a Animator, so we switched to PhotonAnimatorView so that you can serialized the Animator variables");
}
else if (!typeof(IPunObservable).IsAssignableFrom(_newType))
{
bool _ignore = false;
#if PLAYMAKER
_ignore = _newType == typeof(PlayMakerFSM);// Photon Integration for PlayMaker will swap at runtime to a proxy using iPunObservable.
#endif
if (_newType == null || _newType == typeof(Rigidbody) || _newType == typeof(Rigidbody2D))
{
_ignore = true;
}
if (!_ignore)
{
listProperty.GetArrayElementAtIndex(i).objectReferenceValue = null;
Debug.LogError("PhotonView Detected you dropped a Component missing IPunObservable Interface,\n You dropped a <" + _newType + "> instead. It's been removed from observed field.");
}
}
}
//Debug.Log( listProperty.GetArrayElementAtIndex( i ).objectReferenceValue.GetType() );
//Rect statsPosition = new Rect( propertyPosition.xMax + 7, propertyPosition.yMin, statsIcon.width, statsIcon.height );
//ReorderableListResources.DrawTexture( statsPosition, statsIcon );
Rect removeButtonRect = new Rect(elementRect.xMax - PhotonGUI.DefaultRemoveButtonStyle.fixedWidth,
elementRect.yMin + 2,
PhotonGUI.DefaultRemoveButtonStyle.fixedWidth,
PhotonGUI.DefaultRemoveButtonStyle.fixedHeight);
GUI.enabled = !disabled && listProperty.arraySize > 1;
if (GUI.Button(removeButtonRect, new GUIContent(ReorderableListResources.texRemoveButton), PhotonGUI.DefaultRemoveButtonStyle))
{
listProperty.DeleteArrayElementAtIndex(i);
}
GUI.enabled = !disabled;
if (i < listProperty.arraySize - 1)
{
texturePosition = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1);
PhotonGUI.DrawSplitter(texturePosition);
}
}
}
}
if (PhotonGUI.AddButton())
{
listProperty.InsertArrayElementAtIndex(Mathf.Max(0, listProperty.arraySize - 1));
}
this.serializedObject.ApplyModifiedProperties();
bool isObservedComponentsEmpty = this.m_Target.ObservedComponents.FindAll(item => item != null).Count == 0;
if (wasObservedComponentsEmpty == true && isObservedComponentsEmpty == false && this.m_Target.Synchronization == ViewSynchronization.Off)
{
Undo.RecordObject(this.m_Target, "Change PhotonView");
this.m_Target.Synchronization = ViewSynchronization.UnreliableOnChange;
this.serializedObject.Update();
}
if (wasObservedComponentsEmpty == false && isObservedComponentsEmpty == true)
{
Undo.RecordObject(this.m_Target, "Change PhotonView");
this.m_Target.Synchronization = ViewSynchronization.Off;
this.serializedObject.Update();
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e73a30c46df19194f873ea7a9ce12753
labels:
- ExitGames
- PUN
- Photon
- Networking
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

View File

@ -0,0 +1,45 @@
fileFormatVersion: 2
guid: 1faa1cf0448470c4ebbb23b97759ab50
TextureImporter:
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 256
textureSettings:
filterMode: 0
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

View File

@ -0,0 +1,178 @@
// ----------------------------------------------------------------------------
// <copyright file="PunSceneSettings.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// Optional lowest-viewID setting per-scene. So PhotonViews don't get the same ID.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Photon.Pun
{
[Serializable]
public class SceneSetting
{
public SceneAsset sceneAsset;
public string sceneName;
public int minViewId;
}
[HelpURL("https://doc.photonengine.com/en-us/pun/current/getting-started/feature-overview#scene_photonviews_in_multiple_scenes")]
public class PunSceneSettings : ScriptableObject
{
#if UNITY_EDITOR
// Suppressing compiler warning "this variable is never used". Only used in the CustomEditor, only in Editor
#pragma warning disable 0414
[SerializeField]
bool SceneSettingsListFoldoutOpen = true;
#pragma warning restore 0414
#endif
[SerializeField]
public List<SceneSetting> MinViewIdPerScene = new List<SceneSetting>();
private const string SceneSettingsFileName = "PunSceneSettingsFile.asset";
// we use the path to PunSceneSettings.cs as path to create a scene settings file
private static string punSceneSettingsCsPath;
public static string PunSceneSettingsCsPath
{
get
{
if (!string.IsNullOrEmpty(punSceneSettingsCsPath))
{
return punSceneSettingsCsPath;
}
// Unity 4.3.4 does not yet have AssetDatabase.FindAssets(). Would be easier.
var result = Directory.GetFiles(Application.dataPath, "PunSceneSettings.cs", SearchOption.AllDirectories);
if (result.Length >= 1)
{
punSceneSettingsCsPath = Path.GetDirectoryName(result[0]);
punSceneSettingsCsPath = punSceneSettingsCsPath.Replace('\\', '/');
punSceneSettingsCsPath = punSceneSettingsCsPath.Replace(Application.dataPath, "Assets");
// AssetDatabase paths have to use '/' and are relative to the project's folder. Always.
punSceneSettingsCsPath = punSceneSettingsCsPath + "/" + SceneSettingsFileName;
}
return punSceneSettingsCsPath;
}
}
private static PunSceneSettings instanceField;
public static PunSceneSettings Instance
{
get
{
if (instanceField != null)
{
return instanceField;
}
instanceField = (PunSceneSettings)AssetDatabase.LoadAssetAtPath(PunSceneSettingsCsPath, typeof(PunSceneSettings));
if (instanceField == null)
{
instanceField = CreateInstance<PunSceneSettings>();
#pragma warning disable 0168
try
{
AssetDatabase.CreateAsset(instanceField, PunSceneSettingsCsPath);
}
catch (Exception e)
{
#if PHOTON_UNITY_NETWORKING
Debug.LogError("-- WARNING: PROJECT CLEANUP NECESSARY -- If you delete pun from your project, make sure you also clean up the Scripting define symbols from any reference to PUN like 'PHOTON_UNITY_NETWORKING ");
#endif
}
#pragma warning restore 0168
}
return instanceField;
}
}
public static int MinViewIdForScene(string sceneName)
{
if (string.IsNullOrEmpty(sceneName))
{
return 1;
}
PunSceneSettings pss = Instance;
if (pss == null)
{
Debug.LogError("pss cant be null");
return 1;
}
foreach (SceneSetting setting in pss.MinViewIdPerScene)
{
if (setting.sceneName.Equals(sceneName))
{
return setting.minViewId;
}
}
return 1;
}
public static void SanitizeSceneSettings()
{
if (Instance == null)
{
return;
}
#if UNITY_EDITOR
foreach (SceneSetting sceneSetting in Instance.MinViewIdPerScene)
{
if (sceneSetting.sceneAsset == null && !string.IsNullOrEmpty(sceneSetting.sceneName))
{
string[] guids = AssetDatabase.FindAssets(sceneSetting.sceneName + " t:SceneAsset");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
if (Path.GetFileNameWithoutExtension(path) == sceneSetting.sceneName)
{
sceneSetting.sceneAsset =
AssetDatabase.LoadAssetAtPath<SceneAsset>(
AssetDatabase.GUIDToAssetPath(guid));
// Debug.Log("SceneSettings : ''"+sceneSetting.sceneName+"'' scene is missing: Issue corrected",Instance);
break;
}
}
//Debug.Log("SceneSettings : ''"+sceneSetting.sceneName+"'' scene is missing",Instance);
continue;
}
if (sceneSetting.sceneAsset != null && sceneSetting.sceneName!= sceneSetting.sceneAsset.name )
{
// Debug.Log("SceneSettings : '"+sceneSetting.sceneName+"' mismatch with sceneAsset: '"+sceneSetting.sceneAsset.name+"' : Issue corrected",Instance);
sceneSetting.sceneName = sceneSetting.sceneAsset.name;
continue;
}
}
#endif
}
}
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fc3284eace5a64d4bb516df7d7effdb9
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}

View File

@ -0,0 +1,21 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fc3284eace5a64d4bb516df7d7effdb9, type: 3}
m_Name: PunSceneSettingsFile
m_EditorClassIdentifier:
SceneSettingsListFoldoutOpen: 1
MinViewIdPerScene:
- sceneAsset: {fileID: 102900000, guid: 559222f4671e440cba71aecba1de3505, type: 3}
sceneName: SceneView_A
minViewId: 2
- sceneAsset: {fileID: 102900000, guid: a81615022a16c489aac8daadf8f51fae, type: 3}
sceneName: SceneView_B
minViewId: 10

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d0aacb83307022d449e90a09d28222ae

View File

@ -0,0 +1,260 @@
// ----------------------------------------------------------------------------
// <copyright file="PunSceneSettingsInspector.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2019 Exit Games GmbH
// </copyright>
// <summary>
// Custom inspector for the PunSceneSettings component.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Photon.Pun
{
[CustomEditor(typeof(PunSceneSettings))]
internal class PunSceneSettingsInspector : Editor
{
private PunSceneSettings m_Target;
private bool isOpen;
private List<string> _duplicateScenesDefinition;
private List<int> _duplicateViewIdDefinition;
private SerializedProperty listProperty;
private SerializedProperty _sceneSettings_i;
private SerializedProperty sceneNameProperty;
private SerializedProperty sceneAssetProperty;
private SerializedProperty minViewIdProperty;
private bool _firstTime;
public override void OnInspectorGUI()
{
this.m_Target = (PunSceneSettings) this.target;
// error checking
_duplicateScenesDefinition = m_Target.MinViewIdPerScene.GroupBy(x => x.sceneName)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToList();
_duplicateViewIdDefinition = m_Target.MinViewIdPerScene.GroupBy(x => x.minViewId)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToList();
DrawSceneSettingsList();
foreach (string dup in _duplicateScenesDefinition)
{
EditorGUILayout.LabelField("Found duplicates for scene",dup);
}
foreach (SceneSetting sceneSettings in m_Target.MinViewIdPerScene)
{
if (_duplicateViewIdDefinition.Contains(sceneSettings.minViewId))
{
GUILayout.Label("Found view Id duplicates '"+sceneSettings.minViewId+"' for scene: " +sceneSettings.sceneName);
}
if (sceneSettings.minViewId > PhotonNetwork.MAX_VIEW_IDS)
{
GUILayout.Label(sceneSettings.sceneName+" view Id can not exceed the max view Id "+PhotonNetwork.MAX_VIEW_IDS);
}
if (sceneSettings.minViewId < 1)
{
GUILayout.Label(sceneSettings.sceneName+" view Id can not be less than 1");
}
if (sceneSettings.sceneAsset == null && !string.IsNullOrEmpty(sceneSettings.sceneName))
{
GUILayout.Label("'"+sceneSettings.sceneName+"' scene is missing in the project");
}
}
_firstTime = false;
}
private void OnEnable()
{
_firstTime = true;
}
private void DrawSceneSettingsList()
{
GUILayout.Space(5);
// check for changes ( from undo for example)
this.serializedObject.Update();
listProperty = this.serializedObject.FindProperty("MinViewIdPerScene");
if (listProperty == null)
{
return;
}
float containerElementHeight = 44;
float containerHeight = listProperty.arraySize * containerElementHeight;
isOpen = PhotonGUI.ContainerHeaderFoldout("Scene Settings (" + listProperty.arraySize + ")", this.serializedObject.FindProperty("SceneSettingsListFoldoutOpen").boolValue);
this.serializedObject.FindProperty("SceneSettingsListFoldoutOpen").boolValue = isOpen;
if (isOpen == false)
{
containerHeight = 0;
}
Rect containerRect = PhotonGUI.ContainerBody(containerHeight);
if (isOpen == true)
{
for (int i = 0; i < listProperty.arraySize; ++i)
{
Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + containerElementHeight * i,
containerRect.width, containerElementHeight);
{
Rect texturePosition = new Rect(elementRect.xMin + 6,
elementRect.yMin + elementRect.height / 2f - 1, 9, 5);
ReorderableListResources.DrawTexture(texturePosition, ReorderableListResources.texGrabHandle);
Rect propertyPosition = new Rect(elementRect.xMin + 20, elementRect.yMin + 3,
elementRect.width - 45, 16);
_sceneSettings_i = listProperty.GetArrayElementAtIndex(i);
sceneNameProperty = _sceneSettings_i.FindPropertyRelative("sceneName");
sceneAssetProperty = _sceneSettings_i.FindPropertyRelative("sceneAsset");
minViewIdProperty = _sceneSettings_i.FindPropertyRelative("minViewId");
string _sceneName = sceneNameProperty.stringValue;
SceneAsset _sceneAsset = m_Target.MinViewIdPerScene[i].sceneAsset;
// check if we need to find the scene asset based on the scene name. This is for backward compatibility or when the scene asset was deleted
if (_firstTime)
{
if (_sceneAsset == null && !string.IsNullOrEmpty(_sceneName))
{
string[] guids = AssetDatabase.FindAssets(_sceneName + " t:SceneAsset");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
if (Path.GetFileNameWithoutExtension(path) == _sceneName)
{
sceneAssetProperty.objectReferenceValue =
AssetDatabase.LoadAssetAtPath<SceneAsset>(
AssetDatabase.GUIDToAssetPath(guid));
break;
}
}
}
}
bool _missingSceneAsset = _sceneAsset == null && !string.IsNullOrEmpty(_sceneName);
// if we don't have a scene asset for the serialized scene named, we show an error.
if (_missingSceneAsset ||
(sceneNameProperty!=null && _duplicateScenesDefinition!=null && _duplicateScenesDefinition.Contains(sceneNameProperty.stringValue))
)
{
GUI.color = Color.red;
}
EditorGUI.BeginChangeCheck();
string _label = _missingSceneAsset
? "Scene Asset: Missing '" + _sceneName + "'"
: "Scene Asset";
EditorGUI.PropertyField(propertyPosition,sceneAssetProperty, new GUIContent(_label));
if (EditorGUI.EndChangeCheck())
{
_sceneAsset = sceneAssetProperty.objectReferenceValue as SceneAsset;
if (_sceneAsset == null && !string.IsNullOrEmpty(sceneNameProperty.stringValue))
{
sceneNameProperty.stringValue = null;
}
else if (sceneNameProperty.stringValue != _sceneAsset.name)
{
sceneNameProperty.stringValue = _sceneAsset.name;
}
}
// EditorGUI.PropertyField(propertyPosition, sceneNameProperty,
// new GUIContent("Scene Name"));
GUI.color = Color.white;
if ( minViewIdProperty.intValue<1 || minViewIdProperty.intValue> PhotonNetwork.MAX_VIEW_IDS)
{
GUI.color = Color.red;
}
Rect secondPropertyPosition = new Rect(elementRect.xMin + 20, elementRect.yMin + containerElementHeight/2,
elementRect.width - 45, 16);
EditorGUI.PropertyField(secondPropertyPosition, _sceneSettings_i.FindPropertyRelative("minViewId"),
new GUIContent("Minimum View ID"));
GUI.color = Color.white;
//Debug.Log( listProperty.GetArrayElementAtIndex( i ).objectReferenceValue.GetType() );
//Rect statsPosition = new Rect( propertyPosition.xMax + 7, propertyPosition.yMin, statsIcon.width, statsIcon.height );
//ReorderableListResources.DrawTexture( statsPosition, statsIcon );
Rect removeButtonRect = new Rect(
elementRect.xMax - PhotonGUI.DefaultRemoveButtonStyle.fixedWidth,
elementRect.yMin + 2,
PhotonGUI.DefaultRemoveButtonStyle.fixedWidth,
PhotonGUI.DefaultRemoveButtonStyle.fixedHeight);
if (GUI.Button(removeButtonRect, new GUIContent(ReorderableListResources.texRemoveButton),
PhotonGUI.DefaultRemoveButtonStyle))
{
listProperty.DeleteArrayElementAtIndex(i);
Undo.RecordObject(this.m_Target, "Removed SceneSettings Entry");
}
if (i < listProperty.arraySize - 1)
{
texturePosition = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4,
1);
PhotonGUI.DrawSplitter(texturePosition);
}
}
}
}
if (PhotonGUI.AddButton())
{
this.listProperty.InsertArrayElementAtIndex(Mathf.Max(0, listProperty.arraySize - 1));
_sceneSettings_i = this.listProperty.GetArrayElementAtIndex(listProperty.arraySize - 1);
sceneNameProperty = _sceneSettings_i.FindPropertyRelative("sceneName");
sceneAssetProperty = _sceneSettings_i.FindPropertyRelative("sceneAsset");
minViewIdProperty = _sceneSettings_i.FindPropertyRelative("minViewId");
sceneAssetProperty.objectReferenceValue = null;
sceneNameProperty.stringValue = "";
minViewIdProperty.intValue = 1;
Undo.RecordObject(this.m_Target, "Added SceneSettings Entry");
}
this.serializedObject.ApplyModifiedProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ad59deacfd0848dcb64a51b0a0eb960
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 62126d9bb7b8eb64ea07a039d902d0ac
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,26 @@
Copyright (c) 2013, Rotorz Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c2fbd2e43c3dfae4d9830e9921238cf5
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,237 @@
// Copyright (c) 2012-2013 Rotorz Limited. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
using UnityEngine;
using UnityEditor;
using System;
namespace Photon.Pun
{
/// <summary>
/// Resources to assist with reorderable list control.
/// </summary>
internal static class ReorderableListResources
{
static ReorderableListResources()
{
GenerateSpecialTextures();
LoadResourceAssets();
}
#region Texture Resources
private enum ResourceName
{
add_button = 0,
add_button_active,
container_background,
grab_handle,
remove_button,
remove_button_active,
title_background,
}
/// <summary>
/// Resource assets for light skin.
/// </summary>
/// <remarks>
/// <para>Resource assets are PNG images which have been encoded using a base-64
/// string so that actual asset files are not necessary.</para>
/// </remarks>
private static string[] s_LightSkin = {
"iVBORw0KGgoAAAANSUhEUgAAAB4AAAAQCAYAAAABOs/SAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAW0lEQVRIS+3NywnAQAhF0anI4mzVCmzBBl7QEBgGE5JFhBAXd+OHM5gZZgYRKcktNxu+HRFF2e6qhtOjtQM7K/tZ+xY89wSbazg9eqOfw6oag4rcChjY8coAjA2l1RxFDY8IFAAAAABJRU5ErkJggg==",
"iVBORw0KGgoAAAANSUhEUgAAAB4AAAAQCAYAAAABOs/SAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGlJREFUeNpiFBER+f/jxw8GNjY2BnqAX79+MXBwcDAwMQwQGHoWnzp1CoxHjo8pBSykBi8+MTMzs2HmY2QfwXxKii9HExdZgNwgHuFB/efPH7pZCLOL8f///wyioqL/6enbL1++MAIEGABvGSLA+9GPZwAAAABJRU5ErkJggg==",
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAMElEQVQYV2P4//8/Q1FR0X8YBvHBAp8+ffp/+fJlMA3igwUfPnwIFgDRYEFM7f8ZAG1EOYL9INrfAAAAAElFTkSuQmCC",
"iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAIElEQVQYV2P49OnTf0KYobCw8D8hzPD/P2FMLesK/wMAs5yJpK+6aN4AAAAASUVORK5CYII=",
"iVBORw0KGgoAAAANSUhEUgAAAAgAAAACCAIAAADq9gq6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABVJREFUeNpiVFZWZsAGmBhwAIAAAwAURgBt4C03ZwAAAABJRU5ErkJggg==",
"iVBORw0KGgoAAAANSUhEUgAAAAgAAAACCAIAAADq9gq6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABVJREFUeNpivHPnDgM2wMSAAwAEGAB8VgKYlvqkBwAAAABJRU5ErkJggg==",
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpi/P//P0NxcfF/BgRgZP78+fN/VVVVhpCQEAZjY2OGs2fPNrCApBwdHRkePHgAVwoWnDVrFgMyAAgwAAt4E1dCq1obAAAAAElFTkSuQmCC"
};
/// <summary>
/// Resource assets for dark skin.
/// </summary>
/// <remarks>
/// <para>Resource assets are PNG images which have been encoded using a base-64
/// string so that actual asset files are not necessary.</para>
/// </remarks>
private static string[] s_DarkSkin = {
"iVBORw0KGgoAAAANSUhEUgAAAB4AAAAQCAYAAAABOs/SAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIBJREFUeNpiVFZW/u/i4sLw4sULBnoACQkJhj179jAwMQwQGHoWl5aWgvHI8TGlgIXU4MUn1t3dPcx8HB8fD2cvXLgQQ0xHR4c2FmMzmBTLhl5QYwt2cn1MtsXkWjg4gvrt27fgWoMeAGQXCDD+//+fQUVF5T89fXvnzh1GgAADAFmSI1Ed3FqgAAAAAElFTkSuQmCC",
"iVBORw0KGgoAAAANSUhEUgAAAB4AAAAQCAYAAAABOs/SAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHlJREFUeNpiFBER+f/jxw8GNjY2BnqAX79+MXBwcDAwMQwQGHoWv3nzBoxHjo8pBSykBi8+MWAOGWY+5uLigrO/ffuGIYbMppnF5Fg2tFM1yKfk+pbkoKZGEA+OVP3nzx+6WQizi/H///8MoqKi/+np2y9fvjACBBgAoTYjgvihfz0AAAAASUVORK5CYII=",
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpi/P//P4OKisp/Bii4c+cOIwtIwMXFheHFixcMEhISYAVMINm3b9+CBUA0CDCiazc0NGQECDAAdH0YelA27kgAAAAASUVORK5CYII=",
"iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACRJREFUeNpizM3N/c9AADAqKysTVMTi5eXFSFAREFPHOoAAAwBCfwcAO8g48QAAAABJRU5ErkJggg==",
"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAYAAACzzX7wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi/P//PwM+wHL06FG8KpgYCABGZWVlvCYABBgA7/sHvGw+cz8AAAAASUVORK5CYII=",
"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAYAAACzzX7wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi/P//PwM+wPKfgAomBgKAhYuLC68CgAADAAxjByOjCHIRAAAAAElFTkSuQmCC",
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADtJREFUeNpi/P//P4OKisp/Bii4c+cOIwtIQE9Pj+HLly9gQRCfBcQACbx69QqmmAEseO/ePQZkABBgAD04FXsmmijSAAAAAElFTkSuQmCC"
};
/// <summary>
/// Gets light or dark texture "add_button.png".
/// </summary>
public static Texture2D texAddButton
{
get { return s_Cached[ (int)ResourceName.add_button ]; }
}
/// <summary>
/// Gets light or dark texture "add_button_active.png".
/// </summary>
public static Texture2D texAddButtonActive
{
get { return s_Cached[ (int)ResourceName.add_button_active ]; }
}
/// <summary>
/// Gets light or dark texture "container_background.png".
/// </summary>
public static Texture2D texContainerBackground
{
get { return s_Cached[ (int)ResourceName.container_background ]; }
}
/// <summary>
/// Gets light or dark texture "grab_handle.png".
/// </summary>
public static Texture2D texGrabHandle
{
get { return s_Cached[ (int)ResourceName.grab_handle ]; }
}
/// <summary>
/// Gets light or dark texture "remove_button.png".
/// </summary>
public static Texture2D texRemoveButton
{
get { return s_Cached[ (int)ResourceName.remove_button ]; }
}
/// <summary>
/// Gets light or dark texture "remove_button_active.png".
/// </summary>
public static Texture2D texRemoveButtonActive
{
get { return s_Cached[ (int)ResourceName.remove_button_active ]; }
}
/// <summary>
/// Gets light or dark texture "title_background.png".
/// </summary>
public static Texture2D texTitleBackground
{
get { return s_Cached[ (int)ResourceName.title_background ]; }
}
#endregion
#region Generated Resources
public static Texture2D texItemSplitter { get; private set; }
/// <summary>
/// Generate special textures.
/// </summary>
private static void GenerateSpecialTextures()
{
var splitterColor = EditorGUIUtility.isProSkin
? new Color( 1f, 1f, 1f, 0.14f )
: new Color( 0.59f, 0.59f, 0.59f, 0.55f )
;
texItemSplitter = CreatePixelTexture( "(Generated) Item Splitter", splitterColor );
}
/// <summary>
/// Create 1x1 pixel texture of specified color.
/// </summary>
/// <param name="name">Name for texture object.</param>
/// <param name="color">Pixel color.</param>
/// <returns>
/// The new <c>Texture2D</c> instance.
/// </returns>
public static Texture2D CreatePixelTexture( string name, Color color )
{
var tex = new Texture2D( 1, 1, TextureFormat.ARGB32, false, true );
tex.name = name;
tex.hideFlags = HideFlags.HideAndDontSave;
tex.filterMode = FilterMode.Point;
tex.SetPixel( 0, 0, color );
tex.Apply();
return tex;
}
#endregion
#region Load PNG from Base-64 Encoded String
private static Texture2D[] s_Cached;
/// <summary>
/// Read textures from base-64 encoded strings. Automatically selects assets based
/// upon whether the light or dark (pro) skin is active.
/// </summary>
private static void LoadResourceAssets()
{
var skin = EditorGUIUtility.isProSkin ? s_DarkSkin : s_LightSkin;
s_Cached = new Texture2D[ skin.Length ];
for( int i = 0; i < s_Cached.Length; ++i )
{
// Get image data (PNG) from base64 encoded strings.
byte[] imageData = Convert.FromBase64String( skin[ i ] );
// Gather image size from image data.
int texWidth, texHeight;
GetImageSize( imageData, out texWidth, out texHeight );
// Generate texture asset.
var tex = new Texture2D( texWidth, texHeight, TextureFormat.ARGB32, false, true );
tex.hideFlags = HideFlags.HideAndDontSave;
tex.name = "(Generated) ReorderableList:" + i;
tex.filterMode = FilterMode.Point;
tex.LoadImage( imageData );
s_Cached[ i ] = tex;
}
s_LightSkin = null;
s_DarkSkin = null;
}
/// <summary>
/// Read width and height if PNG file in pixels.
/// </summary>
/// <param name="imageData">PNG image data.</param>
/// <param name="width">Width of image in pixels.</param>
/// <param name="height">Height of image in pixels.</param>
private static void GetImageSize( byte[] imageData, out int width, out int height )
{
width = ReadInt( imageData, 3 + 15 );
height = ReadInt( imageData, 3 + 15 + 2 + 2 );
}
private static int ReadInt( byte[] imageData, int offset )
{
return ( imageData[ offset ] << 8 ) | imageData[ offset + 1 ];
}
#endregion
#region GUI Helper
private static GUIStyle s_TempStyle = new GUIStyle();
/// <summary>
/// Draw texture using <see cref="GUIStyle"/> to workaround bug in Unity where
/// <see cref="GUI.DrawTexture"/> flickers when embedded inside a property drawer.
/// </summary>
/// <param name="position">Position of which to draw texture in space of GUI.</param>
/// <param name="texture">Texture.</param>
public static void DrawTexture( Rect position, Texture2D texture )
{
if( Event.current.type != EventType.Repaint )
return;
s_TempStyle.normal.background = texture;
s_TempStyle.Draw( position, GUIContent.none, false, false, false, false );
}
#endregion
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 60c609ded101b0a468fb5cf27b31cf27
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,322 @@
// ----------------------------------------------------------------------------
// <copyright file="ServerSettingsInspector.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// This is a custom editor for the ServerSettings scriptable object.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
using System;
using UnityEditor;
using UnityEngine;
using Photon.Pun;
using ExitGames.Client.Photon;
using System.Collections.Generic;
using System.Reflection;
using Photon.Realtime;
namespace Photon.Pun
{
[CustomEditor(typeof(ServerSettings))]
public class ServerSettingsInspector : Editor
{
private string versionPhoton;
private string[] regionsPrefsList;
private string prefLabel;
private const string notAvailableLabel = "n/a";
private string rpcCrc;
private bool showRpcs;
private GUIStyle vertboxStyle;
public void Awake()
{
this.versionPhoton = System.Reflection.Assembly.GetAssembly(typeof(PhotonPeer)).GetName().Version.ToString();
}
public override void OnInspectorGUI()
{
if (vertboxStyle == null)
vertboxStyle = new GUIStyle("HelpBox") { padding = new RectOffset(6, 6, 6, 6) };
SerializedObject sObj = new SerializedObject(this.target);
ServerSettings settings = this.target as ServerSettings;
EditorGUI.BeginChangeCheck();
#region Version Vertical Box
EditorGUILayout.BeginVertical(/*vertboxStyle*/);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(new GUIContent("Version:", "Version of PUN and Photon3Unity3d.dll."));
GUILayout.FlexibleSpace();
var helpicorect = EditorGUILayout.GetControlRect(GUILayout.MaxWidth(16));
EditorGUIUtility.AddCursorRect(helpicorect, MouseCursor.Link);
if (GUI.Button(helpicorect, PhotonGUI.HelpIcon, GUIStyle.none))
{
Application.OpenURL(PhotonEditor.UrlPunSettings);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.LabelField("Pun: " + PhotonNetwork.PunVersion + " Photon lib: " + this.versionPhoton);
EditorGUILayout.EndVertical();
#endregion Version Vertical Box
EditorGUI.indentLevel--;
SerializedProperty showSettingsProp = this.serializedObject.FindProperty("ShowSettings");
bool showSettings = showSettingsProp.Foldout(new GUIContent("Server/Cloud Settings", "Core Photon Server/Cloud settings."));
EditorGUI.indentLevel++;
if (showSettings != settings.ShowSettings)
{
showSettingsProp.boolValue = showSettings;
}
if (showSettingsProp.boolValue)
{
SerializedProperty settingsSp = this.serializedObject.FindProperty("AppSettings");
EditorGUI.indentLevel++;
//Realtime APP ID
this.BuildAppIdField(settingsSp.FindPropertyRelative("AppIdRealtime"), "App Id PUN");
if (PhotonEditorUtils.HasChat)
{
this.BuildAppIdField(settingsSp.FindPropertyRelative("AppIdChat"));
}
if (PhotonEditorUtils.HasVoice)
{
this.BuildAppIdField(settingsSp.FindPropertyRelative("AppIdVoice"));
}
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("AppVersion"));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("UseNameServer"), new GUIContent("Use Name Server", "Photon Cloud requires this checked.\nUncheck for Photon Server SDK (OnPremise)."));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("FixedRegion"), new GUIContent("Fixed Region", "Photon Cloud setting, needs a Name Server.\nDefine one region to always connect to.\nLeave empty to use the best region from a server-side region list."));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("Server"), new GUIContent("Server", "Typically empty for Photon Cloud.\nFor Photon OnPremise, enter your host name or IP. Also uncheck \"Use Name Server\" for older Photon OnPremise servers."));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("Port"), new GUIContent("Port", "Leave 0 to use default Photon Cloud ports for the Name Server.\nOnPremise defaults to 5055 for UDP and 4530 for TCP."));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("ProxyServer"), new GUIContent("Proxy Server", "HTTP Proxy Server for WebSocket connection. See LoadBalancingClient.ProxyServerAddress for options."));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("Protocol"), new GUIContent("Protocol", "Use UDP where possible.\nWSS works on WebGL and Xbox exports.\nDefine WEBSOCKET for use on other platforms."));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("EnableProtocolFallback"), new GUIContent("Protocol Fallback", "Automatically try another network protocol, if initial connect fails.\nWill use default Name Server ports."));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("EnableLobbyStatistics"), new GUIContent("Lobby Statistics", "When using multiple room lists (lobbies), the server can send info about their usage."));
EditorGUILayout.PropertyField(settingsSp.FindPropertyRelative("NetworkLogging"), new GUIContent("Network Logging", "Log level for the Photon libraries."));
EditorGUI.indentLevel--;
}
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("PunLogging"), new GUIContent("PUN Logging", "Log level for the PUN layer."));
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("EnableSupportLogger"), new GUIContent("Support Logger", "Logs additional info for debugging.\nUse this when you submit bugs to the Photon Team."));
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("RunInBackground"), new GUIContent("Run In Background", "Enables apps to keep the connection without focus. Android and iOS ignore this."));
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("StartInOfflineMode"), new GUIContent("Start In Offline Mode", "Simulates an online connection.\nPUN can be used as usual."));
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("DevRegion"), new GUIContent("Dev Region", "Photon Cloud setting, needs a Name Server.\nDefine region the Editor and Development builds will always connect to - ensuring all users can find common rooms.\nLeave empty to use the Fixed Region or best region from a server-side region list. This value will be ignored for non-Development builds."));
#region Best Region Box
EditorGUILayout.BeginVertical(vertboxStyle);
if (!string.IsNullOrEmpty(PhotonNetwork.BestRegionSummaryInPreferences))
{
this.regionsPrefsList = PhotonNetwork.BestRegionSummaryInPreferences.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
if (this.regionsPrefsList.Length < 2)
{
this.prefLabel = notAvailableLabel;
}
else
{
this.prefLabel = string.Format("'{0}' ping:{1}ms ", this.regionsPrefsList[0], this.regionsPrefsList[1]);
}
}
else
{
this.prefLabel = notAvailableLabel;
}
EditorGUILayout.LabelField(new GUIContent("Best Region Preference: " + prefLabel, "Best region is used if Fixed Region is empty."));
EditorGUILayout.BeginHorizontal();
var resetrect = EditorGUILayout.GetControlRect(GUILayout.MinWidth(64));
var editrect = EditorGUILayout.GetControlRect(GUILayout.MinWidth(64));
if (GUI.Button(resetrect, "Reset", EditorStyles.miniButton))
{
ServerSettings.ResetBestRegionCodeInPreferences();
}
if (GUI.Button(editrect, "Edit WhiteList", EditorStyles.miniButton))
{
Application.OpenURL("https://dashboard.photonengine.com/en-US/App/RegionsWhitelistEdit/" + PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
#endregion Best Region Box
//this.showRpcs = EditorGUILayout.Foldout(this.showRpcs, new GUIContent("RPCs", "RPC shortcut list."));
EditorGUI.indentLevel--;
this.showRpcs = this.showRpcs.Foldout(new GUIContent("RPCs", "RPC shortcut list."));
EditorGUI.indentLevel++;
if (this.showRpcs)
{
// first time check to get the rpc has proper
if (string.IsNullOrEmpty(this.rpcCrc))
{
this.rpcCrc = this.RpcListHashCode().ToString("X");
}
#region Begin Vertical Box CRC
EditorGUILayout.BeginVertical(vertboxStyle);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("List CRC");
EditorGUI.indentLevel--;
var copyrect = EditorGUILayout.GetControlRect(GUILayout.MaxWidth(16));
EditorGUILayout.GetControlRect(GUILayout.MaxWidth(12));
var hashrect = EditorGUILayout.GetControlRect(GUILayout.MinWidth(16)); // new Rect(copyrect) { xMin = copyrect.xMin + 32 };
EditorGUIUtility.AddCursorRect(copyrect, MouseCursor.Link);
EditorGUI.LabelField(copyrect, new GUIContent("", "Copy Hashcode to Clipboard"));
if (GUI.Button(copyrect, PhotonGUI.CopyIcon, GUIStyle.none))
{
Debug.Log("RPC-List HashCode copied into your ClipBoard: " + this.rpcCrc + ". Make sure clients that send each other RPCs have the same RPC-List.");
EditorGUIUtility.systemCopyBuffer = this.rpcCrc;
}
EditorGUI.SelectableLabel(hashrect, this.rpcCrc);
EditorGUILayout.EndHorizontal();
EditorGUI.indentLevel++;
EditorGUILayout.BeginHorizontal();
var refreshrect = EditorGUILayout.GetControlRect(GUILayout.MinWidth(64));
var clearrect = EditorGUILayout.GetControlRect(GUILayout.MinWidth(64));
if (GUI.Button(refreshrect, "Refresh RPCs", EditorStyles.miniButton))
{
PhotonEditor.UpdateRpcList();
this.Repaint();
}
if (GUI.Button(clearrect, "Clear RPCs", EditorStyles.miniButton))
{
PhotonEditor.ClearRpcList();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
#endregion End Vertical Box CRC
EditorGUI.indentLevel++;
SerializedProperty sRpcs = sObj.FindProperty("RpcList");
EditorGUILayout.PropertyField(sRpcs, true);
EditorGUI.indentLevel--;
}
if (EditorGUI.EndChangeCheck())
{
sObj.ApplyModifiedProperties();
this.serializedObject.ApplyModifiedProperties();
// cache the rpc hash
this.rpcCrc = this.RpcListHashCode().ToString("X");
}
#region Simple Settings
/// Conditional Simple Sync Settings DrawGUI - Uses reflection to avoid having to hard connect the libraries
var SettingsScriptableObjectBaseType = GetType("Photon.Utilities.SettingsScriptableObjectBase");
if (SettingsScriptableObjectBaseType != null)
{
EditorGUILayout.GetControlRect(false, 3);
EditorGUILayout.LabelField("Simple Extension Settings", (GUIStyle)"BoldLabel");
var drawAllMethod = SettingsScriptableObjectBaseType.GetMethod("DrawAllSettings");
if (drawAllMethod != null && this != null)
{
bool initializeAsOpen = false;
drawAllMethod.Invoke(null, new object[2] { this, initializeAsOpen });
}
}
#endregion
}
private static Type GetType(string typeName)
{
var type = Type.GetType(typeName);
if (type != null) return type;
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
type = a.GetType(typeName);
if (type != null)
return type;
}
return null;
}
private int RpcListHashCode()
{
// this is a hashcode generated to (more) easily compare this Editor's RPC List with some other
int hashCode = PhotonNetwork.PhotonServerSettings.RpcList.Count + 1;
foreach (string s in PhotonNetwork.PhotonServerSettings.RpcList)
{
int h1 = s.GetHashCode();
hashCode = ((h1 << 5) + h1) ^ hashCode;
}
return hashCode;
}
private void BuildAppIdField(SerializedProperty property, string label = null)
{
EditorGUILayout.BeginHorizontal();
if (label != null)
{
EditorGUILayout.PropertyField(property, new GUIContent(label), GUILayout.MinWidth(32));
}
else
{
EditorGUILayout.PropertyField(property, GUILayout.MinWidth(32));
}
property.stringValue = property.stringValue.Trim();
string appId = property.stringValue;
string url = "https://dashboard.photonengine.com/en-US/PublicCloud";
if (!string.IsNullOrEmpty(appId))
{
url = string.Format("https://dashboard.photonengine.com/en-US/App/Manage/{0}", appId);
}
if (GUILayout.Button("Dashboard", EditorStyles.miniButton, GUILayout.MinWidth(78), GUILayout.MaxWidth(78)))
{
Application.OpenURL(url);
}
EditorGUILayout.EndHorizontal();
}
}
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 21239ba77ac4b534f958e8617ef13ede
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c6024eaa234f94341af9e45cc99285c7
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,40 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonAnimatorViewEditor.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// This is a custom editor for the AnimatorView component.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
namespace Photon.Pun
{
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(MonoBehaviourPun))]
public abstract class MonoBehaviourPunEditor : Editor
{
MonoBehaviourPun mbTarget;
private void OnEnable()
{
mbTarget = target as MonoBehaviourPun;
}
public override void OnInspectorGUI()
{
mbTarget = target as MonoBehaviourPun;
base.OnInspectorGUI();
if (mbTarget.photonView == null)
{
EditorGUILayout.HelpBox("Unable to find a PhotonView on this GameObject or on any parent GameObject.", MessageType.Warning);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6da457ee57ad5794782f1f76644536e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,295 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonAnimatorViewEditor.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// This is a custom editor for the AnimatorView component.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
namespace Photon.Pun
{
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
[CustomEditor(typeof(PhotonAnimatorView))]
public class PhotonAnimatorViewEditor : MonoBehaviourPunEditor
{
private Animator m_Animator;
private PhotonAnimatorView m_Target;
private AnimatorController m_Controller;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (this.m_Animator == null)
{
EditorGUILayout.HelpBox("GameObject doesn't have an Animator component to synchronize", MessageType.Warning);
return;
}
this.DrawWeightInspector();
if (this.GetLayerCount() == 0)
{
EditorGUILayout.HelpBox("Animator doesn't have any layers setup to synchronize", MessageType.Warning);
}
this.DrawParameterInspector();
if (this.GetParameterCount() == 0)
{
EditorGUILayout.HelpBox("Animator doesn't have any parameters setup to synchronize", MessageType.Warning);
}
this.serializedObject.ApplyModifiedProperties();
//GUILayout.Label( "m_SynchronizeLayers " + serializedObject.FindProperty( "m_SynchronizeLayers" ).arraySize );
//GUILayout.Label( "m_SynchronizeParameters " + serializedObject.FindProperty( "m_SynchronizeParameters" ).arraySize );
}
private int GetLayerCount()
{
return (this.m_Controller == null) ? 0 : this.m_Controller.layers.Length;
}
private int GetParameterCount()
{
return (this.m_Controller == null) ? 0 : this.m_Controller.parameters.Length;
}
private AnimatorControllerParameter GetAnimatorControllerParameter(int i)
{
return this.m_Controller.parameters[i];
}
private RuntimeAnimatorController GetEffectiveController(Animator animator)
{
RuntimeAnimatorController controller = animator.runtimeAnimatorController;
AnimatorOverrideController overrideController = controller as AnimatorOverrideController;
while (overrideController != null)
{
controller = overrideController.runtimeAnimatorController;
overrideController = controller as AnimatorOverrideController;
}
return controller;
}
private void OnEnable()
{
this.m_Target = (PhotonAnimatorView)this.target;
this.m_Animator = this.m_Target.GetComponent<Animator>();
if (m_Animator)
{
this.m_Controller = this.GetEffectiveController(this.m_Animator) as AnimatorController;
this.CheckIfStoredParametersExist();
}
}
private void DrawWeightInspector()
{
SerializedProperty foldoutProperty = this.serializedObject.FindProperty("ShowLayerWeightsInspector");
foldoutProperty.boolValue = PhotonGUI.ContainerHeaderFoldout("Synchronize Layer Weights", foldoutProperty.boolValue);
if (foldoutProperty.boolValue == false)
{
return;
}
float lineHeight = 20;
Rect containerRect = PhotonGUI.ContainerBody(this.GetLayerCount() * lineHeight);
for (int i = 0; i < this.GetLayerCount(); ++i)
{
if (this.m_Target.DoesLayerSynchronizeTypeExist(i) == false)
{
this.m_Target.SetLayerSynchronized(i, PhotonAnimatorView.SynchronizeType.Disabled);
}
PhotonAnimatorView.SynchronizeType syncType = this.m_Target.GetLayerSynchronizeType(i);
Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + i * lineHeight, containerRect.width, lineHeight);
Rect labelRect = new Rect(elementRect.xMin + 5, elementRect.yMin + 2, EditorGUIUtility.labelWidth - 5, elementRect.height);
GUI.Label(labelRect, "Layer " + i);
Rect popupRect = new Rect(elementRect.xMin + EditorGUIUtility.labelWidth, elementRect.yMin + 2, elementRect.width - EditorGUIUtility.labelWidth - 5, EditorGUIUtility.singleLineHeight);
syncType = (PhotonAnimatorView.SynchronizeType)EditorGUI.EnumPopup(popupRect, syncType);
if (i < this.GetLayerCount() - 1)
{
Rect splitterRect = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1);
PhotonGUI.DrawSplitter(splitterRect);
}
if (syncType != this.m_Target.GetLayerSynchronizeType(i))
{
Undo.RecordObject(this.target, "Modify Synchronize Layer Weights");
this.m_Target.SetLayerSynchronized(i, syncType);
}
}
}
private bool DoesParameterExist(string name)
{
for (int i = 0; i < this.GetParameterCount(); ++i)
{
if (this.GetAnimatorControllerParameter(i).name == name)
{
return true;
}
}
return false;
}
private void CheckIfStoredParametersExist()
{
var syncedParams = this.m_Target.GetSynchronizedParameters();
List<string> paramsToRemove = new List<string>();
for (int i = 0; i < syncedParams.Count; ++i)
{
string parameterName = syncedParams[i].Name;
if (this.DoesParameterExist(parameterName) == false)
{
Debug.LogWarning("Parameter '" + this.m_Target.GetSynchronizedParameters()[i].Name + "' doesn't exist anymore. Removing it from the list of synchronized parameters");
paramsToRemove.Add(parameterName);
}
}
if (paramsToRemove.Count > 0)
{
foreach (string param in paramsToRemove)
{
this.m_Target.GetSynchronizedParameters().RemoveAll(item => item.Name == param);
}
}
}
private void DrawParameterInspector()
{
// flag to expose a note in Interface if one or more trigger(s) are synchronized
bool isUsingTriggers = false;
SerializedProperty foldoutProperty = this.serializedObject.FindProperty("ShowParameterInspector");
foldoutProperty.boolValue = PhotonGUI.ContainerHeaderFoldout("Synchronize Parameters", foldoutProperty.boolValue);
if (foldoutProperty.boolValue == false)
{
return;
}
float lineHeight = 20;
Rect containerRect = PhotonGUI.ContainerBody(this.GetParameterCount() * lineHeight);
for (int i = 0; i < this.GetParameterCount(); i++)
{
AnimatorControllerParameter parameter = null;
parameter = this.GetAnimatorControllerParameter(i);
string defaultValue = "";
if (parameter.type == AnimatorControllerParameterType.Bool)
{
if (Application.isPlaying && this.m_Animator.gameObject.activeInHierarchy)
{
defaultValue += this.m_Animator.GetBool(parameter.name);
}
else
{
defaultValue += parameter.defaultBool.ToString();
}
}
else if (parameter.type == AnimatorControllerParameterType.Float)
{
if (Application.isPlaying && this.m_Animator.gameObject.activeInHierarchy)
{
defaultValue += this.m_Animator.GetFloat(parameter.name).ToString("0.00");
}
else
{
defaultValue += parameter.defaultFloat.ToString();
}
}
else if (parameter.type == AnimatorControllerParameterType.Int)
{
if (Application.isPlaying && this.m_Animator.gameObject.activeInHierarchy)
{
defaultValue += this.m_Animator.GetInteger(parameter.name);
}
else
{
defaultValue += parameter.defaultInt.ToString();
}
}
else if (parameter.type == AnimatorControllerParameterType.Trigger)
{
if (Application.isPlaying && this.m_Animator.gameObject.activeInHierarchy)
{
defaultValue += this.m_Animator.GetBool(parameter.name);
}
else
{
defaultValue += parameter.defaultBool.ToString();
}
}
if (this.m_Target.DoesParameterSynchronizeTypeExist(parameter.name) == false)
{
this.m_Target.SetParameterSynchronized(parameter.name, (PhotonAnimatorView.ParameterType)parameter.type, PhotonAnimatorView.SynchronizeType.Disabled);
}
PhotonAnimatorView.SynchronizeType value = this.m_Target.GetParameterSynchronizeType(parameter.name);
// check if using trigger and actually synchronizing it
if (value != PhotonAnimatorView.SynchronizeType.Disabled && parameter.type == AnimatorControllerParameterType.Trigger)
{
isUsingTriggers = true;
}
Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + i * lineHeight, containerRect.width, lineHeight);
Rect labelRect = new Rect(elementRect.xMin + 5, elementRect.yMin + 2, EditorGUIUtility.labelWidth - 5, elementRect.height);
GUI.Label(labelRect, parameter.name + " (" + defaultValue + ")");
Rect popupRect = new Rect(elementRect.xMin + EditorGUIUtility.labelWidth, elementRect.yMin + 2, elementRect.width - EditorGUIUtility.labelWidth - 5, EditorGUIUtility.singleLineHeight);
value = (PhotonAnimatorView.SynchronizeType)EditorGUI.EnumPopup(popupRect, value);
if (i < this.GetParameterCount() - 1)
{
Rect splitterRect = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1);
PhotonGUI.DrawSplitter(splitterRect);
}
if (value != this.m_Target.GetParameterSynchronizeType(parameter.name))
{
Undo.RecordObject(this.target, "Modify Synchronize Parameter " + parameter.name);
this.m_Target.SetParameterSynchronized(parameter.name, (PhotonAnimatorView.ParameterType)parameter.type, value);
}
}
// display note when synchronized triggers are detected.
if (isUsingTriggers)
{
EditorGUILayout.HelpBox("When using triggers, make sure this component is last in the stack. " +
"If you still experience issues, implement triggers as a regular RPC " +
"or in custom IPunObservable component instead.", MessageType.Warning);
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a3f61bade114730459f7ad45f5f292c1
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,50 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonRigidbody2DViewEditor.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// This is a custom editor for the PhotonRigidbody2DView component.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
namespace Photon.Pun
{
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof (PhotonRigidbody2DView))]
public class PhotonRigidbody2DViewEditor : MonoBehaviourPunEditor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (Application.isPlaying)
{
EditorGUILayout.HelpBox("Editing is disabled in play mode.", MessageType.Info);
return;
}
PhotonRigidbody2DView view = (PhotonRigidbody2DView)target;
view.m_TeleportEnabled = PhotonGUI.ContainerHeaderToggle("Enable teleport for large distances", view.m_TeleportEnabled);
if (view.m_TeleportEnabled)
{
Rect rect = PhotonGUI.ContainerBody(20.0f);
view.m_TeleportIfDistanceGreaterThan = EditorGUI.FloatField(rect, "Teleport if distance greater than", view.m_TeleportIfDistanceGreaterThan);
}
view.m_SynchronizeVelocity = PhotonGUI.ContainerHeaderToggle("Synchronize Velocity", view.m_SynchronizeVelocity);
view.m_SynchronizeAngularVelocity = PhotonGUI.ContainerHeaderToggle("Synchronize Angular Velocity", view.m_SynchronizeAngularVelocity);
if (GUI.changed)
{
EditorUtility.SetDirty(view);
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3a82e8e86b9eecb40ac3f6ebc949f6ef
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,50 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonRigidbodyViewEditor.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// This is a custom editor for the RigidbodyView component.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
namespace Photon.Pun
{
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof (PhotonRigidbodyView))]
public class PhotonRigidbodyViewEditor : MonoBehaviourPunEditor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (Application.isPlaying)
{
EditorGUILayout.HelpBox("Editing is disabled in play mode.", MessageType.Info);
return;
}
PhotonRigidbodyView view = (PhotonRigidbodyView)target;
view.m_TeleportEnabled = PhotonGUI.ContainerHeaderToggle("Enable teleport for large distances", view.m_TeleportEnabled);
if (view.m_TeleportEnabled)
{
Rect rect = PhotonGUI.ContainerBody(20.0f);
view.m_TeleportIfDistanceGreaterThan = EditorGUI.FloatField(rect, "Teleport if distance greater than", view.m_TeleportIfDistanceGreaterThan);
}
view.m_SynchronizeVelocity = PhotonGUI.ContainerHeaderToggle("Synchronize Velocity", view.m_SynchronizeVelocity);
view.m_SynchronizeAngularVelocity = PhotonGUI.ContainerHeaderToggle("Synchronize Angular Velocity", view.m_SynchronizeAngularVelocity);
if (GUI.changed)
{
EditorUtility.SetDirty(view);
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4bcfebc9a2f1074488adedd1fe84e6c9
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,412 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonTransformViewClassicEditor.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// This is a custom editor for the TransformView component.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
namespace Photon.Pun
{
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(PhotonTransformViewClassic))]
public class PhotonTransformViewClassicEditor : MonoBehaviourPunEditor
{
//private PhotonTransformViewClassic m_Target;
private SerializedProperty m_SynchronizePositionProperty;
private SerializedProperty m_SynchronizeRotationProperty;
private SerializedProperty m_SynchronizeScaleProperty;
private bool m_InterpolateHelpOpen;
private bool m_ExtrapolateHelpOpen;
private bool m_InterpolateRotationHelpOpen;
private bool m_InterpolateScaleHelpOpen;
private const int EDITOR_LINE_HEIGHT = 20;
private const string INTERPOLATE_TOOLTIP =
"Choose between synchronizing the value directly (by disabling interpolation) or smoothly move it towards the newest update.";
private const string INTERPOLATE_HELP =
"You can use interpolation to smoothly move your GameObject towards a new position that is received via the network. "
+ "This helps to reduce the stuttering movement that results because the network updates only arrive 10 times per second.\n"
+ "As a side effect, the GameObject is always lagging behind the actual position a little bit. This can be addressed with extrapolation.";
private const string EXTRAPOLATE_TOOLTIP = "Extrapolation is used to predict where the GameObject actually is";
private const string EXTRAPOLATE_HELP =
"Whenever you deal with network values, all values you receive will be a little bit out of date since that data needs "
+ "to reach you first. You can use extrapolation to try to predict where the player actually is, based on the movement data you have received.\n"
+
"This has to be tweaked carefully for each specific game in order to insure the optimal prediction. Sometimes it is very easy to extrapolate states, because "
+
"the GameObject behaves very predictable (for example for vehicles). Other times it can be very hard because the user input is translated directly to the game "
+ "and you cannot really predict what the user is going to do (for example in fighting games)";
private const string INTERPOLATE_HELP_URL = "https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/rpg-movement#interpolate_options";
private const string EXTRAPOLATE_HELP_URL = "https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/rpg-movement#extrapolate_options";
public void OnEnable()
{
SetupSerializedProperties();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
base.OnInspectorGUI();
//this.m_Target = (PhotonTransformViewClassic) target;
DrawIsPlayingWarning();
GUI.enabled = !Application.isPlaying;
DrawSynchronizePositionHeader();
DrawSynchronizePositionData();
GUI.enabled = !Application.isPlaying;
DrawSynchronizeRotationHeader();
DrawSynchronizeRotationData();
GUI.enabled = !Application.isPlaying;
DrawSynchronizeScaleHeader();
DrawSynchronizeScaleData();
serializedObject.ApplyModifiedProperties();
GUI.enabled = true;
}
private void DrawIsPlayingWarning()
{
if (Application.isPlaying == false)
{
return;
}
GUILayout.BeginVertical(GUI.skin.box);
{
GUILayout.Label("Editing is disabled in play mode so the two objects don't go out of sync");
}
GUILayout.EndVertical();
}
private void SetupSerializedProperties()
{
this.m_SynchronizePositionProperty = serializedObject.FindProperty("m_PositionModel.SynchronizeEnabled");
this.m_SynchronizeRotationProperty = serializedObject.FindProperty("m_RotationModel.SynchronizeEnabled");
this.m_SynchronizeScaleProperty = serializedObject.FindProperty("m_ScaleModel.SynchronizeEnabled");
}
private void DrawSynchronizePositionHeader()
{
DrawHeader("Synchronize Position", this.m_SynchronizePositionProperty);
}
private void DrawSynchronizePositionData()
{
if (this.m_SynchronizePositionProperty == null || this.m_SynchronizePositionProperty.boolValue == false)
{
return;
}
SerializedProperty interpolatePositionProperty = serializedObject.FindProperty("m_PositionModel.InterpolateOption");
PhotonTransformViewPositionModel.InterpolateOptions interpolateOption = (PhotonTransformViewPositionModel.InterpolateOptions)interpolatePositionProperty.enumValueIndex;
SerializedProperty extrapolatePositionProperty = serializedObject.FindProperty("m_PositionModel.ExtrapolateOption");
PhotonTransformViewPositionModel.ExtrapolateOptions extrapolateOption = (PhotonTransformViewPositionModel.ExtrapolateOptions)extrapolatePositionProperty.enumValueIndex;
float containerHeight = 155;
switch (interpolateOption)
{
case PhotonTransformViewPositionModel.InterpolateOptions.FixedSpeed:
case PhotonTransformViewPositionModel.InterpolateOptions.Lerp:
containerHeight += EDITOR_LINE_HEIGHT;
break;
/*case PhotonTransformViewPositionModel.InterpolateOptions.MoveTowardsComplex:
containerHeight += EDITOR_LINE_HEIGHT*3;
break;*/
}
if (extrapolateOption != PhotonTransformViewPositionModel.ExtrapolateOptions.Disabled)
{
containerHeight += EDITOR_LINE_HEIGHT;
}
switch (extrapolateOption)
{
case PhotonTransformViewPositionModel.ExtrapolateOptions.FixedSpeed:
containerHeight += EDITOR_LINE_HEIGHT;
break;
}
if (this.m_InterpolateHelpOpen == true)
{
containerHeight += GetInterpolateHelpBoxHeight();
}
if (this.m_ExtrapolateHelpOpen == true)
{
containerHeight += GetExtrapolateHelpBoxHeight();
}
// removed Gizmo Options. -3 lines, -1 splitter
containerHeight -= EDITOR_LINE_HEIGHT * 3;
Rect rect = PhotonGUI.ContainerBody(containerHeight);
Rect propertyRect = new Rect(rect.xMin + 5, rect.yMin + 2, rect.width - 10, EditorGUIUtility.singleLineHeight);
DrawTeleport(ref propertyRect);
DrawSplitter(ref propertyRect);
DrawSynchronizePositionDataInterpolation(ref propertyRect, interpolatePositionProperty, interpolateOption);
DrawSplitter(ref propertyRect);
DrawSynchronizePositionDataExtrapolation(ref propertyRect, extrapolatePositionProperty, extrapolateOption);
}
private float GetInterpolateHelpBoxHeight()
{
return PhotonGUI.RichLabel.CalcHeight(new GUIContent(INTERPOLATE_HELP), Screen.width - 54) + 35;
}
private float GetExtrapolateHelpBoxHeight()
{
return PhotonGUI.RichLabel.CalcHeight(new GUIContent(EXTRAPOLATE_HELP), Screen.width - 54) + 35;
}
private void DrawSplitter(ref Rect propertyRect)
{
Rect splitterRect = new Rect(propertyRect.xMin - 3, propertyRect.yMin, propertyRect.width + 6, 1);
PhotonGUI.DrawSplitter(splitterRect);
propertyRect.y += 5;
}
private void DrawHelpBox(ref Rect propertyRect, bool isOpen, float height, string helpText, string url)
{
if (isOpen == true)
{
Rect helpRect = new Rect(propertyRect.xMin, propertyRect.yMin, propertyRect.width, height - 5);
GUI.BeginGroup(helpRect, GUI.skin.box);
GUI.Label(new Rect(5, 5, propertyRect.width - 10, height - 30), helpText, PhotonGUI.RichLabel);
if (GUI.Button(new Rect(5, height - 30, propertyRect.width - 10, 20), "Read more in our documentation"))
{
Application.OpenURL(url);
}
GUI.EndGroup();
propertyRect.y += height;
}
}
private void DrawPropertyWithHelpIcon(ref Rect propertyRect, ref bool isHelpOpen, SerializedProperty property, string tooltip)
{
Rect propertyFieldRect = new Rect(propertyRect.xMin, propertyRect.yMin, propertyRect.width - 20, propertyRect.height);
string propertyName = ObjectNames.NicifyVariableName(property.name);
EditorGUI.PropertyField(propertyFieldRect, property, new GUIContent(propertyName, tooltip));
Rect helpIconRect = new Rect(propertyFieldRect.xMax + 5, propertyFieldRect.yMin, 20, propertyFieldRect.height);
isHelpOpen = GUI.Toggle(helpIconRect, isHelpOpen, PhotonGUI.HelpIcon, GUIStyle.none);
propertyRect.y += EDITOR_LINE_HEIGHT;
}
private void DrawSynchronizePositionDataExtrapolation(ref Rect propertyRect, SerializedProperty extrapolatePositionProperty,
PhotonTransformViewPositionModel.ExtrapolateOptions extrapolateOption)
{
DrawPropertyWithHelpIcon(ref propertyRect, ref this.m_ExtrapolateHelpOpen, extrapolatePositionProperty, EXTRAPOLATE_TOOLTIP);
DrawHelpBox(ref propertyRect, this.m_ExtrapolateHelpOpen, GetExtrapolateHelpBoxHeight(), EXTRAPOLATE_HELP, EXTRAPOLATE_HELP_URL);
if (extrapolateOption != PhotonTransformViewPositionModel.ExtrapolateOptions.Disabled)
{
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.ExtrapolateIncludingRoundTripTime"));
propertyRect.y += EDITOR_LINE_HEIGHT;
}
switch (extrapolateOption)
{
case PhotonTransformViewPositionModel.ExtrapolateOptions.FixedSpeed:
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.ExtrapolateSpeed"));
propertyRect.y += EDITOR_LINE_HEIGHT;
break;
}
}
private void DrawTeleport(ref Rect propertyRect)
{
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.TeleportEnabled"),
new GUIContent("Enable teleport for great distances"));
propertyRect.y += EDITOR_LINE_HEIGHT;
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.TeleportIfDistanceGreaterThan"),
new GUIContent("Teleport if distance greater than"));
propertyRect.y += EDITOR_LINE_HEIGHT;
}
private void DrawSynchronizePositionDataInterpolation(ref Rect propertyRect, SerializedProperty interpolatePositionProperty,
PhotonTransformViewPositionModel.InterpolateOptions interpolateOption)
{
DrawPropertyWithHelpIcon(ref propertyRect, ref this.m_InterpolateHelpOpen, interpolatePositionProperty, INTERPOLATE_TOOLTIP);
DrawHelpBox(ref propertyRect, this.m_InterpolateHelpOpen, GetInterpolateHelpBoxHeight(), INTERPOLATE_HELP, INTERPOLATE_HELP_URL);
switch (interpolateOption)
{
case PhotonTransformViewPositionModel.InterpolateOptions.FixedSpeed:
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.InterpolateMoveTowardsSpeed"),
new GUIContent("MoveTowards Speed"));
propertyRect.y += EDITOR_LINE_HEIGHT;
break;
case PhotonTransformViewPositionModel.InterpolateOptions.Lerp:
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.InterpolateLerpSpeed"), new GUIContent("Lerp Speed"));
propertyRect.y += EDITOR_LINE_HEIGHT;
break;
/*case PhotonTransformViewPositionModel.InterpolateOptions.MoveTowardsComplex:
Rect curveRect = new Rect(propertyRect.xMin, propertyRect.yMin, propertyRect.width - 100, propertyRect.height);
EditorGUI.PropertyField(curveRect, serializedObject.FindProperty("m_PositionModel.InterpolateSpeedCurve"), new GUIContent("MoveTowards Speed Curve"));
Rect labelRect = new Rect(propertyRect.xMax - 95, propertyRect.yMin, 10, propertyRect.height);
GUI.Label(labelRect, "x");
Rect multiplierRect = new Rect(propertyRect.xMax - 80, propertyRect.yMin, 80, propertyRect.height);
EditorGUI.PropertyField(multiplierRect, serializedObject.FindProperty("m_PositionModel.InterpolateMoveTowardsSpeed"), GUIContent.none);
propertyRect.y += EDITOR_LINE_HEIGHT;
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.InterpolateMoveTowardsAcceleration"),
new GUIContent("Acceleration"));
propertyRect.y += EDITOR_LINE_HEIGHT;
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.InterpolateMoveTowardsDeceleration"),
new GUIContent("Deceleration"));
propertyRect.y += EDITOR_LINE_HEIGHT;
break;*/
}
}
private void DrawSynchronizeRotationHeader()
{
DrawHeader("Synchronize Rotation", this.m_SynchronizeRotationProperty);
}
private void DrawSynchronizeRotationData()
{
if (this.m_SynchronizeRotationProperty == null || this.m_SynchronizeRotationProperty.boolValue == false)
{
return;
}
SerializedProperty interpolateRotationProperty = serializedObject.FindProperty("m_RotationModel.InterpolateOption");
PhotonTransformViewRotationModel.InterpolateOptions interpolateOption =
(PhotonTransformViewRotationModel.InterpolateOptions)interpolateRotationProperty.enumValueIndex;
float containerHeight = 20;
switch (interpolateOption)
{
case PhotonTransformViewRotationModel.InterpolateOptions.RotateTowards:
case PhotonTransformViewRotationModel.InterpolateOptions.Lerp:
containerHeight += EDITOR_LINE_HEIGHT;
break;
}
if (this.m_InterpolateRotationHelpOpen == true)
{
containerHeight += GetInterpolateHelpBoxHeight();
}
Rect rect = PhotonGUI.ContainerBody(containerHeight);
Rect propertyRect = new Rect(rect.xMin + 5, rect.yMin + 2, rect.width - 10, EditorGUIUtility.singleLineHeight);
DrawPropertyWithHelpIcon(ref propertyRect, ref this.m_InterpolateRotationHelpOpen, interpolateRotationProperty, INTERPOLATE_TOOLTIP);
DrawHelpBox(ref propertyRect, this.m_InterpolateRotationHelpOpen, GetInterpolateHelpBoxHeight(), INTERPOLATE_HELP, INTERPOLATE_HELP_URL);
switch (interpolateOption)
{
case PhotonTransformViewRotationModel.InterpolateOptions.RotateTowards:
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_RotationModel.InterpolateRotateTowardsSpeed"),
new GUIContent("RotateTowards Speed"));
break;
case PhotonTransformViewRotationModel.InterpolateOptions.Lerp:
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_RotationModel.InterpolateLerpSpeed"), new GUIContent("Lerp Speed"));
break;
}
}
private void DrawSynchronizeScaleHeader()
{
DrawHeader("Synchronize Scale", this.m_SynchronizeScaleProperty);
}
private void DrawSynchronizeScaleData()
{
if (this.m_SynchronizeScaleProperty == null || this.m_SynchronizeScaleProperty.boolValue == false)
{
return;
}
SerializedProperty interpolateScaleProperty = serializedObject.FindProperty("m_ScaleModel.InterpolateOption");
PhotonTransformViewScaleModel.InterpolateOptions interpolateOption = (PhotonTransformViewScaleModel.InterpolateOptions)interpolateScaleProperty.enumValueIndex;
float containerHeight = EDITOR_LINE_HEIGHT;
switch (interpolateOption)
{
case PhotonTransformViewScaleModel.InterpolateOptions.MoveTowards:
case PhotonTransformViewScaleModel.InterpolateOptions.Lerp:
containerHeight += EDITOR_LINE_HEIGHT;
break;
}
if (this.m_InterpolateScaleHelpOpen == true)
{
containerHeight += GetInterpolateHelpBoxHeight();
}
Rect rect = PhotonGUI.ContainerBody(containerHeight);
Rect propertyRect = new Rect(rect.xMin + 5, rect.yMin + 2, rect.width - 10, EditorGUIUtility.singleLineHeight);
DrawPropertyWithHelpIcon(ref propertyRect, ref this.m_InterpolateScaleHelpOpen, interpolateScaleProperty, INTERPOLATE_TOOLTIP);
DrawHelpBox(ref propertyRect, this.m_InterpolateScaleHelpOpen, GetInterpolateHelpBoxHeight(), INTERPOLATE_HELP, INTERPOLATE_HELP_URL);
switch (interpolateOption)
{
case PhotonTransformViewScaleModel.InterpolateOptions.MoveTowards:
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_ScaleModel.InterpolateMoveTowardsSpeed"),
new GUIContent("MoveTowards Speed"));
break;
case PhotonTransformViewScaleModel.InterpolateOptions.Lerp:
EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_ScaleModel.InterpolateLerpSpeed"), new GUIContent("Lerp Speed"));
break;
}
}
private void DrawHeader(string label, SerializedProperty property)
{
if (property == null)
{
return;
}
bool newValue = PhotonGUI.ContainerHeaderToggle(label, property.boolValue);
if (newValue != property.boolValue)
{
property.boolValue = newValue;
property.serializedObject.ApplyModifiedProperties();
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 22292ca8ffb574945bedfaf49266672e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,72 @@
// ----------------------------------------------------------------------------
// <copyright file="PhotonTransformViewEditor.cs" company="Exit Games GmbH">
// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH
// </copyright>
// <summary>
// This is a custom editor for the TransformView component.
// </summary>
// <author>developer@exitgames.com</author>
// ----------------------------------------------------------------------------
namespace Photon.Pun
{
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(PhotonTransformView))]
public class PhotonTransformViewEditor : Editor
{
private bool helpToggle = false;
SerializedProperty pos, rot, scl, lcl;
public void OnEnable()
{
pos = serializedObject.FindProperty("m_SynchronizePosition");
rot = serializedObject.FindProperty("m_SynchronizeRotation");
scl = serializedObject.FindProperty("m_SynchronizeScale");
lcl = serializedObject.FindProperty("m_UseLocal");
}
public override void OnInspectorGUI()
{
if (Application.isPlaying)
{
EditorGUILayout.HelpBox("Editing is disabled in play mode.", MessageType.Info);
return;
}
PhotonTransformView view = (PhotonTransformView)target;
EditorGUILayout.LabelField("Synchronize Options");
EditorGUI.BeginChangeCheck();
{
EditorGUILayout.BeginVertical("HelpBox");
{
EditorGUILayout.PropertyField(pos, new GUIContent("Position", pos.tooltip));
EditorGUILayout.PropertyField(rot, new GUIContent("Rotation", rot.tooltip));
EditorGUILayout.PropertyField(scl, new GUIContent("Scale", scl.tooltip));
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(lcl, new GUIContent("Use Local", lcl.tooltip));
}
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
this.helpToggle = EditorGUILayout.Foldout(this.helpToggle, "Info");
if (this.helpToggle)
{
EditorGUILayout.HelpBox("The Photon Transform View of PUN 2 is simple by design.\nReplace it with the Photon Transform View Classic if you want the old options.\nThe best solution is a custom IPunObservable implementation.", MessageType.Info, true);
}
}
}
}

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a8c9ec475ad103b43b901d942ff66e02
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,45 @@
fileFormatVersion: 2
guid: 9f1212502533cb34188dd6ef094188cb
TextureImporter:
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData: