andrewgu / ModConfigMenu

XCOM 2 Mod Config Menu: a project to build a shared settings menu for Xcom 2 mods.
11 stars 13 forks source link

Soldier on Start Menu Can Obscure Options Menus #19

Closed Patrick-Seymour closed 8 years ago

Patrick-Seymour commented 8 years ago

This is actually something that you might not be able to resolve without going to a 2D UIScreen, but a soldier with a big gun (say a Mag Cannon) can block-out the scrollbar or some checkboxes, making interacting with the options menu a bit hit-or-miss at times. The tactical/strategy game works fine, the main menu is just an issue because the soldier can appear "on top" of the menu data.

andrewgu Mag cannon blocking out scrollbar and checkboxes: yeah, not sure about that one. I believe the options screen has a similar problem. This might be avoidable by shifting the whole panel to the left. Again I'm inclined to make it a 1.1 thing.

This is one that I'm actually looking in to. I figure if I can iterate over the Actors on screen, I can just grab a reference to the soldier standing there, and either adjust his occlusion of the options menu when it is open, or just straight-up make him invisible while the menu is open. Kind of blunt, but if it works, it works.

Patrick-Seymour commented 8 years ago

So I'm looking in to resolving this somehow. I don't think it's as simple as just setting the visibility of the XCOM soldier on the main menu. This is what happens when I toggle ALL Actor visibility.

https://www.dropbox.com/s/2ahkwlsjy8li40i/toggling-all-actor-visibility.png?dl=0

Obviously something is keeping the XCOM soldier visible, even when setting the Actor to hide.

I fooled around with various ways to get the soldier hidden, and came across a method whereby iterating over all meshes that are owned by the Actor in question, and hiding the meshes individually, seems to cause the soldier to appear invisible.

https://youtu.be/snmUCFXkhd8

It's triggered just by a screen listener, hiding when options is loaded and showing when options is closed. I'm going to include this in my own mod project, but If you'd like I can send you the example code if you want to include it or something similar built-in to MCM.

andrewgu commented 8 years ago

Just noticed you added this comment. Would definitely appreciate if you could send this over! I think it's worth making a default behavior for MCM.

Patrick-Seymour commented 8 years ago

Something like this should work. The nasty nesting in ShowProcess() is just because I didn't bother looking in to whether foreach outputs structs by value or by reference, so it's a mix of for/foreach. Also probably could use some array magic like array.Find(), but again, just haven't looked in to it yet. Some of the UnrealScript array stuff doesn't seem to work properly anyways, so I try to avoid stuff like that where possible.

class HideMainMenuSoldier extends UIScreenListener;

var bool ProcessEnabled;

struct PawnAndComponents {
    var XComUnitPawn Pawn;
    var array<PrimitiveComponent> Comps;
};
var array<PawnAndComponents> PawnAndComps;

event OnInit(UIScreen Screen) {
    HideProcessIfEnabled();
};

event OnRemoved(UIScreen Screen) {
    ShowProcessIfEnabled();
};

simulated function bool IsProcessEnabled() {
    return ProcessEnabled;
};

simulated function bool IsGameLayerMainMenu() {
    return `PRESBASE.ScreenStack.IsInStack(class'UIShell');
};

simulated function HideProcessIfEnabled() {
    if (!IsProcessEnabled()) return;
    if (!IsGameLayerMainMenu()) return;
    HideProcess();
};

simulated function ShowProcessIfEnabled() {
    if (!IsProcessEnabled()) return;
    if (!IsGameLayerMainMenu()) return;
    ShowProcess();
};

simulated function HideProcess() {
    local XComUnitPawn Pawn;
    local PrimitiveComponent Comp;
    local int i;
    local PawnAndComponents PawnAndComp;
    PawnAndComps.Length = 0;
    foreach `XWORLDINFO.AllActors(class'XComUnitPawn', Pawn) {
        PawnAndComp.Pawn = Pawn;
        PawnAndComp.Comps.Length = 0;
        foreach Pawn.AllOwnedComponents(class'PrimitiveComponent', Comp) {
            if (!Comp.HiddenGame) {
                Comp.SetHidden(true);
                PawnAndComp.Comps.AddItem(Comp);
            }
        }
        PawnAndComps.AddItem(PawnAndComp);
    }
};

simulated function ShowProcess() {
    local XComUnitPawn Pawn;
    local PrimitiveComponent Comp;
    local int i, j;
    foreach `XWORLDINFO.AllActors(class'XComUnitPawn', Pawn) {
        for (i = 0; i < PawnAndComps.Length; ++i) {
            if (PawnAndComps[i].Pawn == Pawn) {
                foreach Pawn.AllOwnedComponents(class'PrimitiveComponent', Comp) {
                    for (j = 0; j < PawnAndComps[i].Comps.Length; ++j) {
                        if (PawnAndComps[i].Comps[j] == Comp) {
                            Comp.SetHidden(false);
                            break;
                        }
                    }
                }
                break;
            }
        }
    }
    PawnAndComps.Length = 0;
};

defaultproperties
{
    ScreenClass = class'UIOptionsPCScreen';
}
andrewgu commented 8 years ago

A belated thanks for providing the code! I hope you don't mind that I copy-pasted the meat of it (you are credited in the code). Will go out with next release.