新闻详情

新闻详情

首页 / 资讯中心 / 详情

Babylon.js 编辑器工具链 Fluent UX 现代化改造指南:Primitive、HOC 与渐进式迁移

发布时间:2026/9/30 6:40:34来源:尧图网络
Babylon.js 编辑器工具链 Fluent UX 现代化改造指南:Primitive、HOC 与渐进式迁移
图形学游戏开发3D渲染【免费下载链接】Babylon.jsBabylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.项目地址https://gitcode.com/gh_mirrors/ba/Babylon.js点击查看免费下载导读本文围绕 Babylon.js 仓库中 sharedUiComponents/src/fluent/readme.md 记录的 Fluent 改造计划系统讲解该仓库如何用微软 Fluent Design Systemfluentui/react-components替换编辑器类工具Node Editor、GUI Editor、Inspector 等中旧的自定义控件。你将掌握这套改造的六层架构轻量 Fluent 原语Primitive、预置样式的高阶组件HOC、InspectorV2 直接渲染、基于 Context 的条件渲染、FluentToolWrapper根包裹渐进切换以及?newUXtrue灰度开关的使用方式并看到每一层背后的源码实现证据。一、改造目标与总体架构该文档packages/dev/sharedUiComponents/src/fluent/readme.md开篇即说明了这项工作的背景Babylon.js 团队正着手把现有工具与正在开发的 InspectorV2 所共用的控件全部替换为现代化的 Fluent UX 控件。整个工作被拆分为六个相互独立、可渐进交付的模块Fluent 原语primitives——对现有 Fluent 组件的轻量封装附带少量样式Fluent 高阶组件HOC——围绕原语封装常见 UX 模式的样式与逻辑如PropertyLineInspectorV2 直接使用 Fluent 组件——不再依赖旧 shared-ui-components在旧 shared-ui-components 内条件渲染 Fluent 版本——通过 Context 读取useFluent使旧工具无需修改每个调用点逐个工具包裹FluentToolWrapper渐进迁移——同时用 URL 上的newUX查询参数控制灰度开关迁移后增量重构旧工具——把工具间重复的初始化逻辑下沉到共享 tooling 目录。下文按这六个阶段逐一展开并对照源码给出每一层的实现细节。二、Fluent 原语Primitives轻量封装的组件底座2.1 目录与组件清单原语全部位于 fluent/primitives 目录包括表单类checkbox.tsx、comboBox.tsx、dropdown.tsx、slider.tsx、spinButton.tsx、switch.tsx、textInput.tsx、textarea.tsx、toggleButton.tsx、uploadButton.tsx、searchBox.tsx、searchBar.tsx选择器类entitySelector.tsx、materialSelector.tsx、nodeSelector.tsx、skeletonSelector.tsx、textureSelector.tsx、clusteredLightContainerSelector.tsx、structuralColorPicker.tsx、colorPicker.tsx布局与弹层类accordion.tsx、collapse.tsx、dialog.tsx、popover.tsx、positionedPopover.tsx、contextMenu.tsx、tooltip.tsx、toast.tsx、messageBar.tsx、list.tsx、link.tsx、draggable.tsx、lazyComponent.tsx复合组件syncedSlider.tsx、infoLabel.tsx类型与工具primitive.ts、utils.ts、accordion.contexts.tsx按文档定义这些原语是“对现有 Fluent 组件的轻量封装附带少量样式”。封装程度因组件而异有的只做轻微样式处理有的则包含更复杂的协调逻辑——文档明确举例的正是SyncedSlider它在滑块Slider与数值输入框SpinButton之间同步数值变化。2.2 原语的统一 Props 协议所有原语共享同一套基础类型定义见 primitives/primitive.tsexport type BasePrimitiveProps { disabled?: boolean; // 禁用组件阻止一切交互 className?: string; // 自定义样式类名 style?: React.CSSProperties; // 顶层元素的内联样式 title?: string; // 用于 tooltip 或无障碍访问的标题 }; export type ImmutablePrimitivePropsValueT BasePrimitiveProps { value: ValueT; // 要展示与修改的属性值 infoLabel?: InfoLabelParentProps; // 组件旁侧的信息弹窗 }; export type PrimitivePropsT ImmutablePrimitivePropsT { onChange: (value: T) void; // 值变化时的回调 };这套协议的要点是所有原语都是“受控组件”——由父级持有value并通过onChange接收变更从而保证在 Node 编辑器的属性面板这种高频联动场景中状态始终是单向数据流、可预测的。2.3 以 SyncedSlider 为例看封装逻辑primitives/syncedSlider.tsx 是文档点名的“复杂逻辑”原语。它的 Props 在PrimitivePropsnumber之上扩展了属性含义min/max滑块的最小/最大值两者都定义时才渲染滑块step步长precision显示精度小数点位数覆盖自动计算的精度unit单位显示在 UX 中notifyOnlyOnRelease为true时只在松开滑块pointer up时触发onChange拖拽过程中不触发compact紧凑模式滑块扩展填充、SpinButton 固定 65pxgrowSlider滑块扩展占满全部可用空间无 maxWidth 约束其内部实现有几个值得注意的工程细节拖拽防闪烁useEffect只在!isDraggingRef.current时同步外部props.value避免拖动过程中被父级旧值覆盖导致滑块跳动松手才回调notifyOnlyOnRelease模式下拖拽期间值先存入pendingValueRef待handleSliderPointerUp时才一次性上报布局默认 50/50makeStyles中slider与spinButton均为flex: 1 1 0滑块与输入框平分宽度compact/growSlider则改写为flex: 1 1 auto配合minWidth: 50px的滑块与 65px 的输入框。2.4 原语共享的样式与工具primitives/utils.ts 集中定义了全组件的统一样式标记export const TokenMap { px2: tokens.borderRadiusSmall, /* … */ px40: tokens.lineHeightHero800 }; export const CustomTokens { valueWidth: 150px, lineHeight: TokenMap.px36, // 常规行高 lineHeightSmall: TokenMap.px28, // small 尺寸行高 labelMinWidth: 50px, sliderMinWidth: 30px, sliderMaxWidth: 80px, rightAlignOffset: -8px, // 让属性行右端视觉对齐 };此外还提供了两个可直接复用的纯函数CalculatePrecision(value)依据尾随零或小数点后位数计算数值精度移植自 Fluent 工具库以及ValidateColorHex(val)用正则^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$校验 3/6/8 位十六进制颜色字符串。这些原语既可独立使用也可以被下一层的 HOC如PropertyLine当作子组件组合进预置样式的行结构。三、Fluent 高阶组件HOC预置常见 UX 模式3.1 HOC 目录构成HOC 层位于 fluent/hoc除propertyLines/目录下的 19 个属性行组件外还包括buttonLine.tsx、fileUploadLine.tsx、textureUpload.tsx——带标签/按钮的上传类行pane.tsx——带标题与图标的工具面板容器gradientList.tsx——渐变列表编辑器childWindow.tsx、popupWindow.ts——子窗口与弹窗fluentToolWrapper.tsx——第五阶段的核心工具根包裹器3.2 PropertyLine最典型的 HOC文档明确指出 HOC 的作用是“处理常见 UX 模式的样式”并举例PropertyLine.tsx渲染一个标签、一个用于修改属性的 Fluent 原语子组件以及一个可选的复制按钮——这正是所有编辑器工具属性面板通用的行模式。源码见 hoc/propertyLines/propertyLine.tsx。PropertyLineProps的完整契约包含三类能力基础展示能力属性说明label属性名显示在属性行uniqueId行的持久化 ID用于 accordion 分区内的属性固定与过滤description悬停信息图标时显示的属性说明onCopy返回待复制字符串的函数提供后显示复制按钮docLink属性文档链接信息图标会将其渲染为链接可空值能力通过nullable/ignoreNullable/defaultValue组合控制nullable: true行首显示一个 Checkbox 用于切换null与非空。取消勾选时会把当前值缓存进cachedVal并回调onChange(null)重新勾选时恢复缓存值无缓存则用defaultValueignoreNullable: true接受null但不在 UI 中显示勾选框把子组件以禁用态渲染并用默认值兜底子组件会被cloneElement注入disabled与value派生值并显式清空defaultValue以避免受控/非受控混合状态。可展开能力传入expandedContent时行右侧渲染一个展开/收起 ToggleButtonsmall 尺寸用 16px 图标常规尺寸用 20px 图标展开内容包裹在Collapse组件中并附带tokens.spacingHorizontalM的左内边距expandByDefault控制默认展开态。此外PropertyLine读取ToolContext中的size来切换lineHeight与图标尺寸复制按钮CopyButton在自己的组件位置读取ToolContext这样 accordion 的ToolContext.Provider覆盖如 Ctrl悬停就能独立控制其可见性。LineContainer则把每一行包装进AccordionSectionItem使属性行天然支持面板的分区、固定pin与过滤能力。3.3 颜色属性行HOC 之上的 Runtime 适配colorPropertyLine.tsx与colorPropertyLineCore.tsx展示了“核心逻辑与运行时解耦”的写法ControlledColorPropertyLine是与 Babylon.js 运行时无关的受控颜色编辑器通过ColorPropertyLineAdapter注入“取色”与“构造色”两个动作const Adapter { picker: (props) ColorPickerPopup {...props} /, getColor: (value) value, createColor: (color, source) { if (source instanceof Color4) { return new Color4(color.r, color.g, color.b, color.a ?? source.a); } return source.clone().set(color.r, color.g, color.b); }, };展开区会渲染四个SyncedSliderPropertyLineR/G/B 使用 0–255 整数范围内部换算为 0–1 浮点A仅 Color4使用 0–1、步长 0.01。从而对外导出Color3PropertyLine与Color4PropertyLine两个实体组件。3.4 向量属性行对 Vector2/3/4 与四元数的统一抽象propertyLines/vectorPropertyLine.tsx 通过CreateCoreTensorAdapter把“分量读取/写入”抽象成TensorValueAdapterVector2只含 x/yVector3含 x/y/zVector4与Quaternion含 x/y/z/w。在此基础上Vector2PropertyLine/Vector3PropertyLine/Vector4PropertyLine直接编辑对应向量RotationVectorPropertyLine以欧拉角形式编辑Vector3QuaternionPropertyLine支持useEuler角度制/弧度制换算通过Quaternion.FromEulerAngles与toEulerAngles完成与useDegrees。这一层完整覆盖了属性面板中最常见的数值编辑需求布尔checkboxPropertyLine/switchPropertyLine/toggleButton、枚举comboBoxPropertyLine/dropdownPropertyLine、文本textPropertyLine/textAreaPropertyLine/inputPropertyLine/stringifiedPropertyLine、数值spinButtonPropertyLine/syncedSliderPropertyLine/hexPropertyLine、引用linkPropertyLine/entitySelectorPropertyLine以及徽标行booleanBadgePropertyLine。四、InspectorV2 直接渲染 Fluent 组件第三阶段不再依赖旧 shared-ui-components 组件而是让 InspectorV2 直接使用新的 Fluent 组件。文档给出的示例文件均位于 packages/dev/inspector-v2例如meshGeneralProperties.tsx——网格通用属性面板commonGeneralProperties.tsx——通用属性面板outlineOverlayProperties.tsx——轮廓叠加属性面板从仓库结构看InspectorV2 的组件目录src/components、src/lite与 HOC 属性行组件保持一一对应的关系两者共同消费同一套PrimitiveProps协议。这种“新工具用新组件、旧工具渐进换新组件”的双轨策略保证了改造期间新旧两套 UI 可以共存于同一代码库。五、Context 条件渲染旧组件就地切换 Fluent 版本第四阶段解决“存量工具如何不修改每个调用点就换上 Fluent 版本”的问题。方案是在每个旧 shared-ui-components 组件内部通过contextConsumer读取ToolContext.useFluent据此条件渲染 Fluent 版本或旧版本。从源码搜索可以确认ToolContext/useFluent的读取点遍布旧组件与新组件两侧新侧fluent/primitives/accordion.tsx、button.tsx、colorPicker.tsx、comboBox.tsx、dropdown.tsx、slider.tsx、spinButton.tsx、switch.tsx、textInput.tsx、toggleButton.tsx、toast.tsx等旧侧components/propertyTabComponentBase.tsx 以及lines/下的booleanLineComponent.tsx、floatLineComponent.tsx、sliderLineComponent.tsx等大量旧行组件。这意味着某个工具只要在根部正确创建FluentProvider与ToolContext.Provider即包裹FluentToolWrapper其内部所有 shared-ui-components 调用点会自动渲染出 Fluent 版本调用点代码本身无需改动。六、FluentToolWrapper工具根包裹与 newUX 灰度开关第五阶段是整套迁移的“开关总闸”。文档要求逐个把工具根部包上FluentToolWrapper它同时完成两件事创建 Fluent Provider、并把useFluent置为true。这样可以在工具内先模块化测试新组件再全面点亮。fluent/hoc/fluentToolWrapper.tsx 的实现与文档描述完全一致export const FluentToolWrapper: FunctionComponentPropsWithChildrenToolHostProps (props) { const url new URL(window.location.href); const useFluentFromUrl url.searchParams.has(newUX) || url.hash.includes(newUX); const useFluent props.useFluent ?? useFluentFromUrl; const contextValue { useFluent, disableCopy: !!props.disableCopy, toolName: props.toolName, size: props.size }; return useFluent ? ( FluentProvider theme{props.customTheme || webDarkTheme} ToolContext.Provider value{contextValue}{props.children}/ToolContext.Provider /FluentProvider ) : ( ToolContext.Provider value{contextValue}{props.children}/ToolContext.Provider ); };ToolHostProps的参数说明如下属性类型说明sizesmall \| medium统一工具内所有控件的缩放尺度customThemeTheme宿主可传入自定义主题缺省使用webDarkTheme暗色主题disableCopyboolean设为true时禁用工具内所有属性行的复制按钮默认falsetoolNamestring显示在 UX 中的工具名写入ToolContext供上层读取useFluentboolean手动覆盖 URL 灰度检测结果关键设计——URL 灰度开关useFluentFromUrl url.searchParams.has(newUX) || url.hash.includes(newUX)意味着开发者把新逻辑合入主线时默认所有用户看到的仍是旧 UI只有当 URL 携带?newUXtrue或 hash 中包含newUX时才会启用 Fluent 版本。这正对应文档第 5 条所说的“在不默认对所有用户启用的情况下合入新逻辑”。灰度验证通过后再通过传useFluent{true}或直接移除开关实现全量点亮。七、迁移后的工具重构抽离共享 Tooling 范式第六阶段是收尾工程。文档指出每个工具被 fluent 化之后可以逐步重构 shared-ui-components 的初始化方式示例为PropertyTabComponent把各个工具共有的范式抽取到共享 tooling 目录减少工具间的重复逻辑。从仓库现状可以推断这套重构的落点fluent/hoc/与fluent/primitives/本身即承担了“面板容器Pane—属性行PropertyLine—原语Slider/SyncedSlider/ColorPicker…—行为Accordion 分区/固定/过滤、Toast、Tooltip、ContextMenu”等跨工具范式各编辑器工具tools/nodeEditor、tools/guiEditor、tools/nodeGeometryEditor等只需在其根部组合这些通用件而不再各自实现面板布局逻辑。这样的重构方向让新旧工具的 UI 行为行高、复制按钮、可空值处理、展开区天然趋同。八、完整迁移路径速览综合文档六阶段与上文源码分析一次完整的工具迁移遵循如下路径确认工具内需要迁移的属性行与交互组件在 fluent/primitives 与 fluent/hoc/propertyLines 中已有对应实现在工具根部包裹FluentToolWrapper toolName…可先不传useFluent仅靠 URL 灰度浏览器访问时带上?newUXtrue验证 Fluent 版本模块化修复差异旧 shared-ui-components 的调用点无需改动——内部ToolContext.useFluent会自动切换渲染版本验证通过后固定开启传入useFluent{true}或移除灰度开关按第六阶段把工具间重复的面板/属性行初始化逻辑下沉到共享 HOC收敛到PropertyLine、Pane、Accordion等统一组件。九、小结Babylon.js 的 Fluent 改造不是一次性的“重写 UI”而是一套分层清晰、可灰度、可回滚的渐进式工程Primitive → HOC → 直接使用 → Context 条件渲染 → 根包裹切换 → 重构收敛。文档定义的六阶段与源码一一对应FluentToolWrapper的newUXURL 开关是整套迁移的灰度控制中枢PrimitiveProps受控协议与ToolContext是连接新旧两套 UI 的数据契约。对于任何希望在大型编辑器型项目中平滑引入新一代组件库的团队这套方法论都可以直接借鉴——相关实现均可从 sharedUiComponents/src/fluent 目录开始阅读。赞分享图形学游戏开发3D渲染【免费下载链接】Babylon.jsBabylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.项目地址https://gitcode.com/gh_mirrors/ba/Babylon.js点击查看免费下载相关推荐ics库安全指南防止日历注入攻击的10个最佳实践ics库安全指南防止日历注入攻击的10个最佳实践 在当今数字化时代日历应用已成为我们日常生活和工作中不可或缺的工具。然而许多开发者在使用iCalendar后端序列化Rocket.Chat 前端从 JavaScript 迁移到 TypeScript渐进式改造指南Rocket.Chat 前端从 JavaScript 迁移到 TypeScript渐进式改造指南 本指南以 docs/frontend/migrating f即时通讯后端前端LunaTV核心功能深度解析从YouTube集成到AI推荐的60功能全览LunaTV核心功能深度解析从YouTube集成到AI推荐的60功能全览 LunaTV是一款功能强大的媒体中心应用集成了超过60种实用功能从YouTub上一篇2025新范式Pydantic-AI如何让Phi4模型性能提升300%下一篇网站健康检查清单awesome-checker-services工具组合使用的最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

foobar2000 皮肤 foobox:3 步装完即用,10 分钟把播放器界面改好看 2026/9/30 7:34:43

foobar2000 皮肤 foobox:3 步装完即用,10 分钟把播放器界面改好看

foobar2000 皮肤 foobox:3 步装完即用,10 分钟把播放器界面改好看 【免费下载链接】foobox-cn DUI 配置 for foobar2000 项目地址: https://gitcode.com/GitHub_Trending/fo/foobox-cn foobox 是 foobar2000 的即装即用皮肤包,主题、面…

阅读更多 →
UVa1410/LA4027 Expensive Drink 2026/9/30 7:34:42

UVa1410/LA4027 Expensive Drink

UVa1410/LA4027 Expensive Drink题目链接题意分析AC 代码题目链接 本题是2007年icpc亚洲区域赛北京赛区的E题 题意 你家那个调皮的小妹妹把水、牛奶、红酒混在一起,还加了点糖,打算给你喝。为了不让自己看上去太不讲理,她说如果你能猜到调制…

阅读更多 →
深度学习大模型全链路实战:从环境搭建到ONNX部署的避坑指南 2026/9/30 7:34:29

深度学习大模型全链路实战:从环境搭建到ONNX部署的避坑指南

简介:这份资源是一套面向深度学习研发人员、数据科学家及技术爱好者的全链路实战指南,聚焦大模型从构建到部署的完整流程,帮助具备一定理论基础的学习者打通环境搭建、数据处理、模型选择与训练、评估优化到最终部署的关键环节。资源包内含1个…

阅读更多 →
DDNS攻击手法与防御体系全面解析:从DNS重绑定到域名劫持 2026/9/30 7:34:29

DDNS攻击手法与防御体系全面解析:从DNS重绑定到域名劫持

1. DDNS攻击目标画像:为什么攻击者死盯动态域名1.1 DDNS到底是怎么工作的:三分钟搞懂核心机制DDNS的设计初衷很朴素:你家里或小公司的公网出口IP是动态的,宽带运营商隔一段时间就重新分配一次地址,但你的NAS、摄像头、…

阅读更多 →
算法训练营Day10栈与队列:四道核心题与工程应用全景解析 2026/9/30 7:34:29

算法训练营Day10栈与队列:四道核心题与工程应用全景解析

算法训练营刷到 day10,栈和队列专题正式开始了。整个代码随想录训练营走到这里,其实是一个很微妙的分水岭:前面几天的数组、链表、哈希表,多少还能靠直觉硬写;到了栈和队列,突然就要求你学会“抽象”——不…

阅读更多 →
麒麟V10系统救援模式实战:从GRUB参数到chroot修复 2026/9/30 7:34:29

麒麟V10系统救援模式实战:从GRUB参数到chroot修复

机器点不亮、密码忘了、升级后卡 logo,这些场景我第一次碰到时也慌过。说实话,在麒麟 V10-SP1 2503 桌面系统上,真正解决问题的关键不是桌面端,而是能不能顺利进到救援模式。这篇文章我就把进入救援模式这件事掰开揉碎讲一遍&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉