public void Add(TextureInfo ti) {
     if (texList == null) texList = new List<TextureInfo>();
     texList.Add(ti);
 }
        public void Save(string fileName,  string presetName, Dictionary<string, bool> dDelNodes) {
            Maid maid = holder.currentMaid;
            // カレントのメイドデータからプリセットデータを抽出
            var preset = new PresetData();
            preset.name = presetName;
            foreach (SlotInfo slotInfo in ACConstants.SlotNames.Values) {
                if (!slotInfo.enable) continue;

                TBodySkin slot = maid.body0.GetSlot((int)slotInfo.Id);
                // マスク情報を抽出
                SlotState maskState;
                if (slot.obj == null) {
                    maskState = SlotState.NotLoaded;
                } else if (!slot.boVisible) {
                    maskState = SlotState.Masked;
                } else {
                    maskState = SlotState.Displayed;
                }

                Material[] materialList = holder.GetMaterials(slot);
                if (materialList.Length == 0) continue;

                var slotItem = new CCSlot(slotInfo.Id);
                slotItem.mask = maskState;

                foreach (Material material in materialList) {
                    var type = ShaderType.Resolve(material.shader.name);
                    if (type == ShaderType.UNKNOWN) continue;
                    var cmat = new CCMaterial(material, type);
                    slotItem.Add(cmat);
                    foreach (var texProp in type.texProps) {
                        var tex2d = material.GetTexture(texProp.propId) as Texture2D;
                        if (tex2d == null || string.IsNullOrEmpty(tex2d.name)) continue;

                        var ti = new TextureInfo();
                        cmat.Add(ti);
                        ti.propName = texProp.keyName;
                        ti.texFile = tex2d.name;
                        var fp = texModifier.GetFilter(maid, slotInfo.Id.ToString(), material.name, tex2d.name);
                        if (fp != null && !fp.hasNotChanged()) ti.filter = new TexFilter(fp);
                    }
                }
                preset.slots.Add(slotItem);
            }

            for (int i = TypeUtil.BODY_START; i <= TypeUtil.BODY_END; i++) {
                var mpn = (MPN)Enum.ToObject(typeof(MPN), i);
                MaidProp mp = maid.GetProp(mpn);
                if (mp != null) {
                    if (!String.IsNullOrEmpty(mp.strFileName)) {
                        preset.mpns.Add(new CCMPN(mpn, mp.strFileName));
                    } else {
                        preset.mpnvals.Add(new CCMPNValue(mpn, mp.value, mp.min, mp.max));
                    }
                }
            }

            for (int i = TypeUtil.WEAR_START; i <= TypeUtil.WEAR_END; i++) {
                var mpn = (MPN)Enum.ToObject(typeof(MPN), i);
                MaidProp mp = maid.GetProp(mpn);
                if (mp != null && !String.IsNullOrEmpty(mp.strFileName)) {
                    preset.mpns.Add(new CCMPN(mpn, mp.strFileName));
                }
            }
//            for (int i = (int)MPN_TYPE_RANGE.FOLDER_BODY_START; i <= (int)MPN_TYPE_RANGE.FOLDER_BODY_END; i++) {
//                var mpn = (MPN)Enum.ToObject(typeof(MPN), i);
//                MaidProp mp = maid.GetProp(mpn);
//                if (mp != null) {
//                    LogUtil.Debug(mpn,":", mp.type, ", value=", mp.value, ", temp=", mp.temp_value, ", file=", mp.strFileName);
//                }
//            }

            // 無限色
            for (int j = TypeUtil.PARTSCOLOR_START; j <= TypeUtil.PARTSCOLOR_END; j++) {
                var pcEnum = (MaidParts.PARTS_COLOR)j;
                MaidParts.PartsColor part = maid.Parts.GetPartsColor(pcEnum);
                preset.partsColors[pcEnum.ToString()] = new CCPartsColor(part);
            }

            // 表示ノード
            preset.delNodes = new Dictionary<string, bool>(dDelNodes);
            
            LogUtil.Debug("create preset...", fileName);
            SavePreset(fileName, preset);
        }