Advertisement
Guest User

Untitled

a guest
Jan 18th, 2020
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 5.84 KB | None | 0 0
  1.     Mute Notifications
  2.     Award Token
  3.     Flag For Later
  4.  
  5. Tags
  6. None
  7. Subscribers
  8. None
  9. Tokens
  10. "Like" token, awarded by asterix.
  11. This revision needs review, but there are no reviewers specified.
  12. Details
  13.  
  14. Reviewers
  15.     None
  16. Trac Tickets
  17.     #5387
  18.     #5322
  19.  
  20. Summary
  21.  
  22. The purpose of this diff is to
  23. (1) move from procedural to object oriented code for the AIconfig page (#5387)
  24. (2) update the AIconfig page without closing it and reopening it on the same frame
  25. (3) run it in the same page context as the GameSetup page in order to
  26. (3A) reuse the Gamesetup controller classes instead of reimplementing them, and
  27. (3A) provide an example for future gamesetup subpages that will more clearly benefit from running in the same context.
  28. (4) Change AIConfig page to have changes take effect immediately after changing the dropdowns.
  29.  
  30. This is necessary for the user choice to not be lost in case there are multiple gamesetup controllers (i.e. preparation for #3806).
  31.  
  32. (5) Hide AIDifficulty, AIBehavior if no AI is assigned and hide AIBehavior for Sandbox AI.
  33. Test Plan
  34.  
  35. To evaluate the sanity of the approach, consider the following:
  36.  
  37.     It is possible to implement a C++ GUI diff that allows one GUI page to send data to another GUI page. This however may come with its own catches, possibly dangling references, certainly a reimplementation of the onGameAttributesChange and updateGameAttributes code and hardcoding of references from one GUI page to another (misleading devs that they can code in that one page without considering other pages). The network dialog in D1746 also needed to be updated from the session. For that feature I implemented it using this C++ method:
  38.  
  39. diff --git a/source/gui/scripting/JSInterface_GUIPage.cpp b/source/gui/scripting/JSInterface_GUIPage.cpp
  40. new file mode 100644
  41. index 0000000000..ed39ac195e
  42. --- /dev/null
  43. +++ b/source/gui/scripting/JSInterface_GUIPage.cpp
  44. @@ -0,0 +1,99 @@
  45. +/* Copyright (C) 2018 Wildfire Games.
  46. + * This file is part of 0 A.D.
  47. + *
  48. + * 0 A.D. is free software: you can redistribute it and/or modify
  49. + * it under the terms of the GNU General Public License as published by
  50. + * the Free Software Foundation, either version 2 of the License, or
  51. + * (at your option) any later version.
  52. + *
  53. + * 0 A.D. is distributed in the hope that it will be useful,
  54. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  55. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  56. + * GNU General Public License for more details.
  57. + *
  58. + * You should have received a copy of the GNU General Public License
  59. + * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
  60. + */
  61. +
  62. +#include "precompiled.h"
  63. +
  64. +#include "JSInterface_GUIPage.h"
  65. +
  66. +#include "gui/CGUI.h"
  67. +#include "gui/GUIManager.h"
  68. +#include "scriptinterface/ScriptInterface.h"
  69. +
  70. +JSClass JSI_GUIPage::JSI_class = {
  71. +   "GUIPage", JSCLASS_HAS_PRIVATE,
  72. +   nullptr, nullptr,
  73. +   JSI_GUIPage::GetProperty, JSI_GUIPage::SetProperty,
  74. +   nullptr, nullptr, nullptr, nullptr,
  75. +   nullptr, nullptr, nullptr, nullptr
  76. +};
  77. +
  78. +void JSI_GUIPage::RegisterScriptClass(ScriptInterface& scriptInterface)
  79. +{
  80. +   scriptInterface.DefineCustomObjectType(&JSI_class, nullptr, 1, nullptr, nullptr, nullptr, nullptr);
  81. +}
  82. +
  83. +bool JSI_GUIPage::GetProperty(JSContext* cxSource, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
  84. +{
  85. +   JSAutoRequest rqSource(cxSource);
  86. +
  87. +   JS::RootedValue idval(cxSource);
  88. +   if (!JS_IdToValue(cxSource, id, &idval))
  89. +       return false;
  90. +
  91. +   std::string functionName;
  92. +   if (!ScriptInterface::FromJSVal(cxSource, idval, functionName))
  93. +       return false;
  94. +
  95. +   JS::RootedObject parent(cxSource);
  96. +   JS::Rooted<JSFunction*> function(cxSource, JS_NewFunction(cxSource, JSI_GUIPage::CallFunction, 1, 0, obj, functionName.c_str()));
  97. +   vp.setObject(*JS_GetFunctionObject(function));
  98. +   return true;
  99. +}
  100. +
  101. +bool JSI_GUIPage::SetProperty(JSContext* cx, JS::HandleObject UNUSED(obj), JS::HandleId UNUSED(id), bool UNUSED(strict), JS::MutableHandleValue UNUSED(vp))
  102. +{
  103. +   JS_ReportError(cx, "Page settings are immutable.");
  104. +   return true;
  105. +}
  106. +
  107. +bool JSI_GUIPage::CallFunction(JSContext *cxSource, unsigned argc, JS::Value *vp)
  108. +{
  109. +   // Determine function name
  110. +   JSAutoRequest rqSource(cxSource);
  111. +   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
  112. +   JS::RootedValue functionNameValue(cxSource, JS::StringValue(JS_GetFunctionId(JS_ValueToFunction(cxSource, args.calleev()))));
  113. +   std::string functionNameString;
  114. +   ScriptInterface::FromJSVal(cxSource, functionNameValue, functionNameString);
  115. +
  116. +   // Determine target GUI page from the private data
  117. +   JS::RootedObject thisObj(cxSource, &args.thisv().toObject());
  118. +   CGUI* guiPage = static_cast<CGUI*>(JS_GetInstancePrivate(cxSource, thisObj, &JSI_GUIPage::JSI_class, nullptr));
  119. +
  120. +   if (!g_GUI->IsPageOpen(guiPage))
  121. +   {
  122. +       JS_ReportError(cxSource, "GUIPage is not open.");
  123. +       return true;
  124. +   }
  125. +
  126. +   {
  127. +       ScriptInterface* scriptInterfaceSource = ScriptInterface::GetScriptInterfaceAndCBData(cxSource)->pScriptInterface;
  128. +       JSContext* cxDestination = guiPage->GetScriptInterface()->GetContext();
  129. +       JSAutoRequest rqDestination(cxDestination);
  130. +       JS::RootedValue global(cxDestination, guiPage->GetGlobalObject());
  131. +       JS::RootedValue argument(cxDestination, argc > 0 ? guiPage->GetScriptInterface()->CloneValueFromOtherContext(*scriptInterfaceSource, args[0]) : JS::UndefinedValue());
  132. +       JS::RootedValue returnValueDestination(cxDestination);
  133. +
  134. +       // Call the function of the determined name in the context of the other page
  135. +       guiPage->GetScriptInterface()->CallFunction(global, functionNameString.c_str(), &returnValueDestination, argument);
  136. +
  137. +       // Clone return value
  138. +       JS::RootedValue returnValueSource(cxSource, scriptInterfaceSource->CloneValueFromOtherContext(*guiPage->GetScriptInterface(), returnValueDestination));
  139. +       JS::CallReceiverFromVp(vp).rval().set(returnValueSource);
  140. +   }
  141. +
  142. +   return true;
  143. +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement