【Unity】【エディタ拡張】テクスチャをリサイズするウィンドウ

テクスチャをリサイズするウィンドウです。

Unity2018.2

ソースコード

ソースコードは次の通りです。

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;

public class TextureResizer : ScriptableWizard 
{
    public enum TextureFormat
    {
        PNG,
    }

    [SerializeField]
    private Texture _source;
    [SerializeField]
    private bool _inputScale      = true;
    [SerializeField]
    private float _scale          = 1.0f;
    [SerializeField]
    private int _width                = 128;
    [SerializeField]
    private int _height               = 128;
    [SerializeField]
    private TextureFormat _format  = TextureFormat.PNG;

    [MenuItem("Window/Texture Resizer")]
    private static void Open()
    {
        DisplayWizard<TextureResizer>(ObjectNames.NicifyVariableName(typeof(TextureResizer).Name));
    }

    protected override bool DrawWizardGUI ()
    {
        var so  = new SerializedObject(this);
        so.Update();

        using (var ccs = new EditorGUI.ChangeCheckScope()) {
            EditorGUILayout.PropertyField(so.FindProperty("_source"));
            var inputScaleProp      = so.FindProperty("_inputScale");
            EditorGUILayout.PropertyField(inputScaleProp);
            if (inputScaleProp.boolValue) {
                EditorGUILayout.PropertyField(so.FindProperty("_scale"));
            }
            else {
                EditorGUILayout.PropertyField(so.FindProperty("_width"));
                EditorGUILayout.PropertyField(so.FindProperty("_height"));
            }
            EditorGUILayout.PropertyField(so.FindProperty("_format"));
            if (ccs.changed) {
                so.ApplyModifiedProperties();
                return true;
            }
        }
        return false;
    }

    private void OnWizardCreate () 
    {
        if (_source == null) {
            errorString     = "Source Texture is null.";
            return;
        }
        if (_inputScale && _scale <= float.Epsilon) {
            errorString     = "Invalid scale.";
            return;
        }
        if (!_inputScale && (_width <= 0 || _height <= 0)) {
            errorString     = "Invalid width / height.";
            return;
        }
        
        var sourceAssetPath         = AssetDatabase.GetAssetPath(_source);
        int width;
        int height;
        if (_inputScale) {
            width               = (int)(_source.width * _scale);
            height              = (int)(_source.height * _scale);
        }
        else {
            width               = _width;
            height              = _height;
        }

        // 保存先のファイルパスを取得する
        var fullPath            = EditorUtility
            .SaveFilePanel
            (
                "Save",
                Path.GetDirectoryName(sourceAssetPath),
                Path.GetFileNameWithoutExtension(sourceAssetPath),
                _format.ToString().ToLower()
            );
        if (string.IsNullOrEmpty(fullPath)) {
            return;
        }
        var matchAssetPath      = System.Text.RegularExpressions.Regex.Match(fullPath, "Assets/.*");
        var assetPath           = matchAssetPath.Value;
        
        // TypeがDefaultじゃなかったら一度Defaultにする
        var sourceImporter          = AssetImporter.GetAtPath(sourceAssetPath) as TextureImporter;
        var sourceTextureType       = sourceImporter.textureType;
        if (sourceTextureType != TextureImporterType.Default) {
            sourceImporter.textureType  = TextureImporterType.Default;
            sourceImporter.SaveAndReimport();
        }

        // サイズ変更後のRenderTextureに描画
        var rt                  = RenderTexture.GetTemporary(width, height);
        Graphics.Blit(_source, rt);

        // TextureTypeを戻しておく
        if (sourceTextureType != TextureImporterType.Default) {
            sourceImporter.textureType  = sourceTextureType;
            sourceImporter.SaveAndReimport();
        }
        
        // Texture2Dに描画
        var preRT               = RenderTexture.active;
        RenderTexture.active    = rt;
        var texture             = new Texture2D(width, height);
        texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
        texture.Apply();
        RenderTexture.active    = preRT;

        // 保存
        byte[] bytes;
        switch (_format) {
        case TextureFormat.PNG:
            bytes               = texture.EncodeToPNG();
            break;
        default:
            throw new System.Exception("Invalid format.");
        }
        File.WriteAllBytes(fullPath, bytes);
        AssetDatabase.Refresh();

        // TextureTypeを変更
        if (sourceTextureType != TextureImporterType.Default) {
            
            var importer            = AssetImporter.GetAtPath(assetPath) as TextureImporter;
            importer.textureType    = sourceTextureType;
            importer.SaveAndReimport();
        }

        RenderTexture.ReleaseTemporary(rt);
        DestroyImmediate(texture);
    }
}
#endif

説明はコメントの通りです。
フォーマットはとりあえずpngにだけ対応しています。

実行結果

f:id:halya_11:20181216232632p:plain

関連

light11.hatenadiary.com

light11.hatenadiary.com