1 #region Copyright & License Information
2 /*
3  * Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
4  * This file is part of OpenRA, which is free software. It is made
5  * available to you under the terms of the GNU General Public License
6  * as published by the Free Software Foundation, either version 3 of
7  * the License, or (at your option) any later version. For more
8  * information, see COPYING.
9  */
10 #endregion
11 
12 using System;
13 using System.Collections.Generic;
14 using OpenRA.FileFormats;
15 using OpenRA.FileSystem;
16 using OpenRA.Graphics;
17 using OpenRA.Traits;
18 
19 namespace OpenRA.Mods.Common.Traits
20 {
21 	[Desc("Load a PNG and use its embedded palette.")]
22 	class PaletteFromPngInfo : ITraitInfo, IProvidesCursorPaletteInfo
23 	{
24 		[PaletteDefinition]
25 		[FieldLoader.Require]
26 		[Desc("Internal palette name")]
27 		public readonly string Name = null;
28 
29 		[Desc("If defined, load the palette only for this tileset.")]
30 		public readonly string Tileset = null;
31 
32 		[FieldLoader.Require]
33 		[Desc("Filename to load")]
34 		public readonly string Filename = null;
35 
36 		[Desc("Map listed indices to shadow. Ignores previous color.")]
37 		public readonly int[] ShadowIndex = { };
38 
39 		public readonly bool AllowModifiers = true;
40 
41 		[Desc("Whether this palette is available for cursors.")]
42 		public readonly bool CursorPalette = false;
43 
Create(ActorInitializer init)44 		public object Create(ActorInitializer init) { return new PaletteFromPng(init.World, this); }
45 
46 		string IProvidesCursorPaletteInfo.Palette { get { return CursorPalette ? Name : null; } }
47 
IProvidesCursorPaletteInfo.ReadPalette(IReadOnlyFileSystem fileSystem)48 		ImmutablePalette IProvidesCursorPaletteInfo.ReadPalette(IReadOnlyFileSystem fileSystem)
49 		{
50 			var png = new Png(fileSystem.Open(Filename));
51 
52 			if (png.Palette == null)
53 				throw new InvalidOperationException("Unable to load palette `{0}` from non-paletted png `{1}`".F(Name, Filename));
54 
55 			var colors = new uint[Palette.Size];
56 
57 			for (var i = 0; i < png.Palette.Length; i++)
58 				colors[i] = (uint)png.Palette[i].ToArgb();
59 
60 			return new ImmutablePalette(colors);
61 		}
62 	}
63 
64 	class PaletteFromPng : ILoadsPalettes, IProvidesAssetBrowserPalettes
65 	{
66 		readonly World world;
67 		readonly PaletteFromPngInfo info;
PaletteFromPng(World world, PaletteFromPngInfo info)68 		public PaletteFromPng(World world, PaletteFromPngInfo info)
69 		{
70 			this.world = world;
71 			this.info = info;
72 		}
73 
LoadPalettes(WorldRenderer wr)74 		public void LoadPalettes(WorldRenderer wr)
75 		{
76 			if (info.Tileset != null && info.Tileset.ToLowerInvariant() != world.Map.Tileset.ToLowerInvariant())
77 				return;
78 
79 			wr.AddPalette(info.Name, ((IProvidesCursorPaletteInfo)info).ReadPalette(world.Map), info.AllowModifiers);
80 		}
81 
82 		public IEnumerable<string> PaletteNames
83 		{
84 			get
85 			{
86 				// Only expose the palette if it is available for the shellmap's tileset (which is a requirement for its use).
87 				if (info.Tileset == null || info.Tileset == world.Map.Rules.TileSet.Id)
88 					yield return info.Name;
89 			}
90 		}
91 	}
92 }
93