Skip to content

Commit

Permalink
feat: vrc integration editor (partial) (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
poi-vrc authored Aug 23, 2023
1 parent 5102196 commit bd67d08
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Chocopoi.AvatarLib.Expressions;
using Chocopoi.DressingTools.Animations;
using Chocopoi.DressingTools.Cabinet;
using Chocopoi.DressingTools.Integration.VRChat.Modules;
using Chocopoi.DressingTools.Lib.Logging;
using Chocopoi.DressingTools.Lib.Wearable;
using Chocopoi.DressingTools.Logging;
Expand Down Expand Up @@ -57,8 +58,6 @@ public bool OnPreprocessAvatar()
// obtain FX layer
var fxController = CopyAndReplaceLayerAnimator(avatarDescriptor, VRCAvatarDescriptor.AnimLayerType.FX);

// TODO: these operations are just temporary for testing, need rework to do exception catching etc

EditorUtility.DisplayProgressBar("DressingTools", "Removing old animator layers and parameters...", 0);
AnimationUtils.RemoveAnimatorLayers(fxController, "^cpDT_Cabinet");
AnimationUtils.RemoveAnimatorParameters(fxController, "^cpDT_Cabinet");
Expand Down Expand Up @@ -135,29 +134,37 @@ public bool OnPreprocessAvatar()
continue;
}

// obtain module
var vrcm = DTRuntimeUtils.FindWearableModuleConfig<VRChatIntegrationModuleConfig>(config);
if (vrcm == null)
{
// use default settings if no module
vrcm = new VRChatIntegrationModuleConfig();
}

EditorUtility.DisplayProgressBar("DressingTools", "Generating animations for " + config.Info.name + "...", i / (float)wearables.Length * 100);
var wearableDynamics = DTRuntimeUtils.ScanDynamics(wearables[i].wearableGameObject, false);

// find the animation generation module
var module = DTRuntimeUtils.FindWearableModuleConfig<AnimationGenerationModuleConfig>(config);
if (module == null)
var agm = DTRuntimeUtils.FindWearableModuleConfig<AnimationGenerationModuleConfig>(config);
if (agm == null)
{
Debug.Log("[DressingTools] [BuildDTCabinetCallback] [GenerateAnimationHook] " + config.Info.name + " has no AnimationGenerationModule, skipping this wearable generation");
continue;
}

var animationGenerator = new AnimationGenerator(_report, _cabinet.AvatarGameObject, module, wearables[i].wearableGameObject, wearableDynamics);
var animationGenerator = new AnimationGenerator(_report, _cabinet.AvatarGameObject, agm, wearables[i].wearableGameObject, wearableDynamics);

// TODO: write defaults settings
var wearAnimations = animationGenerator.GenerateWearAnimations(true);
// TODO: merge disable clips and check for conflicts
var wearAnimations = animationGenerator.GenerateWearAnimations(_cabinet.AnimationGenerationWriteDefaults);
pairs.Add(i + 1, wearAnimations.Item1); // enable clip
AssetDatabase.CreateAsset(wearAnimations.Item1, BuildDTCabinetCallback.GeneratedAssetsPath + "/cpDT_" + wearables[i].name + ".anim");

// generate expression menu
subMenu.AddToggle(config.Info.name, "cpDT_Cabinet", i + 1);
subMenu.AddToggle(vrcm.customCabinetToggleName ?? config.Info.name, "cpDT_Cabinet", i + 1);
}

AnimationUtils.GenerateAnyStateLayer(fxController, "cpDT_Cabinet", "cpDT_Cabinet", pairs, true, null, refTransition);
AnimationUtils.GenerateAnyStateLayer(fxController, "cpDT_Cabinet", "cpDT_Cabinet", pairs, _cabinet.AnimationGenerationWriteDefaults, null, refTransition);

EditorUtility.DisplayProgressBar("DressingTools", "Generating expression menu...", 0);
subMenu.CreateAsset(BuildDTCabinetCallback.GeneratedAssetsPath + "/cpDT_Cabinet.asset")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* File: IVRChatIntegrationModuleEditorView.cs
* Project: DressingTools
* Created Date: Wednesday, August 23th 2023, 7:56:36 pm
* Author: chocopoi ([email protected])
* -----
* Copyright (c) 2023 chocopoi
*
* This file is part of DressingTools.
*
* DressingTools is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* DressingTools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DressingTools. If not, see <https://www.gnu.org/licenses/>.
*/

using System;
using Chocopoi.DressingTools.Lib.UI;
using UnityEngine;

namespace Chocopoi.DressingTools.Integrations.VRChat
{
internal interface IVRChatIntegrationModuleEditorView : IEditorView
{
event Action ConfigChange;

bool UseCustomCabinetToggleName { get; set; }
string CustomCabinetToggleName { get; set; }
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* File: VRChatIntegrationModuleEditor.cs
* Project: DressingTools
* Created Date: Wednesday, August 23th 2023, 7:56:36 pm
* Author: chocopoi ([email protected])
* -----
* Copyright (c) 2023 chocopoi
*
* This file is part of DressingTools.
*
* DressingTools is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* DressingTools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DressingTools. If not, see <https://www.gnu.org/licenses/>.
*/

using System;
using System.Diagnostics.CodeAnalysis;
using Chocopoi.DressingTools.Integration.VRChat.Modules;
using Chocopoi.DressingTools.Lib.UI;
using Chocopoi.DressingTools.Lib.Wearable.Modules;
using Chocopoi.DressingTools.UI.Presenters.Modules;
using Chocopoi.DressingTools.UIBase.Views;
using Chocopoi.DressingTools.Wearable.Modules;
using UnityEditor;
using UnityEngine;

namespace Chocopoi.DressingTools.Integrations.VRChat
{
[ExcludeFromCodeCoverage]
[CustomModuleEditor(typeof(VRChatIntegrationModuleProvider))]
internal class VRChatIntegrationModuleEditor : ModuleEditor, IVRChatIntegrationModuleEditorView
{
public event Action ConfigChange;

public bool UseCustomCabinetToggleName { get => _useCustomCabinetToggleName; set => _useCustomCabinetToggleName = value; }
public string CustomCabinetToggleName { get => _customCabinetToggleName; set => _customCabinetToggleName = value; }

private IModuleEditorViewParent _parentView;
private VRChatIntegrationModuleEditorPresenter _presenter;

private bool _useCustomCabinetToggleName;
private string _customCabinetToggleName;

public VRChatIntegrationModuleEditor(IModuleEditorViewParent parentView, VRChatIntegrationModuleProvider provider, IModuleConfig target) : base(parentView, provider, target)
{
_parentView = parentView;
_presenter = new VRChatIntegrationModuleEditorPresenter(this, parentView, (VRChatIntegrationModuleConfig)target);

_useCustomCabinetToggleName = false;
}

public override void OnGUI()
{
ToggleLeft("Use custom cabinet toggle name", ref _useCustomCabinetToggleName, ConfigChange);
BeginDisabled(!_useCustomCabinetToggleName);
{
EditorGUI.indentLevel += 1;
TextField("Toggle Name", ref _customCabinetToggleName, ConfigChange);
EditorGUI.indentLevel -= 1;
}
EndDisabled();
}

public override bool IsValid() => _presenter.IsValid();
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* File: VRChatIntegrationModuleEditorPresenter.cs
* Project: DressingTools
* Created Date: Wednesday, August 23th 2023, 7:56:36 pm
* Author: chocopoi ([email protected])
* -----
* Copyright (c) 2023 chocopoi
*
* This file is part of DressingTools.
*
* DressingTools is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* DressingTools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DressingTools. If not, see <https://www.gnu.org/licenses/>.
*/

using Chocopoi.DressingTools.Integration.VRChat.Modules;
using Chocopoi.DressingTools.Lib.UI;
using Chocopoi.DressingTools.UIBase.Views;
using Chocopoi.DressingTools.Wearable.Modules;

namespace Chocopoi.DressingTools.Integrations.VRChat
{
internal class VRChatIntegrationModuleEditorPresenter
{
private IVRChatIntegrationModuleEditorView _view;
private IModuleEditorViewParent _parentView;
private VRChatIntegrationModuleConfig _module;

public VRChatIntegrationModuleEditorPresenter(IVRChatIntegrationModuleEditorView view, IModuleEditorViewParent parentView, VRChatIntegrationModuleConfig module)
{
_view = view;
_parentView = parentView;
_module = module;

SubscribeEvents();
}

private void SubscribeEvents()
{
_view.Load += OnLoad;
_view.Unload += OnUnload;

_view.ForceUpdateView += OnForceUpdateView;
_view.ConfigChange += OnConfigChange;
}

private void UnsubscribeEvents()
{
_view.Load -= OnLoad;
_view.Unload -= OnUnload;

_view.ForceUpdateView -= OnForceUpdateView;
_view.ConfigChange -= OnConfigChange;
}

private void OnForceUpdateView()
{
UpdateView();
}

private void OnConfigChange()
{
_module.customCabinetToggleName = _view.UseCustomCabinetToggleName ? _view.CustomCabinetToggleName : null;
}

public bool IsValid()
{
return _module.customCabinetToggleName != null ? _module.customCabinetToggleName.Trim() != "" : true;
}

private void UpdateView()
{
if (_module.customCabinetToggleName != null)
{
_view.UseCustomCabinetToggleName = true;
_view.CustomCabinetToggleName = _module.customCabinetToggleName;
}
else
{
_view.UseCustomCabinetToggleName = false;
_view.CustomCabinetToggleName = "";
}
}

private void OnLoad()
{
UpdateView();
}

private void OnUnload()
{
UnsubscribeEvents();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public interface ICabinet

bool GroupDynamicsSeparateGameObjects { get; set; }

bool AnimationGenerationWriteDefaults { get; set; }

DTCabinetWearable[] GetWearables();

void Apply(DTReport report);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class DTCabinet : DTBaseComponent, ICabinet
[field: SerializeField] public string AvatarArmatureName { get; set; }
[field: SerializeField] public bool GroupDynamics { get; set; }
[field: SerializeField] public bool GroupDynamicsSeparateGameObjects { get; set; }
[field: SerializeField] public bool AnimationGenerationWriteDefaults { get; set; }

public DTCabinet()
{
Expand All @@ -41,6 +42,7 @@ public DTCabinet()
AvatarArmatureName = "Armature";
GroupDynamics = true;
GroupDynamicsSeparateGameObjects = true;
AnimationGenerationWriteDefaults = true;
}

public DTCabinetWearable[] GetWearables()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ namespace Chocopoi.DressingTools.Integration.VRChat.Modules
{
internal class VRChatIntegrationModuleConfig : IModuleConfig
{
public string customCabinetToggleName;

public VRChatIntegrationModuleConfig()
{
customCabinetToggleName = null;
}
}

[InitializeOnLoad]
Expand Down

0 comments on commit bd67d08

Please sign in to comment.