diff --git a/Source/Editor/Windows/GameCookerWindow.cs b/Source/Editor/Windows/GameCookerWindow.cs index 0088cdf86..261090d4a 100644 --- a/Source/Editor/Windows/GameCookerWindow.cs +++ b/Source/Editor/Windows/GameCookerWindow.cs @@ -196,6 +196,12 @@ namespace FlaxEditor.Windows var label = layout.Label(text, TextAlignment.Center); label.Label.AutoHeight = true; } + + /// + /// Used to add platform specific tools if available. + /// + /// The layout to start the tools at. + public virtual void OnCustomToolsLayout(LayoutElementsContainer layout) { } public virtual void Build() { @@ -237,6 +243,272 @@ namespace FlaxEditor.Windows class Android : Platform { protected override BuildPlatform BuildPlatform => BuildPlatform.AndroidARM64; + + /// + public override void OnCustomToolsLayout(LayoutElementsContainer layout) + { + base.OnCustomToolsLayout(layout); + + // Add emulation options to android tab. + layout.Space(5); + var emulatorGroup = layout.Group("Tools"); + var sdkPath = Environment.GetEnvironmentVariable("ANDROID_HOME"); + if (string.IsNullOrEmpty(sdkPath)) + sdkPath = Environment.GetEnvironmentVariable("ANDROID_SDK"); + emulatorGroup.Label($"SDK path: {sdkPath}"); + + // AVD and starting emulator + var avdGroup = emulatorGroup.Group("AVD Emulator"); + avdGroup.Label("Note: Create AVDs using Android Studio."); + avdGroup.Panel.IsClosed = false; + var refreshAVDListButton = avdGroup.Button("Refresh AVD list").Button; + var avdListGroup = avdGroup.Group("AVD List"); + avdListGroup.Panel.IsClosed = false; + var noAvdLabel = avdListGroup.Label("No AVDs detected. Click Refresh.", TextAlignment.Center).Label; + var avdListTree = new Tree(false) + { + Parent = avdListGroup.Panel, + }; + refreshAVDListButton.Clicked += () => + { + if (avdListTree.Children.Count > 0) + avdListTree.DisposeChildren(); + + var processStartInfo = new System.Diagnostics.ProcessStartInfo + { + FileName = Path.Combine(sdkPath, "emulator", "emulator.exe"), + Arguments = "-list-avds", + RedirectStandardOutput = true, + CreateNoWindow = true, + }; + + var process = new System.Diagnostics.Process + { + StartInfo = processStartInfo + }; + process.Start(); + var output = new string(process.StandardOutput.ReadToEnd()); + /* + CreateProcessSettings processSettings = new CreateProcessSettings + { + FileName = Path.Combine(sdkPath, "emulator", "emulator.exe"), + Arguments = "-list-avds", + HiddenWindow = false, + SaveOutput = true, + WaitForEnd = true, + }; + //processSettings.ShellExecute = true; + FlaxEngine.Platform.CreateProcess(ref processSettings); + + var output = new string(processSettings.Output);*/ + if (output.Length == 0) + { + noAvdLabel.Visible = true; + FlaxEditor.Editor.LogWarning("No AVDs detected."); + return; + } + noAvdLabel.Visible = false; + var splitOutput = output.Split('\n'); + foreach (var line in splitOutput) + { + if (string.IsNullOrEmpty(line.Trim())) + continue; + var item = new TreeNode + { + Text = line.Trim(), + Parent = avdListTree, + }; + } + avdListGroup.Panel.IsClosed = false; + }; + + avdGroup.Label("Emulator AVD Commands:"); + var commandsTextBox = avdGroup.TextBox().TextBox; + commandsTextBox.IsMultiline = false; + commandsTextBox.Text = "-no-snapshot-load -no-boot-anim"; // TODO: save user changes + + var startEmulatorButton = avdGroup.Button("Start AVD Emulator").Button; + startEmulatorButton.TooltipText = "Starts selected AVD from list."; + startEmulatorButton.Clicked += () => + { + if (avdListTree.Selection.Count == 0) + return; + + CreateProcessSettings processSettings = new CreateProcessSettings + { + FileName = Path.Combine(sdkPath, "emulator", "emulator.exe"), + Arguments = $"-avd {avdListTree.Selection[0].Text} {commandsTextBox.Text}", + HiddenWindow = true, + SaveOutput = false, + WaitForEnd = false, + }; + processSettings.ShellExecute = true; + FlaxEngine.Platform.CreateProcess(ref processSettings); + }; + + emulatorGroup.Space(2); + + // Device + var installGroup = emulatorGroup.Group("Install"); + installGroup.Panel.IsClosed = false; + installGroup.Label("Note: Used to install to AVD or physical devices."); + var refreshDeviceListButton = installGroup.Button("Refresh device list").Button; + var deviceListGroup = installGroup.Group("List of devices"); + deviceListGroup.Panel.IsClosed = false; + var noDevicesLabel = deviceListGroup.Label("No devices found. Click Refresh.", TextAlignment.Center).Label; + var deviceListTree = new Tree(false) + { + Parent = deviceListGroup.Panel, + }; + refreshDeviceListButton.Clicked += () => + { + if (deviceListTree.Children.Count > 0) + deviceListTree.DisposeChildren(); + + var processStartInfo = new System.Diagnostics.ProcessStartInfo + { + FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), + Arguments = "devices -l", + RedirectStandardOutput = true, + CreateNoWindow = true, + }; + + var process = new System.Diagnostics.Process + { + StartInfo = processStartInfo + }; + process.Start(); + var output = new string(process.StandardOutput.ReadToEnd()); + /* + CreateProcessSettings processSettings = new CreateProcessSettings + { + FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), + Arguments = "devices -l", + HiddenWindow = false, + //SaveOutput = true, + WaitForEnd = true, + }; + processSettings.SaveOutput = true; + processSettings.ShellExecute = false; + FlaxEngine.Platform.CreateProcess(ref processSettings); + + var output = new string(processSettings.Output); + */ + + if (output.Length > 0 && !output.Equals("List of devices attached", StringComparison.Ordinal)) + { + noDevicesLabel.Visible = false; + var splitLines = output.Split('\n'); + foreach (var line in splitLines) + { + if (line.Trim().Equals("List of devices attached", StringComparison.Ordinal) || string.IsNullOrEmpty(line.Trim())) + continue; + + var tab = line.Split("device "); + if (tab.Length < 2) + continue; + var item = new TreeNode + { + Text = $"{tab[0].Trim()} - {tab[1].Trim()}", + Tag = tab[0].Trim(), + Parent = deviceListTree, + }; + } + } + else + { + noDevicesLabel.Visible = true; + } + + deviceListGroup.Panel.IsClosed = false; + }; + + var autoStart = installGroup.Checkbox("Try to auto start activity on device."); + var installButton = installGroup.Button("Install APK to Device").Button; + installButton.TooltipText = "Installs APK from the output folder to the selected device."; + installButton.Clicked += () => + { + if (deviceListTree.Selection.Count == 0) + return; + + // Get built APK at output path + string output = StringUtils.ConvertRelativePathToAbsolute(Globals.ProjectFolder, StringUtils.NormalizePath(Output)); + if (!Directory.Exists(output)) + { + FlaxEditor.Editor.LogWarning("Can not copy APK because output folder does not exist."); + return; + } + + var apkFiles = Directory.GetFiles(output, "*.apk"); + if (apkFiles.Length == 0) + { + FlaxEditor.Editor.LogWarning("Can not copy APK because no .apk files were found in output folder."); + return; + } + + string apkFilesString = string.Empty; + for (int i = 0; i < apkFiles.Length; i++) + { + var file = apkFiles[i]; + if (i == 0) + { + apkFilesString = $"\"{file}\""; + continue; + } + apkFilesString += $" \"{file}\""; + } + + CreateProcessSettings processSettings = new CreateProcessSettings + { + FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), + Arguments = $"-s {deviceListTree.Selection[0].Tag} {(apkFiles.Length > 1 ? "install-multiple" : "install")} {apkFilesString}", + LogOutput = true, + }; + FlaxEngine.Platform.CreateProcess(ref processSettings); + + if (autoStart.CheckBox.Checked) + { + var gameSettings = GameSettings.Load(); + var productName = gameSettings.ProductName.Replace(" ", "").ToLower(); + var companyName = gameSettings.CompanyName.Replace(" ", "").ToLower(); + CreateProcessSettings processSettings1 = new CreateProcessSettings + { + FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), + Arguments = $"shell am start -n com.{companyName}.{productName}/com.flaxengine.GameActivity", + LogOutput = true, + }; + FlaxEngine.Platform.CreateProcess(ref processSettings1); + } + }; + + var adbLogButton = emulatorGroup.Button("Start adb log collecting").Button; + adbLogButton.TooltipText = "In debug and development builds the engine and game logs can be output directly to the adb."; + adbLogButton.Clicked += () => + { + var processStartInfo = new System.Diagnostics.ProcessStartInfo + { + FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), + Arguments = "logcat Flax:I *:S", + CreateNoWindow = false, + WindowStyle = ProcessWindowStyle.Normal, + }; + + var process = new System.Diagnostics.Process + { + StartInfo = processStartInfo + }; + process.Start(); + /* + CreateProcessSettings processSettings = new CreateProcessSettings + { + FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), + Arguments = $"logcat Flax:I *:S", + WaitForEnd = false, + }; + FlaxEngine.Platform.CreateProcess(ref processSettings); + */ + }; + } } class Switch : Platform @@ -347,269 +619,7 @@ namespace FlaxEditor.Windows _buildButton = layout.Button("Build").Button; _buildButton.Clicked += OnBuildClicked; - - // Add emulation options to android tab. - if (_platform == PlatformType.Android) - { - layout.Space(5); - var emulatorGroup = layout.Group("Tools"); - var sdkPath = Environment.GetEnvironmentVariable("ANDROID_HOME"); - if (string.IsNullOrEmpty(sdkPath)) - sdkPath = Environment.GetEnvironmentVariable("ANDROID_SDK"); - emulatorGroup.Label($"SDK path: {sdkPath}"); - - // AVD and starting emulator - var avdGroup = emulatorGroup.Group("AVD Emulator"); - avdGroup.Label("Note: Create AVDs using Android Studio."); - avdGroup.Panel.IsClosed = false; - var refreshAVDListButton = avdGroup.Button("Refresh AVD list").Button; - var avdListGroup = avdGroup.Group("AVD List"); - avdListGroup.Panel.IsClosed = false; - var noAvdLabel = avdListGroup.Label("No AVDs detected. Click Refresh.", TextAlignment.Center).Label; - var avdListTree = new Tree(false) - { - Parent = avdListGroup.Panel, - }; - refreshAVDListButton.Clicked += () => - { - if (avdListTree.Children.Count > 0) - avdListTree.DisposeChildren(); - - var processStartInfo = new System.Diagnostics.ProcessStartInfo - { - FileName = Path.Combine(sdkPath, "emulator", "emulator.exe"), - Arguments = "-list-avds", - RedirectStandardOutput = true, - CreateNoWindow = true, - }; - - var process = new System.Diagnostics.Process - { - StartInfo = processStartInfo - }; - process.Start(); - var output = new string(process.StandardOutput.ReadToEnd()); - /* - CreateProcessSettings processSettings = new CreateProcessSettings - { - FileName = Path.Combine(sdkPath, "emulator", "emulator.exe"), - Arguments = "-list-avds", - HiddenWindow = false, - SaveOutput = true, - WaitForEnd = true, - }; - //processSettings.ShellExecute = true; - FlaxEngine.Platform.CreateProcess(ref processSettings); - - var output = new string(processSettings.Output);*/ - if (output.Length == 0) - { - noAvdLabel.Visible = true; - FlaxEditor.Editor.LogWarning("No AVDs detected."); - return; - } - noAvdLabel.Visible = false; - var splitOutput = output.Split('\n'); - foreach (var line in splitOutput) - { - if (string.IsNullOrEmpty(line.Trim())) - continue; - var item = new TreeNode - { - Text = line.Trim(), - Parent = avdListTree, - }; - } - avdListGroup.Panel.IsClosed = false; - }; - - avdGroup.Label("Emulator AVD Commands:"); - var commandsTextBox = avdGroup.TextBox().TextBox; - commandsTextBox.IsMultiline = false; - commandsTextBox.Text = "-no-snapshot-load -no-boot-anim"; // TODO: save user changes - - var startEmulatorButton = avdGroup.Button("Start AVD Emulator").Button; - startEmulatorButton.TooltipText = "Starts selected AVD from list."; - startEmulatorButton.Clicked += () => - { - if (avdListTree.Selection.Count == 0) - return; - - CreateProcessSettings processSettings = new CreateProcessSettings - { - FileName = Path.Combine(sdkPath, "emulator", "emulator.exe"), - Arguments = $"-avd {avdListTree.Selection[0].Text} {commandsTextBox.Text}", - HiddenWindow = true, - SaveOutput = false, - WaitForEnd = false, - }; - processSettings.ShellExecute = true; - FlaxEngine.Platform.CreateProcess(ref processSettings); - }; - - emulatorGroup.Space(2); - - // Device - var installGroup = emulatorGroup.Group("Install"); - installGroup.Panel.IsClosed = false; - installGroup.Label("Note: Used to install to AVD or physical devices."); - var refreshDeviceListButton = installGroup.Button("Refresh device list").Button; - var deviceListGroup = installGroup.Group("List of devices"); - deviceListGroup.Panel.IsClosed = false; - var noDevicesLabel = deviceListGroup.Label("No devices found. Click Refresh.", TextAlignment.Center).Label; - var deviceListTree = new Tree(false) - { - Parent = deviceListGroup.Panel, - }; - refreshDeviceListButton.Clicked += () => - { - if (deviceListTree.Children.Count > 0) - deviceListTree.DisposeChildren(); - - var processStartInfo = new System.Diagnostics.ProcessStartInfo - { - FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), - Arguments = "devices -l", - RedirectStandardOutput = true, - CreateNoWindow = true, - }; - - var process = new System.Diagnostics.Process - { - StartInfo = processStartInfo - }; - process.Start(); - var output = new string(process.StandardOutput.ReadToEnd()); - /* - CreateProcessSettings processSettings = new CreateProcessSettings - { - FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), - Arguments = "devices -l", - HiddenWindow = false, - //SaveOutput = true, - WaitForEnd = true, - }; - processSettings.SaveOutput = true; - processSettings.ShellExecute = false; - FlaxEngine.Platform.CreateProcess(ref processSettings); - - var output = new string(processSettings.Output); - */ - - if (output.Length > 0 && !output.Equals("List of devices attached", StringComparison.Ordinal)) - { - noDevicesLabel.Visible = false; - var splitLines = output.Split('\n'); - foreach (var line in splitLines) - { - if (line.Trim().Equals("List of devices attached", StringComparison.Ordinal) || string.IsNullOrEmpty(line.Trim())) - continue; - - var tab = line.Split("device "); - if (tab.Length < 2) - continue; - var item = new TreeNode - { - Text = $"{tab[0].Trim()} - {tab[1].Trim()}", - Tag = tab[0].Trim(), - Parent = deviceListTree, - }; - } - } - else - { - noDevicesLabel.Visible = true; - } - - deviceListGroup.Panel.IsClosed = false; - }; - - var autoStart = installGroup.Checkbox("Try to auto start activity on device."); - var installButton = installGroup.Button("Install APK to Device").Button; - installButton.TooltipText = "Installs APK from the output folder to the selected device."; - installButton.Clicked += () => - { - if (deviceListTree.Selection.Count == 0) - return; - - // Get built APK at output path - string output = StringUtils.ConvertRelativePathToAbsolute(Globals.ProjectFolder, StringUtils.NormalizePath(proxy.PerPlatformOptions[_platform].Output)); - if (!Directory.Exists(output)) - { - FlaxEditor.Editor.LogWarning("Can not copy APK because output folder does not exist."); - return; - } - - var apkFiles = Directory.GetFiles(output, "*.apk"); - if (apkFiles.Length == 0) - { - FlaxEditor.Editor.LogWarning("Can not copy APK because no .apk files were found in output folder."); - return; - } - - string apkFilesString = string.Empty; - for (int i = 0; i < apkFiles.Length; i++) - { - var file = apkFiles[i]; - if (i == 0) - { - apkFilesString = $"\"{file}\""; - continue; - } - apkFilesString += $" \"{file}\""; - } - - CreateProcessSettings processSettings = new CreateProcessSettings - { - FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), - Arguments = $"-s {deviceListTree.Selection[0].Tag} {(apkFiles.Length > 1 ? "install-multiple" : "install")} {apkFilesString}", - LogOutput = true, - }; - FlaxEngine.Platform.CreateProcess(ref processSettings); - - if (autoStart.CheckBox.Checked) - { - var gameSettings = GameSettings.Load(); - var productName = gameSettings.ProductName.Replace(" ", "").ToLower(); - var companyName = gameSettings.CompanyName.Replace(" ", "").ToLower(); - CreateProcessSettings processSettings1 = new CreateProcessSettings - { - FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), - Arguments = $"shell am start -n com.{companyName}.{productName}/com.flaxengine.GameActivity", - LogOutput = true, - }; - FlaxEngine.Platform.CreateProcess(ref processSettings1); - } - }; - - var adbLogButton = emulatorGroup.Button("Start adb log collecting").Button; - adbLogButton.TooltipText = "In debug and development builds the engine and game logs can be output directly to the adb."; - adbLogButton.Clicked += () => - { - var processStartInfo = new System.Diagnostics.ProcessStartInfo - { - FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), - Arguments = "logcat Flax:I *:S", - CreateNoWindow = false, - WindowStyle = ProcessWindowStyle.Normal, - }; - - var process = new System.Diagnostics.Process - { - StartInfo = processStartInfo - }; - process.Start(); - /* - CreateProcessSettings processSettings = new CreateProcessSettings - { - FileName = Path.Combine(sdkPath, "platform-tools", "adb.exe"), - Arguments = $"logcat Flax:I *:S", - WaitForEnd = false, - }; - FlaxEngine.Platform.CreateProcess(ref processSettings); - */ - }; - } + platformObj.OnCustomToolsLayout(layout); } else {