Skip to content

Commit

Permalink
[KK/KKS] Add HairShadowColorControl plugin (#219)
Browse files Browse the repository at this point in the history
Convenient controls for changing the shadow color of character hair in maker. Uses ME underneath.
  • Loading branch information
ManlyMarco authored Jan 17, 2024
1 parent 33a48c1 commit 8de9323
Show file tree
Hide file tree
Showing 9 changed files with 519 additions and 0 deletions.
22 changes: 22 additions & 0 deletions KK_Plugins.sln
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AI.AccessoriesToStudioItems
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HS2.AccessoriesToStudioItems", "src\AccessoriesToStudioItems.HS2\HS2.AccessoriesToStudioItems.csproj", "{D6B32AEB-1431-432E-932D-AF0E30D2EB9F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HairShadowColorControl", "HairShadowColorControl", "{267C92B3-1324-448C-A699-B0A3A4D6A1A7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KKS.HairShadowColorControl", "src\HairShadowColorControl.KKS\KKS.HairShadowColorControl.csproj", "{0FF15905-4A4E-43EE-9853-F410F0A63876}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KK.HairShadowColorControl", "src\HairShadowColorControl.KK\KK.HairShadowColorControl.csproj", "{25C47673-7B6A-4127-9E47-237B3CA991FB}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Core.HairShadowColorControl", "src\HairShadowColorControl.Core\Core.HairShadowColorControl.shproj", "{30F7FDB4-A1B8-41B9-8D74-E82E3099E555}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1263,6 +1271,14 @@ Global
{D6B32AEB-1431-432E-932D-AF0E30D2EB9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6B32AEB-1431-432E-932D-AF0E30D2EB9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6B32AEB-1431-432E-932D-AF0E30D2EB9F}.Release|Any CPU.Build.0 = Release|Any CPU
{0FF15905-4A4E-43EE-9853-F410F0A63876}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FF15905-4A4E-43EE-9853-F410F0A63876}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FF15905-4A4E-43EE-9853-F410F0A63876}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FF15905-4A4E-43EE-9853-F410F0A63876}.Release|Any CPU.Build.0 = Release|Any CPU
{25C47673-7B6A-4127-9E47-237B3CA991FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25C47673-7B6A-4127-9E47-237B3CA991FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25C47673-7B6A-4127-9E47-237B3CA991FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25C47673-7B6A-4127-9E47-237B3CA991FB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1492,6 +1508,9 @@ Global
{DC93DDEC-8CD0-42F4-905E-6550659CCA85} = {F4AD3F74-B97B-40BF-AD1B-92FFE7A428FC}
{BE3DEE42-3526-42F9-9C2F-9D57BD43A078} = {F4AD3F74-B97B-40BF-AD1B-92FFE7A428FC}
{D6B32AEB-1431-432E-932D-AF0E30D2EB9F} = {F4AD3F74-B97B-40BF-AD1B-92FFE7A428FC}
{0FF15905-4A4E-43EE-9853-F410F0A63876} = {267C92B3-1324-448C-A699-B0A3A4D6A1A7}
{25C47673-7B6A-4127-9E47-237B3CA991FB} = {267C92B3-1324-448C-A699-B0A3A4D6A1A7}
{30F7FDB4-A1B8-41B9-8D74-E82E3099E555} = {267C92B3-1324-448C-A699-B0A3A4D6A1A7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D0F79985-4CB7-46CB-BEC2-FF89C476ED20}
Expand All @@ -1512,6 +1531,7 @@ Global
src\AccessoryQuickRemove.Core\AccessoryQuickRemove.Core.projitems*{0cd64f6f-4e15-4c9c-a990-4616a8a8ea82}*SharedItemsImports = 4
src\Shared\Shared.projitems*{0cd64f6f-4e15-4c9c-a990-4616a8a8ea82}*SharedItemsImports = 4
src\ClothingUnlocker.Core\Core.ClothingUnlocker.projitems*{0f7181c7-8d52-4576-9bff-d4b7d08f42a2}*SharedItemsImports = 13
src\HairShadowColorControl.Core\HairShadowColorControl.Core.projitems*{0ff15905-4a4e-43ee-9853-f410f0a63876}*SharedItemsImports = 4
src\MaleJuice.Core\MaleJuice.Core.projitems*{11112067-cfa0-4522-be2e-0c4d1cf9e36a}*SharedItemsImports = 4
src\Shared\Shared.projitems*{11112067-cfa0-4522-be2e-0c4d1cf9e36a}*SharedItemsImports = 4
src\ForceHighPoly.Core\ForceHighPoly.Core.projitems*{123d12ea-5526-4d07-ab26-7ab9459b4aeb}*SharedItemsImports = 4
Expand Down Expand Up @@ -1563,6 +1583,7 @@ Global
src\Shared\Shared.projitems*{255b5bf8-80ff-49ea-b4fb-7b535e8c6062}*SharedItemsImports = 4
src\Shared\Shared.projitems*{2566acd4-b07d-4feb-aa9c-4cd1751e97fc}*SharedItemsImports = 4
src\StudioSceneLoadedSound.Core\Core.StudioSceneLoadedSound.projitems*{2566acd4-b07d-4feb-aa9c-4cd1751e97fc}*SharedItemsImports = 4
src\HairShadowColorControl.Core\HairShadowColorControl.Core.projitems*{25c47673-7b6a-4127-9e47-237b3ca991fb}*SharedItemsImports = 4
src\MaterialEditor.Base\MaterialEditor.Base.projitems*{25e45f23-4d1d-4cd0-b0bc-653c8ae1c561}*SharedItemsImports = 4
src\MaterialEditor.Core.Maker\Core.MaterialEditor.Maker.projitems*{25e45f23-4d1d-4cd0-b0bc-653c8ae1c561}*SharedItemsImports = 4
src\MaterialEditor.Core\Core.MaterialEditor.projitems*{25e45f23-4d1d-4cd0-b0bc-653c8ae1c561}*SharedItemsImports = 4
Expand All @@ -1574,6 +1595,7 @@ Global
src\ItemBlacklist.Core\ItemBlacklist.Core.projitems*{3078a5da-7330-469c-ad65-7f6f2619fad7}*SharedItemsImports = 4
src\Shared\Shared.projitems*{3078a5da-7330-469c-ad65-7f6f2619fad7}*SharedItemsImports = 4
src\UIUtility\UIUtility.projitems*{3078a5da-7330-469c-ad65-7f6f2619fad7}*SharedItemsImports = 4
src\HairShadowColorControl.Core\HairShadowColorControl.Core.projitems*{30f7fdb4-a1b8-41b9-8d74-e82e3099e555}*SharedItemsImports = 13
src\PoseQuickLoad.Core\Core.PoseQuickLoad.projitems*{35366d0f-99f5-47a4-bc14-db50b58e7ef7}*SharedItemsImports = 4
src\Shared\Shared.projitems*{35366d0f-99f5-47a4-bc14-db50b58e7ef7}*SharedItemsImports = 4
src\MakerDefaults.Core.AIHS2\MakerDefaults.Core.projitems*{35cf8f9c-ec35-49b6-b9e1-c1691771a49e}*SharedItemsImports = 4
Expand Down
14 changes: 14 additions & 0 deletions src/HairShadowColorControl.Core/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Reflection;
using System.Runtime.InteropServices;
using HairShadowColorControl;

[assembly: AssemblyTitle(HairShadowColorControlPlugin.GUID)]
[assembly: AssemblyDescription(HairShadowColorControlPlugin.DisplayName)]
[assembly: AssemblyCompany("https://github.com/IllusionMods/KK_Plugins/")]
[assembly: AssemblyProduct(HairShadowColorControlPlugin.DisplayName)]
[assembly: AssemblyCopyright("Copyright © 2024")]

[assembly: ComVisible(false)]
[assembly: Guid("0ff15905-4a4e-43ee-9853-f410f0a63876")]

[assembly: AssemblyVersion(HairShadowColorControlPlugin.Version)]
13 changes: 13 additions & 0 deletions src/HairShadowColorControl.Core/Core.HairShadowColorControl.shproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>30f7fdb4-a1b8-41b9-8d74-e82e3099e555</ProjectGuid>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<PropertyGroup />
<Import Project="HairShadowColorControl.Core.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>30f7fdb4-a1b8-41b9-8d74-e82e3099e555</SharedGUID>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<Import_RootNamespace>HairShadowColorControl.Core</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)AssemblyInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HairShadowColorControlPlugin.cs" />
</ItemGroup>
</Project>
147 changes: 147 additions & 0 deletions src/HairShadowColorControl.Core/HairShadowColorControlPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using System;
using BepInEx;
using ChaCustom;
using HarmonyLib;
using KK_Plugins.MaterialEditor;
using KKAPI.Maker;
using KKAPI.Maker.UI;
using UniRx;
using UnityEngine;

namespace HairShadowColorControl
{
[BepInPlugin(GUID, DisplayName, Version)]
[BepInDependency(KKAPI.KoikatuAPI.GUID, KKAPI.KoikatuAPI.VersionConst)]
public class HairShadowColorControlPlugin : BaseUnityPlugin
{
public const string GUID = "HairShadowColorControl";
public const string Version = "1.0";
internal const string DisplayName = "HairShadowColorControl";

private const string ShadowColorPropertyName = "ShadowColor";
private static readonly Color _DefaultColor = new Color(0.83f, 0.87f, 0.94f);

private static MakerColor[] _customControls;
private static ChaControl _charaController;
private static MaterialEditorCharaController _meController;

private void Awake()
{
MakerAPI.MakerStartedLoading += MakerLoading;
MakerAPI.ReloadCustomInterface += MakerRefresh;

Harmony.CreateAndPatchAll(typeof(Hooks), GUID);
}

private void MakerLoading(object sender, RegisterCustomControlsEvent args)
{
var makerBase = MakerAPI.GetMakerBase();

_charaController = MakerAPI.GetCharacterControl();
_meController = _charaController.GetComponent<MaterialEditorCharaController>();

// Lines up with how hair parts are indexed
var hairKinds = new[] { MakerConstants.Hair.Back, MakerConstants.Hair.Front, MakerConstants.Hair.Side, MakerConstants.Hair.Extension };
_customControls = new MakerColor[hairKinds.Length];
for (var hairKind = 0; hairKind < hairKinds.Length; hairKind++)
{
var makerCategory = hairKinds[hairKind];
var hairType = (CvsHair.HairType)hairKind;
var control = args.AddControl(new MakerColor("Hair shadow color", false, makerCategory, _DefaultColor, this) { GroupingID = null });
control.ValueChanged.Subscribe(color =>
{
if (!MakerAPI.InsideAndLoaded) return;

var chaCtrl = MakerAPI.GetCharacterControl();

if (makerBase.customSettingSave.hairSameSetting)
{
for (var i = 0; i < _customControls.Length; i++)
{
SetShadowColor(chaCtrl, color, (CvsHair.HairType)i);
_customControls[i].SetValue(color, false);
}
}
else
{
SetShadowColor(chaCtrl, color, hairType);
}
});
_customControls[hairKind] = control;
}
}

private static void SetShadowColor(ChaControl chaCtrl, Color color, CvsHair.HairType kind)
{
var me = chaCtrl.GetComponent<MaterialEditorCharaController>();

var rend = chaCtrl.GetCustomHairComponent((int)kind);
if (rend != null && rend.rendHair != null)
{
foreach (var r in rend.rendHair)
me.SetMaterialColorProperty((int)kind, MaterialEditorCharaController.ObjectType.Hair, r.material, ShadowColorPropertyName, color, rend.gameObject);
}
}

private static void MakerRefresh(object sender, EventArgs e)
{
for (var hairPart = 0; hairPart < _customControls.Length; hairPart++)
UpdateSliderValue(hairPart);
}

private static void UpdateSliderValue(int hairPart)
{
if (!MakerAPI.InsideMaker) return;

// Figure out current color to show in the color control
Color? setColor = null, originColor = null, currentColor = null;
var any = false;
var rendHair = _charaController.GetCustomHairComponent(hairPart)?.rendHair;
if (rendHair != null)
{
foreach (var renderer in rendHair)
{
if (renderer == null) continue;
any = true;

setColor = _meController.GetMaterialColorPropertyValue(hairPart, MaterialEditorCharaController.ObjectType.Hair, renderer.material, ShadowColorPropertyName, renderer.gameObject);
if (setColor.HasValue) break;

if (originColor.HasValue) continue;
originColor = _meController.GetMaterialColorPropertyValueOriginal(hairPart, MaterialEditorCharaController.ObjectType.Hair, renderer.material, ShadowColorPropertyName, renderer.gameObject);

if (currentColor.HasValue) continue;
currentColor = renderer.material.GetColor("_" + ShadowColorPropertyName);
}
}
var color = setColor ?? originColor ?? currentColor ?? _DefaultColor;
// Alpha is ignored by shaders and can be 0 making it invisible in the color picker
color.a = 1;

var customControl = _customControls[hairPart];
customControl.SetValue(color, false);

// If there are no renderers then the control should be hidden like base game color controls
if (customControl.Visible.Value != any)
customControl.Visible.OnNext(any);
}

private static class Hooks
{
[HarmonyPostfix]
[HarmonyPatch(typeof(CvsHair), nameof(CvsHair.UpdateSelectHair))]
private static void UpdateHairUi(CvsHair __instance)
{
// Problem is that if user changes hair type then shadow color is lost
// Update the slider to show the color of the newly loaded hair type
UpdateSliderValue(__instance.hairType);

// doesn't work, no obvious way to tell if this is a card load or user ui click (breaks card load)
//var makerColor = _customControls[__instance.hairType];
//var value = makerColor.Value;
//makerColor.SetValue(Color.magenta, false);
//makerColor.SetValue(value, true);
}
}
}
}
Loading

0 comments on commit 8de9323

Please sign in to comment.