本文内容
第13章 Gem Set Window Position
第13章 Gem: Set Window Position
注意:您可以在 GitHub 上找到本章的代码: https://github.com/AMZN-Olex/O3DEBookCode2111/tree/ch13_gem_window_position
简介和动机
在本章中,我们将实现我们的第一个 gem。它不会引入任何新组件,但会注册一个新的控制台命令,该命令将允许用户设置游戏应用程序或 Editor 的窗口位置。如果您需要启动一个服务器和几个客户端,而它们之间不会相互重叠,这在多人游戏测试中通常很有用。默认情况下,O3DE 引擎会将两个客户端窗口置于同一位置。在某些时候,您可能会厌倦了手动移动这些窗口,并开始怀疑是否可以以某种方式自动化该过程。是的,您可以。本章将向您展示如何作。
使用此 Gem,您将能够通过将命令传递给游戏启动器启动参数来设置窗口位置,例如:
MyProject.GameLauncher.exe +SetWindowXY 100 200
SetWindowXY 将需要两个参数:距屏幕左上角的 x 和 y 距离,以放置 O3DE 应用程序的左上角。
创建 WindowPosition Gem
如上一章所示,我们首先创建一个新的 gem,该 gem 将容纳 console 命令。
C:\O3DE\21.11.2\scripts\o3de.bat create-gem
-gp C:\git\book\Gems\WindowPosition
然后向 project.json 注册其位置。
"external_subdirectories": [
"C:/git/book/Gems/MyGem",
"C:/git/book/Gems/WindowPosition"
]
并按其名称为项目启用它。
set(ENABLED_GEMS
...
MyGem
WindowPosition # new
)
控制台子系统
O3DE 允许您使用 AzCore/Console/IConsole.h 中的 AZ::Console 宏添加控制台命令。
图 13.1.IConsole 代码段
//! @class IConsole
//! A simple console class for providing text
//! based variable and process interaction.
class IConsole
有许多有用的宏可以注册新的控制台命令和变量。
- 本章我将使用 AZ_CONSOLEFREEFUNC 在调用 AZ::Console 命令时将免费函数注册为回调。
- 还有一些AZ_CONSOLEFUNC将回调实现为类成员函数。
例 13.1.AZ_CONSOLEFUNC 使用情况
class ConsoleTests
{
...
void TestClassFunc(const AZ::ConsoleCommandContainer& someStrings);
AZ_CONSOLEFUNC(ConsoleTests, TestClassFunc, AZ::ConsoleFunctorFlags::Null, "");
- AZ_CVAR创建一个控制台变量。
AZ_CVAR(int32_t, cloth_DebugDraw, 0, nullptr,
AZ::ConsoleFunctorFlags::Null,
"Draw cloth wireframe mesh:\n"
" 0 - Disabled\n"
" 1 - Cloth wireframe and particle weights");
可以按其名称 cloth_DebugDraw 在同一源文件中使用。
if (cloth_DebugDraw == 1) { /*...*/ }
在AZ_CVAR定义之外的源文件中,您必须首先通过 AZ_CVAR_EXTERNED 引用它。
AZ_CVAR_EXTERNED(int32_t, cloth_DebugDraw);
例 13.2. AZ_CONSOLEFREEFUNC的使用
AZ_CONSOLEFREEFUNC(SetWindowXY, AZ::ConsoleFunctorFlags::Null, "Moves the window to x,y coordinates");
SetWindowXY 既是控制台命令的回调方法,也是将命令传递到游戏启动器或从游戏内控制台调用时要在 中调用的名称。
控制台命令回调
所有控制台回调方法都采用以下格式:
void SetWindowXY(const AZ::ConsoleCommandContainer& args);
AZ::ConsoleCommandContainer 是字符串的固定向量。您可以通过将参数转换为您期望的类型来一次提取一个参数。
以下是控制台命令 windowxy 的 WindowXY 回调示例:
void SetWindowXY(const AZ::ConsoleCommandContainer& args)
{
if (args.size() != 2)
{
return;
}
// Grab first argument.
AZ::CVarFixedString argX{ args.front() };
const int x = atoi(argX.c_str());
// Grab second argument.
AZ::CVarFixedString argY{ *(args.begin() + 1) };
const int y = atoi(argY.c_str());
// ...
实现的其余部分特定于 Windows。它获取窗口手柄并设置位置。讨论特定于 Windows 的 API 超出了本书的范围,因此我们将通过显示最终结果来轻松完成它。
注意:如果您想知道在哪里可以阅读 GetActiveWindow、GetWindowInfo 和 SetWindowPos 的文档,您应该参考公共 MSDN: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos
例 13.3.WindowX 完整方法
void SetWindowXY(const AZ::ConsoleCommandContainer& args)
{
if (args.size() != 2)
{
return;
}
// Grab first argument.
AZ::CVarFixedString argX{ args.front() };
const int x = atoi(argX.c_str());
// Grab second argument.
AZ::CVarFixedString argY{ *(args.begin() + 1) };
const int y = atoi(argY.c_str());
HWND handle = GetActiveWindow();
if (!handle)
{
}
// Try the console window.
handle = GetConsoleWindow();
if (handle)
{
SetWindowPos(handle, nullptr,
x, y,
0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE);
}
}
结论和源代码
为项目编译并启用新 Gem 后,您可以使用波浪号键在游戏启动器中调出 ImGui 调试控制台。并键入命令的部分拼写,然后按 Tab。这将触发自动完成的建议。
图 13.2.控制台命令示例:SetWindowXY
注意:您可以在 GitHub 上找到本章的代码: https://github.com/AMZN-Olex/O3DEBookCode2111/tree/ch13_gem_window_position
WindowConsoleCommand.cpp
例 13.4. WindowConsoleCommand.cpp
#include <AzCore/PlatformIncl.h>
#include <AzCore/Console/IConsole.h>
namespace WindowPosition
{
void SetWindowXY(const AZ::ConsoleCommandContainer& args)
{
if (args.size() != 2)
{
return;
}
// Grab first argument.
AZ::CVarFixedString argX{ args.front() };
const int x = atoi(argX.c_str());
// Grab second argument.
AZ::CVarFixedString argY{ *(args.begin() + 1) };
const int y = atoi(argY.c_str());
HWND handle = GetActiveWindow();
if (!handle)
{
}
// Try the console window.
handle = GetConsoleWindow();
if (handle)
{
SetWindowPos(handle, nullptr,
x, y,
0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE);
}
}
AZ_CONSOLEFREEFUNC(SetWindowXY, AZ::ConsoleFunctorFlags::Null,
"Moves the window to x,y coordinates");
} // namespace WindowPosition
请注意,这次此文件不属于任何组件。它是一个独立的源文件,但仍需要将其添加到 windowposition_files.cmake。
例 13.5.windowposition_files.cmake
set(FILES
Include/WindowPosition/WindowPositionBus.h
Source/WindowPositionModuleInterface.h
Source/WindowPositionSystemComponent.cpp
Source/WindowPositionSystemComponent.h
Source/WindowConsoleCommand.cpp # new
)