Ejemplo n.º 1
0
        private static void RegisterCustomSubCategories(object sender, RegisterSubCategoriesEvent e)
        {
            if (MakerAPI.GetMakerSex() == 0)
            {
                var category = MakerConstants.Parameter.Character;

                _toggleEnabled = e.AddControl(new MakerToggle(category, "Character is a trap or a futa (changes gameplay)", BecomeTrap.Instance));
                _toggleEnabled.ValueChanged.Subscribe(val => GetMakerController().IsTrap = val);

                _animType = e.AddControl(new MakerDropdown("Idle trap animation", _idleAnimations.Select(x => x.Value).ToArray(), category, 0, BecomeTrap.Instance));
                _animType.ValueChanged.Subscribe(i => GetMakerController().IdleAnimation = _idleAnimations[i].Key);
            }
        }
Ejemplo n.º 2
0
        internal static void MakerAPI_RegisterCustomSubCategories(object sender, RegisterSubCategoriesEvent ev)
        {
            MakerCategory category = new MakerCategory("03_ClothesTop", "tglSettings", MakerConstants.Clothes.Copy.Position + 1, "Settings");

            var addRemoveText = new MakerText("Add or remove outfit slots", category, Instance);

            ev.AddControl(addRemoveText);

            var coordinateNameTextbox = new MakerTextbox(category, "Outfit Name", TextboxDefault, Instance);

            ev.AddControl(coordinateNameTextbox);

            var addCoordinateButton = new MakerButton("Add additional clothing slot", category, Instance);

            ev.AddControl(addCoordinateButton);
            addCoordinateButton.OnClick.AddListener(() =>
            {
                var chaControl = MakerAPI.GetCharacterControl();
                SetCoordinateName(chaControl, chaControl.chaFile.coordinate.Length, coordinateNameTextbox.Value);
                AddCoordinateSlot(chaControl);
            });

            var removeCoordinateButton = new MakerButton("Remove last additional clothing slot", category, Instance);

            ev.AddControl(removeCoordinateButton);
            removeCoordinateButton.OnClick.AddListener(() => { RemoveCoordinateSlot(MakerAPI.GetCharacterControl()); });

            RenameCoordinateText = new MakerText("Rename outfit slots", category, Instance);
            ev.AddControl(RenameCoordinateText);

            RenameCoordinateDropdown = new MakerDropdown("Outfit", new string[] { "none" }, category, 0, Instance);
            ev.AddControl(RenameCoordinateDropdown);

            RenameCoordinateTextbox = new MakerTextbox(category, "New Name", TextboxDefault, Instance);
            RenameCoordinateTextbox.ValueChanged.Subscribe(value =>
            {
                if (value != TextboxDefault)
                {
                    var chaControl = MakerAPI.GetCharacterControl();
                    SetCoordinateName(chaControl, OriginalCoordinateLength + RenameCoordinateDropdown.Value, RenameCoordinateTextbox.Value);
                    UpdateMakerUI();
                }
            });
            ev.AddControl(RenameCoordinateTextbox);

            ev.AddSubCategory(category);
        }
Ejemplo n.º 3
0
        private static void MakerAPI_MakerBaseLoaded(object sender, RegisterCustomControlsEvent e)
        {
            // Replace the stock skin type selection window with a dropdown
            // This is because the dropdown icons are all NSFW
            // This part creates the new control
            var chaListCtrl  = Singleton <Character> .Instance.chaListCtrl;
            var categoryInfo = chaListCtrl.GetCategoryInfo(ChaListDefine.CategoryNo.mt_body_detail);
            var headValues   = categoryInfo.Values.ToList();

            _skinTypeReplacementControl     = e.AddControl(new MakerDropdown("Skin type", headValues.Select(x => x.Name).ToArray(), MakerConstants.Body.All, 0, null));
            MakerAPI.ReloadCustomInterface += (o, args) => _skinTypeReplacementControl.Value = headValues.FindIndex(i => i.Id == MakerAPI.GetCharacterControl().chaFile.custom.body.detailId);
            _skinTypeReplacementControl.ValueChanged.Subscribe(x =>
            {
                var newId      = headValues[x].Id;
                var chaControl = MakerAPI.GetCharacterControl();
                var body       = chaControl.chaFile.custom.body;
                if (body.detailId != newId)
                {
                    body.detailId = newId;
                    chaControl.ChangeSettingBodyDetail();
                }
            });
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Initialize the character maker GUI
        /// </summary>
        private void MakerAPI_RegisterCustomSubCategories(object sender, RegisterSubCategoriesEvent e)
        {
            bool DoDropdownEvents = false;

            e.AddControl(new MakerText(PluginName, MakerConstants.Body.All, this));

            BodyList.Clear();
            BodyListDisplay.Clear();

            BodyList.Add("Default");
            BodyListDisplay.Add("Default");

            var characterSex = (byte)MakerAPI.GetMakerSex();

            foreach (BodyData bodyData in BodyDictionary.Select(x => x.Value)
                     .OrderByDescending(x => x.Sex == characterSex)
                     .ThenBy(x => x.Sex)
                     .ThenBy(x => x.DisplayName))
            {
                if (BodyAllowedInMaker(bodyData.Sex, characterSex))
                {
                    BodyList.Add(bodyData.BodyGUID);
                    BodyListDisplay.Add(BodyGuidToDisplayName(bodyData.BodyGUID));
                }
            }

            BodyDropdown = e.AddControl(new MakerDropdown("Body", BodyListDisplay.ToArray(), MakerConstants.Body.All, 0, this));
            BodyDropdown.ValueChanged.Subscribe(Observer.Create <int>(BodyDropdownChanged));
            void BodyDropdownChanged(int ID)
            {
                if (DoDropdownEvents == false)
                {
                    return;
                }

                var controller = GetController(MakerAPI.GetCharacterControl());

                controller.BodyGUID = ID == 0 ? null : BodyList[ID];
                controller.UpdateUncensor();
            }

            PenisList.Clear();
            PenisListDisplay.Clear();

            PenisList.Add("Default");
            PenisListDisplay.Add("Default");
#if KK
            PenisList.Add("None");
            PenisListDisplay.Add("None");
#endif

            foreach (PenisData penis in PenisDictionary.Select(x => x.Value).OrderByDescending(x => x.DisplayName))
            {
                PenisList.Add(penis.PenisGUID);
                PenisListDisplay.Add(penis.DisplayName);
            }

#if KK
            PenisDropdown = e.AddControl(new MakerDropdown("Penis", PenisListDisplay.ToArray(), MakerConstants.Body.All, characterSex == 0 ? 0 : 1, this));
#elif EC
            PenisDropdown = e.AddControl(new MakerDropdown("Penis", PenisListDisplay.ToArray(), MakerConstants.Body.All, 0, this));
#endif
            PenisDropdown.ValueChanged.Subscribe(Observer.Create <int>(PenisDropdownChanged));
            void PenisDropdownChanged(int ID)
            {
                if (DoDropdownEvents == false)
                {
                    return;
                }

                var controller = GetController(MakerAPI.GetCharacterControl());

#if KK
                controller.PenisGUID    = ID == 0 || ID == 1 ? null : PenisList[ID];
                controller.DisplayPenis = ID == 1 ? false : true;
#elif EC
                controller.PenisGUID    = ID == 0 ? null : PenisList[ID];
                controller.DisplayPenis = characterSex == 0;
#endif
                controller.UpdateUncensor();
            }

            BallsList.Clear();
            BallsListDisplay.Clear();

            BallsList.Add("Default");
            BallsListDisplay.Add("Default");
            BallsList.Add("None");
            BallsListDisplay.Add("None");

            foreach (BallsData balls in BallsDictionary.Select(x => x.Value).OrderByDescending(x => x.DisplayName))
            {
                BallsList.Add(balls.BallsGUID);
                BallsListDisplay.Add(balls.DisplayName);
            }

            int ballsInitialValue = characterSex == 0 ? 0 : DefaultFemaleDisplayBalls.Value == true ? 0 : 1;
            BallsDropdown = e.AddControl(new MakerDropdown("Balls", BallsListDisplay.ToArray(), MakerConstants.Body.All, ballsInitialValue, this));
            BallsDropdown.ValueChanged.Subscribe(Observer.Create <int>(BallsDropdownChanged));
            void BallsDropdownChanged(int ID)
            {
                if (DoDropdownEvents == false)
                {
                    return;
                }

                var controller = GetController(MakerAPI.GetCharacterControl());

                controller.BallsGUID    = ID == 0 || ID == 1 ? null : BallsList[ID];
                controller.DisplayBalls = ID == 1 ? false : true;
                controller.UpdateUncensor();
            }

#if EC
            if (characterSex == 1)
            {
                var dickToggle = e.AddControl(new MakerToggle(MakerConstants.Body.All, "Toggle Penis Display", characterSex == 0, this));
                dickToggle.ValueChanged.Subscribe(Observer.Create <bool>(delegate { MakerAPI.GetCharacterControl().fileStatus.visibleSonAlways = dickToggle.Value; }));
            }
#endif

            DoDropdownEvents = true;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Initialize the character maker GUI
        /// </summary>
        private void MakerAPI_RegisterCustomSubCategories(object sender, RegisterSubCategoriesEvent e)
        {
            DoDropdownEvents = false;
            e.AddControl(new MakerText(PluginName, MakerConstants.Body.All, this));

            BodyList.Clear();
            BodyListDisplay.Clear();

            BodyList.Add("Default");
            BodyListDisplay.Add("Default");

            var characterSex = (byte)MakerAPI.GetMakerSex();

            foreach (BodyData bodyData in BodyDictionary.Select(x => x.Value)
                     .OrderByDescending(x => x.Sex == characterSex)
                     .ThenBy(x => x.Sex)
                     .ThenBy(x => x.DisplayName))
            {
                if (BodyAllowedInMaker(bodyData.Sex, characterSex))
                {
                    BodyList.Add(bodyData.BodyGUID);
                    BodyListDisplay.Add(BodyGuidToDisplayName(bodyData.BodyGUID));
                }
            }

            BodyDropdown = e.AddControl(new MakerDropdown("Body", BodyListDisplay.ToArray(), MakerConstants.Body.All, 0, this));
            BodyDropdown.ValueChanged.Subscribe(Observer.Create <int>(BodyDropdownChanged));
            void BodyDropdownChanged(int ID)
            {
                if (DoDropdownEvents == false)
                {
                    return;
                }

                var controller = GetController(MakerAPI.GetCharacterControl());

                controller.BodyGUID = ID == 0 ? null : BodyList[ID];
                controller.UpdateUncensor();
            }

            PenisList.Clear();
            PenisListDisplay.Clear();

            PenisList.Add("Default");
            PenisListDisplay.Add("Default");
            PenisList.Add("None");
            PenisListDisplay.Add("None");

            foreach (PenisData penis in PenisDictionary.Select(x => x.Value).OrderByDescending(x => x.DisplayName))
            {
                PenisList.Add(penis.PenisGUID);
                PenisListDisplay.Add(penis.DisplayName);
            }

            PenisDropdown = e.AddControl(new MakerDropdown("Penis", PenisListDisplay.ToArray(), MakerConstants.Body.All, characterSex == 0 ? 0 : 1, this));
            PenisDropdown.ValueChanged.Subscribe(Observer.Create <int>(PenisDropdownChanged));
            void PenisDropdownChanged(int ID)
            {
                if (DoDropdownEvents == false)
                {
                    return;
                }

                var controller = GetController(MakerAPI.GetCharacterControl());

                controller.PenisGUID    = ID == 0 || ID == 1 ? null : PenisList[ID];
                controller.DisplayPenis = ID == 1 ? false : true;
                controller.UpdateUncensor();
            }

            BallsList.Clear();
            BallsListDisplay.Clear();

            BallsList.Add("Default");
            BallsListDisplay.Add("Default");
            BallsList.Add("None");
            BallsListDisplay.Add("None");

            foreach (BallsData balls in BallsDictionary.Select(x => x.Value).OrderByDescending(x => x.DisplayName))
            {
                BallsList.Add(balls.BallsGUID);
                BallsListDisplay.Add(balls.DisplayName);
            }

            BallsDropdown = e.AddControl(new MakerDropdown("Balls", BallsListDisplay.ToArray(), MakerConstants.Body.All, characterSex == 0 ? 0 : 1, this));
            BallsDropdown.ValueChanged.Subscribe(Observer.Create <int>(BallsDropdownChanged));
            void BallsDropdownChanged(int ID)
            {
                if (DoDropdownEvents == false)
                {
                    return;
                }

                var controller = GetController(MakerAPI.GetCharacterControl());

                controller.BallsGUID    = ID == 0 || ID == 1 ? null : BallsList[ID];
                controller.DisplayBalls = ID == 1 ? false : true;
                controller.UpdateUncensor();
            }
        }
Ejemplo n.º 6
0
        private void RegisterCustomSubCategories(object sender, RegisterSubCategoriesEvent ev)
        {
            MakerCategory category = new MakerCategory("03_ClothesTop", "tglPushup", MakerConstants.Clothes.Bra.Position + 1, "Pushup");

            //Bra or top
            SelectButtons = ev.AddControl(new MakerRadioButtons(category, this, "Type", "Bra", "Top"));
            SelectButtons.ValueChanged.Subscribe(i => ReloadPushup());

            //Basic mode
            EnablePushupToggle = new MakerToggle(category, "Enabled", true, this);
            ev.AddControl(EnablePushupToggle);

            FirmnessSlider     = MakeSlider(category, "Firmness", ev, ConfigFirmnessDefault.Value);
            LiftSlider         = MakeSlider(category, "Lift", ev, ConfigLiftDefault.Value);
            PushTogetherSlider = MakeSlider(category, "Push Together", ev, ConfigPushTogetherDefault.Value);
            SqueezeSlider      = MakeSlider(category, "Squeeze", ev, ConfigSqueezeDefault.Value);
            CenterSlider       = MakeSlider(category, "Center Nipples", ev, ConfigNippleCenteringDefault.Value);

            FlattenNippleToggle = new MakerToggle(category, "Flatten Nipples", true, this);
            ev.AddControl(FlattenNippleToggle);

            //Advanced mode
            ev.AddControl(new MakerSeparator(category, this));

            AdvancedModeToggle = new MakerToggle(category, "Advanced Mode", false, this);
            ev.AddControl(AdvancedModeToggle);

            var copyBodyButton = new MakerButton("Copy Body To Advanced", category, this);

            ev.AddControl(copyBodyButton);
            copyBodyButton.OnClick.AddListener(CopyBodyToSliders);

            var copyBasicButton = new MakerButton("Copy Basic To Advanced", category, this);

            ev.AddControl(copyBasicButton);
            copyBasicButton.OnClick.AddListener(CopyBasicToSliders);

            PushSizeSlider               = MakeSlider(category, "Size", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexSize], true);
            PushVerticalPositionSlider   = MakeSlider(category, "Vertical Position", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexVerticalPosition], true);
            PushHorizontalAngleSlider    = MakeSlider(category, "Horizontal Angle", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexHorizontalAngle], true);
            PushHorizontalPositionSlider = MakeSlider(category, "Horizontal Position", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexHorizontalPosition], true);
            PushVerticalAngleSlider      = MakeSlider(category, "Vertical Angle", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexVerticalAngle], true);
            PushDepthSlider              = MakeSlider(category, "Depth", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexDepth], true);
            PushRoundnessSlider          = MakeSlider(category, "Roundness", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexRoundness], true);

            PushSoftnessSlider = MakeSlider(category, "Softness", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.bustSoftness, true);
            PushWeightSlider   = MakeSlider(category, "Weight", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.bustWeight, true);

            PushAreolaDepthSlider = MakeSlider(category, "Areola Depth", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexAreolaDepth], true);
            PushNippleWidthSlider = MakeSlider(category, "Nipple Width", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexNippleWidth], true);
            PushNippleDepthSlider = MakeSlider(category, "Nipple Depth", ev, Singleton <CustomBase> .Instance.defChaInfo.custom.body.shapeValueBody[PushupConstants.IndexNippleDepth], true);

#if KK
            //Only one outfit in EC
            var coordinateList = Enum.GetNames(typeof(ChaFileDefine.CoordinateType)).ToList();
            coordinateList.Add("All");
            ev.AddControl(new MakerSeparator(category, this));
            var copyDropdown = new MakerDropdown("Copy To Coordinate", coordinateList.ToArray(), category, 0, this);
            ev.AddControl(copyDropdown);

            string[] DataTypes        = new string[] { "Basic and Advanced", "Basic", "Advanced" };
            var      copyDataDropdown = new MakerDropdown("Data To Copy", DataTypes, category, 0, this);
            ev.AddControl(copyDataDropdown);

            var copyButton = new MakerButton("Copy", category, this);
            ev.AddControl(copyButton);
            copyButton.OnClick.AddListener(delegate
            {
                bool copyBasic    = copyDataDropdown.Value == 0 || copyDataDropdown.Value == 1;
                bool copyAdvanced = copyDataDropdown.Value == 0 || copyDataDropdown.Value == 2;

                if (copyDropdown.Value == coordinateList.Count - 1) //Copy all
                {
                    for (int i = 0; i < coordinateList.Count - 1; i++)
                    {
                        CopySlidersToCoordinate(i, copyBasic, copyAdvanced);
                    }
                }
                else
                {
                    CopySlidersToCoordinate(copyDropdown.Value, copyBasic, copyAdvanced);
                }
            });
#endif
            ev.AddSubCategory(category);
        }
Ejemplo n.º 7
0
 private static void MakerExiting(object sender, EventArgs e)
 {
     _toggleEnabled = null;
     _animType      = null;
 }
Ejemplo n.º 8
0
        private void RegisterCustomSubCategories(object sender, RegisterSubCategoriesEvent args)
        {
            ChaControl _chaCtrl = CustomBase.Instance.chaCtrl;
            CharacterAccessoryController _pluginCtrl = GetController(_chaCtrl);

            SidebarToggleEnable = args.AddSidebarControl(new SidebarToggle("CharaAcc", CfgMakerMasterSwitch.Value, this));
            SidebarToggleEnable.ValueChanged.Subscribe(value => CfgMakerMasterSwitch.Value = value);

            MakerCategory category = new MakerCategory("03_ClothesTop", "tglCharaAcc", MakerConstants.Clothes.Copy.Position + 1, "CharaAcc");

            args.AddSubCategory(category);

            args.AddControl(new MakerText("The set to be used as a template to clone on load", category, this));

            List <string> coordinateList = Enum.GetNames(typeof(ChaFileDefine.CoordinateType)).ToList();

            coordinateList.Add("CharaAcc");
            MakerDropdownRef = new MakerDropdown("Referral", coordinateList.ToArray(), category, 0, this);
            MakerDropdownRef.ValueChanged.Subscribe(value =>
            {
                _pluginCtrl.SetReferralIndex(value);
            });
            args.AddControl(MakerDropdownRef);

            MakerToggleEnable = args.AddControl(new MakerToggle(category, "Enable", false, this));
            MakerToggleEnable.ValueChanged.Subscribe(value =>
            {
                _pluginCtrl.FunctionEnable = value;
            });

            MakerToggleAutoCopyToBlank = args.AddControl(new MakerToggle(category, "Auto Copy To Blank", false, this));
            MakerToggleAutoCopyToBlank.ValueChanged.Subscribe(value =>
            {
                _pluginCtrl.AutoCopyToBlank = value;
            });

            args.AddControl(new MakerButton("Backup", category, this)).OnClick.AddListener(delegate
            {
                if (_pluginCtrl.DuringLoading)
                {
                    return;
                }
                _pluginCtrl.Backup();
            });

            args.AddControl(new MakerButton("Restore", category, this)).OnClick.AddListener(delegate
            {
                if (_pluginCtrl.DuringLoading)
                {
                    return;
                }
                if (MoreAccessoriesSupport.ListUsedPartsInfo(_chaCtrl, _chaCtrl.fileStatus.coordinateType).Count > 0)
                {
                    Logger.LogMessage("Please clear the accessories on current coordinate before using this function");
                    return;
                }
                _pluginCtrl.TaskLock();
                _pluginCtrl.RestorePartsInfo();
            });

            args.AddControl(new MakerButton("Reset", category, this)).OnClick.AddListener(delegate
            {
                if (_pluginCtrl.DuringLoading)
                {
                    return;
                }
                _pluginCtrl.Reset();
                MakerDropdownRef.Value           = _pluginCtrl.ReferralIndex;
                MakerToggleEnable.Value          = _pluginCtrl.FunctionEnable;
                MakerToggleAutoCopyToBlank.Value = _pluginCtrl.AutoCopyToBlank;
            });
#if DEBUG
            args.AddControl(new MakerButton("Transfer", category, this)).OnClick.AddListener(delegate
            {
                if (_pluginCtrl.DuringLoading)
                {
                    return;
                }
                if (_pluginCtrl.ReferralIndex > 6)
                {
                    Logger.LogMessage("Please choose a coordinate other than CharaAcc as referral");
                    return;
                }
                _pluginCtrl.TaskLock();
                _pluginCtrl.PrepareQueue();
            });

            args.AddControl(new MakerButton("Hair info (local)", category, this)).OnClick.AddListener(delegate
            {
                _pluginCtrl.HairAccessoryCustomizer.DumpInfo(true);
            });

            args.AddControl(new MakerButton("Hair info", category, this)).OnClick.AddListener(delegate
            {
                _pluginCtrl.HairAccessoryCustomizer.DumpInfo(false);
            });
#endif
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Initialize the character maker GUI
        /// </summary>
        private void MakerAPI_RegisterCustomSubCategories(object sender, RegisterSubCategoriesEvent e)
        {
            bool DoDropdownEvents = false;

            e.AddControl(new MakerText(PluginName, MakerConstants.Body.All, this));

            BodyList.Clear();
            BodyListDisplay.Clear();

            BodyList.Add("Default");
            BodyListDisplay.Add("Default");

            var characterSex = (byte)MakerAPI.GetMakerSex();

            foreach (BodyData bodyData in BodyDictionary.Select(x => x.Value)
                     .OrderByDescending(x => x.Sex == characterSex)
                     .ThenBy(x => x.Sex)
                     .ThenBy(x => x.DisplayName))
            {
                if (BodyAllowedInMaker(bodyData.Sex, characterSex))
                {
                    BodyList.Add(bodyData.BodyGUID);
                    BodyListDisplay.Add(BodyGuidToDisplayName(bodyData.BodyGUID));
                }
            }

            BodyDropdown = e.AddControl(new MakerDropdown("Body", BodyListDisplay.ToArray(), MakerConstants.Body.All, 0, this));
            BodyDropdown.ValueChanged.Subscribe(value =>
            {
                if (!DoDropdownEvents)
                {
                    return;
                }
                BodyDropdownChanged(value);
            });

            PenisList.Clear();
            PenisListDisplay.Clear();

            PenisList.Add("Default");
            PenisListDisplay.Add("Default");
#if KK || KKS
            PenisList.Add("None");
            PenisListDisplay.Add("None");
#endif

            foreach (PenisData penis in PenisDictionary.Select(x => x.Value).OrderByDescending(x => x.DisplayName))
            {
                PenisList.Add(penis.PenisGUID);
                PenisListDisplay.Add(penis.DisplayName);
            }

#if KK || KKS
            PenisDropdown = e.AddControl(new MakerDropdown("Penis", PenisListDisplay.ToArray(), MakerConstants.Body.All, characterSex == 0 ? 0 : 1, this));
#else
            PenisDropdown = e.AddControl(new MakerDropdown("Penis", PenisListDisplay.ToArray(), MakerConstants.Body.All, 0, this));
#endif
            PenisDropdown.ValueChanged.Subscribe(value =>
            {
                if (!DoDropdownEvents)
                {
                    return;
                }
                PenisDropdownChanged(value);
            });

            BallsList.Clear();
            BallsListDisplay.Clear();

            BallsList.Add("Default");
            BallsListDisplay.Add("Default");
            BallsList.Add("None");
            BallsListDisplay.Add("None");

            foreach (BallsData balls in BallsDictionary.Select(x => x.Value).OrderByDescending(x => x.DisplayName))
            {
                BallsList.Add(balls.BallsGUID);
                BallsListDisplay.Add(balls.DisplayName);
            }

            int ballsInitialValue = characterSex == 0 ? 0 : DefaultFemaleDisplayBalls.Value ? 0 : 1;
            BallsDropdown = e.AddControl(new MakerDropdown("Balls", BallsListDisplay.ToArray(), MakerConstants.Body.All, ballsInitialValue, this));
            BallsDropdown.ValueChanged.Subscribe(value =>
            {
                if (!DoDropdownEvents)
                {
                    return;
                }
                BallsDropdownChanged(value);
            });

#if EC
            if (characterSex == 1)
            {
                var dickToggle = e.AddControl(new MakerToggle(MakerConstants.Body.All, "Toggle Penis Display", characterSex == 0, this));
                dickToggle.ValueChanged.Subscribe(Observer.Create <bool>(obj => MakerAPI.GetCharacterControl().fileStatus.visibleSonAlways = dickToggle.Value));
            }
#endif

#if AI || HS2
            if (characterSex == 0)
            {
                BodyDropdown.Visible.OnNext(false);
            }
            else
            {
                TogglePenisBallsUI(false);
            }
#endif

            DoDropdownEvents = true;
        }