Colour pixel-art toolbar icons, 64 px toolbar slots, ViewportCapture: screenshots in sRGB under hdr_2d
No files matched your search
@@ -22,6 +22,10 @@ namespace Cthangover.Mods.Interface.Tool
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ToolBox : Control, IToolbarHost, ISaveIconHost
|
public partial class ToolBox : Control, IToolbarHost, ISaveIconHost
|
||||||
{
|
{
|
||||||
|
/// <summary>Side of a toolbar button and its icon: the icons are 64 px pixel-art sprites (scaled x4), so a
|
||||||
|
/// 64 px slot shows every sprite pixel; at 60 px the nearest filter dropped rows of them.</summary>
|
||||||
|
private const int SlotSize = 64;
|
||||||
|
|
||||||
private HBoxContainer _buttons;
|
private HBoxContainer _buttons;
|
||||||
private TextureRect _saveIcon;
|
private TextureRect _saveIcon;
|
||||||
|
|
||||||
@@ -64,14 +68,14 @@ namespace Cthangover.Mods.Interface.Tool
|
|||||||
{
|
{
|
||||||
var button = new Button
|
var button = new Button
|
||||||
{
|
{
|
||||||
CustomMinimumSize = new Vector2(60, 60),
|
CustomMinimumSize = new Vector2(SlotSize, SlotSize),
|
||||||
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
SizeFlagsVertical = SizeFlags.ShrinkCenter,
|
||||||
TooltipText = title,
|
TooltipText = title,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (icon != null)
|
if (icon != null)
|
||||||
{
|
{
|
||||||
var iconRect = UiKit.Icon(icon, 60);
|
var iconRect = UiKit.Icon(icon, SlotSize);
|
||||||
button.AddChild(iconRect);
|
button.AddChild(iconRect);
|
||||||
iconRect.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect);
|
iconRect.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect);
|
||||||
}
|
}
|
||||||
@@ -92,7 +96,7 @@ namespace Cthangover.Mods.Interface.Tool
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds one "tools" toolbar button whose popup lists every visible
|
/// Adds one "tools" toolbar button whose popup lists every visible
|
||||||
/// <see cref="IToolBoxButton"/>. Tools used to get a text button each,
|
/// <see cref="IToolBoxButton"/>. Tools used to get a text button each,
|
||||||
/// which did not fit the 60×60 icon row and overlapped its icons; a
|
/// which did not fit the square icon row and overlapped its icons; a
|
||||||
/// single icon keeps the HUD row uniform no matter how many tools are
|
/// single icon keeps the HUD row uniform no matter how many tools are
|
||||||
/// installed. Nothing is added when no tool button is visible.
|
/// installed. Nothing is added when no tool button is visible.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
namespace Cthangover.Mods.Interface.View
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Takes a screenshot of a viewport the way the player sees it.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The project renders 2D in HDR (<c>rendering/viewport/hdr_2d</c>): the viewport texture then holds linear
|
||||||
|
/// colour, and Godot converts it to sRGB only when it blits to the window. A plain
|
||||||
|
/// <c>GetTexture().GetImage().SavePng()</c> wrote those linear values, so every screenshot (the site's
|
||||||
|
/// gallery included) came out much darker than the game, shadows most of all. The conversion runs on
|
||||||
|
/// float data before the 8-bit quantisation, so dark gradients do not band.
|
||||||
|
/// </remarks>
|
||||||
|
public static class ViewportCapture
|
||||||
|
{
|
||||||
|
/// <summary>The current frame of <paramref name="viewport"/> as RGBA8 sRGB, or null without a frame.</summary>
|
||||||
|
public static Image Take(Viewport viewport)
|
||||||
|
{
|
||||||
|
var image = viewport.GetTexture()?.GetImage();
|
||||||
|
if (image == null || !viewport.UseHdr2D)
|
||||||
|
return image;
|
||||||
|
|
||||||
|
image.Convert(Image.Format.Rgbaf);
|
||||||
|
var floats = MemoryMarshal.Cast<byte, float>(image.GetData());
|
||||||
|
var bytes = new byte[floats.Length];
|
||||||
|
for (var i = 0; i < floats.Length; i++)
|
||||||
|
{
|
||||||
|
var v = Math.Clamp(floats[i], 0f, 1f);
|
||||||
|
if (i % 4 != 3)
|
||||||
|
v = v <= 0.0031308f ? v * 12.92f : 1.055f * MathF.Pow(v, 1f / 2.4f) - 0.055f;
|
||||||
|
bytes[i] = (byte)MathF.Round(v * 255f);
|
||||||
|
}
|
||||||
|
return Image.CreateFromData(image.GetWidth(), image.GetHeight(), false, Image.Format.Rgba8, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Saves the current frame of <paramref name="viewport"/> as a PNG; false without a frame.</summary>
|
||||||
|
public static bool SavePng(Viewport viewport, string path)
|
||||||
|
{
|
||||||
|
var image = Take(viewport);
|
||||||
|
return image != null && image.SavePng(path) == Error.Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 390 B After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 5.7 KiB |