public MainGuiElement(Window window) { _window = window; // Setup static mesh if needed, note that it's in screen-space coordinates as no transformation is applied _glMesh = _glMesh ?? new GLMesh( new[] { new Vector3(-1, -1, 0), new Vector3(1, -1, 0), new Vector3(1, 1, 0), new Vector3(-1, 1, 0) }, new uint[] { 0, 1, 3, 1, 2, 3 }); // Setup static shader if needed. Normally this would be managed by a material, but this is a one-off exception if (_guiShader == null) { _guiShader = new GLGuiShader(); _guiShader.GpuAllocateDeferred(); } // Setup defaults Width = new SFixed(window.NativeWindow.Width); Height = new SFixed(window.NativeWindow.Height); ChildAlignment = ChildAlignments.Row; // GL Deynamic Texture // Re-upload texutre to GPU _glTexture = new GLDynamicTexture(GLTextureParams.Default, _window.UnscaledSize.Width, _window.UnscaledSize.Height); _glTexture.GpuAllocateDeferred(); // Register NativeWindow events window.NativeWindow.KeyDown += (sender, args) => FocusedElement?.OnKeyDown(args); window.NativeWindow.KeyUp += (sender, args) => FocusedElement?.OnKeyUp(args); window.NativeWindow.Resize += (sender, args) => _glTexture.Resize(_window.UnscaledSize.Width, _window.UnscaledSize.Height); window.NativeWindow.MouseDown += (sender, args) => { var clickedElement = GetTopmostElementAtPoint(args.Position); if (clickedElement == FocusedElement) { return; } // De-Focus last focused element FocusedElement?.OnLostFocus(); // Focus the new one FocusedElement = clickedElement; FocusedElement.OnFocus(); }; window.NativeWindow.MouseUp += (sender, args) => { var clickedElement = GetTopmostElementAtPoint(args.Position); // If the mouse is still within the control's bounds fire click event if (clickedElement == FocusedElement) { FocusedElement?.OnClicked(args); } // TODO: Fire the drag release event here clickedElement?.OnMouseUp(args); }; window.NativeWindow.MouseMove += (sender, args) => { var mouseOverElement = GetTopmostElementAtPoint(args.Position); if (mouseOverElement != _lastMouseOver) { _lastMouseOver?.OnMouseLeave(); } _lastMouseOver = mouseOverElement; mouseOverElement?.OnMouseEnter(); }; window.NativeWindow.MouseWheel += (sender, args) => FocusedElement?.OnMouseWheel(args); window.NativeWindow.FocusedChanged += (sender, args) => { if (window.NativeWindow.Focused) { // Reforcused FocusedElement?.OnFocus(); } else { // Unfocused FocusedElement?.OnLostFocus(); _lastMouseOver?.OnMouseLeave(); } }; }
private void LoadCharacterSet(string characters) { using (var graphics = Graphics.FromImage(AtlasTexture.Bitmap)) { graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.SmoothingMode = SmoothingMode.HighQuality; // DEBUG using (Brush aGradientBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, 1024), Color.Blue, Color.Green)) { graphics.FillRectangle(aGradientBrush, 0, 0, 1024, 1024); } foreach (var character in characters) { var glyphIndex = _face.GetCharIndex(character); _face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); _face.Glyph.RenderGlyph(RenderMode.Normal); // Get all Kerning pairs Dictionary <char, float> kerningPairs = null; if (_face.HasKerning) { kerningPairs = new Dictionary <char, float>(); // Load all kerning pairs foreach (var otherCharacter in characters) { var kerning = (float)_face.GetKerning(glyphIndex, _face.GetCharIndex(otherCharacter), KerningMode.Default).X; kerningPairs.Add(otherCharacter, kerning); } } // Draw the image, if there is one (might not be, for example 'space') var ftbmp = _face.Glyph.Bitmap; if (ftbmp.Width > 0 && ftbmp.Rows > 0) { // Draw the Glyph to the atlas Bitmap var cBmp = ftbmp.ToGdipBitmap(Color.Red); var drawLocation = BoxPacker.TryPackingBox(cBmp.Size); if (!drawLocation.HasValue) { throw new Exception("Failed to pack chacter"); } // Draw using the bottom left as (0, 0) not the top left. var flippedDrawLocation = new Point(drawLocation.Value.X, AtlasSize - drawLocation.Value.Y - cBmp.Height); graphics.DrawImageUnscaled(cBmp, flippedDrawLocation); // Some quick helper to keep Position and UV stuff a little cleaner. var positionLowerLeft = new Vector3(_face.Glyph.BitmapLeft, -(cBmp.Height - _face.Glyph.BitmapTop), 0); var uvLowerLeft = new Vector2(drawLocation.Value.X / (float)AtlasSize, drawLocation.Value.Y / (float)AtlasSize); var uvSize = new Vector2(cBmp.Width / (float)AtlasSize, cBmp.Height / (float)AtlasSize); _characterMetrics.Add(character, new CharacterMetric { IsDrawn = true, PositionOffsets = new[] { positionLowerLeft, positionLowerLeft + new Vector3(cBmp.Width, cBmp.Height, 0), positionLowerLeft + new Vector3(0, cBmp.Height, 0), positionLowerLeft + new Vector3(cBmp.Width, 0, 0) }, UV0 = new[] { uvLowerLeft, uvLowerLeft + uvSize, new Vector2(uvLowerLeft.X, uvLowerLeft.Y + uvSize.Y), new Vector2(uvLowerLeft.X + uvSize.X, uvLowerLeft.Y) }, Size = cBmp.Size, Bearing = new Point(_face.Glyph.BitmapLeft, _face.Glyph.BitmapTop), Advance = (int)_face.Glyph.Advance.X, KerningPairs = kerningPairs }); } else { _characterMetrics.Add(character, new CharacterMetric { IsDrawn = false, Advance = (int)_face.Glyph.Advance.X, KerningPairs = kerningPairs }); } } } // Update GPU texture if (AtlasTexture != null) { return; } AtlasTexture = new GLDynamicTexture(GLTextureParams.Default, AtlasSize, AtlasSize); AtlasTexture.GpuAllocateDeferred(); }