I fixed and broke stuff at the same time!

This commit is contained in:
Michael 2017-07-03 15:41:35 -04:00
parent 659ccfb29d
commit 15b3b356b0
4 changed files with 163 additions and 73 deletions

View file

@ -10,6 +10,7 @@ using ShiftOS.Frontend.GraphicsSubsystem;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using Microsoft.Xna.Framework;
using System.Runtime.InteropServices;
namespace ShiftOS.Frontend.GUI
{
@ -36,6 +37,48 @@ namespace ShiftOS.Frontend.GUI
private int _mouseX = 0;
private int _mouseY = 0;
private bool _captureMouse = false;
public bool RequiresPaint
{
get
{
bool requires_child_repaint = false;
foreach (var child in _children)
{
requires_child_repaint = child.RequiresPaint;
if (requires_child_repaint)
break;
}
return _invalidated || requires_child_repaint;
}
}
public Image TextureCache
{
get
{
return _texCache;
}
}
public byte[] PaintCache
{
get
{
var data = _texCache.LockBits(new System.Drawing.Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
var rgb = new byte[Math.Abs(data.Stride) * data.Height];
Marshal.Copy(data.Scan0, rgb, 0, rgb.Length);
for(int i = 0; i < rgb.Length; i += 4)
{
byte r = rgb[i];
byte b = rgb[i + 2];
rgb[i] = b;
rgb[i + 2] = r;
}
_texCache.UnlockBits(data);
return rgb;
}
}
public bool CaptureMouse
{
@ -74,6 +117,9 @@ namespace ShiftOS.Frontend.GUI
}
set
{
if (_anchor == value)
return;
_anchor = value;
Invalidate();
}
@ -96,6 +142,8 @@ namespace ShiftOS.Frontend.GUI
}
set
{
if (_opacity == value)
return;
_opacity = value;
Invalidate();
}
@ -164,6 +212,9 @@ namespace ShiftOS.Frontend.GUI
}
set
{
if (_visible == value)
return;
_visible = value;
Invalidate();
}
@ -213,6 +264,8 @@ namespace ShiftOS.Frontend.GUI
}
set
{
if (_x == value)
return;
_x = value;
Invalidate();
}
@ -226,6 +279,8 @@ namespace ShiftOS.Frontend.GUI
}
set
{
if (_y == value)
return;
_y = value;
Invalidate();
}
@ -239,6 +294,8 @@ namespace ShiftOS.Frontend.GUI
}
set
{
if (_w == value)
return;
_w = value;
Invalidate();
}
@ -252,6 +309,8 @@ namespace ShiftOS.Frontend.GUI
}
set
{
if (_h == value)
return;
_h = value;
Invalidate();
}
@ -329,7 +388,6 @@ namespace ShiftOS.Frontend.GUI
}
_invalidated = false;
}
gfx.DrawImage(_texCache, 0, 0);
foreach (var child in _children)
{
if (child.Visible)
@ -339,6 +397,10 @@ namespace ShiftOS.Frontend.GUI
var cBmp = new Bitmap(child.Width, child.Height);
child.Paint(System.Drawing.Graphics.FromImage(cBmp));
cBmp.SetOpacity((float)child.Opacity);
using(var cGfx = Graphics.FromImage(_texCache))
{
cGfx.DrawImage(child.TextureCache, child.X, child.Y);
}
child._invalidated = false;
child._texCache = cBmp;
gfx.DrawImage(cBmp, new System.Drawing.Point(child.X, child.Y));
@ -352,7 +414,7 @@ namespace ShiftOS.Frontend.GUI
}
}
}
gfx.DrawImage(_texCache, 0, 0);
}
}

View file

@ -25,6 +25,21 @@ namespace ShiftOS.Frontend.GUI
_index--;
}
if(e.Key == Microsoft.Xna.Framework.Input.Keys.Back)
{
if(_index > 0)
{
_text = _text.Remove(_index - 1, 1);
_index--;
}
}
if(e.Key == Microsoft.Xna.Framework.Input.Keys.Delete)
{
if(_index < _text.Length - 1)
{
_text = _text.Remove(_index, 1);
}
}
if (e.Key == Microsoft.Xna.Framework.Input.Keys.Right)
if (_index < _text.Length)
_index++;
@ -36,52 +51,47 @@ namespace ShiftOS.Frontend.GUI
Invalidate();
base.OnKeyEvent(e);
}
private int textInputOffset = 0;
private int maxCanFit = 5;
string visibleText = "";
float caretPos = 2f;
protected void CalculateVisibleText()
{
visibleText = "";
caretPos = -1f;
using (var gfx = Graphics.FromImage(new Bitmap(1, 1)))
using(var gfx = Graphics.FromImage(new Bitmap(1, 1)))
{
for (int i = textInputOffset; i < _text.Length; i++)
string toCaret = _text.Substring(0, _index);
var measure = gfx.MeasureString(toCaret, _font);
caretPos = 2 + measure.Width;
while(caretPos - _textDrawOffset < 0)
{
visibleText += _text[i];
var measure = gfx.MeasureString(visibleText, _font);
if (measure.Width > Width)
{
maxCanFit = visibleText.Length;
if(_index < textInputOffset)
{
textInputOffset = MathHelper.Clamp(_index - (maxCanFit / 2), 0, _text.Length - 1);
}
if(_index > textInputOffset + maxCanFit)
{
textInputOffset = MathHelper.Clamp(_index + (maxCanFit / 2), 0, _text.Length - 1) - maxCanFit;
}
break;
}
Height = (int)measure.Height + 4;
_textDrawOffset -= 0.01f;
}
while(caretPos - _textDrawOffset > Width)
{
_textDrawOffset += 0.01f;
}
}
}
private float _textDrawOffset = 0;
protected override void OnPaint(Graphics gfx)
{
gfx.Clear(LoadedSkin.ControlColor);
gfx.DrawString(visibleText, _font, new SolidBrush(LoadedSkin.ControlTextColor), 2, 2);
gfx.DrawString(_text, _font, new SolidBrush(LoadedSkin.ControlTextColor), 2 - _textDrawOffset, 2);
if (IsFocusedControl)
{
//Draw caret.
gfx.FillRectangle(new SolidBrush(LoadedSkin.ControlTextColor), new RectangleF(caretPos, 2, 2, Height - 4));
gfx.FillRectangle(new SolidBrush(LoadedSkin.ControlTextColor), new RectangleF(caretPos - _textDrawOffset, 2, 2, Height - 4));
}
gfx.DrawRectangle(new Pen(new SolidBrush(LoadedSkin.ControlTextColor), 1), new Rectangle(0, 0, Width - 1, Height - 1));
else
{
if (string.IsNullOrEmpty(_text))
{
gfx.DrawString(_label, _font, Brushes.Gray, 2, 2);
}
}
gfx.DrawRectangle(new Pen(new SolidBrush(LoadedSkin.ControlTextColor), 1), new System.Drawing.Rectangle(0, 0, Width - 1, Height - 1));
}

View file

@ -21,7 +21,7 @@ namespace ShiftOS.Frontend.GraphicsSubsystem
public static void LayoutUpdate()
{
foreach (var toplevel in topLevels)
foreach (var toplevel in topLevels.ToArray())
toplevel.Layout();
}
@ -40,32 +40,26 @@ namespace ShiftOS.Frontend.GraphicsSubsystem
t.Start();
}
public static Dictionary<int, Texture2D> TextureCaches = new Dictionary<int, Texture2D>();
public static void DrawControls(GraphicsDevice graphics, SpriteBatch batch)
{
foreach (var ctrl in topLevels.ToArray())
{
using(var bmp = new System.Drawing.Bitmap(ctrl.Width, ctrl.Height))
int hc = ctrl.GetHashCode();
if (ctrl.RequiresPaint)
{
var gfx = System.Drawing.Graphics.FromImage(bmp);
ctrl.Paint(gfx);
bmp.SetOpacity((float)ctrl.Opacity);
//get the bits of the bitmap
var data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
byte[] rgb = new byte[Math.Abs(data.Stride) * data.Height];
Marshal.Copy(data.Scan0, rgb, 0, rgb.Length);
bmp.UnlockBits(data);
for(int i = 0; i < rgb.Length; i+=4)
var bmp = new System.Drawing.Bitmap(ctrl.Width, ctrl.Height);
ctrl.Paint(System.Drawing.Graphics.FromImage(bmp));
if (TextureCaches.ContainsKey(hc))
{
byte r = rgb[i];
byte b = rgb[i + 2];
rgb[i] = b;
rgb[i + 2] = r;
TextureCaches[hc].Dispose();
TextureCaches.Remove(hc);
}
var tex2 = new Texture2D(graphics, bmp.Width, bmp.Height);
tex2.SetData<byte>(rgb);
batch.Draw(tex2, new Rectangle(ctrl.X, ctrl.Y, ctrl.Width, ctrl.Height), Color.White);
TextureCaches.Add(hc, new Texture2D(graphics, ctrl.Width, ctrl.Height));
TextureCaches[hc].SetData<byte>(ctrl.PaintCache);
}
batch.Draw(TextureCaches[hc], new Rectangle(ctrl.X, ctrl.Y, ctrl.Width, ctrl.Height), Color.White);
}
}
@ -139,7 +133,7 @@ namespace ShiftOS.Frontend.GraphicsSubsystem
{
public static char ToCharacter(this Keys key, bool shift)
{
char c = ' ';
char c = '\0';
switch (key)
{
case Keys.Space:

View file

@ -40,6 +40,8 @@ namespace ShiftOS.Frontend
}
private GUI.TextControl _titleLabel = null;
private Keys lastKey = Keys.None;
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
@ -123,10 +125,16 @@ Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime type
textinput.Y = 0;
UIManager.AddTopLevel(textinput);
framerate.Width = GraphicsDevice.PreferredBackBufferWidth;
framerate.Height = GraphicsDevice.PreferredBackBufferHeight;
framerate.TextAlign = GUI.TextAlign.BottomRight;
base.Initialize();
}
private Texture2D MouseTexture = null;
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
@ -137,6 +145,14 @@ Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime type
this.spriteBatch = new SpriteBatch(base.GraphicsDevice);
// TODO: use this.Content to load your game content here
var bmp = Properties.Resources.cursor_9x_pointer;
var _lock = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
byte[] rgb = new byte[Math.Abs(_lock.Stride) * _lock.Height];
Marshal.Copy(_lock.Scan0, rgb, 0, rgb.Length);
bmp.UnlockBits(_lock);
MouseTexture = new Texture2D(GraphicsDevice.GraphicsDevice, bmp.Width, bmp.Height);
MouseTexture.SetData<byte>(rgb);
rgb = null;
}
/// <summary>
@ -145,9 +161,11 @@ Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime type
/// </summary>
protected override void UnloadContent()
{
MouseTexture = null;
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
@ -158,14 +176,14 @@ Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime type
//Let's get the mouse state
var mouseState = Mouse.GetState(this.Window);
//Now let's process it.
UIManager.ProcessMouseState(mouseState);
//Now let's process it.
UIManager.ProcessMouseState(mouseState);
//Cause layout update on all elements
UIManager.LayoutUpdate();
//set framerate
framerate.Text = "ShiftOS 1.0 Beta 4\r\nCopyright (c) 2017 ShiftOS\r\nFPS: " + (1 / gameTime.ElapsedGameTime.TotalSeconds);
framerate.Text = "ShiftOS 1.0 Beta 4\r\nCopyright (c) 2017 ShiftOS\r\nFPS: " + (1000 / gameTime.ElapsedGameTime.TotalMilliseconds);
//So we have mouse input, and the UI layout system working...
@ -180,22 +198,34 @@ Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime type
var keys = keystate.GetPressedKeys();
if (keys.Length > 0)
{
//Of course, we need modifier keys...
//First for Control.
bool controlDown = keys.Contains(Keys.LeftControl) || keys.Contains(Keys.RightControl);
//Now SHIFT.
bool shiftDown = keys.Contains(Keys.LeftShift) || keys.Contains(Keys.RightShift);
//And ALT.
bool altDown = keys.Contains(Keys.LeftAlt) || keys.Contains(Keys.RightAlt);
foreach(var key in keys)
var key = keys.FirstOrDefault(x => x != Keys.LeftControl && x != Keys.RightControl && x != Keys.LeftShift && x != Keys.RightShift && x != Keys.LeftAlt && x != Keys.RightAlt);
if (lastKey != key)
{
//This'll make it so we skip the modifier keys.
if(key != Keys.LeftAlt && key != Keys.RightAlt && key != Keys.LeftControl && key != Keys.RightControl && key != Keys.LeftShift && key != Keys.RightShift)
lastKey = key;
//Of course, we need modifier keys...
//First for Control.
bool controlDown = keys.Contains(Keys.LeftControl) || keys.Contains(Keys.RightControl);
//Now SHIFT.
bool shiftDown = keys.Contains(Keys.LeftShift) || keys.Contains(Keys.RightShift);
//And ALT.
bool altDown = keys.Contains(Keys.LeftAlt) || keys.Contains(Keys.RightAlt);
var keyevent = new KeyEvent(controlDown, altDown, shiftDown, key);
var t = new System.Threading.Thread(() =>
{
var keyevent = new KeyEvent(controlDown, altDown, shiftDown, key);
UIManager.ProcessKeyEvent(keyevent);
}
lastKey = Keys.None;
System.Threading.Thread.Sleep(1000);
if(lastKey == keyevent.Key)
while (Keyboard.GetState().IsKeyDown(keyevent.Key))
{
UIManager.ProcessKeyEvent(keyevent);
System.Threading.Thread.Sleep(75);
}
lastKey = Keys.None;
});
t.Start();
}
}
@ -221,15 +251,9 @@ Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime type
//Draw a mouse cursor
var bmp = Properties.Resources.cursor_9x_pointer;
var data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
byte[] rgb = new byte[Math.Abs(data.Stride) * data.Height];
Marshal.Copy(data.Scan0, rgb, 0, rgb.Length);
bmp.UnlockBits(data);
var mousepos = Mouse.GetState(this.Window).Position;
var tex2 = new Texture2D(graphics, bmp.Width, bmp.Height);
tex2.SetData<byte>(rgb);
spriteBatch.Draw(tex2, new Rectangle(mousepos.X, mousepos.Y, bmp.Width, bmp.Height), Color.White);
spriteBatch.Draw(MouseTexture, new Rectangle(mousepos.X, mousepos.Y, MouseTexture.Width, MouseTexture.Height), Color.White);