[Unity editor extension] PSD to UGUI Prefab - the use of Aspose.PSD and Harmony library

"Whether the spell UI is responsible for the planning or the program?" has always been a highly controversial topic in the domestic game industry.

The contradiction is also clear:

Program: The UI is cumbersome and has no technical content. It should be handed over to the planner. The program is heavy and the time should be used wisely.

Planning: The program has complex requirements for the hierarchical structure and naming of the spelling UI, and the spelling of the UI requires technical thinking, and the program should be responsible.

In short, each has its own reasons, but having said that, since the UI designer must spell the UI elements when designing the UI interface, and there are various layers, colors, fonts and font sizes, why repeat the work of the UI designer and manually spell them out again? What about a UI?

In fact, Blue Lake has already been solving this pain point on the market. After installing the Blue Lake plug-in in PS, you can upload the UI to the Blue Lake website with one click by marking and cutting pictures, and project team members can see the UI layout, font size , UI element spacing/position, batch download of cut images, etc. Blue Lake has a free version and a paid version. If you are worried about resource security, enterprises can also purchase intranet deployment services, so many companies are using Blue Lake Collaboration. However, Blue Lake is designed for Android, iOS, and Web. In essence, for the Unity game UI, Blue Lake only solves the problem of not allowing the UI to adjust the position and font size through visual inspection, and Blue Lake parses out the psd layer. For numerical information, it is still necessary to manually spell the UI.

UI designers commonly use adobe illustrator and Photoshop, and adobe illustrator can also be exported as a psd file, so wouldn’t it be great to write a tool to automatically generate a collaged UI interface prefab directly based on the Photoshop file (psd)?

1. Use of Aspose.PSD .Net library

Aspose.PSD .Net library download: https://download.csdn.net/download/final5788/87685311

Aspose官网:File Format APIs for Word Excel PDF Email PowerPoint Barcode Images OCR Note and 3D 

 A paid psd file parsing library, you need to buy a license. Aspose.PSD does not rely on ps software, uses C# scripts to directly parse psd files, supports multiple layer analysis, export layer cutting, and also supports merging layers, etc., with very powerful functions.

By analyzing layer information through Aspose.PSD, it is not even necessary for the UI designer to rasterize the layer into an image layer. You can directly export the shape layer, fill color layer, etc. into an image. For the text layer (TextLayer), you can directly Read information such as text font, font size, color, etc., and directly generate Unity UGUI's Text text component or TextMeshProUGUI component and automatically set the text style.

1. Use PS to simply make an interface, export psd and put it into the Unity project:

 2. Use the Aspose.PSD interface to analyze and export the fragmented image

Here is a simple example of parsing a psd layer using Aspose.PSD:

using (var psd = Aspose.PSD.Image.Load(psdFile) as PsdImage)
            {
                foreach (var layer in psd.Layers)
                {
                    var layerTp = layer.GetType();
                    Debug.Log($"{layer.Name}->{layerTp.Name}");
                    switch (layerTp.Name)
                    {
                        case LayerType.Layer:
                        case LayerType.FillLayer:
                        case LayerType.TextLayer:

                            var fileName = Path.Combine(Path.GetDirectoryName(psdFile), Path.GetFileNameWithoutExtension(psdFile), $"{layer.DisplayName}.png");
                            var fileDir = Path.GetDirectoryName(fileName);
                            if (!Directory.Exists(fileDir)) Directory.CreateDirectory(fileDir);

                            layer.ToBitmap().Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
                            break;
                        //case LayerType.FillLayer://填充色图层

                        //    break;
                        //case LayerType.TextLayer:
                        //    if (layer is TextLayer txtLayer)
                        //    {
                        //        Debug.Log($"文本层:{txtLayer.Text}, color:{txtLayer.TextColor}");
                        //    }
                        //    break;
                        //case LayerType.SectionDividerLayer:
                        //    break;
                        //case LayerType.LayerGroup://组
                        //    if (layer is LayerGroup gpLayer)
                        //    {

                        //    }
                        //    break;
                    }

                }
            }


class LayerType
        {
            internal const string Layer = "Layer";
            internal const string FillLayer = "FillLayer";
            internal const string TextLayer = "TextLayer";
            internal const string SectionDividerLayer = "SectionDividerLayer";
            internal const string LayerGroup = "LayerGroup";
        }

 Save the psd layer as an image file:

imgLayer.ToBitmap().Save(fileName, System.Drawing.Imaging.ImageFormat.Png);

 You can even use the previously written image compression tool to automatically compress the fragmented image when exporting the fragmented image.

The program successfully exported the fragmented image, but there is a watermark on the image, and the text layer is also flawed after being exported into an image:

 At least let Aspose try it seriously, so I don’t know whether it is a “flaw” intentionally created by not buying a license, or the plug-in itself is flawed?

If you have Licenses, you need to initialize the certificate first:

new Aspose.PSD.License().SetLicense(new MemoryStream(Convert.FromBase64String("Your Licenses")));

The so-called "taste before buying", then first identify whether the plug-in is flawed, and if there is no flaw, we will buy a license.

I opened the dll with dnSpy and found that I was innocent. As expected of a technical software company, the obfuscation and anti-tracking were almost done to the extreme. No wonder I was so confident that I dared to cash in the form of an offline license.

Then change the way of thinking and continue to identify. . .

Second, the use of the Harmony library

Don't get me wrong, it has nothing to do with Huawei's Hongmeng. Harmony is an open source plug-in that can patch C# functions at runtime, and supports .net and mono.

Harmony library open source address: GitHub - pardeike/Harmony: A library for patching, replacing and decorating .NET and Mono methods during runtime

 Idea: Find a public license on the Internet. Aspose.PSD reports an error message during verification, which probably means that the license can support Aspose.PSD.dll released before xxx time point. Your dll release time is xxx, which means the license Expiration is invalid. This prompt is exposed:

1. An expiration date is stored in the license string;

2. A release date is saved in the dll;

3. During SetLicense, the license date is compared with the dll release date to determine whether the verification is successful.

According to the above clues, it is found that the license date is obtained from Xml, and the error prompt intimately gives the accurate license expiration date.

Ok, we have all the clues. Inject a patch into the Getter method of the system class System.Xml.XmlElement.InnerText through the Harmony library. If the text content is judged to be the same as the license expiration date, the date will be forced to a future date, so that it will never expire.

How to use Harmony:

First define the patch class:

Add to the patch class: HarmonyPatch(Type declaringType, string methodName, MethodType methodType)

[HarmonyPatch(typeof(System.Xml.XmlElement), nameof(System.Xml.XmlElement.InnerText), MethodType.Getter)]
    class MagicPatch
    {
        static void Prefix()
        {

        }
        static void Postfix(ref string __result)
        {
            if (__result == "20210827")
            {
                __result = "20250827";
            }
        }
    }

Among them, the static method Prefix: triggers before the original function is called; Postfix: triggers when the original function is called; Note: the function name cannot be changed, and Prefix and Postfix are fixed;

If you want to access the return value of the original function, you must be in Postfix. As in the above code, ref string __result is the reference of the return value of the InnerText Get method, and you can directly modify the referenced value.

After defining the patch class, you need to call the Harmony interface to inject the patch to take effect:

[InitializeOnLoadMethod]
        static void InitAsposeLicense()
        {
            if (licenseInitiated) return;
            var harmonyHook = new Harmony("Test");
            harmonyHook.PatchAll();

            new Aspose.PSD.License().SetLicense(new MemoryStream(Convert.FromBase64String("You License")));

            licenseInitiated = true;
            harmonyHook.UnpatchAll();
        }

PatchAll will automatically inject the patch class marked by HarmonyPatch. In order not to affect other InnerText using Xml, when the patch is used up and not needed, call UnpatchAll to cancel all the patches.

OK, it's that simple. All work is ready, start testing:

 Export the psd layer again, and everything is normal for the picture, which proves that the Aspose.PSD library can work perfectly, and the existing "flaw" is the reason for not having a license, so you can buy the license with confidence.

Guess you like

Origin blog.csdn.net/final5788/article/details/130114695