RedWindows

RedWindows

用于模组的Windows窗口,以游戏自身界面绘制。面向作者:ImGui风格的API。\(^_^)/

- 简介 -

RedWindows 在游戏自身的界面中提供了游戏内窗口:真实的墨水控件、Raj 字体、你已熟悉的蓝色调。它们的设计旨在看起来像是《赛博朋克 2077》原生界面——“ImGui 风格”描述的是代码模组作者的编写方式,而不是你在屏幕上看到的内容。窗口驻留在 HUD 上,因此不会像弹出窗口或教程那样暂停游戏——例如,你可以在开车时让读数停留在屏幕上。按下叠加层按键,指针会与任何仅在叠加层激活时显示的窗口一同出现。你可以选择暂停游戏,此选项在坞站菜单中即可轻松找到,只需勾选一个复选框即可。每个窗口都可交互;再次按下叠加层按键,它们会淡出,除非它们被设定为你游戏 HUD 的一部分。

对于模组作者来说,API 的阅读体验类似于 ImGui——Text、Button、Checkbox、SliderF、Combo、ListBox、选项卡、折叠标题、SameLine——但其底层是保留模式的,因此让窗口保持在屏幕上不会产生任何持续开销,也不会每帧重建。

最终,为像我这样的 Redscript 用户提供了一种构建真实 UI 元素的更简单方法!这一切当然都受到了 CET 及其布局和功能的启发——为了便于那些已经了解和使用过 CET 的用户上手,其设计有意地接近 CET。然而,它并非旨在替代 CET,也与 LUA 或 LUA 模组完全无关:它独立运行。

太长不看 - 看起来像游戏自带的模组窗口。(⌐⊙_⊙)

- 面向玩家 -

按下 F7(可重新绑定)进入叠加模式。

  • 坞站 位于顶部:包含控制台、设置、快捷键、窗口、照片、日志和暂停游戏复选框,每个选项仅在其对应的模组已安装时才会出现。
  • 照片(需安装 RedIMGRetriever 0.3.0+)可直接在 HUD 上浏览你的 Pictures\Cyberpunk 2077 截图文件夹——最新的排在前面,尺寸适合窗口,并且该文件夹中的动态 GIF 可以播放。如果你不需要完整分辨率,两个复选框可将纹理限制在 1080p 或 2160p。
  • 窗口 可通过其标题栏拖动——如果窗口没有标题,则可在其主体任意位置拖动。角落可以调整大小,滚轮可以滚动任何过高的内容,点击标题栏可将窗口折叠到仅剩该栏。
  • 窗口管理器(窗口按钮)会列出任何模组已注册的每个窗口,并带有复选框以管理其可见性。
  • 暂停游戏 复选框只是在叠加层打开时暂停游戏;因此你可以自行决定游戏是否继续。
  • 是否固定 由模组决定:读数可以在你离开叠加层后留在 HUD 上,而设置窗口则会随之消失。
  • 所有设置都会被记忆——位置、大小、折叠状态,以及你关闭了哪些窗口——跨会话保存。
  • 文字大小 可缩放窗口文字及其下方的行。
  • 你的语言决定字体。中文、日文、韩文、泰文、阿拉伯文和西里尔文界面会为相应文字使用游戏自带的字形。
  • Esc 退出叠加层。坞站中的设置按钮配置 RedWindows 本身:热键、指针速度、未选中窗口的变暗程度、窗口不透明度以及文字大小。

当叠加层打开时,它会独占你的键盘和鼠标,因此在文本字段中打字不会触发其他模组的热键,点击按钮也不会发射武器。

- 面向模组作者 -

获取一个窗口,向其中放入内容。在你已有的任何更新逻辑中调用此代码——行会创建一次并在原地更新,因此每帧调用它也没问题:

import RedWindows.*

let w: ref<RWWindow> = RedWindowsAPI.Window(gi, n"MyMod.Stats", "My Stats");
w.Text(n"hp", s"HP: \(hp)");
if w.Button(n"reset", "Reset") { this.Reset(); }
let vol: Float = w.SliderF(n"vol", "Volume", 0.0, 1.0, 0.8);
if w.Changed(n"vol") { this.SetVolume(vol); }

控件集:

Text / TextColored / Header / Separator / Spacer / BulletText / TextWrapped
Button / Checkbox / RadioButton / Selectable / Combo / ListBox
SliderF / SliderI / ProgressBar / Input / TextArea / Icon / KeyBind
TabBar / CollapsingHeader / SameLine / Indent / BeginDisabled / Tip
Shapes

有两个可选参数值得了解。滑块最后接受一个 step 参数,以便数值落在整齐的刻度上。CollapsingHeader 接受 startClosed 参数,它决定了某部分在用户首次看到时的外观。

w.SliderF(n"posX", "X", 0.0, 1.0, 0.5, 0.05);         // 21 个档位,而不是像素渐变
w.SliderI(n"count", "Count", 0, 100, 20, 5);           // 以 5 为单位计数
if w.CollapsingHeader(n"adv", "Advanced", true) { }    // 默认折叠

Shapes 有点像绘图。它保留一个区域,你可以用多边形填充——随时填充颜色、描边、重新着色——因此可以表达任何一行控件都无法表达的读数形式,如身体地图、仪表、示意图等。无需涉及纹理、图集或档案资源。

w.Shapes(n"body", 9);                         // 一个 9 行高的区域
w.SetShape(n"body", n"head", headPoints);     // 点坐标是 0..1 的区域比例
w.SetShapeBorder(n"body", n"head", edge, 2.0);
w.SetShapeColor(n"body", n"head", hitRed);    // 随时重新着色
w.SetShapeOpacity(n"body", n"head", 0.4);

点坐标已归一化,因此一次创建的图形会随窗口调整大小而自适应。绘制顺序是你首次声明每个 shape 的顺序,ShapeCount(id) 会告诉你是否已创建它。

目前每个 shape 都会渲染为一个适合你提供的多边形的旋转矩形——四边形形状会变成一个沿其脊线、具有平均宽度的条形,其他任何形状都会变成其竖直方向的盒子。因此,锥形形状会呈现为直线。你仍然描述真实的多边形,而需要成为真正多边形的形状将在不更改一行代码的情况下变为真实多边形。

一个 shape 可以绘制来自你自己 inkatlas 的 精灵图,而不是条形,这是模组将真实美术资源显示在屏幕上的方式。此时多边形仅指明其位置——美术资源会带来自己的轮廓和形状:

w.SetShapeImage(n"body", n"head", r"base\mymod\ui\figure.inkatlas", n"head");

色调仍然有效,因此以白色制作的美术资源可以采用你设置的任何颜色,并像其他元素一样淡出。需要注意两点:图集是 ResRef(使用 r"..." 字面量形式),并且你的纹理宽度和高度都必须能被 4 整除,否则游戏无法加载它——它将呈现为一个纯白色方框,且不会在别处产生任何错误。

读取状态:

  • Changed(id) 用于编辑状态——它在读取时会清除,因此如果你需要答案两次,请将其读入一个变量。
  • Hovered(id)Active(id) 用于指针状态。按钮和 Selectable 在点击本身发生时返回 true。

窗口控制:

  • SetShowTitle(false) 用于无边框读数
  • SetFrameVisible(false) 同时去掉背景和边框
  • SetOverlayOnly(true) 在叠加层关闭时隐藏它
  • minW 用于你的最窄合理宽度
  • SetRowVisible(id, on) 折叠某一行
  • SetSpan(id, rows) 在创建后调整区域(Shapes、TextArea、ListBox)的大小——将其映射到窗口高度,你的区域就会随之增长
  • Show/Hide 以及通过 SetPartColorSetWidgetColor 对任何部分进行着色

模组拥有的菜单(1.3.0+):命令菜单或对话框希望独占指针——没有坞站、没有其他工具窗口——并且没有 X,因为何时消失由模组决定。那就是 win.SetClosable(false) 加上 RedWindowsAPI.OpenFor(gi, win) 为该窗口打开叠加层(固定读数保持显示),以及当某个命令被点击时使用 RedWindowsAPI.Close(gi)。Esc 仍会将其关闭,与任何叠加层一样。

指针模式(1.3.0+):将叠加层光标作为世界空间指针。在 RedWindowsAPI.PointerBegin(gi) 之后,空地上的左键点击和任何右键点击都会为你锁定(PointerTake(gi) 返回 0/1/2 并清除),PointerNormalized(gi) 以归一化屏幕空间坐标(X 向右,Y 向上,-1..1)给出光标位置,用于 CameraSystem.UnprojectPoint。窗口在此期间仍可正常工作;以 PointerEnd(gi) 结束(叠加层关闭也会结束它)。Drone Companions 的“Point”命令是参考用例(发布时)。

控件 id 是永久的——同一个 id 始终表示同一行,这正是保留模式模型成本低廉的原因。宽度由你决定:设置 minW 以便你最长的标签能够容纳,因为标签会截断而不是溢出。文字大小不受影响——玩家拥有该项控制权,而行、标签和截断都会根据他们的选择重新调整,所以不要依赖某个特定的文字大小。

如果你想在未安装它的情况下运行,可以进行软依赖:

@if(ModuleExists("RedWindows"))
import RedWindows.*

建议先试用: 设置中有一个演示窗口切换开关,会在屏幕上放置三个窗口,演示大量控件和选项——这是了解你能使用哪些功能的最快方式。

- 备注 -

叠加模式目前仅在游戏中可用。在主菜单中,窗口可以绘制但无法接受点击,因此在那里被禁用,而不是半失效状态,但我们很快就会解决这个问题。

还有一个外观上的小瑕疵:在叠加层打开时,按住诸如电话或载具呼叫之类的长按按键仍会填充其屏幕指示器,尽管该操作从未触发。这个问题已列入修复清单。

- 更新日志 -

1.0.0 - 首次发布。 1.0.1 - 窗口现在会随分辨率缩放。 1.1.0 - 窗口现在可以绘图。Shapes() 为模组提供了一个区域,可以用多边形填充,或使用其自身图集中的精灵图。窗口现在可以完全移除其框架。调整大小手柄延伸至屏幕边缘,而不是停在固定大小。当安装 RedLogger 时,日志会加入坞站。叠加层对 CPU 的占用大幅降低。 1.2.0 - 新增 SetSpan 功能。坞站新增 PHOTOS 应用。 1.3.0 - 新增文字大小设置。字体现在随界面语言变化,因此中文、日文、韩文、泰文、阿拉伯文和西里尔文可以正确渲染。对于模组作者:滑块增加可选 step 参数,CollapsingHeader 增加可选 startClosed 参数;新增菜单模式和指针模式。

- 前置要求 -

此模组需要你安装以下前置:

- 安装 -

  1. 安装所有前置依赖。
  2. 将下载的文件解压到你的游戏主目录中。

- 卸载 -

删除目录 \Cyberpunk 2077\r6\scripts\RedWindows

窗口位置存储在 \Cyberpunk 2077\r6\storages\RedWindows 中——如果你想彻底移除,也请一并删除。没有任何内容写入你的存档,因此随时可以安全移除。

- 致谢 -

感谢 RED4ext、Redscript、Codeware 和 CET 社区提供的工具和文档,此处所有内容都建立在这些基础之上。

DigitalVixen 模组套件的一部分。 你现在可以在 Discord 上找到我,[点此加入!](https://discord.gg/TRuuDSrGWJ)