Всем привет, сегодня я пришел с легенькой темой, которая, однако, требует некоторых усилий на реализацию.
Когда программируются редакторы мы повсеместно используем нестандартные иконки (если, конечно, хотим сделать качественный продукт - нужно поработать над оформлением).
Предположим, что на выходе вы хотите получить некоторый редактор одним DLL файлом. Но вот иконки, которые вы вынуждены хранить в одной папке с проектом ну просто портят всю картину!
Все мы знаем, что есть стандартная возможность "пришить ресурсы к DLL". Именно это и делается с картинками.
Но вот о том, как с ними взаимодействовать - я сегодня и расскажу.
Всё до безумия просто и уже готово для вас. Условлюсь лишь на том, что выдаю материал "как есть", без всяких универсальностей и подгона под статью - по сути там только две функции, в которых легко разобраться самим.
Предполагается, что для формирования самой DLL вы используете плагин UnityVS и все настройки уже проставлены верно.
Сама работа
- Создаете папку для ресурсов в проекте вашей DLL (например Resources) и кидаете туда нужные вам картинки.
Обязательно нужно выставить свойство "BuildAction = Embedded Resource".
Важно: ни в коем случае не надо пытаться использовать стандартный Resource-файл, если вы сформировали такой - удалите его нафиг. Нам нужны только картинки, Unity не поддерживает тип Bitmap, который там используется.
- Далее разбираемся в этом скрипте и делаем по аналогии:
public static class Icons { public static Texture2D MultiCreate0, MultiCreate1, MultiCreate2, MultiPick0, MultiPick1, SingleCreate0, SingleCreate1; public const string ManifestPath = "SpriteMaper.Editor.Resources."; static Icons() { var fields = typeof (Icons) .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static) .Where(x => x.FieldType == typeof (Texture2D)) .ToList(); var assembly = typeof (Icons).Assembly; Debug.Log(fields.Count); foreach (FieldInfo field in fields) field.SetValue(null, LoadTextureResource(assembly, field.Name, 64, 64)); } public static Texture2D LoadTextureResource(Assembly assembly, string resourceName, int width, int height, FilterMode filterMode = 0) { Texture2D textured = null; try { var manifestResourceStream = assembly.GetManifestResourceStream(ManifestPath + resourceName + ".png"); if (manifestResourceStream != null) { using (manifestResourceStream) { textured = new Texture2D(width, height, TextureFormat.ARGB32, false, true) { filterMode = filterMode }; textured.LoadImage(ReadToEnd(manifestResourceStream)); textured.hideFlags = HideFlags.HideAndDontSave; return textured; } } } catch {} if (textured == null) Debug.LogError("Missing Dll resource: " + resourceName); return textured; } private static byte[] ReadToEnd(Stream stream) { byte[] buffer4; long position = 0L; if (stream.CanSeek) { position = stream.Position; stream.Position = 0L; } try { int num3; var buffer = new byte[0x1000]; int offset = 0; while ((num3 = stream.Read(buffer, offset, buffer.Length - offset)) > 0) { offset += num3; if (offset == buffer.Length) { int num4 = stream.ReadByte(); if (num4 != -1) { var buffer2 = new byte[buffer.Length * 2]; Buffer.BlockCopy(buffer, 0, buffer2, 0, buffer.Length); Buffer.SetByte(buffer2, offset, (byte)num4); buffer = buffer2; offset++; } } } byte[] dst = buffer; if (buffer.Length != offset) { dst = new byte[offset]; Buffer.BlockCopy(buffer, 0, dst, 0, offset); } buffer4 = dst; } finally { if (stream.CanSeek) stream.Position = position; } return buffer4; } }
Для вашего проекта будут некоторые отличия:
- Исправьте константу ManifestPath на нужное вам значение. Обычно это название вашего основного пространства имен + ".Resources." или ".Properties.Resources." на конце. Пространство имен можно посмотреть в свойствах проекта.
- У вас будут другие поля для ваших Texture2D файлов
- Мой вариант конструктора создает иконки размером 64 на 64 с помощью рефлексии. Вы можете использовать другой подход и вручную перебрать всех нужные вам иконки. Для ручного перебора просто используйте эту функцию:
LoadTextureResource(assembly, textureName, 64, 64)
- Возможно вы имеет файлы с другим расширением (не .png). В этом случае участок кода можно изменить:
Находим:
var manifestResourceStream = assembly.GetManifestResourceStream(ManifestPath + resourceName + ".png");
И меняем расширение.
Далее можно спокойно использовать такие текстурки, не засоряя папку проекта:
((галерея
))
Всем спасибо за внимание.
Смотрите также:
Комментарии
Далее разбираемся в этом скрипте и делаем по аналогии
А почему бы не воспользоваться T4?
alexprey, дополню по возможности, если она будет конечно. Вообще я хз сам откуда достать скажем размер иконки, потому забиваю вручную.
alexprey, верю на слово. Я просто с генератором этим не работал особо, и времени разбираться сейчас в нём нет.
Extravert, Ну я так понял там нативный шарп используется для генерации, хотя могу и ошибаться, тоже не работал, но у нас активно используется. Сканируется ресурсный файл и генерируются свойства для получения значений от туда
CollectableItemData.cs
[CreateMenuItem(fileName = "newItem", menuName = "Data/Items/Collectable", order = 51]