[GUI] Add console logger

This commit is contained in:
VaDiM 2023-12-06 17:28:10 +03:00
parent d42a1879ab
commit f82a73f018
12 changed files with 296 additions and 42 deletions

View File

@ -1,10 +1,10 @@
using System;
namespace AssetStudioCLI
namespace AssetStudio
{
// Represents set with 16 base colors using ANSI escape codes, which should be supported in most terminals
// (well, except for windows editions before windows 10)
public static class CLIAnsiColors
public static class ColorConsole
{
public static readonly string
Black = "\u001b[30m",
@ -27,7 +27,7 @@ namespace AssetStudioCLI
public static string Color(this string str, string ansiColor)
{
if (!CLIWinAnsiFix.isAnsiSupported)
if (!ColorConsoleHelper.isAnsiCodesSupported)
{
return str;
}
@ -35,10 +35,10 @@ namespace AssetStudioCLI
return $"{ansiColor}{str}{Reset}";
}
public static void ANSICodesTest()
public static void AnsiCodesTest()
{
Console.WriteLine("ANSI escape codes test");
Console.WriteLine($"Supported: {CLIWinAnsiFix.isAnsiSupported}");
Console.WriteLine($"Supported: {ColorConsoleHelper.isAnsiCodesSupported}");
Console.WriteLine("\u001b[30m A \u001b[31m B \u001b[32m C \u001b[33m D \u001b[0m");
Console.WriteLine("\u001b[34m E \u001b[35m F \u001b[36m G \u001b[37m H \u001b[0m");
Console.WriteLine("\u001b[30;1m A \u001b[31;1m B \u001b[32;1m C \u001b[33;1m D \u001b[0m");

View File

@ -2,11 +2,11 @@
using System;
using System.Runtime.InteropServices;
namespace AssetStudioCLI
namespace AssetStudio
{
static class CLIWinAnsiFix
internal static class ColorConsoleHelper
{
public static readonly bool isAnsiSupported;
public static readonly bool isAnsiCodesSupported;
private const int STD_OUTPUT_HANDLE = -11;
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
@ -19,21 +19,21 @@ namespace AssetStudioCLI
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(int nStdHandle);
static CLIWinAnsiFix()
static ColorConsoleHelper()
{
bool isWin = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
var isWin = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
if (isWin)
{
isAnsiSupported = TryEnableVTMode();
if (!isAnsiSupported)
isAnsiCodesSupported = TryEnableVTMode();
if (!isAnsiCodesSupported)
{
//Check for bash terminal emulator. E.g., Git Bash, Cmder
isAnsiSupported = Environment.GetEnvironmentVariable("TERM") != null;
isAnsiCodesSupported = Environment.GetEnvironmentVariable("TERM") != null;
}
}
else
{
isAnsiSupported = true;
isAnsiCodesSupported = true;
}
}
@ -51,12 +51,7 @@ namespace AssetStudioCLI
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(iStdOut, outConsoleMode))
{
return false;
}
return true;
return SetConsoleMode(iStdOut, outConsoleMode);
}
}
}

View File

@ -29,6 +29,7 @@ namespace AssetStudioCLI
LogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogName);
var arch = Environment.Is64BitProcess ? "x64" : "x32";
Console.OutputEncoding = System.Text.Encoding.UTF8;
LogToFile(LoggerEvent.Verbose, $"---{appAssembly.Name} v{appAssembly.Version} [{arch}] | Logger launched---\n" +
$"CMD Args: {string.Join(" ", CLIOptions.cliArgs)}");
@ -36,15 +37,15 @@ namespace AssetStudioCLI
private static string ColorLogLevel(LoggerEvent logLevel)
{
string formattedLevel = $"[{logLevel}]";
var formattedLevel = $"[{logLevel}]";
switch (logLevel)
{
case LoggerEvent.Info:
return $"{formattedLevel.Color(CLIAnsiColors.BrightCyan)}";
return $"{formattedLevel.Color(ColorConsole.BrightCyan)}";
case LoggerEvent.Warning:
return $"{formattedLevel.Color(CLIAnsiColors.BrightYellow)}";
return $"{formattedLevel.Color(ColorConsole.BrightYellow)}";
case LoggerEvent.Error:
return $"{formattedLevel.Color(CLIAnsiColors.BrightRed)}";
return $"{formattedLevel.Color(ColorConsole.BrightRed)}";
default:
return formattedLevel;
}
@ -59,7 +60,7 @@ namespace AssetStudioCLI
string formattedMessage;
if (consoleMode)
{
string colorLogLevel = ColorLogLevel(logMsgLevel);
var colorLogLevel = ColorLogLevel(logMsgLevel);
formattedMessage = $"{colorLogLevel} {message}";
if (multiLine)
{

View File

@ -327,7 +327,7 @@ namespace AssetStudioCLI
Directory.CreateDirectory(dir);
return true;
}
Logger.Error($"Export error. File \"{fullPath.Color(CLIAnsiColors.BrightRed)}\" already exist");
Logger.Error($"Export error. File \"{fullPath.Color(ColorConsole.BrightRed)}\" already exist");
return false;
}

View File

@ -397,8 +397,8 @@ namespace AssetStudioCLI.Options
{
cliArgs = args;
var brightYellow = CLIAnsiColors.BrightYellow;
var brightRed = CLIAnsiColors.BrightRed;
var brightYellow = ColorConsole.BrightYellow;
var brightRed = ColorConsole.BrightRed;
if (args.Length == 0 || args.Any(x => x.ToLower() == "-h" || x.ToLower() == "--help" || x.ToLower() == "-?"))
{
@ -858,7 +858,7 @@ namespace AssetStudioCLI.Options
}
catch (Exception ex)
{
Console.WriteLine("Unknown Error.".Color(CLIAnsiColors.Red));
Console.WriteLine("Unknown Error.".Color(ColorConsole.Red));
Console.WriteLine(ex);
return;
}
@ -901,7 +901,7 @@ namespace AssetStudioCLI.Options
var arg = isFlag ? "flag" : "option";
var rand = new Random();
var rndOption = optionDesc.ElementAt(rand.Next(0, optionDesc.Length));
Console.WriteLine($"Did you mean [{$"{rndOption.Key}".Color(CLIAnsiColors.BrightYellow)}] {arg}?");
Console.WriteLine($"Did you mean [{$"{rndOption.Key}".Color(ColorConsole.BrightYellow)}] {arg}?");
Console.WriteLine($"Here's a description of it: \n\n{rndOption.Value}");
return true;

View File

@ -7,7 +7,7 @@ using System.Linq;
using System.Xml.Linq;
using static AssetStudioCLI.Exporter;
using static CubismLive2DExtractor.Live2DExtractor;
using Ansi = AssetStudioCLI.CLIAnsiColors;
using Ansi = AssetStudio.ColorConsole;
namespace AssetStudioCLI
{

View File

@ -77,6 +77,8 @@
this.allToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem();
this.showConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.writeLogToFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
@ -536,6 +538,8 @@
//
this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem15,
this.showConsoleToolStripMenuItem,
this.writeLogToFileToolStripMenuItem,
this.exportClassStructuresMenuItem});
this.debugMenuItem.Name = "debugMenuItem";
this.debugMenuItem.Size = new System.Drawing.Size(54, 20);
@ -549,6 +553,24 @@
this.toolStripMenuItem15.Text = "Show all error messages";
this.toolStripMenuItem15.Click += new System.EventHandler(this.toolStripMenuItem15_Click);
//
// showConsoleToolStripMenuItem
//
this.showConsoleToolStripMenuItem.Checked = true;
this.showConsoleToolStripMenuItem.CheckOnClick = true;
this.showConsoleToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
this.showConsoleToolStripMenuItem.Name = "showConsoleToolStripMenuItem";
this.showConsoleToolStripMenuItem.Size = new System.Drawing.Size(200, 22);
this.showConsoleToolStripMenuItem.Text = "Show console logger";
this.showConsoleToolStripMenuItem.Click += new System.EventHandler(this.showConsoleToolStripMenuItem_Click);
//
// writeLogToFileToolStripMenuItem
//
this.writeLogToFileToolStripMenuItem.CheckOnClick = true;
this.writeLogToFileToolStripMenuItem.Name = "writeLogToFileToolStripMenuItem";
this.writeLogToFileToolStripMenuItem.Size = new System.Drawing.Size(200, 22);
this.writeLogToFileToolStripMenuItem.Text = "Write log to file";
this.writeLogToFileToolStripMenuItem.CheckedChanged += new System.EventHandler(this.writeLogToFileToolStripMenuItem_CheckedChanged);
//
// exportClassStructuresMenuItem
//
this.exportClassStructuresMenuItem.Name = "exportClassStructuresMenuItem";
@ -1256,6 +1278,7 @@
this.Name = "AssetStudioGUIForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "AssetStudioModGUI";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.AssetStudioGUIForm_FormClosing);
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragDrop);
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragEnter);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.AssetStudioForm_KeyDown);
@ -1405,6 +1428,8 @@
private System.Windows.Forms.ToolStripMenuItem showRelatedAssetsToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
private System.Windows.Forms.ListView assetListView;
private System.Windows.Forms.ToolStripMenuItem showConsoleToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem writeLogToFileToolStripMenuItem;
}
}

View File

@ -117,20 +117,26 @@ namespace AssetStudioGUI
public AssetStudioGUIForm()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
ConsoleWindow.RunConsole(Properties.Settings.Default.showConsole);
InitializeComponent();
var appAssembly = typeof(Program).Assembly.GetName();
guiTitle = $"{appAssembly.Name} v{appAssembly.Version}";
Text = guiTitle;
delayTimer = new System.Timers.Timer(800);
delayTimer.Elapsed += new ElapsedEventHandler(delayTimer_Elapsed);
delayTimer.Elapsed += delayTimer_Elapsed;
displayAll.Checked = Properties.Settings.Default.displayAll;
displayInfo.Checked = Properties.Settings.Default.displayInfo;
enablePreview.Checked = Properties.Settings.Default.enablePreview;
showConsoleToolStripMenuItem.Checked = Properties.Settings.Default.showConsole;
FMODinit();
listSearchFilterMode.SelectedIndex = 0;
logger = new GUILogger(StatusStripUpdate);
Logger.Default = logger;
writeLogToFileToolStripMenuItem.Checked = Properties.Settings.Default.useFileLogger;
Progress.Default = new Progress<int>(SetProgressBarValue);
Studio.StatusStripUpdate = StatusStripUpdate;
}
@ -233,17 +239,11 @@ namespace AssetStudioGUI
return;
}
(var productName, var treeNodeCollection) = await Task.Run(() => BuildAssetData());
var (productName, treeNodeCollection) = await Task.Run(() => BuildAssetData());
var typeMap = await Task.Run(() => BuildClassStructure());
productName = string.IsNullOrEmpty(productName) ? "no productName" : productName;
if (!string.IsNullOrEmpty(productName))
{
Text = $"{guiTitle} - {productName} - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}";
}
else
{
Text = $"{guiTitle} - no productName - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}";
}
Text = $"{guiTitle} - {productName} - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}";
assetListView.VirtualListSize = visibleAssets.Count;
@ -2011,6 +2011,32 @@ namespace AssetStudioGUI
}
}
private void showConsoleToolStripMenuItem_Click(object sender, EventArgs e)
{
var showConsole = showConsoleToolStripMenuItem.Checked;
if (showConsole)
ConsoleWindow.ShowConsoleWindow();
else
ConsoleWindow.HideConsoleWindow();
Properties.Settings.Default.showConsole = showConsole;
Properties.Settings.Default.Save();
}
private void writeLogToFileToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
var useFileLogger = writeLogToFileToolStripMenuItem.Checked;
logger.UseFileLogger = useFileLogger;
Properties.Settings.Default.useFileLogger = useFileLogger;
Properties.Settings.Default.Save();
}
private void AssetStudioGUIForm_FormClosing(object sender, FormClosingEventArgs e)
{
Logger.Verbose("Closing AssetStudio");
}
#region FMOD
private void FMODinit()
{

View File

@ -0,0 +1,67 @@
using System;
using System.Runtime.InteropServices;
using AssetStudio;
namespace AssetStudioGUI
{
internal static class ConsoleWindow
{
private enum CtrlSignalType
{
CTRL_C_EVENT,
CTRL_BREAK_EVENT,
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll", SetLastError = true)]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
private delegate bool EventHandler(CtrlSignalType ctrlSignal);
private static EventHandler eventHandler;
private static IntPtr ConsoleWindowHandle;
private static readonly int SW_HIDE = 0;
private static readonly int SW_SHOW = 5;
private static bool CloseEventHandler(CtrlSignalType ctrlSignal)
{
switch (ctrlSignal)
{
case CtrlSignalType.CTRL_C_EVENT:
case CtrlSignalType.CTRL_BREAK_EVENT:
return true;
default:
Logger.Verbose("Closing AssetStudio");
return false;
}
}
public static void RunConsole(bool showConsole)
{
AllocConsole();
ConsoleWindowHandle = GetConsoleWindow();
eventHandler += CloseEventHandler;
SetConsoleCtrlHandler(eventHandler, true);
if (!showConsole)
HideConsoleWindow();
}
public static void ShowConsoleWindow()
{
ShowWindow(ConsoleWindowHandle, SW_SHOW);
}
public static void HideConsoleWindow()
{
ShowWindow(ConsoleWindowHandle, SW_HIDE);
}
}
}

View File

@ -1,5 +1,8 @@
using AssetStudio;
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace AssetStudioGUI
@ -7,15 +10,122 @@ namespace AssetStudioGUI
class GUILogger : ILogger
{
public bool ShowErrorMessage = false;
private bool IsFileLoggerRunning = false;
private string LoggerInitString;
private string FileLogName;
private string FileLogPath;
private Action<string> action;
private bool _useFileLogger = false;
public bool UseFileLogger
{
get => _useFileLogger;
set
{
_useFileLogger = value;
if (_useFileLogger && !IsFileLoggerRunning)
{
var appAssembly = typeof(Program).Assembly.GetName();
FileLogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
FileLogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FileLogName);
LogToFile(LoggerEvent.Verbose, $"# {LoggerInitString} - Logger launched #");
IsFileLoggerRunning = true;
}
else if (!_useFileLogger && IsFileLoggerRunning)
{
LogToFile(LoggerEvent.Verbose, "# Logger closed #");
IsFileLoggerRunning = false;
}
}
}
public GUILogger(Action<string> action)
{
this.action = action;
var appAssembly = typeof(Program).Assembly.GetName();
var arch = Environment.Is64BitProcess ? "x64" : "x32";
var frameworkName = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;
LoggerInitString = $"{appAssembly.Name} v{appAssembly.Version} [{arch}] [{frameworkName}]";
try
{
Console.Title = $"Console Logger - {appAssembly.Name} v{appAssembly.Version}";
Console.OutputEncoding = System.Text.Encoding.UTF8;
}
catch
{
// ignored
}
Console.WriteLine($"# {LoggerInitString}");
}
private static string ColorLogLevel(LoggerEvent logLevel)
{
var formattedLevel = $"[{logLevel}]";
switch (logLevel)
{
case LoggerEvent.Info:
return $"{formattedLevel.Color(ColorConsole.BrightCyan)}";
case LoggerEvent.Warning:
return $"{formattedLevel.Color(ColorConsole.BrightYellow)}";
case LoggerEvent.Error:
return $"{formattedLevel.Color(ColorConsole.BrightRed)}";
default:
return formattedLevel;
}
}
private static string FormatMessage(LoggerEvent logMsgLevel, string message, bool toConsole)
{
message = message.TrimEnd();
var multiLine = message.Contains('\n');
string formattedMessage;
if (toConsole)
{
var colorLogLevel = ColorLogLevel(logMsgLevel);
formattedMessage = $"{colorLogLevel} {message}";
if (multiLine)
{
formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ");
}
}
else
{
var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
message = Regex.Replace(message, @"\e\[[0-9;]*m(?:\e\[K)?", ""); //Delete ANSI colors
var logLevel = $"{logMsgLevel.ToString().ToUpper(),-7}";
formattedMessage = $"{curTime} | {logLevel} | {message}";
if (multiLine)
{
formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ");
}
}
return formattedMessage;
}
private async void LogToFile(LoggerEvent logMsgLevel, string message)
{
using (var sw = new StreamWriter(FileLogPath, append: true, System.Text.Encoding.UTF8))
{
await sw.WriteLineAsync(FormatMessage(logMsgLevel, message, toConsole: false));
}
}
public void Log(LoggerEvent loggerEvent, string message, bool ignoreLevel)
{
//File logger
if (_useFileLogger)
{
LogToFile(loggerEvent, message);
}
//Console logger
Console.WriteLine(FormatMessage(loggerEvent, message, toConsole: true));
//GUI logger
switch (loggerEvent)
{
case LoggerEvent.Error:

View File

@ -12,7 +12,7 @@ namespace AssetStudioGUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@ -310,5 +310,29 @@ namespace AssetStudioGUI.Properties {
this["l2dForceBezier"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool showConsole {
get {
return ((bool)(this["showConsole"]));
}
set {
this["showConsole"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool useFileLogger {
get {
return ((bool)(this["useFileLogger"]));
}
set {
this["useFileLogger"] = value;
}
}
}
}

View File

@ -74,5 +74,11 @@
<Setting Name="l2dForceBezier" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="showConsole" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="useFileLogger" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>