#Toggle Notifications devlog

1 messages · Page 3 of 1

visual bone
#

Feels really good to have it working

#

Sortaish

#

Never knew how hard it was to get a GUI made. But now it seems easy

opal lagoon
#

It does, doesn't it!

#

There's a learning curve.

visual bone
#

Like the lines to separate the window

#

I also plan on shifting the fill window to the togglenotifiationsui

#

Removing a bunch of stuff in that that I'm not using etc

opal lagoon
#

For some their learning curve resembles a plane taking off and climbing, for some a rocket, and for a few special ones a submarine...

visual bone
#

I'm not sure what mines been

#

2+ weeks and I've got four buttons

opal lagoon
#

You've gone from nada to a mod that does something useful pretty quickly.

#

And there's a ton of things you had to learn along the way! Things that don't necessarily show up in the finished product, but impact your ability to develop it further.

visual bone
#

It's been fun and I'm enjoying it alot

#

Thanks for all the help so far

opal lagoon
#

Yeah, me too!

#

You're very welcome!

visual bone
#

I'm also glad I don't have to do math or calculate orbits or hohmann transfers 🤣

opal lagoon
#

Me too!

visual bone
#

I just turn button on and off

opal lagoon
#

Oh... wait...

timid quail
#

gone from YouTube videos covering mods to making mods!

visual bone
#

Lol

#

I'll be making more videos just wanting to get this up and running and honestly having a blast modding

#

Youtube is fun and that's why I do it.

opal lagoon
visual bone
opal lagoon
#

I'm not sure what you're showing here, but it seems like it might be broken. What does it mean for a thing to be both "Active" and also "Active"?

visual bone
#

im taking screenshots so i can have a visual aid while i fix things

#

cause i have a terrible memory

#

ive made the buttons dynamic in how they calculate their width as well

#

they dont seem centered though

timid quail
#

they seem centered to me (in the remaining space that they have next to the green rectangle)

opal lagoon
#

Ahh, IC. What I do for that is to make an Images folder at the base level of the project and stuff things in there, then use GitHub to push them up to the repo. That way I can reference them easily in the README if I want to use them there. It also means they're posted online where I can use them for posts to KSP forums, or reference them from SpaceDock much like in the README

visual bone
#

also this is being calculated every frame

#

so im making an updatewindow in the togglenotifUI that will do that in the background

#

and fillwindow will call it when the user changes the value

opal lagoon
#

The Images folder is different from assets/images and doesn't ship with the game, but it's handy for other stuff

visual bone
#

clever

#

this looks sleeker

#

obv still figuring out how I want it to look etc

opal lagoon
#

The wide buttons? Yes, definitely

visual bone
#

but this is an option to pursue

#

i feel like it ssimple and it works with other mods

#

so theres familiarity

opal lagoon
#

I like it this way

visual bone
#

also moving everything to the UI and making the plugin skinnier

#

its almost as if I planned this all out

visual bone
#

if this works ill be amazed

#
  internal void OnGUI()
        {
            this.MainUI.OnGUI();
        }
        internal void FillWindow(int windowID)
        {
            MainUI.FillWindow(windowID);
        }
    }
opal lagoon
#

@visual bone I just made the raw video for my first tutorial video. I'm sure it's far from ideal, but I've got the raw video captured from OBS Studio. This leaves me with a 141mb MKV file. What's the next step?

#

Is there a way in OBS Studio to make it smaller and suitable for uplaoding?

visual bone
#

hm

#

mkv is a slippery slope

#

they're not the most stable files, ive had them get corrupted very easily

#

i record using mp4 because its reliable and doesnt get corrupted as easily as mkv

#

full views of the windows

#

with recording you want to jack up your bitrate

opal lagoon
#

Well I can re-record it.

visual bone
#

54000 Kbps works really well for 4k video

#

look up the spec ranges for the Kbps for whatever quality you're going for

#

this isnt for streaming

#

streaming is a whole other animal

#

simple but its different

#

ive got a stream pc that handles all of that

#

i stream on stream pc, and record 4k with my game pc

#

but once you have your settings all squared away, then you can test it

#

you wanna make sure you're getting the best quality your rig can get

#

no idea what specs you're running

opal lagoon
#

I've got 2K monitors and the game is at 1920 x 1080 windowed

visual bone
#

gpu and cpu?

opal lagoon
#

My video card?

visual bone
#

yup

#

it matters when it comes to setting this up

opal lagoon
#

GPU high end

visual bone
#

alright good

#

you can then use it to do the workload

opal lagoon
#

It's one that KSP2 recommended

visual bone
#

thats what you want to use

#

that basically uses your GPU to do allt he work

#

x264 is for a good cpu

opal lagoon
#

I can't use Nvida due to this being a dual boot hackintosh and OSX doesn't like those cards

visual bone
#

ah

#

then you'll wanna rock x264

#

x264 will use your cpu

#

youll have to tweak your settings based off using the x264

#

its like coding, play with it til it works how you want on your rig

#

any other questions or way si can help?

#

obviously the recording tab shows you where you can have the video save the .mp4 to

#

wait one.

opal lagoon
#

Lots more questions, and I'm completely new and most of what you've told me has gone right over my head.

#

How do you see your video card in stupid f-ing windows?

visual bone
#

lol

opal lagoon
#

I know how in OSX, but obviously I'm in windows atm

#

It's a high end AMD radeon

visual bone
#

windows key type device manager

#

display adapaters

opal lagoon
#

It's an RX 6800 XT with 16GB I think

visual bone
#

not familiar with team red. havent used AMD since early 2000's

opal lagoon
#

OK, so I think my next steps are in OBS studio, and I'm barely able to find the start recording button

#

Where do I tell it what format to capture in and all that other stuff you were telling me?

visual bone
#

wait one

#

so you have a scene setup correct?

opal lagoon
#

yeah like that

visual bone
#

and the scene has your display that you're capturing

opal lagoon
visual bone
#

controls has the settings that change everything

#

so bottom right

#

start streaming, start recording... then settings

opal lagoon
#

Settings > Output?

visual bone
#

yup

#

so youll want to look at the streaming tab and recording tab within output

#

video tab lets you pick the resolution you record

opal lagoon
#

For video encoder I've got options for Software (x264) and Hardware AMD H.264

visual bone
#

so base is the native resolution your monitor is at

opal lagoon
#

Should I go with HW?

visual bone
#

oh try hardware amd h.264

#

thatll use your gpu

#

software x264 is going ot use your cpu and wont be as good as the gpu

#

the technical aspects im not sure

#

but the last thing i wanna learn is how a graphics card works and calculates things

opal lagoon
#

found where to set it to mpeg-4

visual bone
#

yup

#

itll be in output >> recording

#

you can change the pathing there and the format you record in

#

as well as select which audio tracks to record

opal lagoon
#

What do you do with the audio tracks? I've got my mic disabled and the sound from the game is the only thing. Audi Track 1 is checked and the others are not

visual bone
#

i use voicemeeter

#

im building a rack right now to takeover the mixer and audio interface so i have hardware instead of software

#

uh but for recording, it just depends

opal lagoon
#

OBS gives me this warning with MPEG-4

visual bone
#

i record gameplay with only the game audio

#

most of the time i delete the audio from the game

#

yeah

#

if your computer shuts off

#

it wont save your mp4

#

but from 3 years of streaming and just starting on youtube, def have learned mp4s are the most stable

#

better quality and they work with every software

#

mkv will not be useable by premiere

opal lagoon
#

Does this mean I might be able to take the MKV I've got now and "remux" it to MPEG-4?

visual bone
#

youd have to convert the mkv to mp4 to use the footage in premiere

#

yup

#

you def can

#

may lose a bit of quality

opal lagoon
#

I don't have premiere

visual bone
#

blender?

#

i used blender when i started over again with youtube this year

#

all my 1080p videos are with blender

opal lagoon
#

I've got some Adobe stuff, but only Ps and LrC

#

I'm mainly a stills guy

#

Is blender free?

visual bone
#

yup

#

blender is free

#

HORRIBLE UI

opal lagoon
#

Then I'll go get blender and use that

visual bone
#

ABSOLUTELY TRASH UI

#

but

opal lagoon
#

Oh fun...

visual bone
#

once you figure out whwere things are and how it works

#

its not bad

timid quail
#

Blender? as in the 3D modeling software??

#

lmao

visual bone
#

yup

timid quail
#

that's a new one for me, never heard of anyone using it for video editing

opal lagoon
#

So OBS can't help me with that stuff and it just does capture?

#

I guess I was kinda hoping it was a one stop shop for this... 😛

visual bone
#

lol

#

nope

#

obs just records

#

theres some cool plugins i use with obs

#

which eventually as i learn more coding i wanna make my own plugin for obs

visual bone
#

but it was free

#

and i wanted to see if i enjoyed youtube so before i spent money on premiere it made sense

#

then i found out i really enjoy youtube and streaming is more when i feel like it

timid quail
#

wouldn't something like DaVinci Resolve be better?

visual bone
#

resolve is really good

timid quail
#

since it's actually made for the purpose of video editing

visual bone
#

i just use premiere

#

ive also not used resolve personally but a lot of content creator friends use it

opal lagoon
#

is it free?

visual bone
#

i went with premiere because later this year im gonna get after effects

opal lagoon
#

I like free!

visual bone
#

and learn how that works

timid quail
visual bone
#

also im starting to understand what a GUI will look like via code

#

weird that stuff uses the top left to adjust from

#

like who does that? why not be normal like all mathematics and use the bottom left?

#

^ dis is normal and it has sun

timid quail
#

most people read from top left to bottom right

#

etc

#

so why not computers

visual bone
#

computers speak 0's and 1's

opal lagoon
#

There are 10 kinds of people...

visual bone
#

well later today im going to think about how to make the GUI work and not on the plugin

#

because i can tell this is going to be a resource hog if it stays the way it is

#

dont need this being updated every frame

timid quail
#

there's no other way, that's how IMGUI is designed to work

#

all you can do it use a different UI library

#

UITK or UGUI

visual bone
#

(!radioButton3 && selectedRadioButton3 == 1) this prevents it from being updated every frame

timid quail
#

IMGUI is mostly intended to be used for debugging purposes, but the KSP 1 (and because of that, KSP 2) community started using it for mods because it was the easiest to use

visual bone
#

nice lol

#

toggle notifications im going to use IMGUI as its teaching me a lot of how this all works

timid quail
#

but no matter what, the whole UI will keep getting re-rendered multiple times per frame

visual bone
#

thats so weird

#

i tried to use a windowupdate method and call it from the MainUI.WindowUpdate()

#

i had everything on screen

#

but no buttons

#

and then i had buttons

#

but they didnt fit in the window

timid quail
#

which "windowupdate" method?

visual bone
#

and i couldnt figure out how to get the MainUI.windowUpdate to be called AND check the windowfill to fit within the window

#

a method i made up

#
private void FillWindow(int windowID)
{
    MainUI.FillWindow(windowID);
}
timid quail
#

This is totally fine, it's the same exact thing as if you put the code from MainUI.FillWindow inside the plugin's FillWindow method

#

so something else has to be going wrong

visual bone
#
internal void UpdateWindow()
        {
            int buttonWidth = (int)(windowRect.width - 12); // Subtract 3 on each side for padding
            // Check if the button state has changed
            if (previousButtonState1 != isButtonSwitched)
            {
                bool radioButton1 = GUI.Toggle(new Rect(3, 56, buttonWidth, 20), selectedRadioButton == 1, "Game Pause", selectedRadioButton == 0 ? TNBaseStyle.ToggleError : TNBaseStyle.Toggle);
                TNBaseStyle.ToggleError.normal.textColor = selectedRadioButton == 0 ? Color.red : ColorTools.ParseColor("#C0E2DC");
                TNBaseStyle.Toggle.normal.textColor = selectedRadioButton == 1 ? ColorTools.ParseColor("#C0C1E2") : ColorTools.ParseColor("#C0E2DC");
                if (radioButton1)
                {
                    selectedRadioButton = 1;
                    isButtonSwitched = true;
                }
                else
                {
                    selectedRadioButton = 0;
                    isButtonSwitched = false;
                }

                // Update the previous button state
                previousButtonState1 = isButtonSwitched;
            }
        }
        internal bool OnGUI()
        {
            UpdateWindow();
            return true;
        }```
#

thats what i had come up with

#

so it gets called

#

it generates a window but no buttons

timid quail
#

can OnGUI even have a return value? Unity only ever uses it with a void type

visual bone
#

and then it later on generated a window but the four buttons didnt fit inside the window

timid quail
#

afaik

visual bone
#

OnGUI has to have a return

#

that was the early thing i was trying

#

then i went to this

timid quail
visual bone
#

hm

#

what i did is i put everything from my FillWindow into the ToggleNotifidcationsUI

#

created my own FillWindow there,

timid quail
#

yeah so now all you need to do is create an instance of this class and call its OnGUI method from the plugin class's OnGUI

visual bone
#

hm

timid quail
#

oh and since you have an Update method here, the same goes for that

visual bone
#

i called both the update and the ongui in the plugins update

#

but what im working on should eventually work?

timid quail
#

IMGUI code can only be called inside OnGUI, it doesn't work anywhere else

visual bone
#

might explain why some stuff didnt work

#

well im gonna relax for a bit and read this on my phone to see if i can see anything thats causing the gui to not show up

timid quail
#

and what's on the line 125 in your plugin class?

visual bone
#

Looking now

#

Reference for me later

#
internal void OnGUI()
        {
            this.MainUI.OnGUI();
        }
#

thats line 125

timid quail
#

well, then that means you've never assigned a value to MainUI

visual bone
#

I set ToggleNotificationsUI to MainUI? Is that not setting a value?

#

😫

timid quail
#

can you show me where/how?

#

if you mean something like private ToggleNotificationUI MainUI; then no, that only creates an empty variable of the type ToggleNotificationUI which has no value

visual bone
#
namespace ToggleNotifications
{
    internal class ToggleNotificationsUI
    {
        internal List<string> NotificationList = new List<string>();
        internal static ToggleNotificationsUI instance;
        internal static NotificationToggle toggleNotification;
        internal ToggleNotificationsPlugin mainPlugin;
        internal MessageCenterMessage Refreshing;
        internal NotificationEvents RefreshingNotification;
        internal static NotificationToggle notificationToggle;
        private bool InitDone;
        private bool isGUIVisible;
        private TabsUI tabs;
        internal bool interfaceEnabled;
        private Rect windowRect = Rect.zero;
        private int windowWidth = 250;
        internal ToggleNotificationsUI MainUI;
#

Son of a

timid quail
#

you need to do the same thing you do with the list in that code snippet

visual bone
#

Oh

timid quail
#

otherwise it's just null

visual bone
#

Makes sense now

#

It has a way to check a value

#

When it's in a list

#

Otherwise it isn't doing anything

#

And what it checks is the contents of the OnGUI?

timid quail
#

I'm not following

visual bone
#

Thus is me trying to understand how that works

#

I'm gonna nod off as I need sleep. I appreciate the wisdom. I'll read up on more of this and get a better understanding later today 🤘🙏

timid quail
#
class Person
{
    private string _name;

    public Person(string name)
    {
        _name = name;
    }
    
    public void SayHello()
    {
        Console.WriteLine($"Hello, {_name}!");
    }

    public static void SayHelloToAnyone()
    {
        Console.WriteLine("Hello there!");
    }
}

class Greeter
{
    private Person _person1 = new Person("John");
    private Person _person2 = new Person("Kate");
    private Person _person3;

    public void GreetPeople()
    {
        _person1.SayHello(); // will output "Hello, John!"
        _person2.SayHello(); // will output "Hello, Kate!"
        _person3.SayHello(); // will throw a NullReferenceException because the variable is null (the person does not exist)
        Person.SayHelloToAnyone(); // will output "Hello there!", is called on the class itself instead of on an instance of it because it's static, can't access any non-static information about a specific Person instance, such as "_name"
    }
}
#

hopefully this will help a bit

opal lagoon
#

@visual bone, I've got a video made. The file seem freaking huge as I started with a 141mb MKV, trimmed it just slightly, but otherwise did nothing to really edit it, and ended up with a 237mb MP4. Maybe that's normal.

#

I'm in the process of uploading it to YouTube and I've got s dumb questions.

#

YT want's to know if it's made for kids. Well... Not specifically, but it's age appropriate to anyone who might play KSP2 and want to perform an orbital rendezvous...

#

On the one hand, I don't expect kids to be particularly interested, but on the other I don't want to limit visibility

timid quail
#

the only thing that does is flag the video to be available on the YouTube Kids app and disables comments and other stuff like that, afaik

opal lagoon
#

Well, I don't think I want to disable comments and don't really give a crap about the YT kids app...

visual bone
#

did you upload it @opal lagoon ?

#

i think i understood what the template you provided should be doing

#

whoops

visual bone
#

It works! Got everything from plugin class migrated to the ui class

#

Decided to switch to transpilers instead of prefix. I think this will let me modify the patches to return to their original state

visual bone
opal lagoon
#

There are two videos. They are very basic! literally, the only editiing I did was to trim a bit off at the beginning of both and at the end of the second one. As Falki has pointed out I really ought to add some annotations.

visual bone
#

Looks good!

#

You'll get it figured out. I've found having a pre-written script and reading it really helps

#

Literally a video essay

#

not sure why my button changed to that

#

figured it out

#

whats really annoying is I have to patch 3 things in the game for it to make pause not show up

opal lagoon
visual bone
#
private static IEnumerable<CodeInstruction> TranspilerLogic(IEnumerable<CodeInstruction> instructions)
        {
            var codes = new List<CodeInstruction>(instructions);

            for (int i = 0; i < codes.Count; i++)
            {
                if (codes[i].opcode == OpCodes.Ldc_I4_0)
                {
                    // Replace the false value with our local variable
                    codes[i].opcode = OpCodes.Ldsfld;
                    codes[i].operand = AccessTools.Field(typeof(AssistantToTheAssistantPatchManager), nameof(isGamePaused));
                }
                else if (codes[i].opcode == OpCodes.Ldc_I4_1)
                {
                    // Replace the true value with the inverted local variable
                    codes[i].opcode = OpCodes.Ldsfld;
                    codes[i].operand = AccessTools.Field(typeof(AssistantToTheAssistantPatchManager), nameof(isGamePaused));
                    codes.Insert(i + 1, new CodeInstruction(OpCodes.Ldc_I4_0));
                    codes.Insert(i + 2, new CodeInstruction(OpCodes.Ceq));
                }
            }

            // Add the isPauseVisible check here
            codes.Insert(0, new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(AssistantToTheAssistantPatchManager), nameof(isPauseVisible))));
            codes.Insert(1, new CodeInstruction(OpCodes.Brfalse_S, codes[codes.Count - 1].labels[0]));

            return codes.AsEnumerable();
        }
#

so im very intricately changing the harmony patch to use Transpilers instead of Prefixes

#

since transpilers modify the IL code instead of C#

#

and its working

#

but i need to completely disable all the dumb messages that game pause has, which is 3 separate ways it works, so i have to stop all 3

#

i cant just sto p one

#

dumb.

#

lol

#

but if i can get the game pause to toggle off and on and it works correctly with the GUI and the escape button works, ill release v0.2.2 today

stable epoch
visual bone
visual bone
opal lagoon
#

Why you would want to subscribe to my videos is beyond me... You guys are nuts!

visual bone
#

lol

#

spacing is a bit tight

opal lagoon
worn token
#

and me

opal lagoon
#

Honestly though, this is what makes the modding society great. I think any one of us on our own would be having less fun and getting less done than we do collaborating and learning from each other.

#

I secretly wish the KSP forum were like this... God, that place is overrun with whiners.

#

But here, when we find a problem with the game we turn it into an opportunity for a new mod!

visual bone
#

lol

#

transpilers = hell BUT i have it functioning

#

its just not working how i thought because i keep getting null values returned

#

mainly my mainPlugin is returning null

#

I can figure out a transpiler but i cant undrerstand how to set a value to things

#
ArgumentException: Value does not fall within the expected range.
  at ToggleNotifications.ToggleNotificationsPlugin.OnGUI () [0x00036] in C:\Users\nicho\source\repos\Toggle-Notifications\Toggle NotificationsProject\ToggleNotificationsPlugin.cs:116 
#
this.windowRect = GUILayout.Window(

thats line 116

timid quail
#

need to see all the arguments in that method call

visual bone
#
private void OnGUI()
        {
            if (!isGUIVisible)
                return;

            TNStyles.Init();
            WindowTool.CheckMainWindowPos(ref windowRect, windowWidth);
            GUI.skin = TNBaseStyle.Skin;

            this.windowRect = GUILayout.Window(
                GUIUtility.GetControlID(FocusType.Passive),
                this.windowRect,
                MainUI.FillWindow, // Call the FillWindow method of the MainUI instance
                "<color=#696DFF>TOGGLE NOTIFICATIONS</color>",
                GUILayout.Height(0.0f),
                GUILayout.Width((float)this.windowWidth),
                GUILayout.MinHeight(400) // Adjust the value to your desired height
            );

            saverectpos();
        }    
#

also using transpilers and moving everything UI related to the UI class has dramatically imrpoved how smooth the mod runs

#
 public override void OnInitialized()
        {
            TNBaseSettings.Init(SettingsPath);

            base.OnInitialized();
            
            Instance = this;
            Logger = base.Logger;
            Logger.LogInfo("Loaded");
            ///MainUI = new ToggleNotificationsUI(this, isGUIVisible);

            game = GameManager.Instance.Game;

            // Register Flight AppBar button
            Appbar.RegisterAppButton(
#

its cause i commented out the MainUI in oninit

timid quail
#

heh

visual bone
#
[Info   : Unity Log] Initial isWindowOpen value: True
[Info   :Toggle Notifications] Update: Toggle Notifications UI toggled with hotkey
[Warning: Unity Log] UnityEngine.GUISkin must be instantiated using the ScriptableObject.CreateInstance method instead of new GUISkin.
[Info   : Unity Log] custom styles is null
[Error  : Unity Log] mainPlugin or mainPlugin.notificationToggle is null
[Info   : Unity Log] [Simulation] [UniverseTime] Pause State changed to: True
[Info   : Unity Log] [Simulation] [UniverseTime] Time Scale Changed to physics:0.000, multiplier:1.000, universe:0.000
#
 notificationToggle = new NotificationToggle(this, new Dictionary<NotificationType, bool>()
            {
                { NotificationType.GamePauseToggledMessage, true },
                { NotificationType.PauseStateChangedMessageToggle, true },
                { NotificationType.SolarPanelsIneffectiveMessage, false },
            });

            // configuration
            tnConfig = Config.Bind("Notification Settings", "Toggle Notifications", defaultValue, "Toggle Notifications is a mod that allows you to enable or disable notifications");
            defaultValue = tnConfig.Value;
            tnConfig.Value = true;

            AssistantToTheAssistantPatchManager.ApplyPatches(notificationToggle);
            MainUI = new ToggleNotificationsUI(this, isGUIVisible);
#

see if that fixes it

visual bone
#
GameInstance gameInstance = FindObjectOfType<GameInstance>(); // Get the GameInstance object
MessageCenter messageCenter = gameInstance.Messages; // Access the MessageCenter instance
#

THAT is how you can access the message center and get an INSTANCE of message center

timid quail
#

noooo

visual bone
#

holy crap I had to go hunting in the code to find that shit

timid quail
#

don't do that

visual bone
#

why not?

timid quail
#

the plugin class literally gives you a GameInstance object

visual bone
#

MessageCenter is not a GameInstance object

#

so FindObjectTypeOf

timid quail
#

I mean the first line

visual bone
#

doesnt work

#

so in order to find a gameinstance of message center thats how i have to do it

timid quail
#

that's not how it works

visual bone
#

cause i tried to do FindObjectOfType<MessageCenter>

timid quail
#

you don't get a "gameinstance of message center"

#

Messages is a property on an object of type GameInstance

visual bone
#
 internal ToggleNotificationsUI(ToggleNotificationsPlugin mainPlugin, bool isGUIVisible, MessageCenter messageCenter)
        {
            if (mainPlugin != null && messageCenter != null)
            {
                instance = this;
                this.mainPlugin = mainPlugin;
                this.mainPlugin.isGUIVisible = isGUIVisible;
                this.mainPlugin.messageCenter = messageCenter;
                tabs = new TabsUI();
                tabs.Init();
            }
            else
            {
                Debug.LogError("ToggleNotificationsPlugin instance or MessageCenter is null. ToggleNotificationUI");
            }
        }
#
public override void OnInitialized()
        {
            TNBaseSettings.Init(SettingsPath);

            base.OnInitialized();

            Instance = this;
            Logger = base.Logger;
            Logger.LogInfo("Loaded");

            game = GameManager.Instance.Game;
            MessageCenter messageCenter = game.Messages;
            messageCenter = game.Messages;
            MainUI = new ToggleNotificationsUI(this, isGUIVisible, messageCenter);

#

tahts what i have

timid quail
#

don't even need to do GameManager.Instance.Game

#

your plugin class has an object called Game

#

that's the GameInstance object

#

as well

#

so all you need to get the messages is Game.Messages

visual bone
#
internal ToggleNotificationsUI(
    ToggleNotificationsPlugin mainPlugin,
    bool isGUIVisible)
{
    if (mainPlugin != null)
    {
        instance = this;
        this.mainPlugin = mainPlugin;
        this.mainPlugin.isGUIVisible = isGUIVisible;

        // Find the MessageCenter component in the scene
        MessageCenter messageCenter = GameObject.FindObjectOfType<MessageCenter>();

        if (messageCenter != null)
        {
            this.mainPlugin.messageCenter = messageCenter;
            tabs = new TabsUI();
            tabs.Init();
        }
        else
        {
            Debug.LogError("MessageCenter component not found in the scene. ToggleNotificationUI");
        }
    }
    else
    {
        Debug.LogError("ToggleNotificationsPlugin instance is null. ToggleNotificationUI");
    }
}

I tried this, and it didnt work

#

which makes sense

#

now

timid quail
#

yes, because MessageCenter is not a GameObject

visual bone
#

yup

#

found that out

#
game = GameManager.Instance.Game;
            messageCenter = game.Messages;
            MainUI = new ToggleNotificationsUI(this, isGUIVisible, messageCenter);
#

thats what ive reduced it to

#

the issue is that this doesnt work

timid quail
#

and like I said, you can reduce it to

messageCenter = Game.Messages;
MainUI = new ToggleNotificationsUI(this, isGUIVisible, messageCenter);
visual bone
#

[Error : Unity Log] messageCenter is null

timid quail
visual bone
#

it comes up null

#

every way I've tried so far, messageCenter is null because I can't get access to it

#

so even though that compiles, it doesnt actualy work

#
internal ToggleNotificationsUI(ToggleNotificationsPlugin mainPlugin, bool isGUIVisible, MessageCenter messageCenter)
        {
            if (mainPlugin != null && messageCenter != null)
            {
                instance = this;
                this.mainPlugin = mainPlugin;
                this.mainPlugin.isGUIVisible = isGUIVisible;
                this.mainPlugin.messageCenter = messageCenter;
                tabs = new TabsUI();
                tabs.Init();
            }
            else
            {
                Debug.LogError("ToggleNotificationsPlugin instance or MessageCenter is null. ToggleNotificationUI");
            }
        }
#
  public override void OnInitialized()
        {
            TNBaseSettings.Init(SettingsPath);

            base.OnInitialized();
            
            Instance = this;
            Logger = base.Logger;
            Logger.LogInfo("Loaded");

            game = GameManager.Instance.Game;
            messageCenter = game.Messages;
            MainUI = new ToggleNotificationsUI(this, isGUIVisible, messageCenter);

            // Register Flight AppBar button
            Appbar.RegisterAppButton(
                "Toggle Notifications",
                ToolbarFlightButtonID,
                AssetManager.GetAsset<Texture2D>($"{this.SpaceWarpMetadata.ModID}/images/icon.png"),
                isOpen =>
                {
                    ToggleButton(isOpen, isOpen);
                    Debug.Log($"Initial isWindowOpen value: {interfaceEnabled}");
                }
            );

                notificationToggle = new NotificationToggle(this, new Dictionary<NotificationType, bool>()
                {
                    { NotificationType.GamePauseToggledMessage, true },
                    { NotificationType.PauseStateChangedMessageToggle, true },
                    { NotificationType.SolarPanelsIneffectiveMessage, false },
                });

            // configuration
            tnConfig = Config.Bind("Notification Settings", "Toggle Notifications", defaultValue, "Toggle Notifications is a mod that allows you to enable or disable notifications");
            defaultValue = tnConfig.Value;
            tnConfig.Value = true;

            AssistantToTheAssistantPatchManager.ApplyPatches(notificationToggle);
        }
#

now im going to run it and see what error pops up

timid quail
#

I kinda don't understand why you're setting this.mainPlugin.messageCenter = messageCenter; inside the ToggleNotificationUI class, which you create from the plugin class itself

visual bone
timid quail
#

you can just do that directly in the plugin class before you create the ToggleNotificationUI object

visual bone
#

still learning so if i do things that are weird thats why

#

im simply trying to get this to work and when i get it to compile and i get errors i try to fix them

#

later on i try to figure out how to shorten and clean up the code

#

but the priority i have is getting it to function

#
internal ToggleNotificationsUI(ToggleNotificationsPlugin mainPlugin, bool isGUIVisible, MessageCenter messageCenter)
        {
            if (mainPlugin != null && messageCenter != null)
            {
                instance = this;
                tabs = new TabsUI();
                tabs.Init();
            }
            else
            {
                Debug.LogError("ToggleNotificationsPlugin instance or MessageCenter is null. ToggleNotificationUI");
            }
        }
timid quail
#

basically what you do now is:

  1. get an instance of MessageCenter and assign it to yourPluginClassInstance.messageCenter
  2. create an instance of ToggleNotificationUI and pass yourPluginClassInstance.messageCenter to it
  3. inside the constructor of ToggleNotificationUI, you assign yourPluginClassInstance.messageCenter to yourPluginClassInstance.messageCenter
visual bone
#

thats what i was trying to do is get an instance, i finaly got an instance which mean si can make it not null

#

i didnt realize i had wrote a bunch of redundant code

#

and it oculd be simplified

#

i just knew it was working and now i needed ot make the value not null

#

so i thought i would share how i got the instance for KSP.Messages to be created since it was a pain in the ass to get for me

#

which hindsight, probably very easy for experienced people to do

timid quail
#

honestly, with most of these game-wide systems, you always want to look through the members of GameManager and GameInstance, and chances are you'll find it there

visual bone
#

good to know

#

i went from the end and searched all the way back

#

also i hate how they designed the notification system

#

its like a spider web of doom

#

thats solved, thank you for the help

#

sorry if i came off as brash or whatever

#

also a few more nulls to remove and create instances for. seems to be a trend with my code. i never create an instance for things

#
UnityEngine.GUISkin must be instantiated using the ScriptableObject.CreateInstance method instead of new GUISkin.
custom styles is null
timid quail
#

wait so how did you resolve MessageCenter coming up as null?

visual bone
#

oh

#

haha

#

here

#
  internal ToggleNotificationsUI(ToggleNotificationsPlugin mainPlugin, bool isGUIVisible, MessageCenter messageCenter)
        {
            if (mainPlugin != null && messageCenter != null)
            {
                instance = this;
                this.messageCenter = messageCenter;
                tabs = new TabsUI();
                tabs.Init();
            }
            else
            {
                Debug.LogError("ToggleNotificationsPlugin instance or MessageCenter is null. ToggleNotificationUI");
            }
        }
#

then in the oninit in my plugin

timid quail
#

tbh I just tested getting it in OnInitialized and got it just fine

visual bone
#
public override void OnInitialized()
        {
            TNBaseSettings.Init(SettingsPath);

            base.OnInitialized();

            Instance = this;
            Logger = base.Logger;
            Logger.LogInfo("Loaded");

            game = GameManager.Instance.Game;
            messageCenter = game.Messages;
            MainUI = new ToggleNotificationsUI(this, isGUIVisible, messageCenter);


            // Register Flight AppBar button
            Appbar.RegisterAppButton(
                "Toggle Notifications",
                ToolbarFlightButtonID,
                AssetManager.GetAsset<Texture2D>($"{this.SpaceWarpMetadata.ModID}/images/icon.png"),
                isOpen =>
                {
                    ToggleButton(isOpen, isOpen);
                    Debug.Log($"Initial isWindowOpen value: {interfaceEnabled}");
                }
            );

            notificationToggle = new NotificationToggle(this, new Dictionary<NotificationType, bool>()
    {
        { NotificationType.GamePauseToggledMessage, true },
        { NotificationType.PauseStateChangedMessageToggle, true },
        { NotificationType.SolarPanelsIneffectiveMessage, false },
    });

            // configuration
            tnConfig = Config.Bind("Notification Settings", "Toggle Notifications", defaultValue, "Toggle Notifications is a mod that allows you to enable or disable notifications");
            defaultValue = tnConfig.Value;
            tnConfig.Value = true;

            AssistantToTheAssistantPatchManager.ApplyPatches(notificationToggle);

            // Create an instance of ToggleNotificationsUI and pass the messageCenter instance to it
            ToggleNotificationsUI toggleNotificationsUI = new ToggleNotificationsUI(this, isGUIVisible, messageCenter);
        }
timid quail
#

so I'm not sure where the issue was

visual bone
#

so thats what i did and now i dont get the messagecenter is null

visual bone
#

okay it works but not like i thought

opal lagoon
#

Is that the effect you're going for? Seems a bit off to me.

#

Also, unrelated question to this mod... Is there a way to pan/zoom/rotate camera view in mapview mode that doesn't involve using the mouse? Something with the keyboard perhaps?

visual bone
#

yes

#

but i dont remember how but there are hotkeys binded in the game that let you mess with the camera

#

i could be compeltely wrong

#

its off because i need to fix the logic

#

so im finally able to control the notificaiton but i need to swap the logic

#

so that when its enabled it doesnt show and when its disabled it shows the notif

#

cause thats the whole point, Toggle Notifications

opal lagoon
worn token
#

It's constantly erroring btw

visual bone
#

Weird. I'm not getting errors with it.

worn token
#

I was in the VAB...yep I forgot to mention that

opal lagoon
#

You may want to check the game state and prevent operating in the VAB or other places where the messages you're looking to disable are not possible.

timid quail
#

happens every time I load into this save which is in VAB

opal lagoon
timid quail
#

I mean the pause/unpause notification probably shouldn't be happening in the VAB

#

but I'd say that that's the only thing that is for sure

#

but the exception seems to be coming from the TN UI anyway

opal lagoon
#

If a mod is throwing NREs in the VAB and not elsewhere, then I'd think look first at what the NREs are coming from, but consider if limiting based on games state makes sense.

timid quail
#

yeah that was kinda my point, seems like they happen in the VAB, too

visual bone
#
private void OnGUI()
        {
            _isGUIenabled = false;
            GameState? state = BaseSpaceWarpPlugin.Game?.GlobalGameState?.GetState();
            GameState? nullable = state;
            GameState gameState1 = GameState.Map3DView;
            if (nullable.GetValueOrDefault() == gameState1 & nullable.HasValue)
                _isGUIenabled = true;
            nullable = state;
            GameState gameState2 = GameState.FlightView;
            if (nullable.GetValueOrDefault() == gameState2 & nullable.HasValue)
                _isGUIenabled = true;
           //game.Messages = GameManager.Instance?.Game?.Messages?.Subscribe<DiscoverableMessage>(message =>

            if (_isGUIenabled)
            {
                TNStyles.Init();
                WindowTool.CheckMainWindowPos(ref windowRect, windowWidth);
                GUI.skin = TNBaseStyle.Skin;
                this._activeVessel = GameManager.Instance?.Game?.ViewController?.GetActiveVehicle(true)?.GetSimVessel();
                if (!this._interfaceEnabled || !this._isGUIenabled || this._activeVessel == null)
                    return;

                this.windowRect = GUILayout.Window(
                    GUIUtility.GetControlID(FocusType.Passive),
                    this.windowRect,
                    MainUI.FillWindow,
                    "<color=#696DFF>TOGGLE NOTIFICATIONS</color>",
                    GUILayout.Height(0.0f),
                    GUILayout.Width((float)this.windowWidth),
                    GUILayout.MinHeight(400) // Adjust the value to your desired height
                );

                saverectpos();
                //tooltips
                UIFields.CheckEditor();
            }
        }
#

ohh

#

okay yeah, that i havent figured out

#

i get a few notifications right away when i load in

#

thats on my "to fix list"

#

now i undersatnd what ya'll are talking about

visual bone
#
bool gamePauseToggle = GUI.Toggle(new Rect(3, 56, buttonWidth, 20), isToggled, "Game Pause", selectedButton2 == 1 ? TNBaseStyle.Toggle : TNBaseStyle.ToggleError);
            TNBaseStyle.Toggle.normal.textColor = selectedButton1 == 1 ? ColorTools.ParseColor("#C0C1E2") : ColorTools.ParseColor("#C0E2DC");
            TNBaseStyle.ToggleError.normal.textColor = selectedButton1 == 0 ? Color.red : ColorTools.ParseColor("#C0E2DC");
            if (gamePauseToggle != isToggled)
            {
                isToggled = gamePauseToggle;
                ButtonToggle1(gamePauseToggle ? 1 : 0);
            }
#

cool... glad I didn't review this

#

selectedButton2? KEKW

worn token
#

Right click maybe?

visual bone
#

ive made four buttons, 3 of them dont do anything right now

#

so selectedButton2 is the placeholder for the solar notification

#

but it doesnt do anything

#

other than turn itself on and off

#

but its not controlling anything, its just UI

#

but now

#

when i click on my UI and toggle it on and off, i dont toggle the game pause on and off anymore

#

also do we need to do this?

[Warning:Space Warp] The swinfo.json "mod_id" property is deprecated and will be removed in a future version. Instead of ModID, use PluginClass.Info.Metadata.GUID in your code.
[Info :spacewarp/modlist/modlist.uss] registering path "spacewarp/modlist/modlist.uss"

PluginClass.Info.Metadata.GUID

visual bone
visual bone
opal lagoon
#

Looking good!

visual bone
#

Still can't turn the notification back on yet. 🤣

visual bone
#

Toggle Notifications devlog [0.2.3-dev]

visual bone
#
        //Solar Panel Patches 
         [HarmonyPatch(typeof(NotificationEvents))] 
         internal static class SolarPanelsIneffectiveMessagePatch 
         { 
             [HarmonyTranspiler] 
             [HarmonyPatch("SolarPanelsIneffectiveMessage")] 
             internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) 
             { 
                 Logger.LogInfo("Transpiler Loaded for SolarPanelsIneffectiveMessage in NotificationEvents"); 
                 return TranspilerLogic(instructions); 
             } 
         }
visual bone
#

got it working, so now solarpanelineffective is blocked. but i cant reenable them yet

#

that sokay, ill get it working slowly

#

0.2.3 is adding hopefully all of these. solar panels is working now

visual bone
#
[Known Issues]
Game Pause Button:

Issue: The game pause button is always disabled regardless of whether you toggle it on or off.
Possible cause: The logic in the GamePauseButtonToggle method may not be correctly updating the relevant variables.
Solution: Review the implementation of the GamePauseButtonToggle method and ensure that it correctly updates the variables related to the game pause functionality. Make sure that the correct values are being assigned to mainPlugin.notificationToggle.CheckCurrentState and AssistantToTheAssistantPatchManager based on the toggle value.



Solar Panel Ineffective Button:

Issue: The solar panel ineffective button is always enabled regardless of whether you toggle it on or off.
Possible cause: The logic in the ButtonToggle2 method may not be correctly updating the relevant variables.
Solution: Review the implementation of the ButtonToggle2 method and ensure that it correctly updates the variables related to the solar panel ineffective functionality. Make sure that the correct values are being assigned to mainPlugin.notificationToggle.CheckCurrentState and AssistantToTheAssistantPatchManager based on the toggle value.
visual bone
#

"I'm just going to organize and clean up the code a bit, and focus on functionality. I'm not going to add more features or buttons..."

visual bone
#

Okay so now when you lose sunlight on your solar panels they don't display the part ineffective anymore. They autoadjust

visual bone
#
[Info   :  HarmonyX] Running ILHook manipulator on void KSP.Game.NotificationEvents::SolarPanelsIneffectiveMessage(KSP.Messages.MessageCenterMessage msg)
[Info   :  HarmonyX] Transpiling void KSP.Game.NotificationEvents::SolarPanelsIneffectiveMessage(KSP.Messages.MessageCenterMessage msg)
[Info   :  HarmonyX] Running transpiler static System.Collections.Generic.IEnumerable<HarmonyLib.CodeInstruction> ToggleNotifications.AssistantToTheAssistantPatchManager+SolarPanelsIneffectiveMessagePatch::Transpiler(System.Collections.Generic.IEnumerable<HarmonyLib.CodeInstruction> instructions)
[Info   :AssistantToTheAssistantPatchManager] Transpiler Loaded for SolarPanelsIneffectiveMessage in NotificationEvents
#

success

visual bone
opal lagoon
#

LOL, you and the dating sim...

#

I'd put that under experimental features if I were you.

visual bone
#

LUL

#

i totally forgot about that

#

and i just pushed the 0.2.3 update

#

Toggle Notifications devlog [0.2.4-dev]

wanton lava
wanton lava
#

lol rip

visual bone
#

andddd spacedock is down for right now

visual bone
opal lagoon
#

Really? All those? Fantastic dude!

visual bone
#

Getting tricky testing these lol

#

out of comm range isnt functioning properly. but thats because it works how game pause does and has multiple ways it sends its notification

#

solar panel is straightforward and easy same as out of electricity

#

lost control im having issues getting properly patched but should ahve it all sorted out for 0.2.4

#

game pause will probably stay disabled by default until later on

#

once i figured out solar panel the other ones came easily

#

its just identifying if a notification has one route or multiple.

rule of thumb:

if it only uses notificationevents its pretty easy to patch

if it uses notificationevents and messagecenter

its a pain

#

but i finally undersatnd what im doing, which is super fun. also trying to get the windows to auto-space themselves. it works but only if every UI element is it's own OnGUI

#
GUILayout.BeginVertical();

GUILayout.FlexibleSpace();
            
GUILayout.BeginVertical(GUILayout.Height(60));
 int buttonWidth = Mathf.RoundToInt(mainPlugin.windowRect.width - 12); // Subtract 3 on each side for padding
 int buttonHeight = 20;
 int buttonSpacing = 10;
 int currentY = 56; 

 gamePauseButton.OnGUI();
 currentY += buttonHeight + buttonSpacing;
GUILayout.EndVertical();

// Group 3: Version Number
            GUIStyle nameLabelStyle = new GUIStyle()
            {
                border = new RectOffset(3, 3, 5, 5),
                padding = new RectOffset(3, 3, 4, 4),
                overflow = new RectOffset(0, 0, 0, 0),
                normal = { textColor = ColorTools.ParseColor("#C0C1E2") },
                alignment = TextAnchor.MiddleRight
            };

            GUILayout.FlexibleSpace();

            GUILayout.Label("v0.2.4", nameLabelStyle);

            GUILayout.Box(GUIContent.none, TNBaseStyle.Separator);

mainPlugin.windowRect.height = currentY + buttonHeight + buttonSpacing;```
visual bone
#
GUI.DragWindow(new Rect(0.0f, 0.0f, 10000f, 500f));

            if (Event.current.type == EventType.MouseUp)
            {
                mainPlugin.saverectpos();
            }

            mainPlugin.windowRect.height = currentY + buttonHeight + buttonSpacing;

this may work better

visual bone
#

it helps if I'd enable these when i initialize the plugin

notificationToggle = new NotificationToggle(this, new Dictionary<NotificationType, bool>()
            {
                { NotificationType.GamePauseToggledMessage, true },
                { NotificationType.SolarPanelsIneffectiveMessage, true },
                { NotificationType.CannotPlaceManeuverNodeWhileOutOfFuelMessage, true },
                { NotificationType.VesselOutOfElectricity, true },
                { NotificationType.VesselLostControlMessage, true },
                { NotificationType.VesselLeftCommunicationRangeMessage, true },
                { NotificationType.CannotChangeNodeWhileOutOfFuelMessage, true },
            });
#

i only had gamepausetoggledmessage and solarpanelsineffective set. which is why none of the new notifications were working

#

now it works

visual bone
#

the organizational effort pleases me

visual bone
visual bone
#

FINALLY

#

got the gear button working

visual bone
opal lagoon
#

Excellent video! Really shows off the glorious absence of obtrusive notices. If you're gonna give your builds names, then ChatGPT suggested this... G.O.N.E. - "Gone, Obviating Numerous Entities"

visual bone
#
Patch notes:

*added settings page to view status of notifications
**added these notifications:
-CannotPlaceManeuverNodeWhileOutOfFuelMessage
-VesselOutOfElectricity
-VesselLostControlMessage
-VesselLeftCommunicationRangeMessage
-CannotChangeNodeWhileOutOfFuelMessage
**reorganized mod and pathing
**removed unused code
visual bone
#

Toggle Notifications devlog

visual bone
#
0.2.5 Update:
**All Notifications are able to be enabled/disabled properly
[x] - Game Pause
[x] - Solar
[x] - Electricity
[x] - commrange
[ ] - outoffuel
[ ] - vessel lost control

two more to fix, then 0.2.5 is released
visual bone
#

@junior iris when you get a chance, I wanted your help making sure I installed and setup unity correctly with thunderkit etc. Next mod I make I want to make a simple model to learn. It won't be a mod I release, just more of learning how to make something simple, add it into the game, and it function properly.

junior iris
#

Obviously dw 🤞🤞 munix is making a template for that btw

visual bone
#

Toggle Notifications 0.2.5 will be coming out in the next week or so. Still testing making sure the notifications are turned on and off properly and don't cause havoc

opal lagoon
#

Cry havoc, and release the dogs of Toggle Notifications 0.2.5!

#

Who let the dogs out? Who? Who? Who?

visual bone