// Copyright (c) 2023 bradson // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. using System.Linq; using JetBrains.Annotations; using UnityEngine.Rendering; namespace PerformanceFish.Utility; public static class PipetteTool { [UsedImplicitly] [DebugAction("Misc", "Pipette tool", actionType = DebugActionType.ToolMap, allowedGameStates = AllowedGameStates.PlayingOnMap)] public static void Action() { var things = UI.MouseCell().GetThingList(Find.CurrentMap).ToList(); things.Sort(static (x, y) => ((int)x.def.altitudeLayer).CompareTo((int)y.def.altitudeLayer)); for (var i = things.Count; i-- > 0; ) { var thing = things[i]; var material = thing.Graphic?.MatAt(thing.Rotation, thing); if (material == null) continue; var texture = material.mainTexture; if (texture == null) continue; var destinationTexture = RenderTexture.GetTemporary(texture.width, texture.height); Graphics.Blit(texture, destinationTexture); AsyncGPUReadback.Request(destinationTexture, callback: result => { try { using var pixelDataNative = result.GetData(); var pixelDataFiltered = pixelDataNative .Where(static color => (color.r > 0 || color.g > 0 || color.b > 0) && color.a > 0) .ToArray(); var averageColor = pixelDataFiltered.Length < 1 ? (Color32)Color.black : GetAverage(pixelDataFiltered); Log.Message($"Texture of thing '{thing}' has average color of {averageColor} { "(■)".Colorize(averageColor)}."); Find.LetterStack.AddLetterSilently(LetterMaker.MakeLetter("Pipette result", $"Texture of thing '{thing}' has average color of {averageColor} { "(■)".Colorize(averageColor)}", LetterDefOf.NeutralEvent), averageColor); } catch (Exception e) { Log.Error($"Exception in AsyncGPUReadback:\n{e}"); } finally { RenderTexture.ReleaseTemporary(destinationTexture); } }); break; } } private static Color32 GetAverage(Color32[] colors) => new(GetAverage(colors, static color => color.r), GetAverage(colors, static color => color.g), GetAverage(colors, static color => color.b), GetAverage(colors, static color => color.a)); private static byte GetAverage(IEnumerable colors, Func selector) => (byte)Mathf.RoundToInt((float)colors.Average(selector)); }