mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 22:18:34 +01:00
Compare commits
6 commits
73a02dfe19
...
c5f4fd27bd
Author | SHA1 | Date | |
---|---|---|---|
c5f4fd27bd | |||
44388c0ebd | |||
cdc4756a6a | |||
3fc42143d5 | |||
c4bd03ff04 | |||
a6a34c3937 |
10 changed files with 167 additions and 66 deletions
24
.github/workflows/main.yml
vendored
24
.github/workflows/main.yml
vendored
|
@ -20,32 +20,10 @@ jobs:
|
|||
uses: android-actions/setup-android@v3
|
||||
- name: Restore tools
|
||||
run: dotnet tool restore
|
||||
- name: Run cake
|
||||
- name: Run Publish
|
||||
uses: coactions/setup-xvfb@v1
|
||||
with:
|
||||
run: dotnet cake --target Publish --ref ${{ github.ref }} --buildNum ${{ github.run_number }}
|
||||
env:
|
||||
NUGET_KEY: ${{ secrets.NUGET_KEY }}
|
||||
BAGET_KEY: ${{ secrets.BAGET_KEY }}
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
- name: Restore tools
|
||||
run: dotnet tool restore
|
||||
- name: Run cake
|
||||
run: dotnet cake --target Document --ref ${{ github.ref }} --buildNum ${{ github.run_number }}
|
||||
- name: Deploy
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
# this is a beautiful way to deploy a website and i will not take any criticism
|
||||
run: |
|
||||
curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && sudo dpkg -i cloudflared.deb
|
||||
mkdir ~/.ssh && echo "${{ secrets.ELLBOT_KEY }}" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
|
||||
rsync -rv --delete -e 'ssh -o "ProxyCommand cloudflared access ssh --hostname %h" -o "StrictHostKeyChecking=no"' Docs/_site/. ellbot@ssh.ellpeck.de:/var/www/MLEM
|
||||
|
|
78
.github/workflows/web.yml
vendored
Normal file
78
.github/workflows/web.yml
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
on: [push, pull_request]
|
||||
jobs:
|
||||
build-demo:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
- name: Restore tools
|
||||
run: dotnet tool restore
|
||||
- name: Run PublishWeb
|
||||
run: dotnet cake --target PublishWeb --ref ${{ github.ref }} --buildNum ${{ github.run_number }}
|
||||
- name: Upload demo artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: Demos.Web/bin/Release/net8.0/publish/wwwroot
|
||||
name: demo
|
||||
include-hidden-files: true
|
||||
if-no-files-found: error
|
||||
build-docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
- name: Restore tools
|
||||
run: dotnet tool restore
|
||||
- name: Run Document
|
||||
run: dotnet cake --target Document --ref ${{ github.ref }} --buildNum ${{ github.run_number }}
|
||||
- name: Upload docs artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: Docs/_site
|
||||
name: docs
|
||||
include-hidden-files: true
|
||||
if-no-files-found: error
|
||||
deploy:
|
||||
needs: [build-demo, build-docs]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download demo artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: demo
|
||||
path: demo
|
||||
- name: Download docs artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: docs
|
||||
path: docs
|
||||
- name: Combine sites
|
||||
run: |
|
||||
mv docs _site
|
||||
mv demo _site/demo
|
||||
- name: Upload combined artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: _site
|
||||
name: site
|
||||
include-hidden-files: true
|
||||
if-no-files-found: error
|
||||
- name: Deploy
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
# this is a beautiful way to deploy a website and i will not take any criticism
|
||||
run: |
|
||||
curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && sudo dpkg -i cloudflared.deb
|
||||
mkdir ~/.ssh && echo "${{ secrets.ELLBOT_KEY }}" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
|
||||
rsync -rv --delete -e 'ssh -o "ProxyCommand cloudflared access ssh --hostname %h" -o "StrictHostKeyChecking=no"' _site/. ellbot@ssh.ellpeck.de:/var/www/MLEM
|
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -2,7 +2,8 @@
|
|||
MLEM tries to adhere to [semantic versioning](https://semver.org/). Potentially breaking changes are written in **bold**.
|
||||
|
||||
Jump to version:
|
||||
- [7.1.1](#711-in-development)
|
||||
- [7.1.2](#712-in-development)
|
||||
- [7.1.1](#711)
|
||||
- [7.1.0](#710)
|
||||
- [7.0.0](#700)
|
||||
- [6.3.1](#631)
|
||||
|
@ -15,10 +16,21 @@ Jump to version:
|
|||
- [5.1.0](#510)
|
||||
- [5.0.0](#500)
|
||||
|
||||
## 7.1.1 (In Development)
|
||||
## 7.1.2 (In Development)
|
||||
|
||||
No code changes
|
||||
|
||||
## 7.1.1
|
||||
|
||||
### MLEM
|
||||
Additions
|
||||
- Added TextureExtensions.PremultipliedCopy for textures
|
||||
|
||||
### MLEM.Ui
|
||||
Improvements
|
||||
- Construct images in UiParser.ParseImage on the main thread to support usage with KNI
|
||||
- Create a premultiplied copy of UiParser images to support usage with KNI
|
||||
|
||||
## 7.1.0
|
||||
|
||||
### MLEM
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
"**/MLEM**.csproj"
|
||||
],
|
||||
"exclude": [
|
||||
"**.FNA.**"
|
||||
"**.FNA.**",
|
||||
"**.KNI.**"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
|
@ -6,3 +6,5 @@
|
|||
href: api/
|
||||
- name: Changelog
|
||||
href: ../CHANGELOG.md
|
||||
- name: Web Demo
|
||||
href: demo/
|
||||
|
|
|
@ -17,18 +17,8 @@ namespace MLEM.Data.Content {
|
|||
#endif
|
||||
|
||||
// premultiply the texture's color to be in line with the pipeline's texture reader
|
||||
using (var texture = Texture2D.FromStream(manager.GraphicsDevice, stream)) {
|
||||
var ret = new Texture2D(manager.GraphicsDevice, texture.Width, texture.Height);
|
||||
using (var textureData = texture.GetTextureData()) {
|
||||
using (var retData = ret.GetTextureData()) {
|
||||
for (var x = 0; x < ret.Width; x++) {
|
||||
for (var y = 0; y < ret.Height; y++)
|
||||
retData[x, y] = Color.FromNonPremultiplied(textureData[x, y].ToVector4());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
using (var texture = Texture2D.FromStream(manager.GraphicsDevice, stream))
|
||||
return texture.PremultipliedCopy();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
@ -10,7 +10,6 @@ using MLEM.Ui.Style;
|
|||
|
||||
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
|
||||
using System.Net.Http;
|
||||
|
||||
#else
|
||||
using System.Net;
|
||||
#endif
|
||||
|
@ -139,43 +138,61 @@ namespace MLEM.Ui.Parsers {
|
|||
/// This method invokes an asynchronouns action, meaning the <see cref="Image"/>'s <see cref="Image.Texture"/> will likely not have loaded in when this method returns.
|
||||
/// </summary>
|
||||
/// <param name="path">The absolute, relative or web path to the image.</param>
|
||||
/// <param name="onImageFetched">An action that is invoked with the loaded image once it is fetched. Note that this action will be invoked asynchronously.</param>
|
||||
/// <param name="onImageFetched">An action that is invoked with the loaded image once it is fetched. Note that this action will be invoked synchronously.</param>
|
||||
/// <returns>The loaded image.</returns>
|
||||
/// <exception cref="NullReferenceException">Thrown if <see cref="GraphicsDevice"/> is null, or if there is an <see cref="Exception"/> loading the image and <see cref="ImageExceptionHandler"/> is unset.</exception>
|
||||
protected Image ParseImage(string path, Action<TextureRegion> onImageFetched = null) {
|
||||
if (this.GraphicsDevice == null)
|
||||
throw new NullReferenceException("A UI parser requires a GraphicsDevice for parsing images");
|
||||
|
||||
var imageLock = new object();
|
||||
var bytesLock = new object();
|
||||
byte[] bytes = null;
|
||||
TextureRegion image = null;
|
||||
return new Image(Anchor.AutoLeft, Vector2.One, _ => {
|
||||
lock (imageLock)
|
||||
if (image == null) {
|
||||
bool bytesNull;
|
||||
lock (bytesLock)
|
||||
bytesNull = bytes == null;
|
||||
if (!bytesNull) {
|
||||
Texture2D tex;
|
||||
lock (bytesLock) {
|
||||
using (var stream = new MemoryStream(bytes)) {
|
||||
using (var read = Texture2D.FromStream(this.GraphicsDevice, stream))
|
||||
tex = read.PremultipliedCopy();
|
||||
}
|
||||
bytes = null;
|
||||
}
|
||||
image = new TextureRegion(tex);
|
||||
onImageFetched?.Invoke(image);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}) {
|
||||
SetHeightBasedOnAspect = true,
|
||||
OnAddedToUi = e => {
|
||||
bool imageNull;
|
||||
lock (imageLock)
|
||||
imageNull = image == null;
|
||||
if (imageNull)
|
||||
LoadImageAsync();
|
||||
if (image == null) {
|
||||
bool bytesNull;
|
||||
lock (bytesLock)
|
||||
bytesNull = bytes == null;
|
||||
if (bytesNull)
|
||||
LoadImageStream();
|
||||
}
|
||||
},
|
||||
OnRemovedFromUi = e => {
|
||||
lock (imageLock) {
|
||||
lock (bytesLock)
|
||||
bytes = null;
|
||||
image?.Texture.Dispose();
|
||||
image = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
async void LoadImageAsync() {
|
||||
async void LoadImageStream() {
|
||||
// only apply the base path for relative files
|
||||
if (this.ImageBasePath != null && !path.StartsWith("http") && !Path.IsPathRooted(path))
|
||||
path = $"{this.ImageBasePath}/{path}";
|
||||
try {
|
||||
Texture2D tex;
|
||||
if (path.StartsWith("http")) {
|
||||
byte[] src;
|
||||
if (path.StartsWith("http")) {
|
||||
#if NETSTANDARD2_0_OR_GREATER || NET6_0_OR_GREATER
|
||||
using (var client = new HttpClient())
|
||||
src = await client.GetByteArrayAsync(path);
|
||||
|
@ -183,18 +200,16 @@ namespace MLEM.Ui.Parsers {
|
|||
using (var client = new WebClient())
|
||||
src = await client.DownloadDataTaskAsync(path);
|
||||
#endif
|
||||
using (var memory = new MemoryStream(src))
|
||||
tex = Texture2D.FromStream(this.GraphicsDevice, memory);
|
||||
} else {
|
||||
using (var stream = Path.IsPathRooted(path) ? File.OpenRead(path) : TitleContainer.OpenStream(path))
|
||||
tex = Texture2D.FromStream(this.GraphicsDevice, stream);
|
||||
}
|
||||
lock (imageLock) {
|
||||
if (image == null) {
|
||||
image = new TextureRegion(tex);
|
||||
onImageFetched?.Invoke(image);
|
||||
using (var fileStream = Path.IsPathRooted(path) ? File.OpenRead(path) : TitleContainer.OpenStream(path)) {
|
||||
using (var memStream = new MemoryStream()) {
|
||||
await fileStream.CopyToAsync(memStream);
|
||||
src = memStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
lock (bytesLock)
|
||||
bytes = src;
|
||||
} catch (Exception e) {
|
||||
if (this.ImageExceptionHandler != null) {
|
||||
this.ImageExceptionHandler.Invoke(path, e);
|
||||
|
|
|
@ -18,6 +18,24 @@ namespace MLEM.Textures {
|
|||
return new TextureData(texture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and returns a copy of the given <paramref name="texture"/> with all colors converted to premultiplied alpha, which is the format that MonoGame's content pipeline loads textures in. This method uses <see cref="Color.FromNonPremultiplied(Microsoft.Xna.Framework.Vector4)"/> for all pixels in the <paramref name="texture"/>.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture of which to create a premultiplied copy.</param>
|
||||
/// <returns>The premultiplied copy of the <paramref name="texture"/>.</returns>
|
||||
public static Texture2D PremultipliedCopy(this Texture2D texture) {
|
||||
var ret = new Texture2D(texture.GraphicsDevice, texture.Width, texture.Height);
|
||||
using (var textureData = texture.GetTextureData()) {
|
||||
using (var retData = ret.GetTextureData()) {
|
||||
for (var x = 0; x < ret.Width; x++) {
|
||||
for (var y = 0; y < ret.Height; y++)
|
||||
retData[x, y] = Color.FromNonPremultiplied(textureData[x, y].ToVector4());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A struct that represents the data of a texture, accessed through <see cref="TextureExtensions.GetTextureData"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -9,7 +9,7 @@ MLEM is platform-agnostic and multi-targets .NET Standard 2.0, .NET 8.0 and .NET
|
|||
- Get prerelease builds on [BaGet](https://nuget.ellpeck.de/?q=mlem)
|
||||
- See the source code on [GitHub](https://github.com/Ellpeck/MLEM)
|
||||
- See tutorials and API documentation on [the website](https://mlem.ellpeck.de/)
|
||||
- Check out [the demos](https://github.com/Ellpeck/MLEM/tree/main/Demos) on [Desktop](https://github.com/Ellpeck/MLEM/tree/main/Demos.DesktopGL) or [Android](https://github.com/Ellpeck/MLEM/tree/main/Demos.Android)
|
||||
- Check out [the demos](https://github.com/Ellpeck/MLEM/tree/main/Demos) on [Desktop](https://github.com/Ellpeck/MLEM/tree/main/Demos.DesktopGL), [Android](https://github.com/Ellpeck/MLEM/tree/main/Demos.Android) or [Web](https://mlem.ellpeck.de/demo)
|
||||
- See [the changelog](https://mlem.ellpeck.de/CHANGELOG.html) for information on updates
|
||||
- Join [the Discord server](https://link.ellpeck.de/discordweb) to ask questions
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#tool dotnet:?package=docfx&version=2.75.3
|
||||
|
||||
// this is the upcoming version, for prereleases
|
||||
var version = Argument("version", "7.1.1");
|
||||
var version = Argument("version", "7.1.2");
|
||||
var target = Argument("target", "Default");
|
||||
var gitRef = Argument("ref", "refs/heads/main");
|
||||
var buildNum = Argument("buildNum", "");
|
||||
|
@ -83,6 +83,13 @@ Task("Document").Does(() => {
|
|||
DocFxServe("Docs/_site");
|
||||
});
|
||||
|
||||
Task("PublishWeb").Does(() => {
|
||||
DotNetPublish("Demos.Web/Demos.Web.KNI.csproj", new DotNetPublishSettings {
|
||||
Configuration = config,
|
||||
ArgumentCustomization = args => args.Append($"/p:Version={version}")
|
||||
});
|
||||
});
|
||||
|
||||
Task("Default").IsDependentOn("Pack");
|
||||
Task("Publish").IsDependentOn("Push");
|
||||
|
||||
|
|
Loading…
Reference in a new issue