• The forum has been updated. For an explanation of some of the changes, head over here.

[RESOLVED] GauntletUI questions during Character Creation

Currently viewing this thread:

guiskj

Sergeant at Arms
I have three questions regarding the GauntletUI in Character Creation:

1 - How are you supposed to add Layers to those screens?? I am trying to add some extra functionality to the FaceGenBody.xml window but so far no luck.
Behaviour class:
C#:
public class CharacterGenPresetBehavior : CampaignBehaviorBase
    {
        private GauntletLayer _layer;

        public override void RegisterEvents()
        {
            CampaignEvents.OnNewGameCreatedEvent.AddNonSerializedListener(this, OnNewGameCreated);
        }

        private void OnNewGameCreated(CampaignGameStarter starter)
        {
            _layer = new CharacterGenPresetLayer(10000);
            ScreenManager.TopScreen.AddLayer(_layer);
        }

        public override void SyncData(IDataStore dataStore) { }
    }
Layer and ViewModel classes
C#:
    public class CharacterGenPresetLayer : GauntletLayer
    {
        public CharacterGenPresetLayer(int localOrder, string categoryId = "GauntletLayer") : base(localOrder, categoryId)
        {
            var viewModel = new CharacterGenPresetViewModel();
            LoadMovie("CharacterGenPreset", viewModel);
            Utils.Logger.Log("CharacterGenPresetViewModel Created");
        }
    }

    class CharacterGenPresetViewModel : ViewModel
    {
        [DataSourceProperty]
        public string TestingCharGenPresetText{ get => "Testing"; }

        public override void RefreshValues()
        {
            base.RefreshValues();

            Utils.Logger.Log("CharacterGenPresetViewModel Refresh");
        }
    }
GauntletUI
XML:
<?xml version="1.0" encoding="utf-8" ?>
<Prefab>
  <Constants />
  <VisualDefinitions>
  </VisualDefinitions>
  <Window>
    <Widget DoNotAcceptEvents="true" WidthSizePolicy="StretchToParent" HeightSizePolicy="StretchToParent">
      <Children>

        <TextWidget WidthSizePolicy="CoverChildren" HeightSizePolicy="CoverChildren" HorizontalAlignment="Center" VerticalAlignment="Center" Brush="FaceGen.Property.Text" Text="@TestingCharGenPresetText" ClipContents="false"/>

      </Children>
    </Widget>
  </Window>
</Prefab>

2. How can I detect when screens change so I know when to add my layer? I have tried looking into `Game.Current.EventManager.RegisterEvent`, `CampaignEvents` and `ScreenManager` but nothing fits the bill.


I would really prefer not to have to resort to Harmony patches to change those screens since we had a whole Dev Diary that talked about how awesome and easy it was to mod game screens with GauntletUI...


Thanks in advance for any help.
 

guiskj

Sergeant at Arms
Also, if anyone knows where in the code is the logic that handles CTRL+C / CTRL+V for the character creation screen, please let me know.
 

guiskj

Sergeant at Arms
OK, I found a solution. It involved Harmony, which is what I was trying to avoid, but I think I have figured out a way to be as minimally invasive as possible.

Since I could not find a native event that would tell me how the Player was advancing through the character generation screens, I created my own custom events. Then I used Harmony to fire those events at the right time.

Here is the result.

FaceGenVM Patch
C#:
    [HarmonyPatch(typeof(FaceGenVM))]
    class FaceGenVMPatch
    {
        [HarmonyPostfix]
        [HarmonyPatch(MethodType.Constructor, new Type[] { typeof(BodyGenerator), typeof(IFaceGeneratorHandler), typeof(Action<float>), typeof(Action), typeof(TextObject), typeof(TextObject), typeof(int), typeof(int), typeof(int), typeof(Action<int>), typeof(bool), typeof(bool), typeof(IFaceGeneratorCustomFilter) })]
        static void ConstructorPostfix()
        {
            Game.Current.EventManager.TriggerEvent(new FaceGenVMCustomEventOn());
        }

        [HarmonyPostfix]
        [HarmonyPatch("OnTabClicked")]
        static void OnTabClickedPostfix(int index)
        {
            if (index == 0)
                Game.Current.EventManager.TriggerEvent(new FaceGenVMCustomEventOn());
            else
                Game.Current.EventManager.TriggerEvent(new FaceGenVMCustomEventOff());
        }

        [HarmonyPostfix]
        [HarmonyPatch("ExecuteCancel")]
        static void ExecuteCancelPostfix()
        {
            Game.Current.EventManager.TriggerEvent(new FaceGenVMCustomEventOff());
        }

        [HarmonyPostfix]
        [HarmonyPatch("ExecuteDone")]
        static void ExecuteDonePostfix()
        {
            Game.Current.EventManager.TriggerEvent(new FaceGenVMCustomEventOff());
        }
    }

My Layer remained the same.

Updated Behavior
C#:
    public class CharacterGenPresetBehavior : CampaignBehaviorBase
    {
        private GauntletLayer _layer;

        public override void RegisterEvents()
        {
            Game.Current.EventManager.RegisterEvent(new Action<FaceGenVMCustomEventOn>(AddLayer));
            Game.Current.EventManager.RegisterEvent(new Action<FaceGenVMCustomEventOff>(RemoveLayer));
        }

        private void AddLayer(FaceGenVMCustomEventOn customEvent)
        {
            _layer = new CharacterGenPresetLayer(10);
            ScreenManager.TopScreen.AddLayer(_layer);
        }

        private void RemoveLayer(FaceGenVMCustomEventOff customEvent)
        {
            ScreenManager.TopScreen?.RemoveLayer(_layer);
        }

        public override void SyncData(IDataStore dataStore) { }
    }
 
Top Bottom