1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-22 12:58:33 +01:00

started working on touch support for MLEM.Ui

This commit is contained in:
Ellpeck 2019-08-30 18:15:50 +02:00
parent 7eeecc19d1
commit 353afdef6f
22 changed files with 517 additions and 30 deletions

View file

@ -102,7 +102,6 @@ namespace MLEM.Ui.Elements {
} }
protected UiControls Controls => this.System.Controls; protected UiControls Controls => this.System.Controls;
protected InputHandler Input => this.Controls.Input; protected InputHandler Input => this.Controls.Input;
public Point MousePos => this.Input.MousePosition;
public RootElement Root { get; internal set; } public RootElement Root { get; internal set; }
public float Scale => this.Root.ActualScale; public float Scale => this.Root.ActualScale;
public Element Parent { get; private set; } public Element Parent { get; private set; }
@ -443,15 +442,15 @@ namespace MLEM.Ui.Elements {
} }
} }
public virtual Element GetMousedElement() { public virtual Element GetElementUnderPos(Point position) {
if (this.IsHidden) if (this.IsHidden)
return null; return null;
for (var i = this.SortedChildren.Count - 1; i >= 0; i--) { for (var i = this.SortedChildren.Count - 1; i >= 0; i--) {
var element = this.SortedChildren[i].GetMousedElement(); var element = this.SortedChildren[i].GetElementUnderPos(position);
if (element != null) if (element != null)
return element; return element;
} }
return this.CanBeMoused && this.Area.Contains(this.MousePos) ? this : null; return this.CanBeMoused && this.Area.Contains(position) ? this : null;
} }
protected virtual void InitStyle(UiStyle style) { protected virtual void InitStyle(UiStyle style) {

View file

@ -117,11 +117,11 @@ namespace MLEM.Ui.Elements {
base.DrawEarly(time, batch, alpha, blendState, samplerState); base.DrawEarly(time, batch, alpha, blendState, samplerState);
} }
public override Element GetMousedElement() { public override Element GetElementUnderPos(Point position) {
// if overflow is handled, don't propagate mouse checks to hidden children // if overflow is handled, don't propagate mouse checks to hidden children
if (this.scrollOverflow && !this.GetRenderTargetArea().Contains(this.MousePos)) if (this.scrollOverflow && !this.GetRenderTargetArea().Contains(position))
return null; return null;
return base.GetMousedElement(); return base.GetElementUnderPos(position);
} }
private Rectangle GetRenderTargetArea() { private Rectangle GetRenderTargetArea() {

View file

@ -56,11 +56,12 @@ namespace MLEM.Ui.Elements {
} }
if (this.isMouseHeld) { if (this.isMouseHeld) {
var mouse = this.Input.MousePosition;
if (this.Horizontal) { if (this.Horizontal) {
var internalX = this.MousePos.X - this.Area.X - this.ScrollerSize.X * this.Scale / 2; var internalX = mouse.X - this.Area.X - this.ScrollerSize.X * this.Scale / 2;
this.CurrentValue = internalX / (this.Area.Width - this.ScrollerSize.X * this.Scale) * this.MaxValue; this.CurrentValue = internalX / (this.Area.Width - this.ScrollerSize.X * this.Scale) * this.MaxValue;
} else { } else {
var internalY = this.MousePos.Y - this.Area.Y - this.ScrollerSize.Y * this.Scale / 2; var internalY = mouse.Y - this.Area.Y - this.ScrollerSize.Y * this.Scale / 2;
this.CurrentValue = internalY / (this.Area.Height - this.ScrollerSize.Y * this.Scale) * this.MaxValue; this.CurrentValue = internalY / (this.Area.Height - this.ScrollerSize.Y * this.Scale) * this.MaxValue;
} }
} }

View file

@ -25,7 +25,7 @@ namespace MLEM.Ui.Elements {
base.Update(time); base.Update(time);
var viewport = this.System.Viewport.Size; var viewport = this.System.Viewport.Size;
var offset = this.MousePos.ToVector2() / this.Scale + this.MouseOffset; var offset = this.Input.MousePosition.ToVector2() / this.Scale + this.MouseOffset;
if (offset.X < 0) if (offset.X < 0)
offset.X = 0; offset.X = 0;
if (offset.Y < 0) if (offset.Y < 0)

View file

@ -2,6 +2,7 @@ using System;
using System.Linq; using System.Linq;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using MLEM.Input; using MLEM.Input;
using MLEM.Ui.Elements; using MLEM.Ui.Elements;
@ -20,14 +21,17 @@ namespace MLEM.Ui {
this.system = system; this.system = system;
this.Input = inputHandler ?? new InputHandler(); this.Input = inputHandler ?? new InputHandler();
this.isInputOurs = inputHandler == null; this.isInputOurs = inputHandler == null;
// enable all required gestures
this.Input.EnableGestures(GestureType.Tap, GestureType.Hold);
} }
public void Update() { public void Update() {
if (this.isInputOurs) if (this.isInputOurs)
this.Input.Update(); this.Input.Update();
var mousedNow = this.GetMousedElement(); // MOUSE INPUT
// mouse new element var mousedNow = this.GetElementUnderPos(this.Input.MousePosition);
if (mousedNow != this.MousedElement) { if (mousedNow != this.MousedElement) {
if (this.MousedElement != null) if (this.MousedElement != null)
this.MousedElement.OnMouseExit?.Invoke(this.MousedElement); this.MousedElement.OnMouseExit?.Invoke(this.MousedElement);
@ -36,21 +40,19 @@ namespace MLEM.Ui {
this.MousedElement = mousedNow; this.MousedElement = mousedNow;
this.system.Propagate(e => e.OnMousedElementChanged?.Invoke(e, mousedNow)); this.system.Propagate(e => e.OnMousedElementChanged?.Invoke(e, mousedNow));
} }
if (this.Input.IsMouseButtonPressed(MouseButton.Left)) { if (this.Input.IsMouseButtonPressed(MouseButton.Left)) {
// select element
var selectedNow = mousedNow != null && mousedNow.CanBeSelected ? mousedNow : null; var selectedNow = mousedNow != null && mousedNow.CanBeSelected ? mousedNow : null;
if (this.SelectedElement != selectedNow) this.SelectElement(selectedNow, true);
this.SelectElement(selectedNow, true);
// first action on element
if (mousedNow != null) if (mousedNow != null)
mousedNow.OnPressed?.Invoke(mousedNow); mousedNow.OnPressed?.Invoke(mousedNow);
} else if (this.Input.IsMouseButtonPressed(MouseButton.Right)) { } else if (this.Input.IsMouseButtonPressed(MouseButton.Right)) {
// secondary action on element
if (mousedNow != null) if (mousedNow != null)
mousedNow.OnSecondaryPressed?.Invoke(mousedNow); mousedNow.OnSecondaryPressed?.Invoke(mousedNow);
} else if (this.Input.IsKeyPressed(Keys.Enter) || this.Input.IsKeyPressed(Keys.Space)) { }
// KEYBOARD INPUT
else if (this.Input.IsKeyPressed(Keys.Enter) || this.Input.IsKeyPressed(Keys.Space)) {
if (this.SelectedElement != null) { if (this.SelectedElement != null) {
if (this.Input.IsModifierKeyDown(ModifierKey.Shift)) { if (this.Input.IsModifierKeyDown(ModifierKey.Shift)) {
// secondary action on element using space or enter // secondary action on element using space or enter
@ -64,9 +66,25 @@ namespace MLEM.Ui {
// tab or shift-tab to next or previous element // tab or shift-tab to next or previous element
this.SelectElement(this.GetNextElement(this.Input.IsModifierKeyDown(ModifierKey.Shift)), false); this.SelectElement(this.GetNextElement(this.Input.IsModifierKeyDown(ModifierKey.Shift)), false);
} }
// TOUCH INPUT
else if (this.Input.GetGesture(GestureType.Tap, out var tap)) {
var tapped = this.GetElementUnderPos(tap.Position.ToPoint());
this.SelectElement(tapped, true);
if (tapped != null)
tapped.OnPressed?.Invoke(tapped);
} else if (this.Input.GetGesture(GestureType.Hold, out var hold)) {
var held = this.GetElementUnderPos(hold.Position.ToPoint());
this.SelectElement(held, true);
if (held != null)
held.OnSecondaryPressed?.Invoke(held);
}
} }
public void SelectElement(Element element, bool mouse) { public void SelectElement(Element element, bool mouse) {
if (this.SelectedElement == element)
return;
if (this.SelectedElement != null) if (this.SelectedElement != null)
this.SelectedElement.OnDeselected?.Invoke(this.SelectedElement); this.SelectedElement.OnDeselected?.Invoke(this.SelectedElement);
if (element != null) if (element != null)
@ -76,9 +94,9 @@ namespace MLEM.Ui {
this.system.Propagate(e => e.OnSelectedElementChanged?.Invoke(e, element)); this.system.Propagate(e => e.OnSelectedElementChanged?.Invoke(e, element));
} }
public Element GetMousedElement() { public Element GetElementUnderPos(Point position) {
foreach (var root in this.system.GetRootElements()) { foreach (var root in this.system.GetRootElements()) {
var moused = root.Element.GetMousedElement(); var moused = root.Element.GetElementUnderPos(position);
if (moused != null) if (moused != null)
return moused; return moused;
} }

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using MLEM.Extensions; using MLEM.Extensions;
using MLEM.Font; using MLEM.Font;
using MLEM.Input; using MLEM.Input;
@ -48,7 +49,7 @@ namespace MLEM.Ui {
public SamplerState SamplerState = SamplerState.PointClamp; public SamplerState SamplerState = SamplerState.PointClamp;
public UiControls Controls; public UiControls Controls;
public readonly bool SupportsTextInput; public readonly bool SupportsTextInput;
public UiSystem(GameWindow window, GraphicsDevice device, UiStyle style, InputHandler inputHandler = null) { public UiSystem(GameWindow window, GraphicsDevice device, UiStyle style, InputHandler inputHandler = null) {
this.Controls = new UiControls(this, inputHandler); this.Controls = new UiControls(this, inputHandler);
this.GraphicsDevice = device; this.GraphicsDevice = device;
@ -61,11 +62,12 @@ namespace MLEM.Ui {
foreach (var root in this.rootElements) foreach (var root in this.rootElements)
root.Element.ForceUpdateArea(); root.Element.ForceUpdateArea();
}; };
try { try {
window.TextInput += (sender, args) => { NativeTextInput.AddToTextInput(window, (key, character) => {
foreach (var root in this.rootElements) foreach (var root in this.rootElements)
root.Element.Propagate(e => e.OnTextInput?.Invoke(e, args.Key, args.Character)); root.Element.Propagate(e => e.OnTextInput?.Invoke(e, key, character));
}; });
this.SupportsTextInput = true; this.SupportsTextInput = true;
} catch (TypeLoadException) { } catch (TypeLoadException) {
this.SupportsTextInput = false; this.SupportsTextInput = false;
@ -144,6 +146,14 @@ namespace MLEM.Ui {
root.Element.Propagate(action); root.Element.Propagate(action);
} }
private static class NativeTextInput {
internal static void AddToTextInput(GameWindow window, Action<Keys, char> func) {
window.TextInput += (sender, args) => func(args.Key, args.Character);
}
}
} }
public class RootElement { public class RootElement {

View file

@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demos", "Demos\Demos.csproj
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Ui", "MLEM.Ui\MLEM.Ui.csproj", "{6F00629A-8B87-4264-8896-19983285E32F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MLEM.Ui", "MLEM.Ui\MLEM.Ui.csproj", "{6F00629A-8B87-4264-8896-19983285E32F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidTests", "Test\AndroidTests.csproj", "{410C0262-131C-4D0E-910D-D01B4F7143E0}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -36,5 +38,9 @@ Global
{6F00629A-8B87-4264-8896-19983285E32F}.Debug|Any CPU.Build.0 = Debug|Any CPU {6F00629A-8B87-4264-8896-19983285E32F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F00629A-8B87-4264-8896-19983285E32F}.Release|Any CPU.ActiveCfg = Release|Any CPU {6F00629A-8B87-4264-8896-19983285E32F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F00629A-8B87-4264-8896-19983285E32F}.Release|Any CPU.Build.0 = Release|Any CPU {6F00629A-8B87-4264-8896-19983285E32F}.Release|Any CPU.Build.0 = Release|Any CPU
{410C0262-131C-4D0E-910D-D01B4F7143E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{410C0262-131C-4D0E-910D-D01B4F7143E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{410C0262-131C-4D0E-910D-D01B4F7143E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{410C0262-131C-4D0E-910D-D01B4F7143E0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View file

@ -176,12 +176,19 @@ namespace MLEM.Input {
return this.WasGamepadButtonUp(button, index) && this.IsGamepadButtonDown(button, index); return this.WasGamepadButtonUp(button, index) && this.IsGamepadButtonDown(button, index);
} }
public GestureSample GetGesture(GestureType type) { public void EnableGestures(params GestureType[] gestures) {
foreach (var gesture in gestures)
TouchPanel.EnabledGestures |= gesture;
}
public bool GetGesture(GestureType type, out GestureSample sample) {
foreach (var gesture in this.Gestures) { foreach (var gesture in this.Gestures) {
if (gesture.GestureType == type) if (gesture.GestureType == type) {
return gesture; sample = gesture;
return true;
}
} }
return default; return false;
} }
public bool IsDown(object control, int index = -1) { public bool IsDown(object control, int index = -1) {

25
Test/Activity1.cs Normal file
View file

@ -0,0 +1,25 @@
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Views;
namespace AndroidTests {
[Activity(Label = "AndroidTests"
, MainLauncher = true
, Icon = "@drawable/icon"
, Theme = "@style/Theme.Splash"
, AlwaysRetainTaskState = true
, LaunchMode = LaunchMode.SingleInstance
, ScreenOrientation = ScreenOrientation.UserLandscape
, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize)]
public class Activity1 : Microsoft.Xna.Framework.AndroidGameActivity {
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
var g = new GameImpl();
this.SetContentView((View) g.Services.GetService(typeof(View)));
g.Run();
}
}
}

114
Test/AndroidTests.csproj Normal file
View file

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{410C0262-131C-4D0E-910D-D01B4F7143E0}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AndroidTests</RootNamespace>
<AssemblyName>AndroidTests</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidApplication>true</AndroidApplication>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidSupportedAbis>armeabi-v7a;x86</AndroidSupportedAbis>
<AndroidStoreUncompressedFileExtensions>.m4a</AndroidStoreUncompressedFileExtensions>
<MandroidI18n />
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
<MonoGamePlatform>Android</MonoGamePlatform>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
<DefineConstants>DEBUG;TRACE;ANDROID</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
<DefineConstants>TRACE;ANDROID</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
</PropertyGroup>
<ItemGroup>
<Reference Include="Coroutine, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\packages\Coroutine.1.0.1\lib\netstandard2.0\Coroutine.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Android" />
<Reference Include="MonoGame.Extended, Version=3.7.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\packages\MonoGame.Extended.3.7.0\lib\netstandard2.0\MonoGame.Extended.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\netstandard2.0\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
<Reference Include="MonoGame.Framework">
<HintPath>$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\Android\MonoGame.Framework.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Activity1.cs" />
<Compile Include="GameImpl.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\Values\Strings.xml" />
<AndroidResource Include="Resources\Drawable\Icon.png" />
<AndroidResource Include="Resources\Drawable\Splash.png" />
<AndroidResource Include="Resources\Values\Styles.xml" />
</ItemGroup>
<ItemGroup>
<MonoGameContentReference Include="Content\Content.mgcb" />
<None Include="Properties\AndroidManifest.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MLEM.Extended\MLEM.Extended.csproj">
<Project>{232a6513-a28c-4d7f-ba5a-89281bfc1538}</Project>
<Name>MLEM.Extended</Name>
</ProjectReference>
<ProjectReference Include="..\MLEM.Startup\MLEM.Startup.csproj">
<Project>{997f4739-7bec-4621-b9ca-68deb2d74412}</Project>
<Name>MLEM.Startup</Name>
</ProjectReference>
<ProjectReference Include="..\MLEM.Ui\MLEM.Ui.csproj">
<Project>{6f00629a-8b87-4264-8896-19983285e32f}</Project>
<Name>MLEM.Ui</Name>
</ProjectReference>
<ProjectReference Include="..\MLEM\MLEM.csproj">
<Project>{1d6ab762-43c4-4775-8924-707c7ec3f142}</Project>
<Name>MLEM</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Content\Fonts\TestFont.spritefont" />
<Content Include="Content\Textures\Test.png" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
</Project>

34
Test/Content/Content.mgcb Normal file
View file

@ -0,0 +1,34 @@
#----------------------------- Global Properties ----------------------------#
/outputDir:bin/$(Platform)
/intermediateDir:obj/$(Platform)
/platform:Android
/config:
/profile:Reach
/compress:False
#-------------------------------- References --------------------------------#
#---------------------------------- Content ---------------------------------#
#begin Textures/Test.png
/importer:TextureImporter
/processor:TextureProcessor
/processorParam:ColorKeyColor=255,0,255,255
/processorParam:ColorKeyEnabled=True
/processorParam:GenerateMipmaps=False
/processorParam:PremultiplyAlpha=True
/processorParam:ResizeToPowerOfTwo=False
/processorParam:MakeSquare=False
/processorParam:TextureFormat=Color
/build:Textures/Test.png
#begin Fonts/TestFont.spritefont
/importer:FontDescriptionImporter
/processor:FontDescriptionProcessor
/processorParam:PremultiplyAlpha=True
/processorParam:TextureFormat=Compressed
/build:Fonts/TestFont.spritefont

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains an xml description of a font, and will be read by the XNA
Framework Content Pipeline. Follow the comments to customize the appearance
of the font in your game, and to change the characters which are available to draw
with.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">
<!--
Modify this string to change the font that will be imported.
-->
<FontName>Arial</FontName>
<!--
Size is a float value, measured in points. Modify this value to change
the size of the font.
-->
<Size>32</Size>
<!--
Spacing is a float value, measured in pixels. Modify this value to change
the amount of spacing in between characters.
-->
<Spacing>0</Spacing>
<!--
UseKerning controls the layout of the font. If this value is true, kerning information
will be used when placing characters.
-->
<UseKerning>true</UseKerning>
<!--
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
and "Bold, Italic", and are case sensitive.
-->
<Style>Regular</Style>
<!--
If you uncomment this line, the default character will be substituted if you draw
or measure text that contains characters which were not included in the font.
-->
<DefaultCharacter>*</DefaultCharacter>
<!--
CharacterRegions control what letters are available in the font. Every
character from Start to End will be built and made available for drawing. The
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
character set. The characters are ordered according to the Unicode standard.
See the documentation for more information.
-->
<CharacterRegions>
<CharacterRegion>
<Start>&#32;</Start>
<End>&#591;</End>
</CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 B

50
Test/GameImpl.cs Normal file
View file

@ -0,0 +1,50 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Font;
using MLEM.Startup;
using MLEM.Textures;
using MLEM.Ui;
using MLEM.Ui.Elements;
using MLEM.Ui.Style;
namespace AndroidTests {
public class GameImpl : MlemGame {
protected override void LoadContent() {
base.LoadContent();
var tex = LoadContent<Texture2D>("Textures/Test");
var style = new UntexturedStyle(this.SpriteBatch) {
Font = new GenericSpriteFont(LoadContent<SpriteFont>("Fonts/TestFont")),
TextScale = 0.1F,
PanelTexture = new NinePatch(new TextureRegion(tex, 0, 8, 24, 24), 8),
ButtonTexture = new NinePatch(new TextureRegion(tex, 24, 8, 16, 16), 4),
TextFieldTexture = new NinePatch(new TextureRegion(tex, 24, 8, 16, 16), 4),
ScrollBarBackground = new NinePatch(new TextureRegion(tex, 12, 0, 4, 8), 1, 1, 2, 2),
ScrollBarScrollerTexture = new NinePatch(new TextureRegion(tex, 8, 0, 4, 8), 1, 1, 2, 2),
CheckboxTexture = new NinePatch(new TextureRegion(tex, 24, 8, 16, 16), 4),
CheckboxCheckmark = new TextureRegion(tex, 24, 0, 8, 8),
RadioTexture = new NinePatch(new TextureRegion(tex, 16, 0, 8, 8), 3),
RadioCheckmark = new TextureRegion(tex, 32, 0, 8, 8)
};
this.UiSystem.Style = style;
this.UiSystem.GlobalScale = 10;
this.UiSystem.AutoScaleWithScreen = true;
var panel = new Panel(Anchor.Center, new Vector2(100, 0), Vector2.Zero, true);
this.UiSystem.Add("Panel", panel);
panel.AddChild(new Paragraph(Anchor.AutoLeft, 1, "I am Android"));
var image = new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(tex, 0, 0, 8, 8)) {IsHidden = true};
panel.AddChild(image);
panel.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.5F, 10), "Toggle Image") {
OnPressed = element => image.IsHidden = !image.IsHidden
});
}
protected override void DoDraw(GameTime gameTime) {
this.GraphicsDevice.Clear(Color.CornflowerBlue);
base.DoDraw(gameTime);
}
}
}

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="AndroidTests" android:versionCode="1" android:versionName="1.0">
<uses-sdk />
<application android:label="AndroidTests"></application>
</manifest>

View file

@ -0,0 +1,41 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AndroidTests")]
[assembly: AssemblyProduct("AndroidTests")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6f377592-2266-4c47-855e-6260ff75e1f4")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Add some common permissions, these can be removed if not needed
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

99
Test/Resources/Resource.Designer.cs generated Normal file
View file

@ -0,0 +1,99 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
[assembly: global::Android.Runtime.ResourceDesignerAttribute("AndroidTests.Resource", IsApplication=true)]
namespace AndroidTests
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
public partial class Resource
{
static Resource()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
public static void UpdateIdValues()
{
}
public partial class Attribute
{
static Attribute()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Attribute()
{
}
}
public partial class Drawable
{
// aapt resource value: 0x7f020000
public const int Icon = 2130837504;
// aapt resource value: 0x7f020001
public const int Splash = 2130837505;
static Drawable()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Drawable()
{
}
}
public partial class String
{
// aapt resource value: 0x7f030001
public const int ApplicationName = 2130903041;
// aapt resource value: 0x7f030000
public const int Hello = 2130903040;
static String()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private String()
{
}
}
public partial class Style
{
// aapt resource value: 0x7f040000
public const int Theme_Splash = 2130968576;
static Style()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Style()
{
}
}
}
}
#pragma warning restore 1591

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="Hello">Hello World, Click Me!</string>
<string name="ApplicationName">AndroidTests</string>
</resources>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Splash" parent="android:Theme">
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>

6
Test/packages.config Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Coroutine" version="1.0.1" targetFramework="monoandroid90" />
<package id="MonoGame.Extended" version="3.7.0" targetFramework="monoandroid90" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="monoandroid90" />
</packages>