]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
WIP profile apply fix: subscribe to cvar changes
authorColdSpirit <coldspiritvolf@gmail.com>
Thu, 20 Jan 2022 23:58:48 +0000 (03:58 +0400)
committerColdSpirit <coldspiritvolf@gmail.com>
Thu, 20 Jan 2022 23:58:48 +0000 (03:58 +0400)
qcsrc/dpdefs/upstream/menudefs.qc
qcsrc/menu/_mod.inc
qcsrc/menu/_mod.qh
qcsrc/menu/cvarcallbackitem.qc [new file with mode: 0644]
qcsrc/menu/cvarcallbackitem.qh [new file with mode: 0644]
qcsrc/menu/menu.qc
qcsrc/menu/menu.qh
qcsrc/menu/xonotic/dialog_multiplayer_profile.qc
qcsrc/menu/xonotic/dialog_multiplayer_profile.qh

index 63d2c6388e8447e90e46445abbe65506e93e074b..47549c82c7d6ac2f180a9983dc01f0b23e090511 100644 (file)
@@ -18,6 +18,7 @@ void(float keynr, float ascii) m_keydown;
 void(float width, float height) m_draw;
 void(float mode) m_toggle;
 void() m_shutdown;
+void(string name, string oldValue, string newValue) m_cvar_changed;
 // optional: float(float) m_gethostcachecategory;
 
 /////////////////////////////////////////////////////////
index d2a8d702f16ad3241b92011889b7a52da3599bd4..b029bc1cfb8e8c985b0997603802c76af7072556 100644 (file)
@@ -1,4 +1,5 @@
 // generated file; do not modify
+#include <menu/cvarcallbackitem.qc>
 #include <menu/draw.qc>
 #include <menu/item.qc>
 #include <menu/matrix.qc>
index da8675831a4d8e130e66df558f7ecb102625ce5a..f3020f519dfe248db784a0cde1000ed0ba303db6 100644 (file)
@@ -1,4 +1,5 @@
 // generated file; do not modify
+#include <menu/cvarcallbackitem.qh>
 #include <menu/draw.qh>
 #include <menu/item.qh>
 #include <menu/matrix.qh>
diff --git a/qcsrc/menu/cvarcallbackitem.qc b/qcsrc/menu/cvarcallbackitem.qc
new file mode 100644 (file)
index 0000000..da9aabc
--- /dev/null
@@ -0,0 +1,11 @@
+#include "cvarcallbackitem.qh"
+
+entity createCvarCallbackItem(string theCvarName, cvar_callback theCallback, entity theContext)
+{
+       entity item;
+       item = NEW(CvarCallbackItem);
+       item.cvarName = theCvarName;
+       item.callback = theCallback;
+       item.context = theContext;
+       return item;
+}
\ No newline at end of file
diff --git a/qcsrc/menu/cvarcallbackitem.qh b/qcsrc/menu/cvarcallbackitem.qh
new file mode 100644 (file)
index 0000000..0b8621d
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma once
+
+#define cvar_callback void(string, string, string, entity)
+
+CLASS(CvarCallbackItem, Object)
+       ATTRIB(CvarCallbackItem, cvarName, string);
+       ATTRIB(CvarCallbackItem, callback, cvar_callback); // old value, new value
+       ATTRIB(CvarCallbackItem, context, entity);
+ENDCLASS(CvarCallbackItem)
+
+entity createCvarCallbackItem(string theCvarName, cvar_callback theCallback, entity theContext);
\ No newline at end of file
index 710dca1e6685be3d57671237bd9a1647148cfa55..0eb3def831511c6fd808f938ebbab01eaab38ddd 100644 (file)
@@ -416,9 +416,9 @@ int menuTooltipState;  // 0: static, 1: fading in, 2: fading out, 3: forced fadi
 bool m_testmousetooltipbox(vector pos)
 {
        return !(
-           (pos.x >= menuTooltipOrigin.x && pos.x < menuTooltipOrigin.x + menuTooltipSize.x)
-           && (pos.y >= menuTooltipOrigin.y && pos.y < menuTooltipOrigin.y + menuTooltipSize.y)
-               );
+               (pos.x >= menuTooltipOrigin.x && pos.x < menuTooltipOrigin.x + menuTooltipSize.x)
+               && (pos.y >= menuTooltipOrigin.y && pos.y < menuTooltipOrigin.y + menuTooltipSize.y)
+                       );
 }
 bool m_testtooltipbox(vector tooltippos)
 {
@@ -710,12 +710,12 @@ void m_draw(float width, float height)
        {
                menuNotTheFirstFrame = true;
                if (Menu_Active && !cvar("menu_video_played"))
-        {
-            localcmd("cd loop $menu_cdtrack\n");
-            // TODO: use this when we have a welcome sound
-            //localcmd("cd loop $menu_cdtrack; play sound/announcer/default/welcome.wav\n");
-            menuLogoAlpha = -0.8;  // no idea why, but when I start this at zero, it jumps instead of fading FIXME
-        }
+               {
+                       localcmd("cd loop $menu_cdtrack\n");
+                       // TODO: use this when we have a welcome sound
+                       //localcmd("cd loop $menu_cdtrack; play sound/announcer/default/welcome.wav\n");
+                       menuLogoAlpha = -0.8;  // no idea why, but when I start this at zero, it jumps instead of fading FIXME
+               }
                // ALWAYS set this cvar; if we start but menu is not active, this means we want no background music!
                localcmd("set menu_video_played 1\n");
        }
@@ -739,8 +739,8 @@ void m_draw(float width, float height)
        if (Menu_Active)
        {
                if (getmousetarget() == (menuMouseMode ? MT_CLIENT : MT_MENU)
-                   && (getkeydest() == KEY_MENU || getkeydest() == KEY_MENU_GRABBED))
-                       setkeydest(keyGrabber ? KEY_MENU_GRABBED : KEY_MENU);
+                       && (getkeydest() == KEY_MENU || getkeydest() == KEY_MENU_GRABBED))
+                               setkeydest(keyGrabber ? KEY_MENU_GRABBED : KEY_MENU);
                else m_hide();
        }
 
@@ -999,3 +999,30 @@ void m_play_click_sound(string soundfile)
        if (!cvar("menu_sounds")) return;
        localsound(soundfile);
 }
+
+void m_cvar_changed(string theCvarName, string oldValue, string newValue)
+{
+       if (!menuInitialized) return;
+
+       // some variables have name "\n"
+       // LOG_INFOF("========> QC: Cvar \"%s\" changed from \"%s\" to \"%s\"",
+       //     strreplace("\n", "\\n", theCvarName),
+       //     strreplace("\n", "\\n", oldValue),
+       //     strreplace("\n", "\\n", newValue)
+       // );
+
+       // search for subscribed callbacks and call them
+       IL_EACH(cvarCallbackItems, it.cvarName == theCvarName, 
+       {
+               // LOG_INFOF("=========> Callback triggered for %s", it.name);
+               entity theContext = it.context;
+               it.callback(theCvarName, oldValue, newValue, theContext);
+       });
+}
+
+void cvar_onChangeSubscribe(string theCvarName, cvar_callback theCallback, entity theContext)
+{
+       entity callbackItem;
+       callbackItem = createCvarCallbackItem(theCvarName, theCallback, theContext);
+       IL_PUSH(cvarCallbackItems, callbackItem);
+}
\ No newline at end of file
index 2df331950848c1dcdab9c53b63d9ebd553a3cb9a..5243b6059c9971a8d25d8b69e7bf4925d63241e3 100644 (file)
@@ -8,6 +8,8 @@
 #include <common/constants.qh>
 #include <common/util.qh>
 
+#include "cvarcallbackitem.qh"
+
 const int GAME_ISSERVER     = BIT(0);
 const int GAME_CONNECTED    = BIT(1);
 const int GAME_DEVELOPER    = BIT(2);
@@ -57,3 +59,8 @@ const string MENU_SOUND_WINNER  = "sound/menu/winner.wav";
 
 void m_play_focus_sound();
 void m_play_click_sound(string soundfile);
+
+// callback list and method to subscribe
+IntrusiveList cvarCallbackItems;
+STATIC_INIT(cvarCallbackItems) { cvarCallbackItems = IL_NEW(); }
+void cvar_onChangeSubscribe(string, cvar_callback, entity);
\ No newline at end of file
index e885ee0b0de1e42b1213d463c3bd851ff8391281..028c740e0212f1c0ccdd3a534877fbb53d835264 100644 (file)
@@ -23,17 +23,94 @@ entity makeXonoticProfileTab()
        me = NEW(XonoticProfileTab);
        me.configureDialog(me);
 
+       string name = cvar_string("_cl_name");
+       string playermodel = cvar_string("_cl_playermodel");
+       string playerskin = cvar_string("_cl_playerskin");
+       string color = cvar_string("_cl_color");
+
        // if color unset, set random color (init it)
-       if (cvar_string("_cl_color") == cvar_defstring("_cl_color"))
+       if (color == cvar_defstring("_cl_color"))
        {
                // idk what meaning of 16, maybe just COLOR_BUTTONS_COUNT+1
                float randomColor = 16 * floor(random() * COLOR_BUTTONS_COUNT) + floor(random() * COLOR_BUTTONS_COUNT);
-               cvar_set("_cl_color", ftos(randomColor));
+               color = ftos(randomColor);
+               cvar_set("_cl_color", color);
        }
 
+       // copy field values from game cvars
+       cvar_set(MENU_CVAR_COLOR, color);
+       cvar_set(MENU_CVAR_NAME, name);
+       cvar_set(MENU_CVAR_SKIN, playerskin);
+       cvar_set(MENU_CVAR_MODEL, playermodel);
+
+       // subscribe to cvar changes
+
+       // stable branch cvars
+       cvar_onChangeSubscribe("_cl_name", onCvarChanged, me);
+       cvar_onChangeSubscribe("_cl_color", onCvarChanged, me);
+       cvar_onChangeSubscribe("_cl_playermodel", onCvarChanged, me);
+
+       // master branch cvars
+       cvar_onChangeSubscribe("name", onCvarChanged, me);
+       cvar_onChangeSubscribe("topcolor", onCvarChanged, me);
+       cvar_onChangeSubscribe("bottomcolor", onCvarChanged, me);
+       cvar_onChangeSubscribe("playermodel", onCvarChanged, me);
+
        return me;
 }
 
+// if values changed from console, update it in menu
+void onCvarChanged(string cvarName, string oldValue, string newValue, entity me)
+{
+       // IMPORTANT: dont change same cvars that was observed to avoid infinite loop
+
+       // nothing to change
+       if (oldValue == newValue)
+       {
+               return;
+       }
+
+       // not update field values when tab in 'edit mode'
+       if (!me.applyButton.disabled)
+       {
+               return;
+       }
+
+       // LOG_INFOF("[onCvarChanged]: %s, %s, %s", cvarName, oldValue, newValue);
+
+       // name
+       if (cvarName == "_cl_name" || cvarName == "name")
+       {
+               cvar_set(MENU_CVAR_NAME, newValue);
+               me.nameInput.loadCvars(me.nameInput);
+       }
+
+       // model
+       else if (cvarName == "_cl_playermodel" || cvarName == "playermodel")
+       {
+               cvar_set(MENU_CVAR_MODEL, newValue);
+               me.playerModelSelector.loadCvars(me.playerModelSelector);
+               me.playerModelSelector.go(me.playerModelSelector, 0);
+       }
+
+       // skin (skin not tested, dont know what cvars it use)
+       // else if (cvarName == "_cl_playerskin" || cvarName == "playerskin")
+       // {
+       // }
+
+       // color
+       else if (cvarName == "_cl_color")
+       {
+               cvar_set(MENU_CVAR_COLOR, newValue);
+               me.updateColor(me);
+       }
+       else if (cvarName == "topcolor" || cvarName == "bottomcolor")
+       {
+               cvar_set(MENU_CVAR_COLOR, cvar_string("_cl_color"));
+               me.updateColor(me);
+       }
+}
+
 void XonoticProfileTab_draw(entity me)
 {
        string name = cvar_string("_cl_name");
@@ -42,44 +119,6 @@ void XonoticProfileTab_draw(entity me)
                me.playerNameLabel.alpha = ((mod(time * 2, 2) < 1) ? 1 : 0);
        else
                me.playerNameLabel.alpha = me.playerNameLabelAlpha;
-       
-       // if values changed from console, update it in menu
-       if (me.applyButton.disabled)
-       {
-               // name field
-               string inputName  = cvar_string(MENU_CVAR_NAME);
-               if (name != inputName)
-               {
-                       cvar_set(MENU_CVAR_NAME, name);
-                       me.nameInput.loadCvars(me.nameInput);
-               }
-
-               // color buttons
-               string color = cvar_string("_cl_color");
-               string inputColor = cvar_string(MENU_CVAR_COLOR);
-               if (color != inputColor)
-               {
-                       cvar_set(MENU_CVAR_COLOR, color);
-                       for (int i = 0; i < COLOR_BUTTONS_COUNT; i++)
-                       {
-                               me.colorButtonGroup1[i].loadCvars(me.colorButtonGroup1[i]);
-                               me.colorButtonGroup2[i].loadCvars(me.colorButtonGroup2[i]);
-                       }
-               }
-
-               // player model
-               string skin = cvar_string("_cl_playerskin");
-               string skinInput = cvar_string(MENU_CVAR_SKIN);
-               string model = cvar_string("_cl_playermodel");
-               string modelInput = cvar_string(MENU_CVAR_MODEL);
-               if (skin != skinInput || model != modelInput)
-               {
-                       cvar_set(MENU_CVAR_SKIN, skin);
-                       cvar_set(MENU_CVAR_MODEL, model);
-                       me.playerModelSelector.loadCvars(me.playerModelSelector);
-                       me.playerModelSelector.go(me.playerModelSelector, 0);
-               }
-       }
 
        SUPER(XonoticProfileTab).draw(me);
 }
@@ -92,7 +131,7 @@ void XonoticProfileTab_fill(entity me)
        entity e, label;
        float i;
        me.applyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0',
-               "_cl_color \"$"MENU_CVAR_COLOR"\""
+               "_cl_color \"$"MENU_CVAR_COLOR"\";"
                "color -1 -1;" // apply colors contained in _cl_color
                "name \"$"MENU_CVAR_NAME"\";"
                "playermodel $"MENU_CVAR_MODEL";"
@@ -221,3 +260,12 @@ void XonoticProfileTab_fill(entity me)
        me.gotoRC(me, me.rows - 1, 0);
                me.TD(me, 1, me.columns, me.applyButton);
 }
+
+void XonoticProfileTab_updateColor(entity me)
+{
+       for (int i = 0; i < COLOR_BUTTONS_COUNT; i++)
+       {
+               me.colorButtonGroup1[i].loadCvars(me.colorButtonGroup1[i]);
+               me.colorButtonGroup2[i].loadCvars(me.colorButtonGroup2[i]);
+       }
+}
\ No newline at end of file
index ccf7725181eb85dbae44eba300fb641b7f6054b7..db7393613c93616db6b011c7826ef0b2e2122636 100644 (file)
@@ -5,6 +5,7 @@ const int COLOR_BUTTONS_COUNT = 15;
 CLASS(XonoticProfileTab, XonoticTab)
        METHOD(XonoticProfileTab, fill, void(entity));
        METHOD(XonoticProfileTab, draw, void(entity));
+       METHOD(XonoticProfileTab, updateColor, void(entity));
        ATTRIB(XonoticProfileTab, intendedWidth, float, 0.9);
        ATTRIB(XonoticProfileTab, rows, float, 23);
        ATTRIB(XonoticProfileTab, columns, float, 6.1);  // added extra .2 for center space
@@ -17,3 +18,5 @@ CLASS(XonoticProfileTab, XonoticTab)
        ATTRIB(XonoticProfileTab, playerModelSelector, entity);
 ENDCLASS(XonoticProfileTab)
 entity makeXonoticProfileTab();
+
+cvar_callback onCvarChanged;
\ No newline at end of file