MosswartMassacre/MosswartMassacre/Views/VVSBaseView.cs
2025-06-22 22:31:21 +02:00

395 lines
No EOL
12 KiB
C#

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Timers;
using VirindiViewService;
using VirindiViewService.XMLParsers;
namespace MosswartMassacre.Views
{
/// <summary>
/// Base class for VVS (VirindiViewService) based views.
/// Replaces the wrapper-based BaseView with direct VVS integration.
/// </summary>
public class VVSBaseView : IDisposable
{
#region Windows API for boundary checking
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public int Width { get { return Right - Left; } }
public int Height { get { return Bottom - Top; } }
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
#endregion
#region Core VVS Components
protected HudView view;
protected ViewProperties properties;
protected ControlGroup controls;
protected PluginCore pluginCore;
#endregion
#region Position Management
private Timer positionSaveTimer;
#endregion
public VVSBaseView(PluginCore core)
{
pluginCore = core;
InitializePositionTimer();
}
#region VVS Initialization
protected void CreateFromXMLResource(string resourcePath, bool doIcon = true, bool doTitle = true)
{
try
{
// Parse XML using VVS Decal3XMLParser
new Decal3XMLParser().ParseFromResource(resourcePath, out properties, out controls);
// Set window properties
if (doTitle)
{
properties.Title = "Mosswart Massacre v5.0.0.0";
}
if (doIcon)
{
// Use default icon for now - can be customized later
properties.Icon = 7735; // Same icon as in XML
}
// Create the HudView
view = new HudView(properties, controls);
// Subscribe to essential events
view.VisibleChanged += View_VisibleChanged;
view.Moved += View_Moved;
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error creating VVS view from {resourcePath}: {ex.Message}");
PluginCore.WriteToChat($"Stack trace: {ex.StackTrace}");
}
}
protected void CreateFromXMLString(string xmlString, bool doIcon = true, bool doTitle = true)
{
try
{
// Parse XML string using VVS Decal3XMLParser
new Decal3XMLParser().Parse(xmlString, out properties, out controls);
if (doTitle)
{
properties.Title = "Mosswart Massacre v5.0.0.0";
}
if (doIcon)
{
properties.Icon = 7735;
}
view = new HudView(properties, controls);
view.VisibleChanged += View_VisibleChanged;
view.Moved += View_Moved;
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error creating VVS view from XML string: {ex.Message}");
}
}
#endregion
#region Control Access
/// <summary>
/// Get a control by name with proper type casting.
/// Usage: var button = GetControl&lt;HudButton&gt;("btnExample");
/// </summary>
protected T GetControl<T>(string controlName) where T : class
{
try
{
if (view != null && view[controlName] != null)
{
return view[controlName] as T;
}
return null;
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error getting control '{controlName}': {ex.Message}");
return null;
}
}
/// <summary>
/// Get a control by name (alternative syntax)
/// Usage: var button = (HudButton)GetControl("btnExample");
/// </summary>
protected object GetControl(string controlName)
{
try
{
return view?[controlName];
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error getting control '{controlName}': {ex.Message}");
return null;
}
}
#endregion
#region Window Management
protected virtual void SaveWindowPosition()
{
try
{
if (view != null && PluginSettings.Instance != null)
{
PluginSettings.Instance.MainWindowX = view.Location.X;
PluginSettings.Instance.MainWindowY = view.Location.Y;
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error saving window position: {ex.Message}");
}
}
protected virtual void RestoreWindowPosition()
{
try
{
if (view != null && PluginSettings.Instance != null)
{
view.Location = new Point(
PluginSettings.Instance.MainWindowX,
PluginSettings.Instance.MainWindowY
);
}
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error restoring window position: {ex.Message}");
}
}
protected void KeepWindowInBounds()
{
try
{
if (view == null) return;
RECT rect = new RECT();
IntPtr gameWindowHandle = PluginCore.MyHost?.Decal?.Hwnd ?? IntPtr.Zero;
if (gameWindowHandle != IntPtr.Zero && GetWindowRect(gameWindowHandle, ref rect))
{
Point currentLocation = view.Location;
int viewWidth = view.Width;
int viewHeight = view.Height;
bool needsUpdate = false;
// Check right boundary
if (currentLocation.X + viewWidth > rect.Width)
{
currentLocation.X = rect.Width - viewWidth;
needsUpdate = true;
}
// Check left boundary
else if (currentLocation.X < 0)
{
currentLocation.X = 20;
needsUpdate = true;
}
// Check bottom boundary
if (currentLocation.Y + viewHeight > rect.Height)
{
currentLocation.Y = rect.Height - viewHeight;
needsUpdate = true;
}
// Check top boundary
else if (currentLocation.Y < 0)
{
currentLocation.Y = 20;
needsUpdate = true;
}
if (needsUpdate)
{
view.Location = currentLocation;
}
}
}
catch
{
// Silently ignore boundary check errors
}
}
#endregion
#region Position Timer Management
private void InitializePositionTimer()
{
positionSaveTimer = new Timer(2000); // 2 second delay after movement stops
positionSaveTimer.Elapsed += (s, e) => {
SaveWindowPosition();
positionSaveTimer.Stop();
};
}
private void View_Moved(object sender, EventArgs e)
{
try
{
// Reset timer when window moves
if (positionSaveTimer != null)
{
if (positionSaveTimer.Enabled)
positionSaveTimer.Stop();
positionSaveTimer.Start();
}
}
catch
{
// Ignore timer errors
}
}
protected virtual void View_VisibleChanged(object sender, EventArgs e)
{
try
{
if (view.Visible)
{
KeepWindowInBounds();
}
}
catch
{
// Ignore visibility change errors
}
}
#endregion
#region Public Interface
public virtual void Initialize()
{
try
{
RestoreWindowPosition();
KeepWindowInBounds();
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error initializing VVS view: {ex.Message}");
}
}
public virtual void Show()
{
if (view != null)
{
view.Visible = true;
}
}
public virtual void Hide()
{
if (view != null)
{
view.Visible = false;
}
}
public virtual void Toggle()
{
if (view != null)
{
view.Visible = !view.Visible;
}
}
public bool IsVisible
{
get { return view?.Visible ?? false; }
}
public Point Location
{
get { return view?.Location ?? Point.Empty; }
set { if (view != null) view.Location = value; }
}
public Size Size
{
get { return view != null ? new Size(view.Width, view.Height) : Size.Empty; }
}
#endregion
#region IDisposable Support
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
try
{
// Save final position before disposal
SaveWindowPosition();
// Clean up timers
if (positionSaveTimer != null)
{
positionSaveTimer.Stop();
positionSaveTimer.Dispose();
positionSaveTimer = null;
}
// Clean up VVS view
if (view != null)
{
view.VisibleChanged -= View_VisibleChanged;
view.Moved -= View_Moved;
view.Dispose();
view = null;
}
// Clean up VVS objects
properties = null;
controls = null;
}
catch (Exception ex)
{
PluginCore.WriteToChat($"Error disposing VVS view: {ex.Message}");
}
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}