2014-01-27 00:02:21 +00:00
|
|
|
using System;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Text;
|
|
|
|
using System.Drawing;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
using BizHawk.Client.Common;
|
|
|
|
|
|
|
|
using BizHawk.Bizware.BizwareGL;
|
|
|
|
|
|
|
|
namespace BizHawk.Client.EmuHawk
|
|
|
|
{
|
2014-01-28 04:39:27 +00:00
|
|
|
/// <summary>
|
|
|
|
/// This is an old abstracted rendering class that the OSD system is using to get its work done.
|
|
|
|
/// We should probably just use a GuiRenderer (it was designed to do that) although wrapping it with
|
|
|
|
/// more information for OSDRendering could be helpful I suppose
|
|
|
|
/// </summary>
|
|
|
|
public interface IBlitter
|
|
|
|
{
|
|
|
|
|
|
|
|
IBlitterFont GetFontType(string fontType);
|
|
|
|
void DrawString(string s, IBlitterFont font, Color color, float x, float y);
|
|
|
|
SizeF MeasureString(string s, IBlitterFont font);
|
|
|
|
Rectangle ClipBounds { get; set; }
|
|
|
|
}
|
|
|
|
|
2014-01-27 06:03:18 +00:00
|
|
|
class UIMessage
|
|
|
|
{
|
|
|
|
public string Message;
|
|
|
|
public DateTime ExpireAt;
|
|
|
|
}
|
|
|
|
|
|
|
|
class UIDisplay
|
|
|
|
{
|
|
|
|
public string Message;
|
|
|
|
public int X;
|
|
|
|
public int Y;
|
|
|
|
public int Anchor;
|
|
|
|
public Color ForeColor;
|
|
|
|
public Color BackGround;
|
|
|
|
}
|
2014-01-27 00:02:21 +00:00
|
|
|
|
|
|
|
public class OSDManager
|
|
|
|
{
|
|
|
|
public string FPS { get; set; }
|
|
|
|
public string MT { get; set; }
|
|
|
|
public IBlitterFont MessageFont;
|
2014-04-27 13:01:10 +00:00
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Begin(IBlitter blitter)
|
|
|
|
{
|
|
|
|
MessageFont = blitter.GetFontType("MessageFont");
|
|
|
|
}
|
|
|
|
|
|
|
|
public System.Drawing.Color FixedMessagesColor { get { return System.Drawing.Color.FromArgb(Global.Config.MessagesColor); } }
|
|
|
|
public System.Drawing.Color FixedAlertMessageColor { get { return System.Drawing.Color.FromArgb(Global.Config.AlertMessageColor); } }
|
|
|
|
|
|
|
|
public OSDManager()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-04-27 13:53:20 +00:00
|
|
|
private float GetX(IBlitter g, int x, int anchor, string message)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
var size = g.MeasureString(message, MessageFont);
|
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
switch (anchor)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case 0: //Top Left
|
|
|
|
case 2: //Bottom Left
|
|
|
|
return x;
|
|
|
|
case 1: //Top Right
|
|
|
|
case 3: //Bottom Right
|
|
|
|
return g.ClipBounds.Width - x - size.Width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-27 13:53:20 +00:00
|
|
|
private float GetY(IBlitter g, int y, int anchor, string message)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
var size = g.MeasureString(message, MessageFont);
|
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
switch (anchor)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case 0: //Top Left
|
|
|
|
case 1: //Top Right
|
|
|
|
return y;
|
|
|
|
case 2: //Bottom Left
|
|
|
|
case 3: //Bottom Right
|
|
|
|
return g.ClipBounds.Height - y - size.Height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private string MakeFrameCounter()
|
|
|
|
{
|
|
|
|
if (Global.MovieSession.Movie.IsFinished)
|
|
|
|
{
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
sb
|
|
|
|
.Append(Global.Emulator.Frame)
|
|
|
|
.Append('/')
|
|
|
|
.Append(Global.MovieSession.Movie.FrameCount)
|
|
|
|
.Append(" (Finished)");
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
2014-04-27 13:53:20 +00:00
|
|
|
|
|
|
|
if (Global.MovieSession.Movie.IsPlaying)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
sb
|
|
|
|
.Append(Global.Emulator.Frame)
|
|
|
|
.Append('/')
|
|
|
|
.Append(Global.MovieSession.Movie.FrameCount);
|
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
2014-04-27 13:53:20 +00:00
|
|
|
|
|
|
|
if (Global.MovieSession.Movie.IsRecording)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
|
|
|
return Global.Emulator.Frame.ToString();
|
|
|
|
}
|
2014-04-27 13:53:20 +00:00
|
|
|
|
|
|
|
return Global.Emulator.Frame.ToString();
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private List<UIMessage> messages = new List<UIMessage>(5);
|
|
|
|
private List<UIDisplay> GUITextList = new List<UIDisplay>();
|
|
|
|
|
|
|
|
public void AddMessage(string message)
|
|
|
|
{
|
|
|
|
GlobalWin.DisplayManager.NeedsToPaint = true;
|
|
|
|
messages.Add(new UIMessage { Message = message, ExpireAt = DateTime.Now + TimeSpan.FromSeconds(2) });
|
|
|
|
}
|
|
|
|
|
2014-04-27 13:01:10 +00:00
|
|
|
public void AddGUIText(string message, int x, int y, Color backGround, Color foreColor, int anchor)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
|
|
|
GlobalWin.DisplayManager.NeedsToPaint = true;
|
2014-04-27 13:01:10 +00:00
|
|
|
GUITextList.Add(new UIDisplay
|
|
|
|
{
|
|
|
|
Message = message,
|
|
|
|
X = x,
|
|
|
|
Y = y,
|
|
|
|
BackGround = backGround,
|
|
|
|
ForeColor = foreColor,
|
|
|
|
Anchor = anchor
|
|
|
|
});
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void ClearGUIText()
|
|
|
|
{
|
|
|
|
GlobalWin.DisplayManager.NeedsToPaint = true;
|
|
|
|
GUITextList.Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void DrawMessages(IBlitter g)
|
|
|
|
{
|
|
|
|
if (!Global.ClientControls["MaxTurbo"])
|
|
|
|
{
|
|
|
|
messages.RemoveAll(m => DateTime.Now > m.ExpireAt);
|
|
|
|
int line = 1;
|
|
|
|
if (Global.Config.StackOSDMessages)
|
|
|
|
{
|
|
|
|
for (int i = messages.Count - 1; i >= 0; i--, line++)
|
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
float x = GetX(g, Global.Config.DispMessagex, Global.Config.DispMessageanchor, messages[i].Message);
|
|
|
|
float y = GetY(g, Global.Config.DispMessagey, Global.Config.DispMessageanchor, messages[i].Message);
|
2014-01-27 00:02:21 +00:00
|
|
|
if (Global.Config.DispMessageanchor < 2)
|
|
|
|
{
|
|
|
|
y += ((line - 1) * 18);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y -= ((line - 1) * 18);
|
|
|
|
}
|
2014-04-27 13:53:20 +00:00
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
g.DrawString(messages[i].Message, MessageFont, Color.Black, x + 2, y + 2);
|
|
|
|
g.DrawString(messages[i].Message, MessageFont, FixedMessagesColor, x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-27 18:45:21 +00:00
|
|
|
if (messages.Any())
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
|
|
|
int i = messages.Count - 1;
|
|
|
|
|
2014-04-27 13:53:20 +00:00
|
|
|
float x = GetX(g, Global.Config.DispMessagex, Global.Config.DispMessageanchor, messages[i].Message);
|
|
|
|
float y = GetY(g, Global.Config.DispMessagey, Global.Config.DispMessageanchor, messages[i].Message);
|
2014-01-27 00:02:21 +00:00
|
|
|
if (Global.Config.DispMessageanchor < 2)
|
|
|
|
{
|
|
|
|
y += ((line - 1) * 18);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y -= ((line - 1) * 18);
|
|
|
|
}
|
2014-04-27 13:01:10 +00:00
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
g.DrawString(messages[i].Message, MessageFont, Color.Black, x + 2, y + 2);
|
|
|
|
g.DrawString(messages[i].Message, MessageFont, FixedMessagesColor, x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-27 18:45:21 +00:00
|
|
|
foreach (var text in GUITextList)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2014-04-27 18:45:21 +00:00
|
|
|
float posx = GetX(g, text.X, text.Anchor, text.Message);
|
|
|
|
float posy = GetY(g, text.Y, text.Anchor, text.Message);
|
2014-01-27 00:02:21 +00:00
|
|
|
|
2014-04-27 18:45:21 +00:00
|
|
|
g.DrawString(text.Message, MessageFont, text.BackGround, posx + 2, posy + 2);
|
|
|
|
g.DrawString(text.Message, MessageFont, text.ForeColor, posx, posy);
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
catch (Exception)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public string MakeInputDisplay()
|
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
StringBuilder sb;
|
2014-01-27 00:02:21 +00:00
|
|
|
if (!Global.MovieSession.Movie.IsActive || Global.MovieSession.Movie.IsFinished)
|
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
sb = new StringBuilder(Global.GetOutputControllersAsMnemonic());
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
sb = new StringBuilder(Global.MovieSession.Movie.GetInput(Global.Emulator.Frame - 1));
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
2014-04-27 13:53:20 +00:00
|
|
|
sb.Replace(".", " ").Replace("|", "").Replace(" 000, 000", " ");
|
2014-01-27 00:02:21 +00:00
|
|
|
|
2014-04-27 13:53:20 +00:00
|
|
|
return sb.ToString();
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public string MakeRerecordCount()
|
|
|
|
{
|
|
|
|
if (Global.MovieSession.Movie.IsActive)
|
|
|
|
{
|
|
|
|
return "Rerecord Count: " + Global.MovieSession.Movie.Header.Rerecords;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-27 13:17:35 +00:00
|
|
|
return string.Empty;
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
}
|
2014-04-27 13:17:35 +00:00
|
|
|
|
|
|
|
private void DrawOsdMessage(IBlitter g, string message, Color color, float x, float y)
|
|
|
|
{
|
|
|
|
g.DrawString(message, MessageFont, Color.Black, x + 1, y + 1);
|
|
|
|
g.DrawString(message, MessageFont, color, x, y);
|
|
|
|
}
|
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Display all screen info objects like fps, frame counter, lag counter, and input display
|
|
|
|
/// </summary>
|
|
|
|
public void DrawScreenInfo(IBlitter g)
|
|
|
|
{
|
|
|
|
if (Global.Config.DisplayFrameCounter)
|
|
|
|
{
|
|
|
|
string message = MakeFrameCounter();
|
2014-04-27 13:53:20 +00:00
|
|
|
float x = GetX(g, Global.Config.DispFrameCx, Global.Config.DispFrameanchor, message);
|
|
|
|
float y = GetY(g, Global.Config.DispFrameCy, Global.Config.DispFrameanchor, message);
|
2014-04-27 13:17:35 +00:00
|
|
|
|
|
|
|
DrawOsdMessage(g, message, Color.FromArgb(Global.Config.MessagesColor), x, y);
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
2014-04-27 13:17:35 +00:00
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
if (Global.Config.DisplayInput)
|
|
|
|
{
|
|
|
|
string input = MakeInputDisplay();
|
|
|
|
Color c;
|
2014-04-27 13:53:20 +00:00
|
|
|
float x = GetX(g, Global.Config.DispInpx, Global.Config.DispInpanchor, input);
|
|
|
|
float y = GetY(g, Global.Config.DispInpy, Global.Config.DispInpanchor, input);
|
2014-01-27 00:02:21 +00:00
|
|
|
if (Global.MovieSession.Movie.IsPlaying && !Global.MovieSession.Movie.IsRecording)
|
|
|
|
{
|
|
|
|
c = Color.FromArgb(Global.Config.MovieInput);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = Color.FromArgb(Global.Config.MessagesColor);
|
|
|
|
}
|
|
|
|
|
2014-04-27 13:17:35 +00:00
|
|
|
// TODO: this needs to be multi-colored and more intelligent: https://code.google.com/p/bizhawk/issues/detail?id=52
|
2014-01-27 00:02:21 +00:00
|
|
|
g.DrawString(input, MessageFont, Color.Black, x + 1, y + 1);
|
|
|
|
g.DrawString(input, MessageFont, c, x, y);
|
|
|
|
}
|
2014-04-27 13:17:35 +00:00
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
if (Global.MovieSession.MultiTrack.IsActive)
|
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
float x = GetX(g, Global.Config.DispMultix, Global.Config.DispMultianchor, MT);
|
|
|
|
float y = GetY(g, Global.Config.DispMultiy, Global.Config.DispMultianchor, MT);
|
2014-04-27 13:17:35 +00:00
|
|
|
|
|
|
|
DrawOsdMessage(g, MT, FixedMessagesColor, x, y);
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
2014-04-27 13:17:35 +00:00
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
if (Global.Config.DisplayFPS && FPS != null)
|
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
float x = GetX(g, Global.Config.DispFPSx, Global.Config.DispFPSanchor, FPS);
|
|
|
|
float y = GetY(g, Global.Config.DispFPSy, Global.Config.DispFPSanchor, FPS);
|
2014-04-27 13:17:35 +00:00
|
|
|
|
|
|
|
DrawOsdMessage(g, FPS, FixedMessagesColor, x, y);
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Global.Config.DisplayLagCounter)
|
|
|
|
{
|
2014-04-27 18:45:21 +00:00
|
|
|
var counter = Global.Emulator.LagCount.ToString();
|
|
|
|
var x = GetX(g, Global.Config.DispLagx, Global.Config.DispLaganchor, counter);
|
|
|
|
var y = GetY(g, Global.Config.DispLagy, Global.Config.DispLaganchor, counter);
|
2014-01-27 00:02:21 +00:00
|
|
|
|
2014-04-27 13:17:35 +00:00
|
|
|
DrawOsdMessage(g, counter, (Global.Emulator.IsLagFrame ? FixedAlertMessageColor : FixedAlertMessageColor), x, y);
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
2014-04-27 13:17:35 +00:00
|
|
|
|
2014-01-27 00:02:21 +00:00
|
|
|
if (Global.Config.DisplayRerecordCount)
|
|
|
|
{
|
|
|
|
string rerec = MakeRerecordCount();
|
2014-04-27 13:53:20 +00:00
|
|
|
float x = GetX(g, Global.Config.DispRecx, Global.Config.DispRecanchor, rerec);
|
|
|
|
float y = GetY(g, Global.Config.DispRecy, Global.Config.DispRecanchor, rerec);
|
2014-04-27 13:17:35 +00:00
|
|
|
|
|
|
|
DrawOsdMessage(g, rerec, FixedMessagesColor, x, y);
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Global.ClientControls["Autohold"] || Global.ClientControls["Autofire"])
|
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
var disp = new StringBuilder("Held: ");
|
2014-01-27 00:02:21 +00:00
|
|
|
|
2014-04-27 13:53:20 +00:00
|
|
|
foreach (string sticky in Global.StickyXORAdapter.CurrentStickies)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
disp.Append(sticky).Append(' ');
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
2014-04-27 13:53:20 +00:00
|
|
|
foreach (string autoSticky in Global.AutofireStickyXORAdapter.CurrentStickies)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
disp
|
|
|
|
.Append("Auto-")
|
|
|
|
.Append(autoSticky)
|
|
|
|
.Append(' ');
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
2014-04-27 13:53:20 +00:00
|
|
|
var message = disp.ToString();
|
|
|
|
|
|
|
|
g.DrawString(
|
|
|
|
message,
|
|
|
|
MessageFont,
|
|
|
|
Color.White,
|
|
|
|
GetX(g, Global.Config.DispAutoholdx, Global.Config.DispAutoholdanchor, message),
|
|
|
|
GetY(g, Global.Config.DispAutoholdy, Global.Config.DispAutoholdanchor, message));
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Global.MovieSession.Movie.IsActive && Global.Config.DisplaySubtitles)
|
|
|
|
{
|
2014-04-27 13:53:20 +00:00
|
|
|
var subList = Global.MovieSession.Movie.Header.Subtitles.GetSubtitles(Global.Emulator.Frame);
|
2014-01-27 00:02:21 +00:00
|
|
|
|
2014-04-27 13:17:35 +00:00
|
|
|
foreach (var sub in subList)
|
2014-01-27 00:02:21 +00:00
|
|
|
{
|
2014-04-27 13:17:35 +00:00
|
|
|
DrawOsdMessage(g, sub.Message, Color.FromArgb((int)sub.Color), sub.X, sub.Y);
|
2014-01-27 00:02:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|