using System; using System.ComponentModel.Composition.Primitives; using System.Linq; using System.Threading.Tasks; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; using Object = UnityEngine.Object; namespace Needle.Engine.Deployment { public class BuildWindowDeployOptions : INeedleBuildPlatformGUIProvider { private GUIStyle fixedMiniLabel; public void OnBuildPlatformsGUI(NeedleEngineBuildOptions options) { if (fixedMiniLabel == null) { fixedMiniLabel = new GUIStyle(EditorStyles.wordWrappedMiniLabel); fixedMiniLabel.padding.left = 0; } if (NeedleDebug.DeveloperMode) { EditorGUILayout.HelpBox("DEVELOPER MODE IS ENABLED", MessageType.Warning); GUILayout.Space(5); } var hasLicense = LicenseCheck.HasCommercialLicense; var hasValidLicense = LicenseCheck.LicenseIsActive; var width = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth -= 30; using (new EditorGUILayout.HorizontalScope()) { var tooltip = NeedleEngineBuildOptions.DevelopmentBuild ? "Development build enabled - this means your project will produce bigger files because textures and meshes will not be compressed. Press this button to enable Production builds and compress your glTF files after building." : "Production build enabled - when building your resulting glTF files will get compressed using toktx (this means mainly meshes and textures will get way smaller)"; NeedleEngineBuildOptions.DevelopmentBuild = EditorGUILayout.Toggle(new GUIContent("Development Build", tooltip), NeedleEngineBuildOptions.DevelopmentBuild); if (NeedleEngineBuildOptions.DevelopmentBuild) { using(new EditorGUI.DisabledScope(true)) GUILayout.Label(new GUIContent("No mesh/texture compression", "For production we recommend to disable the development build option. Development builds produce uncompressed output resulting in larger assets, higher runtime memory requirements, and reduced performance."), EditorStyles.wordWrappedLabel); } } using (new EditorGUILayout.HorizontalScope()) { var tooltip = "When enabled, HTML, CSS and JS files will be gzip-compressed during the build process, reducing their size. This is recommended for production builds. Make sure your server is set up to serve gzipped files."; using (new EditorGUI.DisabledScope(!hasValidLicense)) { if (!hasValidLicense) NeedleEngineBuildOptions.UseGzipCompression = true; NeedleEngineBuildOptions.UseGzipCompression = EditorGUILayout.Toggle(new GUIContent("Gzip Compression", tooltip), NeedleEngineBuildOptions.UseGzipCompression); } } EditorGUILayout.Space(10); using (new EditorGUILayout.VerticalScope()) { // var main = EditorStyles.wordWrappedLabel; // GUILayout.Label( // new GUIContent("Deployment", // "Click any of the buttons below to add the deployment component to your scene or (if it already exists) ping the object"), // EditorStyles.boldLabel); // GUILayout.Space(6); // if (!Authentication.IsLoggedIn()) // { // using (new EditorGUILayout.HorizontalScope()) // { // EditorGUILayout.HelpBox("Get a Needle Engine license to deploy with ease to any platform", MessageType.Info); // if (GUILayout.Button(new GUIContent("Login to Needle Cloud", "See the available commercial plans - deploy with ease with Needle Engine"), GUILayout.Width(150), GUILayout.Height(38))) // { // Authentication.Login(); // } // } // GUILayout.Space(5); // } EditorGUILayout.LabelField("Deploy to Needle Cloud", EditorStyles.boldLabel); GUILayout.Space(-5); EditorGUILayout.LabelField("Fast deployments, versioning, and collaboration.", fixedMiniLabel); var exp = ExportInfo.Get(); if (exp) { NeedleCloudGUI.Instance.OnGUI(); } GUILayout.Space(5); GUILayout.FlexibleSpace(); EditorGUILayout.LabelField("Other Platforms", EditorStyles.boldLabel, GUILayout.MaxWidth(150), GUILayout.MaxHeight(10)); if (!hasLicense) { using(new EditorGUI.DisabledScope(true)) EditorGUILayout.LabelField("Deploy to Needle Cloud for free or get PRO to deploy anywhere: Fast deployment to other platforms", fixedMiniLabel); } else { EditorGUILayout.LabelField("Fast deployment to various hosting platforms.", fixedMiniLabel); } using (new EditorGUI.DisabledScope(!hasValidLicense || !hasLicense)) { DrawDeployToOptionButtons(); } // if (hasValidLicense) // { // GUILayout.Space(5); // using (new EditorGUILayout.HorizontalScope()) // { // EditorGUILayout.LabelField( // new GUIContent( // "Learn more about all our deployment options by visiting the Needle Engine documentation."), // main); // if (GUILayout.Button("Open Documentation ↗")) // Help.BrowseURL(Constants.DocumentationUrlDeployment); // } // } } EditorGUIUtility.labelWidth = width; } private class DeploymentComponentEntry { public Type type; public Texture2D icon; public string label; public string niceName; public GUIContent content; } private static DeploymentComponentEntry[] deploymentComponents; private static GUIStyle buttonLeftAligned; private static void DrawDeployToOptionButtons() { deploymentComponents ??= TypeCache .GetTypesWithAttribute() .Where(t => typeof(MonoBehaviour).IsAssignableFrom(t)) .OrderBy(t => t.Name) .Select(x => { var labelText = ObjectNames.NicifyVariableName(x.Name); if (labelText.StartsWith("Deploy To")) labelText = labelText.Substring("Deploy To".Length); var entry = new DeploymentComponentEntry { type = x, niceName = labelText, }; if (x .GetCustomAttributes(typeof(CustomComponentHeaderLinkAttribute), true) .FirstOrDefault() is CustomComponentHeaderLinkAttribute comp && !string.IsNullOrEmpty(comp.IconIconPathOrGuid)) { entry.icon = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath(comp.IconIconPathOrGuid));; } if (x .GetCustomAttributes(typeof(AddComponentMenu), true) .FirstOrDefault() is AddComponentMenu menu && !string.IsNullOrEmpty(menu.componentMenu)) { entry.label = menu.componentMenu; } entry.content = new GUIContent(entry.niceName, entry.icon,"Click to add the '" + entry.label + "' component to your scene"); return entry; }) .ToArray(); buttonLeftAligned ??= new GUIStyle(GUI.skin.button) { alignment = TextAnchor.MiddleLeft, padding = new RectOffset(5,5,5,5), }; EditorGUILayout.BeginHorizontal(); var i = 0; const int leftColumnWidth = 295; var maxWidthPerButton = (Screen.width / EditorGUIUtility.pixelsPerPoint - leftColumnWidth) / 2.0f; maxWidthPerButton -= 7; // to avoid horizontal scrollbar IF we have a vertical scrollbar (seems to be windows only) var width = GUILayout.Width(maxWidthPerButton); var height = GUILayout.Height(24); for (var index = 0; index < deploymentComponents.Length; index++) { var entry = deploymentComponents[index]; if (i++ >= 2) { i = 1; EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); } if (GUILayout.Button(entry.content, buttonLeftAligned, width, height)) { var existing = Object.FindAnyObjectByType(entry.type); if (existing) { EditorGUIUtility.PingObject(existing); Selection.activeObject = existing; } else { var exp = ExportInfo.Get(); if (exp) { var gameObject = exp.gameObject; EditorGUIUtility.PingObject(exp); Selection.activeObject = gameObject; AddDelayed(); async void AddDelayed() { await Task.Delay(300); Debug.Log("Added the \"" + entry.niceName + "\" component to " + gameObject, gameObject); Undo.AddComponent(exp.gameObject, entry.type); } } } } } EditorGUILayout.EndHorizontal(); } } }