View difference between Paste ID: F4ACs27D and cQYNu6r9
SHOW: | | - or go back to the newest paste.
1
/*
2-
 * CM3D2.YASD.Plugin (Yet Another Soft Demosaic Plugin)
2+
 * CM3D2.YASD.Plugin (Yet Another Soft Demosaic Plugin)+CBL Patch
3
 *
4
 * 改造者注:元の作者さんが長らくメンテされてないようなので、自力でChuB-Lip対応と新ダンス・撮影モード
5
 * 等への対応を行いました。しばりすのGameDataにテクスチャを置けばテクスチャ変更機能は要らなくなる
6
 * と思いますが、元作者さんに敬意を表してまだ残してあります。でも再帰的に取得できても配置が出来ないから
7
 * いまとなってはしばりすに任せたほうが……と思います。
8
 * ChuB-Lip のシーン番号は通常版とは異なるのですが、一覧を調べる方法がわからなったので調べられた範囲だけ
9
 * 載せています。
10
 *
11
 *
12
 *
13
 * モザイクのON/OFFを切り替えたりボディのテクスチャを変更できるUnityInjectorのプラグインです。
14
 * 
15
 * モザイクはF4でメイド|メイドとおもちゃ|全部|消さないを切り替えます。
16
 * iniファイルを書き換えるとキーや切り替えの有効無効、モザイクを消す対象を変更できます。
17
 * 切り替えを無効にしてもiniで指定されたモザイクは消えます。
18
 * 切り替え機能がいらなければOFFにすると無駄な処理が減る分ちょっとだけ軽くなるかも。
19
 *
20
 * テクスチャ変更はメイドのボディ限定でTranslation Loaderと同じような処理をします。
21
 * Translation Loaderと違いReiPatcherでパッチを当てる必要がないのが強みです。
22
 * メイドのボディ以外のテクスチャも変更したい場合は素直にTranslation Loaderを使ってください。
23
 * プラグインを導入して一度ゲームを起動するとUnityInjector\Configに
24
 * YASD.iniファイルとYASDフォルダが作成されるのでYASDフォルダの中にテクスチャファイルを
25
 * コピーしてください。
26
 * テクスチャはpng形式のみに対応しています。
27
 * メイドが表示されているときにF3を押すとメイドに反映されます。
28
 * F3を押さずに自動で変更することもできますがデフォルトで無効になっています。
29
 * 自動で変更する場合はiniファイルの[ChangeTexture]セクションの[AutoChange]を
30
 * Trueに書き換えてください。
31
 *
32-
 * SofrDemosaic.iniの内容
32+
33
 * テクスチャはゲーム起動時にリストが作成されてその中の物のみが反映されます。
34
 * テクスチャ変更時に何らかの理由で読み込みに失敗したファイルはリストから消去されます。
35
 * また、一度変更したテクスチャはファイルを入れ替えても即時反映されません。
36
 * ゲーム内のエディットで肌を変更後元の肌戻すと最新のファイルを読み込みます。
37
 * また、自動変更中にF3を押すとリストを更新し最新のファイルを強制的に適用します。
38
 * 要はゲーム中にテクスチャを入れ替えたらF3を押してください。
39
 *
40
 *
41
 * yasd.iniの内容
42
 * [DeMosaic]セクション
43
 * ChangeMode={True, False}
44
 *      キーボードでの切り替えの有効無効を設定します。
45
 *      True=有効 False=無効
46
 *
47
 * Target={None, Maid, MaidAndItem, All}
48
 *     モザイクを消す対象を指定。
49
 *     キーボード切り替えが有効な場合は押す度に切り替わります。
50
 *     無効の場合はiniで指定した値で固定されます。
51
 *          None=消さない
52
 *          Maid=女性のみ
53
 *          MaidAndItem=女性とおもちゃ
54
 *          All=全て(女性、おもちゃ、男性)
55
 *
56
 * HotKey
57
 *      モザイクモード切替キーの設定。デフォルトはF4。
58
 *      指定するコードは下記URL参照。
59
 *      http://docs.unity3d.com/jp/current/ScriptReference/KeyCode.html
60
 *
61
 *
62
 * [ChangeTexture]セクション
63
 * AutoChange={True, False}
64
 *      テクスチャ自動変更機能の有効無効を設定します。
65
 *      True=有効 False=無効
66
 *
67
 * HotKey
68
 *      テクスチャリスト再読み込みキーの設定。デフォルトはF3
69
 *      自動更新が無効の場合はテクスチャリスト読み込みとテクスチャの変更を行います。
70
 *      指定するコードはDeMosaicセクションのURL参照。
71
 *
72
 * 
73
 * コンパイル時の参照設定
74
 * /r:UnityEngine.dll /r:UnityInjector.dll /r:Assembly-CSharp.dll /r:Assembly-CSharp-firstpass.dll /r:ExINI.dll
75
 * 
76
*/
77
78
using ExIni;
79
using System;
80
using System.Collections;
81
using System.Collections.Generic;
82
using System.Diagnostics;
83
using System.IO;
84
using System.Linq;
85
using System.Text.RegularExpressions;
86-
    PluginName("Yet Another Soft DeMosaic"),
86+
87-
    PluginVersion("2.0.0.0")]
87+
88
using UnityInjector.Attributes;
89
using System.Reflection;
90
91
namespace CM3D2.YetAnotherSoftDemosaic.Plugin
92
{
93
    static internal class LINQExt {
94
        public static void ForEach<T>(this IEnumerable<T> self , Action<T> act) {
95
            foreach(var cur in self) act(cur);
96
        }
97-
        private bool allowAutoChangeTexture = false;
97+
98
99
    public static class UnityExtensionsBridge {
100
        static UnityExtensionsBridge() {
101
            klass = Type.GetType("UnityInjector.Extensions,UnityInjector");
102
        }
103
        static Type klass = null;
104
105
        public static string UserDataPath {
106
            get {
107
                return (string)klass.GetMethod("get_UserDataPath").Invoke(null,null);
108
            }
109
        }
110
    }
111
112
    [PluginFilter("CM3D2x64"),
113
    PluginFilter("CM3D2x86"),
114
    PluginFilter("CM3D2VRx64"),
115
    PluginFilter("CM3D2OHx64"),
116
    PluginFilter("CM3D2OHx86"),
117
    PluginFilter("CM3D2OHVRx64"),
118
    PluginName("Yet Another Soft DeMosaic+CBL Patch"),
119
    PluginVersion("2.0.0.1")]
120
    public class YASD : PluginBase
121
    {
122
        private Coroutine deMosaicCoroutine;
123
        private Coroutine[] changeTextureCoroutine = new Coroutine[2];
124
        private bool runningCoroutine = false;
125
126
        private bool allowChangeMosaic = true;
127
        private KeyCode deMosaicHotKey = KeyCode.F4;
128
129
        private bool allowAutoChangeTexture = true;
130
        private KeyCode loadTextureKey = KeyCode.F3;
131
132
        private bool isChubLip = false;
133
134
        //1fで1秒
135
        private const float WAIT_SECOND_DEMOSAIC = 0.5f;
136
137
        private const float WAIT_SECOND_CHANGE_TEXTURE = 1f;
138
139
        /// <summary>
140
        /// CM3D2のシーンリスト
141
        /// </summary>
142
        private enum Scene
143
        {
144
            /// <summary>メイド選択(夜伽、品評会の前など)</summary>
145
            SceneCharacterSelect = 1,
146
147
            /// <summary>品評会</summary>
148
            SceneCompetitiveShow = 2,
149
150
            /// <summary>昼夜メニュー、仕事結果</summary>
151
            SceneDaily = 3,
152
153
            /// <summary>ダンス1</summary>
154
            SceneDance_DDFL = 4,
155
156
            /// <summary>メイドエディット</summary>
157
            SceneEdit = 5,
158
159
            /// <summary>メーカーロゴ</summary>
160
            SceneLogo = 6,
161
162
            /// <summary>メイド管理</summary>
163
            SceneMaidManagement = 7,
164
165
            /// <summary>ショップ</summary>
166
            SceneShop = 8,
167
168-
            SceneDance_ETYL = 20
168+
169
            SceneTitle = 9,
170
171
            /// <summary>トロフィー閲覧</summary>
172
            SceneTrophy = 10,
173
174
            /// <summary>???</summary>
175
            SceneTryInfo = 11,
176
177
            /// <summary>主人公エディット</summary>
178
            SceneUserEdit = 12,
179
180
            /// <summary>起動時警告画面</summary>
181
            SceneWarning = 13,
182
183
            /// <summary>夜伽</summary>
184
            SceneYotogi = 14,
185
186
            /// <summary>ADVパート(kgスクリプト処理)</summary>
187
            SceneADV = 15,
188
189
            /// <summary>日付画面</summary>
190
            SceneStartDaily = 16,
191
192
            /// <summary>タイトルに戻る</summary>
193
            SceneToTitle = 17,
194
195
            /// <summary>MVP</summary>
196
            SceneSingleEffect = 18,
197
198-
            SceneDance_ETYL = 20
198+
199
            SceneStaffRoll = 19,
200
201
            /// <summary>ダンス2</summary>
202
            SceneDance_ETYL = 20,
203
204
            /// <summary>ダンス選択</summary>
205
            SceneDance_Selector = 21,
206
207
            /// <summary>ダンス_3</summary>
208
            SceneDance_SL = 22,
209
210-
            SceneADV = 15
210+
            /// <summary>デスクトップカスタム</summary>
211
            SceneEditDesk = 23,
212
213
            /// <summary>リコレクション</summary>
214
            SceneRecollection = 24,
215
216
            /// <summary>メイドバトル</summary>
217
            SceneMaidBattle = 25,
218
219
            /// <summary>ダンス_4</summary>
220
            SceneDance_SMT = 26,
221
222
            /// <summary>撮影モード</summary>
223
            ScenePoser = 27
224
        }
225
226
        /// <summary>
227
        /// CM3D2CBLのシーンリスト
228-
            SceneDance_ETYL = 20
228+
229
        private enum SceneCBL
230
        {
231
            /// <summary>1</summary>
232
233
            /// <summary>CBL:メニュー画面</summary>
234
            SceneMainMenuWithChubLip = 2,
235
236
            /// <summary>CBL:ダンス1</summary>
237
            SceneDance_DDFL_Release = 3,
238
239
            /// <summary>CBL:メイドエディット</summary>
240
            SceneEdit = 4,
241
242
            /// <summary>5</summary>
243
244
            /// <summary>CBL:タイトル画面</summary>
245
            SceneTitle = 6,
246
247
            /// <summary>7</summary>
248
249
            /// <summary>CBL:主人公エディット</summary>
250
            SceneShop = 8,
251
252
            /// <summary>CBL:起動時警告画面</summary>
253
            SceneWarning = 9,
254
255
            /// <summary>CBL:夜伽</summary>
256
            SceneYotogiWithChubLip = 10,
257
258
            /// <summary>CBL:ADVパート(kgスクリプト処理)</summary>
259
            SceneADV = 11,
260
261
            /// <summary>CBL:日付画面</summary>
262
            SceneStartDaily = 12,
263
264
            /// <summary>CBL:タイトルに戻る</summary>
265
            SceneToTitle = 13,
266
267
            /// <summary>14</summary>
268
269
            /// <summary>15</summary>
270
271
            /// <summary>CBL:ダンス2</summary>
272
            SceneDance_ETYL_Release = 16,
273
274
            /// <summary>CBL:ダンス選択</summary>
275
            SceneDanceSelect = 17,
276
277
            /// <summary>18</summary>
278
279
            /// <summary>CBL:デスクトップカスタム</summary>
280
            SceneDeskCustomize = 19,
281
282
            /// <summary>20</summary>
283
284
            /// <summary>CBL:撮影モード</summary>
285
            ScenePhotoMode = 21
286
        }
287
288
        /// <summary>
289
        /// 3Dキャラが描画されるレベル
290
        /// </summary>
291
        private enum EnableLevel
292
        {
293
            /// <summary>品評会</summary>
294
            SceneCompetitiveShow = 2,
295
296
            /// <summary>ダンス1</summary>
297
            SceneDance_DDFL = 4,
298
299
            /// <summary>メイドエディット</summary>
300
            SceneEdit = 5,
301
302
            /// <summary>ショップ</summary>
303
            SceneShop = 8,
304
305
            /// <summary>夜伽</summary>
306
            SceneYotogi = 14,
307
308
            /// <summary>ADVパート(kgスクリプト処理)</summary>
309
            SceneADV = 15,
310
311
            /// <summary>MVP</summary>
312
            SceneSingleEffect = 18,
313
314
            /// <summary>ダンス2</summary>
315
            SceneDance_ETYL = 20,
316
317
            /// <summary>ダンス_3</summary>
318
            SceneDance_SL = 22,
319
320
            /// <summary>リコレクション</summary>
321
            SceneRecollection = 24,
322
323
            /// <summary>メイドバトル</summary>
324
            SceneMaidBattle = 25,
325
326
            /// <summary>ダンス_4</summary>
327
            SceneDance_SMT = 26,
328
329
            /// <summary>撮影モード</summary>
330
            ScenePoser = 27
331
        }
332
333
        /// <summary>
334
        /// 3Dキャラが描画されるレベル ChuB-Lip
335
        /// </summary>
336
        private enum EnableLevelCBL
337
        {
338
            /// <summary>CBL:メニュー画面</summary>
339
            SceneMainMenuWithChubLip = 2,
340
341
            /// <summary>CBL:ダンス1</summary>
342
            SceneDance_DDFL_Release = 3,
343
344
            /// <summary>CBL:メイドエディット</summary>
345
            SceneEdit = 4,
346
347
            /// <summary>CBL:主人公エディット</summary>
348-
            if (Enum.IsDefined(typeof(EnableLevel), level))
348+
349
350
            /// <summary>CBL:夜伽/チュートリアル感度調整モード</summary>
351
            SceneYotogiWithChubLip = 10,
352
353
            /// <summary>CBL:ADVパート(kgスクリプト処理)</summary>
354
            SceneADV = 11,
355
356
            /// <summary>CBL:ダンス2</summary>
357
            SceneDance_ETYL_Release = 16,
358
359
            /// <summary>CBL:撮影モード</summary>
360
            ScenePhotoMode = 21
361
        }
362
363
        /// <summary>
364
        /// 男キャラやおもちゃが出現するレベル
365
        /// </summary>
366
        private enum ShowMenOrToysLevel
367
        {
368
            /// <summary>夜伽</summary>
369
            SceneYotogi = 14,
370
371
            /// <summary>ADVパート(kgスクリプト処理)</summary>
372
            SceneADV = 15,
373
374
            /// <summary>撮影モード</summary>
375
            ScenePoser = 27
376
        }
377
378
        /// <summary>
379
        /// 男キャラやおもちゃが出現するレベル ChuB-Lip
380
        /// </summary>
381
        private enum ShowMenOrToysLevelCBL
382
        {
383
            /// <summary>CBL:夜伽/チュートリアル感度調整モード</summary>
384
            SceneYotogiWithChubLip = 10,
385
386
            /// <summary>CBL:ADVパート(kgスクリプト処理)</summary>
387
            SceneADV = 11,
388
389
            /// <summary>CBL:撮影モード</summary>
390
            ScenePhotoMode = 21
391
        }
392
393
        /// <summary>
394
        /// メイドが出現するがキャラ変更や着替えを行わないレベル
395
        /// </summary>
396
        private enum NotChangeMaidsLevel
397
        {
398
            /// <summary>品評会</summary>
399
            SceneCompetitiveShow = 2,
400
401
            /// <summary>ダンス1</summary>
402
            SceneDance_DDFL = 4,
403
404
            /// <summary>MVP</summary>
405
            SceneSingleEffect = 18,
406
407
            /// <summary>ダンス2</summary>
408
            SceneDance_ETYL = 20,
409
410-
                if (Enum.IsDefined(typeof(ShowMenOrToysLevel), level))
410+
            /// <summary>ダンス3</summary>
411
            SceneDance_SL = 22,
412
413
            /// <summary>ダンス4</summary>
414
            SceneDance_SMT = 26
415
        }
416
417
        /// <summary>
418
        /// メイドが出現するがキャラ変更や着替えを行わないレベル ChuB-Lip
419
        /// </summary>
420
        private enum NotChangeMaidsLevelCBL
421
        {
422
            /// <summary>CBL:ダンス1</summary>
423
            SceneDance_DDFL_Release = 3,
424
425
            /// <summary>CBL:ダンス2</summary>
426
            SceneDance_ETYL_Release = 16
427
        }
428
429
        private ChangeBodyTexture changeBodyTexture = new ChangeBodyTexture();
430
        private DeMosaic deMosaic = new DeMosaic();
431
432
        private void LoadConfig()
433
        {
434
            IniKey changeMosaic = Preferences["DeMosaic"]["ChangeMode"];
435
            IniKey target = Preferences["DeMosaic"]["Target"];
436
            IniKey changeMosaicKey = Preferences["DeMosaic"]["HotKey"];
437
            IniKey changeTex = Preferences["ChangeTexture"]["AutoChange"];
438
            IniKey changeTexKey = Preferences["ChangeTexture"]["HotKey"];
439
440
            string dataPath = Application.dataPath;
441
            isChubLip = dataPath.Contains("CM3D2OH");
442
443
            if (changeMosaic == null || string.IsNullOrEmpty(changeMosaic.Value))
444
            {
445
                changeMosaic.Value = allowChangeMosaic.ToString();
446
                SaveConfig();
447
            }
448-
        private Shader shaderTransparent = Shader.Find("CM3D2/Toony_Lighted_Trans");
448+
449-
        private Shader shaderMosaic = Shader.Find("CM3D2/Mosaic");
449+
450
                if (!bool.TryParse(changeMosaic.Value, out allowChangeMosaic))
451
                {
452
                    changeMosaic.Value = allowChangeMosaic.ToString();
453
                    SaveConfig();
454
                }
455
            }
456
457
            if (target == null || string.IsNullOrEmpty(target.Value))
458
            {
459
                target.Value = deMosaic.Target.ToString();
460
                SaveConfig();
461
            }
462
            else
463
            {
464
                if (Enum.IsDefined(typeof(DeMosaic.Switch), target.Value))
465
                {
466
                    deMosaic.Target = (DeMosaic.Switch)Enum.Parse(typeof(DeMosaic.Switch), target.Value, true);
467
                }
468
                else
469
                {
470
                    target.Value = deMosaic.Target.ToString();
471
                    SaveConfig();
472
                }
473
            }
474
475
            if (changeMosaicKey == null || string.IsNullOrEmpty(changeMosaicKey.Value))
476
            {
477
                changeMosaicKey.Value = deMosaicHotKey.ToString();
478
                SaveConfig();
479
            }
480
            else
481
            {
482
                if (Enum.IsDefined(typeof(KeyCode), changeMosaicKey.Value))
483
                {
484
                    deMosaicHotKey = (KeyCode)Enum.Parse(typeof(KeyCode), changeMosaicKey.Value, true);
485
                }
486
                else
487
                {
488
                    changeMosaicKey.Value = deMosaicHotKey.ToString();
489
                    SaveConfig();
490
                }
491
            }
492
493
            if (changeTex == null || string.IsNullOrEmpty(changeTex.Value))
494
            {
495
                changeTex.Value = allowAutoChangeTexture.ToString();
496
                SaveConfig();
497
            }
498
            else
499
            {
500
                if (!bool.TryParse(changeTex.Value, out allowAutoChangeTexture))
501
                {
502
                    changeTex.Value = allowAutoChangeTexture.ToString();
503
                    SaveConfig();
504
                }
505
            }
506
507
            if (changeTexKey == null || string.IsNullOrEmpty(changeTexKey.Value))
508
            {
509
                changeTexKey.Value = loadTextureKey.ToString();
510
                SaveConfig();
511
            }
512
            else
513
            {
514
                if (Enum.IsDefined(typeof(KeyCode), changeTexKey.Value))
515
                {
516
                    loadTextureKey = (KeyCode)Enum.Parse(typeof(KeyCode), changeTexKey.Value, true);
517
                }
518
                else
519
                {
520
                    changeTexKey.Value = loadTextureKey.ToString();
521
                    SaveConfig();
522
                }
523
            }
524
        }
525
526
        private void Awake()
527
        {
528
            GameObject.DontDestroyOnLoad(this);
529
            System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(Console.Out));
530
531
            LoadConfig();
532
533
            StartCoroutine(GetKeyInput());
534
        }
535
536
        private void OnLevelWasLoaded(int level)
537
        {
538
            if (runningCoroutine)
539
            {
540
                System.Diagnostics.Debug.WriteLine("Demosaic Coroutine stop.");
541
                StopCoroutine(deMosaicCoroutine);
542
                StopCoroutine(changeTextureCoroutine[0]);
543
                if (allowAutoChangeTexture)
544
                {
545
                    StopCoroutine(changeTextureCoroutine[1]);
546
                }
547
                runningCoroutine = false;
548
            }
549
            
550
            if ((isChubLip && Enum.IsDefined(typeof(EnableLevelCBL), level)) || (!isChubLip && Enum.IsDefined(typeof(EnableLevel), level)))
551
            {
552
                System.Diagnostics.Debug.WriteLine("Demosaic Coroutine start.");
553
                deMosaicCoroutine = StartCoroutine(DeMosaicCoroutine(level));
554
                changeTextureCoroutine[0] = StartCoroutine(GetKeyInputForTextureChanger());
555
                if (allowAutoChangeTexture)
556
                {
557
                    changeTextureCoroutine[1] = StartCoroutine(AutoTextureChangerCoroutine());
558
                }
559
                runningCoroutine = true;
560
            }
561
        }
562
563
        private IEnumerator AutoTextureChangerCoroutine()
564
        {
565
            while (true)
566
            {
567
                yield return new WaitForSeconds(WAIT_SECOND_CHANGE_TEXTURE);
568
                changeBodyTexture.ChangeTexture(false);
569
            }
570
        }
571
572
        private IEnumerator GetKeyInputForTextureChanger()
573
        {
574
            while (true)
575
            {
576
                if (Input.GetKeyDown(loadTextureKey))
577
                {
578
                    ChangeBodyTexture.LoadTextureList(ChangeBodyTexture.textureList);
579
                    changeBodyTexture.ChangeTexture(true);
580
                }
581
                yield return null;
582
            }
583
        }
584
585
        private IEnumerator GetKeyInput()
586
        {
587
            while (true)
588
            {
589-
                UnityInjector.Extensions.UserDataPath,
589+
590
                {
591
                    deMosaic.Target++;
592
                    Console.WriteLine("YADSM Target:{0}", deMosaic.Target.ToString());
593
                }
594
                yield return null;
595
            }
596
        }
597
598
        private IEnumerator DeMosaicCoroutine(int level)
599
        {
600
            while (true)
601
            {
602
                bool result = deMosaic.DeMosaicMaids();
603
604
                if (result && !allowChangeMosaic && Enum.IsDefined(typeof(NotChangeMaidsLevel), level))
605
                {
606
                    System.Diagnostics.Debug.WriteLine("DeMosaic Coroutine Break.");
607
                    runningCoroutine = false;
608
                    yield break;
609
                }
610
                yield return null;
611
612
                if ((isChubLip && Enum.IsDefined(typeof(ShowMenOrToysLevelCBL), level)) || (!isChubLip && Enum.IsDefined(typeof(ShowMenOrToysLevel), level)))
613
                {
614
                    deMosaic.DeMosaicToys();
615
                    yield return null;
616
617
                    deMosaic.DeMosaicMen();
618
                }
619
                //System.Diagnostics.Debug.WriteLine("DeMosaic Coroutine Continue.");
620
                yield return new WaitForSeconds(WAIT_SECOND_DEMOSAIC);
621
            }
622
        }
623
624
        public void OnApplicationQuit()
625
        {
626
            Preferences["DeMosaic"]["Target"].Value = deMosaic.Target.ToString();
627
            SaveConfig();
628
        }
629
    }
630
631
    public class DeMosaic
632
    {
633
        public enum Switch
634
        {
635
            None,
636
            Maid,
637
            MaidAndItem,
638
            All,
639
            Max
640
        }
641
642
        private Switch _target = Switch.All;
643
644
        public Switch Target
645
        {
646
            get { return _target; }
647
            set { _target = value == Switch.Max ? Switch.None : value; }
648
        }
649
650
        private Shader shaderTransparent;
651
        private Shader shaderMosaic;
652
653
        private bool isChubLip = false;
654
655
        public DeMosaic() {
656
            string dataPath = Application.dataPath;
657
            isChubLip = dataPath.Contains("CM3D2OH");
658
        
659
            shaderTransparent = (isChubLip) ? Shader.Find("CM3D2CBL/Toony_Lighted_Trans") : Shader.Find("CM3D2/Toony_Lighted_Trans");
660
            shaderMosaic = (isChubLip) ? Shader.Find("CM3D2CBL/Mosaic") : Shader.Find("CM3D2/Mosaic");
661
        }
662
663
        private string getHiraerchy(Transform t)
664
        {
665
            string hiraerchy = "/" + t.name;
666-
                    get { return Path.Combine(path, Name); }
666+
667
            {
668
                t = t.parent;
669
                hiraerchy = "/" + t.name + hiraerchy;
670
            }
671
672
            return hiraerchy;
673
        }
674
675
        private Renderer[] GetMosaicRenderer(string type)
676
        {
677
            GameObject alloffset = GameObject.Find("__GameMain__/Character/Active/AllOffset");
678
            if (!alloffset)
679
            {
680
                return null;
681
            }
682
            Renderer[] mosaic = alloffset.GetComponentsInChildren<Renderer>(true)
683
                .Where(_ => _.materials.Any(m => m.name.Contains("moza")))
684
                .ToArray();
685
686
            string s;
687
688
            if (type.Equals("toy"))
689
            {
690
                return mosaic
691
                    .Where(_ => _.materials.Any(m => m.name != "moza"))
692
                    .ToArray();
693
            }
694
            else if (type.Equals("man"))
695
            {
696
                s = "Man[";
697
            }
698
            else if (type.Equals("maid"))
699
            {
700
                s = "Maid[";
701
            }
702
            else
703
            {
704
                Console.WriteLine("YASD.GetMosaicRenderer: Argument error.");
705
                return null;
706
            }
707
708
            return mosaic
709
                .Where(_ => _.name.Equals("moza"))
710
                .Where(_ => getHiraerchy(_.transform).Contains(s))
711
                .ToArray();
712
        }
713
714
        private Renderer[] GetMaidsMosaicRenderer()
715
        {
716
            return GetMosaicRenderer("maid");
717
        }
718
719
        private Renderer[] GetMenMosaicRenderer()
720
        {
721
            return GetMosaicRenderer("man");
722
        }
723
724
        private Renderer[] GetToysMosaicRenderer()
725
        {
726
            return GetMosaicRenderer("toy");
727
        }
728
729
        public bool DeMosaicMaids()
730
        {
731
            bool result = false;
732
            Renderer[] maidsMosaicList = GetMaidsMosaicRenderer();
733
734
            if (maidsMosaicList != null)
735
            {
736
                result = HumanMosaicSwitcher(maidsMosaicList, (Target == DeMosaic.Switch.None));
737
            }
738
            return result;
739
        }
740
741
        public void DeMosaicMen()
742
        {
743
            Renderer[] menMosaicList = GetMenMosaicRenderer();
744
745
            if (menMosaicList != null)
746
            {
747
                HumanMosaicSwitcher(menMosaicList, (Target != DeMosaic.Switch.All));
748
            }
749
        }
750
751
        private bool HumanMosaicSwitcher(Renderer[] mosaic, bool enableMosaic)
752
        {
753
            bool result = false;
754
            if (mosaic == null)
755
            {
756-
                list.AddRange(Directory.GetFiles(path, "*.png").Select(_ => Path.GetFileName(_)));
756+
757
            }
758
            mosaic.Where(_ => _.enabled == !enableMosaic).ForEach(_ =>
759
            {
760
                _.enabled = enableMosaic;
761
                System.Diagnostics.Debug.WriteLine(string.Format("{0}'s Mosaic Enable:{1}", _.name, enableMosaic));
762
                result = true;
763
            });
764
765
            return result;
766
        }
767
768
        public void DeMosaicToys()
769
        {
770
            Renderer[] rs = GetToysMosaicRenderer();
771
            if (rs != null)
772
            {
773
                foreach (Renderer r in rs)
774
                {
775
                    ToyMaterialChanger(r);
776
                }
777
            }
778
        }
779
780
        private void ToyMaterialChanger(Renderer mosaic)
781
        {
782
            if (mosaic.materials.Length == 1)
783
            {
784
                return;
785
            }
786
            bool mosaicDisable = Target >= DeMosaic.Switch.MaidAndItem;
787
            mosaic.materials
788
                .Where(_ => mosaicDisable ? _.shader.Equals(shaderMosaic) : _.shader.Equals(shaderTransparent))
789
                .ForEach(_ =>
790
                {
791
                    _.shader = mosaicDisable ? shaderTransparent : shaderMosaic;
792
                    _.color += mosaicDisable ? new Color(0f, 0f, 0f, -1f) : new Color(0f, 0f, 0f, 1f);
793
                });
794
        }
795
    }
796
797
    public class ChangeBodyTexture
798
    {
799
        public static List<string> textureList;
800
            public static readonly string path = Path.Combine(
801
                UnityExtensionsBridge.UserDataPath,
802
                "YASD"
803
                );
804
805
        public ChangeBodyTexture()
806
        {
807
            if (!Directory.Exists(path))
808
            {
809
                Directory.CreateDirectory(path);
810
            }
811
812
            textureList = new List<string>();
813
            LoadTextureList(textureList);
814
#if DEBUG
815
            foreach (var item in textureList)
816
            {
817
                System.Diagnostics.Debug.WriteLine(item);
818
            }
819
#endif
820
        }
821
822
        public class TextureSet
823
        {
824
825
            private const string diffuseType = "_MainTex";
826
            private const string toonType = "_ToonRamp";
827
            private const string shadowType = "_ShadowTex";
828
            private const string shadowRateToonType = "_ShadowRateToon";
829
830
            public Tex MainTex;
831
            public Tex Toon;
832
            public Tex Shadow;
833
            public Tex ShadowRateToon;
834
835
            public TextureSet(Material material, bool force)
836
            {
837
                MainTex = new Tex(diffuseType, material);
838
                if (!MainTex.IsReplaced || force)
839
                {
840
                    Toon = new Tex(toonType, material);
841
                    Shadow = new Tex(shadowType, material);
842
                    ShadowRateToon = new Tex(shadowRateToonType, material);
843
                }
844
            }
845
846
            public class Tex
847
            {
848
                private readonly Regex rx = new Regex(@"(?<name>[^:]+)\.tex");
849
850
                private Material material;
851
852
                private string _type;
853
854
                public string Type
855
                {
856
                    get { return _type; }
857
                }
858
859
                private Texture _texture;
860
861
                public Texture Texture
862
                {
863
                    get { return _texture; }
864
                }
865
866
                private string _name;
867
868
                public string Name
869
                {
870
                    get
871
                    {
872
                        return _name;
873
                    }
874
                }
875
876
                public string FullPath
877
                {
878
                    get {
879
                        String fullPath = Directory.GetFiles(path, Name, SearchOption.AllDirectories).First();
880
#if DEBUG
881
                        Console.WriteLine(fullPath);
882
#endif
883
                        return fullPath;
884
                    }
885
                }
886
887
                public bool IsReplaced
888
                {
889
                    get { return Path.GetExtension(Texture.name).Equals(".png", System.StringComparison.OrdinalIgnoreCase); }
890
                }
891
892
                public Tex(String textureType, Material mate)
893
                {
894
                    this.material = mate;
895
                    _type = textureType;
896
                    _texture = material.GetTexture(Type);
897
                    Match m = rx.Match(this._texture.name);
898
                    if (m.Success)
899
                    {
900
                        _name = m.Groups["name"].Value + ".png";
901
                    }
902
                    else
903
                    {
904
                        _name = Texture.name;
905
                    }
906
                }
907
908
                public void ReplaceTex()
909
                {
910
                    System.Diagnostics.Debug.WriteLine(string.Format("YASD.ReplaceTex: Texture Name {0}", Texture.name));
911
//                    Console.WriteLine("YASD: hoge 1 {0} , {1}", Name, Texture.name);
912
                    if (!textureList.Any(_ => _.Equals(Name, StringComparison.OrdinalIgnoreCase)))
913
                    {
914
                        System.Diagnostics.Debug.WriteLine("YASD.ReplaceTex: FileName not Found in FileList");
915
                        return;
916
                    }
917
                    if (!Texture)
918
                    {
919
                        System.Diagnostics.Debug.WriteLine("YASD.ReplaceTex: Texture is NULL.");
920
921
                        return;
922
                    }
923
                    if (string.IsNullOrEmpty(Name))
924
                    {
925
                        System.Diagnostics.Debug.WriteLine("YASD.ReplaceTex: Texture's Name is NULL or Empty.");
926
                        return;
927
                    }
928
929
                    try
930
                    {
931
                        if (!File.Exists(FullPath))
932
                        {
933
                            textureList.Remove(Name);
934
                            return;
935
                        }
936
                        System.Diagnostics.Debug.WriteLine(string.Format("YASD.ReplaceTex: {0} found.", Name));
937
938
                        using (BinaryReader br = new BinaryReader(File.OpenRead(FullPath)))
939
                        {
940
                            byte[] b = br.ReadBytes((int)br.BaseStream.Length);
941
942
                            Texture2D t = new Texture2D(1, 1, TextureFormat.RGBA32, false);
943
944
                            if (t.LoadImage(b))
945
                            {
946
                                t.name = Name;
947
                                material.SetTexture(Type, t);
948
                                System.Diagnostics.Debug.WriteLine(string.Format("YASD.ReplaceTex: {0} Replaced.", Name));
949
                            }
950
                        }
951
                    }
952
                    catch (Exception ex)
953
                    {
954
                        Console.WriteLine("YASD.ReplaceTex: Texture Replace Fail!{0} ({1})", Name, ex);
955
                        textureList.Remove(Name);
956
                    }
957
                }
958
            }
959
960
            public void ReplaceTexture(bool force)
961
            {
962
                if (!MainTex.IsReplaced || force)
963
                {
964
                    MainTex.ReplaceTex();
965
                    Toon.ReplaceTex();
966
                    Shadow.ReplaceTex();
967
                    ShadowRateToon.ReplaceTex();
968
                }
969
            }
970
971
        }
972
            public static void LoadTextureList(List<string> list)
973
            {
974
                list.Clear();
975
                list.AddRange(Directory.GetFiles(path, "*.png", SearchOption.AllDirectories).Select(_ => Path.GetFileName(_)));
976
977
                Console.WriteLine("YASD: {0} Texture(s) found.", list.Count);
978
#if DEBUG
979
                foreach (string file in list)
980
                {
981
                    Console.WriteLine(file);
982
                }
983
#endif
984
            }
985
986
        public void ChangeTexture(bool force)
987
        {
988
            GameObject maid = GameMain.Instance.CharacterMgr.GetMaid(0).gameObject;
989
            GameObject body = maid.transform.Find("Offset/_BO_body001/_SM_body001/body").gameObject;
990
            Material[] materials = body.renderer.materials;
991
992
            ////GetMaterialsの方がゲーム内で使われている手法に近くて汎用性が高いが1.5倍ぐらい遅い
993
            //Maid md = GameMain.Instance.CharacterMgr.GetMaid(0);
994
            //Material[] materials = GetMaterials(md, "body");
995
996
            foreach (var material in materials)
997
            {
998
                TextureSet tex = new TextureSet(material, force);
999
1000
                if (Directory.Exists(path))
1001
                {
1002
                    tex.ReplaceTexture(force);
1003
                }
1004
            }
1005
        }
1006
1007
        public Material[] GetMaterials(Maid maid, string slotname)
1008
        {
1009
            TBody tbody = maid.body0;
1010
            TBodySkin skin = tbody.goSlot[(int)TBody.hashSlotName[slotname]];
1011
            GameObject go = skin.obj;
1012
1013
            Renderer[] renderers = go.transform.GetComponentsInChildren<Renderer>(true);
1014
1015
            return renderers.Where(_ => _ != null || _.sharedMaterials != null).SelectMany(_ => _.materials).ToArray();
1016
        }
1017
    }
1018
}