IconGenerator.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. //This file is partially subject to Chromium's BSD license, read the class notes for more details.
  2. using System;
  3. using UnityEngine;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Text;
  9. using UnityEditor;
  10. using CursorType = ZenFulcrum.EmbeddedBrowser.BrowserNative.CursorType;
  11. /**
  12. * Utility for generating the cursor icons.
  13. *
  14. * This isn't really here for general usage, but if you're willing to read the source and
  15. * fiddle with things this may give you a head start from starting with nothing.
  16. *
  17. * The default icons are pulled from
  18. * https://chromium.googlesource.com/chromium/src.git/+/master/ui/resources/default_100_percent/common/pointers/
  19. * https://chromium.googlesource.com/chromium/src.git/+/master/ui/resources/ui_resources.grd
  20. * and
  21. * https://chromium.googlesource.com/chromium/src.git/+/master/ui/base/cursor/cursors_aura.cc
  22. * This tool is used with a local directory, {IconGenerator.path}, filled with those icons.
  23. *
  24. * You also need to add a "loading.png" to the folder.
  25. *
  26. * To use this script, update the local path to your icons, define ZF_ICON_GENERATOR, and run it in
  27. * from Assets->ZF Browser->Generate Icons.
  28. */
  29. [ExecuteInEditMode]
  30. public class IconGenerator {
  31. private const string path = @"/my/path/to/chromium/ui-resources/default_100_percent/common/pointers";
  32. private const string destAsset = "ZFBrowser/Resources/Browser/Cursors";
  33. public static bool useBig = false;
  34. #if ZF_ICON_GENERATOR
  35. [MenuItem("Assets/ZF Browser/Generate Icons")]
  36. #endif
  37. public static void GenerateIcons() {
  38. var icons = new SortedDictionary<string, Texture2D>();
  39. var w = -1;
  40. var h = -1;
  41. foreach (var file in Directory.GetFiles(path)) {
  42. if (useBig && !file.Contains("_big.png")) continue;
  43. if (!useBig && file.Contains("_big.png")) continue;
  44. var tex = new Texture2D(0, 0);
  45. tex.LoadImage(File.ReadAllBytes(file));
  46. if (w < 0) {
  47. w = tex.width;
  48. h = tex.height;
  49. } else if (w != tex.width || h != tex.height) {
  50. throw new Exception("Icons are not all the same size. This differs: " + file);
  51. }
  52. var name = Path.GetFileNameWithoutExtension(file);
  53. if (useBig) name = name.Substring(0, name.Length - 4);
  54. icons[name] = tex;
  55. }
  56. //Also add one for "cursor: none"
  57. icons["_none_"] = null;
  58. var res = new Texture2D(w * icons.Count, h, TextureFormat.ARGB32, false);
  59. var descData = new StringBuilder();
  60. var namesToPositions = new Dictionary<string, int>();
  61. var i = 0;
  62. foreach (var kvp in icons) {
  63. if (kvp.Value == null) {
  64. Fill(new Color(0, 0, 0, 0), res, i * w, 0, w, h);
  65. } else {
  66. Copy(kvp.Value, res, i * w, 0);
  67. }
  68. namesToPositions[kvp.Key] = i++;
  69. }
  70. foreach (var kvp in mapping) {
  71. var pos = -1;
  72. try {
  73. if (kvp.Value.name != "_custom_") pos = namesToPositions[kvp.Value.name];
  74. } catch (KeyNotFoundException) {
  75. throw new KeyNotFoundException("No file found for " + kvp.Value.name);
  76. }
  77. if (descData.Length != 0) descData.Append("\n");
  78. var hotspot = kvp.Value.hotspot;
  79. if (!useBig) {
  80. hotspot.x = Mathf.Round(hotspot.x * .5f) - 3;
  81. hotspot.y = Mathf.Round(kvp.Value.hotspot.y * .5f) - 4;
  82. }
  83. descData
  84. .Append(kvp.Key).Append(",")
  85. .Append(pos).Append(",")
  86. .Append(hotspot.x).Append(",")
  87. .Append(hotspot.y)
  88. ;
  89. }
  90. var resName = Application.dataPath + "/" + destAsset;
  91. File.WriteAllBytes(
  92. resName + ".png",
  93. res.EncodeToPNG()
  94. );
  95. File.WriteAllText(
  96. resName + ".csv",
  97. descData.ToString()
  98. );
  99. AssetDatabase.Refresh();
  100. Debug.Log("Wrote icons files to " + resName + ".(png|csv) size: " + w + "x" + h);
  101. }
  102. private static void Fill(Color color, Texture2D dest, int sx, int sy, int w, int h) {
  103. for (int x = sx; x < w; ++x) {
  104. for (int y = sy; y < h; ++y) {
  105. dest.SetPixel(x, y, color);
  106. }
  107. }
  108. }
  109. private static void Copy(Texture2D src, Texture2D dest, int destX, int destY) {
  110. //slow, but fine for a utility
  111. for (int x = 0; x < src.width; ++x) {
  112. for (int y = 0; y < src.height; ++y) {
  113. dest.SetPixel(x + destX, y + destY, src.GetPixel(x, y));
  114. }
  115. }
  116. }
  117. private struct CursorInfo {
  118. public CursorInfo(string name, Vector2 hotspot) {
  119. this.name = name;
  120. this.hotspot = hotspot;
  121. }
  122. public string name;
  123. public Vector2 hotspot;
  124. }
  125. private static Dictionary<CursorType, CursorInfo> mapping = new Dictionary<CursorType, CursorInfo>() {
  126. //Hotspots in for the default Chromium cursors can be found in ui/base/cursor/cursors_aura.cc, this is adapted
  127. //from there.
  128. //Note that we are always using the 2x (_big) icons.
  129. {
  130. //{19, 11}, {38, 22}} alias kCursorAlias IDR_AURA_CURSOR_ALIAS CT_ALIAS
  131. CursorType.Alias,
  132. new CursorInfo("alias", new Vector2(19, 11))
  133. }, {
  134. //{30, 30}, {60, 60}} cell kCursorCell IDR_AURA_CURSOR_CELL CT_CELL
  135. CursorType.Cell,
  136. new CursorInfo("cell", new Vector2(30, 30))
  137. }, {
  138. //{35, 29}, {70, 58}} sb_h_double_arrow kCursorColumnResize IDR_AURA_CURSOR_COL_RESIZE CT_COLUMNRESIZE
  139. CursorType.ColumnResize,
  140. new CursorInfo("sb_h_double_arrow", new Vector2(35, 29))
  141. }, {
  142. //{11, 11}, {22, 22}} context_menu kCursorContextMenu IDR_AURA_CURSOR_CONTEXT_MENU CT_CONTEXTMENU
  143. CursorType.ContextMenu,
  144. new CursorInfo("context_menu", new Vector2(11, 11))
  145. }, {
  146. //{10, 10}, {20, 20}} copy kCursorCopy IDR_AURA_CURSOR_COPY CT_COPY
  147. CursorType.Copy,
  148. new CursorInfo("copy", new Vector2(10, 10))
  149. }, {
  150. //{31, 30}, {62, 60}} crosshair kCursorCross IDR_AURA_CURSOR_CROSSHAIR CT_CROSS
  151. CursorType.Cross,
  152. new CursorInfo("crosshair", new Vector2(31, 30))
  153. }, {
  154. //{??, ??}, {??, ??}} custom kCursorCustom IDR_NONE CT_CUSTOM
  155. CursorType.Custom,
  156. new CursorInfo("_custom_", new Vector2(-1, -1))
  157. }, {
  158. //{??, ??}, {??, ??}} _unknown_ kCursorEastPanning IDR_NONE CT_EASTPANNING
  159. CursorType.EastPanning,
  160. new CursorInfo("move", new Vector2(32, 31))
  161. }, {
  162. //{35, 29}, {70, 58}} sb_h_double_arrow kCursorEastResize IDR_AURA_CURSOR_EAST_RESIZE CT_EASTRESIZE
  163. CursorType.EastResize,
  164. new CursorInfo("sb_h_double_arrow", new Vector2(35, 29))
  165. }, {
  166. //{35, 29}, {70, 58}} sb_h_double_arrow kCursorEastWestResize IDR_AURA_CURSOR_EAST_WEST_RESIZE CT_EASTWESTRESIZE
  167. CursorType.EastWestResize,
  168. new CursorInfo("sb_h_double_arrow", new Vector2(35, 29))
  169. }, {
  170. //{21, 11}, {42, 22}} fleur kCursorGrab IDR_AURA_CURSOR_GRAB CT_GRAB
  171. CursorType.Grab,
  172. new CursorInfo("fleur", new Vector2(21, 11))
  173. }, {
  174. //{20, 12}, {40, 24}} hand3 kCursorGrabbing IDR_AURA_CURSOR_GRABBING CT_GRABBING
  175. CursorType.Grabbing,
  176. new CursorInfo("hand3", new Vector2(20, 12))
  177. }, {
  178. //{25, 7}, {50, 14}} hand2 kCursorHand IDR_AURA_CURSOR_HAND CT_HAND
  179. CursorType.Hand,
  180. new CursorInfo("hand2", new Vector2(25, 7))
  181. }, {
  182. //{10, 11}, {20, 22}} help kCursorHelp IDR_AURA_CURSOR_HELP CT_HELP
  183. CursorType.Help,
  184. new CursorInfo("help", new Vector2(10, 11))
  185. }, {
  186. //{30, 32}, {60, 64}} xterm kCursorIBeam IDR_AURA_CURSOR_IBEAM CT_IBEAM
  187. CursorType.IBeam,
  188. new CursorInfo("xterm", new Vector2(30, 32))
  189. }, {
  190. //{??, ??}, {??, ??}} _unknown_ kCursorMiddlePanning IDR_NONE CT_MIDDLEPANNING
  191. CursorType.MiddlePanning,
  192. new CursorInfo("move", new Vector2(32, 31))
  193. }, {
  194. //{32, 31}, {64, 62}} move kCursorMove IDR_AURA_CURSOR_MOVE CT_MOVE
  195. CursorType.Move,
  196. new CursorInfo("move", new Vector2(32, 31))
  197. }, {
  198. //{10, 10}, {20, 20}} nodrop kCursorNoDrop IDR_AURA_CURSOR_NO_DROP CT_NODROP
  199. CursorType.NoDrop,
  200. new CursorInfo("nodrop", new Vector2(10, 10))
  201. }, {
  202. //{??, ??}, {??, ??}} _unknown_ kCursorNone IDR_NONE CT_NONE
  203. CursorType.None,
  204. new CursorInfo("_none_", new Vector2(0, 0))
  205. }, {
  206. //{??, ??}, {??, ??}} _unknown_ kCursorNorthEastPanning IDR_NONE CT_NORTHEASTPANNING
  207. CursorType.NorthEastPanning,
  208. new CursorInfo("move", new Vector2(32, 31))
  209. }, {
  210. //{31, 28}, {62, 56}} top_right_corner kCursorNorthEastResize IDR_AURA_CURSOR_NORTH_EAST_RESIZE CT_NORTHEASTRESIZE
  211. CursorType.NorthEastResize,
  212. new CursorInfo("top_right_corner", new Vector2(31, 28))
  213. }, {
  214. //{32, 30}, {64, 60}} top_right_corner kCursorNorthEastSouthWestResize IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE CT_NORTHEASTSOUTHWESTRESIZE
  215. CursorType.NorthEastSouthWestResize,
  216. new CursorInfo("top_right_corner", new Vector2(32, 30))
  217. }, {
  218. //{??, ??}, {??, ??}} _unknown_ kCursorNorthPanning IDR_NONE CT_NORTHPANNING
  219. CursorType.NorthPanning,
  220. new CursorInfo("move", new Vector2(32, 31))
  221. }, {
  222. //{29, 32}, {58, 64}} sb_v_double_arrow kCursorNorthResize IDR_AURA_CURSOR_NORTH_RESIZE CT_NORTHRESIZE
  223. CursorType.NorthResize,
  224. new CursorInfo("sb_v_double_arrow", new Vector2(29, 32))
  225. }, {
  226. //{29, 32}, {58, 64}} sb_v_double_arrow kCursorNorthSouthResize IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE CT_NORTHSOUTHRESIZE
  227. CursorType.NorthSouthResize,
  228. new CursorInfo("sb_v_double_arrow", new Vector2(29, 32))
  229. }, {
  230. //{??, ??}, {??, ??}} _unknown_ kCursorNorthWestPanning IDR_NONE CT_NORTHWESTPANNING
  231. CursorType.NorthWestPanning,
  232. new CursorInfo("move", new Vector2(32, 31))
  233. }, {
  234. //{28, 28}, {56, 56}} top_left_corner kCursorNorthWestResize IDR_AURA_CURSOR_NORTH_WEST_RESIZE CT_NORTHWESTRESIZE
  235. CursorType.NorthWestResize,
  236. new CursorInfo("top_left_corner", new Vector2(28, 28))
  237. }, {
  238. //{32, 31}, {64, 62}} top_left_corner kCursorNorthWestSouthEastResize IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE CT_NORTHWESTSOUTHEASTRESIZE
  239. CursorType.NorthWestSouthEastResize,
  240. new CursorInfo("top_left_corner", new Vector2(32, 31))
  241. }, {
  242. //{10, 10}, {20, 20}} nodrop kCursorNotAllowed IDR_AURA_CURSOR_NO_DROP CT_NOTALLOWED
  243. CursorType.NotAllowed,
  244. new CursorInfo("nodrop", new Vector2(10, 10))
  245. }, {
  246. //{10, 10}, {20, 20}} left_ptr kCursorPointer IDR_AURA_CURSOR_PTR CT_POINTER
  247. CursorType.Pointer,
  248. new CursorInfo("left_ptr", new Vector2(10, 10))
  249. }, {
  250. //{??, ??}, {??, ??}} _unknown_ kCursorProgress IDR_NONE CT_PROGRESS
  251. CursorType.Progress,
  252. new CursorInfo("loading", new Vector2(32, 32))
  253. }, {
  254. //{29, 32}, {58, 64}} sb_v_double_arrow kCursorRowResize IDR_AURA_CURSOR_ROW_RESIZE CT_ROWRESIZE
  255. CursorType.RowResize,
  256. new CursorInfo("sb_v_double_arrow", new Vector2(29, 32))
  257. }, {
  258. //{??, ??}, {??, ??}} _unknown_ kCursorSouthEastPanning IDR_NONE CT_SOUTHEASTPANNING
  259. CursorType.SouthEastPanning,
  260. new CursorInfo("move", new Vector2(32, 31))
  261. }, {
  262. //{28, 28}, {56, 56}} top_left_corner kCursorSouthEastResize IDR_AURA_CURSOR_SOUTH_EAST_RESIZE CT_SOUTHEASTRESIZE
  263. CursorType.SouthEastResize,
  264. new CursorInfo("top_left_corner", new Vector2(28, 28))
  265. }, {
  266. //{??, ??}, {??, ??}} _unknown_ kCursorSouthPanning IDR_NONE CT_SOUTHPANNING
  267. CursorType.SouthPanning,
  268. new CursorInfo("move", new Vector2(32, 31))
  269. }, {
  270. //{29, 32}, {58, 64}} sb_v_double_arrow kCursorSouthResize IDR_AURA_CURSOR_SOUTH_RESIZE CT_SOUTHRESIZE
  271. CursorType.SouthResize,
  272. new CursorInfo("sb_v_double_arrow", new Vector2(29, 32))
  273. }, {
  274. //{??, ??}, {??, ??}} _unknown_ kCursorSouthWestPanning IDR_NONE CT_SOUTHWESTPANNING
  275. CursorType.SouthWestPanning,
  276. new CursorInfo("move", new Vector2(32, 31))
  277. }, {
  278. //{31, 28}, {62, 56}} top_right_corner kCursorSouthWestResize IDR_AURA_CURSOR_SOUTH_WEST_RESIZE CT_SOUTHWESTRESIZE
  279. CursorType.SouthWestResize,
  280. new CursorInfo("top_right_corner", new Vector2(31, 28))
  281. }, {
  282. //{32, 30}, {64, 60}} xterm_horiz kCursorVerticalText IDR_AURA_CURSOR_XTERM_HORIZ CT_VERTICALTEXT
  283. CursorType.VerticalText,
  284. new CursorInfo("xterm_horiz", new Vector2(32, 30))
  285. }, {
  286. //{??, ??}, {??, ??}} _unknown_ kCursorWait IDR_NONE CT_WAIT
  287. CursorType.Wait,
  288. new CursorInfo("loading", new Vector2(32, 32))
  289. }, {
  290. //{??, ??}, {??, ??}} _unknown_ kCursorWestPanning IDR_NONE CT_WESTPANNING
  291. CursorType.WestPanning,
  292. new CursorInfo("move", new Vector2(32, 31))
  293. }, {
  294. //{35, 29}, {70, 58}} sb_h_double_arrow kCursorWestResize IDR_AURA_CURSOR_WEST_RESIZE CT_WESTRESIZE
  295. CursorType.WestResize,
  296. new CursorInfo("sb_h_double_arrow", new Vector2(35, 29))
  297. }, {
  298. //{25, 26}, {50, 52}} zoom_in kCursorZoomIn IDR_AURA_CURSOR_ZOOM_IN CT_ZOOMIN
  299. CursorType.ZoomIn,
  300. new CursorInfo("zoom_in", new Vector2(25, 26))
  301. }, {
  302. //{26, 26}, {52, 52}} zoom_out kCursorZoomOut IDR_AURA_CURSOR_ZOOM_OUT CT_ZOOMOUT
  303. CursorType.ZoomOut,
  304. new CursorInfo("zoom_out", new Vector2(26, 26))
  305. },
  306. };
  307. }