forked from YikaiFu-cart/acRealman_xr
optimze unity project for xr_rm
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,6 +21,7 @@ __pycache__/
|
|||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
|
*.log
|
||||||
qtcreator-*
|
qtcreator-*
|
||||||
*.user
|
*.user
|
||||||
|
|
||||||
|
|||||||
34
CODEX.md
34
CODEX.md
@ -15,7 +15,7 @@ PICO/XR UDP JSON
|
|||||||
-> /xr_rm/<arm_name>/current_pose、raw_target_pose、target_pose、cmd_vel、target_clamped
|
-> /xr_rm/<arm_name>/current_pose、raw_target_pose、target_pose、cmd_vel、target_clamped
|
||||||
```
|
```
|
||||||
|
|
||||||
核心控制方式是相对位姿透传遥操作:`grip=true` 的第一帧锁定手柄起点和机器人 TCP 起点,之后用手柄位移增量生成目标 TCP,并通过 `rm_movep_canfd` 下发位姿目标;`grip=false`、UDP 超时、异常或节点退出必须停止。
|
核心控制方式是相对位姿透传遥操作:`grip=true` 的第一帧锁定手柄起点和机器人 TCP 起点,之后用手柄位移增量生成目标 TCP,并通过 `rm_movep_canfd` 下发位姿目标;`grip=false`、`pose_valid=false`、UDP 超时、异常或节点退出必须停止。
|
||||||
|
|
||||||
## 固定工作流
|
## 固定工作流
|
||||||
|
|
||||||
@ -38,12 +38,16 @@ PICO/XR UDP JSON
|
|||||||
- 人负责目标、验收和最终合并。
|
- 人负责目标、验收和最终合并。
|
||||||
- AI 负责探索、修改、运行检查、总结风险。
|
- AI 负责探索、修改、运行检查、总结风险。
|
||||||
- Git 分支、测试和 `git diff` 是隔离与回滚边界。
|
- Git 分支、测试和 `git diff` 是隔离与回滚边界。
|
||||||
- 不允许绕过人工确认直接提交、推送或删除重要文件。
|
- 默认不允许绕过人工确认直接修改文件、提交、推送或删除重要文件。
|
||||||
|
- 除非用户明确写出“可以直接修改”“无需确认”“直接执行”等授权语句,否则任何会写入文件的操作前都必须先输出计划并等待人工确认。
|
||||||
|
|
||||||
## 代理执行规则
|
## 代理执行规则
|
||||||
|
|
||||||
- 先探索,再修改。优先读相关 package、launch、YAML、消息、Unity 脚本和 README。
|
- 先探索,再修改。优先读相关 package、launch、YAML、消息、Unity 脚本和 README。
|
||||||
- 修改前说明目标理解、涉及文件、实现计划和风险;小任务可以简短说明后直接执行。
|
- 修改前必须先说明目标理解、涉及文件、实现计划、风险和验证方式,并等待用户明确回复同意后再动手。
|
||||||
|
- 小任务也遵守确认门禁;可以把计划写得很短,但不能在未获授权时直接写文件。
|
||||||
|
- 用户已经明确授权直接修改的当前请求,可以在简短说明后执行;仍需保持小步修改并在结束时总结差异。
|
||||||
|
- 在等待确认前,可以执行只读探索命令,例如查看文件、搜索代码、检查 `git status --short` 和阅读 diff。
|
||||||
- 只改与任务相关的最小文件集,避免无关重构、格式化和大范围重写。
|
- 只改与任务相关的最小文件集,避免无关重构、格式化和大范围重写。
|
||||||
- 不要自动 `git add .`、commit、push、force push、删分支或合并分支。
|
- 不要自动 `git add .`、commit、push、force push、删分支或合并分支。
|
||||||
- 不要回滚用户已有改动。工作区有未提交内容时,默认它们属于用户。
|
- 不要回滚用户已有改动。工作区有未提交内容时,默认它们属于用户。
|
||||||
@ -59,6 +63,7 @@ PICO/XR UDP JSON
|
|||||||
- 不要随意修改工作空间边界、圆柱半径限制、`xr_to_robot_matrix`、初始化关节/TCP 位姿、速度/加速度限制、末端外设配置。
|
- 不要随意修改工作空间边界、圆柱半径限制、`xr_to_robot_matrix`、初始化关节/TCP 位姿、速度/加速度限制、末端外设配置。
|
||||||
- 真机相关改动必须保持以下安全停止路径:
|
- 真机相关改动必须保持以下安全停止路径:
|
||||||
- `grip=false`
|
- `grip=false`
|
||||||
|
- PICO/Unity 发送 `pose_valid=false`
|
||||||
- UDP 超时 / controller 数据过期
|
- UDP 超时 / controller 数据过期
|
||||||
- adapter 异常
|
- adapter 异常
|
||||||
- 节点 shutdown
|
- 节点 shutdown
|
||||||
@ -88,9 +93,12 @@ ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=true
|
|||||||
模拟 UDP:
|
模拟 UDP:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ros2 run xr_rm_input sample_udp_sender --hand both --host 127.0.0.1 --port 15000 --seconds 10
|
ros2 run xr_rm_input sample_udp_sender --hand both --host 127.0.0.1 --port 15000 \
|
||||||
|
--pattern axis_sweep --seconds 60 --both-mode staggered
|
||||||
```
|
```
|
||||||
|
|
||||||
|
当前 `sample_udp_sender` 默认用 `axis_sweep` 扫轴轨迹;`--both-mode staggered` 会先左后右,适合双臂方向检查。
|
||||||
|
|
||||||
常用话题:
|
常用话题:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -148,7 +156,13 @@ git diff --check
|
|||||||
小功能开发:
|
小功能开发:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
请实现 XXX。限制:不改变现有接口,不重构无关代码,修改前说明计划,修改后运行测试或告诉我如何测试。
|
请实现 XXX。限制:不改变现有接口,不重构无关代码。本轮先不要修改文件,请先说明计划、涉及文件、风险和验证方式,等我回复“开始修改”后再动手。
|
||||||
|
```
|
||||||
|
|
||||||
|
直接授权小改:
|
||||||
|
|
||||||
|
```text
|
||||||
|
请直接修改 XXX,无需等待二次确认。限制:只改相关文件,修改后说明差异和验证方式。
|
||||||
```
|
```
|
||||||
|
|
||||||
代码审查:
|
代码审查:
|
||||||
@ -166,17 +180,17 @@ git diff --check
|
|||||||
## 包职责
|
## 包职责
|
||||||
|
|
||||||
- `xr_rm_interfaces`:定义 `XrController`。
|
- `xr_rm_interfaces`:定义 `XrController`。
|
||||||
- `xr_rm_input`:接收 UDP controller JSON,发布左右手柄话题,并提供 `sample_udp_sender`。
|
- `xr_rm_input`:接收 UDP controller JSON,发布左右手柄话题;`pose_valid=false` 会强制 `grip=false`;提供 `sample_udp_sender` 扫轴/正弦调试数据。
|
||||||
- `xr_rm_teleop`:把手柄相对位移映射成 RM75 笛卡尔位姿透传目标。
|
- `xr_rm_teleop`:把手柄相对位移映射成 RM75 笛卡尔位姿透传目标。
|
||||||
- `xr_rm_bringup`:维护 launch、YAML、现场 UI 和运行入口。
|
- `xr_rm_bringup`:维护 launch、YAML、现场 UI 和运行入口。
|
||||||
- `unity/XR_RM_PICO_UDP_Sender`:PICO 4 Ultra UDP Sender Unity 工程。
|
- `unity/XR_RM_PICO_UDP_Sender`:PICO 4 Ultra UDP Sender Unity 工程,发送 `seq`、`source_time`、`pose_valid`、`pose_source`、tracking/controller status 等诊断字段。
|
||||||
|
|
||||||
## 文档规则
|
## 文档规则
|
||||||
|
|
||||||
- 根目录保留 `README.md` 和 `CODEX.md`。
|
- 根目录保留 `README.md` 和 `CODEX.md`。
|
||||||
- `README.md` 是唯一项目主文档,包含 ROS2 构建、运行、mock、真机、安全和协议说明。
|
- `README.md` 是唯一项目主文档,包含 ROS2 构建、运行、mock、真机、安全和协议说明。
|
||||||
- `CODEX.md` 是代码代理规则文档,修改工作流时优先更新它。
|
- `CODEX.md` 是代码代理规则文档,修改工作流时优先更新它。
|
||||||
- `docs/` 只保留 Ubuntu 22.04 下 PICO 发送 UDP 数据的配置教程。
|
- `docs/` 下的 Markdown 只维护 Ubuntu 22.04 下 PICO 发送 UDP 数据的配置教程;已有非 Markdown 汇报材料不要扩写成源码教程。
|
||||||
- 不要新增零散 Markdown,除非用户明确要求。
|
- 不要新增零散 Markdown,除非用户明确要求。
|
||||||
- 不要声明未实现功能已经完成。mock、真机、Unity/PICO 路线要写清楚。
|
- 不要声明未实现功能已经完成。mock、真机、Unity/PICO 路线要写清楚。
|
||||||
|
|
||||||
@ -184,9 +198,11 @@ git diff --check
|
|||||||
|
|
||||||
- 当前 Unity 工程:`unity/XR_RM_PICO_UDP_Sender`。
|
- 当前 Unity 工程:`unity/XR_RM_PICO_UDP_Sender`。
|
||||||
- 当前 PICO SDK:`unity/PICO-Unity-Integration-SDK-release_3.4.0`。
|
- 当前 PICO SDK:`unity/PICO-Unity-Integration-SDK-release_3.4.0`。
|
||||||
|
- 当前 Unity package 还依赖 TextMeshPro,PICO 面板字体来自预生成的 `Assets/Resources/Fonts/Roboto-Regular SDF.asset` 和 `Roboto-Bold SDF.asset`;不要在 APK 运行时动态创建 TMP 字体资产。
|
||||||
- APK、Unity `Builds/`、`Library/`、日志和临时文件不是源码,不应提交。
|
- APK、Unity `Builds/`、`Library/`、日志和临时文件不是源码,不应提交。
|
||||||
- PICO UDP 目标 IP 必须是当前 Ubuntu ROS 主机在同一局域网的 IPv4。
|
- PICO UDP 目标 IP 必须是当前 Ubuntu ROS 主机在同一局域网的 IPv4。
|
||||||
- PICO App 暂停、退出或关闭发送时必须发送 `grip=false` 或让 ROS 侧超时安全停止。
|
- PICO App 暂停、退出或关闭发送时必须发送 `grip=false`,姿态无效时必须发送 `pose_valid=false` 并让 ROS receiver 强制停止。
|
||||||
|
- 当前 Unity `Project (+Z back)` 输出必须是 `+X` 右、`+Y` 上、`+Z` 后。PXR `pxr_predict` 原始坐标按实测先转换为 `project.x=native.z`、`project.y=native.y`、`project.z=-native.x`;`Source raw` 仅用于现场对照。若 `/xr/*_controller.pose.position` 已正确但某一只臂方向不对,优先改对应 YAML 的 `xr_to_robot_matrix`。
|
||||||
|
|
||||||
## 不在当前任务范围内
|
## 不在当前任务范围内
|
||||||
|
|
||||||
|
|||||||
98
README.md
98
README.md
@ -21,7 +21,7 @@ PICO/XR 双手柄 UDP JSON
|
|||||||
- 通过统一的 `arm_debug.launch.py` 支持左臂、右臂、双臂的 mock 调试和真机调试。
|
- 通过统一的 `arm_debug.launch.py` 支持左臂、右臂、双臂的 mock 调试和真机调试。
|
||||||
- RM75 真机连接适配,包含 `rm_movep_canfd` 位姿透传、安全速度/加速度配置、可选初始化点位移动。
|
- RM75 真机连接适配,包含 `rm_movep_canfd` 位姿透传、安全速度/加速度配置、可选初始化点位移动。
|
||||||
- Tkinter 启动面板 `launcher_ui.py`,用于现场快速启动、监控 topic、检查环境和清理进程。
|
- Tkinter 启动面板 `launcher_ui.py`,用于现场快速启动、监控 topic、检查环境和清理进程。
|
||||||
- 自定义 PICO 4 Ultra UDP Sender Unity 工程,负责发送左右手柄 pose、`grip` 和 `trigger`。
|
- 自定义 PICO 4 Ultra UDP Sender Unity 工程,负责发送左右手柄 pose、`grip`、`trigger` 和 pose 诊断字段。
|
||||||
|
|
||||||
暂未完成:
|
暂未完成:
|
||||||
|
|
||||||
@ -36,9 +36,14 @@ src/
|
|||||||
├── README.md # 项目主文档
|
├── README.md # 项目主文档
|
||||||
├── CODEX.md # Codex/Claude Code 项目工作流和安全规则
|
├── CODEX.md # Codex/Claude Code 项目工作流和安全规则
|
||||||
├── docs/
|
├── docs/
|
||||||
│ └── pico_udp_sender_ubuntu22_setup.md
|
│ └── pico_udp_sender_ubuntu22_setup.md # Ubuntu 22.04 下 PICO UDP Sender 配置教程
|
||||||
├── unity/
|
├── unity/
|
||||||
│ ├── XR_RM_PICO_UDP_Sender/ # PICO 4 Ultra UDP Sender Unity 工程
|
│ ├── XR_RM_PICO_UDP_Sender/ # PICO 4 Ultra UDP Sender Unity 工程
|
||||||
|
│ │ ├── Assets/Editor/ # Android/PICO 设置与 APK 构建菜单
|
||||||
|
│ │ ├── Assets/Scripts/ # UDP sender、配置面板、KeepAwake
|
||||||
|
│ │ ├── Assets/Resources/ # PICO 资源与 Roboto TMP 字体
|
||||||
|
│ │ ├── Packages/ # Unity package manifest
|
||||||
|
│ │ └── ProjectSettings/
|
||||||
│ └── PICO-Unity-Integration-SDK-release_3.4.0/
|
│ └── PICO-Unity-Integration-SDK-release_3.4.0/
|
||||||
├── xr_rm_bringup/
|
├── xr_rm_bringup/
|
||||||
│ ├── config/
|
│ ├── config/
|
||||||
@ -56,7 +61,7 @@ src/
|
|||||||
│ │ └── udp_receiver.launch.py # 低层 UDP 接收测试入口
|
│ │ └── udp_receiver.launch.py # 低层 UDP 接收测试入口
|
||||||
│ └── xr_rm_input/
|
│ └── xr_rm_input/
|
||||||
│ ├── udp_controller_receiver.py
|
│ ├── udp_controller_receiver.py
|
||||||
│ └── sample_udp_sender.py # 本机模拟手柄 UDP 数据
|
│ └── sample_udp_sender.py # 本机扫轴/正弦模拟手柄 UDP 数据
|
||||||
├── xr_rm_interfaces/
|
├── xr_rm_interfaces/
|
||||||
│ └── msg/
|
│ └── msg/
|
||||||
│ └── XrController.msg # hand/grip/trigger/pose
|
│ └── XrController.msg # hand/grip/trigger/pose
|
||||||
@ -111,7 +116,7 @@ ros2 run xr_rm_bringup launcher_ui
|
|||||||
|
|
||||||
面板顶部的 `Mode` 分为五类:
|
面板顶部的 `Mode` 分为五类:
|
||||||
|
|
||||||
- `Simulation`:左臂 mock、右臂 mock、双臂 mock、sample UDP 发送、one-click mock demo。
|
- `Simulation`:左臂 mock、右臂 mock、双臂 mock、sample UDP 发送、one-click mock demo、controller 位置/频率监控。
|
||||||
- `Left Arm`:左臂网络 ping、左臂真机 launch、左手 sample UDP。
|
- `Left Arm`:左臂网络 ping、左臂真机 launch、左手 sample UDP。
|
||||||
- `Right Arm`:右臂网络 ping、右臂真机 launch、右手 sample UDP。
|
- `Right Arm`:右臂网络 ping、右臂真机 launch、右手 sample UDP。
|
||||||
- `Dual Arm`:左右臂 ping、双臂真机 launch、双手 sample UDP。
|
- `Dual Arm`:左右臂 ping、双臂真机 launch、双手 sample UDP。
|
||||||
@ -123,12 +128,14 @@ ros2 run xr_rm_bringup launcher_ui
|
|||||||
- `Check Env`:检查 ROS2 Humble、工作空间 build、终端、核心 ROS 包、睿尔曼 API2。
|
- `Check Env`:检查 ROS2 Humble、工作空间 build、终端、核心 ROS 包、睿尔曼 API2。
|
||||||
- `Stop All`:结束由本工作空间启动的 launch、sample sender、topic monitor、相关 ROS 节点和终端窗口。
|
- `Stop All`:结束由本工作空间启动的 launch、sample sender、topic monitor、相关 ROS 节点和终端窗口。
|
||||||
|
|
||||||
每个模式都会附带三个监控入口:
|
每个模式都会附带基础监控入口:
|
||||||
|
|
||||||
- `Open Controller Topic Monitor`:同时查看 `/xr/left_controller` 和 `/xr/right_controller`。
|
- `Open Controller Topic Monitor`:同时查看 `/xr/left_controller` 和 `/xr/right_controller`。
|
||||||
- `Open Target Velocity Monitor`:同时查看 `/xr_rm/left_rm75/cmd_vel` 和 `/xr_rm/right_rm75/cmd_vel`;该话题表示目标位姿变化率,仅用于调试。
|
- `Open Target Velocity Monitor`:同时查看 `/xr_rm/left_rm75/cmd_vel` 和 `/xr_rm/right_rm75/cmd_vel`;该话题表示目标位姿变化率,仅用于调试。
|
||||||
- `Open ROS Topic/Node List Monitor`:每秒刷新 `ros2 topic list` 和 `ros2 node list`。
|
- `Open ROS Topic/Node List Monitor`:每秒刷新 `ros2 topic list` 和 `ros2 node list`。
|
||||||
|
|
||||||
|
`Simulation` 模式还提供 `Open Controller Position Monitor` 和 `Open Controller Hz Monitor`,用于快速看手柄位置字段和接收频率。
|
||||||
|
|
||||||
分屏监控依赖 `x-terminal-emulator` 指向 Terminator。若提示不支持,可安装并切换:
|
分屏监控依赖 `x-terminal-emulator` 指向 Terminator。若提示不支持,可安装并切换:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -148,9 +155,12 @@ sudo update-alternatives --config x-terminal-emulator
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=true
|
ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=true
|
||||||
ros2 run xr_rm_input sample_udp_sender --hand both --host 127.0.0.1 --port 15000 --seconds 10
|
ros2 run xr_rm_input sample_udp_sender --hand both --host 127.0.0.1 --port 15000 \
|
||||||
|
--pattern axis_sweep --seconds 60 --both-mode staggered
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`sample_udp_sender` 默认使用 `axis_sweep` 成对扫轴轨迹,并在终端打印 `XR +X/-X/+Y/-Y/+Z/-Z` 标签。`--hand both --both-mode staggered --seconds 60` 会先左后右,适合肉眼确认左右臂方向;如果只想左右同时动,可用 `--both-mode synchronized`。
|
||||||
|
|
||||||
观察:
|
观察:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -200,8 +210,12 @@ ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=false \
|
|||||||
- `left_robot_ip`:左臂 IP,默认 `192.168.192.18`。
|
- `left_robot_ip`:左臂 IP,默认 `192.168.192.18`。
|
||||||
- `right_robot_ip`:右臂 IP,默认 `192.168.192.19`。
|
- `right_robot_ip`:右臂 IP,默认 `192.168.192.19`。
|
||||||
- `robot_port`:RM75 TCP 端口,默认 `8080`。
|
- `robot_port`:RM75 TCP 端口,默认 `8080`。
|
||||||
|
- `left_avoid_singularity` / `right_avoid_singularity`:左右臂避奇异参数,默认左 `0`、右 `1`。
|
||||||
|
- `avoid_singularity`:非空时覆盖左右臂避奇异参数。
|
||||||
|
- `frame_type`:`rm_movep_canfd` 坐标系类型,默认 `1`。
|
||||||
- `control_rate_hz`:`rm_movep_canfd` 目标位姿发送频率,默认 `90.0`。
|
- `control_rate_hz`:`rm_movep_canfd` 目标位姿发送频率,默认 `90.0`。
|
||||||
- `follow`:传给 `rm_movep_canfd` 的跟随标志,默认 `false`。
|
- `follow`:传给 `rm_movep_canfd` 的跟随标志,默认 `false`。
|
||||||
|
- `configure_safety_limits`:连接真机后是否配置速度/加速度安全参数,默认 `true`。
|
||||||
- `enable_tool_control`:是否在遥操作节点内启用末端工具控制 topic,默认 `true`。
|
- `enable_tool_control`:是否在遥操作节点内启用末端工具控制 topic,默认 `true`。
|
||||||
- `configure_peripheral_on_connect`:遥操作节点连接真机后是否配置末端外设,默认 `true`;工具控制会复用同一个 RealMan 连接,避免两个进程同时抢占同一机械臂。
|
- `configure_peripheral_on_connect`:遥操作节点连接真机后是否配置末端外设,默认 `true`;工具控制会复用同一个 RealMan 连接,避免两个进程同时抢占同一机械臂。
|
||||||
- `move_to_initial_pose_on_connect`:连接后是否执行 `movej`/`movel` 初始化,默认 `false`。
|
- `move_to_initial_pose_on_connect`:连接后是否执行 `movej`/`movel` 初始化,默认 `false`。
|
||||||
@ -226,18 +240,20 @@ ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=false \
|
|||||||
- `max_linear_speed`:目标位姿单帧步长限制对应的最大线速度。
|
- `max_linear_speed`:目标位姿单帧步长限制对应的最大线速度。
|
||||||
- `workspace_min` / `workspace_max`:笛卡尔工作空间边界。
|
- `workspace_min` / `workspace_max`:笛卡尔工作空间边界。
|
||||||
- `cyl_radius_limit`:基座圆柱半径限制。
|
- `cyl_radius_limit`:基座圆柱半径限制。
|
||||||
- `xr_to_robot_matrix`:PICO/OpenXR 位移到 RM75 base 坐标的映射矩阵。
|
- `xr_to_robot_matrix`:`/xr/*_controller` Project 位移到 RM75 base 坐标的映射矩阵。
|
||||||
- `current_pose_poll_hz`:低频读取真机当前 TCP 的频率;控制中不再每帧阻塞读取状态。
|
- `current_pose_poll_hz`:低频读取真机当前 TCP 的频率;控制中不再每帧阻塞读取状态。
|
||||||
- `mock_initial_pose`:mock 模式初始 TCP 位姿。
|
- `mock_initial_pose`:mock 模式初始 TCP 位姿。
|
||||||
- `initial_joint_pose` / `initial_tcp_pose`:可选真机初始化点。
|
- `initial_joint_pose` / `initial_tcp_pose`:可选真机初始化点。
|
||||||
|
|
||||||
当前坐标约定:
|
当前 `/xr/*_controller` 的 Project 坐标约定:
|
||||||
|
|
||||||
- PICO/OpenXR:`+X` 向右,`+Y` 向上,`+Z` 向后。
|
- Project:`+X` 向右,`+Y` 向上,`+Z` 向后。
|
||||||
|
- Unity APK 的 `Project (+Z back)` 会把 PXR `pxr_predict` 原始坐标转换为 `project.x=native.z`、`project.y=native.y`、`project.z=-native.x`。
|
||||||
|
- `Source raw` 模式保留原始 pose source 坐标,只用于现场对照。
|
||||||
- 左臂映射:机器人位移增量 = `[-手柄y, 手柄z, -手柄x]`。
|
- 左臂映射:机器人位移增量 = `[-手柄y, 手柄z, -手柄x]`。
|
||||||
- 右臂映射:机器人位移增量 = `[手柄y, 手柄z, 手柄x]`。
|
- 右臂映射:机器人位移增量 = `[手柄y, 手柄z, 手柄x]`。
|
||||||
|
|
||||||
如果某个方向相反,只改对应臂的 `xr_to_robot_matrix` 符号,不要同时改多个控制参数。
|
如果 `/xr/*_controller.pose.position` 已符合 Project 坐标,但某个机械臂方向相反,只改对应臂的 `xr_to_robot_matrix` 符号,不要同时改多个控制参数。
|
||||||
|
|
||||||
## 末端工具开合
|
## 末端工具开合
|
||||||
|
|
||||||
@ -255,34 +271,52 @@ ros2 topic pub --once /xr_rm/right_rm75/tool_enable std_msgs/msg/Bool "{data: fa
|
|||||||
|
|
||||||
## UDP 数据格式
|
## UDP 数据格式
|
||||||
|
|
||||||
单个手柄:
|
当前 Unity APK 每个周期发送一个双手柄 JSON 包:
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"hand": "right",
|
|
||||||
"grip": true,
|
|
||||||
"trigger": 0.2,
|
|
||||||
"pos": [0.12, 1.05, 0.30],
|
|
||||||
"quat": [0.0, 0.0, 0.0, 1.0]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
左右手柄一起发送:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"t": 12.345,
|
||||||
|
"source_time": 12.345,
|
||||||
|
"seq": 42,
|
||||||
|
"frame_id": "xr_world",
|
||||||
"controllers": {
|
"controllers": {
|
||||||
"left": {
|
"left": {
|
||||||
"grip": true,
|
"grip": true,
|
||||||
"trigger": 0.0,
|
"trigger": 0.0,
|
||||||
"pos": [-0.12, 1.05, 0.30],
|
"pos": [-0.12, 1.05, 0.30],
|
||||||
"quat": [0.0, 0.0, 0.0, 1.0]
|
"quat": [0.0, 0.0, 0.0, 1.0],
|
||||||
|
"pose_valid": true,
|
||||||
|
"pose_source": "pxr_predict",
|
||||||
|
"tracking_state": 3,
|
||||||
|
"controller_status": 2,
|
||||||
|
"grip_value": 1.0,
|
||||||
|
"axis": [0.0, 0.0],
|
||||||
|
"buttons": {
|
||||||
|
"grip": true,
|
||||||
|
"primary": false,
|
||||||
|
"secondary": false,
|
||||||
|
"menu": false,
|
||||||
|
"axis_click": false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"right": {
|
"right": {
|
||||||
"grip": true,
|
"grip": true,
|
||||||
"trigger": 0.4,
|
"trigger": 0.4,
|
||||||
"pos": [0.12, 1.05, 0.30],
|
"pos": [0.12, 1.05, 0.30],
|
||||||
"quat": [0.0, 0.0, 0.0, 1.0]
|
"quat": [0.0, 0.0, 0.0, 1.0],
|
||||||
|
"pose_valid": true,
|
||||||
|
"pose_source": "unity_xr",
|
||||||
|
"tracking_state": 3,
|
||||||
|
"controller_status": -1,
|
||||||
|
"grip_value": 0.8,
|
||||||
|
"axis": [0.0, 0.0],
|
||||||
|
"buttons": {
|
||||||
|
"grip": true,
|
||||||
|
"primary": false,
|
||||||
|
"secondary": false,
|
||||||
|
"menu": false,
|
||||||
|
"axis_click": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,11 +324,19 @@ ros2 topic pub --once /xr_rm/right_rm75/tool_enable std_msgs/msg/Bool "{data: fa
|
|||||||
|
|
||||||
字段说明:
|
字段说明:
|
||||||
|
|
||||||
- `hand`:`left` 或 `right`。
|
- `t` / `source_time`:Unity 端 `Time.realtimeSinceStartupAsDouble`,用于后续延迟分析。
|
||||||
|
- `seq`:Unity 端递增包序号,用于后续丢包分析。
|
||||||
|
- `frame_id`:默认 `xr_world`,会写入 `XrController.header.frame_id`。
|
||||||
- `grip`:运动使能。`true` 时进入相对位移控制,`false` 时停止。
|
- `grip`:运动使能。`true` 时进入相对位移控制,`false` 时停止。
|
||||||
- `trigger`:扳机值,范围 `0.0-1.0`。当前控制主链路不使用它,预留给后续夹爪集成。
|
- `trigger`:扳机值,范围 `0.0-1.0`。当前控制主链路不使用它,预留给后续夹爪集成。
|
||||||
- `pos`:手柄位置,长度 3。
|
- `pos`:手柄位置,长度 3。
|
||||||
- `quat`:手柄姿态四元数,默认按 `xyzw` 解析。
|
- `quat`:手柄姿态四元数,默认按 `xyzw` 解析。
|
||||||
|
- `pose_valid`:姿态是否可信。ROS 接收端看到 `false` 会强制 `grip=false`。
|
||||||
|
- `pose_source`:`pxr_predict`、`unity_xr` 或 `none`,用于判断姿态来自 PICO 预测接口还是 Unity XR fallback。
|
||||||
|
- `tracking_state` / `controller_status`:Unity/PICO 侧追踪诊断值,只用于日志和排查。
|
||||||
|
- `grip_value`、`axis`、`buttons`:PICO 端输入诊断字段,当前不会写入 `XrController` 消息。
|
||||||
|
|
||||||
|
`udp_controller_receiver` 仍兼容调试用的单手柄包:可以直接发送带 `hand`、`pos`、`quat` 的 JSON object,也可以用 `controllers` list、顶层 `left/right`、`pose.position`、`position`、`p`、`q` 等常见字段。四元数默认按 `xyzw` 解析,也可通过 `quat_order:=wxyz` 切换。
|
||||||
|
|
||||||
PICO 4 Ultra 在 Ubuntu 22.04 下配置 Unity、构建 APK、安装到头显并向 ROS2 主机发送 UDP 的详细步骤见 [docs/pico_udp_sender_ubuntu22_setup.md](docs/pico_udp_sender_ubuntu22_setup.md)。
|
PICO 4 Ultra 在 Ubuntu 22.04 下配置 Unity、构建 APK、安装到头显并向 ROS2 主机发送 UDP 的详细步骤见 [docs/pico_udp_sender_ubuntu22_setup.md](docs/pico_udp_sender_ubuntu22_setup.md)。
|
||||||
|
|
||||||
@ -316,7 +358,7 @@ PICO 4 Ultra 在 Ubuntu 22.04 下配置 Unity、构建 APK、安装到头显并
|
|||||||
|
|
||||||
为了达到“稳定可用的双臂 XR 遥操作/采摘平台”,建议按下面顺序推进:
|
为了达到“稳定可用的双臂 XR 遥操作/采摘平台”,建议按下面顺序推进:
|
||||||
|
|
||||||
1. 稳定 PICO 数据链路:固定 UDP JSON 协议和坐标系,增加频率、延迟、丢包统计,记录 `/xr/*_controller`、`/xr_rm/*/raw_target_pose`、`/xr_rm/*/target_pose`、`/xr_rm/*/target_clamped`、`/xr_rm/*/current_pose`。
|
1. 稳定 PICO 数据链路:利用 `seq`、`source_time`、`pose_valid` 做频率、延迟、丢包和追踪状态统计,记录 `/xr/*_controller`、`/xr_rm/*/raw_target_pose`、`/xr_rm/*/target_pose`、`/xr_rm/*/target_clamped`、`/xr_rm/*/current_pose`。
|
||||||
2. 提升真机安全性:增加启动前安全检查、软件急停 topic、UI Stop 状态提示、双臂中间区域互斥边界和速度/加速度限幅。
|
2. 提升真机安全性:增加启动前安全检查、软件急停 topic、UI Stop 状态提示、双臂中间区域互斥边界和速度/加速度限幅。
|
||||||
3. 集成末端执行器:明确夹爪 topic、力控比例、开合方向和安全上限,把 `trigger` 从预留字段变成稳定夹爪输入。
|
3. 集成末端执行器:明确夹爪 topic、力控比例、开合方向和安全上限,把 `trigger` 从预留字段变成稳定夹爪输入。
|
||||||
4. 接入视觉和数据记录:加入 D405/D435 相机 launch、TF、内外参和 rosbag2 实验记录。
|
4. 接入视觉和数据记录:加入 D405/D435 相机 launch、TF、内外参和 rosbag2 实验记录。
|
||||||
@ -344,10 +386,12 @@ Controller topic 没有数据:
|
|||||||
- 确认 UDP 发送端目标 IP 是运行 ROS2 的主机 IP。
|
- 确认 UDP 发送端目标 IP 是运行 ROS2 的主机 IP。
|
||||||
- 确认端口是 `15000`,或 launch 与发送端端口一致。
|
- 确认端口是 `15000`,或 launch 与发送端端口一致。
|
||||||
- 用 `sample_udp_sender` 在本机验证接收链路。
|
- 用 `sample_udp_sender` 在本机验证接收链路。
|
||||||
|
- 如果 Unity HUD 显示某个手柄 `invalid none`,ROS 侧会把该手柄 `grip` 强制置为 `false`。
|
||||||
|
|
||||||
机械臂不动:
|
机械臂不动:
|
||||||
|
|
||||||
- 确认 `grip=true`。
|
- 确认 `grip=true`。
|
||||||
|
- 确认 `udp_controller_receiver` 终端没有持续 `pose_valid=false` 日志;该字段不会写入 `XrController` 消息,但会让接收端强制停止。
|
||||||
- 确认 `/xr_rm/<arm>/raw_target_pose` 与 `/xr_rm/<arm>/target_pose` 是否在变化。
|
- 确认 `/xr_rm/<arm>/raw_target_pose` 与 `/xr_rm/<arm>/target_pose` 是否在变化。
|
||||||
- 确认 `/xr_rm/<arm>/target_clamped` 是否持续为 `true`,如果是,目标 TCP 可能被工作空间、圆柱半径或单帧步长限制夹住。
|
- 确认 `/xr_rm/<arm>/target_clamped` 是否持续为 `true`,如果是,目标 TCP 可能被工作空间、圆柱半径或单帧步长限制夹住。
|
||||||
- 确认真机 SDK 连接成功,且 RM75 没有报警或急停。
|
- 确认真机 SDK 连接成功,且 RM75 没有报警或急停。
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
目标链路:
|
目标链路:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
PICO 4 Ultra 双手柄 6DoF pose / grip / trigger
|
PICO 4 Ultra 双手柄 6DoF pose / grip / trigger / pose 诊断
|
||||||
-> Unity Android APK
|
-> Unity Android APK
|
||||||
-> UDP JSON, 默认 192.168.9.99:15000 或当前 ROS 主机 IP:15000
|
-> UDP JSON, 默认当前 ROS 主机 IP:15000,兜底 192.168.9.99:15000
|
||||||
-> xr_rm_input/udp_controller_receiver
|
-> xr_rm_input/udp_controller_receiver
|
||||||
-> /xr/left_controller 与 /xr/right_controller
|
-> /xr/left_controller 与 /xr/right_controller
|
||||||
```
|
```
|
||||||
@ -19,12 +19,13 @@ PICO 4 Ultra 双手柄 6DoF pose / grip / trigger
|
|||||||
- Unity Editor 路径:`/home/robot/Unity/Hub/Editor/2022.3.62f3c1/Editor/Unity`
|
- Unity Editor 路径:`/home/robot/Unity/Hub/Editor/2022.3.62f3c1/Editor/Unity`
|
||||||
- PICO SDK 路径:`unity/PICO-Unity-Integration-SDK-release_3.4.0`
|
- PICO SDK 路径:`unity/PICO-Unity-Integration-SDK-release_3.4.0`
|
||||||
- PICO package 引用:`Packages/manifest.json` 中的 `file:../../PICO-Unity-Integration-SDK-release_3.4.0`
|
- PICO package 引用:`Packages/manifest.json` 中的 `file:../../PICO-Unity-Integration-SDK-release_3.4.0`
|
||||||
|
- Unity UI 依赖:`com.unity.textmeshpro`,运行面板使用预生成的 `Assets/Resources/Fonts/Roboto-Regular SDF.asset` 和 `Roboto-Bold SDF.asset`
|
||||||
- Android 包名:`com.local.xr_rm_udp_sender`
|
- Android 包名:`com.local.xr_rm_udp_sender`
|
||||||
- 默认 UDP 目标:`192.168.9.99:15000`
|
- 默认 UDP 目标:构建时优先使用 `XR_RM_UDP_TARGET_HOST`,否则自动选择本机局域网 IPv4,兜底 `192.168.9.99:15000`
|
||||||
- 默认发送频率:`60 Hz`
|
- 默认发送频率:`90 Hz`
|
||||||
- APK 输出:`unity/XR_RM_PICO_UDP_Sender/Builds/XR-RM-PICO-UDP-Sender.apk`
|
- APK 输出:`unity/XR_RM_PICO_UDP_Sender/Builds/XR-RM-PICO-UDP-Sender.apk`
|
||||||
|
|
||||||
PICO 端建议稳定发送 `60 Hz` 或 `90 Hz`,不要低于 `20 Hz`。ROS 遥操作节点默认 `command_timeout_sec=0.12`,超时会停止。
|
PICO 端建议稳定发送 `90 Hz`,网络或性能不足时可降到 `60 Hz`,不要低于 `20 Hz`。ROS 遥操作节点默认 `command_timeout_sec=0.12`,超时会停止。
|
||||||
|
|
||||||
## 2. Ubuntu 22.04 环境准备
|
## 2. Ubuntu 22.04 环境准备
|
||||||
|
|
||||||
@ -164,6 +165,7 @@ XR-RM -> Build Android APK
|
|||||||
- XR Management Android loader = PICO `PXR_Loader`
|
- XR Management Android loader = PICO `PXR_Loader`
|
||||||
- `Assets/Scenes/Main.unity`
|
- `Assets/Scenes/Main.unity`
|
||||||
- 场景中的 `PicoControllerUdpSender`、`PicoUdpConfigPanel` 和 `PicoKeepAwake`
|
- 场景中的 `PicoControllerUdpSender`、`PicoUdpConfigPanel` 和 `PicoKeepAwake`
|
||||||
|
- TextMeshPro UI、Roboto SDF 字体、Saved/Favorite IP 面板、PICO predicted pose 优先读取和 Unity XR fallback
|
||||||
|
|
||||||
也可以使用 batchmode 构建:
|
也可以使用 batchmode 构建:
|
||||||
|
|
||||||
@ -238,8 +240,10 @@ ip -4 addr
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `Target IP` | `192.168.9.99`,替换为当前 Ubuntu 主机 IP |
|
| `Target IP` | `192.168.9.99`,替换为当前 Ubuntu 主机 IP |
|
||||||
| `Target Port` | `15000` |
|
| `Target Port` | `15000` |
|
||||||
| `Send Rate` | `60 Hz` 或 `90 Hz` |
|
| `Saved IP` | 最近使用或收藏的 IP,可用摇杆左右切换 |
|
||||||
| `Coordinates` | `Project` |
|
| `Favorite` | `ON` 表示当前 IP 已收藏 |
|
||||||
|
| `Send Rate` | 推荐 `90 Hz`,不稳定时用 `60 Hz` |
|
||||||
|
| `Coordinates` | `Project (+Z back)` |
|
||||||
| `UDP Sending` | `ON` |
|
| `UDP Sending` | `ON` |
|
||||||
|
|
||||||
如果 Ubuntu 开启了 UFW:
|
如果 Ubuntu 开启了 UFW:
|
||||||
@ -254,7 +258,7 @@ sudo ufw status
|
|||||||
面板操作:
|
面板操作:
|
||||||
|
|
||||||
- 摇杆上/下:选择行
|
- 摇杆上/下:选择行
|
||||||
- 摇杆左/右:调整端口、频率、坐标模式或发送开关
|
- 摇杆左/右:选择 Saved IP、收藏当前 IP、调整端口/频率、切换坐标模式或发送开关
|
||||||
- Trigger / A / X:编辑当前行或触发当前行
|
- Trigger / A / X:编辑当前行或触发当前行
|
||||||
- B / Y:保存并应用
|
- B / Y:保存并应用
|
||||||
- Menu:在配置面板和运行 HUD 之间切换
|
- Menu:在配置面板和运行 HUD 之间切换
|
||||||
@ -262,9 +266,10 @@ sudo ufw status
|
|||||||
|
|
||||||
验证现象:
|
验证现象:
|
||||||
|
|
||||||
- 面板中 `L ok / R ok` 表示 Unity 能读到左右手柄。
|
- 面板中 `L valid pxr/unity` 或 `R valid pxr/unity` 表示 Unity 能读到对应手柄姿态;`invalid none` 表示该手柄姿态不可用。
|
||||||
- `UDP Sending ON` 后,ROS2 的 `/xr/left_controller` 与 `/xr/right_controller` 应持续刷新。
|
- `UDP Sending ON` 后,ROS2 的 `/xr/left_controller` 与 `/xr/right_controller` 应持续刷新。
|
||||||
- HUD 显示包计数、追踪状态、grip 和 KeepAwake 状态。
|
- HUD 显示包计数、发送端点、左右姿态状态和 KeepAwake 状态。
|
||||||
|
- `pose_valid=false` 时,ROS 接收端会强制该手柄 `grip=false`,即使 PICO 端按下了 Grip。
|
||||||
- 按住 `grip` 并移动手柄时,mock 模式下 `/xr_rm/*/target_pose` 应连续变化,`/xr_rm/*/cmd_vel` 会显示目标位姿变化率。
|
- 按住 `grip` 并移动手柄时,mock 模式下 `/xr_rm/*/target_pose` 应连续变化,`/xr_rm/*/cmd_vel` 会显示目标位姿变化率。
|
||||||
- 松开 `grip` 后,机械臂慢停,`cmd_vel` 应回到零。
|
- 松开 `grip` 后,机械臂慢停,`cmd_vel` 应回到零。
|
||||||
|
|
||||||
@ -352,9 +357,12 @@ ros2 topic echo /xr_rm/right_rm75/target_pose
|
|||||||
如果要排除 PICO 端问题,可用本机 sample sender 验证 ROS 端:
|
如果要排除 PICO 端问题,可用本机 sample sender 验证 ROS 端:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ros2 run xr_rm_input sample_udp_sender --hand both --host 127.0.0.1 --port 15000 --seconds 20
|
ros2 run xr_rm_input sample_udp_sender --hand both --host 127.0.0.1 --port 15000 \
|
||||||
|
--pattern axis_sweep --seconds 60 --both-mode staggered
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`axis_sweep` 会按 `XR +X/-X/+Y/-Y/+Z/-Z` 打印方向标签。双手 `staggered` 模式先左后右,便于现场逐只确认映射。
|
||||||
|
|
||||||
## 11. UDP JSON 协议
|
## 11. UDP JSON 协议
|
||||||
|
|
||||||
Unity APK 每个周期发送一个双手柄 JSON 包:
|
Unity APK 每个周期发送一个双手柄 JSON 包:
|
||||||
@ -362,19 +370,47 @@ Unity APK 每个周期发送一个双手柄 JSON 包:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"t": 12.345,
|
"t": 12.345,
|
||||||
|
"source_time": 12.345,
|
||||||
|
"seq": 42,
|
||||||
"frame_id": "xr_world",
|
"frame_id": "xr_world",
|
||||||
"controllers": {
|
"controllers": {
|
||||||
"left": {
|
"left": {
|
||||||
"grip": true,
|
"grip": true,
|
||||||
"trigger": 0.0,
|
"trigger": 0.0,
|
||||||
"pos": [-0.12, 1.05, 0.30],
|
"pos": [-0.12, 1.05, 0.30],
|
||||||
"quat": [0.0, 0.0, 0.0, 1.0]
|
"quat": [0.0, 0.0, 0.0, 1.0],
|
||||||
|
"pose_valid": true,
|
||||||
|
"pose_source": "pxr_predict",
|
||||||
|
"tracking_state": 3,
|
||||||
|
"controller_status": 2,
|
||||||
|
"grip_value": 1.0,
|
||||||
|
"axis": [0.0, 0.0],
|
||||||
|
"buttons": {
|
||||||
|
"grip": true,
|
||||||
|
"primary": false,
|
||||||
|
"secondary": false,
|
||||||
|
"menu": false,
|
||||||
|
"axis_click": false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"right": {
|
"right": {
|
||||||
"grip": true,
|
"grip": true,
|
||||||
"trigger": 0.4,
|
"trigger": 0.4,
|
||||||
"pos": [0.12, 1.05, 0.30],
|
"pos": [0.12, 1.05, 0.30],
|
||||||
"quat": [0.0, 0.0, 0.0, 1.0]
|
"quat": [0.0, 0.0, 0.0, 1.0],
|
||||||
|
"pose_valid": true,
|
||||||
|
"pose_source": "unity_xr",
|
||||||
|
"tracking_state": 3,
|
||||||
|
"controller_status": -1,
|
||||||
|
"grip_value": 0.8,
|
||||||
|
"axis": [0.0, 0.0],
|
||||||
|
"buttons": {
|
||||||
|
"grip": true,
|
||||||
|
"primary": false,
|
||||||
|
"secondary": false,
|
||||||
|
"menu": false,
|
||||||
|
"axis_click": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -385,6 +421,8 @@ Unity APK 每个周期发送一个双手柄 JSON 包:
|
|||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `t` | number | `Time.realtimeSinceStartupAsDouble` |
|
| `t` | number | `Time.realtimeSinceStartupAsDouble` |
|
||||||
|
| `source_time` | number | 当前同 `t`,预留给延迟统计 |
|
||||||
|
| `seq` | number | 发送端递增包序号,预留给丢包统计 |
|
||||||
| `frame_id` | string | 默认 `xr_world` |
|
| `frame_id` | string | 默认 `xr_world` |
|
||||||
| `controllers.left` | object | 左手柄 |
|
| `controllers.left` | object | 左手柄 |
|
||||||
| `controllers.right` | object | 右手柄 |
|
| `controllers.right` | object | 右手柄 |
|
||||||
@ -392,25 +430,31 @@ Unity APK 每个周期发送一个双手柄 JSON 包:
|
|||||||
| `trigger` | float | `0.0-1.0` |
|
| `trigger` | float | `0.0-1.0` |
|
||||||
| `pos` | float[3] | `[x, y, z]` |
|
| `pos` | float[3] | `[x, y, z]` |
|
||||||
| `quat` | float[4] | `[qx, qy, qz, qw]` |
|
| `quat` | float[4] | `[qx, qy, qz, qw]` |
|
||||||
|
| `pose_valid` | bool | 姿态有效性;`false` 时 ROS receiver 强制 `grip=false` |
|
||||||
|
| `pose_source` | string | `pxr_predict`、`unity_xr` 或 `none` |
|
||||||
|
| `tracking_state` | int | Unity XR tracking state 原始值 |
|
||||||
|
| `controller_status` | int | PICO controller status 原始值,Unity XR fallback 时为 `-1` |
|
||||||
|
| `grip_value` | float | Grip 模拟量,范围 `0.0-1.0` |
|
||||||
|
| `axis` | float[2] | 主摇杆二维轴 |
|
||||||
|
| `buttons` | object | `grip`、`primary`、`secondary`、`menu`、`axis_click` |
|
||||||
|
|
||||||
坐标转换应与当前工程保持一致:
|
当前工程的 `Project (+Z back)` 坐标是 ROS 侧使用的统一项目坐标:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
payload.pos[0] = position.x;
|
project.x = native.z;
|
||||||
payload.pos[1] = position.y;
|
project.y = native.y;
|
||||||
payload.pos[2] = -position.z;
|
project.z = -native.x;
|
||||||
|
|
||||||
payload.quat[0] = -rotation.x;
|
|
||||||
payload.quat[1] = -rotation.y;
|
|
||||||
payload.quat[2] = rotation.z;
|
|
||||||
payload.quat[3] = rotation.w;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
这条转换只用于 `pose_source=pxr_predict` 且 `Coordinates=Project (+Z back)` 的情况。`Source raw` 模式保留 PXR native 或 Unity XR fallback 的原始坐标,便于现场对照;`unity_xr` fallback 暂不做 PXR native 转换,避免把已经由 Unity XR 提供的坐标二次转换。
|
||||||
|
|
||||||
禁用发送、App 暂停或退出时,必须额外发送一次左右手柄 `grip=false`,让 ROS 侧安全停止。
|
禁用发送、App 暂停或退出时,必须额外发送一次左右手柄 `grip=false`,让 ROS 侧安全停止。
|
||||||
|
|
||||||
|
`udp_controller_receiver` 仍兼容调试脚本的旧格式:单个 object 可以直接带 `hand`、`pos`、`quat`;`controllers` 可以是 object 或 list;位置字段也支持 `position`、`p`、`pose.position`,姿态字段支持 `orientation`、`q`。四元数默认按 `xyzw` 解析,也可用 `quat_order:=wxyz` 覆盖。
|
||||||
|
|
||||||
## 12. 坐标方向检查
|
## 12. 坐标方向检查
|
||||||
|
|
||||||
当前配置使用 PICO/OpenXR 位置坐标:
|
当前 Project 输出使用下面的位置坐标:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
+X: 向右
|
+X: 向右
|
||||||
@ -418,6 +462,8 @@ payload.quat[3] = rotation.w;
|
|||||||
+Z: 向后
|
+Z: 向后
|
||||||
```
|
```
|
||||||
|
|
||||||
|
PXR `pxr_predict` 原始坐标按现场实测通常表现为右移 `native.z+`、前伸 `native.x+`,所以 Unity 在 Project 模式中会输出 `project.x=native.z`、`project.z=-native.x`。如果切到 `Source raw`,应能看到原始 PXR 现象,用于确认当前到底是 PXR native 问题还是 ROS 侧映射问题。
|
||||||
|
|
||||||
双臂配置中的映射关系:
|
双臂配置中的映射关系:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@ -428,12 +474,14 @@ payload.quat[3] = rotation.w;
|
|||||||
建议现场按下面顺序验证:
|
建议现场按下面顺序验证:
|
||||||
|
|
||||||
1. 只启动 `use_mock:=true`。
|
1. 只启动 `use_mock:=true`。
|
||||||
2. 按住左手 `grip`,沿 PICO 的 `+X/-X`、`+Y/-Y`、`+Z/-Z` 每次只动一个轴。
|
2. APK 中选择 `Project (+Z back)`,按住左手 `grip`,每次只沿右/左、上/下、前/后移动一个方向。
|
||||||
3. 记录 `/xr/left_controller.pose.position` 的变化方向。
|
3. 记录 `/xr/left_controller.pose.position` 的变化方向。
|
||||||
4. 记录 `/xr_rm/left_rm75/target_pose` 的方向。
|
4. 记录 `/xr_rm/left_rm75/target_pose` 的方向。
|
||||||
5. 右手重复。
|
5. 右手重复。
|
||||||
|
|
||||||
如果两个手柄在 ROS topic 里的某个轴都反了,优先检查 Unity 的坐标转换。如果 ROS topic 正确,但某一只机械臂运动方向不符合现场坐标,只改对应 YAML 的 `xr_to_robot_matrix`。
|
如果两个手柄在 ROS topic 里的某个轴都反了,优先检查 Unity/PICO 发送到 `/xr/*_controller.pose.position` 的实际方向。如果 ROS topic 正确,但某一只机械臂运动方向不符合现场坐标,只改对应 YAML 的 `xr_to_robot_matrix`。
|
||||||
|
|
||||||
|
`Coordinates=Source raw` 只用于诊断,不建议用于正式遥操作。现场方向修正优先通过 ROS 侧 topic 观察定位:如果 `/xr/*_controller.pose.position` 已经符合 Project 坐标约定,就不要在 Unity 中继续临时改符号。
|
||||||
|
|
||||||
## 13. 真机前置检查
|
## 13. 真机前置检查
|
||||||
|
|
||||||
@ -468,13 +516,13 @@ ros2 launch xr_rm_bringup arm_debug.launch.py arm:=both use_mock:=false \
|
|||||||
| Unity 找不到 PICO package | 检查 `Packages/manifest.json` 的 `../../PICO-Unity-Integration-SDK-release_3.4.0` 路径 |
|
| Unity 找不到 PICO package | 检查 `Packages/manifest.json` 的 `../../PICO-Unity-Integration-SDK-release_3.4.0` 路径 |
|
||||||
| Gradle 或 Android 构建失败 | 检查 Android Build Support、SDK/NDK/OpenJDK、IL2CPP、ARM64、Android Build Target 和 PICO SDK 编译错误 |
|
| Gradle 或 Android 构建失败 | 检查 Android Build Support、SDK/NDK/OpenJDK、IL2CPP、ARM64、Android Build Target 和 PICO SDK 编译错误 |
|
||||||
| PICO 安装失败或 `unauthorized` | 重新授权 USB 调试,执行 `adb kill-server && adb start-server && adb devices` |
|
| PICO 安装失败或 `unauthorized` | 重新授权 USB 调试,执行 `adb kill-server && adb start-server && adb devices` |
|
||||||
| ROS2 收不到 UDP | 检查同一 Wi-Fi、Target IP、Target Port、UFW、`UDP Sending ON`、`L ok / R ok` |
|
| ROS2 收不到 UDP | 检查同一 Wi-Fi、Target IP、Target Port、UFW、`UDP Sending ON`、左右手柄是否 `valid pxr/unity` |
|
||||||
| tcpdump 有包但 topic 没数据 | JSON 字段不对,确认包含 `controllers.left/right`,且 `pos` 长度 3、`quat` 长度 4 |
|
| tcpdump 有包但 topic 没数据 | JSON 字段不对,确认包含 `controllers.left/right`,且 `pos` 长度 3、`quat` 长度 4 |
|
||||||
| 有 topic 但机械臂不动 | 检查 `grip`、teleop 节点订阅话题、工作空间限幅、UDP 超时 |
|
| 有 topic 但机械臂不动 | 检查 `grip`、`pose_valid` 日志、teleop 节点订阅话题、工作空间限幅、UDP 超时 |
|
||||||
| 按左手右臂动 | PICO 端 left/right 获取或填充反了 |
|
| 按左手右臂动 | PICO 端 left/right 获取或填充反了 |
|
||||||
| 松开 grip 后仍有速度 | 确认 PICO 持续发送 `grip=false`,并检查 teleop 超时停止 |
|
| 松开 grip 后仍有速度 | 确认 PICO 持续发送 `grip=false`,并检查 teleop 超时停止 |
|
||||||
| 经常超时 | 发送频率太低、网络丢包、PICO 应用后台暂停;提高 `sendHz` 并保持应用前台运行 |
|
| 经常超时 | 发送频率太低、网络丢包、PICO 应用后台暂停;提高 `sendHz` 并保持应用前台运行 |
|
||||||
| 前后方向反了 | 先切换 Unity 坐标转换,再验证 ROS topic |
|
| 前后方向反了 | 先看 `/xr/*_controller.pose.position` 是否符合 `+Z` 向后;topic 正确时修改对应 YAML 的 `xr_to_robot_matrix` |
|
||||||
| 某一只臂方向反了 | 修改对应 YAML 的 `xr_to_robot_matrix` |
|
| 某一只臂方向反了 | 修改对应 YAML 的 `xr_to_robot_matrix` |
|
||||||
|
|
||||||
## 15. 参考链接
|
## 15. 参考链接
|
||||||
|
|||||||
@ -0,0 +1,260 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TextCore.LowLevel;
|
||||||
|
|
||||||
|
public static class XrRmTmpFontAssetBuilder
|
||||||
|
{
|
||||||
|
private const string ResourcesDirectory = "Assets/Resources";
|
||||||
|
private const string FontDirectory = "Assets/Resources/Fonts";
|
||||||
|
private const string RegularFontPath = FontDirectory + "/Roboto-Regular.ttf";
|
||||||
|
private const string BoldFontPath = FontDirectory + "/Roboto-Bold.ttf";
|
||||||
|
private const string RegularAssetPath = FontDirectory + "/Roboto-Regular SDF.asset";
|
||||||
|
private const string BoldAssetPath = FontDirectory + "/Roboto-Bold SDF.asset";
|
||||||
|
private const string PreferredTmpSettingsPath = ResourcesDirectory + "/TMP Settings.asset";
|
||||||
|
private const string StandardTmpSettingsPath = "Assets/TextMesh Pro/Resources/TMP Settings.asset";
|
||||||
|
private const int SamplingPointSize = 90;
|
||||||
|
private const int AtlasPadding = 9;
|
||||||
|
private const int AtlasSize = 1024;
|
||||||
|
private const string MobileSdfShaderName = "TextMeshPro/Mobile/Distance Field";
|
||||||
|
|
||||||
|
[MenuItem("XR-RM/Rebuild Roboto TMP Font Assets")]
|
||||||
|
public static void RebuildRobotoFontAssets()
|
||||||
|
{
|
||||||
|
EnsureRobotoFontAssets(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnsureRobotoFontAssets(bool forceRebuild = false)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(ResourcesDirectory);
|
||||||
|
Directory.CreateDirectory(FontDirectory);
|
||||||
|
EnsureTmpEssentialResources();
|
||||||
|
|
||||||
|
TMP_FontAsset regularFontAsset = EnsureFontAsset(
|
||||||
|
RegularFontPath,
|
||||||
|
RegularAssetPath,
|
||||||
|
"Roboto-Regular SDF",
|
||||||
|
forceRebuild);
|
||||||
|
TMP_FontAsset boldFontAsset = EnsureFontAsset(
|
||||||
|
BoldFontPath,
|
||||||
|
BoldAssetPath,
|
||||||
|
"Roboto-Bold SDF",
|
||||||
|
forceRebuild);
|
||||||
|
|
||||||
|
EnsureTmpSettings(regularFontAsset, boldFontAsset);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
Debug.Log("XR-RM Roboto TMP font assets are ready.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TMP_FontAsset EnsureFontAsset(string fontPath, string assetPath, string assetName, bool forceRebuild)
|
||||||
|
{
|
||||||
|
if (!forceRebuild)
|
||||||
|
{
|
||||||
|
TMP_FontAsset existing = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(assetPath);
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(fontPath))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Roboto font file is missing.", fontPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetDatabase.ImportAsset(fontPath, ImportAssetOptions.ForceSynchronousImport);
|
||||||
|
Font sourceFont = AssetDatabase.LoadAssetAtPath<Font>(fontPath);
|
||||||
|
if (sourceFont == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Unity could not import Roboto font: " + fontPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(assetPath))
|
||||||
|
{
|
||||||
|
AssetDatabase.DeleteAsset(assetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_FontAsset fontAsset = TMP_FontAsset.CreateFontAsset(
|
||||||
|
sourceFont,
|
||||||
|
SamplingPointSize,
|
||||||
|
AtlasPadding,
|
||||||
|
GlyphRenderMode.SDFAA,
|
||||||
|
AtlasSize,
|
||||||
|
AtlasSize,
|
||||||
|
AtlasPopulationMode.Dynamic,
|
||||||
|
false);
|
||||||
|
if (fontAsset == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("TextMesh Pro could not create font asset from: " + fontPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
fontAsset.name = assetName;
|
||||||
|
fontAsset.atlasTextures[0].name = assetName + " Atlas";
|
||||||
|
fontAsset.material.name = assetName + " Atlas Material";
|
||||||
|
|
||||||
|
if (!fontAsset.TryAddCharacters(BuildAsciiCharacterSet(), out string missingCharacters) ||
|
||||||
|
!string.IsNullOrEmpty(missingCharacters))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(assetName + " is missing ASCII glyphs: " + missingCharacters);
|
||||||
|
}
|
||||||
|
|
||||||
|
fontAsset.atlasPopulationMode = AtlasPopulationMode.Static;
|
||||||
|
fontAsset.ReadFontAssetDefinition();
|
||||||
|
|
||||||
|
Texture2D atlasTexture = fontAsset.atlasTexture;
|
||||||
|
Material atlasMaterial = fontAsset.material;
|
||||||
|
AssetDatabase.CreateAsset(fontAsset, assetPath);
|
||||||
|
if (atlasTexture != null)
|
||||||
|
{
|
||||||
|
AssetDatabase.AddObjectToAsset(atlasTexture, fontAsset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atlasMaterial != null)
|
||||||
|
{
|
||||||
|
AssetDatabase.AddObjectToAsset(atlasMaterial, fontAsset);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorUtility.SetDirty(fontAsset);
|
||||||
|
return fontAsset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EnsureTmpSettings(TMP_FontAsset regularFontAsset, TMP_FontAsset fallbackFontAsset)
|
||||||
|
{
|
||||||
|
string settingsPath = ResolveTmpSettingsPath();
|
||||||
|
TMP_Settings settings = AssetDatabase.LoadAssetAtPath<TMP_Settings>(settingsPath);
|
||||||
|
if (settings == null)
|
||||||
|
{
|
||||||
|
settings = ScriptableObject.CreateInstance<TMP_Settings>();
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(settingsPath));
|
||||||
|
AssetDatabase.CreateAsset(settings, settingsPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedObject serializedSettings = new SerializedObject(settings);
|
||||||
|
SetObject(serializedSettings, "m_defaultFontAsset", regularFontAsset);
|
||||||
|
SetString(serializedSettings, "m_defaultFontAssetPath", "Fonts/");
|
||||||
|
SetFloat(serializedSettings, "m_defaultFontSize", 36.0f);
|
||||||
|
SetFloat(serializedSettings, "m_defaultAutoSizeMinRatio", 0.5f);
|
||||||
|
SetFloat(serializedSettings, "m_defaultAutoSizeMaxRatio", 1.0f);
|
||||||
|
SetBool(serializedSettings, "m_enableWordWrapping", false);
|
||||||
|
SetBool(serializedSettings, "m_enableKerning", true);
|
||||||
|
SetBool(serializedSettings, "m_EnableRaycastTarget", false);
|
||||||
|
SetObjectArray(serializedSettings, "m_fallbackFontAssets", fallbackFontAsset);
|
||||||
|
serializedSettings.ApplyModifiedPropertiesWithoutUndo();
|
||||||
|
EditorUtility.SetDirty(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EnsureTmpEssentialResources()
|
||||||
|
{
|
||||||
|
if (Shader.Find(MobileSdfShaderName) != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityEditor.PackageManager.PackageInfo packageInfo =
|
||||||
|
UnityEditor.PackageManager.PackageInfo.FindForAssembly(typeof(TMP_Text).Assembly);
|
||||||
|
if (packageInfo == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Could not locate the TextMesh Pro package.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string packagePath = Path.GetFullPath(Path.Combine(
|
||||||
|
packageInfo.resolvedPath,
|
||||||
|
"Package Resources/TMP Essential Resources.unitypackage"));
|
||||||
|
if (!File.Exists(packagePath))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("TMP Essential Resources package is missing.", packagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log("XR-RM importing TMP Essential Resources: " + packagePath);
|
||||||
|
AssetDatabase.ImportPackage(packagePath, false);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
|
||||||
|
if (Shader.Find(MobileSdfShaderName) == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("TMP Essential Resources did not import the shader: " + MobileSdfShaderName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveTmpSettingsPath()
|
||||||
|
{
|
||||||
|
if (File.Exists(PreferredTmpSettingsPath))
|
||||||
|
{
|
||||||
|
return PreferredTmpSettingsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(StandardTmpSettingsPath))
|
||||||
|
{
|
||||||
|
return StandardTmpSettingsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PreferredTmpSettingsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetObject(SerializedObject serializedObject, string propertyName, UnityEngine.Object value)
|
||||||
|
{
|
||||||
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||||||
|
if (property != null)
|
||||||
|
{
|
||||||
|
property.objectReferenceValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetObjectArray(SerializedObject serializedObject, string propertyName, UnityEngine.Object value)
|
||||||
|
{
|
||||||
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||||||
|
if (property == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
property.arraySize = value == null ? 0 : 1;
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
property.GetArrayElementAtIndex(0).objectReferenceValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetString(SerializedObject serializedObject, string propertyName, string value)
|
||||||
|
{
|
||||||
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||||||
|
if (property != null)
|
||||||
|
{
|
||||||
|
property.stringValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetFloat(SerializedObject serializedObject, string propertyName, float value)
|
||||||
|
{
|
||||||
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||||||
|
if (property != null)
|
||||||
|
{
|
||||||
|
property.floatValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetBool(SerializedObject serializedObject, string propertyName, bool value)
|
||||||
|
{
|
||||||
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||||||
|
if (property != null)
|
||||||
|
{
|
||||||
|
property.boolValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildAsciiCharacterSet()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder(95);
|
||||||
|
for (char character = ' '; character <= '~'; character++)
|
||||||
|
{
|
||||||
|
builder.Append(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 920e39429cd12b700a4f933dc98ab844
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,10 +1,8 @@
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using UnityEditor.Build;
|
using UnityEditor.Build;
|
||||||
using UnityEditor.Build.Reporting;
|
using UnityEditor.Build.Reporting;
|
||||||
@ -21,18 +19,25 @@ using Unity.XR.PXR;
|
|||||||
public static class XrRmUdpSenderProjectSetup
|
public static class XrRmUdpSenderProjectSetup
|
||||||
{
|
{
|
||||||
private const string ScenePath = "Assets/Scenes/Main.unity";
|
private const string ScenePath = "Assets/Scenes/Main.unity";
|
||||||
|
private const string PicoProjectSettingPath = "Assets/Resources/PXR_ProjectSetting.asset";
|
||||||
private const string PackageName = "com.local.xr_rm_udp_sender";
|
private const string PackageName = "com.local.xr_rm_udp_sender";
|
||||||
private const string ProductName = "XR-RM-PICO-UDP-Sender";
|
private const string ProductName = "XR-RM-PICO-UDP-Sender";
|
||||||
|
private const string VersionName = "1.0";
|
||||||
private const string DefaultTargetHost = "192.168.9.99";
|
private const string DefaultTargetHost = "192.168.9.99";
|
||||||
private const string TargetHostEnvVar = "XR_RM_UDP_TARGET_HOST";
|
private const string TargetHostEnvVar = "XR_RM_UDP_TARGET_HOST";
|
||||||
|
private const int MaxAndroidVersionCode = 2100000000;
|
||||||
|
private static readonly DateTime BuildVersionEpochUtc = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||||
|
|
||||||
[MenuItem("XR-RM/Apply UDP Sender Android Settings")]
|
[MenuItem("XR-RM/Apply UDP Sender Android Settings")]
|
||||||
public static void ApplyAndroidSettings()
|
public static void ApplyAndroidSettings()
|
||||||
{
|
{
|
||||||
|
PlayerSettings.companyName = "XR-RM";
|
||||||
PlayerSettings.productName = ProductName;
|
PlayerSettings.productName = ProductName;
|
||||||
|
PlayerSettings.bundleVersion = VersionName;
|
||||||
PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, PackageName);
|
PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, PackageName);
|
||||||
PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel29;
|
PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel29;
|
||||||
PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevelAuto;
|
PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevelAuto;
|
||||||
|
PlayerSettings.Android.preferredInstallLocation = AndroidPreferredInstallLocation.ForceInternal;
|
||||||
PlayerSettings.Android.forceInternetPermission = true;
|
PlayerSettings.Android.forceInternetPermission = true;
|
||||||
PlayerSettings.SetScriptingBackend(NamedBuildTarget.Android, ScriptingImplementation.IL2CPP);
|
PlayerSettings.SetScriptingBackend(NamedBuildTarget.Android, ScriptingImplementation.IL2CPP);
|
||||||
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
|
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
|
||||||
@ -49,7 +54,9 @@ public static class XrRmUdpSenderProjectSetup
|
|||||||
|
|
||||||
EditorUserBuildSettings.selectedBuildTargetGroup = BuildTargetGroup.Android;
|
EditorUserBuildSettings.selectedBuildTargetGroup = BuildTargetGroup.Android;
|
||||||
EnsurePicoSettings();
|
EnsurePicoSettings();
|
||||||
|
NormalizePicoProjectSettings();
|
||||||
EnablePicoLoader();
|
EnablePicoLoader();
|
||||||
|
XrRmTmpFontAssetBuilder.EnsureRobotoFontAssets();
|
||||||
CreateOrRefreshScene();
|
CreateOrRefreshScene();
|
||||||
EditorBuildSettings.scenes = new[] { new EditorBuildSettingsScene(ScenePath, true) };
|
EditorBuildSettings.scenes = new[] { new EditorBuildSettingsScene(ScenePath, true) };
|
||||||
AssetDatabase.SaveAssets();
|
AssetDatabase.SaveAssets();
|
||||||
@ -77,7 +84,7 @@ public static class XrRmUdpSenderProjectSetup
|
|||||||
component = sender.AddComponent<PicoControllerUdpSender>();
|
component = sender.AddComponent<PicoControllerUdpSender>();
|
||||||
}
|
}
|
||||||
|
|
||||||
string targetHost = ResolveTargetHost();
|
string targetHost = ResolveTargetHost(component.host);
|
||||||
component.host = targetHost;
|
component.host = targetHost;
|
||||||
component.port = 15000;
|
component.port = 15000;
|
||||||
component.sendHz = 90.0f;
|
component.sendHz = 90.0f;
|
||||||
@ -131,6 +138,7 @@ public static class XrRmUdpSenderProjectSetup
|
|||||||
public static void BuildAndroidApk()
|
public static void BuildAndroidApk()
|
||||||
{
|
{
|
||||||
ApplyAndroidSettings();
|
ApplyAndroidSettings();
|
||||||
|
BumpAndroidVersionCodeForInstall();
|
||||||
|
|
||||||
Directory.CreateDirectory("Builds");
|
Directory.CreateDirectory("Builds");
|
||||||
BuildPlayerOptions options = new BuildPlayerOptions
|
BuildPlayerOptions options = new BuildPlayerOptions
|
||||||
@ -152,6 +160,54 @@ public static class XrRmUdpSenderProjectSetup
|
|||||||
Debug.Log($"Android APK built: {options.locationPathName}");
|
Debug.Log($"Android APK built: {options.locationPathName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void BumpAndroidVersionCodeForInstall()
|
||||||
|
{
|
||||||
|
long elapsedMinutes = (long)(DateTime.UtcNow - BuildVersionEpochUtc).TotalMinutes;
|
||||||
|
long currentVersionCode = Math.Max(0, PlayerSettings.Android.bundleVersionCode);
|
||||||
|
long nextVersionCode = Math.Max(currentVersionCode + 1, elapsedMinutes);
|
||||||
|
|
||||||
|
if (nextVersionCode > MaxAndroidVersionCode)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Android versionCode {nextVersionCode} exceeds safe install limit {MaxAndroidVersionCode}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerSettings.Android.bundleVersionCode = (int)nextVersionCode;
|
||||||
|
Debug.Log($"XR-RM Android versionCode set to {nextVersionCode} for installable APK builds.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void NormalizePicoProjectSettings()
|
||||||
|
{
|
||||||
|
UnityEngine.Object projectSetting = AssetDatabase.LoadMainAssetAtPath(PicoProjectSettingPath);
|
||||||
|
if (projectSetting == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedObject serializedSetting = new SerializedObject(projectSetting);
|
||||||
|
SetBoolOrInt(serializedSetting, "portalInited", false);
|
||||||
|
serializedSetting.ApplyModifiedPropertiesWithoutUndo();
|
||||||
|
EditorUtility.SetDirty(projectSetting);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetBoolOrInt(SerializedObject serializedObject, string propertyName, bool value)
|
||||||
|
{
|
||||||
|
SerializedProperty property = serializedObject.FindProperty(propertyName);
|
||||||
|
if (property == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property.propertyType == SerializedPropertyType.Boolean)
|
||||||
|
{
|
||||||
|
property.boolValue = value;
|
||||||
|
}
|
||||||
|
else if (property.propertyType == SerializedPropertyType.Integer)
|
||||||
|
{
|
||||||
|
property.intValue = value ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void EnablePicoLoader()
|
private static void EnablePicoLoader()
|
||||||
{
|
{
|
||||||
XRGeneralSettingsPerBuildTarget buildTargetSettings = AssetDatabase.FindAssets("t:XRGeneralSettingsPerBuildTarget")
|
XRGeneralSettingsPerBuildTarget buildTargetSettings = AssetDatabase.FindAssets("t:XRGeneralSettingsPerBuildTarget")
|
||||||
@ -196,7 +252,7 @@ public static class XrRmUdpSenderProjectSetup
|
|||||||
EditorUtility.SetDirty(buildTargetSettings);
|
EditorUtility.SetDirty(buildTargetSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ResolveTargetHost()
|
private static string ResolveTargetHost(string existingHost)
|
||||||
{
|
{
|
||||||
string envHost = Environment.GetEnvironmentVariable(TargetHostEnvVar);
|
string envHost = Environment.GetEnvironmentVariable(TargetHostEnvVar);
|
||||||
if (IsUsableTargetHost(envHost))
|
if (IsUsableTargetHost(envHost))
|
||||||
@ -204,40 +260,12 @@ public static class XrRmUdpSenderProjectSetup
|
|||||||
return envHost.Trim();
|
return envHost.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
string discoveredHost = GetPreferredLocalIPv4Address();
|
if (IsUsableTargetHost(existingHost))
|
||||||
return string.IsNullOrEmpty(discoveredHost) ? DefaultTargetHost : discoveredHost;
|
{
|
||||||
|
return existingHost.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetPreferredLocalIPv4Address()
|
return DefaultTargetHost;
|
||||||
{
|
|
||||||
List<string> candidates = new List<string>();
|
|
||||||
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
|
|
||||||
{
|
|
||||||
if (networkInterface.OperationalStatus != OperationalStatus.Up)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
|
|
||||||
networkInterface.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (UnicastIPAddressInformation addressInfo in networkInterface.GetIPProperties().UnicastAddresses)
|
|
||||||
{
|
|
||||||
string address = addressInfo.Address.ToString();
|
|
||||||
if (IsUsableTargetHost(address))
|
|
||||||
{
|
|
||||||
candidates.Add(address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return candidates
|
|
||||||
.OrderByDescending(GetAddressScore)
|
|
||||||
.ThenBy(address => address, StringComparer.Ordinal)
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsUsableTargetHost(string value)
|
private static bool IsUsableTargetHost(string value)
|
||||||
@ -256,37 +284,5 @@ public static class XrRmUdpSenderProjectSetup
|
|||||||
return !loopback && !linkLocal && !unspecified;
|
return !loopback && !linkLocal && !unspecified;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetAddressScore(string address)
|
|
||||||
{
|
|
||||||
string[] parts = address.Split('.');
|
|
||||||
if (parts.Length != 4 ||
|
|
||||||
!int.TryParse(parts[0], out int first) ||
|
|
||||||
!int.TryParse(parts[1], out int second))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first == 192 && second == 168)
|
|
||||||
{
|
|
||||||
return 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first == 10)
|
|
||||||
{
|
|
||||||
return 40;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first == 172 && second >= 16 && second <= 31)
|
|
||||||
{
|
|
||||||
return 35;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first == 198 && (second == 18 || second == 19))
|
|
||||||
{
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
8
unity/XR_RM_PICO_UDP_Sender/Assets/Resources/Fonts.meta
Normal file
8
unity/XR_RM_PICO_UDP_Sender/Assets/Resources/Fonts.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 94df55e59529ba0f495c83a2e46c2cb6
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9605d99cce67df46ea0e78c679b423e9
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
@ -0,0 +1,21 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c8a92aff4ec89686dbbebe474b26d3d6
|
||||||
|
TrueTypeFontImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 4
|
||||||
|
fontSize: 16
|
||||||
|
forceTextureCase: -2
|
||||||
|
characterSpacing: 0
|
||||||
|
characterPadding: 1
|
||||||
|
includeFontData: 1
|
||||||
|
fontNames:
|
||||||
|
- Roboto
|
||||||
|
fallbackFontReferences: []
|
||||||
|
customCharacters:
|
||||||
|
fontRenderingMode: 0
|
||||||
|
ascentCalculationMode: 1
|
||||||
|
useLegacyBoundsCalculation: 0
|
||||||
|
shouldRoundAdvanceValue: 1
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 563e0a689f15a82a692f51982090bbf0
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d38777a8d8b70d68788b4c07547a8aca
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
@ -0,0 +1,21 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b58718e8be5f47e71bf35d8503ed1ff8
|
||||||
|
TrueTypeFontImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 4
|
||||||
|
fontSize: 16
|
||||||
|
forceTextureCase: -2
|
||||||
|
characterSpacing: 0
|
||||||
|
characterPadding: 1
|
||||||
|
includeFontData: 1
|
||||||
|
fontNames:
|
||||||
|
- Roboto
|
||||||
|
fallbackFontReferences: []
|
||||||
|
customCharacters:
|
||||||
|
fontRenderingMode: 0
|
||||||
|
ascentCalculationMode: 1
|
||||||
|
useLegacyBoundsCalculation: 0
|
||||||
|
shouldRoundAdvanceValue: 1
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
2
unity/XR_RM_PICO_UDP_Sender/Assets/Resources/PXR_ProjectSetting.asset
Executable file → Normal file
2
unity/XR_RM_PICO_UDP_Sender/Assets/Resources/PXR_ProjectSetting.asset
Executable file → Normal file
@ -50,6 +50,6 @@ MonoBehaviour:
|
|||||||
recommendMSAA: 0
|
recommendMSAA: 0
|
||||||
validationFFREnabled: 0
|
validationFFREnabled: 0
|
||||||
validationETFREnabled: 0
|
validationETFREnabled: 0
|
||||||
portalInited: 1
|
portalInited: 0
|
||||||
isDataCollectionDisabled: 0
|
isDataCollectionDisabled: 0
|
||||||
portalFirstSelected: 0
|
portalFirstSelected: 0
|
||||||
|
|||||||
@ -168,7 +168,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: e4c7a11d85854eddb40a6a614bfb129c, type: 3}
|
m_Script: {fileID: 11500000, guid: e4c7a11d85854eddb40a6a614bfb129c, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
host: 192.168.9.92
|
host: 192.168.43.7
|
||||||
port: 15000
|
port: 15000
|
||||||
sendHz: 90
|
sendHz: 90
|
||||||
convertUnityToProjectCoordinates: 1
|
convertUnityToProjectCoordinates: 1
|
||||||
|
|||||||
@ -5,6 +5,9 @@ using System.Net.Sockets;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.XR;
|
using UnityEngine.XR;
|
||||||
|
#if !PICO_OPENXR_SDK
|
||||||
|
using Unity.XR.PXR;
|
||||||
|
#endif
|
||||||
|
|
||||||
public class PicoControllerUdpSender : MonoBehaviour
|
public class PicoControllerUdpSender : MonoBehaviour
|
||||||
{
|
{
|
||||||
@ -12,7 +15,12 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
private const string PortPrefsKey = "xr_rm_udp_sender.port";
|
private const string PortPrefsKey = "xr_rm_udp_sender.port";
|
||||||
private const string SendHzPrefsKey = "xr_rm_udp_sender.send_hz";
|
private const string SendHzPrefsKey = "xr_rm_udp_sender.send_hz";
|
||||||
private const string ConvertPrefsKey = "xr_rm_udp_sender.convert_coordinates";
|
private const string ConvertPrefsKey = "xr_rm_udp_sender.convert_coordinates";
|
||||||
private const int MaxPacketsPerFrame = 4;
|
private const string PoseSourceNone = "none";
|
||||||
|
private const string PoseSourceUnityXr = "unity_xr";
|
||||||
|
private const string PoseSourcePxrPredict = "pxr_predict";
|
||||||
|
private const int InvalidTrackingState = -1;
|
||||||
|
private const int UnknownControllerStatus = -1;
|
||||||
|
private const double SendScheduleEpsilonSeconds = 0.0001;
|
||||||
|
|
||||||
[Header("ROS UDP Target")]
|
[Header("ROS UDP Target")]
|
||||||
public string host = "192.168.9.99";
|
public string host = "192.168.9.99";
|
||||||
@ -25,15 +33,24 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
|
|
||||||
private UdpClient client;
|
private UdpClient client;
|
||||||
private IPEndPoint endPoint;
|
private IPEndPoint endPoint;
|
||||||
private float nextSendTime;
|
private double nextSendTime;
|
||||||
private bool sendEnabled;
|
private bool sendEnabled;
|
||||||
private readonly Packet packet = new Packet();
|
private readonly Packet packet = new Packet();
|
||||||
private readonly List<InputDevice> deviceBuffer = new List<InputDevice>();
|
private readonly List<InputDevice> deviceBuffer = new List<InputDevice>();
|
||||||
|
private int nextSeq = 1;
|
||||||
|
|
||||||
public bool SendEnabled => sendEnabled;
|
public bool SendEnabled => sendEnabled;
|
||||||
public bool HasEndpoint => endPoint != null;
|
public bool HasEndpoint => endPoint != null;
|
||||||
public bool LeftDeviceValid { get; private set; }
|
public bool LeftDeviceValid { get; private set; }
|
||||||
public bool RightDeviceValid { get; private set; }
|
public bool RightDeviceValid { get; private set; }
|
||||||
|
public bool LeftPoseValid { get; private set; }
|
||||||
|
public bool RightPoseValid { get; private set; }
|
||||||
|
public string LeftPoseSource { get; private set; } = PoseSourceNone;
|
||||||
|
public string RightPoseSource { get; private set; } = PoseSourceNone;
|
||||||
|
public int LeftTrackingState { get; private set; } = InvalidTrackingState;
|
||||||
|
public int RightTrackingState { get; private set; } = InvalidTrackingState;
|
||||||
|
public int LeftControllerStatus { get; private set; } = UnknownControllerStatus;
|
||||||
|
public int RightControllerStatus { get; private set; } = UnknownControllerStatus;
|
||||||
public bool LeftGripPressed { get; private set; }
|
public bool LeftGripPressed { get; private set; }
|
||||||
public bool RightGripPressed { get; private set; }
|
public bool RightGripPressed { get; private set; }
|
||||||
public string LastError { get; private set; } = string.Empty;
|
public string LastError { get; private set; } = string.Empty;
|
||||||
@ -44,6 +61,8 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
private class Packet
|
private class Packet
|
||||||
{
|
{
|
||||||
public double t;
|
public double t;
|
||||||
|
public double source_time;
|
||||||
|
public int seq;
|
||||||
public string frame_id = "xr_world";
|
public string frame_id = "xr_world";
|
||||||
public Controllers controllers = new Controllers();
|
public Controllers controllers = new Controllers();
|
||||||
}
|
}
|
||||||
@ -62,6 +81,23 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
public float trigger;
|
public float trigger;
|
||||||
public float[] pos = new float[] { 0.0f, 1.0f, 0.0f };
|
public float[] pos = new float[] { 0.0f, 1.0f, 0.0f };
|
||||||
public float[] quat = new float[] { 0.0f, 0.0f, 0.0f, 1.0f };
|
public float[] quat = new float[] { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
public bool pose_valid;
|
||||||
|
public int tracking_state = -1;
|
||||||
|
public int controller_status = -1;
|
||||||
|
public float grip_value;
|
||||||
|
public float[] axis = new float[] { 0.0f, 0.0f };
|
||||||
|
public ButtonsPayload buttons = new ButtonsPayload();
|
||||||
|
public string pose_source = PoseSourceNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
private class ButtonsPayload
|
||||||
|
{
|
||||||
|
public bool grip;
|
||||||
|
public bool primary;
|
||||||
|
public bool secondary;
|
||||||
|
public bool menu;
|
||||||
|
public bool axis_click;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
@ -69,7 +105,7 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
LoadConfig();
|
LoadConfig();
|
||||||
ReopenClient();
|
ReopenClient();
|
||||||
sendEnabled = sendOnStart;
|
sendEnabled = sendOnStart;
|
||||||
nextSendTime = 0.0f;
|
nextSendTime = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDisable()
|
private void OnDisable()
|
||||||
@ -86,7 +122,7 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextSendTime = 0.0f;
|
nextSendTime = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnApplicationFocus(bool hasFocus)
|
private void OnApplicationFocus(bool hasFocus)
|
||||||
@ -97,7 +133,7 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextSendTime = 0.0f;
|
nextSendTime = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
@ -110,21 +146,21 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
FillController(XRNode.LeftHand, packet.controllers.left);
|
FillController(XRNode.LeftHand, packet.controllers.left);
|
||||||
FillController(XRNode.RightHand, packet.controllers.right);
|
FillController(XRNode.RightHand, packet.controllers.right);
|
||||||
|
|
||||||
float now = Time.unscaledTime;
|
double now = Time.realtimeSinceStartupAsDouble;
|
||||||
float interval = 1.0f / Mathf.Max(sendHz, 1.0f);
|
double interval = 1.0 / Math.Max((double)sendHz, 1.0);
|
||||||
if (nextSendTime <= 0.0f || now - nextSendTime > interval * MaxPacketsPerFrame)
|
if (nextSendTime <= 0.0 || now - nextSendTime > interval)
|
||||||
{
|
{
|
||||||
nextSendTime = now;
|
nextSendTime = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sentThisFrame = 0;
|
if (now + SendScheduleEpsilonSeconds < nextSendTime)
|
||||||
while (now >= nextSendTime && sentThisFrame < MaxPacketsPerFrame)
|
|
||||||
{
|
{
|
||||||
packet.t = Time.realtimeSinceStartupAsDouble;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StampPacket();
|
||||||
SendPacket();
|
SendPacket();
|
||||||
nextSendTime += interval;
|
nextSendTime += interval;
|
||||||
sentThisFrame++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ApplyConfig(string newHost, int newPort, float newSendHz, bool newConvertUnityToProjectCoordinates, bool save)
|
public bool ApplyConfig(string newHost, int newPort, float newSendHz, bool newConvertUnityToProjectCoordinates, bool save)
|
||||||
@ -169,7 +205,7 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendEnabled = enabled;
|
sendEnabled = enabled;
|
||||||
nextSendTime = 0.0f;
|
nextSendTime = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadConfig()
|
private void LoadConfig()
|
||||||
@ -228,6 +264,8 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
{
|
{
|
||||||
InputDevice device = GetControllerDevice(node);
|
InputDevice device = GetControllerDevice(node);
|
||||||
bool isLeft = node == XRNode.LeftHand;
|
bool isLeft = node == XRNode.LeftHand;
|
||||||
|
ResetControllerPayload(payload);
|
||||||
|
|
||||||
if (isLeft)
|
if (isLeft)
|
||||||
{
|
{
|
||||||
LeftDeviceValid = device.isValid;
|
LeftDeviceValid = device.isValid;
|
||||||
@ -239,40 +277,111 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
|
|
||||||
if (!device.isValid)
|
if (!device.isValid)
|
||||||
{
|
{
|
||||||
payload.grip = false;
|
|
||||||
payload.trigger = 0.0f;
|
|
||||||
SetGripState(isLeft, false);
|
SetGripState(isLeft, false);
|
||||||
|
SetPoseState(isLeft, false, PoseSourceNone, InvalidTrackingState, UnknownControllerStatus);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 position = Vector3.zero;
|
Vector3 unityPosition = Vector3.zero;
|
||||||
Quaternion rotation = Quaternion.identity;
|
Quaternion unityRotation = Quaternion.identity;
|
||||||
float trigger = 0.0f;
|
float trigger = 0.0f;
|
||||||
float gripValue = 0.0f;
|
float gripValue = 0.0f;
|
||||||
|
Vector2 axis = Vector2.zero;
|
||||||
bool gripButton = false;
|
bool gripButton = false;
|
||||||
|
bool primaryButton = false;
|
||||||
|
bool secondaryButton = false;
|
||||||
|
bool menuButton = false;
|
||||||
|
bool axisClick = false;
|
||||||
|
bool isTracked = true;
|
||||||
|
InputTrackingState trackingState = 0;
|
||||||
|
|
||||||
device.TryGetFeatureValue(CommonUsages.devicePosition, out position);
|
bool hasUnityPosition = device.TryGetFeatureValue(CommonUsages.devicePosition, out unityPosition);
|
||||||
device.TryGetFeatureValue(CommonUsages.deviceRotation, out rotation);
|
bool hasUnityRotation = device.TryGetFeatureValue(CommonUsages.deviceRotation, out unityRotation);
|
||||||
device.TryGetFeatureValue(CommonUsages.trigger, out trigger);
|
device.TryGetFeatureValue(CommonUsages.trigger, out trigger);
|
||||||
device.TryGetFeatureValue(CommonUsages.grip, out gripValue);
|
device.TryGetFeatureValue(CommonUsages.grip, out gripValue);
|
||||||
device.TryGetFeatureValue(CommonUsages.gripButton, out gripButton);
|
device.TryGetFeatureValue(CommonUsages.gripButton, out gripButton);
|
||||||
|
device.TryGetFeatureValue(CommonUsages.primary2DAxis, out axis);
|
||||||
|
device.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out axisClick);
|
||||||
|
device.TryGetFeatureValue(CommonUsages.primaryButton, out primaryButton);
|
||||||
|
device.TryGetFeatureValue(CommonUsages.secondaryButton, out secondaryButton);
|
||||||
|
device.TryGetFeatureValue(CommonUsages.menuButton, out menuButton);
|
||||||
|
|
||||||
payload.grip = gripButton || gripValue > 0.5f;
|
bool hasIsTracked = device.TryGetFeatureValue(CommonUsages.isTracked, out isTracked);
|
||||||
SetGripState(isLeft, payload.grip);
|
bool hasTrackingState = device.TryGetFeatureValue(CommonUsages.trackingState, out trackingState);
|
||||||
payload.trigger = Mathf.Clamp01(trigger);
|
int trackingStateValue = hasTrackingState ? (int)trackingState : InvalidTrackingState;
|
||||||
|
bool trackedOk = !hasIsTracked || isTracked;
|
||||||
|
bool trackingStateOk = !hasTrackingState
|
||||||
|
|| ((trackingState & InputTrackingState.Position) != 0
|
||||||
|
&& (trackingState & InputTrackingState.Rotation) != 0);
|
||||||
|
bool unityPoseValid = hasUnityPosition
|
||||||
|
&& hasUnityRotation
|
||||||
|
&& trackedOk
|
||||||
|
&& trackingStateOk
|
||||||
|
&& IsFinite(unityPosition)
|
||||||
|
&& IsFinite(unityRotation);
|
||||||
|
|
||||||
if (convertUnityToProjectCoordinates)
|
Vector3 posePosition = Vector3.zero;
|
||||||
|
Quaternion poseRotation = Quaternion.identity;
|
||||||
|
string poseSource = PoseSourceNone;
|
||||||
|
int controllerStatus = UnknownControllerStatus;
|
||||||
|
bool poseValid = TryGetPicoPredictedPose(isLeft, out posePosition, out poseRotation, out controllerStatus);
|
||||||
|
if (poseValid)
|
||||||
{
|
{
|
||||||
payload.pos[0] = position.x;
|
poseSource = PoseSourcePxrPredict;
|
||||||
payload.pos[1] = position.y;
|
}
|
||||||
payload.pos[2] = -position.z;
|
else if (unityPoseValid)
|
||||||
|
{
|
||||||
|
posePosition = unityPosition;
|
||||||
|
poseRotation = unityRotation;
|
||||||
|
poseSource = PoseSourceUnityXr;
|
||||||
|
poseValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
payload.quat[0] = -rotation.x;
|
payload.trigger = Mathf.Clamp01(trigger);
|
||||||
payload.quat[1] = -rotation.y;
|
payload.grip_value = Mathf.Clamp01(gripValue);
|
||||||
payload.quat[2] = rotation.z;
|
payload.axis[0] = axis.x;
|
||||||
payload.quat[3] = rotation.w;
|
payload.axis[1] = axis.y;
|
||||||
|
payload.buttons.grip = gripButton;
|
||||||
|
payload.buttons.primary = primaryButton;
|
||||||
|
payload.buttons.secondary = secondaryButton;
|
||||||
|
payload.buttons.menu = menuButton;
|
||||||
|
payload.buttons.axis_click = axisClick;
|
||||||
|
payload.pose_valid = poseValid;
|
||||||
|
payload.pose_source = poseSource;
|
||||||
|
payload.tracking_state = trackingStateValue;
|
||||||
|
payload.controller_status = controllerStatus;
|
||||||
|
payload.grip = poseValid && (gripButton || gripValue > 0.5f);
|
||||||
|
SetGripState(isLeft, payload.grip);
|
||||||
|
SetPoseState(isLeft, poseValid, poseSource, trackingStateValue, controllerStatus);
|
||||||
|
WritePose(payload, posePosition, poseRotation, poseSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WritePose(ControllerPayload payload, Vector3 position, Quaternion rotation, string poseSource)
|
||||||
|
{
|
||||||
|
if (convertUnityToProjectCoordinates && poseSource == PoseSourcePxrPredict)
|
||||||
|
{
|
||||||
|
WritePoseValues(
|
||||||
|
payload,
|
||||||
|
ConvertPicoNativePositionToProject(position),
|
||||||
|
ConvertPicoNativeRotationToProject(rotation));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
WritePoseValues(payload, position, rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector3 ConvertPicoNativePositionToProject(Vector3 position)
|
||||||
|
{
|
||||||
|
return new Vector3(position.z, position.y, -position.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Quaternion ConvertPicoNativeRotationToProject(Quaternion rotation)
|
||||||
|
{
|
||||||
|
return Quaternion.Euler(0.0f, 90.0f, 0.0f) * rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WritePoseValues(ControllerPayload payload, Vector3 position, Quaternion rotation)
|
||||||
{
|
{
|
||||||
payload.pos[0] = position.x;
|
payload.pos[0] = position.x;
|
||||||
payload.pos[1] = position.y;
|
payload.pos[1] = position.y;
|
||||||
@ -283,8 +392,59 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
payload.quat[2] = rotation.z;
|
payload.quat[2] = rotation.z;
|
||||||
payload.quat[3] = rotation.w;
|
payload.quat[3] = rotation.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryGetPicoPredictedPose(
|
||||||
|
bool isLeft,
|
||||||
|
out Vector3 position,
|
||||||
|
out Quaternion rotation,
|
||||||
|
out int controllerStatus)
|
||||||
|
{
|
||||||
|
position = Vector3.zero;
|
||||||
|
rotation = Quaternion.identity;
|
||||||
|
controllerStatus = UnknownControllerStatus;
|
||||||
|
|
||||||
|
#if !PICO_OPENXR_SDK && !UNITY_EDITOR
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PXR_Input.Controller controller = isLeft
|
||||||
|
? PXR_Input.Controller.LeftController
|
||||||
|
: PXR_Input.Controller.RightController;
|
||||||
|
if (!PXR_Input.IsControllerConnected(controller))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PXR_Input.ControllerStatus status = PXR_Input.GetControllerStatus(controller);
|
||||||
|
controllerStatus = (int)status;
|
||||||
|
if (!IsPositionCapablePicoStatus(status))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double predictTime = PXR_System.GetPredictedDisplayTime();
|
||||||
|
position = PXR_Input.GetControllerPredictPosition(controller, predictTime);
|
||||||
|
rotation = PXR_Input.GetControllerPredictRotation(controller, predictTime);
|
||||||
|
return IsFinite(position) && IsFinite(rotation);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
LastError = $"PXR pose failed: {exception.Message}";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !PICO_OPENXR_SDK && !UNITY_EDITOR
|
||||||
|
private static bool IsPositionCapablePicoStatus(PXR_Input.ControllerStatus status)
|
||||||
|
{
|
||||||
|
return status == PXR_Input.ControllerStatus.Static
|
||||||
|
|| status == PXR_Input.ControllerStatus.SixDof
|
||||||
|
|| status == PXR_Input.ControllerStatus.CollidedIn6Dof;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private InputDevice GetControllerDevice(XRNode node)
|
private InputDevice GetControllerDevice(XRNode node)
|
||||||
{
|
{
|
||||||
InputDevice device = InputDevices.GetDeviceAtXRNode(node);
|
InputDevice device = InputDevices.GetDeviceAtXRNode(node);
|
||||||
@ -340,15 +500,106 @@ public class PicoControllerUdpSender : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendSafeStopPacket()
|
private void SetPoseState(
|
||||||
|
bool isLeft,
|
||||||
|
bool poseValid,
|
||||||
|
string poseSource,
|
||||||
|
int trackingState,
|
||||||
|
int controllerStatus)
|
||||||
|
{
|
||||||
|
if (isLeft)
|
||||||
|
{
|
||||||
|
LeftPoseValid = poseValid;
|
||||||
|
LeftPoseSource = poseSource;
|
||||||
|
LeftTrackingState = trackingState;
|
||||||
|
LeftControllerStatus = controllerStatus;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RightPoseValid = poseValid;
|
||||||
|
RightPoseSource = poseSource;
|
||||||
|
RightTrackingState = trackingState;
|
||||||
|
RightControllerStatus = controllerStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ResetControllerPayload(ControllerPayload payload)
|
||||||
|
{
|
||||||
|
if (payload.pos == null || payload.pos.Length != 3)
|
||||||
|
{
|
||||||
|
payload.pos = new float[] { 0.0f, 0.0f, 0.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.quat == null || payload.quat.Length != 4)
|
||||||
|
{
|
||||||
|
payload.quat = new float[] { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.axis == null || payload.axis.Length != 2)
|
||||||
|
{
|
||||||
|
payload.axis = new float[] { 0.0f, 0.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.buttons == null)
|
||||||
|
{
|
||||||
|
payload.buttons = new ButtonsPayload();
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.grip = false;
|
||||||
|
payload.trigger = 0.0f;
|
||||||
|
payload.pos[0] = 0.0f;
|
||||||
|
payload.pos[1] = 0.0f;
|
||||||
|
payload.pos[2] = 0.0f;
|
||||||
|
payload.quat[0] = 0.0f;
|
||||||
|
payload.quat[1] = 0.0f;
|
||||||
|
payload.quat[2] = 0.0f;
|
||||||
|
payload.quat[3] = 1.0f;
|
||||||
|
payload.pose_valid = false;
|
||||||
|
payload.tracking_state = InvalidTrackingState;
|
||||||
|
payload.controller_status = UnknownControllerStatus;
|
||||||
|
payload.grip_value = 0.0f;
|
||||||
|
payload.axis[0] = 0.0f;
|
||||||
|
payload.axis[1] = 0.0f;
|
||||||
|
payload.buttons.grip = false;
|
||||||
|
payload.buttons.primary = false;
|
||||||
|
payload.buttons.secondary = false;
|
||||||
|
payload.buttons.menu = false;
|
||||||
|
payload.buttons.axis_click = false;
|
||||||
|
payload.pose_source = PoseSourceNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StampPacket()
|
||||||
{
|
{
|
||||||
packet.t = Time.realtimeSinceStartupAsDouble;
|
packet.t = Time.realtimeSinceStartupAsDouble;
|
||||||
packet.controllers.left.grip = false;
|
packet.source_time = packet.t;
|
||||||
packet.controllers.left.trigger = 0.0f;
|
packet.seq = nextSeq;
|
||||||
packet.controllers.right.grip = false;
|
nextSeq = nextSeq == int.MaxValue ? 1 : nextSeq + 1;
|
||||||
packet.controllers.right.trigger = 0.0f;
|
}
|
||||||
|
|
||||||
|
private static bool IsFinite(Vector3 value)
|
||||||
|
{
|
||||||
|
return IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsFinite(Quaternion value)
|
||||||
|
{
|
||||||
|
return IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z) && IsFinite(value.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsFinite(float value)
|
||||||
|
{
|
||||||
|
return !float.IsNaN(value) && !float.IsInfinity(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendSafeStopPacket()
|
||||||
|
{
|
||||||
|
StampPacket();
|
||||||
|
ResetControllerPayload(packet.controllers.left);
|
||||||
|
ResetControllerPayload(packet.controllers.right);
|
||||||
LeftGripPressed = false;
|
LeftGripPressed = false;
|
||||||
RightGripPressed = false;
|
RightGripPressed = false;
|
||||||
|
SetPoseState(true, false, PoseSourceNone, InvalidTrackingState, UnknownControllerStatus);
|
||||||
|
SetPoseState(false, false, PoseSourceNone, InvalidTrackingState, UnknownControllerStatus);
|
||||||
SendPacket();
|
SendPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
599
unity/XR_RM_PICO_UDP_Sender/Assets/Scripts/PicoUdpConfigPanel.cs
Executable file → Normal file
599
unity/XR_RM_PICO_UDP_Sender/Assets/Scripts/PicoUdpConfigPanel.cs
Executable file → Normal file
@ -1,5 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityEngine.XR;
|
using UnityEngine.XR;
|
||||||
@ -11,29 +15,55 @@ using Unity.XR.PXR;
|
|||||||
|
|
||||||
public class PicoUdpConfigPanel : MonoBehaviour
|
public class PicoUdpConfigPanel : MonoBehaviour
|
||||||
{
|
{
|
||||||
private const int RowCount = 6;
|
private const int RowCount = 8;
|
||||||
|
private const int MaxSavedIps = 5;
|
||||||
private const float AxisRepeatDelay = 0.22f;
|
private const float AxisRepeatDelay = 0.22f;
|
||||||
|
private const string RecentIpPrefsKey = "xr_rm_udp_sender.ip_recent";
|
||||||
|
private const string FavoriteIpPrefsKey = "xr_rm_udp_sender.ip_favorites";
|
||||||
|
private const string IpListSeparator = "|";
|
||||||
|
private const string RegularFontResourcePath = "Fonts/Roboto-Regular SDF";
|
||||||
|
private const string EmphasisFontResourcePath = "Fonts/Roboto-Bold SDF";
|
||||||
|
|
||||||
|
private const int RowTargetIp = 0;
|
||||||
|
private const int RowSavedIp = 1;
|
||||||
|
private const int RowFavorite = 2;
|
||||||
|
private const int RowTargetPort = 3;
|
||||||
|
private const int RowSendHz = 4;
|
||||||
|
private const int RowCoordinates = 5;
|
||||||
|
private const int RowSending = 6;
|
||||||
|
private const int RowSaveApply = 7;
|
||||||
|
|
||||||
public int targetFrameRate = 90;
|
public int targetFrameRate = 90;
|
||||||
public bool showOnStart = true;
|
public bool showOnStart = true;
|
||||||
public bool togglePanelWithMenuButton = true;
|
public bool togglePanelWithMenuButton = true;
|
||||||
|
|
||||||
private readonly Text[] rowTexts = new Text[RowCount];
|
private readonly ConfigRow[] rows = new ConfigRow[RowCount];
|
||||||
private readonly Color normalColor = new Color(0.86f, 0.91f, 0.96f, 1.0f);
|
private readonly List<string> recentIps = new List<string>();
|
||||||
private readonly Color selectedColor = new Color(0.35f, 0.82f, 1.0f, 1.0f);
|
private readonly List<string> favoriteIps = new List<string>();
|
||||||
private readonly Color mutedColor = new Color(0.58f, 0.66f, 0.74f, 1.0f);
|
private readonly List<string> savedIpChoices = new List<string>();
|
||||||
|
private readonly Color normalColor = new Color(0.92f, 0.96f, 0.98f, 1.0f);
|
||||||
|
private readonly Color selectedColor = new Color(0.32f, 0.86f, 1.0f, 1.0f);
|
||||||
|
private readonly Color mutedColor = new Color(0.64f, 0.72f, 0.78f, 1.0f);
|
||||||
|
private readonly Color cardColor = new Color(0.018f, 0.026f, 0.032f, 0.86f);
|
||||||
|
private readonly Color rowColor = new Color(0.08f, 0.105f, 0.125f, 0.66f);
|
||||||
|
private readonly Color selectedRowColor = new Color(0.05f, 0.20f, 0.28f, 0.92f);
|
||||||
|
|
||||||
private PicoControllerUdpSender sender;
|
private PicoControllerUdpSender sender;
|
||||||
private Canvas canvas;
|
private Canvas canvas;
|
||||||
private GameObject configPanelObject;
|
private GameObject configPanelObject;
|
||||||
private GameObject runHudObject;
|
private GameObject runHudObject;
|
||||||
private Text titleText;
|
private Image hudStatusStripe;
|
||||||
private Text statusText;
|
private TextMeshProUGUI titleText;
|
||||||
private Text footerText;
|
private TextMeshProUGUI statusText;
|
||||||
private Text hudTitleText;
|
private TextMeshProUGUI connectionHeaderText;
|
||||||
private Text hudStatusText;
|
private TextMeshProUGUI runtimeHeaderText;
|
||||||
private Text hudDetailText;
|
private TextMeshProUGUI footerText;
|
||||||
private Text hudHintText;
|
private TextMeshProUGUI hudTitleText;
|
||||||
|
private TextMeshProUGUI hudStatusText;
|
||||||
|
private TextMeshProUGUI hudDetailText;
|
||||||
|
private TextMeshProUGUI hudHintText;
|
||||||
|
private TMP_FontAsset regularFontAsset;
|
||||||
|
private TMP_FontAsset emphasisFontAsset;
|
||||||
private TouchScreenKeyboard keyboard;
|
private TouchScreenKeyboard keyboard;
|
||||||
private KeyboardTarget keyboardTarget;
|
private KeyboardTarget keyboardTarget;
|
||||||
private string hostDraft;
|
private string hostDraft;
|
||||||
@ -42,6 +72,7 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
private bool convertDraft;
|
private bool convertDraft;
|
||||||
private PicoKeepAwake keepAwake;
|
private PicoKeepAwake keepAwake;
|
||||||
private int selectedRow;
|
private int selectedRow;
|
||||||
|
private int selectedSavedIpIndex;
|
||||||
private float nextAxisTime;
|
private float nextAxisTime;
|
||||||
private bool wasActivatePressed;
|
private bool wasActivatePressed;
|
||||||
private bool wasApplyPressed;
|
private bool wasApplyPressed;
|
||||||
@ -56,6 +87,15 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
SendHz
|
SendHz
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ConfigRow
|
||||||
|
{
|
||||||
|
public GameObject root;
|
||||||
|
public Image background;
|
||||||
|
public Image accent;
|
||||||
|
public TextMeshProUGUI labelText;
|
||||||
|
public TextMeshProUGUI valueText;
|
||||||
|
}
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
sender = GetComponent<PicoControllerUdpSender>();
|
sender = GetComponent<PicoControllerUdpSender>();
|
||||||
@ -69,6 +109,8 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
{
|
{
|
||||||
keepAwake = gameObject.AddComponent<PicoKeepAwake>();
|
keepAwake = gameObject.AddComponent<PicoKeepAwake>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadFonts();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
@ -76,6 +118,7 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
ApplyRuntimeDefaults();
|
ApplyRuntimeDefaults();
|
||||||
EnsurePanel();
|
EnsurePanel();
|
||||||
LoadDraftsFromSender();
|
LoadDraftsFromSender();
|
||||||
|
LoadIpLists();
|
||||||
canvas.gameObject.SetActive(true);
|
canvas.gameObject.SetActive(true);
|
||||||
SetConfigPanelVisible(showOnStart, false);
|
SetConfigPanelVisible(showOnStart, false);
|
||||||
RefreshPanel();
|
RefreshPanel();
|
||||||
@ -96,6 +139,7 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
Screen.sleepTimeout = SleepTimeout.NeverSleep;
|
Screen.sleepTimeout = SleepTimeout.NeverSleep;
|
||||||
XRSettings.eyeTextureResolutionScale = 1.0f;
|
XRSettings.eyeTextureResolutionScale = 1.0f;
|
||||||
RequestPicoDisplayRefreshRate();
|
RequestPicoDisplayRefreshRate();
|
||||||
|
RequestPicoPassthrough();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RequestPicoDisplayRefreshRate()
|
private void RequestPicoDisplayRefreshRate()
|
||||||
@ -120,6 +164,24 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RequestPicoPassthrough()
|
||||||
|
{
|
||||||
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if PICO_OPENXR_SDK
|
||||||
|
PassthroughFeature.EnableVideoSeeThrough = true;
|
||||||
|
#else
|
||||||
|
PXR_Manager.EnableVideoSeeThrough = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"XR-RM failed to enable PICO video see-through: {exception.Message}");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private void EnsurePanel()
|
private void EnsurePanel()
|
||||||
{
|
{
|
||||||
Camera panelCamera = Camera.main;
|
Camera panelCamera = Camera.main;
|
||||||
@ -130,8 +192,6 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
panelCamera = cameraObject.AddComponent<Camera>();
|
panelCamera = cameraObject.AddComponent<Camera>();
|
||||||
panelCamera.nearClipPlane = 0.05f;
|
panelCamera.nearClipPlane = 0.05f;
|
||||||
panelCamera.farClipPlane = 100.0f;
|
panelCamera.farClipPlane = 100.0f;
|
||||||
panelCamera.clearFlags = CameraClearFlags.SolidColor;
|
|
||||||
panelCamera.backgroundColor = new Color(0.02f, 0.025f, 0.03f, 1.0f);
|
|
||||||
|
|
||||||
if (FindObjectOfType<AudioListener>() == null)
|
if (FindObjectOfType<AudioListener>() == null)
|
||||||
{
|
{
|
||||||
@ -141,6 +201,9 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
AddTrackedPoseDriverIfAvailable(cameraObject);
|
AddTrackedPoseDriverIfAvailable(cameraObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panelCamera.clearFlags = CameraClearFlags.SolidColor;
|
||||||
|
panelCamera.backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
GameObject canvasObject = new GameObject("XR-RM UDP Config Canvas", typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler));
|
GameObject canvasObject = new GameObject("XR-RM UDP Config Canvas", typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler));
|
||||||
canvasObject.transform.SetParent(panelCamera.transform, false);
|
canvasObject.transform.SetParent(panelCamera.transform, false);
|
||||||
canvasObject.transform.localPosition = new Vector3(0.0f, 0.0f, 2.0f);
|
canvasObject.transform.localPosition = new Vector3(0.0f, 0.0f, 2.0f);
|
||||||
@ -156,75 +219,102 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
canvasRect.sizeDelta = new Vector2(980.0f, 640.0f);
|
canvasRect.sizeDelta = new Vector2(980.0f, 640.0f);
|
||||||
|
|
||||||
CanvasScaler scaler = canvasObject.GetComponent<CanvasScaler>();
|
CanvasScaler scaler = canvasObject.GetComponent<CanvasScaler>();
|
||||||
scaler.dynamicPixelsPerUnit = 12.0f;
|
scaler.dynamicPixelsPerUnit = 18.0f;
|
||||||
scaler.referencePixelsPerUnit = 100.0f;
|
scaler.referencePixelsPerUnit = 100.0f;
|
||||||
|
|
||||||
configPanelObject = new GameObject("Config Panel", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
configPanelObject = new GameObject("Config Panel", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
||||||
configPanelObject.transform.SetParent(canvasObject.transform, false);
|
configPanelObject.transform.SetParent(canvasObject.transform, false);
|
||||||
RectTransform backgroundRect = configPanelObject.GetComponent<RectTransform>();
|
RectTransform backgroundRect = configPanelObject.GetComponent<RectTransform>();
|
||||||
backgroundRect.anchorMin = Vector2.zero;
|
SetRect(backgroundRect, new Vector2(0.08f, 0.08f), new Vector2(0.92f, 0.92f), Vector2.zero, Vector2.zero);
|
||||||
backgroundRect.anchorMax = Vector2.one;
|
|
||||||
backgroundRect.offsetMin = Vector2.zero;
|
|
||||||
backgroundRect.offsetMax = Vector2.zero;
|
|
||||||
Image background = configPanelObject.GetComponent<Image>();
|
Image background = configPanelObject.GetComponent<Image>();
|
||||||
background.color = new Color(0.045f, 0.06f, 0.075f, 0.94f);
|
background.color = cardColor;
|
||||||
|
|
||||||
titleText = CreateText("Title", configPanelObject.transform, 38, FontStyle.Bold, TextAnchor.MiddleLeft);
|
titleText = CreateText("Title", configPanelObject.transform, 40, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||||
SetRect(titleText.rectTransform, new Vector2(0.06f, 0.82f), new Vector2(0.94f, 0.96f), Vector2.zero, Vector2.zero);
|
SetRect(titleText.rectTransform, new Vector2(0.06f, 0.875f), new Vector2(0.94f, 0.965f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
statusText = CreateText("Status", configPanelObject.transform, 22, FontStyle.Normal, TextAnchor.MiddleLeft);
|
statusText = CreateText("Status", configPanelObject.transform, 21, FontStyles.Normal, TextAlignmentOptions.Left);
|
||||||
statusText.color = mutedColor;
|
statusText.color = mutedColor;
|
||||||
SetRect(statusText.rectTransform, new Vector2(0.06f, 0.72f), new Vector2(0.94f, 0.82f), Vector2.zero, Vector2.zero);
|
SetRect(statusText.rectTransform, new Vector2(0.06f, 0.795f), new Vector2(0.94f, 0.872f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
for (int i = 0; i < RowCount; i++)
|
connectionHeaderText = CreateText("Connection Header", configPanelObject.transform, 18, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||||
{
|
connectionHeaderText.color = selectedColor;
|
||||||
Text rowText = CreateText("Row " + i, configPanelObject.transform, 27, FontStyle.Normal, TextAnchor.MiddleLeft);
|
SetRect(connectionHeaderText.rectTransform, new Vector2(0.06f, 0.725f), new Vector2(0.94f, 0.775f), Vector2.zero, Vector2.zero);
|
||||||
float top = 0.68f - i * 0.09f;
|
|
||||||
SetRect(rowText.rectTransform, new Vector2(0.08f, top - 0.075f), new Vector2(0.92f, top), Vector2.zero, Vector2.zero);
|
|
||||||
rowTexts[i] = rowText;
|
|
||||||
}
|
|
||||||
|
|
||||||
footerText = CreateText("Footer", configPanelObject.transform, 23, FontStyle.Normal, TextAnchor.MiddleCenter);
|
CreateConfigRow(RowTargetIp, 0.655f, 0.715f);
|
||||||
footerText.color = normalColor;
|
CreateConfigRow(RowSavedIp, 0.585f, 0.645f);
|
||||||
SetRect(footerText.rectTransform, new Vector2(0.05f, 0.025f), new Vector2(0.95f, 0.15f), Vector2.zero, Vector2.zero);
|
CreateConfigRow(RowFavorite, 0.515f, 0.575f);
|
||||||
|
|
||||||
|
runtimeHeaderText = CreateText("Runtime Header", configPanelObject.transform, 18, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||||
|
runtimeHeaderText.color = selectedColor;
|
||||||
|
SetRect(runtimeHeaderText.rectTransform, new Vector2(0.06f, 0.445f), new Vector2(0.94f, 0.495f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
|
CreateConfigRow(RowTargetPort, 0.375f, 0.435f);
|
||||||
|
CreateConfigRow(RowSendHz, 0.305f, 0.365f);
|
||||||
|
CreateConfigRow(RowCoordinates, 0.235f, 0.295f);
|
||||||
|
CreateConfigRow(RowSending, 0.165f, 0.225f);
|
||||||
|
CreateConfigRow(RowSaveApply, 0.095f, 0.155f);
|
||||||
|
|
||||||
|
footerText = CreateText("Footer", configPanelObject.transform, 19, FontStyles.Normal, TextAlignmentOptions.Center);
|
||||||
|
footerText.color = mutedColor;
|
||||||
|
SetRect(footerText.rectTransform, new Vector2(0.05f, 0.020f), new Vector2(0.95f, 0.075f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
CreateRunHud(canvasObject.transform);
|
CreateRunHud(canvasObject.transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreateConfigRow(int index, float bottom, float top)
|
||||||
|
{
|
||||||
|
GameObject rowObject = new GameObject("Row " + index, typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
||||||
|
rowObject.transform.SetParent(configPanelObject.transform, false);
|
||||||
|
RectTransform rowRect = rowObject.GetComponent<RectTransform>();
|
||||||
|
SetRect(rowRect, new Vector2(0.06f, bottom), new Vector2(0.94f, top), Vector2.zero, Vector2.zero);
|
||||||
|
Image background = rowObject.GetComponent<Image>();
|
||||||
|
background.color = rowColor;
|
||||||
|
|
||||||
|
GameObject accentObject = CreateImage("Accent", rowObject.transform, new Color(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
|
SetRect(accentObject.GetComponent<RectTransform>(), new Vector2(0.0f, 0.0f), new Vector2(0.018f, 1.0f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
|
TextMeshProUGUI labelText = CreateText("Label", rowObject.transform, 20, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||||
|
SetRect(labelText.rectTransform, new Vector2(0.045f, 0.10f), new Vector2(0.38f, 0.90f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
|
TextMeshProUGUI valueText = CreateText("Value", rowObject.transform, 21, FontStyles.Normal, TextAlignmentOptions.Left);
|
||||||
|
SetRect(valueText.rectTransform, new Vector2(0.39f, 0.10f), new Vector2(0.965f, 0.90f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
|
rows[index] = new ConfigRow
|
||||||
|
{
|
||||||
|
root = rowObject,
|
||||||
|
background = background,
|
||||||
|
accent = accentObject.GetComponent<Image>(),
|
||||||
|
labelText = labelText,
|
||||||
|
valueText = valueText,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateRunHud(Transform canvasParent)
|
private void CreateRunHud(Transform canvasParent)
|
||||||
{
|
{
|
||||||
runHudObject = new GameObject("Run HUD", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
runHudObject = new GameObject("Run HUD", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
||||||
runHudObject.transform.SetParent(canvasParent, false);
|
runHudObject.transform.SetParent(canvasParent, false);
|
||||||
RectTransform hudRect = runHudObject.GetComponent<RectTransform>();
|
RectTransform hudRect = runHudObject.GetComponent<RectTransform>();
|
||||||
hudRect.anchorMin = Vector2.zero;
|
SetRect(hudRect, new Vector2(0.035f, 0.055f), new Vector2(0.54f, 0.285f), Vector2.zero, Vector2.zero);
|
||||||
hudRect.anchorMax = Vector2.one;
|
|
||||||
hudRect.offsetMin = Vector2.zero;
|
|
||||||
hudRect.offsetMax = Vector2.zero;
|
|
||||||
Image hudBackground = runHudObject.GetComponent<Image>();
|
Image hudBackground = runHudObject.GetComponent<Image>();
|
||||||
hudBackground.color = new Color(0.018f, 0.026f, 0.032f, 0.88f);
|
hudBackground.color = new Color(0.012f, 0.020f, 0.026f, 0.82f);
|
||||||
|
|
||||||
GameObject headerObject = CreateImage("HUD Header", runHudObject.transform, new Color(0.035f, 0.05f, 0.06f, 0.88f));
|
GameObject stripeObject = CreateImage("HUD Status Stripe", runHudObject.transform, selectedColor);
|
||||||
SetRect(headerObject.GetComponent<RectTransform>(), new Vector2(0.05f, 0.70f), new Vector2(0.95f, 0.92f), Vector2.zero, Vector2.zero);
|
SetRect(stripeObject.GetComponent<RectTransform>(), new Vector2(0.0f, 0.0f), new Vector2(0.018f, 1.0f), Vector2.zero, Vector2.zero);
|
||||||
|
hudStatusStripe = stripeObject.GetComponent<Image>();
|
||||||
|
|
||||||
hudTitleText = CreateText("HUD Title", headerObject.transform, 34, FontStyle.Bold, TextAnchor.MiddleLeft);
|
hudTitleText = CreateText("HUD Title", runHudObject.transform, 24, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||||
SetRect(hudTitleText.rectTransform, new Vector2(0.04f, 0.54f), new Vector2(0.96f, 0.95f), Vector2.zero, Vector2.zero);
|
SetRect(hudTitleText.rectTransform, new Vector2(0.055f, 0.74f), new Vector2(0.95f, 0.96f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
hudStatusText = CreateText("HUD Status", headerObject.transform, 28, FontStyle.Bold, TextAnchor.MiddleLeft);
|
hudStatusText = CreateText("HUD Status", runHudObject.transform, 22, FontStyles.Bold, TextAlignmentOptions.Left);
|
||||||
hudStatusText.color = selectedColor;
|
hudStatusText.color = selectedColor;
|
||||||
SetRect(hudStatusText.rectTransform, new Vector2(0.04f, 0.15f), new Vector2(0.96f, 0.56f), Vector2.zero, Vector2.zero);
|
SetRect(hudStatusText.rectTransform, new Vector2(0.055f, 0.49f), new Vector2(0.95f, 0.75f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
hudDetailText = CreateText("HUD Detail", runHudObject.transform, 25, FontStyle.Normal, TextAnchor.MiddleCenter);
|
hudDetailText = CreateText("HUD Detail", runHudObject.transform, 19, FontStyles.Normal, TextAlignmentOptions.Left);
|
||||||
SetRect(hudDetailText.rectTransform, new Vector2(0.07f, 0.36f), new Vector2(0.93f, 0.64f), Vector2.zero, Vector2.zero);
|
SetRect(hudDetailText.rectTransform, new Vector2(0.055f, 0.16f), new Vector2(0.95f, 0.50f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
hudHintText = CreateText("HUD Hint", runHudObject.transform, 23, FontStyle.Normal, TextAnchor.MiddleCenter);
|
hudHintText = CreateText("HUD Hint", runHudObject.transform, 17, FontStyles.Normal, TextAlignmentOptions.Left);
|
||||||
hudHintText.color = mutedColor;
|
hudHintText.color = mutedColor;
|
||||||
SetRect(hudHintText.rectTransform, new Vector2(0.07f, 0.08f), new Vector2(0.93f, 0.20f), Vector2.zero, Vector2.zero);
|
SetRect(hudHintText.rectTransform, new Vector2(0.055f, 0.02f), new Vector2(0.95f, 0.16f), Vector2.zero, Vector2.zero);
|
||||||
|
|
||||||
GameObject verticalLine = CreateImage("HUD Vertical Reticle", runHudObject.transform, new Color(0.35f, 0.82f, 1.0f, 0.38f));
|
|
||||||
SetRect(verticalLine.GetComponent<RectTransform>(), new Vector2(0.498f, 0.27f), new Vector2(0.502f, 0.36f), Vector2.zero, Vector2.zero);
|
|
||||||
|
|
||||||
GameObject horizontalLine = CreateImage("HUD Horizontal Reticle", runHudObject.transform, new Color(0.35f, 0.82f, 1.0f, 0.38f));
|
|
||||||
SetRect(horizontalLine.GetComponent<RectTransform>(), new Vector2(0.47f, 0.313f), new Vector2(0.53f, 0.319f), Vector2.zero, Vector2.zero);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddTrackedPoseDriverIfAvailable(GameObject cameraObject)
|
private static void AddTrackedPoseDriverIfAvailable(GameObject cameraObject)
|
||||||
@ -246,25 +336,62 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Text CreateText(string name, Transform parent, int fontSize, FontStyle fontStyle, TextAnchor alignment)
|
private void LoadFonts()
|
||||||
{
|
{
|
||||||
GameObject textObject = new GameObject(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(Text));
|
regularFontAsset = Resources.Load<TMP_FontAsset>(RegularFontResourcePath);
|
||||||
|
emphasisFontAsset = Resources.Load<TMP_FontAsset>(EmphasisFontResourcePath);
|
||||||
|
|
||||||
|
if (regularFontAsset == null)
|
||||||
|
{
|
||||||
|
regularFontAsset = TMP_Settings.GetFontAsset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emphasisFontAsset == null)
|
||||||
|
{
|
||||||
|
emphasisFontAsset = regularFontAsset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regularFontAsset == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("XR-RM failed to load Roboto TMP font assets. Rebuild with XR-RM/Rebuild Roboto TMP Font Assets.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextMeshProUGUI CreateText(string name, Transform parent, int fontSize, FontStyles fontStyle, TextAlignmentOptions alignment)
|
||||||
|
{
|
||||||
|
GameObject textObject = new GameObject(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI));
|
||||||
textObject.transform.SetParent(parent, false);
|
textObject.transform.SetParent(parent, false);
|
||||||
|
|
||||||
Text text = textObject.GetComponent<Text>();
|
TextMeshProUGUI text = textObject.GetComponent<TextMeshProUGUI>();
|
||||||
text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
|
TMP_FontAsset fontAsset = GetFontAssetForStyle(fontStyle);
|
||||||
|
if (fontAsset != null)
|
||||||
|
{
|
||||||
|
text.font = fontAsset;
|
||||||
|
}
|
||||||
|
|
||||||
text.fontSize = fontSize;
|
text.fontSize = fontSize;
|
||||||
text.fontStyle = fontStyle;
|
text.fontStyle = fontStyle;
|
||||||
text.alignment = alignment;
|
text.alignment = alignment;
|
||||||
text.horizontalOverflow = HorizontalWrapMode.Wrap;
|
text.enableAutoSizing = true;
|
||||||
text.verticalOverflow = VerticalWrapMode.Truncate;
|
text.fontSizeMin = Mathf.Max(13, fontSize - 6);
|
||||||
text.resizeTextForBestFit = true;
|
text.fontSizeMax = fontSize;
|
||||||
text.resizeTextMinSize = Mathf.Max(12, fontSize - 8);
|
text.enableWordWrapping = false;
|
||||||
text.resizeTextMaxSize = fontSize;
|
text.overflowMode = TextOverflowModes.Ellipsis;
|
||||||
|
text.raycastTarget = false;
|
||||||
text.color = normalColor;
|
text.color = normalColor;
|
||||||
|
|
||||||
|
Shadow shadow = textObject.AddComponent<Shadow>();
|
||||||
|
shadow.effectColor = new Color(0.0f, 0.0f, 0.0f, 0.78f);
|
||||||
|
shadow.effectDistance = new Vector2(1.4f, -1.4f);
|
||||||
|
shadow.useGraphicAlpha = true;
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TMP_FontAsset GetFontAssetForStyle(FontStyles fontStyle)
|
||||||
|
{
|
||||||
|
return fontStyle == FontStyles.Bold && emphasisFontAsset != null ? emphasisFontAsset : regularFontAsset;
|
||||||
|
}
|
||||||
|
|
||||||
private static void SetRect(RectTransform rectTransform, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax)
|
private static void SetRect(RectTransform rectTransform, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax)
|
||||||
{
|
{
|
||||||
rectTransform.anchorMin = anchorMin;
|
rectTransform.anchorMin = anchorMin;
|
||||||
@ -290,6 +417,61 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
convertDraft = sender.convertUnityToProjectCoordinates;
|
convertDraft = sender.convertUnityToProjectCoordinates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadIpLists()
|
||||||
|
{
|
||||||
|
LoadIpList(RecentIpPrefsKey, recentIps);
|
||||||
|
LoadIpList(FavoriteIpPrefsKey, favoriteIps);
|
||||||
|
RefreshSavedIpChoices(hostDraft);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadIpList(string prefsKey, List<string> target)
|
||||||
|
{
|
||||||
|
target.Clear();
|
||||||
|
string raw = PlayerPrefs.GetString(prefsKey, string.Empty);
|
||||||
|
if (string.IsNullOrEmpty(raw))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] values = raw.Split(new[] { IpListSeparator }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
for (int i = 0; i < values.Length && target.Count < MaxSavedIps; i++)
|
||||||
|
{
|
||||||
|
AddUniqueIp(target, values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveIpLists()
|
||||||
|
{
|
||||||
|
PlayerPrefs.SetString(RecentIpPrefsKey, string.Join(IpListSeparator, recentIps.ToArray()));
|
||||||
|
PlayerPrefs.SetString(FavoriteIpPrefsKey, string.Join(IpListSeparator, favoriteIps.ToArray()));
|
||||||
|
PlayerPrefs.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshSavedIpChoices(string preferredIp)
|
||||||
|
{
|
||||||
|
savedIpChoices.Clear();
|
||||||
|
for (int i = 0; i < favoriteIps.Count; i++)
|
||||||
|
{
|
||||||
|
AddUniqueIp(savedIpChoices, favoriteIps[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < recentIps.Count; i++)
|
||||||
|
{
|
||||||
|
AddUniqueIp(savedIpChoices, recentIps[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (savedIpChoices.Count == 0 && IsValidIpv4(hostDraft))
|
||||||
|
{
|
||||||
|
savedIpChoices.Add(hostDraft);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedSavedIpIndex = Mathf.Clamp(FindIpIndex(savedIpChoices, preferredIp), 0, Mathf.Max(0, savedIpChoices.Count - 1));
|
||||||
|
if (selectedSavedIpIndex < 0)
|
||||||
|
{
|
||||||
|
selectedSavedIpIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleKeyboard()
|
private void HandleKeyboard()
|
||||||
{
|
{
|
||||||
if (keyboard == null)
|
if (keyboard == null)
|
||||||
@ -317,6 +499,7 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
if (keyboardTarget == KeyboardTarget.Host)
|
if (keyboardTarget == KeyboardTarget.Host)
|
||||||
{
|
{
|
||||||
hostDraft = trimmed;
|
hostDraft = trimmed;
|
||||||
|
RefreshSavedIpChoices(hostDraft);
|
||||||
panelMessage = "Target IP edited";
|
panelMessage = "Target IP edited";
|
||||||
}
|
}
|
||||||
else if (keyboardTarget == KeyboardTarget.Port)
|
else if (keyboardTarget == KeyboardTarget.Port)
|
||||||
@ -403,22 +586,30 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
|
|
||||||
private void AdjustSelectedValue(int direction)
|
private void AdjustSelectedValue(int direction)
|
||||||
{
|
{
|
||||||
if (selectedRow == 1)
|
if (selectedRow == RowSavedIp)
|
||||||
|
{
|
||||||
|
SelectSavedIp(direction);
|
||||||
|
}
|
||||||
|
else if (selectedRow == RowFavorite)
|
||||||
|
{
|
||||||
|
ToggleFavoriteIp();
|
||||||
|
}
|
||||||
|
else if (selectedRow == RowTargetPort)
|
||||||
{
|
{
|
||||||
portDraft = Mathf.Clamp(portDraft + direction, 1, 65535);
|
portDraft = Mathf.Clamp(portDraft + direction, 1, 65535);
|
||||||
panelMessage = "Target port adjusted";
|
panelMessage = "Target port adjusted";
|
||||||
}
|
}
|
||||||
else if (selectedRow == 2)
|
else if (selectedRow == RowSendHz)
|
||||||
{
|
{
|
||||||
sendHzDraft = Mathf.Clamp(sendHzDraft + direction * 5.0f, 1.0f, 120.0f);
|
sendHzDraft = Mathf.Clamp(sendHzDraft + direction * 5.0f, 1.0f, 120.0f);
|
||||||
panelMessage = "Send rate adjusted";
|
panelMessage = "Send rate adjusted";
|
||||||
}
|
}
|
||||||
else if (selectedRow == 3)
|
else if (selectedRow == RowCoordinates)
|
||||||
{
|
{
|
||||||
convertDraft = !convertDraft;
|
convertDraft = !convertDraft;
|
||||||
panelMessage = "Coordinate mode toggled";
|
panelMessage = "Coordinate mode toggled";
|
||||||
}
|
}
|
||||||
else if (selectedRow == 4)
|
else if (selectedRow == RowSending)
|
||||||
{
|
{
|
||||||
ToggleSending();
|
ToggleSending();
|
||||||
}
|
}
|
||||||
@ -426,33 +617,91 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
|
|
||||||
private void ActivateSelectedRow()
|
private void ActivateSelectedRow()
|
||||||
{
|
{
|
||||||
if (selectedRow == 0)
|
if (selectedRow == RowTargetIp)
|
||||||
{
|
{
|
||||||
OpenKeyboard(KeyboardTarget.Host, hostDraft, TouchScreenKeyboardType.URL);
|
OpenKeyboard(KeyboardTarget.Host, hostDraft, TouchScreenKeyboardType.URL);
|
||||||
}
|
}
|
||||||
else if (selectedRow == 1)
|
else if (selectedRow == RowSavedIp)
|
||||||
{
|
{
|
||||||
OpenKeyboard(KeyboardTarget.Port, portDraft.ToString(), TouchScreenKeyboardType.NumberPad);
|
ApplySelectedSavedIp();
|
||||||
}
|
}
|
||||||
else if (selectedRow == 2)
|
else if (selectedRow == RowFavorite)
|
||||||
{
|
{
|
||||||
OpenKeyboard(KeyboardTarget.SendHz, Mathf.RoundToInt(sendHzDraft).ToString(), TouchScreenKeyboardType.NumberPad);
|
ToggleFavoriteIp();
|
||||||
}
|
}
|
||||||
else if (selectedRow == 3)
|
else if (selectedRow == RowTargetPort)
|
||||||
|
{
|
||||||
|
OpenKeyboard(KeyboardTarget.Port, portDraft.ToString(CultureInfo.InvariantCulture), TouchScreenKeyboardType.NumberPad);
|
||||||
|
}
|
||||||
|
else if (selectedRow == RowSendHz)
|
||||||
|
{
|
||||||
|
OpenKeyboard(KeyboardTarget.SendHz, Mathf.RoundToInt(sendHzDraft).ToString(CultureInfo.InvariantCulture), TouchScreenKeyboardType.NumberPad);
|
||||||
|
}
|
||||||
|
else if (selectedRow == RowCoordinates)
|
||||||
{
|
{
|
||||||
convertDraft = !convertDraft;
|
convertDraft = !convertDraft;
|
||||||
panelMessage = "Coordinate mode toggled";
|
panelMessage = "Coordinate mode toggled";
|
||||||
}
|
}
|
||||||
else if (selectedRow == 4)
|
else if (selectedRow == RowSending)
|
||||||
{
|
{
|
||||||
ToggleSending();
|
ToggleSending();
|
||||||
}
|
}
|
||||||
else if (selectedRow == 5)
|
else if (selectedRow == RowSaveApply)
|
||||||
{
|
{
|
||||||
ApplyDrafts();
|
ApplyDrafts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SelectSavedIp(int direction)
|
||||||
|
{
|
||||||
|
if (savedIpChoices.Count == 0)
|
||||||
|
{
|
||||||
|
panelMessage = "No saved IPs";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedSavedIpIndex = (selectedSavedIpIndex + direction + savedIpChoices.Count) % savedIpChoices.Count;
|
||||||
|
panelMessage = "Saved IP selected";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplySelectedSavedIp()
|
||||||
|
{
|
||||||
|
if (savedIpChoices.Count == 0)
|
||||||
|
{
|
||||||
|
panelMessage = "No saved IPs";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedSavedIpIndex = Mathf.Clamp(selectedSavedIpIndex, 0, savedIpChoices.Count - 1);
|
||||||
|
hostDraft = savedIpChoices[selectedSavedIpIndex];
|
||||||
|
panelMessage = "Saved IP applied";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleFavoriteIp()
|
||||||
|
{
|
||||||
|
if (!IsValidIpv4(hostDraft))
|
||||||
|
{
|
||||||
|
panelMessage = "Invalid IP for favorite";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = FindIpIndex(favoriteIps, hostDraft);
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
favoriteIps.RemoveAt(index);
|
||||||
|
panelMessage = "Favorite removed";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InsertIpAtFront(favoriteIps, hostDraft);
|
||||||
|
TrimIpList(favoriteIps);
|
||||||
|
panelMessage = "Favorite saved";
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveIpLists();
|
||||||
|
RefreshSavedIpChoices(hostDraft);
|
||||||
|
}
|
||||||
|
|
||||||
private void OpenKeyboard(KeyboardTarget target, string text, TouchScreenKeyboardType keyboardType)
|
private void OpenKeyboard(KeyboardTarget target, string text, TouchScreenKeyboardType keyboardType)
|
||||||
{
|
{
|
||||||
keyboardTarget = target;
|
keyboardTarget = target;
|
||||||
@ -469,7 +718,83 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
private void ApplyDrafts()
|
private void ApplyDrafts()
|
||||||
{
|
{
|
||||||
bool applied = sender.ApplyConfig(hostDraft, portDraft, sendHzDraft, convertDraft, true);
|
bool applied = sender.ApplyConfig(hostDraft, portDraft, sendHzDraft, convertDraft, true);
|
||||||
panelMessage = applied ? "Saved and applied" : sender.LastError;
|
if (!applied)
|
||||||
|
{
|
||||||
|
panelMessage = sender.LastError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordRecentIp(hostDraft);
|
||||||
|
SaveIpLists();
|
||||||
|
RefreshSavedIpChoices(hostDraft);
|
||||||
|
panelMessage = "Saved and applied";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecordRecentIp(string ip)
|
||||||
|
{
|
||||||
|
if (!IsValidIpv4(ip))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InsertIpAtFront(recentIps, ip);
|
||||||
|
TrimIpList(recentIps);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InsertIpAtFront(List<string> values, string ip)
|
||||||
|
{
|
||||||
|
int existingIndex = FindIpIndex(values, ip);
|
||||||
|
if (existingIndex >= 0)
|
||||||
|
{
|
||||||
|
values.RemoveAt(existingIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
values.Insert(0, ip.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AddUniqueIp(List<string> values, string ip)
|
||||||
|
{
|
||||||
|
string trimmed = ip == null ? string.Empty : ip.Trim();
|
||||||
|
if (!IsValidIpv4(trimmed) || FindIpIndex(values, trimmed) >= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
values.Add(trimmed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TrimIpList(List<string> values)
|
||||||
|
{
|
||||||
|
while (values.Count > MaxSavedIps)
|
||||||
|
{
|
||||||
|
values.RemoveAt(values.Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int FindIpIndex(List<string> values, string ip)
|
||||||
|
{
|
||||||
|
string trimmed = ip == null ? string.Empty : ip.Trim();
|
||||||
|
for (int i = 0; i < values.Count; i++)
|
||||||
|
{
|
||||||
|
if (string.Equals(values[i], trimmed, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidIpv4(string value)
|
||||||
|
{
|
||||||
|
string trimmed = value == null ? string.Empty : value.Trim();
|
||||||
|
return IPAddress.TryParse(trimmed, out IPAddress address) && address.AddressFamily == AddressFamily.InterNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsCurrentHostFavorite()
|
||||||
|
{
|
||||||
|
return FindIpIndex(favoriteIps, hostDraft) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsActivatePressed()
|
private bool IsActivatePressed()
|
||||||
@ -479,12 +804,19 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
|
|
||||||
private static Vector2 ReadPrimaryAxis()
|
private static Vector2 ReadPrimaryAxis()
|
||||||
{
|
{
|
||||||
if (TryReadPrimaryAxis(XRNode.RightHand, out Vector2 rightAxis))
|
bool hasRightAxis = TryReadPrimaryAxis(XRNode.RightHand, out Vector2 rightAxis);
|
||||||
|
bool hasLeftAxis = TryReadPrimaryAxis(XRNode.LeftHand, out Vector2 leftAxis);
|
||||||
|
if (hasRightAxis && hasLeftAxis)
|
||||||
|
{
|
||||||
|
return rightAxis.sqrMagnitude >= leftAxis.sqrMagnitude ? rightAxis : leftAxis;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasRightAxis)
|
||||||
{
|
{
|
||||||
return rightAxis;
|
return rightAxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryReadPrimaryAxis(XRNode.LeftHand, out Vector2 leftAxis))
|
if (hasLeftAxis)
|
||||||
{
|
{
|
||||||
return leftAxis;
|
return leftAxis;
|
||||||
}
|
}
|
||||||
@ -552,15 +884,19 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
{
|
{
|
||||||
titleText.text = "XR-RM PICO UDP Sender";
|
titleText.text = "XR-RM PICO UDP Sender";
|
||||||
statusText.text = BuildConfigStatusText();
|
statusText.text = BuildConfigStatusText();
|
||||||
|
connectionHeaderText.text = "Connection";
|
||||||
|
runtimeHeaderText.text = "Runtime";
|
||||||
|
|
||||||
SetRow(0, "Target IP", hostDraft);
|
SetRow(RowTargetIp, "Target IP", hostDraft);
|
||||||
SetRow(1, "Target Port", portDraft.ToString());
|
SetRow(RowSavedIp, "Saved IP", BuildSavedIpText());
|
||||||
SetRow(2, "Send Rate", Mathf.RoundToInt(sendHzDraft) + " Hz");
|
SetRow(RowFavorite, "Favorite", IsCurrentHostFavorite() ? "ON" : "OFF");
|
||||||
SetRow(3, "Coordinates", convertDraft ? "Project (+Z forward)" : "Unity raw");
|
SetRow(RowTargetPort, "Target Port", portDraft.ToString(CultureInfo.InvariantCulture));
|
||||||
SetRow(4, "UDP Sending", sender.SendEnabled ? "ON" : "OFF");
|
SetRow(RowSendHz, "Send Rate", Mathf.RoundToInt(sendHzDraft).ToString(CultureInfo.InvariantCulture) + " Hz");
|
||||||
SetRow(5, "Save & Apply", "press trigger");
|
SetRow(RowCoordinates, "Coordinates", convertDraft ? "Project (+Z back)" : "Source raw");
|
||||||
|
SetRow(RowSending, "UDP Sending", sender.SendEnabled ? "ON" : "OFF");
|
||||||
|
SetRow(RowSaveApply, "Save & Apply", "press trigger");
|
||||||
|
|
||||||
footerText.text = "Stick: select / adjust Trigger, A or X: edit\nB or Y: save Menu: run view";
|
footerText.text = "Stick: select / adjust Trigger, A or X: edit/apply B or Y: save Menu: run view";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshRunHud()
|
private void RefreshRunHud()
|
||||||
@ -570,11 +906,13 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hudTitleText.text = "XR-RM UDP Sender";
|
Color stateColor = sender.SendEnabled ? new Color(0.28f, 0.92f, 0.62f, 1.0f) : new Color(1.0f, 0.68f, 0.30f, 1.0f);
|
||||||
|
hudStatusStripe.color = stateColor;
|
||||||
|
hudTitleText.text = "XR-RM UDP";
|
||||||
|
hudStatusText.color = stateColor;
|
||||||
hudStatusText.text = (sender.SendEnabled ? "SENDING" : "PAUSED") + " " + BuildEndpointText();
|
hudStatusText.text = (sender.SendEnabled ? "SENDING" : "PAUSED") + " " + BuildEndpointText();
|
||||||
hudDetailText.text = BuildTrackingStateText() + " " + BuildGripStateText() + "\n"
|
hudDetailText.text = BuildCompactTrackingStateText() + "\n" + BuildPacketStateText(false);
|
||||||
+ BuildPacketStateText(false) + " " + BuildKeepAwakeStateText();
|
hudHintText.text = "Menu: config";
|
||||||
hudHintText.text = "Menu: config panel";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildConfigStatusText()
|
private string BuildConfigStatusText()
|
||||||
@ -593,14 +931,70 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
return sender.HasEndpoint ? sender.host + ":" + sender.port : "not configured";
|
return sender.HasEndpoint ? sender.host + ":" + sender.port : "not configured";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildTrackingStateText()
|
private string BuildSavedIpText()
|
||||||
{
|
{
|
||||||
return "L " + (sender.LeftDeviceValid ? "ok" : "--") + " / R " + (sender.RightDeviceValid ? "ok" : "--");
|
if (savedIpChoices.Count == 0)
|
||||||
|
{
|
||||||
|
return "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildGripStateText()
|
selectedSavedIpIndex = Mathf.Clamp(selectedSavedIpIndex, 0, savedIpChoices.Count - 1);
|
||||||
|
string ip = savedIpChoices[selectedSavedIpIndex];
|
||||||
|
string marker = FindIpIndex(favoriteIps, ip) >= 0 ? "favorite" : "recent";
|
||||||
|
return ip + " " + marker + " " + (selectedSavedIpIndex + 1).ToString(CultureInfo.InvariantCulture) + "/" + savedIpChoices.Count.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildTrackingStateText()
|
||||||
{
|
{
|
||||||
return "Grip L " + (sender.LeftGripPressed ? "ON" : "--") + " / R " + (sender.RightGripPressed ? "ON" : "--");
|
return "L " + BuildPoseSummary(true) + " / R " + BuildPoseSummary(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildCompactTrackingStateText()
|
||||||
|
{
|
||||||
|
return "L " + BuildCompactPoseSummary(true) + " / R " + BuildCompactPoseSummary(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildCompactPoseSummary(bool left)
|
||||||
|
{
|
||||||
|
bool deviceValid = left ? sender.LeftDeviceValid : sender.RightDeviceValid;
|
||||||
|
if (!deviceValid)
|
||||||
|
{
|
||||||
|
return "--";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool poseValid = left ? sender.LeftPoseValid : sender.RightPoseValid;
|
||||||
|
string source = ShortPoseSource(left ? sender.LeftPoseSource : sender.RightPoseSource);
|
||||||
|
return (poseValid ? "valid" : "invalid") + " " + source;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildPoseSummary(bool left)
|
||||||
|
{
|
||||||
|
bool deviceValid = left ? sender.LeftDeviceValid : sender.RightDeviceValid;
|
||||||
|
if (!deviceValid)
|
||||||
|
{
|
||||||
|
return "--";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool poseValid = left ? sender.LeftPoseValid : sender.RightPoseValid;
|
||||||
|
string source = ShortPoseSource(left ? sender.LeftPoseSource : sender.RightPoseSource);
|
||||||
|
int status = left ? sender.LeftControllerStatus : sender.RightControllerStatus;
|
||||||
|
int tracking = left ? sender.LeftTrackingState : sender.RightTrackingState;
|
||||||
|
return (poseValid ? "valid" : "invalid") + " " + source + " s" + status + " t" + tracking;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ShortPoseSource(string source)
|
||||||
|
{
|
||||||
|
if (source == "pxr_predict")
|
||||||
|
{
|
||||||
|
return "pxr";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source == "unity_xr")
|
||||||
|
{
|
||||||
|
return "unity";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildPacketStateText(bool compact)
|
private string BuildPacketStateText(bool compact)
|
||||||
@ -628,11 +1022,20 @@ public class PicoUdpConfigPanel : MonoBehaviour
|
|||||||
|
|
||||||
private void SetRow(int index, string label, string value)
|
private void SetRow(int index, string label, string value)
|
||||||
{
|
{
|
||||||
Text rowText = rowTexts[index];
|
ConfigRow row = rows[index];
|
||||||
bool selected = index == selectedRow;
|
bool selected = index == selectedRow;
|
||||||
rowText.color = selected ? selectedColor : normalColor;
|
row.background.color = selected ? selectedRowColor : rowColor;
|
||||||
rowText.fontStyle = selected ? FontStyle.Bold : FontStyle.Normal;
|
row.accent.color = selected ? selectedColor : new Color(0.18f, 0.25f, 0.30f, 0.70f);
|
||||||
rowText.text = (selected ? "> " : " ") + label.PadRight(14) + value;
|
row.labelText.text = label;
|
||||||
|
row.valueText.text = value;
|
||||||
|
row.labelText.color = selected ? selectedColor : mutedColor;
|
||||||
|
row.valueText.color = normalColor;
|
||||||
|
row.valueText.fontStyle = selected ? FontStyles.Bold : FontStyles.Normal;
|
||||||
|
TMP_FontAsset valueFontAsset = GetFontAssetForStyle(row.valueText.fontStyle);
|
||||||
|
if (valueFontAsset != null)
|
||||||
|
{
|
||||||
|
row.valueText.font = valueFontAsset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryParseFloat(string value, out float parsedValue)
|
private static bool TryParseFloat(string value, out float parsedValue)
|
||||||
|
|||||||
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro.meta
Executable file
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f54d1bd14bd3ca042bd867b519fee8cc
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Fonts.meta
Executable file
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Fonts.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6ab70aee4d56447429c680537fbf93ed
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
Digitized data copyright (c) 2010 Google Corporation
|
||||||
|
with Reserved Font Arimo, Tinos and Cousine.
|
||||||
|
Copyright (c) 2012 Red Hat, Inc.
|
||||||
|
with Reserved Font Name Liberation.
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6e59c59b81ab47f9b6ec5781fa725d2c
|
||||||
|
timeCreated: 1484171296
|
||||||
|
licenseType: Pro
|
||||||
|
TextScriptImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Fonts/LiberationSans.ttf
Executable file
BIN
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Fonts/LiberationSans.ttf
Executable file
Binary file not shown.
@ -0,0 +1,19 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e3265ab4bf004d28a9537516768c1c75
|
||||||
|
timeCreated: 1484171297
|
||||||
|
licenseType: Pro
|
||||||
|
TrueTypeFontImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
fontSize: 16
|
||||||
|
forceTextureCase: -2
|
||||||
|
characterSpacing: 1
|
||||||
|
characterPadding: 0
|
||||||
|
includeFontData: 1
|
||||||
|
use2xBehaviour: 0
|
||||||
|
fontNames: []
|
||||||
|
fallbackFontReferences: []
|
||||||
|
customCharacters:
|
||||||
|
fontRenderingMode: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Resources.meta
Executable file
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Resources.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 243e06394e614e5d99fab26083b707fa
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 731f1baa9d144a9897cb1d341c2092b8
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1442040525
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!21 &2100000
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: LiberationSans SDF - Drop Shadow
|
||||||
|
m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3}
|
||||||
|
m_ShaderKeywords: OUTLINE_ON UNDERLAY_ON
|
||||||
|
m_LightmapFlags: 5
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _BumpMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _Cube:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _FaceTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee,
|
||||||
|
type: 2}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OutlineTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Floats:
|
||||||
|
- _Ambient: 0.5
|
||||||
|
- _Bevel: 0.5
|
||||||
|
- _BevelClamp: 0
|
||||||
|
- _BevelOffset: 0
|
||||||
|
- _BevelRoundness: 0
|
||||||
|
- _BevelWidth: 0
|
||||||
|
- _BumpFace: 0
|
||||||
|
- _BumpOutline: 0
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _Diffuse: 0.5
|
||||||
|
- _DiffusePower: 1
|
||||||
|
- _FaceDilate: 0.1
|
||||||
|
- _FaceUVSpeedX: 0
|
||||||
|
- _FaceUVSpeedY: 0
|
||||||
|
- _GlowInner: 0.05
|
||||||
|
- _GlowOffset: 0
|
||||||
|
- _GlowOuter: 0.05
|
||||||
|
- _GlowPower: 0.75
|
||||||
|
- _GradientScale: 10
|
||||||
|
- _LightAngle: 3.1416
|
||||||
|
- _MaskSoftnessX: 0
|
||||||
|
- _MaskSoftnessY: 0
|
||||||
|
- _OutlineSoftness: 0
|
||||||
|
- _OutlineUVSpeedX: 0
|
||||||
|
- _OutlineUVSpeedY: 0
|
||||||
|
- _OutlineWidth: 0.1
|
||||||
|
- _PerspectiveFilter: 0.875
|
||||||
|
- _Reflectivity: 10
|
||||||
|
- _ScaleRatioA: 0.9
|
||||||
|
- _ScaleRatioB: 0.73125
|
||||||
|
- _ScaleRatioC: 0.64125
|
||||||
|
- _ScaleX: 1
|
||||||
|
- _ScaleY: 1
|
||||||
|
- _ShaderFlags: 0
|
||||||
|
- _Sharpness: 0
|
||||||
|
- _SpecularPower: 2
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _TextureHeight: 1024
|
||||||
|
- _TextureWidth: 1024
|
||||||
|
- _UnderlayDilate: 0
|
||||||
|
- _UnderlayOffsetX: 0.5
|
||||||
|
- _UnderlayOffsetY: -0.5
|
||||||
|
- _UnderlaySoftness: 0.05
|
||||||
|
- _VertexOffsetX: 0
|
||||||
|
- _VertexOffsetY: 0
|
||||||
|
- _WeightBold: 0.75
|
||||||
|
- _WeightNormal: 0
|
||||||
|
m_Colors:
|
||||||
|
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||||
|
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _GlowColor: {r: 0, g: 1, b: 0, a: 0.5}
|
||||||
|
- _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767}
|
||||||
|
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _SpecularColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e73a58f6e2794ae7b1b7e50b7fb811b0
|
||||||
|
timeCreated: 1484172806
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,343 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!21 &2180264
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: LiberationSans SDF Material
|
||||||
|
m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3}
|
||||||
|
m_ShaderKeywords:
|
||||||
|
m_LightmapFlags: 1
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _BumpMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _Cube:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailAlbedoMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailMask:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailNormalMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _EmissionMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _FaceTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 28268798066460806}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MetallicGlossMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OcclusionMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OutlineTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _ParallaxMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Floats:
|
||||||
|
- _Ambient: 0.5
|
||||||
|
- _Bevel: 0.5
|
||||||
|
- _BevelClamp: 0
|
||||||
|
- _BevelOffset: 0
|
||||||
|
- _BevelRoundness: 0
|
||||||
|
- _BevelWidth: 0
|
||||||
|
- _BumpFace: 0
|
||||||
|
- _BumpOutline: 0
|
||||||
|
- _BumpScale: 1
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _CullMode: 0
|
||||||
|
- _Cutoff: 0.5
|
||||||
|
- _DetailNormalMapScale: 1
|
||||||
|
- _Diffuse: 0.5
|
||||||
|
- _DstBlend: 0
|
||||||
|
- _FaceDilate: 0
|
||||||
|
- _FaceUVSpeedX: 0
|
||||||
|
- _FaceUVSpeedY: 0
|
||||||
|
- _GlossMapScale: 1
|
||||||
|
- _Glossiness: 0.5
|
||||||
|
- _GlossyReflections: 1
|
||||||
|
- _GlowInner: 0.05
|
||||||
|
- _GlowOffset: 0
|
||||||
|
- _GlowOuter: 0.05
|
||||||
|
- _GlowPower: 0.75
|
||||||
|
- _GradientScale: 10
|
||||||
|
- _LightAngle: 3.1416
|
||||||
|
- _MaskSoftnessX: 0
|
||||||
|
- _MaskSoftnessY: 0
|
||||||
|
- _Metallic: 0
|
||||||
|
- _Mode: 0
|
||||||
|
- _OcclusionStrength: 1
|
||||||
|
- _OutlineSoftness: 0
|
||||||
|
- _OutlineUVSpeedX: 0
|
||||||
|
- _OutlineUVSpeedY: 0
|
||||||
|
- _OutlineWidth: 0
|
||||||
|
- _Parallax: 0.02
|
||||||
|
- _PerspectiveFilter: 0.875
|
||||||
|
- _Reflectivity: 10
|
||||||
|
- _ScaleRatioA: 0.90909094
|
||||||
|
- _ScaleRatioB: 0.73125
|
||||||
|
- _ScaleRatioC: 0.7386364
|
||||||
|
- _ScaleX: 1
|
||||||
|
- _ScaleY: 1
|
||||||
|
- _ShaderFlags: 0
|
||||||
|
- _Sharpness: 0
|
||||||
|
- _SmoothnessTextureChannel: 0
|
||||||
|
- _SpecularHighlights: 1
|
||||||
|
- _SpecularPower: 2
|
||||||
|
- _SrcBlend: 1
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _TextureHeight: 512
|
||||||
|
- _TextureWidth: 512
|
||||||
|
- _UVSec: 0
|
||||||
|
- _UnderlayDilate: 0
|
||||||
|
- _UnderlayOffsetX: 0
|
||||||
|
- _UnderlayOffsetY: 0
|
||||||
|
- _UnderlaySoftness: 0
|
||||||
|
- _VertexOffsetX: 0
|
||||||
|
- _VertexOffsetY: 0
|
||||||
|
- _WeightBold: 0.75
|
||||||
|
- _WeightNormal: 0
|
||||||
|
- _ZWrite: 1
|
||||||
|
m_Colors:
|
||||||
|
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||||
|
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _GlowColor: {r: 0, g: 1, b: 0, a: 0.5}
|
||||||
|
- _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767}
|
||||||
|
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _SpecularColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 71c1514a6bd24e1e882cebbe1904ce04, type: 3}
|
||||||
|
m_Name: LiberationSans SDF - Fallback
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
hashCode: -1699145518
|
||||||
|
material: {fileID: 2180264}
|
||||||
|
materialHashCode: 462855346
|
||||||
|
m_Version: 1.1.0
|
||||||
|
m_SourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75
|
||||||
|
m_SourceFontFile_EditorRef: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75,
|
||||||
|
type: 3}
|
||||||
|
m_SourceFontFile: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3}
|
||||||
|
m_AtlasPopulationMode: 1
|
||||||
|
m_FaceInfo:
|
||||||
|
m_FamilyName: Liberation Sans
|
||||||
|
m_StyleName: Regular
|
||||||
|
m_PointSize: 86
|
||||||
|
m_Scale: 1
|
||||||
|
m_LineHeight: 98.8916
|
||||||
|
m_AscentLine: 77.853516
|
||||||
|
m_CapLine: 59
|
||||||
|
m_MeanLine: 45
|
||||||
|
m_Baseline: 0
|
||||||
|
m_DescentLine: -18.22461
|
||||||
|
m_SuperscriptOffset: 77.853516
|
||||||
|
m_SuperscriptSize: 0.5
|
||||||
|
m_SubscriptOffset: -18.22461
|
||||||
|
m_SubscriptSize: 0.5
|
||||||
|
m_UnderlineOffset: -12.261719
|
||||||
|
m_UnderlineThickness: 6.298828
|
||||||
|
m_StrikethroughOffset: 18
|
||||||
|
m_StrikethroughThickness: 6.298828
|
||||||
|
m_TabWidth: 24
|
||||||
|
m_GlyphTable: []
|
||||||
|
m_CharacterTable: []
|
||||||
|
m_AtlasTextures:
|
||||||
|
- {fileID: 28268798066460806}
|
||||||
|
m_AtlasTextureIndex: 0
|
||||||
|
m_IsMultiAtlasTexturesEnabled: 0
|
||||||
|
m_ClearDynamicDataOnBuild: 1
|
||||||
|
m_UsedGlyphRects: []
|
||||||
|
m_FreeGlyphRects:
|
||||||
|
- m_X: 0
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 511
|
||||||
|
m_Height: 511
|
||||||
|
m_fontInfo:
|
||||||
|
Name: Liberation Sans
|
||||||
|
PointSize: 86
|
||||||
|
Scale: 1
|
||||||
|
CharacterCount: 250
|
||||||
|
LineHeight: 98.90625
|
||||||
|
Baseline: 0
|
||||||
|
Ascender: 77.84375
|
||||||
|
CapHeight: 59.1875
|
||||||
|
Descender: -18.21875
|
||||||
|
CenterLine: 0
|
||||||
|
SuperscriptOffset: 77.84375
|
||||||
|
SubscriptOffset: -12.261719
|
||||||
|
SubSize: 0.5
|
||||||
|
Underline: -12.261719
|
||||||
|
UnderlineThickness: 6.298828
|
||||||
|
strikethrough: 23.675
|
||||||
|
strikethroughThickness: 0
|
||||||
|
TabWidth: 239.0625
|
||||||
|
Padding: 9
|
||||||
|
AtlasWidth: 1024
|
||||||
|
AtlasHeight: 1024
|
||||||
|
atlas: {fileID: 0}
|
||||||
|
m_AtlasWidth: 512
|
||||||
|
m_AtlasHeight: 512
|
||||||
|
m_AtlasPadding: 9
|
||||||
|
m_AtlasRenderMode: 4169
|
||||||
|
m_glyphInfoList: []
|
||||||
|
m_KerningTable:
|
||||||
|
kerningPairs: []
|
||||||
|
m_FontFeatureTable:
|
||||||
|
m_GlyphPairAdjustmentRecords: []
|
||||||
|
fallbackFontAssets: []
|
||||||
|
m_FallbackFontAssetTable: []
|
||||||
|
m_CreationSettings:
|
||||||
|
sourceFontFileName:
|
||||||
|
sourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75
|
||||||
|
pointSizeSamplingMode: 0
|
||||||
|
pointSize: 86
|
||||||
|
padding: 9
|
||||||
|
packingMode: 4
|
||||||
|
atlasWidth: 512
|
||||||
|
atlasHeight: 512
|
||||||
|
characterSetSelectionMode: 1
|
||||||
|
characterSequence: 32 - 126, 160 - 255, 8192 - 8303, 8364, 8482, 9633
|
||||||
|
referencedFontAssetGUID: 8f586378b4e144a9851e7b34d9b748ee
|
||||||
|
referencedTextAssetGUID:
|
||||||
|
fontStyle: 0
|
||||||
|
fontStyleModifier: 0
|
||||||
|
renderMode: 4169
|
||||||
|
includeFontFeatures: 1
|
||||||
|
m_FontWeightTable:
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
fontWeights:
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
- regularTypeface: {fileID: 0}
|
||||||
|
italicTypeface: {fileID: 0}
|
||||||
|
normalStyle: 0
|
||||||
|
normalSpacingOffset: 0
|
||||||
|
boldStyle: 0.75
|
||||||
|
boldSpacing: 7
|
||||||
|
italicStyle: 35
|
||||||
|
tabSize: 10
|
||||||
|
--- !u!28 &28268798066460806
|
||||||
|
Texture2D:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: LiberationSans SDF Atlas
|
||||||
|
m_ImageContentsHash:
|
||||||
|
serializedVersion: 2
|
||||||
|
Hash: 00000000000000000000000000000000
|
||||||
|
m_ForcedFallbackFormat: 4
|
||||||
|
m_DownscaleFallback: 0
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Width: 0
|
||||||
|
m_Height: 0
|
||||||
|
m_CompleteImageSize: 0
|
||||||
|
m_TextureFormat: 1
|
||||||
|
m_MipCount: 1
|
||||||
|
m_IsReadable: 1
|
||||||
|
m_StreamingMipmaps: 0
|
||||||
|
m_StreamingMipmapsPriority: 0
|
||||||
|
m_AlphaIsTransparency: 0
|
||||||
|
m_ImageCount: 1
|
||||||
|
m_TextureDimension: 2
|
||||||
|
m_TextureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_FilterMode: 1
|
||||||
|
m_Aniso: 1
|
||||||
|
m_MipBias: 0
|
||||||
|
m_WrapU: 0
|
||||||
|
m_WrapV: 0
|
||||||
|
m_WrapW: 0
|
||||||
|
m_LightmapFormat: 0
|
||||||
|
m_ColorSpace: 0
|
||||||
|
image data: 0
|
||||||
|
_typelessdata:
|
||||||
|
m_StreamData:
|
||||||
|
offset: 0
|
||||||
|
size: 0
|
||||||
|
path:
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2e498d1c8094910479dc3e1b768306a4
|
||||||
|
timeCreated: 1484171803
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!21 &2100000
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: LiberationSans SDF - Outline
|
||||||
|
m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3}
|
||||||
|
m_ShaderKeywords: OUTLINE_ON
|
||||||
|
m_LightmapFlags: 5
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _BumpMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _Cube:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _FaceTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee,
|
||||||
|
type: 2}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OutlineTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Floats:
|
||||||
|
- _Ambient: 0.5
|
||||||
|
- _Bevel: 0.5
|
||||||
|
- _BevelClamp: 0
|
||||||
|
- _BevelOffset: 0
|
||||||
|
- _BevelRoundness: 0
|
||||||
|
- _BevelWidth: 0
|
||||||
|
- _BumpFace: 0
|
||||||
|
- _BumpOutline: 0
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _Diffuse: 0.5
|
||||||
|
- _FaceDilate: 0.1
|
||||||
|
- _FaceUVSpeedX: 0
|
||||||
|
- _FaceUVSpeedY: 0
|
||||||
|
- _GlowInner: 0.05
|
||||||
|
- _GlowOffset: 0
|
||||||
|
- _GlowOuter: 0.05
|
||||||
|
- _GlowPower: 0.75
|
||||||
|
- _GradientScale: 10
|
||||||
|
- _LightAngle: 3.1416
|
||||||
|
- _MaskSoftnessX: 0
|
||||||
|
- _MaskSoftnessY: 0
|
||||||
|
- _OutlineSoftness: 0
|
||||||
|
- _OutlineUVSpeedX: 0
|
||||||
|
- _OutlineUVSpeedY: 0
|
||||||
|
- _OutlineWidth: 0.1
|
||||||
|
- _PerspectiveFilter: 0.875
|
||||||
|
- _Reflectivity: 10
|
||||||
|
- _ScaleRatioA: 0.9
|
||||||
|
- _ScaleRatioB: 0.73125
|
||||||
|
- _ScaleRatioC: 0.64125
|
||||||
|
- _ScaleX: 1
|
||||||
|
- _ScaleY: 1
|
||||||
|
- _ShaderFlags: 0
|
||||||
|
- _Sharpness: 0
|
||||||
|
- _SpecularPower: 2
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _TextureHeight: 1024
|
||||||
|
- _TextureWidth: 1024
|
||||||
|
- _UnderlayDilate: 0
|
||||||
|
- _UnderlayOffsetX: 0
|
||||||
|
- _UnderlayOffsetY: 0
|
||||||
|
- _UnderlaySoftness: 0
|
||||||
|
- _VertexOffsetX: 0
|
||||||
|
- _VertexOffsetY: 0
|
||||||
|
- _WeightBold: 0.75
|
||||||
|
- _WeightNormal: 0
|
||||||
|
m_Colors:
|
||||||
|
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||||
|
- _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0}
|
||||||
|
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _GlowColor: {r: 0, g: 1, b: 0, a: 0.5}
|
||||||
|
- _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767}
|
||||||
|
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _SpecularColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 79459efec17a4d00a321bdcc27bbc385
|
||||||
|
timeCreated: 1484172856
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8f586378b4e144a9851e7b34d9b748ee
|
||||||
|
timeCreated: 1484171803
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1 @@
|
|||||||
|
)]}〕〉》」』】〙〗〟’”⦆»ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻‐゠–〜?!‼⁇⁈⁉・、%,.:;。!?]):;=}¢°"†‡℃〆%,.
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fade42e8bc714b018fac513c043d323b
|
||||||
|
timeCreated: 1425440388
|
||||||
|
licenseType: Store
|
||||||
|
TextScriptImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1 @@
|
|||||||
|
([{〔〈《「『【〘〖〝‘“⦅«$—…‥〳〴〵\[({£¥"々〇$¥₩ #
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d82c1b31c7e74239bff1220585707d2b
|
||||||
|
timeCreated: 1425440388
|
||||||
|
licenseType: Store
|
||||||
|
TextScriptImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 512a49d95c0c4332bdd98131869c23c9
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1441876896
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,659 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!21 &2103686
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: TextMeshPro/Sprite
|
||||||
|
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||||
|
m_ShaderKeywords: UNITY_UI_CLIP_RECT
|
||||||
|
m_LightmapFlags: 5
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 2800000, guid: dffef66376be4fa480fb02b19edbe903, type: 3}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
m_Floats:
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _CullMode: 0
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _UseUIAlphaClip: 0
|
||||||
|
m_Colors:
|
||||||
|
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||||
|
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3}
|
||||||
|
m_Name: EmojiOne
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
hashCode: -1836805472
|
||||||
|
material: {fileID: 2103686}
|
||||||
|
materialHashCode: 0
|
||||||
|
m_Version: 1.1.0
|
||||||
|
m_FaceInfo:
|
||||||
|
m_FamilyName:
|
||||||
|
m_StyleName:
|
||||||
|
m_PointSize: 0
|
||||||
|
m_Scale: 0
|
||||||
|
m_LineHeight: 0
|
||||||
|
m_AscentLine: 0
|
||||||
|
m_CapLine: 0
|
||||||
|
m_MeanLine: 0
|
||||||
|
m_Baseline: 0
|
||||||
|
m_DescentLine: 0
|
||||||
|
m_SuperscriptOffset: 0
|
||||||
|
m_SuperscriptSize: 0
|
||||||
|
m_SubscriptOffset: 0
|
||||||
|
m_SubscriptSize: 0
|
||||||
|
m_UnderlineOffset: 0
|
||||||
|
m_UnderlineThickness: 0
|
||||||
|
m_StrikethroughOffset: 0
|
||||||
|
m_StrikethroughThickness: 0
|
||||||
|
m_TabWidth: 0
|
||||||
|
spriteSheet: {fileID: 2800000, guid: dffef66376be4fa480fb02b19edbe903, type: 3}
|
||||||
|
m_SpriteCharacterTable:
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128522
|
||||||
|
m_GlyphIndex: 0
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: Smiling face with smiling eyes
|
||||||
|
m_HashCode: -1318250903
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128523
|
||||||
|
m_GlyphIndex: 1
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f60b
|
||||||
|
m_HashCode: 57188339
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128525
|
||||||
|
m_GlyphIndex: 2
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f60d
|
||||||
|
m_HashCode: 57188341
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128526
|
||||||
|
m_GlyphIndex: 3
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f60e
|
||||||
|
m_HashCode: 57188340
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128512
|
||||||
|
m_GlyphIndex: 4
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: Grinning face
|
||||||
|
m_HashCode: -95541379
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128513
|
||||||
|
m_GlyphIndex: 5
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f601
|
||||||
|
m_HashCode: 57188256
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128514
|
||||||
|
m_GlyphIndex: 6
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: Face with tears of joy
|
||||||
|
m_HashCode: 239522663
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128515
|
||||||
|
m_GlyphIndex: 7
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f603
|
||||||
|
m_HashCode: 57188258
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128516
|
||||||
|
m_GlyphIndex: 8
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f604
|
||||||
|
m_HashCode: 57188261
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128517
|
||||||
|
m_GlyphIndex: 9
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f605
|
||||||
|
m_HashCode: 57188260
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128518
|
||||||
|
m_GlyphIndex: 10
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f606
|
||||||
|
m_HashCode: 57188263
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 128521
|
||||||
|
m_GlyphIndex: 11
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f609
|
||||||
|
m_HashCode: 57188264
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 0
|
||||||
|
m_GlyphIndex: 12
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: .notdef
|
||||||
|
m_HashCode: -600915428
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 129315
|
||||||
|
m_GlyphIndex: 13
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 1f923
|
||||||
|
m_HashCode: 57200239
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 9786
|
||||||
|
m_GlyphIndex: 14
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 263a
|
||||||
|
m_HashCode: 1748406
|
||||||
|
- m_ElementType: 2
|
||||||
|
m_Unicode: 9785
|
||||||
|
m_GlyphIndex: 15
|
||||||
|
m_Scale: 1
|
||||||
|
m_Name: 2639
|
||||||
|
m_HashCode: 1748462
|
||||||
|
m_SpriteGlyphTable:
|
||||||
|
- m_Index: 0
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 0
|
||||||
|
m_Y: 384
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 1
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 128
|
||||||
|
m_Y: 384
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 2
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 256
|
||||||
|
m_Y: 384
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 3
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 384
|
||||||
|
m_Y: 384
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 4
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 0
|
||||||
|
m_Y: 256
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 5
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 128
|
||||||
|
m_Y: 256
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 6
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 256
|
||||||
|
m_Y: 256
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 7
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 384
|
||||||
|
m_Y: 256
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 8
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 0
|
||||||
|
m_Y: 128
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 9
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 128
|
||||||
|
m_Y: 128
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 10
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 256
|
||||||
|
m_Y: 128
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 11
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 384
|
||||||
|
m_Y: 128
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 12
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 0
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 13
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 128
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 14
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 256
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- m_Index: 15
|
||||||
|
m_Metrics:
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_HorizontalBearingX: 0
|
||||||
|
m_HorizontalBearingY: 115.6
|
||||||
|
m_HorizontalAdvance: 128
|
||||||
|
m_GlyphRect:
|
||||||
|
m_X: 384
|
||||||
|
m_Y: 0
|
||||||
|
m_Width: 128
|
||||||
|
m_Height: 128
|
||||||
|
m_Scale: 1
|
||||||
|
m_AtlasIndex: 0
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
spriteInfoList:
|
||||||
|
- id: 0
|
||||||
|
x: 0
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: Smiling face with smiling eyes
|
||||||
|
hashCode: -1318250903
|
||||||
|
unicode: 128522
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 1
|
||||||
|
x: 128
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f60b
|
||||||
|
hashCode: 57188339
|
||||||
|
unicode: 128523
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 2
|
||||||
|
x: 256
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f60d
|
||||||
|
hashCode: 57188341
|
||||||
|
unicode: 128525
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 3
|
||||||
|
x: 384
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f60e
|
||||||
|
hashCode: 57188340
|
||||||
|
unicode: 128526
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 4
|
||||||
|
x: 0
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: Grinning face
|
||||||
|
hashCode: -95541379
|
||||||
|
unicode: 128512
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 5
|
||||||
|
x: 128
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f601
|
||||||
|
hashCode: 57188256
|
||||||
|
unicode: 128513
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 6
|
||||||
|
x: 256
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: Face with tears of joy
|
||||||
|
hashCode: 239522663
|
||||||
|
unicode: 128514
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 7
|
||||||
|
x: 384
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f603
|
||||||
|
hashCode: 57188258
|
||||||
|
unicode: 128515
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 8
|
||||||
|
x: 0
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f604
|
||||||
|
hashCode: 57188261
|
||||||
|
unicode: 128516
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 9
|
||||||
|
x: 128
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f605
|
||||||
|
hashCode: 57188260
|
||||||
|
unicode: 128517
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 10
|
||||||
|
x: 256
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f606
|
||||||
|
hashCode: 57188263
|
||||||
|
unicode: 128518
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 11
|
||||||
|
x: 384
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f609
|
||||||
|
hashCode: 57188264
|
||||||
|
unicode: 128521
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 12
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f618
|
||||||
|
hashCode: 57188168
|
||||||
|
unicode: 128536
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 13
|
||||||
|
x: 128
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 1f923
|
||||||
|
hashCode: 57200239
|
||||||
|
unicode: 129315
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 14
|
||||||
|
x: 256
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 263a
|
||||||
|
hashCode: 1748406
|
||||||
|
unicode: 9786
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
- id: 15
|
||||||
|
x: 384
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
xOffset: 0
|
||||||
|
yOffset: 115.6
|
||||||
|
xAdvance: 128
|
||||||
|
scale: 1
|
||||||
|
name: 2639
|
||||||
|
hashCode: 1748462
|
||||||
|
unicode: 9785
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
sprite: {fileID: 0}
|
||||||
|
fallbackSpriteAssets: []
|
||||||
|
--- !u!21 &1369835458
|
||||||
|
Material:
|
||||||
|
serializedVersion: 6
|
||||||
|
m_ObjectHideFlags: 1
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_Name: TextMeshPro/Sprite
|
||||||
|
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||||
|
m_ShaderKeywords:
|
||||||
|
m_LightmapFlags: 5
|
||||||
|
m_EnableInstancingVariants: 0
|
||||||
|
m_DoubleSidedGI: 0
|
||||||
|
m_CustomRenderQueue: -1
|
||||||
|
stringTagMap: {}
|
||||||
|
disabledShaderPasses: []
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs: []
|
||||||
|
m_Floats: []
|
||||||
|
m_Colors: []
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c41005c129ba4d66911b75229fd70b45
|
||||||
|
timeCreated: 1480316912
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4aecb92fff08436c8303b10eab8da368
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1441876950
|
||||||
|
licenseType: Pro
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: ab2114bdc8544297b417dfefe9f1e410, type: 3}
|
||||||
|
m_Name: Default Style Sheet
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_StyleList:
|
||||||
|
- m_Name: H1
|
||||||
|
m_HashCode: 2425
|
||||||
|
m_OpeningDefinition: <size=2em><b><#40ff80>*
|
||||||
|
m_ClosingDefinition: '*</size></b></color>'
|
||||||
|
m_OpeningTagArray: 3c00000073000000690000007a000000650000003d00000032000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000660000006600000038000000300000003e0000002a000000
|
||||||
|
m_ClosingTagArray: 2a0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000
|
||||||
|
- m_Name: Quote
|
||||||
|
m_HashCode: 92254330
|
||||||
|
m_OpeningDefinition: <i><size=75%><margin=10%>
|
||||||
|
m_ClosingDefinition: </i></size></width></margin>
|
||||||
|
m_OpeningTagArray: 3c000000690000003e0000003c00000073000000690000007a000000650000003d0000003700000035000000250000003e0000003c0000006d000000610000007200000067000000690000006e0000003d0000003100000030000000250000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000690000003e0000003c0000002f00000073000000690000007a000000650000003e0000003c0000002f00000077000000690000006400000074000000680000003e0000003c0000002f0000006d000000610000007200000067000000690000006e0000003e000000
|
||||||
|
- m_Name: Link
|
||||||
|
m_HashCode: 2687968
|
||||||
|
m_OpeningDefinition: <u><#40a0ff><link="ID_01">
|
||||||
|
m_ClosingDefinition: </u></color></link>
|
||||||
|
m_OpeningTagArray: 3c000000750000003e0000003c000000230000003400000030000000610000003000000066000000660000003e0000003c0000006c000000690000006e0000006b0000003d0000002200000049000000440000005f0000003000000031000000220000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000750000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f0000006c000000690000006e0000006b0000003e000000
|
||||||
|
- m_Name: Title
|
||||||
|
m_HashCode: 98732960
|
||||||
|
m_OpeningDefinition: <size=125%><b><align=center>
|
||||||
|
m_ClosingDefinition: </size></b></align>
|
||||||
|
m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e0000003c000000620000003e0000003c000000610000006c00000069000000670000006e0000003d00000063000000650000006e0000007400000065000000720000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000610000006c00000069000000670000006e0000003e000000
|
||||||
|
- m_Name: H2
|
||||||
|
m_HashCode: 2426
|
||||||
|
m_OpeningDefinition: <size=1.5em><b><#4080FF>
|
||||||
|
m_ClosingDefinition: </size></b></color>
|
||||||
|
m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000002e00000035000000650000006d0000003e0000003c000000620000003e0000003c000000230000003400000030000000380000003000000046000000460000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000
|
||||||
|
- m_Name: H3
|
||||||
|
m_HashCode: 2427
|
||||||
|
m_OpeningDefinition: <size=1.17em><b><#FF8040>
|
||||||
|
m_ClosingDefinition: </size></b></color>
|
||||||
|
m_OpeningTagArray: 3c00000073000000690000007a000000650000003d000000310000002e0000003100000037000000650000006d0000003e0000003c000000620000003e0000003c000000230000004600000046000000380000003000000034000000300000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f00000073000000690000007a000000650000003e0000003c0000002f000000620000003e0000003c0000002f000000630000006f0000006c0000006f000000720000003e000000
|
||||||
|
- m_Name: C1
|
||||||
|
m_HashCode: 2194
|
||||||
|
m_OpeningDefinition: <color=#ffff40>
|
||||||
|
m_ClosingDefinition: </color>
|
||||||
|
m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000006600000066000000660000006600000034000000300000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e000000
|
||||||
|
- m_Name: C2
|
||||||
|
m_HashCode: 2193
|
||||||
|
m_OpeningDefinition: <color=#ff40FF><size=125%>
|
||||||
|
m_ClosingDefinition: </color></size>
|
||||||
|
m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000006600000066000000340000003000000046000000460000003e0000003c00000073000000690000007a000000650000003d000000310000003200000035000000250000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f00000073000000690000007a000000650000003e000000
|
||||||
|
- m_Name: C3
|
||||||
|
m_HashCode: 2192
|
||||||
|
m_OpeningDefinition: <color=#80A0FF><b>
|
||||||
|
m_ClosingDefinition: </color></b>
|
||||||
|
m_OpeningTagArray: 3c000000630000006f0000006c0000006f000000720000003d000000230000003800000030000000410000003000000046000000460000003e0000003c000000620000003e000000
|
||||||
|
m_ClosingTagArray: 3c0000002f000000630000006f0000006c0000006f000000720000003e0000003c0000002f000000620000003e000000
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f952c082cb03451daed3ee968ac6c63e
|
||||||
|
timeCreated: 1432805430
|
||||||
|
licenseType: Store
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 2705215ac5b84b70bacc50632be6e391, type: 3}
|
||||||
|
m_Name: TMP Settings
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_enableWordWrapping: 0
|
||||||
|
m_enableKerning: 1
|
||||||
|
m_enableExtraPadding: 0
|
||||||
|
m_enableTintAllSprites: 0
|
||||||
|
m_enableParseEscapeCharacters: 1
|
||||||
|
m_EnableRaycastTarget: 0
|
||||||
|
m_GetFontFeaturesAtRuntime: 1
|
||||||
|
m_missingGlyphCharacter: 0
|
||||||
|
m_warningsDisabled: 0
|
||||||
|
m_defaultFontAsset: {fileID: 11400000, guid: d38777a8d8b70d68788b4c07547a8aca, type: 2}
|
||||||
|
m_defaultFontAssetPath: Fonts/
|
||||||
|
m_defaultFontSize: 36
|
||||||
|
m_defaultAutoSizeMinRatio: 0.5
|
||||||
|
m_defaultAutoSizeMaxRatio: 1
|
||||||
|
m_defaultTextMeshProTextContainerSize: {x: 20, y: 5}
|
||||||
|
m_defaultTextMeshProUITextContainerSize: {x: 200, y: 50}
|
||||||
|
m_autoSizeTextContainer: 0
|
||||||
|
m_IsTextObjectScaleStatic: 0
|
||||||
|
m_fallbackFontAssets:
|
||||||
|
- {fileID: 11400000, guid: 9605d99cce67df46ea0e78c679b423e9, type: 2}
|
||||||
|
m_matchMaterialPreset: 1
|
||||||
|
m_defaultSpriteAsset: {fileID: 11400000, guid: c41005c129ba4d66911b75229fd70b45, type: 2}
|
||||||
|
m_defaultSpriteAssetPath: Sprite Assets/
|
||||||
|
m_enableEmojiSupport: 1
|
||||||
|
m_MissingCharacterSpriteUnicode: 0
|
||||||
|
m_defaultColorGradientPresetsPath: Color Gradient Presets/
|
||||||
|
m_defaultStyleSheet: {fileID: 11400000, guid: f952c082cb03451daed3ee968ac6c63e, type: 2}
|
||||||
|
m_StyleSheetsResourcePath:
|
||||||
|
m_leadingCharacters: {fileID: 4900000, guid: d82c1b31c7e74239bff1220585707d2b, type: 3}
|
||||||
|
m_followingCharacters: {fileID: 4900000, guid: fade42e8bc714b018fac513c043d323b, type: 3}
|
||||||
|
m_UseModernHangulLineBreakingRules: 0
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3f5b5dff67a942289a9defa416b206f3
|
||||||
|
timeCreated: 1436653997
|
||||||
|
licenseType: Pro
|
||||||
|
NativeFormatImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders.meta
Executable file
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e9f693669af91aa45ad615fc681ed29f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,143 @@
|
|||||||
|
Shader "TextMeshPro/Bitmap Custom Atlas" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_FaceTex ("Font Texture", 2D) = "white" {}
|
||||||
|
[HDR]_FaceColor ("Text Color", Color) = (1,1,1,1)
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_Padding ("Padding", float) = 0
|
||||||
|
|
||||||
|
_StencilComp("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil("Stencil ID", Float) = 0
|
||||||
|
_StencilOp("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode("Cull Mode", Float) = 0
|
||||||
|
_ColorMask("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader{
|
||||||
|
|
||||||
|
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref[_Stencil]
|
||||||
|
Comp[_StencilComp]
|
||||||
|
Pass[_StencilOp]
|
||||||
|
ReadMask[_StencilReadMask]
|
||||||
|
WriteMask[_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Lighting Off
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
ZWrite Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
ColorMask[_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
|
struct appdata_t {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct v2f {
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
float4 mask : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform sampler2D _MainTex;
|
||||||
|
uniform sampler2D _FaceTex;
|
||||||
|
uniform float4 _FaceTex_ST;
|
||||||
|
uniform fixed4 _FaceColor;
|
||||||
|
|
||||||
|
uniform float _VertexOffsetX;
|
||||||
|
uniform float _VertexOffsetY;
|
||||||
|
uniform float4 _ClipRect;
|
||||||
|
uniform float _MaskSoftnessX;
|
||||||
|
uniform float _MaskSoftnessY;
|
||||||
|
|
||||||
|
float2 UnpackUV(float uv)
|
||||||
|
{
|
||||||
|
float2 output;
|
||||||
|
output.x = floor(uv / 4096);
|
||||||
|
output.y = uv - 4096 * output.x;
|
||||||
|
|
||||||
|
return output * 0.001953125;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2f vert (appdata_t v)
|
||||||
|
{
|
||||||
|
float4 vert = v.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
vert.xy += (vert.w * 0.5) / _ScreenParams.xy;
|
||||||
|
|
||||||
|
float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert));
|
||||||
|
|
||||||
|
fixed4 faceColor = v.color;
|
||||||
|
faceColor *= _FaceColor;
|
||||||
|
|
||||||
|
v2f OUT;
|
||||||
|
OUT.vertex = vPosition;
|
||||||
|
OUT.color = faceColor;
|
||||||
|
OUT.texcoord0 = v.texcoord0;
|
||||||
|
OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex);
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1]));
|
||||||
|
|
||||||
|
// Clamp _ClipRect to 16bit.
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed4 frag (v2f IN) : SV_Target
|
||||||
|
{
|
||||||
|
fixed4 color = tex2D(_MainTex, IN.texcoord0) * tex2D(_FaceTex, IN.texcoord1) * IN.color;
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
|
||||||
|
color *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(color.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 48bb5f55d8670e349b6e614913f9d910
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
145
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader
Executable file
145
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_Bitmap-Mobile.shader
Executable file
@ -0,0 +1,145 @@
|
|||||||
|
Shader "TextMeshPro/Mobile/Bitmap" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
[HDR]_Color ("Text Color", Color) = (1,1,1,1)
|
||||||
|
_DiffusePower ("Diffuse Power", Range(1.0,4.0)) = 1.0
|
||||||
|
|
||||||
|
_VertexOffsetX("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY("Vertex OffsetY", float) = 0
|
||||||
|
_MaskSoftnessX("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
|
||||||
|
_StencilComp("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil("Stencil ID", Float) = 0
|
||||||
|
_StencilOp("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode("Cull Mode", Float) = 0
|
||||||
|
_ColorMask("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
|
||||||
|
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref[_Stencil]
|
||||||
|
Comp[_StencilComp]
|
||||||
|
Pass[_StencilOp]
|
||||||
|
ReadMask[_StencilReadMask]
|
||||||
|
WriteMask[_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Lighting Off
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
ZWrite Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
ColorMask[_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
#pragma fragmentoption ARB_precision_hint_fastest
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
|
struct appdata_t {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct v2f {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float4 mask : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
sampler2D _MainTex;
|
||||||
|
fixed4 _Color;
|
||||||
|
float _DiffusePower;
|
||||||
|
|
||||||
|
uniform float _VertexOffsetX;
|
||||||
|
uniform float _VertexOffsetY;
|
||||||
|
uniform float4 _ClipRect;
|
||||||
|
uniform float _MaskSoftnessX;
|
||||||
|
uniform float _MaskSoftnessY;
|
||||||
|
|
||||||
|
v2f vert (appdata_t v)
|
||||||
|
{
|
||||||
|
v2f OUT;
|
||||||
|
float4 vert = v.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
vert.xy += (vert.w * 0.5) / _ScreenParams.xy;
|
||||||
|
|
||||||
|
OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert));
|
||||||
|
OUT.color = v.color;
|
||||||
|
OUT.color *= _Color;
|
||||||
|
OUT.color.rgb *= _DiffusePower;
|
||||||
|
OUT.texcoord0 = v.texcoord0;
|
||||||
|
|
||||||
|
float2 pixelSize = OUT.vertex.w;
|
||||||
|
//pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1]));
|
||||||
|
|
||||||
|
// Clamp _ClipRect to 16bit.
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed4 frag (v2f IN) : COLOR
|
||||||
|
{
|
||||||
|
fixed4 color = fixed4(IN.color.rgb, IN.color.a * tex2D(_MainTex, IN.texcoord0).a);
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
|
||||||
|
color *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(color.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
|
||||||
|
Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
BindChannels {
|
||||||
|
Bind "Color", color
|
||||||
|
Bind "Vertex", vertex
|
||||||
|
Bind "TexCoord", texcoord0
|
||||||
|
}
|
||||||
|
Pass {
|
||||||
|
SetTexture [_MainTex] {
|
||||||
|
constantColor [_Color] combine constant * primary, constant * texture
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1e3b057af24249748ff873be7fafee47
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
143
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader
Executable file
143
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_Bitmap.shader
Executable file
@ -0,0 +1,143 @@
|
|||||||
|
Shader "TextMeshPro/Bitmap" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_FaceTex ("Font Texture", 2D) = "white" {}
|
||||||
|
[HDR]_FaceColor ("Text Color", Color) = (1,1,1,1)
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
|
||||||
|
_StencilComp("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil("Stencil ID", Float) = 0
|
||||||
|
_StencilOp("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode("Cull Mode", Float) = 0
|
||||||
|
_ColorMask("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader{
|
||||||
|
|
||||||
|
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref[_Stencil]
|
||||||
|
Comp[_StencilComp]
|
||||||
|
Pass[_StencilOp]
|
||||||
|
ReadMask[_StencilReadMask]
|
||||||
|
WriteMask[_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Lighting Off
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
ZWrite Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
ColorMask[_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
|
struct appdata_t {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct v2f {
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
float4 mask : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform sampler2D _MainTex;
|
||||||
|
uniform sampler2D _FaceTex;
|
||||||
|
uniform float4 _FaceTex_ST;
|
||||||
|
uniform fixed4 _FaceColor;
|
||||||
|
|
||||||
|
uniform float _VertexOffsetX;
|
||||||
|
uniform float _VertexOffsetY;
|
||||||
|
uniform float4 _ClipRect;
|
||||||
|
uniform float _MaskSoftnessX;
|
||||||
|
uniform float _MaskSoftnessY;
|
||||||
|
|
||||||
|
float2 UnpackUV(float uv)
|
||||||
|
{
|
||||||
|
float2 output;
|
||||||
|
output.x = floor(uv / 4096);
|
||||||
|
output.y = uv - 4096 * output.x;
|
||||||
|
|
||||||
|
return output * 0.001953125;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2f vert (appdata_t v)
|
||||||
|
{
|
||||||
|
float4 vert = v.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
vert.xy += (vert.w * 0.5) / _ScreenParams.xy;
|
||||||
|
|
||||||
|
float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert));
|
||||||
|
|
||||||
|
fixed4 faceColor = v.color;
|
||||||
|
faceColor *= _FaceColor;
|
||||||
|
|
||||||
|
v2f OUT;
|
||||||
|
OUT.vertex = vPosition;
|
||||||
|
OUT.color = faceColor;
|
||||||
|
OUT.texcoord0 = v.texcoord0;
|
||||||
|
OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex);
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1]));
|
||||||
|
|
||||||
|
// Clamp _ClipRect to 16bit.
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed4 frag (v2f IN) : SV_Target
|
||||||
|
{
|
||||||
|
fixed4 color = tex2D(_MainTex, IN.texcoord0);
|
||||||
|
color = fixed4 (tex2D(_FaceTex, IN.texcoord1).rgb * IN.color.rgb, IN.color.a * color.a);
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
|
||||||
|
color *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(color.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 128e987d567d4e2c824d754223b3f3b0
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
317
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader
Executable file
317
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF Overlay.shader
Executable file
@ -0,0 +1,317 @@
|
|||||||
|
Shader "TextMeshPro/Distance Field Overlay" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_FaceTex ("Face Texture", 2D) = "white" {}
|
||||||
|
_FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineTex ("Outline Texture", 2D) = "white" {}
|
||||||
|
_OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0, 1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_Bevel ("Bevel", Range(0,1)) = 0.5
|
||||||
|
_BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0
|
||||||
|
_BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0
|
||||||
|
_BevelClamp ("Bevel Clamp", Range(0,1)) = 0
|
||||||
|
_BevelRoundness ("Bevel Roundness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416
|
||||||
|
[HDR]_SpecularColor ("Specular", Color) = (1,1,1,1)
|
||||||
|
_SpecularPower ("Specular", Range(0,4)) = 2.0
|
||||||
|
_Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10
|
||||||
|
_Diffuse ("Diffuse", Range(0,1)) = 0.5
|
||||||
|
_Ambient ("Ambient", Range(1,0)) = 0.5
|
||||||
|
|
||||||
|
_BumpMap ("Normal map", 2D) = "bump" {}
|
||||||
|
_BumpOutline ("Bump Outline", Range(0,1)) = 0
|
||||||
|
_BumpFace ("Bump Face", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ }
|
||||||
|
_EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5)
|
||||||
|
_GlowOffset ("Offset", Range(-1,1)) = 0
|
||||||
|
_GlowInner ("Inner", Range(0,1)) = 0.05
|
||||||
|
_GlowOuter ("Outer", Range(0,1)) = 0.05
|
||||||
|
_GlowPower ("Falloff", Range(1, 0)) = 0.75
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = 0.5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5.0
|
||||||
|
_ScaleX ("Scale X", float) = 1.0
|
||||||
|
_ScaleY ("Scale Y", float) = 1.0
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767)
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Overlay"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest Always
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma target 3.0
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ BEVEL_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
#pragma shader_feature __ GLOW_ON
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
#include "TMPro.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 atlas : TEXCOORD0; // Atlas
|
||||||
|
float4 param : TEXCOORD1; // alphaClip, scale, bias, weight
|
||||||
|
float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw)
|
||||||
|
float3 viewDir : TEXCOORD3;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 texcoord2 : TEXCOORD4; // u,v, scale, bias
|
||||||
|
fixed4 underlayColor : COLOR1;
|
||||||
|
#endif
|
||||||
|
float4 textures : TEXCOORD5;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used by Unity internally to handle Texture Tiling and Offset.
|
||||||
|
float4 _FaceTex_ST;
|
||||||
|
float4 _OutlineTex_ST;
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input,output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.position;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float bias =(.5 - weight) + (.5 / scale);
|
||||||
|
|
||||||
|
float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA);
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 underlayColor = _UnderlayColor;
|
||||||
|
underlayColor.rgb *= underlayColor.a;
|
||||||
|
|
||||||
|
float bScale = scale;
|
||||||
|
bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale);
|
||||||
|
float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 bOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Support for texture tiling and offset
|
||||||
|
float2 textureUV = UnpackUV(input.texcoord1.x);
|
||||||
|
float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex);
|
||||||
|
float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex);
|
||||||
|
|
||||||
|
|
||||||
|
output.position = vPosition;
|
||||||
|
output.color = input.color;
|
||||||
|
output.atlas = input.texcoord0;
|
||||||
|
output.param = float4(alphaClip, scale, bias, weight);
|
||||||
|
output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz);
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias);
|
||||||
|
output.underlayColor = underlayColor;
|
||||||
|
#endif
|
||||||
|
output.textures = float4(faceUV, outlineUV);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
float c = tex2D(_MainTex, input.atlas).a;
|
||||||
|
|
||||||
|
#ifndef UNDERLAY_ON
|
||||||
|
clip(c - input.param.x);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float scale = input.param.y;
|
||||||
|
float bias = input.param.z;
|
||||||
|
float weight = input.param.w;
|
||||||
|
float sd = (bias - c) * scale;
|
||||||
|
|
||||||
|
float outline = (_OutlineWidth * _ScaleRatioA) * scale;
|
||||||
|
float softness = (_OutlineSoftness * _ScaleRatioA) * scale;
|
||||||
|
|
||||||
|
half4 faceColor = _FaceColor;
|
||||||
|
half4 outlineColor = _OutlineColor;
|
||||||
|
|
||||||
|
faceColor.rgb *= input.color.rgb;
|
||||||
|
|
||||||
|
faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y);
|
||||||
|
outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y);
|
||||||
|
|
||||||
|
faceColor = GetColor(sd, faceColor, outlineColor, outline, softness);
|
||||||
|
|
||||||
|
#if BEVEL_ON
|
||||||
|
float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0);
|
||||||
|
float3 n = GetSurfaceNormal(input.atlas, weight, dxy);
|
||||||
|
|
||||||
|
float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz;
|
||||||
|
bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5));
|
||||||
|
n = normalize(n- bump);
|
||||||
|
|
||||||
|
float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0));
|
||||||
|
|
||||||
|
float3 col = GetSpecular(n, light);
|
||||||
|
faceColor.rgb += col*faceColor.a;
|
||||||
|
faceColor.rgb *= 1-(dot(n, light)*_Diffuse);
|
||||||
|
faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z);
|
||||||
|
|
||||||
|
fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n));
|
||||||
|
faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z;
|
||||||
|
faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z;
|
||||||
|
faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
float4 glowColor = GetGlowColor(sd, scale);
|
||||||
|
faceColor.rgb += glowColor.rgb * glowColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
faceColor *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(faceColor.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return faceColor * input.color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Fallback "TextMeshPro/Mobile/Distance Field"
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dd89cf5b9246416f84610a006f916af7
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
310
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader
Executable file
310
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF SSD.shader
Executable file
@ -0,0 +1,310 @@
|
|||||||
|
Shader "TextMeshPro/Distance Field SSD" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_FaceTex ("Face Texture", 2D) = "white" {}
|
||||||
|
_FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineTex ("Outline Texture", 2D) = "white" {}
|
||||||
|
_OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0, 1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_Bevel ("Bevel", Range(0,1)) = 0.5
|
||||||
|
_BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0
|
||||||
|
_BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0
|
||||||
|
_BevelClamp ("Bevel Clamp", Range(0,1)) = 0
|
||||||
|
_BevelRoundness ("Bevel Roundness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416
|
||||||
|
[HDR]_SpecularColor ("Specular", Color) = (1,1,1,1)
|
||||||
|
_SpecularPower ("Specular", Range(0,4)) = 2.0
|
||||||
|
_Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10
|
||||||
|
_Diffuse ("Diffuse", Range(0,1)) = 0.5
|
||||||
|
_Ambient ("Ambient", Range(1,0)) = 0.5
|
||||||
|
|
||||||
|
_BumpMap ("Normal map", 2D) = "bump" {}
|
||||||
|
_BumpOutline ("Bump Outline", Range(0,1)) = 0
|
||||||
|
_BumpFace ("Bump Face", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ }
|
||||||
|
_EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5)
|
||||||
|
_GlowOffset ("Offset", Range(-1,1)) = 0
|
||||||
|
_GlowInner ("Inner", Range(0,1)) = 0.05
|
||||||
|
_GlowOuter ("Outer", Range(0,1)) = 0.05
|
||||||
|
_GlowPower ("Falloff", Range(1, 0)) = 0.75
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = 0.5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5.0
|
||||||
|
_ScaleX ("Scale X", float) = 1.0
|
||||||
|
_ScaleY ("Scale Y", float) = 1.0
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767)
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue" = "Transparent"
|
||||||
|
"IgnoreProjector" = "True"
|
||||||
|
"RenderType" = "Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref[_Stencil]
|
||||||
|
Comp[_StencilComp]
|
||||||
|
Pass[_StencilOp]
|
||||||
|
ReadMask[_StencilReadMask]
|
||||||
|
WriteMask[_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull[_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest[unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask[_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma target 3.0
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ BEVEL_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
#pragma shader_feature __ GLOW_ON
|
||||||
|
#pragma shader_feature __ FORCE_LINEAR
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
#include "TMPro.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
float4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float4 color : COLOR;
|
||||||
|
float2 atlas : TEXCOORD0;
|
||||||
|
float weight : TEXCOORD1;
|
||||||
|
float2 mask : TEXCOORD2; // Position in object space(xy)
|
||||||
|
float3 viewDir : TEXCOORD3;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float2 texcoord2 : TEXCOORD4;
|
||||||
|
float4 underlayColor : COLOR1;
|
||||||
|
#endif
|
||||||
|
float4 textures : TEXCOORD5;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used by Unity internally to handle Texture Tiling and Offset.
|
||||||
|
float4 _FaceTex_ST;
|
||||||
|
float4 _OutlineTex_ST;
|
||||||
|
|
||||||
|
float4 SRGBToLinear(float4 rgba) {
|
||||||
|
return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input,output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.position;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 underlayColor = _UnderlayColor;
|
||||||
|
underlayColor.rgb *= underlayColor.a;
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 bOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
|
||||||
|
// Support for texture tiling and offset
|
||||||
|
float2 textureUV = UnpackUV(input.texcoord1.x);
|
||||||
|
float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex);
|
||||||
|
float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex);
|
||||||
|
|
||||||
|
float4 color = input.color;
|
||||||
|
#if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA)
|
||||||
|
color = SRGBToLinear(input.color);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
output.position = vPosition;
|
||||||
|
output.color = color;
|
||||||
|
output.atlas = input.texcoord0;
|
||||||
|
output.weight = weight;
|
||||||
|
output.mask = half2(vert.xy * 2 - clampedRect.xy - clampedRect.zw);
|
||||||
|
output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz);
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord2 = input.texcoord0 + bOffset;
|
||||||
|
output.underlayColor = underlayColor;
|
||||||
|
#endif
|
||||||
|
output.textures = float4(faceUV, outlineUV);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
float c = tex2D(_MainTex, input.atlas).a;
|
||||||
|
|
||||||
|
float2 pixelSize = float2(ddx(input.atlas.y), ddy(input.atlas.y));
|
||||||
|
pixelSize *= _TextureWidth * .75;
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize)) * _GradientScale * (_Sharpness + 1);
|
||||||
|
|
||||||
|
float weight = input.weight;
|
||||||
|
float bias = (.5 - weight) + (.5 / scale);
|
||||||
|
float sd = (bias - c) * scale;
|
||||||
|
|
||||||
|
float outline = (_OutlineWidth * _ScaleRatioA) * scale;
|
||||||
|
float softness = (_OutlineSoftness * _ScaleRatioA) * scale;
|
||||||
|
|
||||||
|
half4 faceColor = _FaceColor;
|
||||||
|
half4 outlineColor = _OutlineColor;
|
||||||
|
|
||||||
|
faceColor.rgb *= input.color.rgb;
|
||||||
|
|
||||||
|
faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y);
|
||||||
|
outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y);
|
||||||
|
|
||||||
|
faceColor = GetColor(sd, faceColor, outlineColor, outline, softness);
|
||||||
|
|
||||||
|
#if BEVEL_ON
|
||||||
|
float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0);
|
||||||
|
float3 n = GetSurfaceNormal(input.atlas, weight, dxy);
|
||||||
|
|
||||||
|
float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz;
|
||||||
|
bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5));
|
||||||
|
n = normalize(n - bump);
|
||||||
|
|
||||||
|
float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0));
|
||||||
|
|
||||||
|
float3 col = GetSpecular(n, light);
|
||||||
|
faceColor.rgb += col * faceColor.a;
|
||||||
|
faceColor.rgb *= 1 - (dot(n, light) * _Diffuse);
|
||||||
|
faceColor.rgb *= lerp(_Ambient, 1, n.z * n.z);
|
||||||
|
|
||||||
|
fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n));
|
||||||
|
faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float bScale = scale;
|
||||||
|
bScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * bScale);
|
||||||
|
float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale;
|
||||||
|
faceColor += input.underlayColor * saturate(d - bBias) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale;
|
||||||
|
faceColor += input.underlayColor * (1 - saturate(d - bBias)) * saturate(1 - sd) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
float4 glowColor = GetGlowColor(sd, scale);
|
||||||
|
faceColor.rgb += glowColor.rgb * glowColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
float2 maskZW = 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + (1 / scale));
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * maskZW);
|
||||||
|
faceColor *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(faceColor.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return faceColor * input.color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Fallback "TextMeshPro/Mobile/Distance Field"
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 14eb328de4b8eb245bb7cea29e4ac00b
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,247 @@
|
|||||||
|
// Simplified SDF shader:
|
||||||
|
// - No Shading Option (bevel / bump / env map)
|
||||||
|
// - No Glow Option
|
||||||
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field - Masking" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0,1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = .5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5
|
||||||
|
_ScaleX ("Scale X", float) = 1
|
||||||
|
_ScaleY ("Scale Y", float) = 1
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
_MaskTex ("Mask Texture", 2D) = "white" {}
|
||||||
|
_MaskInverse ("Inverse", float) = 0
|
||||||
|
_MaskEdgeColor ("Edge Color", Color) = (1,1,1,1)
|
||||||
|
_MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01
|
||||||
|
_MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ OUTLINE_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 faceColor : COLOR;
|
||||||
|
fixed4 outlineColor : COLOR1;
|
||||||
|
float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV
|
||||||
|
half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w)
|
||||||
|
half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw)
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved
|
||||||
|
half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
float _MaskWipeControl;
|
||||||
|
float _MaskEdgeSoftness;
|
||||||
|
fixed4 _MaskEdgeColor;
|
||||||
|
bool _MaskInverse;
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float layerScale = scale;
|
||||||
|
|
||||||
|
scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
|
||||||
|
float bias = (0.5 - weight) * scale - 0.5;
|
||||||
|
float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale;
|
||||||
|
|
||||||
|
float opacity = input.color.a;
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
opacity = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor;
|
||||||
|
faceColor.rgb *= faceColor.a;
|
||||||
|
|
||||||
|
fixed4 outlineColor = _OutlineColor;
|
||||||
|
outlineColor.a *= opacity;
|
||||||
|
outlineColor.rgb *= outlineColor.a;
|
||||||
|
outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2))));
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
|
||||||
|
layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale);
|
||||||
|
float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 layerOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Structure for pixel shader
|
||||||
|
pixel_t output = {
|
||||||
|
vPosition,
|
||||||
|
faceColor,
|
||||||
|
outlineColor,
|
||||||
|
float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y),
|
||||||
|
half4(scale, bias - outline, bias + outline, bias),
|
||||||
|
half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)),
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float4(input.texcoord0 + layerOffset, input.color.a, 0),
|
||||||
|
half2(layerScale, layerBias),
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PIXEL SHADER
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x;
|
||||||
|
half4 c = input.faceColor * saturate(d - input.param.w);
|
||||||
|
|
||||||
|
#ifdef OUTLINE_ON
|
||||||
|
c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z));
|
||||||
|
c *= saturate(d - input.param.y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
half sd = saturate(d - input.param.z);
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
//#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
c *= m.x * m.y;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a);
|
||||||
|
float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl;
|
||||||
|
a = saturate(t / _MaskEdgeSoftness);
|
||||||
|
c.rgb = lerp(_MaskEdgeColor.rgb*c.a, c.rgb, a);
|
||||||
|
c *= a;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
c *= input.texcoord1.z;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(c.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bc1ede39bf3643ee8e493720e4259791
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,240 @@
|
|||||||
|
// Simplified SDF shader:
|
||||||
|
// - No Shading Option (bevel / bump / env map)
|
||||||
|
// - No Glow Option
|
||||||
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field Overlay" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0,1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = .5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5
|
||||||
|
_ScaleX ("Scale X", float) = 1
|
||||||
|
_ScaleY ("Scale Y", float) = 1
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Overlay"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest Always
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ OUTLINE_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 faceColor : COLOR;
|
||||||
|
fixed4 outlineColor : COLOR1;
|
||||||
|
float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV
|
||||||
|
half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w)
|
||||||
|
half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw)
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved
|
||||||
|
half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float layerScale = scale;
|
||||||
|
|
||||||
|
scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
|
||||||
|
float bias = (0.5 - weight) * scale - 0.5;
|
||||||
|
float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale;
|
||||||
|
|
||||||
|
float opacity = input.color.a;
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
opacity = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor;
|
||||||
|
faceColor.rgb *= faceColor.a;
|
||||||
|
|
||||||
|
fixed4 outlineColor = _OutlineColor;
|
||||||
|
outlineColor.a *= opacity;
|
||||||
|
outlineColor.rgb *= outlineColor.a;
|
||||||
|
outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2))));
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale);
|
||||||
|
float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 layerOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Populate structure for pixel shader
|
||||||
|
output.vertex = vPosition;
|
||||||
|
output.faceColor = faceColor;
|
||||||
|
output.outlineColor = outlineColor;
|
||||||
|
output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y);
|
||||||
|
output.param = half4(scale, bias - outline, bias + outline, bias);
|
||||||
|
output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0);
|
||||||
|
output.underlayParam = half2(layerScale, layerBias);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PIXEL SHADER
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x;
|
||||||
|
half4 c = input.faceColor * saturate(d - input.param.w);
|
||||||
|
|
||||||
|
#ifdef OUTLINE_ON
|
||||||
|
c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z));
|
||||||
|
c *= saturate(d - input.param.y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
half sd = saturate(d - input.param.z);
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
c *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
c *= input.texcoord1.z;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(c.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a02a7d8c237544f1962732b55a9aebf1
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
// Simplified SDF shader:
|
||||||
|
// - No Shading Option (bevel / bump / env map)
|
||||||
|
// - No Glow Option
|
||||||
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field SSD" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0,1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = .5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5
|
||||||
|
_ScaleX ("Scale X", float) = 1
|
||||||
|
_ScaleY ("Scale Y", float) = 1
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
_MaskTex ("Mask Texture", 2D) = "white" {}
|
||||||
|
_MaskInverse ("Inverse", float) = 0
|
||||||
|
_MaskEdgeColor ("Edge Color", Color) = (1,1,1,1)
|
||||||
|
_MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01
|
||||||
|
_MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags {
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ OUTLINE_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
|
||||||
|
#include "TMPro_Mobile.cginc"
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c8d12adcee749c344b8117cf7c7eb912
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
240
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader
Executable file
240
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF-Mobile.shader
Executable file
@ -0,0 +1,240 @@
|
|||||||
|
// Simplified SDF shader:
|
||||||
|
// - No Shading Option (bevel / bump / env map)
|
||||||
|
// - No Glow Option
|
||||||
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0,1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = .5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5
|
||||||
|
_ScaleX ("Scale X", float) = 1
|
||||||
|
_ScaleY ("Scale Y", float) = 1
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ OUTLINE_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 faceColor : COLOR;
|
||||||
|
fixed4 outlineColor : COLOR1;
|
||||||
|
float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV
|
||||||
|
half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w)
|
||||||
|
half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw)
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved
|
||||||
|
half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.vertex;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float layerScale = scale;
|
||||||
|
|
||||||
|
scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
|
||||||
|
float bias = (0.5 - weight) * scale - 0.5;
|
||||||
|
float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale;
|
||||||
|
|
||||||
|
float opacity = input.color.a;
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
opacity = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor;
|
||||||
|
faceColor.rgb *= faceColor.a;
|
||||||
|
|
||||||
|
fixed4 outlineColor = _OutlineColor;
|
||||||
|
outlineColor.a *= opacity;
|
||||||
|
outlineColor.rgb *= outlineColor.a;
|
||||||
|
outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2))));
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale);
|
||||||
|
float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 layerOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Populate structure for pixel shader
|
||||||
|
output.vertex = vPosition;
|
||||||
|
output.faceColor = faceColor;
|
||||||
|
output.outlineColor = outlineColor;
|
||||||
|
output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y);
|
||||||
|
output.param = half4(scale, bias - outline, bias + outline, bias);
|
||||||
|
output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0);
|
||||||
|
output.underlayParam = half2(layerScale, layerBias);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PIXEL SHADER
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x;
|
||||||
|
half4 c = input.faceColor * saturate(d - input.param.w);
|
||||||
|
|
||||||
|
#ifdef OUTLINE_ON
|
||||||
|
c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z));
|
||||||
|
c *= saturate(d - input.param.y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
half sd = saturate(d - input.param.z);
|
||||||
|
d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x;
|
||||||
|
c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
c *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
c *= input.texcoord1.z;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(c.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fe393ace9b354375a9cb14cdbbc28be4
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
// Simplified version of the SDF Surface shader :
|
||||||
|
// - No support for Bevel, Bump or envmap
|
||||||
|
// - Diffuse only lighting
|
||||||
|
// - Fully supports only 1 directional light. Other lights can affect it, but it will be per-vertex/SH.
|
||||||
|
|
||||||
|
Shader "TextMeshPro/Mobile/Distance Field (Surface)" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_FaceTex ("Fill Texture", 2D) = "white" {}
|
||||||
|
[HDR]_FaceColor ("Fill Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineTex ("Outline Texture", 2D) = "white" {}
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0, 1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5)
|
||||||
|
_GlowOffset ("Offset", Range(-1,1)) = 0
|
||||||
|
_GlowInner ("Inner", Range(0,1)) = 0.05
|
||||||
|
_GlowOuter ("Outer", Range(0,1)) = 0.05
|
||||||
|
_GlowPower ("Falloff", Range(1, 0)) = 0.75
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = 0.5
|
||||||
|
|
||||||
|
// Should not be directly exposed to the user
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5.0
|
||||||
|
_ScaleX ("Scale X", float) = 1.0
|
||||||
|
_ScaleY ("Scale Y", float) = 1.0
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
//_MaskCoord ("Mask Coords", vector) = (0,0,0,0)
|
||||||
|
//_MaskSoftness ("Mask Softness", float) = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
|
||||||
|
Tags {
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
LOD 300
|
||||||
|
Cull [_CullMode]
|
||||||
|
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma surface PixShader Lambert alpha:blend vertex:VertShader noforwardadd nolightmap nodirlightmap
|
||||||
|
#pragma target 3.0
|
||||||
|
#pragma shader_feature __ GLOW_ON
|
||||||
|
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
#include "TMPro.cginc"
|
||||||
|
|
||||||
|
half _FaceShininess;
|
||||||
|
half _OutlineShininess;
|
||||||
|
|
||||||
|
struct Input
|
||||||
|
{
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 uv_MainTex;
|
||||||
|
float2 uv2_FaceTex;
|
||||||
|
float2 uv2_OutlineTex;
|
||||||
|
float2 param; // Weight, Scale
|
||||||
|
float3 viewDirEnv;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "TMPro_Surface.cginc"
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
|
||||||
|
// Pass to render object as a shadow caster
|
||||||
|
Pass
|
||||||
|
{
|
||||||
|
Name "Caster"
|
||||||
|
Tags { "LightMode" = "ShadowCaster" }
|
||||||
|
Offset 1, 1
|
||||||
|
|
||||||
|
Fog {Mode Off}
|
||||||
|
ZWrite On ZTest LEqual Cull Off
|
||||||
|
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
#pragma multi_compile_shadowcaster
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
|
struct v2f {
|
||||||
|
V2F_SHADOW_CASTER;
|
||||||
|
float2 uv : TEXCOORD1;
|
||||||
|
float2 uv2 : TEXCOORD3;
|
||||||
|
float alphaClip : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform float4 _MainTex_ST;
|
||||||
|
uniform float4 _OutlineTex_ST;
|
||||||
|
float _OutlineWidth;
|
||||||
|
float _FaceDilate;
|
||||||
|
float _ScaleRatioA;
|
||||||
|
|
||||||
|
v2f vert( appdata_base v )
|
||||||
|
{
|
||||||
|
v2f o;
|
||||||
|
TRANSFER_SHADOW_CASTER(o)
|
||||||
|
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||||
|
o.uv2 = TRANSFORM_TEX(v.texcoord, _OutlineTex);
|
||||||
|
o.alphaClip = o.alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _FaceDilate * _ScaleRatioA) / 2;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform sampler2D _MainTex;
|
||||||
|
|
||||||
|
float4 frag(v2f i) : COLOR
|
||||||
|
{
|
||||||
|
fixed4 texcol = tex2D(_MainTex, i.uv).a;
|
||||||
|
clip(texcol.a - i.alphaClip);
|
||||||
|
SHADOW_CASTER_FRAGMENT(i)
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 85187c2149c549c5b33f0cdb02836b17
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
158
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader
Executable file
158
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF-Surface.shader
Executable file
@ -0,0 +1,158 @@
|
|||||||
|
Shader "TextMeshPro/Distance Field (Surface)" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_FaceTex ("Fill Texture", 2D) = "white" {}
|
||||||
|
_FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
[HDR]_FaceColor ("Fill Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineTex ("Outline Texture", 2D) = "white" {}
|
||||||
|
_OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0, 1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_Bevel ("Bevel", Range(0,1)) = 0.5
|
||||||
|
_BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0
|
||||||
|
_BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0
|
||||||
|
_BevelClamp ("Bevel Clamp", Range(0,1)) = 0
|
||||||
|
_BevelRoundness ("Bevel Roundness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_BumpMap ("Normalmap", 2D) = "bump" {}
|
||||||
|
_BumpOutline ("Bump Outline", Range(0,1)) = 0.5
|
||||||
|
_BumpFace ("Bump Face", Range(0,1)) = 0.5
|
||||||
|
|
||||||
|
_ReflectFaceColor ("Face Color", Color) = (0,0,0,1)
|
||||||
|
_ReflectOutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ }
|
||||||
|
_EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0)
|
||||||
|
[HDR]_SpecColor ("Specular Color", Color) = (0,0,0,1)
|
||||||
|
|
||||||
|
_FaceShininess ("Face Shininess", Range(0,1)) = 0
|
||||||
|
_OutlineShininess ("Outline Shininess", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5)
|
||||||
|
_GlowOffset ("Offset", Range(-1,1)) = 0
|
||||||
|
_GlowInner ("Inner", Range(0,1)) = 0.05
|
||||||
|
_GlowOuter ("Outer", Range(0,1)) = 0.05
|
||||||
|
_GlowPower ("Falloff", Range(1, 0)) = 0.75
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = 0.5
|
||||||
|
|
||||||
|
// Should not be directly exposed to the user
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5.0
|
||||||
|
_ScaleX ("Scale X", float) = 1.0
|
||||||
|
_ScaleY ("Scale Y", float) = 1.0
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
//_MaskCoord ("Mask Coords", vector) = (0,0,0,0)
|
||||||
|
//_MaskSoftness ("Mask Softness", float) = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
|
||||||
|
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
|
||||||
|
|
||||||
|
LOD 300
|
||||||
|
Cull [_CullMode]
|
||||||
|
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma surface PixShader BlinnPhong alpha:blend vertex:VertShader nolightmap nodirlightmap
|
||||||
|
#pragma target 3.0
|
||||||
|
#pragma shader_feature __ GLOW_ON
|
||||||
|
#pragma glsl
|
||||||
|
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
#include "TMPro.cginc"
|
||||||
|
|
||||||
|
half _FaceShininess;
|
||||||
|
half _OutlineShininess;
|
||||||
|
|
||||||
|
struct Input
|
||||||
|
{
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 uv_MainTex;
|
||||||
|
float2 uv2_FaceTex;
|
||||||
|
float2 uv2_OutlineTex;
|
||||||
|
float2 param; // Weight, Scale
|
||||||
|
float3 viewDirEnv;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define BEVEL_ON 1
|
||||||
|
#include "TMPro_Surface.cginc"
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
|
||||||
|
// Pass to render object as a shadow caster
|
||||||
|
Pass
|
||||||
|
{
|
||||||
|
Name "Caster"
|
||||||
|
Tags { "LightMode" = "ShadowCaster" }
|
||||||
|
Offset 1, 1
|
||||||
|
|
||||||
|
Fog {Mode Off}
|
||||||
|
ZWrite On
|
||||||
|
ZTest LEqual
|
||||||
|
Cull Off
|
||||||
|
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
#pragma multi_compile_shadowcaster
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
|
struct v2f {
|
||||||
|
V2F_SHADOW_CASTER;
|
||||||
|
float2 uv : TEXCOORD1;
|
||||||
|
float2 uv2 : TEXCOORD3;
|
||||||
|
float alphaClip : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform float4 _MainTex_ST;
|
||||||
|
uniform float4 _OutlineTex_ST;
|
||||||
|
float _OutlineWidth;
|
||||||
|
float _FaceDilate;
|
||||||
|
float _ScaleRatioA;
|
||||||
|
|
||||||
|
v2f vert( appdata_base v )
|
||||||
|
{
|
||||||
|
v2f o;
|
||||||
|
TRANSFER_SHADOW_CASTER(o)
|
||||||
|
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||||
|
o.uv2 = TRANSFORM_TEX(v.texcoord, _OutlineTex);
|
||||||
|
o.alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _FaceDilate * _ScaleRatioA) / 2;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform sampler2D _MainTex;
|
||||||
|
|
||||||
|
float4 frag(v2f i) : COLOR
|
||||||
|
{
|
||||||
|
fixed4 texcol = tex2D(_MainTex, i.uv).a;
|
||||||
|
clip(texcol.a - i.alphaClip);
|
||||||
|
SHADOW_CASTER_FRAGMENT(i)
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f7ada0af4f174f0694ca6a487b8f543d
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
317
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF.shader
Executable file
317
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_SDF.shader
Executable file
@ -0,0 +1,317 @@
|
|||||||
|
Shader "TextMeshPro/Distance Field" {
|
||||||
|
|
||||||
|
Properties {
|
||||||
|
_FaceTex ("Face Texture", 2D) = "white" {}
|
||||||
|
_FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
[HDR]_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
_FaceDilate ("Face Dilate", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1)
|
||||||
|
_OutlineTex ("Outline Texture", 2D) = "white" {}
|
||||||
|
_OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0
|
||||||
|
_OutlineWidth ("Outline Thickness", Range(0, 1)) = 0
|
||||||
|
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_Bevel ("Bevel", Range(0,1)) = 0.5
|
||||||
|
_BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0
|
||||||
|
_BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0
|
||||||
|
_BevelClamp ("Bevel Clamp", Range(0,1)) = 0
|
||||||
|
_BevelRoundness ("Bevel Roundness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416
|
||||||
|
[HDR]_SpecularColor ("Specular", Color) = (1,1,1,1)
|
||||||
|
_SpecularPower ("Specular", Range(0,4)) = 2.0
|
||||||
|
_Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10
|
||||||
|
_Diffuse ("Diffuse", Range(0,1)) = 0.5
|
||||||
|
_Ambient ("Ambient", Range(1,0)) = 0.5
|
||||||
|
|
||||||
|
_BumpMap ("Normal map", 2D) = "bump" {}
|
||||||
|
_BumpOutline ("Bump Outline", Range(0,1)) = 0
|
||||||
|
_BumpFace ("Bump Face", Range(0,1)) = 0
|
||||||
|
|
||||||
|
_ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1)
|
||||||
|
_Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ }
|
||||||
|
_EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
[HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5)
|
||||||
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
_UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0
|
||||||
|
_UnderlayDilate ("Border Dilate", Range(-1,1)) = 0
|
||||||
|
_UnderlaySoftness ("Border Softness", Range(0,1)) = 0
|
||||||
|
|
||||||
|
[HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5)
|
||||||
|
_GlowOffset ("Offset", Range(-1,1)) = 0
|
||||||
|
_GlowInner ("Inner", Range(0,1)) = 0.05
|
||||||
|
_GlowOuter ("Outer", Range(0,1)) = 0.05
|
||||||
|
_GlowPower ("Falloff", Range(1, 0)) = 0.75
|
||||||
|
|
||||||
|
_WeightNormal ("Weight Normal", float) = 0
|
||||||
|
_WeightBold ("Weight Bold", float) = 0.5
|
||||||
|
|
||||||
|
_ShaderFlags ("Flags", float) = 0
|
||||||
|
_ScaleRatioA ("Scale RatioA", float) = 1
|
||||||
|
_ScaleRatioB ("Scale RatioB", float) = 1
|
||||||
|
_ScaleRatioC ("Scale RatioC", float) = 1
|
||||||
|
|
||||||
|
_MainTex ("Font Atlas", 2D) = "white" {}
|
||||||
|
_TextureWidth ("Texture Width", float) = 512
|
||||||
|
_TextureHeight ("Texture Height", float) = 512
|
||||||
|
_GradientScale ("Gradient Scale", float) = 5.0
|
||||||
|
_ScaleX ("Scale X", float) = 1.0
|
||||||
|
_ScaleY ("Scale Y", float) = 1.0
|
||||||
|
_PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875
|
||||||
|
_Sharpness ("Sharpness", Range(-1,1)) = 0
|
||||||
|
|
||||||
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
|
_MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767)
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader {
|
||||||
|
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
ZWrite Off
|
||||||
|
Lighting Off
|
||||||
|
Fog { Mode Off }
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
Blend One OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass {
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma target 3.0
|
||||||
|
#pragma vertex VertShader
|
||||||
|
#pragma fragment PixShader
|
||||||
|
#pragma shader_feature __ BEVEL_ON
|
||||||
|
#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER
|
||||||
|
#pragma shader_feature __ GLOW_ON
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
#include "TMPro_Properties.cginc"
|
||||||
|
#include "TMPro.cginc"
|
||||||
|
|
||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 atlas : TEXCOORD0; // Atlas
|
||||||
|
float4 param : TEXCOORD1; // alphaClip, scale, bias, weight
|
||||||
|
float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw)
|
||||||
|
float3 viewDir : TEXCOORD3;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 texcoord2 : TEXCOORD4; // u,v, scale, bias
|
||||||
|
fixed4 underlayColor : COLOR1;
|
||||||
|
#endif
|
||||||
|
float4 textures : TEXCOORD5;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used by Unity internally to handle Texture Tiling and Offset.
|
||||||
|
float4 _FaceTex_ST;
|
||||||
|
float4 _OutlineTex_ST;
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input,output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.position;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
float bias =(.5 - weight) + (.5 / scale);
|
||||||
|
|
||||||
|
float alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _OutlineSoftness * _ScaleRatioA);
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 underlayColor = _UnderlayColor;
|
||||||
|
underlayColor.rgb *= underlayColor.a;
|
||||||
|
|
||||||
|
float bScale = scale;
|
||||||
|
bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale);
|
||||||
|
float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale);
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
float2 bOffset = float2(x, y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
// Support for texture tiling and offset
|
||||||
|
float2 textureUV = UnpackUV(input.texcoord1.x);
|
||||||
|
float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex);
|
||||||
|
float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex);
|
||||||
|
|
||||||
|
|
||||||
|
output.position = vPosition;
|
||||||
|
output.color = input.color;
|
||||||
|
output.atlas = input.texcoord0;
|
||||||
|
output.param = float4(alphaClip, scale, bias, weight);
|
||||||
|
output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy));
|
||||||
|
output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz);
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias);
|
||||||
|
output.underlayColor = underlayColor;
|
||||||
|
#endif
|
||||||
|
output.textures = float4(faceUV, outlineUV);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
float c = tex2D(_MainTex, input.atlas).a;
|
||||||
|
|
||||||
|
#ifndef UNDERLAY_ON
|
||||||
|
clip(c - input.param.x);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float scale = input.param.y;
|
||||||
|
float bias = input.param.z;
|
||||||
|
float weight = input.param.w;
|
||||||
|
float sd = (bias - c) * scale;
|
||||||
|
|
||||||
|
float outline = (_OutlineWidth * _ScaleRatioA) * scale;
|
||||||
|
float softness = (_OutlineSoftness * _ScaleRatioA) * scale;
|
||||||
|
|
||||||
|
half4 faceColor = _FaceColor;
|
||||||
|
half4 outlineColor = _OutlineColor;
|
||||||
|
|
||||||
|
faceColor.rgb *= input.color.rgb;
|
||||||
|
|
||||||
|
faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y);
|
||||||
|
outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y);
|
||||||
|
|
||||||
|
faceColor = GetColor(sd, faceColor, outlineColor, outline, softness);
|
||||||
|
|
||||||
|
#if BEVEL_ON
|
||||||
|
float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0);
|
||||||
|
float3 n = GetSurfaceNormal(input.atlas, weight, dxy);
|
||||||
|
|
||||||
|
float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz;
|
||||||
|
bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5));
|
||||||
|
n = normalize(n- bump);
|
||||||
|
|
||||||
|
float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0));
|
||||||
|
|
||||||
|
float3 col = GetSpecular(n, light);
|
||||||
|
faceColor.rgb += col*faceColor.a;
|
||||||
|
faceColor.rgb *= 1-(dot(n, light)*_Diffuse);
|
||||||
|
faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z);
|
||||||
|
|
||||||
|
fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n));
|
||||||
|
faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z;
|
||||||
|
faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z;
|
||||||
|
faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
float4 glowColor = GetGlowColor(sd, scale);
|
||||||
|
faceColor.rgb += glowColor.rgb * glowColor.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness.
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
|
faceColor *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(faceColor.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return faceColor * input.color.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Fallback "TextMeshPro/Mobile/Distance Field"
|
||||||
|
CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI"
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 68e6db2ebdc24f95958faec2be5558d6
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
116
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader
Executable file
116
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMP_Sprite.shader
Executable file
@ -0,0 +1,116 @@
|
|||||||
|
Shader "TextMeshPro/Sprite"
|
||||||
|
{
|
||||||
|
Properties
|
||||||
|
{
|
||||||
|
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
||||||
|
_Color ("Tint", Color) = (1,1,1,1)
|
||||||
|
|
||||||
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
|
_CullMode ("Cull Mode", Float) = 0
|
||||||
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
|
|
||||||
|
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader
|
||||||
|
{
|
||||||
|
Tags
|
||||||
|
{
|
||||||
|
"Queue"="Transparent"
|
||||||
|
"IgnoreProjector"="True"
|
||||||
|
"RenderType"="Transparent"
|
||||||
|
"PreviewType"="Plane"
|
||||||
|
"CanUseSpriteAtlas"="True"
|
||||||
|
}
|
||||||
|
|
||||||
|
Stencil
|
||||||
|
{
|
||||||
|
Ref [_Stencil]
|
||||||
|
Comp [_StencilComp]
|
||||||
|
Pass [_StencilOp]
|
||||||
|
ReadMask [_StencilReadMask]
|
||||||
|
WriteMask [_StencilWriteMask]
|
||||||
|
}
|
||||||
|
|
||||||
|
Cull [_CullMode]
|
||||||
|
Lighting Off
|
||||||
|
ZWrite Off
|
||||||
|
ZTest [unity_GUIZTestMode]
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
ColorMask [_ColorMask]
|
||||||
|
|
||||||
|
Pass
|
||||||
|
{
|
||||||
|
Name "Default"
|
||||||
|
CGPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
#pragma target 2.0
|
||||||
|
|
||||||
|
#include "UnityCG.cginc"
|
||||||
|
#include "UnityUI.cginc"
|
||||||
|
|
||||||
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
|
struct appdata_t
|
||||||
|
{
|
||||||
|
float4 vertex : POSITION;
|
||||||
|
float4 color : COLOR;
|
||||||
|
float2 texcoord : TEXCOORD0;
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
};
|
||||||
|
|
||||||
|
struct v2f
|
||||||
|
{
|
||||||
|
float4 vertex : SV_POSITION;
|
||||||
|
fixed4 color : COLOR;
|
||||||
|
float2 texcoord : TEXCOORD0;
|
||||||
|
float4 worldPosition : TEXCOORD1;
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
};
|
||||||
|
|
||||||
|
sampler2D _MainTex;
|
||||||
|
fixed4 _Color;
|
||||||
|
fixed4 _TextureSampleAdd;
|
||||||
|
float4 _ClipRect;
|
||||||
|
float4 _MainTex_ST;
|
||||||
|
|
||||||
|
v2f vert(appdata_t v)
|
||||||
|
{
|
||||||
|
v2f OUT;
|
||||||
|
UNITY_SETUP_INSTANCE_ID(v);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
|
||||||
|
OUT.worldPosition = v.vertex;
|
||||||
|
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
|
||||||
|
|
||||||
|
OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||||
|
|
||||||
|
OUT.color = v.color * _Color;
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed4 frag(v2f IN) : SV_Target
|
||||||
|
{
|
||||||
|
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
|
||||||
|
|
||||||
|
#ifdef UNITY_UI_CLIP_RECT
|
||||||
|
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNITY_UI_ALPHACLIP
|
||||||
|
clip (color.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
ENDCG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cf81c85f95fe47e1a27f6ae460cf182c
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
84
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMPro.cginc
Executable file
84
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMPro.cginc
Executable file
@ -0,0 +1,84 @@
|
|||||||
|
float2 UnpackUV(float uv)
|
||||||
|
{
|
||||||
|
float2 output;
|
||||||
|
output.x = floor(uv / 4096);
|
||||||
|
output.y = uv - 4096 * output.x;
|
||||||
|
|
||||||
|
return output * 0.001953125;
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed4 GetColor(half d, fixed4 faceColor, fixed4 outlineColor, half outline, half softness)
|
||||||
|
{
|
||||||
|
half faceAlpha = 1-saturate((d - outline * 0.5 + softness * 0.5) / (1.0 + softness));
|
||||||
|
half outlineAlpha = saturate((d + outline * 0.5)) * sqrt(min(1.0, outline));
|
||||||
|
|
||||||
|
faceColor.rgb *= faceColor.a;
|
||||||
|
outlineColor.rgb *= outlineColor.a;
|
||||||
|
|
||||||
|
faceColor = lerp(faceColor, outlineColor, outlineAlpha);
|
||||||
|
|
||||||
|
faceColor *= faceAlpha;
|
||||||
|
|
||||||
|
return faceColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 GetSurfaceNormal(float4 h, float bias)
|
||||||
|
{
|
||||||
|
bool raisedBevel = step(1, fmod(_ShaderFlags, 2));
|
||||||
|
|
||||||
|
h += bias+_BevelOffset;
|
||||||
|
|
||||||
|
float bevelWidth = max(.01, _OutlineWidth+_BevelWidth);
|
||||||
|
|
||||||
|
// Track outline
|
||||||
|
h -= .5;
|
||||||
|
h /= bevelWidth;
|
||||||
|
h = saturate(h+.5);
|
||||||
|
|
||||||
|
if(raisedBevel) h = 1 - abs(h*2.0 - 1.0);
|
||||||
|
h = lerp(h, sin(h*3.141592/2.0), _BevelRoundness);
|
||||||
|
h = min(h, 1.0-_BevelClamp);
|
||||||
|
h *= _Bevel * bevelWidth * _GradientScale * -2.0;
|
||||||
|
|
||||||
|
float3 va = normalize(float3(1.0, 0.0, h.y - h.x));
|
||||||
|
float3 vb = normalize(float3(0.0, -1.0, h.w - h.z));
|
||||||
|
|
||||||
|
return cross(va, vb);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 GetSurfaceNormal(float2 uv, float bias, float3 delta)
|
||||||
|
{
|
||||||
|
// Read "height field"
|
||||||
|
float4 h = {tex2D(_MainTex, uv - delta.xz).a,
|
||||||
|
tex2D(_MainTex, uv + delta.xz).a,
|
||||||
|
tex2D(_MainTex, uv - delta.zy).a,
|
||||||
|
tex2D(_MainTex, uv + delta.zy).a};
|
||||||
|
|
||||||
|
return GetSurfaceNormal(h, bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 GetSpecular(float3 n, float3 l)
|
||||||
|
{
|
||||||
|
float spec = pow(max(0.0, dot(n, l)), _Reflectivity);
|
||||||
|
return _SpecularColor.rgb * spec * _SpecularPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 GetGlowColor(float d, float scale)
|
||||||
|
{
|
||||||
|
float glow = d - (_GlowOffset*_ScaleRatioB) * 0.5 * scale;
|
||||||
|
float t = lerp(_GlowInner, (_GlowOuter * _ScaleRatioB), step(0.0, glow)) * 0.5 * scale;
|
||||||
|
glow = saturate(abs(glow/(1.0 + t)));
|
||||||
|
glow = 1.0-pow(glow, _GlowPower);
|
||||||
|
glow *= sqrt(min(1.0, t)); // Fade off glow thinner than 1 screen pixel
|
||||||
|
return float4(_GlowColor.rgb, saturate(_GlowColor.a * glow * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 BlendARGB(float4 overlying, float4 underlying)
|
||||||
|
{
|
||||||
|
overlying.rgb *= overlying.a;
|
||||||
|
underlying.rgb *= underlying.a;
|
||||||
|
float3 blended = overlying.rgb + ((1-overlying.a)*underlying.rgb);
|
||||||
|
float alpha = underlying.a + (1-underlying.a)*overlying.a;
|
||||||
|
return float4(blended, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
9
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta
Executable file
9
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMPro.cginc.meta
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 407bc68d299748449bbf7f48ee690f8d
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
157
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc
Executable file
157
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMPro_Mobile.cginc
Executable file
@ -0,0 +1,157 @@
|
|||||||
|
struct vertex_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
float4 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
float4 color : COLOR;
|
||||||
|
float2 texcoord0 : TEXCOORD0;
|
||||||
|
float2 texcoord1 : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pixel_t {
|
||||||
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||||
|
UNITY_VERTEX_OUTPUT_STEREO
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float4 faceColor : COLOR;
|
||||||
|
float4 outlineColor : COLOR1;
|
||||||
|
float4 texcoord0 : TEXCOORD0;
|
||||||
|
float4 param : TEXCOORD1; // weight, scaleRatio
|
||||||
|
float2 mask : TEXCOORD2;
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 texcoord2 : TEXCOORD3;
|
||||||
|
float4 underlayColor : COLOR2;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
float4 SRGBToLinear(float4 rgba) {
|
||||||
|
return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_t VertShader(vertex_t input)
|
||||||
|
{
|
||||||
|
pixel_t output;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(pixel_t, output);
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
||||||
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||||
|
|
||||||
|
float bold = step(input.texcoord1.y, 0);
|
||||||
|
|
||||||
|
float4 vert = input.position;
|
||||||
|
vert.x += _VertexOffsetX;
|
||||||
|
vert.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
|
||||||
|
float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0;
|
||||||
|
weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5;
|
||||||
|
|
||||||
|
// Generate UV for the Masking Texture
|
||||||
|
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||||
|
float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
|
||||||
|
|
||||||
|
float4 color = input.color;
|
||||||
|
#if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA)
|
||||||
|
color = SRGBToLinear(input.color);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float opacity = color.a;
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
opacity = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float4 faceColor = float4(color.rgb, opacity) * _FaceColor;
|
||||||
|
faceColor.rgb *= faceColor.a;
|
||||||
|
|
||||||
|
float4 outlineColor = _OutlineColor;
|
||||||
|
outlineColor.a *= opacity;
|
||||||
|
outlineColor.rgb *= outlineColor.a;
|
||||||
|
|
||||||
|
output.position = vPosition;
|
||||||
|
output.faceColor = faceColor;
|
||||||
|
output.outlineColor = outlineColor;
|
||||||
|
output.texcoord0 = float4(input.texcoord0.xy, maskUV.xy);
|
||||||
|
output.param = float4(0.5 - weight, 1.3333 * _GradientScale * (_Sharpness + 1) / _TextureWidth, _OutlineWidth * _ScaleRatioA * 0.5, 0);
|
||||||
|
|
||||||
|
float2 mask = float2(0, 0);
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
mask = vert.xy * 2 - clampedRect.xy - clampedRect.zw;
|
||||||
|
#endif
|
||||||
|
output.mask = mask;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
|
float4 underlayColor = _UnderlayColor;
|
||||||
|
underlayColor.rgb *= underlayColor.a;
|
||||||
|
|
||||||
|
float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth;
|
||||||
|
float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;
|
||||||
|
|
||||||
|
output.texcoord2 = float4(input.texcoord0 + float2(x, y), input.color.a, 0);
|
||||||
|
output.underlayColor = underlayColor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 PixShader(pixel_t input) : SV_Target
|
||||||
|
{
|
||||||
|
UNITY_SETUP_INSTANCE_ID(input);
|
||||||
|
|
||||||
|
float d = tex2D(_MainTex, input.texcoord0.xy).a;
|
||||||
|
|
||||||
|
float2 UV = input.texcoord0.xy;
|
||||||
|
float scale = rsqrt(abs(ddx(UV.x) * ddy(UV.y) - ddy(UV.x) * ddx(UV.y))) * input.param.y;
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
float layerScale = scale;
|
||||||
|
layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale);
|
||||||
|
float layerBias = input.param.x * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale);
|
||||||
|
|
||||||
|
float4 faceColor = input.faceColor * saturate((d - input.param.x) * scale + 0.5);
|
||||||
|
|
||||||
|
#ifdef OUTLINE_ON
|
||||||
|
float4 outlineColor = lerp(input.faceColor, input.outlineColor, sqrt(min(1.0, input.param.z * scale * 2)));
|
||||||
|
faceColor = lerp(outlineColor, input.faceColor, saturate((d - input.param.x - input.param.z) * scale + 0.5));
|
||||||
|
faceColor *= saturate((d - input.param.x + input.param.z) * scale + 0.5);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_ON
|
||||||
|
d = tex2D(_MainTex, input.texcoord2.xy).a * layerScale;
|
||||||
|
faceColor += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - layerBias) * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNDERLAY_INNER
|
||||||
|
float bias = input.param.x * scale - 0.5;
|
||||||
|
float sd = saturate(d * scale - bias - input.param.z);
|
||||||
|
d = tex2D(_MainTex, input.texcoord2.xy).a * layerScale;
|
||||||
|
faceColor += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - layerBias)) * sd * (1 - faceColor.a);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MASKING
|
||||||
|
float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a);
|
||||||
|
float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl;
|
||||||
|
a = saturate(t / _MaskEdgeSoftness);
|
||||||
|
faceColor.rgb = lerp(_MaskEdgeColor.rgb * faceColor.a, faceColor.rgb, a);
|
||||||
|
faceColor *= a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Alternative implementation to UnityGet2DClipping with support for softness
|
||||||
|
#if UNITY_UI_CLIP_RECT
|
||||||
|
float2 maskZW = 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + (1 / scale));
|
||||||
|
float2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * maskZW);
|
||||||
|
faceColor *= m.x * m.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
|
faceColor *= input.texcoord2.z;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_UI_ALPHACLIP
|
||||||
|
clip(faceColor.a - 0.001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return faceColor;
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c334973cef89a9840b0b0c507e0377ab
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
// UI Editable properties
|
||||||
|
uniform sampler2D _FaceTex; // Alpha : Signed Distance
|
||||||
|
uniform float _FaceUVSpeedX;
|
||||||
|
uniform float _FaceUVSpeedY;
|
||||||
|
uniform fixed4 _FaceColor; // RGBA : Color + Opacity
|
||||||
|
uniform float _FaceDilate; // v[ 0, 1]
|
||||||
|
uniform float _OutlineSoftness; // v[ 0, 1]
|
||||||
|
|
||||||
|
uniform sampler2D _OutlineTex; // RGBA : Color + Opacity
|
||||||
|
uniform float _OutlineUVSpeedX;
|
||||||
|
uniform float _OutlineUVSpeedY;
|
||||||
|
uniform fixed4 _OutlineColor; // RGBA : Color + Opacity
|
||||||
|
uniform float _OutlineWidth; // v[ 0, 1]
|
||||||
|
|
||||||
|
uniform float _Bevel; // v[ 0, 1]
|
||||||
|
uniform float _BevelOffset; // v[-1, 1]
|
||||||
|
uniform float _BevelWidth; // v[-1, 1]
|
||||||
|
uniform float _BevelClamp; // v[ 0, 1]
|
||||||
|
uniform float _BevelRoundness; // v[ 0, 1]
|
||||||
|
|
||||||
|
uniform sampler2D _BumpMap; // Normal map
|
||||||
|
uniform float _BumpOutline; // v[ 0, 1]
|
||||||
|
uniform float _BumpFace; // v[ 0, 1]
|
||||||
|
|
||||||
|
uniform samplerCUBE _Cube; // Cube / sphere map
|
||||||
|
uniform fixed4 _ReflectFaceColor; // RGB intensity
|
||||||
|
uniform fixed4 _ReflectOutlineColor;
|
||||||
|
//uniform float _EnvTiltX; // v[-1, 1]
|
||||||
|
//uniform float _EnvTiltY; // v[-1, 1]
|
||||||
|
uniform float3 _EnvMatrixRotation;
|
||||||
|
uniform float4x4 _EnvMatrix;
|
||||||
|
|
||||||
|
uniform fixed4 _SpecularColor; // RGB intensity
|
||||||
|
uniform float _LightAngle; // v[ 0,Tau]
|
||||||
|
uniform float _SpecularPower; // v[ 0, 1]
|
||||||
|
uniform float _Reflectivity; // v[ 5, 15]
|
||||||
|
uniform float _Diffuse; // v[ 0, 1]
|
||||||
|
uniform float _Ambient; // v[ 0, 1]
|
||||||
|
|
||||||
|
uniform fixed4 _UnderlayColor; // RGBA : Color + Opacity
|
||||||
|
uniform float _UnderlayOffsetX; // v[-1, 1]
|
||||||
|
uniform float _UnderlayOffsetY; // v[-1, 1]
|
||||||
|
uniform float _UnderlayDilate; // v[-1, 1]
|
||||||
|
uniform float _UnderlaySoftness; // v[ 0, 1]
|
||||||
|
|
||||||
|
uniform fixed4 _GlowColor; // RGBA : Color + Intesity
|
||||||
|
uniform float _GlowOffset; // v[-1, 1]
|
||||||
|
uniform float _GlowOuter; // v[ 0, 1]
|
||||||
|
uniform float _GlowInner; // v[ 0, 1]
|
||||||
|
uniform float _GlowPower; // v[ 1, 1/(1+4*4)]
|
||||||
|
|
||||||
|
// API Editable properties
|
||||||
|
uniform float _ShaderFlags;
|
||||||
|
uniform float _WeightNormal;
|
||||||
|
uniform float _WeightBold;
|
||||||
|
|
||||||
|
uniform float _ScaleRatioA;
|
||||||
|
uniform float _ScaleRatioB;
|
||||||
|
uniform float _ScaleRatioC;
|
||||||
|
|
||||||
|
uniform float _VertexOffsetX;
|
||||||
|
uniform float _VertexOffsetY;
|
||||||
|
|
||||||
|
//uniform float _UseClipRect;
|
||||||
|
uniform float _MaskID;
|
||||||
|
uniform sampler2D _MaskTex;
|
||||||
|
uniform float4 _MaskCoord;
|
||||||
|
uniform float4 _ClipRect; // bottom left(x,y) : top right(z,w)
|
||||||
|
//uniform float _MaskWipeControl;
|
||||||
|
//uniform float _MaskEdgeSoftness;
|
||||||
|
//uniform fixed4 _MaskEdgeColor;
|
||||||
|
//uniform bool _MaskInverse;
|
||||||
|
|
||||||
|
uniform float _MaskSoftnessX;
|
||||||
|
uniform float _MaskSoftnessY;
|
||||||
|
|
||||||
|
// Font Atlas properties
|
||||||
|
uniform sampler2D _MainTex;
|
||||||
|
uniform float _TextureWidth;
|
||||||
|
uniform float _TextureHeight;
|
||||||
|
uniform float _GradientScale;
|
||||||
|
uniform float _ScaleX;
|
||||||
|
uniform float _ScaleY;
|
||||||
|
uniform float _PerspectiveFilter;
|
||||||
|
uniform float _Sharpness;
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3997e2241185407d80309a82f9148466
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
101
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc
Executable file
101
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Shaders/TMPro_Surface.cginc
Executable file
@ -0,0 +1,101 @@
|
|||||||
|
void VertShader(inout appdata_full v, out Input data)
|
||||||
|
{
|
||||||
|
v.vertex.x += _VertexOffsetX;
|
||||||
|
v.vertex.y += _VertexOffsetY;
|
||||||
|
|
||||||
|
UNITY_INITIALIZE_OUTPUT(Input, data);
|
||||||
|
|
||||||
|
float bold = step(v.texcoord1.y, 0);
|
||||||
|
|
||||||
|
// Generate normal for backface
|
||||||
|
float3 view = ObjSpaceViewDir(v.vertex);
|
||||||
|
v.normal *= sign(dot(v.normal, view));
|
||||||
|
|
||||||
|
#if USE_DERIVATIVE
|
||||||
|
data.param.y = 1;
|
||||||
|
#else
|
||||||
|
float4 vert = v.vertex;
|
||||||
|
float4 vPosition = UnityObjectToClipPos(vert);
|
||||||
|
float2 pixelSize = vPosition.w;
|
||||||
|
|
||||||
|
pixelSize /= float2(_ScaleX, _ScaleY) * mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy);
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
|
scale *= abs(v.texcoord1.y) * _GradientScale * (_Sharpness + 1);
|
||||||
|
scale = lerp(scale * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(v.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
data.param.y = scale;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
data.param.x = (lerp(_WeightNormal, _WeightBold, bold) / 4.0 + _FaceDilate) * _ScaleRatioA * 0.5; //
|
||||||
|
|
||||||
|
v.texcoord1.xy = UnpackUV(v.texcoord1.x);
|
||||||
|
data.viewDirEnv = mul((float3x3)_EnvMatrix, WorldSpaceViewDir(v.vertex));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixShader(Input input, inout SurfaceOutput o)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if USE_DERIVATIVE
|
||||||
|
float2 pixelSize = float2(ddx(input.uv_MainTex.y), ddy(input.uv_MainTex.y));
|
||||||
|
pixelSize *= _TextureWidth * .75;
|
||||||
|
float scale = rsqrt(dot(pixelSize, pixelSize)) * _GradientScale * (_Sharpness + 1);
|
||||||
|
#else
|
||||||
|
float scale = input.param.y;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Signed distance
|
||||||
|
float c = tex2D(_MainTex, input.uv_MainTex).a;
|
||||||
|
float sd = (.5 - c - input.param.x) * scale + .5;
|
||||||
|
float outline = _OutlineWidth*_ScaleRatioA * scale;
|
||||||
|
float softness = _OutlineSoftness*_ScaleRatioA * scale;
|
||||||
|
|
||||||
|
// Color & Alpha
|
||||||
|
float4 faceColor = _FaceColor;
|
||||||
|
float4 outlineColor = _OutlineColor;
|
||||||
|
faceColor *= input.color;
|
||||||
|
outlineColor.a *= input.color.a;
|
||||||
|
faceColor *= tex2D(_FaceTex, float2(input.uv2_FaceTex.x + _FaceUVSpeedX * _Time.y, input.uv2_FaceTex.y + _FaceUVSpeedY * _Time.y));
|
||||||
|
outlineColor *= tex2D(_OutlineTex, float2(input.uv2_OutlineTex.x + _OutlineUVSpeedX * _Time.y, input.uv2_OutlineTex.y + _OutlineUVSpeedY * _Time.y));
|
||||||
|
faceColor = GetColor(sd, faceColor, outlineColor, outline, softness);
|
||||||
|
faceColor.rgb /= max(faceColor.a, 0.0001);
|
||||||
|
|
||||||
|
#if BEVEL_ON
|
||||||
|
float3 delta = float3(1.0 / _TextureWidth, 1.0 / _TextureHeight, 0.0);
|
||||||
|
|
||||||
|
float4 smp4x = {tex2D(_MainTex, input.uv_MainTex - delta.xz).a,
|
||||||
|
tex2D(_MainTex, input.uv_MainTex + delta.xz).a,
|
||||||
|
tex2D(_MainTex, input.uv_MainTex - delta.zy).a,
|
||||||
|
tex2D(_MainTex, input.uv_MainTex + delta.zy).a };
|
||||||
|
|
||||||
|
// Face Normal
|
||||||
|
float3 n = GetSurfaceNormal(smp4x, input.param.x);
|
||||||
|
|
||||||
|
// Bumpmap
|
||||||
|
float3 bump = UnpackNormal(tex2D(_BumpMap, input.uv2_FaceTex.xy)).xyz;
|
||||||
|
bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5));
|
||||||
|
bump = lerp(float3(0, 0, 1), bump, faceColor.a);
|
||||||
|
n = normalize(n - bump);
|
||||||
|
|
||||||
|
// Cubemap reflection
|
||||||
|
fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDirEnv, mul((float3x3)unity_ObjectToWorld, n)));
|
||||||
|
float3 emission = reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a;
|
||||||
|
#else
|
||||||
|
float3 n = float3(0, 0, -1);
|
||||||
|
float3 emission = float3(0, 0, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if GLOW_ON
|
||||||
|
float4 glowColor = GetGlowColor(sd, scale);
|
||||||
|
glowColor.a *= input.color.a;
|
||||||
|
emission += glowColor.rgb*glowColor.a;
|
||||||
|
faceColor = BlendARGB(glowColor, faceColor);
|
||||||
|
faceColor.rgb /= max(faceColor.a, 0.0001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set Standard output structure
|
||||||
|
o.Albedo = faceColor.rgb;
|
||||||
|
o.Normal = -n;
|
||||||
|
o.Emission = emission;
|
||||||
|
o.Specular = lerp(_FaceShininess, _OutlineShininess, saturate(sd + outline * 0.5));
|
||||||
|
o.Gloss = 1;
|
||||||
|
o.Alpha = faceColor.a;
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d930090c0cd643c7b55f19a38538c162
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Sprites.meta
Executable file
8
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Sprites.meta
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d0603b6d5186471b96c778c3949c7ce2
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
This sample of beautiful emojis are provided by EmojiOne https://www.emojione.com/
|
||||||
|
|
||||||
|
Please visit their website to view the complete set of their emojis and review their licensing terms.
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 381dcb09d5029d14897e55f98031fca5
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
156
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Sprites/EmojiOne.json
Executable file
156
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Sprites/EmojiOne.json
Executable file
@ -0,0 +1,156 @@
|
|||||||
|
{"frames": [
|
||||||
|
|
||||||
|
{
|
||||||
|
"filename": "1f60a.png",
|
||||||
|
"frame": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f60b.png",
|
||||||
|
"frame": {"x":128,"y":0,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f60d.png",
|
||||||
|
"frame": {"x":256,"y":0,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f60e.png",
|
||||||
|
"frame": {"x":384,"y":0,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f600.png",
|
||||||
|
"frame": {"x":0,"y":128,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f601.png",
|
||||||
|
"frame": {"x":128,"y":128,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f602.png",
|
||||||
|
"frame": {"x":256,"y":128,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f603.png",
|
||||||
|
"frame": {"x":384,"y":128,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f604.png",
|
||||||
|
"frame": {"x":0,"y":256,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f605.png",
|
||||||
|
"frame": {"x":128,"y":256,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f606.png",
|
||||||
|
"frame": {"x":256,"y":256,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f609.png",
|
||||||
|
"frame": {"x":384,"y":256,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f618.png",
|
||||||
|
"frame": {"x":0,"y":384,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "1f923.png",
|
||||||
|
"frame": {"x":128,"y":384,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "263a.png",
|
||||||
|
"frame": {"x":256,"y":384,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "2639.png",
|
||||||
|
"frame": {"x":384,"y":384,"w":128,"h":128},
|
||||||
|
"rotated": false,
|
||||||
|
"trimmed": false,
|
||||||
|
"spriteSourceSize": {"x":0,"y":0,"w":128,"h":128},
|
||||||
|
"sourceSize": {"w":128,"h":128},
|
||||||
|
"pivot": {"x":0.5,"y":0.5}
|
||||||
|
}],
|
||||||
|
"meta": {
|
||||||
|
"app": "http://www.codeandweb.com/texturepacker",
|
||||||
|
"version": "1.0",
|
||||||
|
"image": "EmojiOne.png",
|
||||||
|
"format": "RGBA8888",
|
||||||
|
"size": {"w":512,"h":512},
|
||||||
|
"scale": "1",
|
||||||
|
"smartupdate": "$TexturePacker:SmartUpdate:196a26a2e149d875b91ffc8fa3581e76:fc928c7e275404b7e0649307410475cb:424723c3774975ddb2053fd5c4b85f6e$"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8f05276190cf498a8153f6cbe761d4e6
|
||||||
|
timeCreated: 1480316860
|
||||||
|
licenseType: Pro
|
||||||
|
TextScriptImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Sprites/EmojiOne.png
Executable file
BIN
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Sprites/EmojiOne.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
431
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Sprites/EmojiOne.png.meta
Executable file
431
unity/XR_RM_PICO_UDP_Sender/Assets/TextMesh Pro/Sprites/EmojiOne.png.meta
Executable file
@ -0,0 +1,431 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dffef66376be4fa480fb02b19edbe903
|
||||||
|
TextureImporter:
|
||||||
|
fileIDToRecycleName:
|
||||||
|
21300000: EmojiOne_0
|
||||||
|
21300002: EmojiOne_1
|
||||||
|
21300004: EmojiOne_2
|
||||||
|
21300006: EmojiOne_3
|
||||||
|
21300008: EmojiOne_4
|
||||||
|
21300010: EmojiOne_6
|
||||||
|
21300012: EmojiOne_7
|
||||||
|
21300014: EmojiOne_8
|
||||||
|
21300016: EmojiOne_9
|
||||||
|
21300018: EmojiOne_10
|
||||||
|
21300020: EmojiOne_11
|
||||||
|
21300022: EmojiOne_12
|
||||||
|
21300024: EmojiOne_13
|
||||||
|
21300026: EmojiOne_5
|
||||||
|
21300028: EmojiOne_14
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 5
|
||||||
|
mipmaps:
|
||||||
|
mipMapMode: 0
|
||||||
|
enableMipMap: 1
|
||||||
|
sRGBTexture: 1
|
||||||
|
linearTexture: 0
|
||||||
|
fadeOut: 0
|
||||||
|
borderMipMap: 0
|
||||||
|
mipMapsPreserveCoverage: 0
|
||||||
|
alphaTestReferenceValue: 0.5
|
||||||
|
mipMapFadeDistanceStart: 1
|
||||||
|
mipMapFadeDistanceEnd: 3
|
||||||
|
bumpmap:
|
||||||
|
convertToNormalMap: 0
|
||||||
|
externalNormalMap: 0
|
||||||
|
heightScale: 0.25
|
||||||
|
normalMapFilter: 0
|
||||||
|
isReadable: 0
|
||||||
|
grayScaleToAlpha: 0
|
||||||
|
generateCubemap: 6
|
||||||
|
cubemapConvolution: 0
|
||||||
|
seamlessCubemap: 0
|
||||||
|
textureFormat: -1
|
||||||
|
maxTextureSize: 2048
|
||||||
|
textureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
filterMode: -1
|
||||||
|
aniso: -1
|
||||||
|
mipBias: -1
|
||||||
|
wrapU: 1
|
||||||
|
wrapV: 1
|
||||||
|
wrapW: 1
|
||||||
|
nPOTScale: 0
|
||||||
|
lightmap: 0
|
||||||
|
compressionQuality: 50
|
||||||
|
spriteMode: 2
|
||||||
|
spriteExtrude: 1
|
||||||
|
spriteMeshType: 1
|
||||||
|
alignment: 0
|
||||||
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
spritePixelsToUnits: 100
|
||||||
|
alphaUsage: 1
|
||||||
|
alphaIsTransparency: 1
|
||||||
|
spriteTessellationDetail: -1
|
||||||
|
textureType: 0
|
||||||
|
textureShape: 1
|
||||||
|
singleChannelComponent: 0
|
||||||
|
maxTextureSizeSet: 0
|
||||||
|
compressionQualitySet: 0
|
||||||
|
textureFormatSet: 0
|
||||||
|
platformSettings:
|
||||||
|
- serializedVersion: 2
|
||||||
|
buildTarget: DefaultTexturePlatform
|
||||||
|
maxTextureSize: 512
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
- serializedVersion: 2
|
||||||
|
buildTarget: Standalone
|
||||||
|
maxTextureSize: 512
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
- serializedVersion: 2
|
||||||
|
buildTarget: iPhone
|
||||||
|
maxTextureSize: 512
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
- serializedVersion: 2
|
||||||
|
buildTarget: Android
|
||||||
|
maxTextureSize: 512
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
spriteSheet:
|
||||||
|
serializedVersion: 2
|
||||||
|
sprites:
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_0
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 4bcc36da2108f2c4ba3de5c921d25c3c
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_1
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 128
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: e9eea8093eaeaee4d901c4553f572c22
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_2
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 256
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 49451da35411dcc42a3692e39b0fde70
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_3
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 384
|
||||||
|
y: 384
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: f65709664b924904790c850a50ca82bc
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_4
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 5b92c568a5ec9ad4b9ed90e271f1c9a8
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_6
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 256
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: b10f2b48b7281594bb8a24a6511a35af
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_7
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 384
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 10a600f9329dc2246a897e89f4d283cd
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_8
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 66cffa363b90ab14787d8a5b90cf4502
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_9
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 128
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 55cf3d409c9b89349b1e1bdc1cc224ad
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_10
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 256
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 2a9e58eaf96feef42bcefa1cf257193f
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_11
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 384
|
||||||
|
y: 128
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 2489120affc155840ae6a7be2e93ce19
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_12
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: 412349a150598d14da4d7140df5c0286
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_13
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 128
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: a937464b42bb3634782dea34c6becb6c
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_5
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 256
|
||||||
|
y: 0
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: b0f933b217682124dbfc5e6b89abe3d0
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: EmojiOne_14
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 128
|
||||||
|
y: 256
|
||||||
|
width: 128
|
||||||
|
height: 128
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: 0
|
||||||
|
bones: []
|
||||||
|
spriteID: f7235c763afe4434e8bb666750a41096
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
bones: []
|
||||||
|
spriteID: 3e32d8f5477abfc43b19066e8ad5032e
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
spritePackingTag:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -2,6 +2,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.xr.picoxr": "file:../../PICO-Unity-Integration-SDK-release_3.4.0",
|
"com.unity.xr.picoxr": "file:../../PICO-Unity-Integration-SDK-release_3.4.0",
|
||||||
"com.unity.xr.management": "4.4.0",
|
"com.unity.xr.management": "4.4.0",
|
||||||
|
"com.unity.textmeshpro": "3.0.6",
|
||||||
"com.unity.modules.androidjni": "1.0.0",
|
"com.unity.modules.androidjni": "1.0.0",
|
||||||
"com.unity.modules.animation": "1.0.0",
|
"com.unity.modules.animation": "1.0.0",
|
||||||
"com.unity.modules.imageconversion": "1.0.0",
|
"com.unity.modules.imageconversion": "1.0.0",
|
||||||
|
|||||||
@ -16,9 +16,18 @@
|
|||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"url": "https://packages.unity.cn"
|
"url": "https://packages.unity.cn"
|
||||||
},
|
},
|
||||||
|
"com.unity.textmeshpro": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.ugui": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.cn"
|
||||||
|
},
|
||||||
"com.unity.ugui": {
|
"com.unity.ugui": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"depth": 2,
|
"depth": 1,
|
||||||
"source": "builtin",
|
"source": "builtin",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.modules.ui": "1.0.0",
|
"com.unity.modules.ui": "1.0.0",
|
||||||
@ -39,14 +48,14 @@
|
|||||||
"depth": 1,
|
"depth": 1,
|
||||||
"source": "registry",
|
"source": "registry",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"com.unity.ugui": "1.0.0",
|
||||||
"com.unity.inputsystem": "1.7.0",
|
"com.unity.inputsystem": "1.7.0",
|
||||||
"com.unity.mathematics": "1.2.6",
|
"com.unity.mathematics": "1.2.6",
|
||||||
"com.unity.ugui": "1.0.0",
|
|
||||||
"com.unity.xr.core-utils": "2.2.3",
|
|
||||||
"com.unity.xr.legacyinputhelpers": "2.1.10",
|
|
||||||
"com.unity.modules.audio": "1.0.0",
|
"com.unity.modules.audio": "1.0.0",
|
||||||
"com.unity.modules.imgui": "1.0.0",
|
"com.unity.modules.imgui": "1.0.0",
|
||||||
"com.unity.modules.physics": "1.0.0"
|
"com.unity.xr.core-utils": "2.2.3",
|
||||||
|
"com.unity.modules.physics": "1.0.0",
|
||||||
|
"com.unity.xr.legacyinputhelpers": "2.1.10"
|
||||||
},
|
},
|
||||||
"url": "https://packages.unity.cn"
|
"url": "https://packages.unity.cn"
|
||||||
},
|
},
|
||||||
@ -134,7 +143,7 @@
|
|||||||
},
|
},
|
||||||
"com.unity.modules.ui": {
|
"com.unity.modules.ui": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"depth": 3,
|
"depth": 2,
|
||||||
"source": "builtin",
|
"source": "builtin",
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -12,7 +12,7 @@ PlayerSettings:
|
|||||||
targetDevice: 2
|
targetDevice: 2
|
||||||
useOnDemandResources: 0
|
useOnDemandResources: 0
|
||||||
accelerometerFrequency: 60
|
accelerometerFrequency: 60
|
||||||
companyName: DefaultCompany
|
companyName: XR-RM
|
||||||
productName: XR-RM-PICO-UDP-Sender
|
productName: XR-RM-PICO-UDP-Sender
|
||||||
defaultCursor: {fileID: 0}
|
defaultCursor: {fileID: 0}
|
||||||
cursorHotspot: {x: 0, y: 0}
|
cursorHotspot: {x: 0, y: 0}
|
||||||
@ -170,10 +170,10 @@ PlayerSettings:
|
|||||||
iPhone: 0
|
iPhone: 0
|
||||||
tvOS: 0
|
tvOS: 0
|
||||||
overrideDefaultApplicationIdentifier: 1
|
overrideDefaultApplicationIdentifier: 1
|
||||||
AndroidBundleVersionCode: 1
|
AndroidBundleVersionCode: 3377155
|
||||||
AndroidMinSdkVersion: 29
|
AndroidMinSdkVersion: 29
|
||||||
AndroidTargetSdkVersion: 0
|
AndroidTargetSdkVersion: 0
|
||||||
AndroidPreferredInstallLocation: 1
|
AndroidPreferredInstallLocation: 2
|
||||||
aotOptions:
|
aotOptions:
|
||||||
stripEngineCode: 1
|
stripEngineCode: 1
|
||||||
iPhoneStrippingLevel: 0
|
iPhoneStrippingLevel: 0
|
||||||
|
|||||||
@ -8,11 +8,14 @@ Configured target:
|
|||||||
```text
|
```text
|
||||||
Host = 192.168.9.99
|
Host = 192.168.9.99
|
||||||
Port = 15000
|
Port = 15000
|
||||||
Send Hz = 60
|
Send Hz = 90
|
||||||
Convert Unity To Project Coordinates = true
|
Convert Unity To Project Coordinates = true
|
||||||
Package Name = com.local.xr_rm_udp_sender
|
Package Name = com.local.xr_rm_udp_sender
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The default send rate is 90 Hz. If the network or headset performance is not
|
||||||
|
stable enough on site, lower it manually in the PICO panel to 60 Hz.
|
||||||
|
|
||||||
Open this folder with the Ubuntu editor installed at:
|
Open this folder with the Ubuntu editor installed at:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@ -44,6 +47,14 @@ Runtime scene components:
|
|||||||
disables PICO auto sleep, applies Android `KEEP_SCREEN_ON`, and restores
|
disables PICO auto sleep, applies Android `KEEP_SCREEN_ON`, and restores
|
||||||
captured screen/sleep timeouts when sending stops.
|
captured screen/sleep timeouts when sending stops.
|
||||||
|
|
||||||
|
Coordinate modes:
|
||||||
|
|
||||||
|
- `Project (+Z back)`: ROS-facing output. For `pose_source=pxr_predict`, the
|
||||||
|
measured PICO native pose is converted with `project.x=native.z`,
|
||||||
|
`project.y=native.y`, and `project.z=-native.x`.
|
||||||
|
- `Source raw`: sends the source pose without this conversion for field
|
||||||
|
diagnostics only.
|
||||||
|
|
||||||
The setup menu chooses the UDP target host from `XR_RM_UDP_TARGET_HOST` when
|
The setup menu chooses the UDP target host from `XR_RM_UDP_TARGET_HOST` when
|
||||||
set. Otherwise it auto-detects a local IPv4 address; on this Ubuntu machine the
|
set. Otherwise it auto-detects a local IPv4 address; on this Ubuntu machine the
|
||||||
current Wi-Fi address is `192.168.9.99`.
|
current Wi-Fi address is `192.168.9.99`.
|
||||||
|
|||||||
1281
unity_build.log
1281
unity_build.log
File diff suppressed because one or more lines are too long
@ -18,6 +18,8 @@ from xr_rm_interfaces.msg import XrController
|
|||||||
class UdpControllerReceiver(Node):
|
class UdpControllerReceiver(Node):
|
||||||
"""将轻量级 XR UDP 数据包转换成 ROS2 左/右手柄消息。"""
|
"""将轻量级 XR UDP 数据包转换成 ROS2 左/右手柄消息。"""
|
||||||
|
|
||||||
|
_VALID_POSE_SOURCES = {"pxr_predict", "unity_xr", "none"}
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__("udp_controller_receiver")
|
super().__init__("udp_controller_receiver")
|
||||||
|
|
||||||
@ -127,7 +129,20 @@ class UdpControllerReceiver(Node):
|
|||||||
msg.header.stamp = self.get_clock().now().to_msg()
|
msg.header.stamp = self.get_clock().now().to_msg()
|
||||||
msg.header.frame_id = str(payload.get("frame_id", "xr_world"))
|
msg.header.frame_id = str(payload.get("frame_id", "xr_world"))
|
||||||
msg.hand = hand
|
msg.hand = hand
|
||||||
msg.grip = self._as_bool(payload.get("grip", payload.get("grip_button", False)))
|
grip = self._as_bool(payload.get("grip", payload.get("grip_button", False)))
|
||||||
|
pose_valid = self._optional_bool(payload.get("pose_valid"), default=True)
|
||||||
|
pose_source = self._validate_pose_diagnostics(payload, hand)
|
||||||
|
if not pose_valid:
|
||||||
|
self.get_logger().warn(
|
||||||
|
f"{hand} XR pose_valid=false,强制 grip=false"
|
||||||
|
f" source={pose_source or 'missing'}"
|
||||||
|
f" tracking_state={payload.get('tracking_state', 'missing')}"
|
||||||
|
f" controller_status={payload.get('controller_status', 'missing')}",
|
||||||
|
throttle_duration_sec=1.0,
|
||||||
|
)
|
||||||
|
grip = False
|
||||||
|
|
||||||
|
msg.grip = grip
|
||||||
msg.trigger = self._clamp_float(payload.get("trigger", 0.0), 0.0, 1.0)
|
msg.trigger = self._clamp_float(payload.get("trigger", 0.0), 0.0, 1.0)
|
||||||
msg.pose.position.x = float(pos[0])
|
msg.pose.position.x = float(pos[0])
|
||||||
msg.pose.position.y = float(pos[1])
|
msg.pose.position.y = float(pos[1])
|
||||||
@ -144,6 +159,30 @@ class UdpControllerReceiver(Node):
|
|||||||
msg.pose.orientation.w = float(w)
|
msg.pose.orientation.w = float(w)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
def _validate_pose_diagnostics(self, payload: Mapping[str, Any], hand: str) -> str:
|
||||||
|
has_any_diagnostic = any(
|
||||||
|
key in payload for key in ("pose_valid", "pose_source", "tracking_state", "controller_status")
|
||||||
|
)
|
||||||
|
if has_any_diagnostic and "pose_valid" not in payload:
|
||||||
|
self.get_logger().warn(
|
||||||
|
f"{hand} XR 诊断字段缺少 pose_valid,按旧协议处理 grip",
|
||||||
|
throttle_duration_sec=5.0,
|
||||||
|
)
|
||||||
|
if has_any_diagnostic and "pose_source" not in payload:
|
||||||
|
self.get_logger().warn(
|
||||||
|
f"{hand} XR 诊断字段缺少 pose_source",
|
||||||
|
throttle_duration_sec=5.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
pose_source_value = payload.get("pose_source", "")
|
||||||
|
pose_source = str(pose_source_value).strip()
|
||||||
|
if pose_source and pose_source not in self._VALID_POSE_SOURCES:
|
||||||
|
self.get_logger().warn(
|
||||||
|
f"{hand} XR 未知 pose_source={pose_source!r}",
|
||||||
|
throttle_duration_sec=5.0,
|
||||||
|
)
|
||||||
|
return pose_source
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _contains_pose(payload: Mapping[str, Any]) -> bool:
|
def _contains_pose(payload: Mapping[str, Any]) -> bool:
|
||||||
return any(key in payload for key in ("pos", "position", "p", "pose"))
|
return any(key in payload for key in ("pos", "position", "p", "pose"))
|
||||||
@ -203,6 +242,12 @@ class UdpControllerReceiver(Node):
|
|||||||
return value.lower() in ("1", "true", "yes", "on")
|
return value.lower() in ("1", "true", "yes", "on")
|
||||||
return bool(value)
|
return bool(value)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _optional_bool(cls, value: Any, default: bool) -> bool:
|
||||||
|
if value is None:
|
||||||
|
return default
|
||||||
|
return cls._as_bool(value)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _clamp_float(value: Any, low: float, high: float) -> float:
|
def _clamp_float(value: Any, low: float, high: float) -> float:
|
||||||
number = float(value)
|
number = float(value)
|
||||||
|
|||||||
Reference in New Issue
Block a user